valasymbolresolver.vala 17.2 KB
Newer Older
1 2
/* valasymbolresolver.vala
 *
3
 * Copyright (C) 2006-2010  Jürg Billeter
4
 * Copyright (C) 2006-2008  Raffaele Sandrini
5 6 7 8
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * 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 12 13 14 15 16 17 18 19 20 21

 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 *
 * Author:
 * 	Jürg Billeter <j@bitron.ch>
22
 * 	Raffaele Sandrini <raffaele@sandrini.ch>
23 24 25 26
 */

using GLib;

27 28 29 30 31
/**
 * Code visitor resolving symbol names.
 */
public class Vala.SymbolResolver : CodeVisitor {
	Symbol root_symbol;
32
	Scope current_scope;
33

34 35 36 37 38
	/**
	 * Resolve symbol names in the specified code context.
	 *
	 * @param context a code context
	 */
39
	public void resolve (CodeContext context) {
40
		root_symbol = context.root;
41

42
		context.root.accept (this);
43 44

		root_symbol = null;
45
	}
46

47 48 49
	public override void visit_namespace (Namespace ns) {
		var old_scope = current_scope;
		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 58 59 60
		if (cl.checked) {
			return;
		}

61
		current_scope = cl.scope;
62

63 64
		cl.accept_children (this);

65
		cl.base_class = null;
66
		foreach (DataType type in cl.get_base_types ()) {
67
			if (type.data_type is Class) {
68
				if (cl.base_class != null) {
Jürg Billeter's avatar
Jürg Billeter committed
69
					cl.error = true;
70
					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 ()));
71
					return;
72
				}
73
				cl.base_class = (Class) type.data_type;
Jürg Billeter's avatar
Jürg Billeter committed
74 75 76 77 78
				if (cl.base_class.is_subtype_of (cl)) {
					cl.error = true;
					Report.error (type.source_reference, "Base class cycle (`%s' and `%s')".printf (cl.get_full_name (), cl.base_class.get_full_name ()));
					return;
				}
79
			}
80
		}
81

82
		current_scope = current_scope.parent_scope;
83
	}
84

85
	public override void visit_struct (Struct st) {
86 87 88 89
		if (st.checked) {
			return;
		}

90
		current_scope = st.scope;
91

92 93
		st.accept_children (this);

94
		if (st.base_type != null) {
95
			var base_type = st.base_struct;
96 97 98
			if (base_type != null) {
				if (base_type.is_subtype_of (st)) {
					st.error = true;
99
					Report.error (st.source_reference, "Base struct cycle (`%s' and `%s')".printf (st.get_full_name (), base_type.get_full_name ()));
100 101 102 103 104
					return;
				}
			}
		}

105
		current_scope = current_scope.parent_scope;
106 107
	}

108
	public override void visit_interface (Interface iface) {
109 110 111 112
		if (iface.checked) {
			return;
		}

113
		current_scope = iface.scope;
114

115 116
		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 120 121 122 123 124
				iface.error = true;
				Report.error (type.source_reference, "Prerequisite cycle (`%s' and `%s')".printf (iface.get_full_name (), type.data_type.get_full_name ()));
				return;
			}
		}

125
		current_scope = current_scope.parent_scope;
126 127
	}

128
	public override void visit_enum (Enum en) {
129 130 131 132
		if (en.checked) {
			return;
		}

133
		current_scope = en.scope;
134 135 136

		en.accept_children (this);

137
		current_scope = current_scope.parent_scope;
138 139
	}

140
	public override void visit_error_domain (ErrorDomain ed) {
141 142 143 144
		if (ed.checked) {
			return;
		}

145 146 147 148 149 150 151
		current_scope = ed.scope;

		ed.accept_children (this);

		current_scope = current_scope.parent_scope;
	}

152
	public override void visit_delegate (Delegate cb) {
153 154 155 156
		if (cb.checked) {
			return;
		}

157
		current_scope = cb.scope;
158

159 160
		cb.accept_children (this);

161
		current_scope = current_scope.parent_scope;
162 163
	}

