3 * Copyright (C) 2006-2010 Jürg Billeter
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.
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.
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
20 * Jürg Billeter <j@bitron.ch>
26 * Represents a part of the parsed source code.
28 * Code nodes get created by the parser and are used throughout the whole
29 * compilation process.
31 public abstract class Vala
.CodeNode
{
33 * Parent of this code node.
35 public weak CodeNode? parent_node
{ get; set; }
38 * References the location in the source file where this code node has
41 public SourceReference? source_reference
{ get; set; }
43 public bool unreachable
{ get; set; }
46 * Contains all attributes that have been specified for this code node.
48 public GLib
.List
<Attribute
> attributes
;
50 public string type_name
{
51 get { return Type
.from_instance (this
).name (); }
54 public bool checked
{ get; set; }
57 * Specifies whether a fatal error has been detected in this code node.
59 public bool error
{ get; set; }
62 * Specifies that this node or a child node may throw an exception.
64 public bool tree_can_fail
{
65 get { return _error_types
!= null && _error_types
.size
> 0; }
68 private List
<DataType
> _error_types
;
69 private static List
<DataType
> _empty_type_list
;
70 private AttributeCache
[] attributes_cache
;
72 static int last_temp_nr
= 0;
73 static int next_attribute_cache_index
= 0;
76 * Specifies the exceptions that can be thrown by this node or a child node
78 public List
<DataType
> get_error_types () {
79 if (_error_types
!= null) {
82 if (_empty_type_list
== null) {
83 _empty_type_list
= new ArrayList
<DataType
> ();
85 return _empty_type_list
;
89 * Adds an error type to the exceptions that can be thrown by this node
92 public void add_error_type (DataType error_type
) {
93 if (_error_types
== null) {
94 _error_types
= new ArrayList
<DataType
> ();
96 _error_types
.add (error_type
);
97 error_type
.parent_node
= this
;
101 * Adds a collection of error types to the exceptions that can be thrown by this node
104 public void add_error_types (List
<DataType
> error_types
) {
105 foreach (DataType error_type
in error_types
) {
106 add_error_type (error_type
);
111 * Visits this code node with the specified CodeVisitor.
113 * @param visitor the visitor to be called while traversing
115 public virtual void accept (CodeVisitor visitor
) {
119 * Visits all children of this code node with the specified CodeVisitor.
121 * @param visitor the visitor to be called while traversing
123 public virtual void accept_children (CodeVisitor visitor
) {
126 public virtual bool check (CodeContext context
) {
130 public virtual void emit (CodeGenerator codegen
) {
133 public virtual void replace_type (DataType old_type
, DataType new_type
) {
136 public virtual void replace_expression (Expression old_node
, Expression new_node
) {
140 * Returns the specified attribute.
142 * @param name attribute name
145 public Attribute?
get_attribute (string name
) {
146 // FIXME: use hash table
147 foreach (Attribute a
in attributes
) {
148 if (a
.name
== name
) {
157 * Returns true if the specified attribute argument is set.
159 * @param attribute attribute name
160 * @param argument argument name
161 * @return true if the attribute has the given argument
163 public bool has_attribute_argument (string attribute
, string argument
) {
164 var a
= get_attribute (attribute
);
168 return a
.has_argument (argument
);
172 * Sets the specified named attribute to this code node.
174 * @param name attribute name
175 * @param value true to add the attribute, false to remove it
177 public void set_attribute (string name
, bool value
, SourceReference? source_reference
= null) {
178 var a
= get_attribute (name
);
179 if (value
&& a
== null) {
180 attributes
.append (new
Attribute (name
, source_reference
));
181 } else if (!value
&& a
!= null) {
182 attributes
.remove (a
);
187 * Remove the specified named attribute argument
189 * @param attribute attribute name
190 * @param argument argument name
192 public void remove_attribute_argument (string attribute
, string argument
) {
193 var a
= get_attribute (attribute
);
195 a
.args
.remove (argument
);
196 if (a
.args
.size
== 0) {
197 attributes
.remove (a
);
203 * Returns the string value of the specified attribute argument.
205 * @param attribute attribute name
206 * @param argument argument name
207 * @return string value
209 public string?
get_attribute_string (string attribute
, string argument
, string? default_value
= null) {
210 var a
= get_attribute (attribute
);
212 return default_value
;
214 return a
.get_string (argument
, default_value
);
218 * Returns the integer value of the specified attribute argument.
220 * @param attribute attribute name
221 * @param argument argument name
222 * @return integer value
224 public int get_attribute_integer (string attribute
, string argument
, int default_value
= 0) {
225 var a
= get_attribute (attribute
);
227 return default_value
;
229 return a
.get_integer (argument
, default_value
);
233 * Returns the double value of the specified attribute argument.
235 * @param attribute attribute name
236 * @param argument argument name
237 * @return double value
239 public double get_attribute_double (string attribute
, string argument
, double default_value
= 0) {
240 if (attributes
== null) {
241 return default_value
;
243 var a
= get_attribute (attribute
);
245 return default_value
;
247 return a
.get_double (argument
, default_value
);
251 * Returns the bool value of the specified attribute argument.
253 * @param attribute attribute name
254 * @param argument argument name
257 public bool get_attribute_bool (string attribute
, string argument
, bool default_value
= false) {
258 if (attributes
== null) {
259 return default_value
;
261 var a
= get_attribute (attribute
);
263 return default_value
;
265 return a
.get_bool (argument
, default_value
);
269 * Sets the string value of the specified attribute argument.
271 * @param attribute attribute name
272 * @param argument argument name
273 * @param value string value
275 public void set_attribute_string (string attribute
, string argument
, string? value
, SourceReference? source_reference
= null) {
277 remove_attribute_argument (attribute
, argument
);
281 var a
= get_attribute (attribute
);
283 a
= new
Attribute (attribute
, source_reference
);
284 attributes
.append (a
);
286 a
.add_argument (argument
, "\"%s\"".printf (value
));
290 * Sets the integer value of the specified attribute argument.
292 * @param attribute attribute name
293 * @param argument argument name
294 * @param value integer value
296 public void set_attribute_integer (string attribute
, string argument
, int value
, SourceReference? source_reference
= null) {
297 var a
= get_attribute (attribute
);
299 a
= new
Attribute (attribute
, source_reference
);
300 attributes
.append (a
);
302 a
.add_argument (argument
, value
.to_string ());
306 * Sets the integer value of the specified attribute argument.
308 * @param attribute attribute name
309 * @param argument argument name
310 * @param value double value
312 public void set_attribute_double (string attribute
, string argument
, double value
, SourceReference? source_reference
= null) {
313 var a
= get_attribute (attribute
);
315 a
= new
Attribute (attribute
, source_reference
);
316 attributes
.append (a
);
318 a
.add_argument (argument
, value
.format (new
char[double.DTOSTR_BUF_SIZE
]));
322 * Sets the boolean value of the specified attribute argument.
324 * @param attribute attribute name
325 * @param argument argument name
326 * @param value bool value
328 public void set_attribute_bool (string attribute
, string argument
, bool value
, SourceReference? source_reference
= null) {
329 var a
= get_attribute (attribute
);
331 a
= new
Attribute (attribute
, source_reference
);
332 attributes
.append (a
);
334 a
.add_argument (argument
, value
.to_string ());
338 * Returns the attribute cache at the specified index.
340 * @param index attribute cache index
341 * @return attribute cache
343 public AttributeCache?
get_attribute_cache (int index
) {
344 if (index
>= attributes_cache
.length
) {
347 return attributes_cache
[index
];
351 * Sets the specified attribute cache to this code node.
353 * @param index attribute cache index
354 * @param cache attribute cache
356 public void set_attribute_cache (int index
, AttributeCache cache
) {
357 if (index
>= attributes_cache
.length
) {
358 attributes_cache
.resize (index
* 2 + 1);
360 attributes_cache
[index
] = cache
;
364 * Returns a string that represents this code node.
366 * @return a string representation
368 public virtual string to_string () {
369 var str
= new
StringBuilder ();
373 if (source_reference
!= null) {
374 str
.append ("@").append (source_reference
.to_string ());
377 return str
.append (" */").str
;
380 public virtual void get_defined_variables (Collection
<Variable
> collection
) {
383 public virtual void get_used_variables (Collection
<Variable
> collection
) {
386 public static string get_temp_name () {
387 return "." + (++last_temp_nr
).to_string ();
391 * Returns a new cache index for accessing the attributes cache of code nodes
393 * @return a new cache index
395 public static int get_attribute_cache_index () {
396 return next_attribute_cache_index
++;
400 public class Vala
.AttributeCache
{