Release 0.41.92
[vala-gnome.git] / vala / valasymbolresolver.vala
blob55fa94f629ed44a1640a1c9671404e72f17d4db2
1 /* valasymbolresolver.vala
3 * Copyright (C) 2006-2010 Jürg Billeter
4 * Copyright (C) 2006-2008 Raffaele Sandrini
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.
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.
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
20 * Author:
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
25 using GLib;
27 /**
28 * Code visitor resolving symbol names.
30 public class Vala.SymbolResolver : CodeVisitor {
31 CodeContext context;
32 Symbol root_symbol;
33 Scope current_scope;
35 /**
36 * Resolve symbol names in the specified code context.
38 * @param context a code context
40 public void resolve (CodeContext context) {
41 this.context = context;
42 root_symbol = context.root;
44 context.root.accept (this);
46 root_symbol = null;
47 this.context = null;
50 public override void visit_namespace (Namespace ns) {
51 var old_scope = current_scope;
52 current_scope = ns.scope;
54 ns.accept_children (this);
56 current_scope = old_scope;
59 public override void visit_class (Class cl) {
60 current_scope = cl.scope;
62 cl.accept_children (this);
64 cl.base_class = null;
65 foreach (DataType type in cl.get_base_types ()) {
66 if (type.data_type is Class) {
67 if (cl.base_class != null) {
68 cl.error = true;
69 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 ()));
70 return;
72 cl.base_class = (Class) type.data_type;
73 if (cl.base_class.is_subtype_of (cl)) {
74 cl.error = true;
75 Report.error (type.source_reference, "Base class cycle (`%s' and `%s')".printf (cl.get_full_name (), cl.base_class.get_full_name ()));
76 return;
81 current_scope = current_scope.parent_scope;
84 public override void visit_struct (Struct st) {
85 current_scope = st.scope;
87 st.accept_children (this);
89 if (st.base_type != null) {
90 var base_type = st.base_struct;
91 if (base_type != null) {
92 if (base_type.is_subtype_of (st)) {
93 st.error = true;
94 Report.error (base_type.source_reference, "Base struct cycle (`%s' and `%s')".printf (st.get_full_name (), base_type.get_full_name ()));
95 return;
100 current_scope = current_scope.parent_scope;
103 public override void visit_interface (Interface iface) {
104 current_scope = iface.scope;
106 iface.accept_children (this);
108 foreach (DataType type in iface.get_prerequisites ()) {
109 if (type.data_type != null && type.data_type.is_subtype_of (iface)) {
110 iface.error = true;
111 Report.error (type.source_reference, "Prerequisite cycle (`%s' and `%s')".printf (iface.get_full_name (), type.data_type.get_full_name ()));
112 return;
116 current_scope = current_scope.parent_scope;
119 public override void visit_enum (Enum en) {
120 current_scope = en.scope;
122 en.accept_children (this);
124 current_scope = current_scope.parent_scope;
127 public override void visit_error_domain (ErrorDomain ed) {
128 current_scope = ed.scope;
130 ed.accept_children (this);
132 current_scope = current_scope.parent_scope;
135 public override void visit_delegate (Delegate cb) {
136 current_scope = cb.scope;
138 cb.accept_children (this);
140 current_scope = current_scope.parent_scope;
143 public override void visit_constant (Constant c) {
144 var old_scope = current_scope;
145 if (!(c.parent_symbol is Block)) {
146 // non-local constant
147 current_scope = c.scope;
150 c.accept_children (this);
152 current_scope = old_scope;
155 public override void visit_field (Field f) {
156 current_scope = f.scope;
158 f.accept_children (this);
160 current_scope = current_scope.parent_scope;
163 public override void visit_method (Method m) {
164 current_scope = m.scope;
166 m.accept_children (this);
168 current_scope = current_scope.parent_scope;
171 public override void visit_creation_method (CreationMethod m) {
172 m.accept_children (this);
175 public override void visit_formal_parameter (Parameter p) {
176 p.accept_children (this);
179 public override void visit_property (Property prop) {
180 prop.accept_children (this);
183 public override void visit_property_accessor (PropertyAccessor acc) {
184 acc.accept_children (this);
187 public override void visit_signal (Signal sig) {
188 sig.accept_children (this);
191 public override void visit_constructor (Constructor c) {
192 c.accept_children (this);
195 public override void visit_destructor (Destructor d) {
196 d.accept_children (this);
199 public override void visit_block (Block b) {
200 b.accept_children (this);
203 public override void visit_using_directive (UsingDirective ns) {
204 var unresolved_symbol = ns.namespace_symbol as UnresolvedSymbol;
205 if (unresolved_symbol != null) {
206 ns.namespace_symbol = resolve_symbol (unresolved_symbol);
207 if (!(ns.namespace_symbol is Namespace)) {
208 ns.error = true;
209 Report.error (ns.source_reference, "The namespace name `%s' could not be found".printf (unresolved_symbol.to_string ()));
210 return;
215 private Symbol? resolve_symbol (UnresolvedSymbol unresolved_symbol) {
216 if (unresolved_symbol.qualified) {
217 // qualified access to global symbol
218 return root_symbol.scope.lookup (unresolved_symbol.name);
219 } else if (unresolved_symbol.inner == null) {
220 Symbol sym = null;
221 Scope scope = current_scope;
222 while (sym == null && scope != null) {
223 sym = scope.lookup (unresolved_symbol.name);
225 // only look for types and type containers
226 if (!(sym is Namespace || sym is TypeSymbol || sym is TypeParameter)) {
227 sym = null;
230 scope = scope.parent_scope;
232 if (sym == null && unresolved_symbol.source_reference != null) {
233 foreach (UsingDirective ns in unresolved_symbol.source_reference.using_directives) {
234 if (ns.error || ns.namespace_symbol is UnresolvedSymbol) {
235 continue;
238 var local_sym = ns.namespace_symbol.scope.lookup (unresolved_symbol.name);
240 // only look for types and type containers
241 if (!(local_sym is Namespace || local_sym is TypeSymbol || sym is TypeParameter)) {
242 local_sym = null;
245 if (local_sym != null) {
246 if (sym != null && sym != local_sym) {
247 unresolved_symbol.error = true;
248 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 ()));
249 return null;
251 sym = local_sym;
255 return sym;
256 } else {
257 var parent_symbol = resolve_symbol (unresolved_symbol.inner);
258 if (parent_symbol == null) {
259 unresolved_symbol.error = true;
260 Report.error (unresolved_symbol.inner.source_reference, "The symbol `%s' could not be found".printf (unresolved_symbol.inner.name));
261 return null;
263 parent_symbol.used = true;
265 return parent_symbol.scope.lookup (unresolved_symbol.name);
269 DataType get_type_for_struct (Struct st, Struct base_struct) {
270 if (st.base_type != null) {
271 // make sure that base type is resolved
273 if (current_scope == st.scope) {
274 // recursive declaration in generic base type
275 return new StructValueType (st);
278 var old_scope = current_scope;
279 current_scope = st.scope;
281 st.base_type.accept (this);
283 current_scope = old_scope;
286 if (base_struct.base_struct != null) {
287 return get_type_for_struct (st, base_struct.base_struct);
290 // attributes are not processed yet, access them directly
291 if (base_struct.get_attribute ("BooleanType") != null) {
292 return new BooleanType (st);
293 } else if (base_struct.get_attribute ("IntegerType") != null) {
294 return new IntegerType (st);
295 } else if (base_struct.get_attribute ("FloatingType") != null) {
296 return new FloatingType (st);
297 } else {
298 return new StructValueType (st);
302 private DataType resolve_type (UnresolvedType unresolved_type) {
303 DataType type = null;
305 // still required for vapigen
306 if (unresolved_type.unresolved_symbol.name == "void") {
307 return new VoidType ();
310 var sym = resolve_symbol (unresolved_type.unresolved_symbol);
311 if (sym == null) {
312 // don't report same error twice
313 if (!unresolved_type.unresolved_symbol.error) {
314 Report.error (unresolved_type.source_reference, "The type name `%s' could not be found".printf (unresolved_type.unresolved_symbol.to_string ()));
316 return new InvalidType ();
319 if (sym is TypeParameter) {
320 type = new GenericType ((TypeParameter) sym);
321 } else if (sym is TypeSymbol) {
322 if (sym is Delegate) {
323 type = new DelegateType ((Delegate) sym);
324 } else if (sym is Class) {
325 var cl = (Class) sym;
326 if (cl.is_error_base) {
327 type = new ErrorType (null, null, unresolved_type.source_reference);
328 } else {
329 type = new ObjectType (cl);
331 } else if (sym is Interface) {
332 type = new ObjectType ((Interface) sym);
333 } else if (sym is Struct) {
334 type = get_type_for_struct ((Struct) sym, (Struct) sym);
335 } else if (sym is Enum) {
336 type = new EnumValueType ((Enum) sym);
337 } else if (sym is ErrorDomain) {
338 type = new ErrorType ((ErrorDomain) sym, null, unresolved_type.source_reference);
339 } else if (sym is ErrorCode) {
340 type = new ErrorType ((ErrorDomain) sym.parent_symbol, (ErrorCode) sym, unresolved_type.source_reference);
341 } else {
342 Report.error (unresolved_type.source_reference, "internal error: `%s' is not a supported type".printf (sym.get_full_name ()));
343 return new InvalidType ();
345 } else {
346 Report.error (unresolved_type.source_reference, "`%s' is not a type".printf (sym.get_full_name ()));
347 return new InvalidType ();
350 type.source_reference = unresolved_type.source_reference;
351 type.value_owned = unresolved_type.value_owned;
352 sym.used = true;
354 if (type is GenericType) {
355 // type parameters are always considered nullable
356 // actual type argument may or may not be nullable
357 type.nullable = true;
358 } else {
359 type.nullable = unresolved_type.nullable;
362 type.is_dynamic = unresolved_type.is_dynamic;
363 foreach (DataType type_arg in unresolved_type.get_type_arguments ()) {
364 type.add_type_argument (type_arg);
367 return type;
370 public override void visit_data_type (DataType data_type) {
371 data_type.accept_children (this);
373 if (!(data_type is UnresolvedType)) {
374 return;
377 var unresolved_type = (UnresolvedType) data_type;
379 unresolved_type.parent_node.replace_type (unresolved_type, resolve_type (unresolved_type));
382 public override void visit_declaration_statement (DeclarationStatement stmt) {
383 stmt.accept_children (this);
386 public override void visit_local_variable (LocalVariable local) {
387 local.accept_children (this);
388 if (!context.experimental_non_null) {
389 // local reference variables are considered nullable
390 // except when using experimental non-null enhancements
391 if (local.variable_type is ReferenceType) {
392 var array_type = local.variable_type as ArrayType;
393 if (array_type != null && array_type.fixed_length) {
394 // local fixed length arrays are not nullable
395 } else {
396 local.variable_type.nullable = true;
402 public override void visit_initializer_list (InitializerList list) {
403 list.accept_children (this);
406 public override void visit_expression_statement (ExpressionStatement stmt) {
407 stmt.accept_children (this);
410 public override void visit_if_statement (IfStatement stmt) {
411 stmt.accept_children (this);
414 public override void visit_switch_statement (SwitchStatement stmt) {
415 stmt.accept_children (this);
418 public override void visit_switch_section (SwitchSection section) {
419 section.accept_children (this);
422 public override void visit_switch_label (SwitchLabel label) {
423 label.accept_children (this);
426 public override void visit_loop (Loop stmt) {
427 stmt.accept_children (this);
430 public override void visit_while_statement (WhileStatement stmt) {
431 stmt.accept_children (this);
434 public override void visit_do_statement (DoStatement stmt) {
435 stmt.accept_children (this);
438 public override void visit_for_statement (ForStatement stmt) {
439 stmt.accept_children (this);
442 public override void visit_foreach_statement (ForeachStatement stmt) {
443 stmt.accept_children (this);
446 public override void visit_return_statement (ReturnStatement stmt) {
447 stmt.accept_children (this);
450 public override void visit_yield_statement (YieldStatement stmt) {
451 stmt.accept_children (this);
454 public override void visit_throw_statement (ThrowStatement stmt) {
455 stmt.accept_children (this);
458 public override void visit_try_statement (TryStatement stmt) {
459 stmt.accept_children (this);
462 public override void visit_delete_statement (DeleteStatement stmt) {
463 stmt.accept_children (this);
466 public override void visit_catch_clause (CatchClause clause) {
467 clause.accept_children (this);
470 public override void visit_array_creation_expression (ArrayCreationExpression e) {
471 e.accept_children (this);
474 public override void visit_template (Template tmpl) {
475 tmpl.accept_children (this);
478 public override void visit_tuple (Tuple tuple) {
479 tuple.accept_children (this);
482 public override void visit_member_access (MemberAccess expr) {
483 expr.accept_children (this);
486 public override void visit_method_call (MethodCall expr) {
487 expr.accept_children (this);
490 public override void visit_element_access (ElementAccess expr) {
491 expr.accept_children (this);
494 public override void visit_slice_expression (SliceExpression expr) {
495 expr.accept_children (this);
498 public override void visit_postfix_expression (PostfixExpression expr) {
499 expr.accept_children (this);
502 public override void visit_object_creation_expression (ObjectCreationExpression expr) {
503 expr.accept_children (this);
506 public override void visit_sizeof_expression (SizeofExpression expr) {
507 expr.accept_children (this);
510 public override void visit_typeof_expression (TypeofExpression expr) {
511 expr.accept_children (this);
514 public override void visit_unary_expression (UnaryExpression expr) {
515 expr.accept_children (this);
518 public override void visit_cast_expression (CastExpression expr) {
519 expr.accept_children (this);
522 public override void visit_named_argument (NamedArgument expr) {
523 expr.accept_children (this);
526 public override void visit_addressof_expression (AddressofExpression expr) {
527 expr.accept_children (this);
530 public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
531 expr.accept_children (this);
534 public override void visit_binary_expression (BinaryExpression expr) {
535 expr.accept_children (this);
538 public override void visit_type_check (TypeCheck expr) {
539 expr.accept_children (this);
542 public override void visit_conditional_expression (ConditionalExpression expr) {
543 expr.accept_children (this);
546 public override void visit_lambda_expression (LambdaExpression l) {
547 l.accept_children (this);
550 public override void visit_assignment (Assignment a) {
551 a.accept_children (this);