164
	public override void visit_constant (Constant c) {
165 166 167 168
		if (c.checked) {
			return;
		}

169
		var old_scope = current_scope;
170 171 172 173
		if (!(c.parent_symbol is Block)) {
			// non-local constant
			current_scope = c.scope;
		}
174

175
		c.accept_children (this);
176 177

		current_scope = old_scope;
178 179
	}

180
	public override void visit_field (Field f) {
181 182 183 184
		if (f.checked) {
			return;
		}

185 186
		current_scope = f.scope;

187
		f.accept_children (this);
188 189

		current_scope = current_scope.parent_scope;
190 191
	}

192
	public override void visit_method (Method m) {
193 194 195 196
		if (m.checked) {
			return;
		}

197 198
		current_scope = m.scope;

199
		m.accept_children (this);
200 201

		current_scope = current_scope.parent_scope;
202 203
	}

204
	public override void visit_creation_method (CreationMethod m) {
205 206 207
		if (m.checked) {
			return;
		}
208 209 210
		m.accept_children (this);
	}

211
	public override void visit_formal_parameter (Parameter p) {
212 213 214
		if (p.checked) {
			return;
		}
215
		p.accept_children (this);
216 217
	}

218
	public override void visit_property (Property prop) {
219 220 221
		if (prop.checked) {
			return;
		}
222 223 224
		prop.accept_children (this);
	}

225
	public override void visit_property_accessor (PropertyAccessor acc) {
226 227 228
		if (acc.checked) {
			return;
		}
229 230 231
		acc.accept_children (this);
	}

232
	public override void visit_signal (Signal sig) {
233 234 235
		if (sig.checked) {
			return;
		}
236 237 238
		sig.accept_children (this);
	}

239
	public override void visit_constructor (Constructor c) {
240 241 242
		if (c.checked) {
			return;
		}
243 244 245
		c.accept_children (this);
	}

246
	public override void visit_destructor (Destructor d) {
247 248 249
		if (d.checked) {
			return;
		}
250 251 252
		d.accept_children (this);
	}

253
	public override void visit_block (Block b) {
254 255 256
		if (b.checked) {
			return;
		}
257 258 259
		b.accept_children (this);
	}

260 261 262 263
	public override void visit_using_directive (UsingDirective ns) {
		var unresolved_symbol = ns.namespace_symbol as UnresolvedSymbol;
		if (unresolved_symbol != null) {
			ns.namespace_symbol = resolve_symbol (unresolved_symbol);
264
			if (!(ns.namespace_symbol is Namespace)) {
265 266 267 268
				ns.error = true;
				Report.error (ns.source_reference, "The namespace name `%s' could not be found".printf (unresolved_symbol.to_string ()));
				return;
			}
269
		}
270
	}
271

272
	private Symbol? resolve_symbol (UnresolvedSymbol unresolved_symbol) {
273 274 275 276
		if (unresolved_symbol.qualified) {
			// qualified access to global symbol
			return root_symbol.scope.lookup (unresolved_symbol.name);
		} else if (unresolved_symbol.inner == null) {
277
			Symbol sym = null;
278
			Scope scope = current_scope;
279
			while (sym == null && scope != null) {
280
				sym = scope.lookup (unresolved_symbol.name);
281 282 283 284 285 286

				// only look for types and type containers
				if (!(sym is Namespace || sym is TypeSymbol || sym is TypeParameter)) {
					sym = null;
				}

287
				scope = scope.parent_scope;
288
			}
289 290
			if (sym == null && unresolved_symbol.source_reference != null) {
				foreach (UsingDirective ns in unresolved_symbol.source_reference.using_directives) {
291
					if (ns.error || ns.namespace_symbol is UnresolvedSymbol) {
292 293 294
						continue;
					}

295
					var local_sym = ns.namespace_symbol.scope.lookup (unresolved_symbol.name);
296 297 298 299 300 301

					// only look for types and type containers
					if (!(local_sym is Namespace || local_sym is TypeSymbol || sym is TypeParameter)) {
						local_sym = null;
					}

302
					if (local_sym != null) {
303
						if (sym != null && sym != local_sym) {
304 305 306
							unresolved_symbol.error = true;
							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 ()));
							return null;
307
						}
308
						sym = local_sym;
309 310
					}
				}
311
			}
