1 /* valadovavaluemodule.vala
3 * Copyright (C) 2009-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>
23 public class Vala
.DovaValueModule
: DovaObjectModule
{
24 public override void visit_creation_method (CreationMethod m
) {
25 if (current_type_symbol is Class
&&
26 (current_class
.base_class
== null ||
27 current_class
.base_class
.get_full_name () != "Dova.Value")) {
28 base.visit_creation_method (m
);
35 public override void generate_struct_declaration (Struct st
, CCodeFile decl_space
) {
36 base.generate_struct_declaration (st
, decl_space
);
38 if (add_symbol_declaration (decl_space
, st
, st
.get_copy_function ())) {
42 generate_class_declaration (type_class
, decl_space
);
44 var type_fun
= new
CCodeFunction ("%s_type_get".printf (st
.get_lower_case_cname ()), "DovaType *");
45 if (st
.is_internal_symbol ()) {
46 type_fun
.modifiers
= CCodeModifiers
.STATIC
;
48 decl_space
.add_type_member_declaration (type_fun
);
50 var type_init_fun
= new
CCodeFunction ("%s_type_init".printf (st
.get_lower_case_cname ()));
51 type_init_fun
.add_parameter (new
CCodeFormalParameter ("type", "DovaType *"));
52 if (st
.is_internal_symbol ()) {
53 type_init_fun
.modifiers
= CCodeModifiers
.STATIC
;
55 decl_space
.add_type_member_declaration (type_init_fun
);
57 var function
= new
CCodeFunction (st
.get_copy_function (), "void");
58 if (st
.is_internal_symbol ()) {
59 function
.modifiers
= CCodeModifiers
.STATIC
;
62 function
.add_parameter (new
CCodeFormalParameter ("dest", st
.get_cname () + "*"));
63 function
.add_parameter (new
CCodeFormalParameter ("dest_index", "int32_t"));
64 function
.add_parameter (new
CCodeFormalParameter ("src", st
.get_cname () + "*"));
65 function
.add_parameter (new
CCodeFormalParameter ("src_index", "int32_t"));
67 decl_space
.add_type_member_declaration (function
);
70 public override void visit_struct (Struct st
) {
71 base.visit_struct (st
);
73 var cdecl
= new
CCodeDeclaration ("int");
74 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_%s_object_offset".printf (st
.get_lower_case_cname ()), new
CCodeConstant ("0")));
75 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
76 cfile
.add_type_member_declaration (cdecl
);
78 string macro
= "((%s *) (((char *) o) + _%s_object_offset))".printf (st
.get_cname (), st
.get_lower_case_cname ());
79 cfile
.add_type_member_declaration (new
CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (st
.get_upper_case_cname (null)), macro
));
82 cdecl
= new
CCodeDeclaration ("DovaType *");
83 cdecl
.add_declarator (new
CCodeVariableDeclarator ("%s_type".printf (st
.get_lower_case_cname ()), new
CCodeConstant ("NULL")));
84 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
85 cfile
.add_type_member_declaration (cdecl
);
87 var type_fun
= new
CCodeFunction ("%s_type_get".printf (st
.get_lower_case_cname ()), "DovaType *");
88 type_fun
.block
= new
CCodeBlock ();
90 var type_init_block
= new
CCodeBlock ();
92 generate_method_declaration ((Method
) object_class
.scope
.lookup ("alloc"), cfile
);
93 generate_property_accessor_declaration (((Property
) type_class
.scope
.lookup ("base_type")).get_accessor
, cfile
);
94 generate_property_accessor_declaration (((Property
) type_class
.scope
.lookup ("base_type")).set_accessor
, cfile
);
95 generate_property_accessor_declaration (((Property
) type_class
.scope
.lookup ("object_size")).get_accessor
, cfile
);
96 generate_property_accessor_declaration (((Property
) type_class
.scope
.lookup ("object_size")).set_accessor
, cfile
);
97 generate_property_accessor_declaration (((Property
) type_class
.scope
.lookup ("type_size")).get_accessor
, cfile
);
98 generate_property_accessor_declaration (((Property
) type_class
.scope
.lookup ("type_size")).set_accessor
, cfile
);
99 generate_property_accessor_declaration (((Property
) type_class
.scope
.lookup ("value_size")).set_accessor
, cfile
);
101 generate_class_declaration ((Class
) context
.root
.scope
.lookup ("Dova").scope
.lookup ("Value"), cfile
);
103 var base_type
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_value_type_get"));
105 var base_type_size
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_get_type_size"));
106 base_type_size
.add_argument (base_type
);
108 var calloc_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("calloc"));
109 calloc_call
.add_argument (new
CCodeConstant ("1"));
110 calloc_call
.add_argument (base_type_size
);
112 type_init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ())), calloc_call
)));
114 generate_class_declaration ((Class
) object_class
, cfile
);
116 type_init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeCastExpression (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ())), "DovaObject *"), "type"), new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_type_get")))));
118 var set_base_type
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_base_type"));
119 set_base_type
.add_argument (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ())));
120 set_base_type
.add_argument (base_type
);
121 type_init_block
.add_statement (new
CCodeExpressionStatement (set_base_type
));
123 var base_size
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_get_object_size"));
124 base_size
.add_argument (base_type
);
126 type_init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_%s_object_offset".printf (st
.get_lower_case_cname ())), base_size
)));
128 var sizeof_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("sizeof"));
129 sizeof_call
.add_argument (new
CCodeIdentifier (st
.get_cname ()));
130 var set_size
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_object_size"));
131 set_size
.add_argument (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ())));
132 set_size
.add_argument (new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, base_size
, sizeof_call
));
133 type_init_block
.add_statement (new
CCodeExpressionStatement (set_size
));
135 set_size
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_value_size"));
136 set_size
.add_argument (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ())));
137 set_size
.add_argument (sizeof_call
);
138 type_init_block
.add_statement (new
CCodeExpressionStatement (set_size
));
140 set_size
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_type_size"));
141 set_size
.add_argument (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ())));
142 set_size
.add_argument (base_type_size
);
143 type_init_block
.add_statement (new
CCodeExpressionStatement (set_size
));
145 var type_init_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_type_init".printf (st
.get_lower_case_cname ())));
146 type_init_call
.add_argument (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ())));
147 type_init_block
.add_statement (new
CCodeExpressionStatement (type_init_call
));
149 // workaround: set value_size again as it is currently overwritten by dova_object_type_init
150 set_size
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_value_size"));
151 set_size
.add_argument (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ())));
152 set_size
.add_argument (sizeof_call
);
153 type_init_block
.add_statement (new
CCodeExpressionStatement (set_size
));
155 type_fun
.block
.add_statement (new
CCodeIfStatement (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ()))), type_init_block
));
157 type_fun
.block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ()))));
159 cfile
.add_function (type_fun
);
161 var type_init_fun
= new
CCodeFunction ("%s_type_init".printf (st
.get_lower_case_cname ()));
162 type_init_fun
.add_parameter (new
CCodeFormalParameter ("type", "DovaType *"));
163 type_init_fun
.block
= new
CCodeBlock ();
165 type_init_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_value_type_init"));
166 type_init_call
.add_argument (new
CCodeIdentifier ("type"));
167 type_init_fun
.block
.add_statement (new
CCodeExpressionStatement (type_init_call
));
169 declare_set_value_copy_function (cfile
);
171 var value_copy_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_value_copy"));
172 value_copy_call
.add_argument (new
CCodeIdentifier ("type"));
173 value_copy_call
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("%s_copy".printf (st
.get_lower_case_cname ())), "void (*)(void *, int32_t, void *, int32_t)"));
174 type_init_fun
.block
.add_statement (new
CCodeExpressionStatement (value_copy_call
));
176 if (st
.scope
.lookup ("equals") is Method
) {
177 var value_equals_fun
= new
CCodeFunction ("%s_value_equals".printf (st
.get_lower_case_cname ()), "bool");
178 value_equals_fun
.modifiers
= CCodeModifiers
.STATIC
;
179 value_equals_fun
.add_parameter (new
CCodeFormalParameter ("value", st
.get_cname () + "*"));
180 value_equals_fun
.add_parameter (new
CCodeFormalParameter ("value_index", "int32_t"));
181 value_equals_fun
.add_parameter (new
CCodeFormalParameter ("other", st
.get_cname () + "*"));
182 value_equals_fun
.add_parameter (new
CCodeFormalParameter ("other_index", "int32_t"));
183 value_equals_fun
.block
= new
CCodeBlock ();
184 var val
= new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, new
CCodeIdentifier ("value"), new
CCodeIdentifier ("value_index"));
185 var other
= new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, new
CCodeIdentifier ("other"), new
CCodeIdentifier ("other_index"));
186 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_equals".printf (st
.get_lower_case_cname ())));
187 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, val
));
188 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, other
));
189 value_equals_fun
.block
.add_statement (new
CCodeReturnStatement (ccall
));
190 cfile
.add_function (value_equals_fun
);
192 declare_set_value_equals_function (cfile
);
194 var value_equals_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_value_equals"));
195 value_equals_call
.add_argument (new
CCodeIdentifier ("type"));
196 value_equals_call
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("%s_value_equals".printf (st
.get_lower_case_cname ())), "bool (*)(void *, int32_t, void *, int32_t)"));
197 type_init_fun
.block
.add_statement (new
CCodeExpressionStatement (value_equals_call
));
200 if (st
.scope
.lookup ("hash") is Method
) {
201 var value_hash_fun
= new
CCodeFunction ("%s_value_hash".printf (st
.get_lower_case_cname ()), "uint32_t");
202 value_hash_fun
.modifiers
= CCodeModifiers
.STATIC
;
203 value_hash_fun
.add_parameter (new
CCodeFormalParameter ("value", st
.get_cname () + "*"));
204 value_hash_fun
.add_parameter (new
CCodeFormalParameter ("value_index", "int32_t"));
205 value_hash_fun
.block
= new
CCodeBlock ();
206 var val
= new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, new
CCodeIdentifier ("value"), new
CCodeIdentifier ("value_index"));
207 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_hash".printf (st
.get_lower_case_cname ())));
208 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, val
));
209 value_hash_fun
.block
.add_statement (new
CCodeReturnStatement (ccall
));
210 cfile
.add_function (value_hash_fun
);
212 declare_set_value_hash_function (cfile
);
214 var value_hash_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_value_hash"));
215 value_hash_call
.add_argument (new
CCodeIdentifier ("type"));
216 value_hash_call
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("%s_value_hash".printf (st
.get_lower_case_cname ())), "uint32_t (*)(void *, int32_t)"));
217 type_init_fun
.block
.add_statement (new
CCodeExpressionStatement (value_hash_call
));
220 // generate method to box values
221 var value_to_any_fun
= new
CCodeFunction ("%s_value_to_any".printf (st
.get_lower_case_cname ()), "DovaObject*");
222 value_to_any_fun
.modifiers
= CCodeModifiers
.STATIC
;
223 value_to_any_fun
.add_parameter (new
CCodeFormalParameter ("value", "void *"));
224 value_to_any_fun
.add_parameter (new
CCodeFormalParameter ("value_index", "int32_t"));
225 value_to_any_fun
.block
= new
CCodeBlock ();
226 var alloc_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_object_alloc"));
227 alloc_call
.add_argument (new
CCodeFunctionCall (new
CCodeIdentifier ("%s_type_get".printf (st
.get_lower_case_cname ()))));
228 cdecl
= new
CCodeDeclaration ("DovaObject *");
229 cdecl
.add_declarator (new
CCodeVariableDeclarator ("result", alloc_call
));
230 value_to_any_fun
.block
.add_statement (cdecl
);
231 var priv_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_PRIVATE".printf (st
.get_upper_case_cname (null))));
232 priv_call
.add_argument (new
CCodeIdentifier ("result"));
233 var copy_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_copy".printf (st
.get_lower_case_cname ())));
234 copy_call
.add_argument (priv_call
);
235 copy_call
.add_argument (new
CCodeConstant ("0"));
236 copy_call
.add_argument (new
CCodeIdentifier ("value"));
237 copy_call
.add_argument (new
CCodeIdentifier ("value_index"));
238 value_to_any_fun
.block
.add_statement (new
CCodeExpressionStatement (copy_call
));
239 value_to_any_fun
.block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("result")));
240 cfile
.add_function (value_to_any_fun
);
242 declare_set_value_to_any_function (cfile
);
244 var value_to_any_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_value_to_any"));
245 value_to_any_call
.add_argument (new
CCodeIdentifier ("type"));
246 value_to_any_call
.add_argument (new
CCodeIdentifier ("%s_value_to_any".printf (st
.get_lower_case_cname ())));
247 type_init_fun
.block
.add_statement (new
CCodeExpressionStatement (value_to_any_call
));
249 // generate method to unbox values
250 var value_from_any_fun
= new
CCodeFunction ("%s_value_from_any".printf (st
.get_lower_case_cname ()));
251 value_from_any_fun
.modifiers
= CCodeModifiers
.STATIC
;
252 value_from_any_fun
.add_parameter (new
CCodeFormalParameter ("any_", "any *"));
253 value_from_any_fun
.add_parameter (new
CCodeFormalParameter ("value", st
.get_cname () + "*"));
254 value_from_any_fun
.add_parameter (new
CCodeFormalParameter ("value_index", "int32_t"));
255 value_from_any_fun
.block
= new
CCodeBlock ();
256 priv_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_PRIVATE".printf (st
.get_upper_case_cname (null))));
257 priv_call
.add_argument (new
CCodeIdentifier ("any_"));
258 copy_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_copy".printf (st
.get_lower_case_cname ())));
259 copy_call
.add_argument (new
CCodeIdentifier ("value"));
260 copy_call
.add_argument (new
CCodeIdentifier ("value_index"));
261 copy_call
.add_argument (priv_call
);
262 copy_call
.add_argument (new
CCodeConstant ("0"));
263 value_from_any_fun
.block
.add_statement (new
CCodeExpressionStatement (copy_call
));
264 cfile
.add_function (value_from_any_fun
);
266 declare_set_value_from_any_function (cfile
);
268 var value_from_any_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_value_from_any"));
269 value_from_any_call
.add_argument (new
CCodeIdentifier ("type"));
270 value_from_any_call
.add_argument (new
CCodeIdentifier ("%s_value_from_any".printf (st
.get_lower_case_cname ())));
271 type_init_fun
.block
.add_statement (new
CCodeExpressionStatement (value_from_any_call
));
273 cfile
.add_function (type_init_fun
);
275 add_struct_copy_function (st
);
278 void add_struct_copy_function (Struct st
) {
279 var function
= new
CCodeFunction (st
.get_copy_function (), "void");
280 if (st
.is_internal_symbol ()) {
281 function
.modifiers
= CCodeModifiers
.STATIC
;
284 function
.add_parameter (new
CCodeFormalParameter ("dest", st
.get_cname () + "*"));
285 function
.add_parameter (new
CCodeFormalParameter ("dest_index", "int32_t"));
286 function
.add_parameter (new
CCodeFormalParameter ("src", st
.get_cname () + "*"));
287 function
.add_parameter (new
CCodeFormalParameter ("src_index", "int32_t"));
289 var cblock
= new
CCodeBlock ();
290 var cfrag
= new
CCodeFragment ();
291 cblock
.add_statement (cfrag
);
293 var dest
= new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, new
CCodeIdentifier ("dest"), new
CCodeIdentifier ("dest_index"));
294 var src
= new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, new
CCodeIdentifier ("src"), new
CCodeIdentifier ("src_index"));
296 foreach (var f
in st
.get_fields ()) {
297 if (f
.binding
== MemberBinding
.INSTANCE
) {
298 var field
= new CCodeMemberAccess
.pointer (dest
, f
.name
);
300 var array_type
= f
.variable_type as ArrayType
;
301 if (array_type
!= null && array_type
.fixed_length
) {
302 for (int i
= 0; i
< array_type
.length
; i
++) {
303 var element
= new
CCodeElementAccess (field
, new
CCodeConstant (i
.to_string ()));
305 if (requires_destroy (array_type
.element_type
)) {
306 cblock
.add_statement (new
CCodeExpressionStatement (get_unref_expression (element
, array_type
.element_type
)));
312 if (requires_destroy (f
.variable_type
)) {
313 var this_access
= new MemberAccess
.simple ("this");
314 this_access
.value_type
= get_data_type_for_symbol ((TypeSymbol
) f
.parent_symbol
);
315 this_access
.ccodenode
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, dest
);
316 var ma
= new
MemberAccess (this_access
, f
.name
);
317 ma
.symbol_reference
= f
;
318 ma
.value_type
= f
.variable_type
.copy ();
319 cblock
.add_statement (new
CCodeExpressionStatement (get_unref_expression (field
, f
.variable_type
, ma
)));
324 var copy_block
= new
CCodeBlock ();
326 if (st
.get_fields ().size
== 0) {
327 copy_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, dest
), new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, src
))));
329 foreach (var f
in st
.get_fields ()) {
330 if (f
.binding
== MemberBinding
.INSTANCE
) {
331 CCodeExpression copy
= new CCodeMemberAccess
.pointer (src
, f
.name
);
332 var dest_field
= new CCodeMemberAccess
.pointer (dest
, f
.name
);
334 var array_type
= f
.variable_type as ArrayType
;
335 if (array_type
!= null && array_type
.fixed_length
) {
336 for (int i
= 0; i
< array_type
.length
; i
++) {
337 CCodeExpression copy_element
= new
CCodeElementAccess (copy
, new
CCodeConstant (i
.to_string ()));
338 var dest_field_element
= new
CCodeElementAccess (dest_field
, new
CCodeConstant (i
.to_string ()));
340 if (requires_copy (array_type
.element_type
)) {
341 copy_element
= get_ref_cexpression (array_type
.element_type
, copy_element
, null, f
);
344 copy_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (dest_field_element
, copy_element
)));
349 if (requires_copy (f
.variable_type
)) {
350 var this_access
= new MemberAccess
.simple ("this");
351 this_access
.value_type
= get_data_type_for_symbol ((TypeSymbol
) f
.parent_symbol
);
352 this_access
.ccodenode
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, src
);
353 var ma
= new
MemberAccess (this_access
, f
.name
);
354 ma
.symbol_reference
= f
;
355 copy
= get_ref_cexpression (f
.variable_type
, copy
, ma
, f
);
358 copy_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (dest_field
, copy
)));
363 cblock
.add_statement (new
CCodeIfStatement (new
CCodeIdentifier ("src"), copy_block
));
365 append_temp_decl (cfrag
, temp_vars
);
368 function
.block
= cblock
;
370 cfile
.add_function (function
);
373 public override void visit_assignment (Assignment assignment
) {
374 var generic_type
= assignment
.left
.value_type as GenericType
;
375 if (generic_type
== null) {
376 base.visit_assignment (assignment
);
380 var dest
= assignment
.left
;
381 CCodeExpression cdest
;
382 CCodeExpression dest_index
= new
CCodeConstant ("0");
383 var src
= assignment
.right
;
384 CCodeExpression csrc
;
385 CCodeExpression src_index
= new
CCodeConstant ("0");
387 if (src is NullLiteral
) {
389 assignment
.ccodenode
= new
CCodeConstant ("0");
393 var dest_ea
= dest as ElementAccess
;
394 var src_ea
= src as ElementAccess
;
396 if (dest_ea
!= null) {
397 dest
= dest_ea
.container
;
399 var array_type
= dest
.value_type as ArrayType
;
400 if (array_type
!= null && !array_type
.inline_allocated
) {
401 generate_property_accessor_declaration (((Property
) array_class
.scope
.lookup ("data")).get_accessor
, cfile
);
403 var data_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_array_get_data"));
404 data_call
.add_argument ((CCodeExpression
) get_ccodenode (dest
));
407 cdest
= (CCodeExpression
) get_ccodenode (dest
);
409 dest_index
= (CCodeExpression
) get_ccodenode (dest_ea
.get_indices ().get (0));
411 cdest
= (CCodeExpression
) get_ccodenode (dest
);
414 if (src_ea
!= null) {
415 src
= src_ea
.container
;
417 var array_type
= src
.value_type as ArrayType
;
418 if (array_type
!= null && !array_type
.inline_allocated
) {
419 generate_property_accessor_declaration (((Property
) array_class
.scope
.lookup ("data")).get_accessor
, cfile
);
421 var data_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_array_get_data"));
422 data_call
.add_argument ((CCodeExpression
) get_ccodenode (src
));
425 csrc
= (CCodeExpression
) get_ccodenode (src
);
427 src_index
= (CCodeExpression
) get_ccodenode (src_ea
.get_indices ().get (0));
429 csrc
= (CCodeExpression
) get_ccodenode (src
);
432 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_value_copy"));
433 if (generic_type
.type_parameter
.parent_symbol is TypeSymbol
) {
435 ccall
.add_argument (new CCodeMemberAccess
.pointer (get_type_private_from_type ((ObjectTypeSymbol
) generic_type
.type_parameter
.parent_symbol
, new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("this"), "type")), "%s_type".printf (generic_type
.type_parameter
.name
.down ())));
438 ccall
.add_argument (new
CCodeIdentifier ("%s_type".printf (generic_type
.type_parameter
.name
.down ())));
440 ccall
.add_argument (cdest
);
441 ccall
.add_argument (dest_index
);
442 ccall
.add_argument (csrc
);
443 ccall
.add_argument (src_index
);
444 assignment
.ccodenode
= ccall
;
447 public override void visit_binary_expression (BinaryExpression expr
) {
448 var generic_type
= expr
.left
.value_type as GenericType
;
449 if (generic_type
== null) {
450 base.visit_binary_expression (expr
);
454 CCodeExpression cleft
;
455 CCodeExpression left_index
= new
CCodeConstant ("0");
456 CCodeExpression cright
;
457 CCodeExpression right_index
= new
CCodeConstant ("0");
459 var left_ea
= expr
.left as ElementAccess
;
460 var right_ea
= expr
.right as ElementAccess
;
462 if (left_ea
!= null) {
463 generate_property_accessor_declaration (((Property
) array_class
.scope
.lookup ("data")).get_accessor
, cfile
);
465 var data_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_array_get_data"));
466 data_call
.add_argument ((CCodeExpression
) get_ccodenode (left_ea
.container
));
468 left_index
= (CCodeExpression
) get_ccodenode (left_ea
.get_indices ().get (0));
470 cleft
= (CCodeExpression
) get_ccodenode (expr
.left
);
473 if (right_ea
!= null) {
474 generate_property_accessor_declaration (((Property
) array_class
.scope
.lookup ("data")).get_accessor
, cfile
);
476 var data_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_array_get_data"));
477 data_call
.add_argument ((CCodeExpression
) get_ccodenode (right_ea
.container
));
479 right_index
= (CCodeExpression
) get_ccodenode (right_ea
.get_indices ().get (0));
481 cright
= (CCodeExpression
) get_ccodenode (expr
.right
);
484 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_value_equals"));
485 ccall
.add_argument (get_type_id_expression (generic_type
));
486 ccall
.add_argument (cleft
);
487 ccall
.add_argument (left_index
);
488 ccall
.add_argument (cright
);
489 ccall
.add_argument (right_index
);
491 if (expr
.operator
== BinaryOperator
.EQUALITY
) {
492 expr
.ccodenode
= ccall
;
494 expr
.ccodenode
= new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, ccall
);
498 public override void visit_method_call (MethodCall expr
) {
499 var ma
= expr
.call as MemberAccess
;
500 if (ma
== null || ma
.inner
== null || !(ma
.inner
.value_type is GenericType
)) {
501 base.visit_method_call (expr
);
505 // handle method calls on generic types
507 expr
.accept_children (this
);
509 if (ma
.member_name
== "hash") {
511 CCodeExpression cval
;
512 CCodeExpression val_index
= new
CCodeConstant ("0");
514 var val_ea
= val as ElementAccess
;
515 if (val_ea
!= null) {
516 val
= val_ea
.container
;
518 generate_property_accessor_declaration (((Property
) array_class
.scope
.lookup ("data")).get_accessor
, cfile
);
520 var data_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_array_get_data"));
521 data_call
.add_argument ((CCodeExpression
) get_ccodenode (val
));
523 val_index
= (CCodeExpression
) get_ccodenode (val_ea
.get_indices ().get (0));
525 cval
= (CCodeExpression
) get_ccodenode (val
);
528 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_value_hash"));
529 ccall
.add_argument (get_type_id_expression (ma
.inner
.value_type
));
530 ccall
.add_argument (cval
);
531 ccall
.add_argument (val_index
);
533 expr
.ccodenode
= ccall
;
537 public override void visit_list_literal (ListLiteral expr
) {
538 var ce
= new
CCodeCommaExpression ();
539 int length
= expr
.get_expressions ().size
;
542 ce
.append_expression (new
CCodeConstant ("NULL"));
544 var array_type
= new
ArrayType (expr
.element_type
, 1, expr
.source_reference
);
545 array_type
.inline_allocated
= true;
546 array_type
.fixed_length
= true;
547 array_type
.length
= length
;
549 var temp_var
= get_temp_variable (array_type
, true, expr
);
550 var name_cnode
= get_variable_cexpression (temp_var
.name
);
552 temp_vars
.add (temp_var
);
555 foreach (Expression e
in expr
.get_expressions ()) {
556 ce
.append_expression (new
CCodeAssignment (new
CCodeElementAccess (name_cnode
, new
CCodeConstant (i
.to_string ())), (CCodeExpression
) e
.ccodenode
));
560 ce
.append_expression (name_cnode
);
563 var list_creation
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_list_new"));
564 list_creation
.add_argument (get_type_id_expression (expr
.element_type
));
565 list_creation
.add_argument (new
CCodeConstant (length
.to_string ()));
566 list_creation
.add_argument (ce
);
568 expr
.ccodenode
= list_creation
;
571 public override void visit_set_literal (SetLiteral expr
) {
572 var ce
= new
CCodeCommaExpression ();
573 int length
= expr
.get_expressions ().size
;
576 ce
.append_expression (new
CCodeConstant ("NULL"));
578 var array_type
= new
ArrayType (expr
.element_type
, 1, expr
.source_reference
);
579 array_type
.inline_allocated
= true;
580 array_type
.fixed_length
= true;
581 array_type
.length
= length
;
583 var temp_var
= get_temp_variable (array_type
, true, expr
);
584 var name_cnode
= get_variable_cexpression (temp_var
.name
);
586 temp_vars
.add (temp_var
);
589 foreach (Expression e
in expr
.get_expressions ()) {
590 ce
.append_expression (new
CCodeAssignment (new
CCodeElementAccess (name_cnode
, new
CCodeConstant (i
.to_string ())), (CCodeExpression
) e
.ccodenode
));
594 ce
.append_expression (name_cnode
);
597 var set_creation
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_set_new"));
598 set_creation
.add_argument (get_type_id_expression (expr
.element_type
));
599 set_creation
.add_argument (new
CCodeConstant (length
.to_string ()));
600 set_creation
.add_argument (ce
);
602 expr
.ccodenode
= set_creation
;
605 public override void visit_map_literal (MapLiteral expr
) {
606 var key_ce
= new
CCodeCommaExpression ();
607 var value_ce
= new
CCodeCommaExpression ();
608 int length
= expr
.get_keys ().size
;
611 key_ce
.append_expression (new
CCodeConstant ("NULL"));
612 value_ce
.append_expression (new
CCodeConstant ("NULL"));
614 var key_array_type
= new
ArrayType (expr
.map_key_type
, 1, expr
.source_reference
);
615 key_array_type
.inline_allocated
= true;
616 key_array_type
.fixed_length
= true;
617 key_array_type
.length
= length
;
619 var key_temp_var
= get_temp_variable (key_array_type
, true, expr
);
620 var key_name_cnode
= get_variable_cexpression (key_temp_var
.name
);
622 temp_vars
.add (key_temp_var
);
624 var value_array_type
= new
ArrayType (expr
.map_value_type
, 1, expr
.source_reference
);
625 value_array_type
.inline_allocated
= true;
626 value_array_type
.fixed_length
= true;
627 value_array_type
.length
= length
;
629 var value_temp_var
= get_temp_variable (value_array_type
, true, expr
);
630 var value_name_cnode
= get_variable_cexpression (value_temp_var
.name
);
632 temp_vars
.add (value_temp_var
);
634 for (int i
= 0; i
< length
; i
++) {
635 key_ce
.append_expression (new
CCodeAssignment (new
CCodeElementAccess (key_name_cnode
, new
CCodeConstant (i
.to_string ())), (CCodeExpression
) expr
.get_keys ().get (i
).ccodenode
));
636 value_ce
.append_expression (new
CCodeAssignment (new
CCodeElementAccess (value_name_cnode
, new
CCodeConstant (i
.to_string ())), (CCodeExpression
) expr
.get_values ().get (i
).ccodenode
));
639 key_ce
.append_expression (key_name_cnode
);
640 value_ce
.append_expression (value_name_cnode
);
643 var map_creation
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_map_new"));
644 map_creation
.add_argument (get_type_id_expression (expr
.map_key_type
));
645 map_creation
.add_argument (get_type_id_expression (expr
.map_value_type
));
646 map_creation
.add_argument (new
CCodeConstant (length
.to_string ()));
647 map_creation
.add_argument (key_ce
);
648 map_creation
.add_argument (value_ce
);
650 expr
.ccodenode
= map_creation
;
653 public override void visit_tuple (Tuple tuple
) {
654 var type_array_type
= new
ArrayType (new
PointerType (new
VoidType ()), 1, tuple
.source_reference
);
655 type_array_type
.inline_allocated
= true;
656 type_array_type
.fixed_length
= true;
657 type_array_type
.length
= tuple
.get_expressions ().size
;
659 var type_temp_var
= get_temp_variable (type_array_type
, true, tuple
);
660 var type_name_cnode
= get_variable_cexpression (type_temp_var
.name
);
661 temp_vars
.add (type_temp_var
);
663 var array_type
= new
ArrayType (new
PointerType (new
VoidType ()), 1, tuple
.source_reference
);
664 array_type
.inline_allocated
= true;
665 array_type
.fixed_length
= true;
666 array_type
.length
= tuple
.get_expressions ().size
;
668 var temp_var
= get_temp_variable (array_type
, true, tuple
);
669 var name_cnode
= get_variable_cexpression (temp_var
.name
);
670 temp_vars
.add (temp_var
);
672 var type_ce
= new
CCodeCommaExpression ();
673 var ce
= new
CCodeCommaExpression ();
676 foreach (Expression e
in tuple
.get_expressions ()) {
677 var element_type
= tuple
.value_type
.get_type_arguments ().get (i
);
679 type_ce
.append_expression (new
CCodeAssignment (new
CCodeElementAccess (type_name_cnode
, new
CCodeConstant (i
.to_string ())), get_type_id_expression (element_type
)));
681 var cexpr
= (CCodeExpression
) e
.ccodenode
;
683 var unary
= cexpr as CCodeUnaryExpression
;
684 if (unary
!= null && unary
.operator
== CCodeUnaryOperator
.POINTER_INDIRECTION
) {
687 } else if (cexpr is CCodeIdentifier
|| cexpr is CCodeMemberAccess
) {
688 cexpr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, cexpr
);
690 // if cexpr is e.g. a function call, we can't take the address of the expression
693 var element_temp_var
= get_temp_variable (element_type
);
694 temp_vars
.add (element_temp_var
);
695 ce
.append_expression (new
CCodeAssignment (get_variable_cexpression (element_temp_var
.name
), cexpr
));
696 cexpr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (element_temp_var
.name
));
699 ce
.append_expression (new
CCodeAssignment (new
CCodeElementAccess (name_cnode
, new
CCodeConstant (i
.to_string ())), cexpr
));
704 type_ce
.append_expression (type_name_cnode
);
705 ce
.append_expression (name_cnode
);
707 var tuple_creation
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_tuple_new"));
708 tuple_creation
.add_argument (new
CCodeConstant (tuple
.get_expressions ().size
.to_string ()));
709 tuple_creation
.add_argument (type_ce
);
710 tuple_creation
.add_argument (ce
);
712 tuple
.ccodenode
= tuple_creation
;