valasymbolresolver.vala 15.3 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
/**
 * Code visitor resolving symbol names.
 */
public class Vala.SymbolResolver : CodeVisitor {
31
	CodeContext context;
32
	Symbol root_symbol;
33
	Scope current_scope;
34

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

44
		context.root.accept (this);
45 46 47

		root_symbol = null;
		this.context = null;
48
	}
49

50 51 52
	public override void visit_namespace (Namespace ns) {
		var old_scope = current_scope;
		current_scope = ns.scope;
53

54
		ns.accept_children (this);
55

56
		current_scope = old_scope;
57
	}
58

59
	public override void visit_class (Class cl) {
60
		current_scope = cl.scope;
61

62 63
		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) {
Jürg Billeter's avatar
Jürg Billeter committed
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;
71
				}
72
				cl.base_class = (Class) type.data_type;
Jürg Billeter's avatar
Jürg Billeter committed
73 74 75 76 77
				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;
				}
78
			}
79
		}
80

81
		current_scope = current_scope.parent_scope;
82
	}
83

84
	public override void visit_struct (Struct st) {
85
		current_scope = st.scope;
86

87 88
		st.accept_children (this);

89
		if (st.base_type != null) {
90
			var base_type = st.base_struct;
91 92 93 94 95 96 97 98 99
			if (base_type != null) {
				if (base_type.is_subtype_of (st)) {
					st.error = true;
					Report.error (base_type.source_reference, "Base struct cycle (`%s' and `%s')".printf (st.get_full_name (), base_type.get_full_name ()));
					return;
				}
			}
		}

100
		current_scope = current_scope.parent_scope;
101 102
	}

103
	public override void visit_interface (Interface iface) {
104
		current_scope = iface.scope;
105

106 107
		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 111 112 113 114 115
				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;
			}
		}

116
		current_scope = current_scope.parent_scope;
117 118
	}

119
	public override void visit_enum (Enum en) {
120
		current_scope = en.scope;
121 122 123

		en.accept_children (this);

124
		current_scope = current_scope.parent_scope;
125 126
	}

127 128 129 130 131 132 133 134
	public override void visit_error_domain (ErrorDomain ed) {
		current_scope = ed.scope;

		ed.accept_children (this);

		current_scope = current_scope.parent_scope;
	}

135
	public override void visit_delegate (Delegate cb) {
136
		current_scope = cb.scope;
137

138 139
		cb.accept_children (this);

140
		current_scope = current_scope.parent_scope;
141 142
	}

143
	public override void visit_constant (Constant c) {
144
		var old_scope = current_scope;
145 146 147 148
		if (!(c.parent_symbol is Block)) {
			// non-local constant
			current_scope = c.scope;
		}
149

150
		c.accept_children (this);
151 152

		current_scope = old_scope;
153 154
	}

155
	public override void visit_field (Field f) {
156 157
		current_scope = f.scope;

158
		f.accept_children (this);
159 160

		current_scope = current_scope.parent_scope;
161 162
	}

163
	public override void visit_method (Method m) {
164 165
		current_scope = m.scope;

166
		m.accept_children (this);
167 168

		current_scope = current_scope.parent_scope;
169 170
	}

171
	public override void visit_creation_method (CreationMethod m) {
172 173 174
		m.accept_children (this);
	}

175
	public override void visit_formal_parameter (Parameter p) {
176
		p.accept_children (this);
177 178
	}

179
	public override void visit_property (Property prop) {
180 181 182
		prop.accept_children (this);
	}

183
	public override void visit_property_accessor (PropertyAccessor acc) {
184 185 186
		acc.accept_children (this);
	}

187
	public override void visit_signal (Signal sig) {
188 189 190
		sig.accept_children (this);
	}

191
	public override void visit_constructor (Constructor c) {
192 193 194
		c.accept_children (this);
	}

195
	public override void visit_destructor (Destructor d) {
196 197 198
		d.accept_children (this);
	}

199
	public override void visit_block (Block b) {
200 201 202
		b.accept_children (this);
	}

203 204 205 206
	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);
207
			if (!(ns.namespace_symbol is Namespace)) {
208 209 210 211
				ns.error = true;
				Report.error (ns.source_reference, "The namespace name `%s' could not be found".printf (unresolved_symbol.to_string ()));
				return;
			}
212
		}
213
	}
214