312
			return sym;
313
		} else {
314 315 316 317 318
			var parent_symbol = resolve_symbol (unresolved_symbol.inner);
			if (parent_symbol == null) {
				unresolved_symbol.error = true;
				Report.error (unresolved_symbol.inner.source_reference, "The symbol `%s' could not be found".printf (unresolved_symbol.inner.name));
				return null;
319
			}
320
			parent_symbol.used = true;
321 322 323 324 325

			return parent_symbol.scope.lookup (unresolved_symbol.name);
		}
	}

326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
	bool has_base_struct_cycle (Struct st, Struct loop_st) {
		if (!(st.base_type is UnresolvedType)) {
			return false;
		}

		var sym = resolve_symbol (((UnresolvedType) st.base_type).unresolved_symbol);
		unowned Struct? base_struct = sym as Struct;
		if (base_struct == null) {
			return false;
		}

		if (base_struct == loop_st) {
			return true;
		}

		return has_base_struct_cycle (base_struct, loop_st);
	}

344
	DataType get_type_for_struct (Struct st, Struct base_struct) {
345 346
		if (st.base_type != null) {
			// make sure that base type is resolved
347

348 349 350 351 352
			if (has_base_struct_cycle (st, st)) {
				// recursive declaration in base type
				return new StructValueType (st);
			}

353 354 355 356 357
			if (current_scope == st.scope) {
				// recursive declaration in generic base type
				return new StructValueType (st);
			}

358 359 360
			var old_scope = current_scope;
			current_scope = st.scope;

361
			st.base_type.accept (this);
362 363

			current_scope = old_scope;
364 365
		}

366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
		if (base_struct.base_struct != null) {
			return get_type_for_struct (st, base_struct.base_struct);
		}

		// attributes are not processed yet, access them directly
		if (base_struct.get_attribute ("BooleanType") != null) {
			return new BooleanType (st);
		} else if (base_struct.get_attribute ("IntegerType") != null) {
			return new IntegerType (st);
		} else if (base_struct.get_attribute ("FloatingType") != null) {
			return new FloatingType (st);
		} else {
			return new StructValueType (st);
		}
	}

382
	private DataType resolve_type (UnresolvedType unresolved_type) {
383
		DataType type = null;
384 385 386 387 388 389 390 391 392 393

		// still required for vapigen
		if (unresolved_type.unresolved_symbol.name == "void") {
			return new VoidType ();
		}

		var sym = resolve_symbol (unresolved_type.unresolved_symbol);
		if (sym == null) {
			// don't report same error twice
			if (!unresolved_type.unresolved_symbol.error) {
394
				Report.error (unresolved_type.source_reference, "The type name `%s' could not be found".printf (unresolved_type.unresolved_symbol.to_string ()));
395
			}
396 397 398 399
			return new InvalidType ();
		}

		if (sym is TypeParameter) {
400
			type = new GenericType ((TypeParameter) sym);
401
		} else if (sym is TypeSymbol) {
402 403
			if (sym is Delegate) {
				type = new DelegateType ((Delegate) sym);
404 405 406
			} else if (sym is Class) {
				var cl = (Class) sym;
				if (cl.is_error_base) {
407
					type = new ErrorType (null, null, unresolved_type.source_reference);
408
				} else {
409
					type = new ObjectType (cl);
410 411
				}
			} else if (sym is Interface) {
412
				type = new ObjectType ((Interface) sym);
413
			} else if (sym is Struct) {
414
				type = get_type_for_struct ((Struct) sym, (Struct) sym);
415
			} else if (sym is Enum) {
416
				type = new EnumValueType ((Enum) sym);
417
			} else if (sym is ErrorDomain) {
418 419 420
				type = new ErrorType ((ErrorDomain) sym, null, unresolved_type.source_reference);
			} else if (sym is ErrorCode) {
				type = new ErrorType ((ErrorDomain) sym.parent_symbol, (ErrorCode) sym, unresolved_type.source_reference);
421
			} else {
422 423
				Report.error (unresolved_type.source_reference, "internal error: `%s' is not a supported type".printf (sym.get_full_name ()));
				return new InvalidType ();
424
			}
425
		} else {
426
			Report.error (unresolved_type.source_reference, "`%s' is not a type".printf (sym.get_full_name ()));
427
			return new InvalidType ();
428
		}
429

430
		type.source_reference = unresolved_type.source_reference;
431
		type.value_owned = unresolved_type.value_owned;
432
		sym.used = true;
433 434 435 436 437 438 439 440 441

		if (type is GenericType) {
			// type parameters are always considered nullable
			// actual type argument may or may not be nullable
			type.nullable = true;
		} else {
			type.nullable = unresolved_type.nullable;
		}

442
		type.is_dynamic = unresolved_type.is_dynamic;
443 444 445 446
		foreach (DataType type_arg in unresolved_type.get_type_arguments ()) {
			type.add_type_argument (type_arg);
		}

447 448 449
		return type;
	}

