posix: Fix SockAddr cname.
[vala-lang.git] / codegen / valadovavaluemodule.vala
blob1f12d61adbfa16762659b9d33a06b2402daced06
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
19 * Author:
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);
29 return;
32 visit_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 ())) {
39 return;
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)));
309 continue;
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))));
328 } else {
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)));
346 continue;
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);
366 temp_vars.clear ();
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);
377 return;
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) {
388 // TODO destroy dest
389 assignment.ccodenode = new CCodeConstant ("0");
390 return;
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));
405 cdest = data_call;
406 } else {
407 cdest = (CCodeExpression) get_ccodenode (dest);
409 dest_index = (CCodeExpression) get_ccodenode (dest_ea.get_indices ().get (0));
410 } else {
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));
423 csrc = data_call;
424 } else {
425 csrc = (CCodeExpression) get_ccodenode (src);
427 src_index = (CCodeExpression) get_ccodenode (src_ea.get_indices ().get (0));
428 } else {
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) {
434 // generic type
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 ())));
436 } else {
437 // generic method
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);
451 return;
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));
467 cleft = data_call;
468 left_index = (CCodeExpression) get_ccodenode (left_ea.get_indices ().get (0));
469 } else {
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));
478 cright = data_call;
479 right_index = (CCodeExpression) get_ccodenode (right_ea.get_indices ().get (0));
480 } else {
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;
493 } else {
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);
502 return;
505 // handle method calls on generic types
507 expr.accept_children (this);
509 if (ma.member_name == "hash") {
510 var val = ma.inner;
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));
522 cval = data_call;
523 val_index = (CCodeExpression) get_ccodenode (val_ea.get_indices ().get (0));
524 } else {
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;
541 if (length == 0) {
542 ce.append_expression (new CCodeConstant ("NULL"));
543 } else {
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);
554 int i = 0;
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));
557 i++;
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;
575 if (length == 0) {
576 ce.append_expression (new CCodeConstant ("NULL"));
577 } else {
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);
588 int i = 0;
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));
591 i++;
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;
610 if (length == 0) {
611 key_ce.append_expression (new CCodeConstant ("NULL"));
612 value_ce.append_expression (new CCodeConstant ("NULL"));
613 } else {
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 ();
675 int i = 0;
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) {
685 // *expr => expr
686 cexpr = unary.inner;
687 } else if (cexpr is CCodeIdentifier || cexpr is CCodeMemberAccess) {
688 cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr);
689 } else {
690 // if cexpr is e.g. a function call, we can't take the address of the expression
691 // tmp = expr, &tmp
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));
701 i++;
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;