glib-2.0: Fix g_variant_new_tuple binding
[vala-lang.git] / vala / valasymbolresolver.vala
blob54b33095964752c07fd0b041211aa26ad474e75e
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);
47 public override void visit_namespace (Namespace ns) {
48 var old_scope = current_scope;
49 current_scope = ns.scope;
51 ns.accept_children (this);
53 current_scope = old_scope;
56 public override void visit_class (Class cl) {
57 current_scope = cl.scope;
59 cl.accept_children (this);
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;
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;
78 if (context.profile == Profile.DOVA) {
79 // classes derive from Object by default
80 if (cl.base_class == null) {
81 var any_class = (Class) root_symbol.scope.lookup ("any");
82 if (cl != any_class) {
83 var object_class = (Class) root_symbol.scope.lookup ("Dova").scope.lookup ("Object");
84 cl.add_base_type (new ObjectType (object_class));
85 cl.base_class = object_class;
90 current_scope = current_scope.parent_scope;
93 public override void visit_struct (Struct st) {
94 current_scope = st.scope;
96 st.accept_children (this);
98 if (st.base_type != null) {
99 var base_type = st.base_struct;
100 if (base_type != null) {
101 if (base_type.is_subtype_of (st)) {
102 st.error = true;
103 Report.error (base_type.source_reference, "Base struct cycle (`%s' and `%s')".printf (st.get_full_name (), base_type.get_full_name ()));
104 return;
109 current_scope = current_scope.parent_scope;
112 public override void visit_interface (Interface iface) {
113 current_scope = iface.scope;
115 iface.accept_children (this);
117 foreach (DataType type in iface.get_prerequisites ()) {
118 if (type.data_type != null && type.data_type.is_subtype_of (iface)) {
119 iface.error = true;
120 Report.error (type.source_reference, "Prerequisite cycle (`%s' and `%s')".printf (iface.get_full_name (), type.data_type.get_full_name ()));
121 return;
125 if (context.profile == Profile.DOVA) {
126 // all interfaces require Object
127 if (iface.get_prerequisites ().size == 0) {
128 var object_class = (Class) root_symbol.scope.lookup ("Dova").scope.lookup ("Object");
129 iface.add_prerequisite (new ObjectType (object_class));
133 current_scope = current_scope.parent_scope;
136 public override void visit_enum (Enum en) {
137 current_scope = en.scope;
139 en.accept_children (this);
141 current_scope = current_scope.parent_scope;
144 public override void visit_error_domain (ErrorDomain ed) {
145 current_scope = ed.scope;
147 ed.accept_children (this);
149 current_scope = current_scope.parent_scope;
152 public override void visit_delegate (Delegate cb) {
153 current_scope = cb.scope;
155 cb.accept_children (this);
157 current_scope = current_scope.parent_scope;
160 public override void visit_constant (Constant c) {
161 var old_scope = current_scope;
162 current_scope = c.scope;
164 c.accept_children (this);
166 current_scope = old_scope;
169 public override void visit_field (Field f) {
170 current_scope = f.scope;
172 f.accept_children (this);
174 current_scope = current_scope.parent_scope;
177 public override void visit_method (Method m) {
178 current_scope = m.scope;
180 m.accept_children (this);
182 current_scope = current_scope.parent_scope;
185 public override void visit_creation_method (CreationMethod m) {
186 m.accept_children (this);
189 public override void visit_formal_parameter (FormalParameter p) {
190 p.accept_children (this);
193 public override void visit_property (Property prop) {
194 prop.accept_children (this);
197 public override void visit_property_accessor (PropertyAccessor acc) {
198 acc.accept_children (this);
201 public override void visit_signal (Signal sig) {
202 sig.accept_children (this);
205 public override void visit_constructor (Constructor c) {
206 c.accept_children (this);
209 public override void visit_destructor (Destructor d) {
210 d.accept_children (this);
213 public override void visit_block (Block b) {
214 b.accept_children (this);
217 public override void visit_using_directive (UsingDirective ns) {
218 var unresolved_symbol = ns.namespace_symbol as UnresolvedSymbol;
219 if (unresolved_symbol != null) {
220 ns.namespace_symbol = resolve_symbol (unresolved_symbol);
221 if (!(ns.namespace_symbol is Namespace)) {
222 ns.error = true;
223 Report.error (ns.source_reference, "The namespace name `%s' could not be found".printf (unresolved_symbol.to_string ()));
224 return;
229 private Symbol? resolve_symbol (UnresolvedSymbol unresolved_symbol) {
230 if (unresolved_symbol.qualified) {
231 // qualified access to global symbol
232 return root_symbol.scope.lookup (unresolved_symbol.name);
233 } else if (unresolved_symbol.inner == null) {
234 Symbol sym = null;
235 Scope scope = current_scope;
236 while (sym == null && scope != null) {
237 sym = scope.lookup (unresolved_symbol.name);
239 // only look for types and type containers
240 if (!(sym is Namespace || sym is TypeSymbol || sym is TypeParameter)) {
241 sym = null;
244 scope = scope.parent_scope;
246 if (sym == null && unresolved_symbol.source_reference != null) {
247 foreach (UsingDirective ns in unresolved_symbol.source_reference.using_directives) {
248 if (ns.error || ns.namespace_symbol is UnresolvedSymbol) {
249 continue;
252 var local_sym = ns.namespace_symbol.scope.lookup (unresolved_symbol.name);
254 // only look for types and type containers
255 if (!(local_sym is Namespace || local_sym is TypeSymbol || sym is TypeParameter)) {
256 local_sym = null;
259 if (local_sym != null) {
260 if (sym != null && sym != local_sym) {
261 unresolved_symbol.error = true;
262 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 ()));
263 return null;
265 sym = local_sym;
269 return sym;
270 } else {
271 var parent_symbol = resolve_symbol (unresolved_symbol.inner);
272 if (parent_symbol == null) {
273 unresolved_symbol.error = true;
274 Report.error (unresolved_symbol.inner.source_reference, "The symbol `%s' could not be found".printf (unresolved_symbol.inner.name));
275 return null;
277 parent_symbol.used = true;
279 return parent_symbol.scope.lookup (unresolved_symbol.name);
283 DataType get_type_for_struct (Struct st, Struct base_struct) {
284 if (st.base_type != null) {
285 // make sure that base type is resolved
287 var old_scope = current_scope;
288 current_scope = st.scope;
290 st.base_type.accept (this);
292 current_scope = old_scope;
295 if (base_struct.base_struct != null) {
296 return get_type_for_struct (st, base_struct.base_struct);
299 // attributes are not processed yet, access them directly
300 if (base_struct.get_attribute ("BooleanType") != null) {
301 return new BooleanType (st);
302 } else if (base_struct.get_attribute ("IntegerType") != null) {
303 return new IntegerType (st);
304 } else if (base_struct.get_attribute ("FloatingType") != null) {
305 return new FloatingType (st);
306 } else {
307 return new StructValueType (st);
311 private DataType resolve_type (UnresolvedType unresolved_type) {
312 DataType type = null;
314 // still required for vapigen
315 if (unresolved_type.unresolved_symbol.name == "void") {
316 return new VoidType ();
319 var sym = resolve_symbol (unresolved_type.unresolved_symbol);
320 if (sym == null) {
321 // don't report same error twice
322 if (!unresolved_type.unresolved_symbol.error) {
323 Report.error (unresolved_type.source_reference, "The type name `%s' could not be found".printf (unresolved_type.unresolved_symbol.to_string ()));
325 return new InvalidType ();
328 if (sym is TypeParameter) {
329 type = new GenericType ((TypeParameter) sym);
330 } else if (sym is TypeSymbol) {
331 if (sym is Delegate) {
332 type = new DelegateType ((Delegate) sym);
333 } else if (sym is Class) {
334 var cl = (Class) sym;
335 if (cl.is_error_base) {
336 type = new ErrorType (null, null, unresolved_type.source_reference);
337 } else {
338 type = new ObjectType (cl);
340 } else if (sym is Interface) {
341 type = new ObjectType ((Interface) sym);
342 } else if (sym is Struct) {
343 type = get_type_for_struct ((Struct) sym, (Struct) sym);
344 } else if (sym is Enum) {
345 type = new EnumValueType ((Enum) sym);
346 } else if (sym is ErrorDomain) {
347 type = new ErrorType ((ErrorDomain) sym, null, unresolved_type.source_reference);
348 } else if (sym is ErrorCode) {
349 type = new ErrorType ((ErrorDomain) sym.parent_symbol, (ErrorCode) sym, unresolved_type.source_reference);
350 } else {
351 Report.error (unresolved_type.source_reference, "internal error: `%s' is not a supported type".printf (sym.get_full_name ()));
352 return new InvalidType ();
354 } else {
355 Report.error (unresolved_type.source_reference, "`%s' is not a type".printf (sym.get_full_name ()));
356 return new InvalidType ();
359 type.source_reference = unresolved_type.source_reference;
360 type.value_owned = unresolved_type.value_owned;
361 sym.used = true;
363 if (type is GenericType) {
364 // type parameters are always considered nullable
365 // actual type argument may or may not be nullable
366 type.nullable = true;
367 } else {
368 type.nullable = unresolved_type.nullable;
371 type.is_dynamic = unresolved_type.is_dynamic;
372 foreach (DataType type_arg in unresolved_type.get_type_arguments ()) {
373 type.add_type_argument (type_arg);
376 return type;
379 public override void visit_data_type (DataType data_type) {
380 data_type.accept_children (this);
382 if (!(data_type is UnresolvedType)) {
383 return;
386 var unresolved_type = (UnresolvedType) data_type;
388 unresolved_type.parent_node.replace_type (unresolved_type, resolve_type (unresolved_type));
391 public override void visit_declaration_statement (DeclarationStatement stmt) {
392 stmt.accept_children (this);
395 public override void visit_local_variable (LocalVariable local) {
396 local.accept_children (this);
397 if (!context.experimental_non_null) {
398 // local reference variables are considered nullable
399 // except when using experimental non-null enhancements
400 if (local.variable_type is ReferenceType) {
401 var array_type = local.variable_type as ArrayType;
402 if (array_type != null && array_type.fixed_length) {
403 // local fixed length arrays are not nullable
404 } else {
405 local.variable_type.nullable = true;
411 public override void visit_initializer_list (InitializerList list) {
412 list.accept_children (this);
415 public override void visit_expression_statement (ExpressionStatement stmt) {
416 stmt.accept_children (this);
419 public override void visit_if_statement (IfStatement stmt) {
420 stmt.accept_children (this);
423 public override void visit_switch_statement (SwitchStatement stmt) {
424 stmt.accept_children (this);
427 public override void visit_switch_section (SwitchSection section) {
428 section.accept_children (this);
431 public override void visit_switch_label (SwitchLabel label) {
432 label.accept_children (this);
435 public override void visit_loop (Loop stmt) {
436 stmt.accept_children (this);
439 public override void visit_while_statement (WhileStatement stmt) {
440 stmt.accept_children (this);
443 public override void visit_do_statement (DoStatement stmt) {
444 stmt.accept_children (this);
447 public override void visit_for_statement (ForStatement stmt) {
448 stmt.accept_children (this);
451 public override void visit_foreach_statement (ForeachStatement stmt) {
452 stmt.accept_children (this);
455 public override void visit_return_statement (ReturnStatement stmt) {
456 stmt.accept_children (this);
459 public override void visit_yield_statement (YieldStatement stmt) {
460 stmt.accept_children (this);
463 public override void visit_throw_statement (ThrowStatement stmt) {
464 stmt.accept_children (this);
467 public override void visit_try_statement (TryStatement stmt) {
468 stmt.accept_children (this);
471 public override void visit_catch_clause (CatchClause clause) {
472 clause.accept_children (this);
475 public override void visit_array_creation_expression (ArrayCreationExpression e) {
476 e.accept_children (this);
479 public override void visit_template (Template tmpl) {
480 tmpl.accept_children (this);
483 public override void visit_list_literal (ListLiteral lit) {
484 lit.accept_children (this);
487 public override void visit_set_literal (SetLiteral lit) {
488 lit.accept_children (this);
491 public override void visit_map_literal (MapLiteral lit) {
492 lit.accept_children (this);
495 public override void visit_tuple (Tuple tuple) {
496 tuple.accept_children (this);
499 public override void visit_member_access (MemberAccess expr) {
500 expr.accept_children (this);
503 public override void visit_method_call (MethodCall expr) {
504 expr.accept_children (this);
507 public override void visit_element_access (ElementAccess expr) {
508 expr.accept_children (this);
511 public override void visit_slice_expression (SliceExpression expr) {
512 expr.accept_children (this);
515 public override void visit_postfix_expression (PostfixExpression expr) {
516 expr.accept_children (this);
519 public override void visit_object_creation_expression (ObjectCreationExpression expr) {
520 expr.accept_children (this);
523 public override void visit_sizeof_expression (SizeofExpression expr) {
524 expr.accept_children (this);
527 public override void visit_typeof_expression (TypeofExpression expr) {
528 expr.accept_children (this);
531 public override void visit_unary_expression (UnaryExpression expr) {
532 expr.accept_children (this);
535 public override void visit_cast_expression (CastExpression expr) {
536 expr.accept_children (this);
539 public override void visit_addressof_expression (AddressofExpression expr) {
540 expr.accept_children (this);
543 public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
544 expr.accept_children (this);
547 public override void visit_binary_expression (BinaryExpression expr) {
548 expr.accept_children (this);
551 public override void visit_type_check (TypeCheck expr) {
552 expr.accept_children (this);
555 public override void visit_conditional_expression (ConditionalExpression expr) {
556 expr.accept_children (this);
559 public override void visit_lambda_expression (LambdaExpression l) {
560 l.accept_children (this);
563 public override void visit_assignment (Assignment a) {
564 a.accept_children (this);