450
	public override void visit_data_type (DataType data_type) {
451 452
		data_type.accept_children (this);

453 454 455 456 457 458
		if (!(data_type is UnresolvedType)) {
			return;
		}

		var unresolved_type = (UnresolvedType) data_type;

459
		unresolved_type.parent_node.replace_type (unresolved_type, resolve_type (unresolved_type));
460
	}
461

462
	public override void visit_declaration_statement (DeclarationStatement stmt) {
463 464 465
		if (stmt.checked) {
			return;
		}
466 467 468
		stmt.accept_children (this);
	}

469
	public override void visit_local_variable (LocalVariable local) {
470 471 472
		if (local.checked) {
			return;
		}
473
		local.accept_children (this);
474 475
	}

476
	public override void visit_initializer_list (InitializerList list) {
477 478 479
		if (list.checked) {
			return;
		}
480 481 482
		list.accept_children (this);
	}

483
	public override void visit_expression_statement (ExpressionStatement stmt) {
484 485 486
		if (stmt.checked) {
			return;
		}
487 488 489
		stmt.accept_children (this);
	}

490
	public override void visit_if_statement (IfStatement stmt) {
491 492 493
		if (stmt.checked) {
			return;
		}
494 495 496
		stmt.accept_children (this);
	}

497
	public override void visit_switch_statement (SwitchStatement stmt) {
498 499 500
		if (stmt.checked) {
			return;
		}
501 502 503
		stmt.accept_children (this);
	}

504
	public override void visit_switch_section (SwitchSection section) {
505 506 507
		if (section.checked) {
			return;
		}
508 509 510
		section.accept_children (this);
	}

511
	public override void visit_switch_label (SwitchLabel label) {
512 513 514
		if (label.checked) {
			return;
		}
515 516 517
		label.accept_children (this);
	}

518
	public override void visit_loop (Loop stmt) {
519 520 521
		if (stmt.checked) {
			return;
		}
522 523 524
		stmt.accept_children (this);
	}

525
	public override void visit_while_statement (WhileStatement stmt) {
526 527 528
		if (stmt.checked) {
			return;
		}
529 530 531
		stmt.accept_children (this);
	}

532
	public override void visit_do_statement (DoStatement stmt) {
533 534 535
		if (stmt.checked) {
			return;
		}
536 537 538
		stmt.accept_children (this);
	}

539
	public override void visit_for_statement (ForStatement stmt) {
540 541 542
		if (stmt.checked) {
			return;
		}
543 544 545
		stmt.accept_children (this);
	}

546
	public override void visit_foreach_statement (ForeachStatement stmt) {
547 548 549
		if (stmt.checked) {
			return;
		}
550 551 552
		stmt.accept_children (this);
	}

553
	public override void visit_return_statement (ReturnStatement stmt) {
554 555 556
		if (stmt.checked) {
			return;
		}
557 558 559
		stmt.accept_children (this);
	}

Jürg Billeter's avatar
Jürg Billeter committed
560
	public override void visit_yield_statement (YieldStatement stmt) {
561 562 563
		if (stmt.checked) {
			return;
		}
Jürg Billeter's avatar
Jürg Billeter committed
564 565 566
		stmt.accept_children (this);
	}

567
	public override void visit_throw_statement (ThrowStatement stmt) {
568 569 570
		if (stmt.checked) {
			return;
		}
571 572 573
		stmt.accept_children (this);
	}

