Line data Source code
1 : /* valacodenode.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 :
23 : using GLib;
24 :
25 : /**
26 : * Represents a part of the parsed source code.
27 : *
28 : * Code nodes get created by the parser and are used throughout the whole
29 : * compilation process.
30 : */
31 851142469 : public abstract class Vala.CodeNode {
32 : /**
33 : * Parent of this code node.
34 : */
35 90878690 : public weak CodeNode? parent_node { get; protected set; }
36 :
37 : /**
38 : * References the location in the source file where this code node has
39 : * been written.
40 : */
41 525561403 : public SourceReference? source_reference { get; set; }
42 :
43 23212 : public bool unreachable { get; set; }
44 :
45 : /**
46 : * Contains all attributes that have been specified for this code node.
47 : */
48 136216134 : public GLib.List<Attribute> attributes;
49 :
50 : public string type_name {
51 0 : get { return Type.from_instance (this).name (); }
52 : }
53 :
54 122169721 : public bool checked { get; set; }
55 :
56 : /**
57 : * Specifies whether a fatal error has been detected in this code node.
58 : */
59 83000241 : public bool error { get; set; }
60 :
61 : /**
62 : * Specifies that this node or a child node may throw an exception.
63 : */
64 : public bool tree_can_fail {
65 996764 : get {
66 996764 : var error_types = new ArrayList<DataType> ();
67 996764 : get_error_types (error_types);
68 996764 : return error_types.size > 0;
69 : }
70 : }
71 :
72 128846218 : private AttributeCache[] attributes_cache;
73 :
74 : static int last_temp_nr = 0;
75 : static int next_attribute_cache_index = 0;
76 :
77 : /**
78 : * Visits this code node with the specified CodeVisitor.
79 : *
80 : * @param visitor the visitor to be called while traversing
81 : */
82 96917796 : public virtual void accept (CodeVisitor visitor) {
83 : }
84 :
85 : /**
86 : * Visits all children of this code node with the specified CodeVisitor.
87 : *
88 : * @param visitor the visitor to be called while traversing
89 : */
90 77678232 : public virtual void accept_children (CodeVisitor visitor) {
91 : }
92 :
93 119568042 : public virtual bool check (CodeContext context) {
94 : return true;
95 : }
96 :
97 332101 : public virtual void emit (CodeGenerator codegen) {
98 : }
99 :
100 16367863 : public virtual void replace_type (DataType old_type, DataType new_type) {
101 : }
102 :
103 49207 : public virtual void replace_expression (Expression old_node, Expression new_node) {
104 : }
105 :
106 : /**
107 : * Returns the specified attribute.
108 : *
109 : * @param name attribute name
110 : * @return attribute
111 : */
112 97207929 : public unowned Attribute? get_attribute (string name) {
113 : // FIXME: use hash table
114 197483743 : foreach (unowned Attribute a in attributes) {
115 111359102 : if (a.name == name) {
116 11083288 : return a;
117 : }
118 : }
119 :
120 97207929 : return null;
121 : }
122 :
123 : /**
124 : * Add attribute and append key/value pairs to an existing one.
125 : *
126 : * @param a an attribute to add
127 : */
128 2 : public void add_attribute (Attribute a) {
129 2 : unowned Attribute? old_a = get_attribute (a.name);
130 2 : if (old_a == null) {
131 14058 : attributes.append (a);
132 : } else {
133 0 : var it = a.args.map_iterator ();
134 0 : while (it.next ()) {
135 0 : old_a.args.set (it.get_key (), it.get_value ());
136 : }
137 : }
138 : }
139 :
140 25254 : unowned Attribute get_or_create_attribute (string name) {
141 25254 : unowned Attribute? a = get_attribute (name);
142 39310 : if (a == null) {
143 14056 : var new_a = new Attribute (name, source_reference);
144 28112 : attributes.append (new_a);
145 14056 : a = new_a;
146 : }
147 : return (!) a;
148 : }
149 :
150 : /**
151 : * Returns true if the specified attribute is set.
152 : *
153 : * @param attribute attribute name
154 : * @return true if the node has the given attribute
155 : */
156 69618649 : public bool has_attribute (string attribute) {
157 69618649 : return get_attribute (attribute) != null;
158 : }
159 :
160 : /**
161 : * Returns true if the specified attribute argument is set.
162 : *
163 : * @param attribute attribute name
164 : * @param argument argument name
165 : * @return true if the attribute has the given argument
166 : */
167 20139087 : public bool has_attribute_argument (string attribute, string argument) {
168 20139087 : unowned Attribute? a = get_attribute (attribute);
169 20139087 : if (a == null) {
170 19070590 : return false;
171 : }
172 1068497 : return a.has_argument (argument);
173 : }
174 :
175 : /**
176 : * Sets the specified named attribute to this code node.
177 : *
178 : * @param name attribute name
179 : * @param value true to add the attribute, false to remove it
180 : */
181 2573 : public void set_attribute (string name, bool value, SourceReference? source_reference = null) {
182 2573 : unowned Attribute? a = get_attribute (name);
183 2573 : if (value && a == null) {
184 1419 : attributes.append (new Attribute (name, source_reference));
185 1154 : } else if (!value && a != null) {
186 0 : attributes.remove (a);
187 : }
188 : }
189 :
190 : /**
191 : * Remove the specified named attribute argument
192 : *
193 : * @param attribute attribute name
194 : * @param argument argument name
195 : */
196 105 : public void remove_attribute_argument (string attribute, string argument) {
197 105 : unowned Attribute? a = get_attribute (attribute);
198 105 : if (a != null) {
199 100 : a.args.remove (argument);
200 100 : if (a.args.size == 0) {
201 96 : attributes.remove (a);
202 : }
203 : }
204 : }
205 :
206 : /**
207 : * Returns the string value of the specified attribute argument.
208 : *
209 : * @param attribute attribute name
210 : * @param argument argument name
211 : * @return string value
212 : */
213 2853412 : public string? get_attribute_string (string attribute, string argument, string? default_value = null) {
214 2853412 : unowned Attribute? a = get_attribute (attribute);
215 2853412 : if (a == null) {
216 4121086 : return default_value;
217 : }
218 792869 : return a.get_string (argument, default_value);
219 : }
220 :
221 : /**
222 : * Returns the integer value of the specified attribute argument.
223 : *
224 : * @param attribute attribute name
225 : * @param argument argument name
226 : * @return integer value
227 : */
228 438026 : public int get_attribute_integer (string attribute, string argument, int default_value = 0) {
229 438026 : unowned Attribute? a = get_attribute (attribute);
230 438026 : if (a == null) {
231 438026 : return default_value;
232 : }
233 49283 : return a.get_integer (argument, default_value);
234 : }
235 :
236 : /**
237 : * Returns the double value of the specified attribute argument.
238 : *
239 : * @param attribute attribute name
240 : * @param argument argument name
241 : * @return double value
242 : */
243 37027 : public double get_attribute_double (string attribute, string argument, double default_value = 0) {
244 37027 : if (attributes == null) {
245 34660 : return default_value;
246 : }
247 3160 : unowned Attribute? a = get_attribute (attribute);
248 3160 : if (a == null) {
249 34660 : return default_value;
250 : }
251 2367 : return a.get_double (argument, default_value);
252 : }
253 :
254 : /**
255 : * Returns the bool value of the specified attribute argument.
256 : *
257 : * @param attribute attribute name
258 : * @param argument argument name
259 : * @return bool value
260 : */
261 7905159 : public bool get_attribute_bool (string attribute, string argument, bool default_value = false) {
262 7905159 : if (attributes == null) {
263 6164752 : return default_value;
264 : }
265 3600987 : unowned Attribute? a = get_attribute (attribute);
266 3600987 : if (a == null) {
267 6164752 : return default_value;
268 : }
269 1740407 : return a.get_bool (argument, default_value);
270 : }
271 :
272 : /**
273 : * Sets the string value of the specified attribute argument.
274 : *
275 : * @param attribute attribute name
276 : * @param argument argument name
277 : * @param value string value
278 : */
279 9338 : public void set_attribute_string (string attribute, string argument, string? value, SourceReference? source_reference = null) {
280 9338 : if (value == null) {
281 0 : remove_attribute_argument (attribute, argument);
282 0 : return;
283 : }
284 :
285 9338 : unowned Attribute a = get_or_create_attribute (attribute);
286 9338 : a.add_argument (argument, "\"%s\"".printf (value));
287 : }
288 :
289 : /**
290 : * Sets the integer value of the specified attribute argument.
291 : *
292 : * @param attribute attribute name
293 : * @param argument argument name
294 : * @param value integer value
295 : */
296 0 : public void set_attribute_integer (string attribute, string argument, int value, SourceReference? source_reference = null) {
297 0 : unowned Attribute a = get_or_create_attribute (attribute);
298 0 : a.add_argument (argument, value.to_string ());
299 : }
300 :
301 : /**
302 : * Sets the integer value of the specified attribute argument.
303 : *
304 : * @param attribute attribute name
305 : * @param argument argument name
306 : * @param value double value
307 : */
308 354 : public void set_attribute_double (string attribute, string argument, double value, SourceReference? source_reference = null) {
309 354 : unowned Attribute a = get_or_create_attribute (attribute);
310 354 : a.add_argument (argument, value.format (new char[double.DTOSTR_BUF_SIZE]));
311 : }
312 :
313 : /**
314 : * Sets the boolean value of the specified attribute argument.
315 : *
316 : * @param attribute attribute name
317 : * @param argument argument name
318 : * @param value bool value
319 : */
320 15562 : public void set_attribute_bool (string attribute, string argument, bool value, SourceReference? source_reference = null) {
321 15562 : unowned Attribute a = get_or_create_attribute (attribute);
322 15562 : a.add_argument (argument, value.to_string ());
323 : }
324 :
325 : /**
326 : * Copy the string value of the specified attribute argument if available.
327 : *
328 : * @param source codenode to copy from
329 : * @param attribute attribute name
330 : * @param argument argument name
331 : * @return true if successful
332 : */
333 313053 : public bool copy_attribute_string (CodeNode source, string attribute, string argument) {
334 313053 : if (source.has_attribute_argument (attribute, argument)) {
335 10 : set_attribute_string (attribute, argument, source.get_attribute_string (attribute, argument));
336 10 : return true;
337 : }
338 313053 : return false;
339 : }
340 :
341 : /**
342 : * Copy the integer value of the specified attribute argument if available.
343 : *
344 : * @param source codenode to copy from
345 : * @param attribute attribute name
346 : * @param argument argument name
347 : * @return true if successful
348 : */
349 0 : public bool copy_attribute_integer (CodeNode source, string attribute, string argument) {
350 0 : if (source.has_attribute_argument (attribute, argument)) {
351 0 : set_attribute_integer (attribute, argument, source.get_attribute_integer (attribute, argument));
352 0 : return true;
353 : }
354 0 : return false;
355 : }
356 :
357 : /**
358 : * Copy the double value of the specified attribute argument if available.
359 : *
360 : * @param source codenode to copy from
361 : * @param attribute attribute name
362 : * @param argument argument name
363 : * @return true if successful
364 : */
365 344656 : public bool copy_attribute_double (CodeNode source, string attribute, string argument) {
366 344656 : if (source.has_attribute_argument (attribute, argument)) {
367 35 : set_attribute_double (attribute, argument, source.get_attribute_double (attribute, argument));
368 35 : return true;
369 : }
370 344656 : return false;
371 : }
372 :
373 : /**
374 : * Copy the boolean value of the specified attribute argument if available.
375 : *
376 : * @param source codenode to copy from
377 : * @param attribute attribute name
378 : * @param argument argument name
379 : * @return true if successful
380 : */
381 1283994 : public bool copy_attribute_bool (CodeNode source, string attribute, string argument) {
382 1283994 : if (source.has_attribute_argument (attribute, argument)) {
383 14244 : set_attribute_bool (attribute, argument, source.get_attribute_bool (attribute, argument));
384 14244 : return true;
385 : }
386 1283994 : return false;
387 : }
388 :
389 : /**
390 : * Returns the attribute cache at the specified index.
391 : *
392 : * @param index attribute cache index
393 : * @return attribute cache
394 : */
395 2009260 : public unowned AttributeCache? get_attribute_cache (int index) {
396 2009260 : if (index >= attributes_cache.length) {
397 253100 : return null;
398 : }
399 1756160 : return attributes_cache[index];
400 : }
401 :
402 : /**
403 : * Sets the specified attribute cache to this code node.
404 : *
405 : * @param index attribute cache index
406 : * @param cache attribute cache
407 : */
408 253100 : public void set_attribute_cache (int index, AttributeCache cache) {
409 253100 : if (index >= attributes_cache.length) {
410 253100 : attributes_cache.resize (index * 2 + 1);
411 : }
412 253100 : attributes_cache[index] = cache;
413 : }
414 :
415 : /**
416 : * Returns a string that represents this code node.
417 : *
418 : * @return a string representation
419 : */
420 9268 : public virtual string to_string () {
421 0 : var str = new StringBuilder ();
422 :
423 0 : str.append ("/* ");
424 0 : str.append (type_name);
425 :
426 0 : if (source_reference != null) {
427 0 : str.append ("@").append (source_reference.to_string ());
428 : }
429 :
430 0 : return str.append (" */").str;
431 : }
432 :
433 8116719 : public virtual void get_defined_variables (Collection<Variable> collection) {
434 : }
435 :
436 2645810 : public virtual void get_used_variables (Collection<Variable> collection) {
437 : }
438 :
439 8534196 : public virtual void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
440 : }
441 :
442 : public static string get_temp_name () {
443 52533 : return "." + (++last_temp_nr).to_string ();
444 : }
445 :
446 : /**
447 : * Returns a new cache index for accessing the attributes cache of code nodes
448 : *
449 : * @return a new cache index
450 : */
451 : public static int get_attribute_cache_index () {
452 2354 : return next_attribute_cache_index++;
453 : }
454 : }
455 :
456 1013287 : public class Vala.AttributeCache {
457 : }
|