codegen: Add get_field_cvalue and load_field
[vala-lang.git] / codegen / valadovavaluemodule.vala
blob0b6d36ec7dd945ac03a5b07d823c25b09dd21f08
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_function_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 CCodeParameter ("type", "DovaType *"));
52 if (st.is_internal_symbol ()) {
53 type_init_fun.modifiers = CCodeModifiers.STATIC;
55 decl_space.add_function_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 CCodeParameter ("dest", st.get_cname () + "*"));
63 function.add_parameter (new CCodeParameter ("dest_index", "intptr_t"));
64 function.add_parameter (new CCodeParameter ("src", st.get_cname () + "*"));
65 function.add_parameter (new CCodeParameter ("src_index", "intptr_t"));
67 decl_space.add_function_declaration (function);
70 public override void visit_struct (Struct st) {
71 base.visit_struct (st);
73 var cdecl = new CCodeDeclaration ("intptr_t");
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 CCodeParameter ("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 *, intptr_t, void *, intptr_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 CCodeParameter ("value", st.get_cname () + "*"));
180 value_equals_fun.add_parameter (new CCodeParameter ("value_index", "intptr_t"));
181 value_equals_fun.add_parameter (new CCodeParameter ("other", st.get_cname () + "*"));
182 value_equals_fun.add_parameter (new CCodeParameter ("other_index", "intptr_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 *, intptr_t, void *, intptr_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 ()), "uintptr_t");
202 value_hash_fun.modifiers = CCodeModifiers.STATIC;
203 value_hash_fun.add_parameter (new CCodeParameter ("value", st.get_cname () + "*"));
204 value_hash_fun.add_parameter (new CCodeParameter ("value_index", "intptr_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 ())), "uintptr_t (*)(void *, intptr_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 CCodeParameter ("value", "void *"));
224 value_to_any_fun.add_parameter (new CCodeParameter ("value_index", "intptr_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 CCodeParameter ("any_", "any *"));
253 value_from_any_fun.add_parameter (new CCodeParameter ("value", st.get_cname () + "*"));
254 value_from_any_fun.add_parameter (new CCodeParameter ("value_index", "intptr_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 CCodeParameter ("dest", st.get_cname () + "*"));
285 function.add_parameter (new CCodeParameter ("dest_index", "intptr_t"));
286 function.add_parameter (new CCodeParameter ("src", st.get_cname () + "*"));
287 function.add_parameter (new CCodeParameter ("src_index", "intptr_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 set_cvalue (this_access, 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 set_cvalue (this_access, 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 function.block = cblock;
367 cfile.add_function (function);
370 public override void visit_assignment (Assignment assignment) {
371 var generic_type = assignment.left.value_type as GenericType;
372 if (generic_type == null) {
373 base.visit_assignment (assignment);
374 return;
377 var dest = assignment.left;
378 CCodeExpression cdest;
379 CCodeExpression dest_index = new CCodeConstant ("0");
380 var src = assignment.right;
381 CCodeExpression csrc;
382 CCodeExpression src_index = new CCodeConstant ("0");
384 if (src is NullLiteral) {
385 // TODO destroy dest
386 set_cvalue (assignment, new CCodeConstant ("0"));
387 return;
390 var dest_ea = dest as ElementAccess;
391 var src_ea = src as ElementAccess;
393 if (dest_ea != null) {
394 dest = dest_ea.container;
396 var array_type = dest.value_type as ArrayType;
397 if (array_type != null && !array_type.inline_allocated) {
398 generate_property_accessor_declaration (((Property) array_class.scope.lookup ("data")).get_accessor, cfile);
400 var data_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_array_get_data"));
401 data_call.add_argument ((CCodeExpression) get_ccodenode (dest));
402 cdest = data_call;
403 } else {
404 cdest = (CCodeExpression) get_ccodenode (dest);
406 dest_index = (CCodeExpression) get_ccodenode (dest_ea.get_indices ().get (0));
407 } else {
408 cdest = (CCodeExpression) get_ccodenode (dest);
411 if (src_ea != null) {
412 src = src_ea.container;
414 var array_type = src.value_type as ArrayType;
415 if (array_type != null && !array_type.inline_allocated) {
416 generate_property_accessor_declaration (((Property) array_class.scope.lookup ("data")).get_accessor, cfile);
418 var data_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_array_get_data"));
419 data_call.add_argument ((CCodeExpression) get_ccodenode (src));
420 csrc = data_call;
421 } else {
422 csrc = (CCodeExpression) get_ccodenode (src);
424 src_index = (CCodeExpression) get_ccodenode (src_ea.get_indices ().get (0));
425 } else {
426 csrc = (CCodeExpression) get_ccodenode (src);
429 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_value_copy"));
430 if (generic_type.type_parameter.parent_symbol is TypeSymbol) {
431 // generic type
432 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 ())));
433 } else {
434 // generic method
435 ccall.add_argument (new CCodeIdentifier ("%s_type".printf (generic_type.type_parameter.name.down ())));
437 ccall.add_argument (cdest);
438 ccall.add_argument (dest_index);
439 ccall.add_argument (csrc);
440 ccall.add_argument (src_index);
441 set_cvalue (assignment, ccall);
444 public override void visit_binary_expression (BinaryExpression expr) {
445 var generic_type = expr.left.value_type as GenericType;
446 if (generic_type == null) {
447 base.visit_binary_expression (expr);
448 return;
451 CCodeExpression cleft;
452 CCodeExpression left_index = new CCodeConstant ("0");
453 CCodeExpression cright;
454 CCodeExpression right_index = new CCodeConstant ("0");
456 var left_ea = expr.left as ElementAccess;
457 var right_ea = expr.right as ElementAccess;
459 if (left_ea != null) {
460 generate_property_accessor_declaration (((Property) array_class.scope.lookup ("data")).get_accessor, cfile);
462 var data_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_array_get_data"));
463 data_call.add_argument ((CCodeExpression) get_ccodenode (left_ea.container));
464 cleft = data_call;
465 left_index = (CCodeExpression) get_ccodenode (left_ea.get_indices ().get (0));
466 } else {
467 cleft = (CCodeExpression) get_ccodenode (expr.left);
470 if (right_ea != null) {
471 generate_property_accessor_declaration (((Property) array_class.scope.lookup ("data")).get_accessor, cfile);
473 var data_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_array_get_data"));
474 data_call.add_argument ((CCodeExpression) get_ccodenode (right_ea.container));
475 cright = data_call;
476 right_index = (CCodeExpression) get_ccodenode (right_ea.get_indices ().get (0));
477 } else {
478 cright = (CCodeExpression) get_ccodenode (expr.right);
481 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_value_equals"));
482 ccall.add_argument (get_type_id_expression (generic_type));
483 ccall.add_argument (cleft);
484 ccall.add_argument (left_index);
485 ccall.add_argument (cright);
486 ccall.add_argument (right_index);
488 if (expr.operator == BinaryOperator.EQUALITY) {
489 set_cvalue (expr, ccall);
490 } else {
491 set_cvalue (expr, new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, ccall));
495 public override void visit_method_call (MethodCall expr) {
496 var ma = expr.call as MemberAccess;
497 if (ma == null || ma.inner == null || !(ma.inner.value_type is GenericType)) {
498 base.visit_method_call (expr);
499 return;
502 // handle method calls on generic types
504 expr.accept_children (this);
506 if (ma.member_name == "hash") {
507 var val = ma.inner;
508 CCodeExpression cval;
509 CCodeExpression val_index = new CCodeConstant ("0");
511 var val_ea = val as ElementAccess;
512 if (val_ea != null) {
513 val = val_ea.container;
515 generate_property_accessor_declaration (((Property) array_class.scope.lookup ("data")).get_accessor, cfile);
517 var data_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_array_get_data"));
518 data_call.add_argument ((CCodeExpression) get_ccodenode (val));
519 cval = data_call;
520 val_index = (CCodeExpression) get_ccodenode (val_ea.get_indices ().get (0));
521 } else {
522 cval = (CCodeExpression) get_ccodenode (val);
525 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_value_hash"));
526 ccall.add_argument (get_type_id_expression (ma.inner.value_type));
527 ccall.add_argument (cval);
528 ccall.add_argument (val_index);
530 set_cvalue (expr, ccall);
534 public override void visit_list_literal (ListLiteral expr) {
535 var ce = new CCodeCommaExpression ();
536 int length = expr.get_expressions ().size;
538 if (length == 0) {
539 ce.append_expression (new CCodeConstant ("NULL"));
540 } else {
541 var array_type = new ArrayType (expr.element_type, 1, expr.source_reference);
542 array_type.inline_allocated = true;
543 array_type.fixed_length = true;
544 array_type.length = length;
546 var temp_var = get_temp_variable (array_type, true, expr);
547 var name_cnode = get_variable_cexpression (temp_var.name);
549 emit_temp_var (temp_var);
551 int i = 0;
552 foreach (Expression e in expr.get_expressions ()) {
553 ce.append_expression (new CCodeAssignment (new CCodeElementAccess (name_cnode, new CCodeConstant (i.to_string ())), get_cvalue (e)));
554 i++;
557 ce.append_expression (name_cnode);
560 var list_creation = new CCodeFunctionCall (new CCodeIdentifier ("dova_list_new"));
561 list_creation.add_argument (get_type_id_expression (expr.element_type));
562 list_creation.add_argument (new CCodeConstant (length.to_string ()));
563 list_creation.add_argument (ce);
565 set_cvalue (expr, list_creation);
568 public override void visit_set_literal (SetLiteral expr) {
569 var ce = new CCodeCommaExpression ();
570 int length = expr.get_expressions ().size;
572 if (length == 0) {
573 ce.append_expression (new CCodeConstant ("NULL"));
574 } else {
575 var array_type = new ArrayType (expr.element_type, 1, expr.source_reference);
576 array_type.inline_allocated = true;
577 array_type.fixed_length = true;
578 array_type.length = length;
580 var temp_var = get_temp_variable (array_type, true, expr);
581 var name_cnode = get_variable_cexpression (temp_var.name);
583 emit_temp_var (temp_var);
585 int i = 0;
586 foreach (Expression e in expr.get_expressions ()) {
587 ce.append_expression (new CCodeAssignment (new CCodeElementAccess (name_cnode, new CCodeConstant (i.to_string ())), get_cvalue (e)));
588 i++;
591 ce.append_expression (name_cnode);
594 var set_creation = new CCodeFunctionCall (new CCodeIdentifier ("dova_set_new"));
595 set_creation.add_argument (get_type_id_expression (expr.element_type));
596 set_creation.add_argument (new CCodeConstant (length.to_string ()));
597 set_creation.add_argument (ce);
599 set_cvalue (expr, set_creation);
602 public override void visit_map_literal (MapLiteral expr) {
603 var key_ce = new CCodeCommaExpression ();
604 var value_ce = new CCodeCommaExpression ();
605 int length = expr.get_keys ().size;
607 if (length == 0) {
608 key_ce.append_expression (new CCodeConstant ("NULL"));
609 value_ce.append_expression (new CCodeConstant ("NULL"));
610 } else {
611 var key_array_type = new ArrayType (expr.map_key_type, 1, expr.source_reference);
612 key_array_type.inline_allocated = true;
613 key_array_type.fixed_length = true;
614 key_array_type.length = length;
616 var key_temp_var = get_temp_variable (key_array_type, true, expr);
617 var key_name_cnode = get_variable_cexpression (key_temp_var.name);
619 emit_temp_var (key_temp_var);
621 var value_array_type = new ArrayType (expr.map_value_type, 1, expr.source_reference);
622 value_array_type.inline_allocated = true;
623 value_array_type.fixed_length = true;
624 value_array_type.length = length;
626 var value_temp_var = get_temp_variable (value_array_type, true, expr);
627 var value_name_cnode = get_variable_cexpression (value_temp_var.name);
629 emit_temp_var (value_temp_var);
631 for (int i = 0; i < length; i++) {
632 key_ce.append_expression (new CCodeAssignment (new CCodeElementAccess (key_name_cnode, new CCodeConstant (i.to_string ())), get_cvalue (expr.get_keys ().get (i))));
633 value_ce.append_expression (new CCodeAssignment (new CCodeElementAccess (value_name_cnode, new CCodeConstant (i.to_string ())), get_cvalue (expr.get_values ().get (i))));
636 key_ce.append_expression (key_name_cnode);
637 value_ce.append_expression (value_name_cnode);
640 var map_creation = new CCodeFunctionCall (new CCodeIdentifier ("dova_map_new"));
641 map_creation.add_argument (get_type_id_expression (expr.map_key_type));
642 map_creation.add_argument (get_type_id_expression (expr.map_value_type));
643 map_creation.add_argument (new CCodeConstant (length.to_string ()));
644 map_creation.add_argument (key_ce);
645 map_creation.add_argument (value_ce);
647 set_cvalue (expr, map_creation);
650 public override void visit_tuple (Tuple tuple) {
651 var type_array_type = new ArrayType (new PointerType (new VoidType ()), 1, tuple.source_reference);
652 type_array_type.inline_allocated = true;
653 type_array_type.fixed_length = true;
654 type_array_type.length = tuple.get_expressions ().size;
656 var type_temp_var = get_temp_variable (type_array_type, true, tuple);
657 var type_name_cnode = get_variable_cexpression (type_temp_var.name);
658 emit_temp_var (type_temp_var);
660 var array_type = new ArrayType (new PointerType (new VoidType ()), 1, tuple.source_reference);
661 array_type.inline_allocated = true;
662 array_type.fixed_length = true;
663 array_type.length = tuple.get_expressions ().size;
665 var temp_var = get_temp_variable (array_type, true, tuple);
666 var name_cnode = get_variable_cexpression (temp_var.name);
667 emit_temp_var (temp_var);
669 var type_ce = new CCodeCommaExpression ();
670 var ce = new CCodeCommaExpression ();
672 int i = 0;
673 foreach (Expression e in tuple.get_expressions ()) {
674 var element_type = tuple.value_type.get_type_arguments ().get (i);
676 type_ce.append_expression (new CCodeAssignment (new CCodeElementAccess (type_name_cnode, new CCodeConstant (i.to_string ())), get_type_id_expression (element_type)));
678 var cexpr = get_cvalue (e);
680 var unary = cexpr as CCodeUnaryExpression;
681 if (unary != null && unary.operator == CCodeUnaryOperator.POINTER_INDIRECTION) {
682 // *expr => expr
683 cexpr = unary.inner;
684 } else if (cexpr is CCodeIdentifier || cexpr is CCodeMemberAccess) {
685 cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr);
686 } else {
687 // if cexpr is e.g. a function call, we can't take the address of the expression
688 // tmp = expr, &tmp
690 var element_temp_var = get_temp_variable (element_type);
691 emit_temp_var (element_temp_var);
692 ce.append_expression (new CCodeAssignment (get_variable_cexpression (element_temp_var.name), cexpr));
693 cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (element_temp_var.name));
696 ce.append_expression (new CCodeAssignment (new CCodeElementAccess (name_cnode, new CCodeConstant (i.to_string ())), cexpr));
698 i++;
701 type_ce.append_expression (type_name_cnode);
702 ce.append_expression (name_cnode);
704 var tuple_creation = new CCodeFunctionCall (new CCodeIdentifier ("dova_tuple_new"));
705 tuple_creation.add_argument (new CCodeConstant (tuple.get_expressions ().size.to_string ()));
706 tuple_creation.add_argument (type_ce);
707 tuple_creation.add_argument (ce);
709 set_cvalue (tuple, tuple_creation);