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 unowned Attribute?
get_attribute (string name
) {
146 // FIXME: use hash table
147 foreach (unowned Attribute a
in attributes
) {
148 if (a
.name
== name
) {
156 unowned Attribute
get_or_create_attribute (string name
) {
157 unowned Attribute? a
= get_attribute (name
);
159 var new_a
= new
Attribute (name
, source_reference
);
160 attributes
.append (new_a
);
167 * Returns true if the specified attribute argument is set.
169 * @param attribute attribute name
170 * @param argument argument name
171 * @return true if the attribute has the given argument
173 public bool has_attribute_argument (string attribute
, string argument
) {
174 unowned Attribute? a
= get_attribute (attribute
);
178 return a
.has_argument (argument
);
182 * Sets the specified named attribute to this code node.
184 * @param name attribute name
185 * @param value true to add the attribute, false to remove it
187 public void set_attribute (string name
, bool value
, SourceReference? source_reference
= null) {
188 unowned Attribute? a
= get_attribute (name
);
189 if (value
&& a
== null) {
190 attributes
.append (new
Attribute (name
, source_reference
));
191 } else if (!value
&& a
!= null) {
192 attributes
.remove (a
);
197 * Remove the specified named attribute argument
199 * @param attribute attribute name
200 * @param argument argument name
202 public void remove_attribute_argument (string attribute
, string argument
) {
203 unowned Attribute? a
= get_attribute (attribute
);
205 a
.args
.remove (argument
);
206 if (a
.args
.size
== 0) {
207 attributes
.remove (a
);
213 * Returns the string value of the specified attribute argument.
215 * @param attribute attribute name
216 * @param argument argument name
217 * @return string value
219 public string?
get_attribute_string (string attribute
, string argument
, string? default_value
= null) {
220 unowned Attribute? a
= get_attribute (attribute
);
222 return default_value
;
224 return a
.get_string (argument
, default_value
);
228 * Returns the integer value of the specified attribute argument.
230 * @param attribute attribute name
231 * @param argument argument name
232 * @return integer value
234 public int get_attribute_integer (string attribute
, string argument
, int default_value
= 0) {
235 unowned Attribute? a
= get_attribute (attribute
);
237 return default_value
;
239 return a
.get_integer (argument
, default_value
);
243 * Returns the double value of the specified attribute argument.
245 * @param attribute attribute name
246 * @param argument argument name
247 * @return double value
249 public double get_attribute_double (string attribute
, string argument
, double default_value
= 0) {
250 if (attributes
== null) {
251 return default_value
;
253 unowned Attribute? a
= get_attribute (attribute
);
255 return default_value
;
257 return a
.get_double (argument
, default_value
);
261 * Returns the bool value of the specified attribute argument.
263 * @param attribute attribute name
264 * @param argument argument name
267 public bool get_attribute_bool (string attribute
, string argument
, bool default_value
= false) {
268 if (attributes
== null) {
269 return default_value
;
271 unowned Attribute? a
= get_attribute (attribute
);
273 return default_value
;
275 return a
.get_bool (argument
, default_value
);
279 * Sets the string value of the specified attribute argument.
281 * @param attribute attribute name
282 * @param argument argument name
283 * @param value string value
285 public void set_attribute_string (string attribute
, string argument
, string? value
, SourceReference? source_reference
= null) {
287 remove_attribute_argument (attribute
, argument
);
291 unowned Attribute a
= get_or_create_attribute (attribute
);
292 a
.add_argument (argument
, "\"%s\"".printf (value
));
296 * Sets the integer value of the specified attribute argument.
298 * @param attribute attribute name
299 * @param argument argument name
300 * @param value integer value
302 public void set_attribute_integer (string attribute
, string argument
, int value
, SourceReference? source_reference
= null) {
303 unowned Attribute a
= get_or_create_attribute (attribute
);
304 a
.add_argument (argument
, value
.to_string ());
308 * Sets the integer value of the specified attribute argument.
310 * @param attribute attribute name
311 * @param argument argument name
312 * @param value double value
314 public void set_attribute_double (string attribute
, string argument
, double value
, SourceReference? source_reference
= null) {
315 unowned Attribute a
= get_or_create_attribute (attribute
);
316 a
.add_argument (argument
, value
.format (new
char[double.DTOSTR_BUF_SIZE
]));
320 * Sets the boolean value of the specified attribute argument.
322 * @param attribute attribute name
323 * @param argument argument name
324 * @param value bool value
326 public void set_attribute_bool (string attribute
, string argument
, bool value
, SourceReference? source_reference
= null) {
327 unowned Attribute a
= get_or_create_attribute (attribute
);
328 a
.add_argument (argument
, value
.to_string ());
332 * Returns the attribute cache at the specified index.
334 * @param index attribute cache index
335 * @return attribute cache
337 public unowned AttributeCache?
get_attribute_cache (int index
) {
338 if (index
>= attributes_cache
.length
) {
341 return attributes_cache
[index
];
345 * Sets the specified attribute cache to this code node.
347 * @param index attribute cache index
348 * @param cache attribute cache
350 public void set_attribute_cache (int index
, AttributeCache cache
) {
351 if (index
>= attributes_cache
.length
) {
352 attributes_cache
.resize (index
* 2 + 1);
354 attributes_cache
[index
] = cache
;
358 * Returns a string that represents this code node.
360 * @return a string representation
362 public virtual string to_string () {
363 var str
= new
StringBuilder ();
367 if (source_reference
!= null) {
368 str
.append ("@").append (source_reference
.to_string ());
371 return str
.append (" */").str
;
374 public virtual void get_defined_variables (Collection
<Variable
> collection
) {
377 public virtual void get_used_variables (Collection
<Variable
> collection
) {
380 public static string get_temp_name () {
381 return "." + (++last_temp_nr
).to_string ();
385 * Returns a new cache index for accessing the attributes cache of code nodes
387 * @return a new cache index
389 public static int get_attribute_cache_index () {
390 return next_attribute_cache_index
++;
394 public class Vala
.AttributeCache
{