Imported Upstream version 0.19.0
[platform/upstream/vala.git] / vala / valasymbolresolver.vala
1 /* valasymbolresolver.vala
2  *
3  * Copyright (C) 2006-2010  Jürg Billeter
4  * Copyright (C) 2006-2008  Raffaele Sandrini
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
19  *
20  * Author:
21  *      Jürg Billeter <j@bitron.ch>
22  *      Raffaele Sandrini <raffaele@sandrini.ch>
23  */
24
25 using GLib;
26
27 /**
28  * Code visitor resolving symbol names.
29  */
30 public class Vala.SymbolResolver : CodeVisitor {
31         CodeContext context;
32         Symbol root_symbol;
33         Scope current_scope;
34         
35         /**
36          * Resolve symbol names in the specified code context.
37          *
38          * @param context a code context
39          */
40         public void resolve (CodeContext context) {
41                 this.context = context;
42                 root_symbol = context.root;
43
44                 context.root.accept (this);
45         }
46         
47         public override void visit_namespace (Namespace ns) {
48                 var old_scope = current_scope;
49                 current_scope = ns.scope;
50
51                 ns.accept_children (this);
52
53                 current_scope = old_scope;
54         }
55         
56         public override void visit_class (Class cl) {
57                 current_scope = cl.scope;
58
59                 cl.accept_children (this);
60
61                 cl.base_class = null;
62                 foreach (DataType type in cl.get_base_types ()) {
63                         if (type.data_type is Class) {
64                                 if (cl.base_class != null) {
65                                         cl.error = true;
66                                         Report.error (type.source_reference, "%s: Classes cannot have multiple base classes (`%s' and `%s')".printf (cl.get_full_name (), cl.base_class.get_full_name (), type.data_type.get_full_name ()));
67                                         return;
68                                 }
69                                 cl.base_class = (Class) type.data_type;
70                                 if (cl.base_class.is_subtype_of (cl)) {
71                                         cl.error = true;
72                                         Report.error (type.source_reference, "Base class cycle (`%s' and `%s')".printf (cl.get_full_name (), cl.base_class.get_full_name ()));
73                                         return;
74                                 }
75                         }
76                 }
77
78                 current_scope = current_scope.parent_scope;
79         }
80
81         public override void visit_struct (Struct st) {
82                 current_scope = st.scope;
83
84                 st.accept_children (this);
85
86                 if (st.base_type != null) {
87                         var base_type = st.base_struct;
88                         if (base_type != null) {
89                                 if (base_type.is_subtype_of (st)) {
90                                         st.error = true;
91                                         Report.error (base_type.source_reference, "Base struct cycle (`%s' and `%s')".printf (st.get_full_name (), base_type.get_full_name ()));
92                                         return;
93                                 }
94                         }
95                 }
96
97                 current_scope = current_scope.parent_scope;
98         }
99
100         public override void visit_interface (Interface iface) {
101                 current_scope = iface.scope;
102
103                 iface.accept_children (this);
104
105                 foreach (DataType type in iface.get_prerequisites ()) {
106                         if (type.data_type != null && type.data_type.is_subtype_of (iface)) {
107                                 iface.error = true;
108                                 Report.error (type.source_reference, "Prerequisite cycle (`%s' and `%s')".printf (iface.get_full_name (), type.data_type.get_full_name ()));
109                                 return;
110                         }
111                 }
112
113                 current_scope = current_scope.parent_scope;
114         }
115
116         public override void visit_enum (Enum en) {
117                 current_scope = en.scope;
118
119                 en.accept_children (this);
120
121                 current_scope = current_scope.parent_scope;
122         }
123
124         public override void visit_error_domain (ErrorDomain ed) {
125                 current_scope = ed.scope;
126
127                 ed.accept_children (this);
128
129                 current_scope = current_scope.parent_scope;
130         }
131
132         public override void visit_delegate (Delegate cb) {
133                 current_scope = cb.scope;
134
135                 cb.accept_children (this);
136
137                 current_scope = current_scope.parent_scope;
138         }
139
140         public override void visit_constant (Constant c) {
141                 var old_scope = current_scope;
142                 if (!(c.parent_symbol is Block)) {
143                         // non-local constant
144                         current_scope = c.scope;
145                 }
146
147                 c.accept_children (this);
148
149                 current_scope = old_scope;
150         }
151
152         public override void visit_field (Field f) {
153                 current_scope = f.scope;
154
155                 f.accept_children (this);
156
157                 current_scope = current_scope.parent_scope;
158         }
159
160         public override void visit_method (Method m) {
161                 current_scope = m.scope;
162
163                 m.accept_children (this);
164
165                 current_scope = current_scope.parent_scope;
166         }
167
168         public override void visit_creation_method (CreationMethod m) {
169                 m.accept_children (this);
170         }
171
172         public override void visit_formal_parameter (Parameter p) {
173                 p.accept_children (this);
174         }
175
176         public override void visit_property (Property prop) {
177                 prop.accept_children (this);
178         }
179
180         public override void visit_property_accessor (PropertyAccessor acc) {
181                 acc.accept_children (this);
182         }
183
184         public override void visit_signal (Signal sig) {
185                 sig.accept_children (this);
186         }
187
188         public override void visit_constructor (Constructor c) {
189                 c.accept_children (this);
190         }
191
192         public override void visit_destructor (Destructor d) {
193                 d.accept_children (this);
194         }
195
196         public override void visit_block (Block b) {
197                 b.accept_children (this);
198         }
199
200         public override void visit_using_directive (UsingDirective ns) {
201                 var unresolved_symbol = ns.namespace_symbol as UnresolvedSymbol;
202                 if (unresolved_symbol != null) {
203                         ns.namespace_symbol = resolve_symbol (unresolved_symbol);
204                         if (!(ns.namespace_symbol is Namespace)) {
205                                 ns.error = true;
206                                 Report.error (ns.source_reference, "The namespace name `%s' could not be found".printf (unresolved_symbol.to_string ()));
207                                 return;
208                         }
209                 }
210         }
211
212         private Symbol? resolve_symbol (UnresolvedSymbol unresolved_symbol) {
213                 if (unresolved_symbol.qualified) {
214                         // qualified access to global symbol
215                         return root_symbol.scope.lookup (unresolved_symbol.name);
216                 } else if (unresolved_symbol.inner == null) {
217                         Symbol sym = null;
218                         Scope scope = current_scope;
219                         while (sym == null && scope != null) {
220                                 sym = scope.lookup (unresolved_symbol.name);
221
222                                 // only look for types and type containers
223                                 if (!(sym is Namespace || sym is TypeSymbol || sym is TypeParameter)) {
224                                         sym = null;
225                                 }
226
227                                 scope = scope.parent_scope;
228                         }
229                         if (sym == null && unresolved_symbol.source_reference != null) {
230                                 foreach (UsingDirective ns in unresolved_symbol.source_reference.using_directives) {
231                                         if (ns.error || ns.namespace_symbol is UnresolvedSymbol) {
232                                                 continue;
233                                         }
234
235                                         var local_sym = ns.namespace_symbol.scope.lookup (unresolved_symbol.name);
236
237                                         // only look for types and type containers
238                                         if (!(local_sym is Namespace || local_sym is TypeSymbol || sym is TypeParameter)) {
239                                                 local_sym = null;
240                                         }
241
242                                         if (local_sym != null) {
243                                                 if (sym != null && sym != local_sym) {
244                                                         unresolved_symbol.error = true;
245                                                         Report.error (unresolved_symbol.source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (unresolved_symbol.name, sym.get_full_name (), local_sym.get_full_name ()));
246                                                         return null;
247                                                 }
248                                                 sym = local_sym;
249                                         }
250                                 }
251                         }
252                         return sym;
253                 } else {
254                         var parent_symbol = resolve_symbol (unresolved_symbol.inner);
255                         if (parent_symbol == null) {
256                                 unresolved_symbol.error = true;
257                                 Report.error (unresolved_symbol.inner.source_reference, "The symbol `%s' could not be found".printf (unresolved_symbol.inner.name));
258                                 return null;
259                         }
260                         parent_symbol.used = true;
261
262                         return parent_symbol.scope.lookup (unresolved_symbol.name);
263                 }
264         }
265
266         DataType get_type_for_struct (Struct st, Struct base_struct) {
267                 if (st.base_type != null) {
268                         // make sure that base type is resolved
269
270                         var old_scope = current_scope;
271                         current_scope = st.scope;
272
273                         st.base_type.accept (this);
274
275                         current_scope = old_scope;
276                 }
277
278                 if (base_struct.base_struct != null) {
279                         return get_type_for_struct (st, base_struct.base_struct);
280                 }
281
282                 // attributes are not processed yet, access them directly
283                 if (base_struct.get_attribute ("BooleanType") != null) {
284                         return new BooleanType (st);
285                 } else if (base_struct.get_attribute ("IntegerType") != null) {
286                         return new IntegerType (st);
287                 } else if (base_struct.get_attribute ("FloatingType") != null) {
288                         return new FloatingType (st);
289                 } else {
290                         return new StructValueType (st);
291                 }
292         }
293
294         private DataType resolve_type (UnresolvedType unresolved_type) {
295                 DataType type = null;
296
297                 // still required for vapigen
298                 if (unresolved_type.unresolved_symbol.name == "void") {
299                         return new VoidType ();
300                 }
301
302                 var sym = resolve_symbol (unresolved_type.unresolved_symbol);
303                 if (sym == null) {
304                         // don't report same error twice
305                         if (!unresolved_type.unresolved_symbol.error) {
306                                 Report.error (unresolved_type.source_reference, "The type name `%s' could not be found".printf (unresolved_type.unresolved_symbol.to_string ()));
307                         }
308                         return new InvalidType ();
309                 }
310
311                 if (sym is TypeParameter) {
312                         type = new GenericType ((TypeParameter) sym);
313                 } else if (sym is TypeSymbol) {
314                         if (sym is Delegate) {
315                                 type = new DelegateType ((Delegate) sym);
316                         } else if (sym is Class) {
317                                 var cl = (Class) sym;
318                                 if (cl.is_error_base) {
319                                         type = new ErrorType (null, null, unresolved_type.source_reference);
320                                 } else {
321                                         type = new ObjectType (cl);
322                                 }
323                         } else if (sym is Interface) {
324                                 type = new ObjectType ((Interface) sym);
325                         } else if (sym is Struct) {
326                                 type = get_type_for_struct ((Struct) sym, (Struct) sym);
327                         } else if (sym is Enum) {
328                                 type = new EnumValueType ((Enum) sym);
329                         } else if (sym is ErrorDomain) {
330                                 type = new ErrorType ((ErrorDomain) sym, null, unresolved_type.source_reference);
331                         } else if (sym is ErrorCode) {
332                                 type = new ErrorType ((ErrorDomain) sym.parent_symbol, (ErrorCode) sym, unresolved_type.source_reference);
333                         } else {
334                                 Report.error (unresolved_type.source_reference, "internal error: `%s' is not a supported type".printf (sym.get_full_name ()));
335                                 return new InvalidType ();
336                         }
337                 } else {
338                         Report.error (unresolved_type.source_reference, "`%s' is not a type".printf (sym.get_full_name ()));
339                         return new InvalidType ();
340                 }
341
342                 type.source_reference = unresolved_type.source_reference;
343                 type.value_owned = unresolved_type.value_owned;
344                 sym.used = true;
345
346                 if (type is GenericType) {
347                         // type parameters are always considered nullable
348                         // actual type argument may or may not be nullable
349                         type.nullable = true;
350                 } else {
351                         type.nullable = unresolved_type.nullable;
352                 }
353
354                 type.is_dynamic = unresolved_type.is_dynamic;
355                 foreach (DataType type_arg in unresolved_type.get_type_arguments ()) {
356                         type.add_type_argument (type_arg);
357                 }
358
359                 return type;
360         }
361
362         public override void visit_data_type (DataType data_type) {
363                 data_type.accept_children (this);
364
365                 if (!(data_type is UnresolvedType)) {
366                         return;
367                 }
368
369                 var unresolved_type = (UnresolvedType) data_type;
370
371                 unresolved_type.parent_node.replace_type (unresolved_type, resolve_type (unresolved_type));
372         }
373
374         public override void visit_declaration_statement (DeclarationStatement stmt) {
375                 stmt.accept_children (this);
376         }
377
378         public override void visit_local_variable (LocalVariable local) {
379                 local.accept_children (this);
380                 if (!context.experimental_non_null) {
381                         // local reference variables are considered nullable
382                         // except when using experimental non-null enhancements
383                         if (local.variable_type is ReferenceType) {
384                                 var array_type = local.variable_type as ArrayType;
385                                 if (array_type != null && array_type.fixed_length) {
386                                         // local fixed length arrays are not nullable
387                                 } else {
388                                         local.variable_type.nullable = true;
389                                 }
390                         }
391                 }
392         }
393
394         public override void visit_initializer_list (InitializerList list) {
395                 list.accept_children (this);
396         }
397
398         public override void visit_expression_statement (ExpressionStatement stmt) {
399                 stmt.accept_children (this);
400         }
401
402         public override void visit_if_statement (IfStatement stmt) {
403                 stmt.accept_children (this);
404         }
405
406         public override void visit_switch_statement (SwitchStatement stmt) {
407                 stmt.accept_children (this);
408         }
409
410         public override void visit_switch_section (SwitchSection section) {
411                 section.accept_children (this);
412         }
413
414         public override void visit_switch_label (SwitchLabel label) {
415                 label.accept_children (this);
416         }
417
418         public override void visit_loop (Loop stmt) {
419                 stmt.accept_children (this);
420         }
421
422         public override void visit_while_statement (WhileStatement stmt) {
423                 stmt.accept_children (this);
424         }
425
426         public override void visit_do_statement (DoStatement stmt) {
427                 stmt.accept_children (this);
428         }
429
430         public override void visit_for_statement (ForStatement stmt) {
431                 stmt.accept_children (this);
432         }
433
434         public override void visit_foreach_statement (ForeachStatement stmt) {
435                 stmt.accept_children (this);
436         }
437
438         public override void visit_return_statement (ReturnStatement stmt) {
439                 stmt.accept_children (this);
440         }
441
442         public override void visit_yield_statement (YieldStatement stmt) {
443                 stmt.accept_children (this);
444         }
445
446         public override void visit_throw_statement (ThrowStatement stmt) {
447                 stmt.accept_children (this);
448         }
449
450         public override void visit_try_statement (TryStatement stmt) {
451                 stmt.accept_children (this);
452         }
453
454         public override void visit_delete_statement (DeleteStatement stmt) {
455                 stmt.accept_children (this);
456         }
457
458         public override void visit_catch_clause (CatchClause clause) {
459                 clause.accept_children (this);
460         }
461
462         public override void visit_array_creation_expression (ArrayCreationExpression e) {
463                 e.accept_children (this);
464         }
465
466         public override void visit_template (Template tmpl) {
467                 tmpl.accept_children (this);
468         }
469
470         public override void visit_tuple (Tuple tuple) {
471                 tuple.accept_children (this);
472         }
473
474         public override void visit_member_access (MemberAccess expr) {
475                 expr.accept_children (this);
476         }
477
478         public override void visit_method_call (MethodCall expr) {
479                 expr.accept_children (this);
480         }
481
482         public override void visit_element_access (ElementAccess expr) {
483                 expr.accept_children (this);
484         }
485
486         public override void visit_slice_expression (SliceExpression expr) {
487                 expr.accept_children (this);
488         }
489
490         public override void visit_postfix_expression (PostfixExpression expr) {
491                 expr.accept_children (this);
492         }
493
494         public override void visit_object_creation_expression (ObjectCreationExpression expr) {
495                 expr.accept_children (this);
496         }
497
498         public override void visit_sizeof_expression (SizeofExpression expr) {
499                 expr.accept_children (this);
500         }
501
502         public override void visit_typeof_expression (TypeofExpression expr) {
503                 expr.accept_children (this);
504         }
505
506         public override void visit_unary_expression (UnaryExpression expr) {
507                 expr.accept_children (this);
508         }
509
510         public override void visit_cast_expression (CastExpression expr) {
511                 expr.accept_children (this);
512         }
513
514         public override void visit_addressof_expression (AddressofExpression expr) {
515                 expr.accept_children (this);
516         }
517
518         public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
519                 expr.accept_children (this);
520         }
521
522         public override void visit_binary_expression (BinaryExpression expr) {
523                 expr.accept_children (this);
524         }
525
526         public override void visit_type_check (TypeCheck expr) {
527                 expr.accept_children (this);
528         }
529
530         public override void visit_conditional_expression (ConditionalExpression expr) {
531                 expr.accept_children (this);
532         }
533
534         public override void visit_lambda_expression (LambdaExpression l) {
535                 l.accept_children (this);
536         }
537
538         public override void visit_assignment (Assignment a) {
539                 a.accept_children (this);
540         }
541 }