574
	public override void visit_try_statement (TryStatement stmt) {
575 576 577
		if (stmt.checked) {
			return;
		}
578 579 580
		stmt.accept_children (this);
	}

581 582 583 584
	public override void visit_delete_statement (DeleteStatement stmt) {
		stmt.accept_children (this);
	}

585
	public override void visit_catch_clause (CatchClause clause) {
586 587 588
		if (clause.checked) {
			return;
		}
589 590
		clause.accept_children (this);
	}
591

592
	public override void visit_array_creation_expression (ArrayCreationExpression e) {
593 594 595
		if (e.checked) {
			return;
		}
596 597
		e.accept_children (this);
	}
598

599
	public override void visit_template (Template tmpl) {
600 601 602
		if (tmpl.checked) {
			return;
		}
603 604 605
		tmpl.accept_children (this);
	}

606
	public override void visit_tuple (Tuple tuple) {
607 608 609
		if (tuple.checked) {
			return;
		}
610 611 612
		tuple.accept_children (this);
	}

613
	public override void visit_member_access (MemberAccess expr) {
614 615 616
		if (expr.checked) {
			return;
		}
617 618 619
		expr.accept_children (this);
	}

620
	public override void visit_method_call (MethodCall expr) {
621 622 623
		if (expr.checked) {
			return;
		}
624 625 626
		expr.accept_children (this);
	}

627
	public override void visit_element_access (ElementAccess expr) {
628 629 630
		if (expr.checked) {
			return;
		}
631 632 633
		expr.accept_children (this);
	}

634
	public override void visit_slice_expression (SliceExpression expr) {
635 636 637
		if (expr.checked) {
			return;
		}
638 639 640
		expr.accept_children (this);
	}

641
	public override void visit_postfix_expression (PostfixExpression expr) {
642 643 644
		if (expr.checked) {
			return;
		}
645 646 647
		expr.accept_children (this);
	}

648
	public override void visit_object_creation_expression (ObjectCreationExpression expr) {
649 650 651
		if (expr.checked) {
			return;
		}
652 653 654
		expr.accept_children (this);
	}

655
	public override void visit_sizeof_expression (SizeofExpression expr) {
656 657 658
		if (expr.checked) {
			return;
		}
659 660 661 662
		expr.accept_children (this);
	}

	public override void visit_typeof_expression (TypeofExpression expr) {
663 664 665
		if (expr.checked) {
			return;
		}
666 667 668
		expr.accept_children (this);
	}

669
	public override void visit_unary_expression (UnaryExpression expr) {
670 671 672
		if (expr.checked) {
			return;
		}
673 674 675
		expr.accept_children (this);
	}

676
	public override void visit_cast_expression (CastExpression expr) {
677 678 679
		if (expr.checked) {
			return;
		}
680 681 682
		expr.accept_children (this);
	}

683 684 685 686
	public override void visit_named_argument (NamedArgument expr) {
		expr.accept_children (this);
	}

687
	public override void visit_addressof_expression (AddressofExpression expr) {
688 689 690
		if (expr.checked) {
			return;
		}
691 692 693
		expr.accept_children (this);
	}

694
	public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
695 696 697
		if (expr.checked) {
			return;
		}
698 699 700
		expr.accept_children (this);
	}

701
	public override void visit_binary_expression (BinaryExpression expr) {
702 703 704
		if (expr.checked) {
			return;
		}
705 706 707
		expr.accept_children (this);
	}

708
	public override void visit_type_check (TypeCheck expr) {
709 710 711
		if (expr.checked) {
			return;
		}
712 713 714 715
		expr.accept_children (this);
	}

	public override void visit_conditional_expression (ConditionalExpression expr) {
716 717 718
		if (expr.checked) {
			return;
		}
719 720 721
		expr.accept_children (this);
	}

722
	public override void visit_lambda_expression (LambdaExpression l) {
723 724 725
		if (l.checked) {
			return;
		}
726 727 728
		l.accept_children (this);
	}

729
	public override void visit_assignment (Assignment a) {
730 731 732
		if (a.checked) {
			return;
		}
733 734
		a.accept_children (this);
	}
735
}