215
	private Symbol? resolve_symbol (UnresolvedSymbol unresolved_symbol) {
216 217 218 219
		if (unresolved_symbol.qualified) {
			// qualified access to global symbol
			return root_symbol.scope.lookup (unresolved_symbol.name);
		} 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);
224 225 226 227 228 229

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

230
				scope = scope.parent_scope;
231
			}
232 233
			if (sym == null && unresolved_symbol.source_reference != null) {
				foreach (UsingDirective ns in unresolved_symbol.source_reference.using_directives) {
234
					if (ns.error || ns.namespace_symbol is UnresolvedSymbol) {
235 236 237
						continue;
					}

238
					var local_sym = ns.namespace_symbol.scope.lookup (unresolved_symbol.name);
239 240 241 242 243 244

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

245
					if (local_sym != null) {
246
						if (sym != null && sym != local_sym) {
247 248 249
							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;
250
						}
251
						sym = local_sym;
252 253
					}
				}
254
			}
255
			return sym;
256
		} else {
257 258 259 260 261
			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;
262
			}
263
			parent_symbol.used = true;
264 265 266 267 268

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

269
	DataType get_type_for_struct (Struct st, Struct base_struct) {
270 271
		if (st.base_type != null) {
			// make sure that base type is resolved
272

273 274 275 276 277
			if (current_scope == st.scope) {
				// recursive declaration in generic base type
				return new StructValueType (st);
			}

278 279 280
			var old_scope = current_scope;
			current_scope = st.scope;

281
			st.base_type.accept (this);
282 283

			current_scope = old_scope;
284 285
		}

286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
		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);
		}
	}

302
	private DataType resolve_type (UnresolvedType unresolved_type) {
303
		DataType type = null;
304 305 306 307 308 309 310 311 312 313

		// 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) {
314
				Report.error (unresolved_type.source_reference, "The type name `%s' could not be found".printf (unresolved_type.unresolved_symbol.to_string ()));
315
			}
316 317 318 319
			return new InvalidType ();
		}

		if (sym is TypeParameter) {
320
			type = new GenericType ((TypeParameter) sym);
321
		} else if (sym is TypeSymbol) {
322 323
			if (sym is Delegate) {
				type = new DelegateType ((Delegate) sym);
324 325 326
			} else if (sym is Class) {
				var cl = (Class) sym;
				if (cl.is_error_base) {
327
					type = new ErrorType (null, null, unresolved_type.source_reference);
328
				} else {
329
					type = new ObjectType (cl);
330 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 339 340
				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);
341
			} else {
342 343
				Report.error (unresolved_type.source_reference, "internal error: `%s' is not a supported type".printf (sym.get_full_name ()));
				return new InvalidType ();
344
			}
345
		} else {
346
			Report.error (unresolved_type.source_reference, "`%s' is not a type".printf (sym.get_full_name ()));
347
			return new InvalidType ();
348
		}
349

350
		type.source_reference = unresolved_type.source_reference;
351
		type.value_owned = unresolved_type.value_owned;
352
		sym.used = true;
353 354 355 356 357 358 359 360 361

		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;
		}

362
		type.is_dynamic = unresolved_type.is_dynamic;
363 364 365 366
		foreach (DataType type_arg in unresolved_type.get_type_arguments ()) {
			type.add_type_argument (type_arg);
		}

367 368 369
		return type;
	}

370
	public override void visit_data_type (DataType data_type) {
371 372
		data_type.accept_children (this);

373 374 375 376 377 378
		if (!(data_type is UnresolvedType)) {
			return;
		}

		var unresolved_type = (UnresolvedType) data_type;

379
		unresolved_type.parent_node.replace_type (unresolved_type, resolve_type (unresolved_type));
380
	}
381

382 383 384 385
	public override void visit_declaration_statement (DeclarationStatement stmt) {
		stmt.accept_children (this);
	}

386 387
	public override void visit_local_variable (LocalVariable local) {
		local.accept_children (this);
388 389 390 391 392 393 394 395 396 397
		if (!context.experimental_non_null) {
			// local reference variables are considered nullable
			// except when using experimental non-null enhancements
			if (local.variable_type is ReferenceType) {
				var array_type = local.variable_type as ArrayType;
				if (array_type != null && array_type.fixed_length) {
					// local fixed length arrays are not nullable
				} else {
					local.variable_type.nullable = true;
				}
398
			}
399
		}
400 401
	}

402
	public override void visit_initializer_list (InitializerList list) {
403 404 405
		list.accept_children (this);
	}

