1/* valatypecheck.vala
2 *
3 * Copyright (C) 2006-2010  Jürg Billeter
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Lesser General Public License for more details.
14
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
18 *
19 * Author:
20 * 	Jürg Billeter <j@bitron.ch>
21 */
22
23using GLib;
24
25/**
26 * Represents a type check (`is`) expression in the source code.
27 */
28public class Vala.TypeCheck : Expression {
29	/**
30	 * The expression to be checked.
31	 */
32	public Expression expression {
33		get { return _expression; }
34		set {
35			_expression = value;
36			_expression.parent_node = this;
37		}
38	}
39
40	/**
41	 * The type to be matched against.
42	 */
43	public DataType type_reference {
44		get { return _data_type; }
45		set {
46			_data_type = value;
47			_data_type.parent_node = this;
48		}
49	}
50
51	Expression _expression;
52	private DataType _data_type;
53
54	/**
55	 * Creates a new type check expression.
56	 *
57	 * @param expr   an expression
58	 * @param type   a data type
59	 * @param source reference to source code
60	 * @return       newly created type check expression
61	 */
62	public TypeCheck (Expression expr, DataType type, SourceReference? source = null) {
63		expression = expr;
64		type_reference = type;
65		source_reference = source;
66	}
67
68	public override void accept (CodeVisitor visitor) {
69		visitor.visit_type_check (this);
70
71		visitor.visit_expression (this);
72	}
73
74	public override void accept_children (CodeVisitor visitor) {
75		expression.accept (visitor);
76
77		type_reference.accept (visitor);
78	}
79
80	public override bool is_pure () {
81		return expression.is_pure ();
82	}
83
84	public override void replace_type (DataType old_type, DataType new_type) {
85		if (type_reference == old_type) {
86			type_reference = new_type;
87		}
88	}
89
90	public override void replace_expression (Expression old_node, Expression new_node) {
91		if (expression == old_node) {
92			expression = new_node;
93		}
94	}
95
96	public override bool check (CodeContext context) {
97		if (checked) {
98			return !error;
99		}
100
101		checked = true;
102
103		expression.check (context);
104
105		type_reference.check (context);
106
107		if (expression.value_type == null) {
108			Report.error (expression.source_reference, "invalid left operand");
109			error = true;
110			return false;
111		}
112
113		if (type_reference.type_symbol == null) {
114			/* if type resolving didn't succeed, skip this check */
115			error = true;
116			return false;
117		}
118
119		if (type_reference is ErrorType && !(expression.value_type is ErrorType)) {
120			Report.error (expression.source_reference, "`%s' must be an error".printf (expression.to_string ()));
121			error = true;
122			return false;
123		}
124
125		if (context.profile == Profile.GOBJECT && type_reference.has_type_arguments ()) {
126			Report.warning (_data_type.source_reference, "Type argument list has no effect");
127		}
128
129		value_type = context.analyzer.bool_type;
130
131		return !error;
132	}
133
134	public override void emit (CodeGenerator codegen) {
135		expression.emit (codegen);
136
137		codegen.visit_type_check (this);
138
139		codegen.visit_expression (this);
140	}
141
142	public override string to_string () {
143		return "(%s is %s)".printf (expression.to_string (), type_reference.to_string ());
144	}
145}
146