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
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
28 * Code visitor resolving symbol names.
30 public class Vala
.SymbolResolver
: CodeVisitor
{
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
);
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
);
65 foreach (DataType type
in cl
.get_base_types ()) {
66 if (type
.data_type is Class
) {
67 if (cl
.base_class
!= null) {
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 ()));
72 cl
.base_class
= (Class
) type
.data_type
;
73 if (cl
.base_class
.is_subtype_of (cl
)) {
75 Report
.error (type
.source_reference
, "Base class cycle (`%s' and `%s')".printf (cl
.get_full_name (), cl
.base_class
.get_full_name ()));
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
)) {
94 Report
.error (base_type
.source_reference
, "Base struct cycle (`%s' and `%s')".printf (st
.get_full_name (), base_type
.get_full_name ()));
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
)) {
111 Report
.error (type
.source_reference
, "Prerequisite cycle (`%s' and `%s')".printf (iface
.get_full_name (), type
.data_type
.get_full_name ()));
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
)) {
209 Report
.error (ns
.source_reference
, "The namespace name `%s' could not be found".printf (unresolved_symbol
.to_string ()));
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) {
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
)) {
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
) {
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
)) {
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 ()));
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
));
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
);
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
);
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
);
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
);
342 Report
.error (unresolved_type
.source_reference
, "internal error: `%s' is not a supported type".printf (sym
.get_full_name ()));
343 return new
InvalidType ();
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
;
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;
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
);
370 public override void visit_data_type (DataType data_type
) {
371 data_type
.accept_children (this
);
373 if (!(data_type is UnresolvedType
)) {
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
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
);