406 407 408 409
	public override void visit_expression_statement (ExpressionStatement stmt) {
		stmt.accept_children (this);
	}

410
	public override void visit_if_statement (IfStatement stmt) {
411 412 413
		stmt.accept_children (this);
	}

414 415 416 417
	public override void visit_switch_statement (SwitchStatement stmt) {
		stmt.accept_children (this);
	}

418
	public override void visit_switch_section (SwitchSection section) {
419 420 421
		section.accept_children (this);
	}

422 423 424 425
	public override void visit_switch_label (SwitchLabel label) {
		label.accept_children (this);
	}

426 427 428 429
	public override void visit_loop (Loop stmt) {
		stmt.accept_children (this);
	}

430
	public override void visit_while_statement (WhileStatement stmt) {
431 432 433
		stmt.accept_children (this);
	}

434
	public override void visit_do_statement (DoStatement stmt) {
435 436 437
		stmt.accept_children (this);
	}

438
	public override void visit_for_statement (ForStatement stmt) {
439 440 441
		stmt.accept_children (this);
	}

442
	public override void visit_foreach_statement (ForeachStatement stmt) {
443 444 445
		stmt.accept_children (this);
	}

446
	public override void visit_return_statement (ReturnStatement stmt) {
447 448 449
		stmt.accept_children (this);
	}

Jürg Billeter's avatar
Jürg Billeter committed
450 451 452 453
	public override void visit_yield_statement (YieldStatement stmt) {
		stmt.accept_children (this);
	}

454
	public override void visit_throw_statement (ThrowStatement stmt) {
455 456 457
		stmt.accept_children (this);
	}

458
	public override void visit_try_statement (TryStatement stmt) {
459 460 461
		stmt.accept_children (this);
	}

462 463 464 465
	public override void visit_delete_statement (DeleteStatement stmt) {
		stmt.accept_children (this);
	}

466
	public override void visit_catch_clause (CatchClause clause) {
467 468
		clause.accept_children (this);
	}
469

470
	public override void visit_array_creation_expression (ArrayCreationExpression e) {
471 472
		e.accept_children (this);
	}
473

474 475 476 477
	public override void visit_template (Template tmpl) {
		tmpl.accept_children (this);
	}

478 479 480 481
	public override void visit_tuple (Tuple tuple) {
		tuple.accept_children (this);
	}

482 483 484 485
	public override void visit_member_access (MemberAccess expr) {
		expr.accept_children (this);
	}

486
	public override void visit_method_call (MethodCall expr) {
487 488 489
		expr.accept_children (this);
	}

490 491 492 493
	public override void visit_element_access (ElementAccess expr) {
		expr.accept_children (this);
	}

494 495 496 497
	public override void visit_slice_expression (SliceExpression expr) {
		expr.accept_children (this);
	}

498 499 500 501
	public override void visit_postfix_expression (PostfixExpression expr) {
		expr.accept_children (this);
	}

502
	public override void visit_object_creation_expression (ObjectCreationExpression expr) {
503 504 505
		expr.accept_children (this);
	}

506 507 508 509 510 511 512 513
	public override void visit_sizeof_expression (SizeofExpression expr) {
		expr.accept_children (this);
	}

	public override void visit_typeof_expression (TypeofExpression expr) {
		expr.accept_children (this);
	}

514 515 516 517
	public override void visit_unary_expression (UnaryExpression expr) {
		expr.accept_children (this);
	}

518 519 520 521
	public override void visit_cast_expression (CastExpression expr) {
		expr.accept_children (this);
	}

522 523 524 525
	public override void visit_named_argument (NamedArgument expr) {
		expr.accept_children (this);
	}

526 527 528 529
	public override void visit_addressof_expression (AddressofExpression expr) {
		expr.accept_children (this);
	}

530 531 532 533
	public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
		expr.accept_children (this);
	}

534 535 536 537
	public override void visit_binary_expression (BinaryExpression expr) {
		expr.accept_children (this);
	}

538 539 540 541 542 543 544 545
	public override void visit_type_check (TypeCheck expr) {
		expr.accept_children (this);
	}

	public override void visit_conditional_expression (ConditionalExpression expr) {
		expr.accept_children (this);
	}

546
	public override void visit_lambda_expression (LambdaExpression l) {
547 548 549
		l.accept_children (this);
	}

550
	public override void visit_assignment (Assignment a) {
551 552
		a.accept_children (this);
	}
553
}