girparser: Simplify postprocessing callbacks. Use symbols info for records.
[vala-lang.git] / codegen / valadovaobjectmodule.vala
blob66468970920012438e828ff47cf196ba5b8dc2e6
1 /* valadovaobjectmodule.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.DovaObjectModule : DovaArrayModule {
24 public override void generate_class_declaration (Class cl, CCodeFile decl_space) {
25 if (add_symbol_declaration (decl_space, cl, cl.get_cname ())) {
26 return;
29 if (cl.base_class == null) {
30 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (cl.get_cname ()), new CCodeVariableDeclarator (cl.get_cname ())));
31 } else if (cl == string_type.data_type) {
32 generate_class_declaration (cl.base_class, decl_space);
33 decl_space.add_type_declaration (new CCodeTypeDefinition ("const uint8_t *", new CCodeVariableDeclarator (cl.get_cname ())));
34 } else {
35 // typedef to base class instead of dummy struct to avoid warnings/casts
36 generate_class_declaration (cl.base_class, decl_space);
37 decl_space.add_type_declaration (new CCodeTypeDefinition (cl.base_class.get_cname (), new CCodeVariableDeclarator (cl.get_cname ())));
40 if (cl.base_class == null) {
41 var instance_struct = new CCodeStruct ("_%s".printf (cl.get_cname ()));
42 instance_struct.add_field ("DovaType *", "type");
43 decl_space.add_type_definition (instance_struct);
44 } else if (cl == type_class) {
45 var value_copy_function = new CCodeFunction ("dova_type_value_copy");
46 value_copy_function.add_parameter (new CCodeParameter ("type", "DovaType *"));
47 value_copy_function.add_parameter (new CCodeParameter ("dest", "void *"));
48 value_copy_function.add_parameter (new CCodeParameter ("dest_index", "intptr_t"));
49 value_copy_function.add_parameter (new CCodeParameter ("src", "void *"));
50 value_copy_function.add_parameter (new CCodeParameter ("src_index", "intptr_t"));
52 cfile.add_function_declaration (value_copy_function);
54 var value_equals_function = new CCodeFunction ("dova_type_value_equals", "bool");
55 value_equals_function.add_parameter (new CCodeParameter ("type", "DovaType *"));
56 value_equals_function.add_parameter (new CCodeParameter ("value", "void *"));
57 value_equals_function.add_parameter (new CCodeParameter ("value_index", "intptr_t"));
58 value_equals_function.add_parameter (new CCodeParameter ("other", "void *"));
59 value_equals_function.add_parameter (new CCodeParameter ("other_index", "intptr_t"));
61 cfile.add_function_declaration (value_equals_function);
63 var value_hash_function = new CCodeFunction ("dova_type_value_hash", "uintptr_t");
64 value_hash_function.add_parameter (new CCodeParameter ("type", "DovaType *"));
65 value_hash_function.add_parameter (new CCodeParameter ("value", "void *"));
66 value_hash_function.add_parameter (new CCodeParameter ("value_index", "intptr_t"));
68 cfile.add_function_declaration (value_hash_function);
71 if (cl.base_class != null) {
72 // cycle Object -> any -> Type -> Object needs to be broken to get correct declaration order
73 generate_class_declaration (type_class, decl_space);
75 generate_method_declaration ((Method) object_class.scope.lookup ("ref"), decl_space);
76 generate_method_declaration ((Method) object_class.scope.lookup ("unref"), decl_space);
78 var type_fun = new CCodeFunction ("%s_type_get".printf (cl.get_lower_case_cname ()), "DovaType *");
79 if (cl.is_internal_symbol ()) {
80 type_fun.modifiers = CCodeModifiers.STATIC;
82 foreach (var type_param in cl.get_type_parameters ()) {
83 type_fun.add_parameter (new CCodeParameter ("%s_type".printf (type_param.name.down ()), "DovaType *"));
85 decl_space.add_function_declaration (type_fun);
87 var type_init_fun = new CCodeFunction ("%s_type_init".printf (cl.get_lower_case_cname ()));
88 if (cl.is_internal_symbol ()) {
89 type_init_fun.modifiers = CCodeModifiers.STATIC;
91 type_init_fun.add_parameter (new CCodeParameter ("type", "DovaType *"));
92 foreach (var type_param in cl.get_type_parameters ()) {
93 type_init_fun.add_parameter (new CCodeParameter ("%s_type".printf (type_param.name.down ()), "DovaType *"));
95 decl_space.add_function_declaration (type_init_fun);
98 void generate_virtual_method_declaration (Method m, CCodeFile decl_space, CCodeStruct type_struct) {
99 if (!m.is_abstract && !m.is_virtual) {
100 return;
103 // add vfunc field to the type struct
104 var vdeclarator = new CCodeFunctionDeclarator (m.vfunc_name);
106 generate_cparameters (m, decl_space, new CCodeFunction ("fake"), vdeclarator);
108 var vdecl = new CCodeDeclaration (m.return_type.get_cname ());
109 vdecl.add_declarator (vdeclarator);
110 type_struct.add_declaration (vdecl);
113 bool has_instance_struct (Class cl) {
114 foreach (Field f in cl.get_fields ()) {
115 if (f.binding == MemberBinding.INSTANCE) {
116 return true;
119 return false;
122 bool has_type_struct (Class cl) {
123 if (cl.get_type_parameters ().size > 0) {
124 return true;
126 foreach (Method m in cl.get_methods ()) {
127 if (m.is_abstract || m.is_virtual) {
128 return true;
131 foreach (Property prop in cl.get_properties ()) {
132 if (prop.is_abstract || prop.is_virtual) {
133 return true;
136 return false;
139 void generate_class_private_declaration (Class cl, CCodeFile decl_space) {
140 if (add_symbol_declaration (decl_space, cl, cl.get_cname () + "Private")) {
141 return;
144 var instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (cl.get_cname ()));
145 var type_priv_struct = new CCodeStruct ("_%sTypePrivate".printf (cl.get_cname ()));
147 foreach (Field f in cl.get_fields ()) {
148 if (f.binding == MemberBinding.INSTANCE) {
149 generate_type_declaration (f.variable_type, decl_space);
151 string field_ctype = f.variable_type.get_cname ();
152 if (f.is_volatile) {
153 field_ctype = "volatile " + field_ctype;
156 instance_priv_struct.add_field (field_ctype, f.get_cname () + f.variable_type.get_cdeclarator_suffix ());
160 if (cl.get_full_name () == "Dova.Type") {
161 var vdeclarator = new CCodeFunctionDeclarator ("value_copy");
162 vdeclarator.add_parameter (new CCodeParameter ("dest", "void *"));
163 vdeclarator.add_parameter (new CCodeParameter ("dest_index", "intptr_t"));
164 vdeclarator.add_parameter (new CCodeParameter ("src", "void *"));
165 vdeclarator.add_parameter (new CCodeParameter ("src_index", "intptr_t"));
167 var vdecl = new CCodeDeclaration ("void");
168 vdecl.add_declarator (vdeclarator);
169 instance_priv_struct.add_declaration (vdecl);
171 vdeclarator = new CCodeFunctionDeclarator ("value_equals");
172 vdeclarator.add_parameter (new CCodeParameter ("value", "void *"));
173 vdeclarator.add_parameter (new CCodeParameter ("value_index", "intptr_t"));
174 vdeclarator.add_parameter (new CCodeParameter ("other", "void *"));
175 vdeclarator.add_parameter (new CCodeParameter ("other_index", "intptr_t"));
177 vdecl = new CCodeDeclaration ("bool");
178 vdecl.add_declarator (vdeclarator);
179 instance_priv_struct.add_declaration (vdecl);
181 vdeclarator = new CCodeFunctionDeclarator ("value_hash");
182 vdeclarator.add_parameter (new CCodeParameter ("value", "void *"));
183 vdeclarator.add_parameter (new CCodeParameter ("value_index", "intptr_t"));
185 vdecl = new CCodeDeclaration ("uintptr_t");
186 vdecl.add_declarator (vdeclarator);
187 instance_priv_struct.add_declaration (vdecl);
189 vdeclarator = new CCodeFunctionDeclarator ("value_to_any");
190 vdeclarator.add_parameter (new CCodeParameter ("value", "void *"));
191 vdeclarator.add_parameter (new CCodeParameter ("value_index", "intptr_t"));
193 vdecl = new CCodeDeclaration ("DovaObject *");
194 vdecl.add_declarator (vdeclarator);
195 instance_priv_struct.add_declaration (vdecl);
197 vdeclarator = new CCodeFunctionDeclarator ("value_from_any");
198 vdeclarator.add_parameter (new CCodeParameter ("any_", "any *"));
199 vdeclarator.add_parameter (new CCodeParameter ("value", "void *"));
200 vdeclarator.add_parameter (new CCodeParameter ("value_index", "intptr_t"));
202 vdecl = new CCodeDeclaration ("void");
203 vdecl.add_declarator (vdeclarator);
204 instance_priv_struct.add_declaration (vdecl);
207 foreach (var type_param in cl.get_type_parameters ()) {
208 var type_param_decl = new CCodeDeclaration ("DovaType *");
209 type_param_decl.add_declarator (new CCodeVariableDeclarator ("%s_type".printf (type_param.name.down ())));
210 type_priv_struct.add_declaration (type_param_decl);
213 foreach (Method m in cl.get_methods ()) {
214 generate_virtual_method_declaration (m, decl_space, type_priv_struct);
217 foreach (Property prop in cl.get_properties ()) {
218 if (!prop.is_abstract && !prop.is_virtual) {
219 continue;
221 generate_type_declaration (prop.property_type, decl_space);
223 var t = (ObjectTypeSymbol) prop.parent_symbol;
225 var this_type = new ObjectType (t);
226 var cselfparam = new CCodeParameter ("this", this_type.get_cname ());
227 var cvalueparam = new CCodeParameter ("value", prop.property_type.get_cname ());
229 if (prop.get_accessor != null) {
230 var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
231 vdeclarator.add_parameter (cselfparam);
232 string creturn_type = prop.property_type.get_cname ();
234 var vdecl = new CCodeDeclaration (creturn_type);
235 vdecl.add_declarator (vdeclarator);
236 type_priv_struct.add_declaration (vdecl);
238 if (prop.set_accessor != null) {
239 var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
240 vdeclarator.add_parameter (cselfparam);
241 vdeclarator.add_parameter (cvalueparam);
243 var vdecl = new CCodeDeclaration ("void");
244 vdecl.add_declarator (vdeclarator);
245 type_priv_struct.add_declaration (vdecl);
249 if (!instance_priv_struct.is_empty) {
250 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (instance_priv_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (cl.get_cname ()))));
251 decl_space.add_type_definition (instance_priv_struct);
254 if (!type_priv_struct.is_empty) {
255 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_priv_struct.name), new CCodeVariableDeclarator ("%sTypePrivate".printf (cl.get_cname ()))));
256 decl_space.add_type_definition (type_priv_struct);
259 var cdecl = new CCodeDeclaration ("intptr_t");
260 cdecl.add_declarator (new CCodeVariableDeclarator ("_%s_object_offset".printf (cl.get_lower_case_cname ()), new CCodeConstant ("0")));
261 cdecl.modifiers = CCodeModifiers.STATIC;
262 decl_space.add_type_member_declaration (cdecl);
264 CCodeExpression type_offset;
266 string macro;
267 if (cl.base_class == null) {
268 // offset of any class is 0
269 macro = "((%sPrivate *) o)".printf (cl.get_cname ());
270 type_offset = new CCodeConstant ("sizeof (anyPrivate) + sizeof (DovaObjectPrivate) + sizeof (DovaTypePrivate)");
271 } else if (cl == object_class) {
272 macro = "((%sPrivate *) (((char *) o) + sizeof (anyPrivate)))".printf (cl.get_cname ());
273 type_offset = new CCodeConstant ("sizeof (anyPrivate) + sizeof (DovaObjectPrivate) + sizeof (DovaTypePrivate) + sizeof (anyTypePrivate)");
274 } else if (cl == type_class) {
275 macro = "((%sPrivate *) (((char *) o) + sizeof (anyPrivate) + sizeof (DovaObjectPrivate)))".printf (cl.get_cname ());
276 type_offset = new CCodeConstant ("sizeof (anyPrivate) + sizeof (DovaObjectPrivate) + sizeof (DovaTypePrivate) + sizeof (anyTypePrivate) + sizeof (DovaObjectTypePrivate)");
277 } else {
278 macro = "((%sPrivate *) (((char *) o) + _%s_object_offset))".printf (cl.get_cname (), cl.get_lower_case_cname ());
279 type_offset = new CCodeConstant ("0");
281 if (!instance_priv_struct.is_empty) {
282 decl_space.add_type_member_declaration (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro));
285 cdecl = new CCodeDeclaration ("intptr_t");
286 cdecl.add_declarator (new CCodeVariableDeclarator ("_%s_type_offset".printf (cl.get_lower_case_cname ()), type_offset));
287 cdecl.modifiers = CCodeModifiers.STATIC;
288 decl_space.add_type_member_declaration (cdecl);
291 CCodeFunction create_set_value_copy_function (bool decl_only = false) {
292 var result = new CCodeFunction ("dova_type_set_value_copy");
293 result.add_parameter (new CCodeParameter ("type", "DovaType *"));
294 result.add_parameter (new CCodeParameter ("(*function) (void *dest, intptr_t dest_index, void *src, intptr_t src_index)", "void"));
295 if (decl_only) {
296 return result;
299 result.block = new CCodeBlock ();
301 var priv_call = new CCodeFunctionCall (new CCodeIdentifier ("DOVA_TYPE_GET_PRIVATE"));
302 priv_call.add_argument (new CCodeIdentifier ("type"));
304 result.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (priv_call, "value_copy"), new CCodeIdentifier ("function"))));
305 return result;
308 public void declare_set_value_copy_function (CCodeFile decl_space) {
309 if (add_symbol_declaration (decl_space, type_class, "dova_type_set_value_copy")) {
310 return;
312 decl_space.add_function_declaration (create_set_value_copy_function (true));
315 CCodeFunction create_set_value_equals_function (bool decl_only = false) {
316 var result = new CCodeFunction ("dova_type_set_value_equals");
317 result.add_parameter (new CCodeParameter ("type", "DovaType *"));
318 result.add_parameter (new CCodeParameter ("(*function) (void *value, intptr_t value_index, void *other, intptr_t other_index)", "bool"));
319 if (decl_only) {
320 return result;
323 result.block = new CCodeBlock ();
325 var priv_call = new CCodeFunctionCall (new CCodeIdentifier ("DOVA_TYPE_GET_PRIVATE"));
326 priv_call.add_argument (new CCodeIdentifier ("type"));
328 result.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (priv_call, "value_equals"), new CCodeIdentifier ("function"))));
329 return result;
332 public void declare_set_value_equals_function (CCodeFile decl_space) {
333 if (add_symbol_declaration (decl_space, type_class, "dova_type_set_value_equals")) {
334 return;
336 decl_space.add_function_declaration (create_set_value_equals_function (true));
339 CCodeFunction create_set_value_hash_function (bool decl_only = false) {
340 var result = new CCodeFunction ("dova_type_set_value_hash");
341 result.add_parameter (new CCodeParameter ("type", "DovaType *"));
342 result.add_parameter (new CCodeParameter ("(*function) (void *value, intptr_t value_index)", "uintptr_t"));
343 if (decl_only) {
344 return result;
347 result.block = new CCodeBlock ();
349 var priv_call = new CCodeFunctionCall (new CCodeIdentifier ("DOVA_TYPE_GET_PRIVATE"));
350 priv_call.add_argument (new CCodeIdentifier ("type"));
352 result.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (priv_call, "value_hash"), new CCodeIdentifier ("function"))));
353 return result;
356 public void declare_set_value_hash_function (CCodeFile decl_space) {
357 if (add_symbol_declaration (decl_space, type_class, "dova_type_set_value_hash")) {
358 return;
360 decl_space.add_function_declaration (create_set_value_hash_function (true));
363 CCodeFunction create_set_value_to_any_function (bool decl_only = false) {
364 var result = new CCodeFunction ("dova_type_set_value_to_any");
365 result.add_parameter (new CCodeParameter ("type", "DovaType *"));
366 result.add_parameter (new CCodeParameter ("(*function) (void *value, intptr_t value_index)", "DovaObject *"));
367 if (decl_only) {
368 return result;
371 result.block = new CCodeBlock ();
373 var priv_call = new CCodeFunctionCall (new CCodeIdentifier ("DOVA_TYPE_GET_PRIVATE"));
374 priv_call.add_argument (new CCodeIdentifier ("type"));
376 result.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (priv_call, "value_to_any"), new CCodeIdentifier ("function"))));
377 return result;
380 public void declare_set_value_to_any_function (CCodeFile decl_space) {
381 if (add_symbol_declaration (decl_space, type_class, "dova_type_set_value_to_any")) {
382 return;
384 decl_space.add_function_declaration (create_set_value_to_any_function (true));
387 CCodeFunction create_set_value_from_any_function (bool decl_only = false) {
388 var result = new CCodeFunction ("dova_type_set_value_from_any");
389 result.add_parameter (new CCodeParameter ("type", "DovaType *"));
390 result.add_parameter (new CCodeParameter ("(*function) (DovaObject *any, void *value, intptr_t value_index)", "void"));
391 if (decl_only) {
392 return result;
395 result.block = new CCodeBlock ();
397 var priv_call = new CCodeFunctionCall (new CCodeIdentifier ("DOVA_TYPE_GET_PRIVATE"));
398 priv_call.add_argument (new CCodeIdentifier ("type"));
400 result.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (priv_call, "value_from_any"), new CCodeIdentifier ("function"))));
401 return result;
404 public void declare_set_value_from_any_function (CCodeFile decl_space) {
405 if (add_symbol_declaration (decl_space, type_class, "dova_type_set_value_from_any")) {
406 return;
408 decl_space.add_function_declaration (create_set_value_from_any_function (true));
411 public CCodeBlock generate_type_get_function (TypeSymbol cl, Class? base_class) {
412 DataType? base_class_type = null;
413 if (base_class != null && cl is Class) {
414 foreach (DataType base_type in ((Class) cl).get_base_types ()) {
415 if (base_type.data_type == base_class) {
416 base_class_type = base_type;
417 break;
422 var cdecl = new CCodeDeclaration ("DovaType *");
423 cdecl.add_declarator (new CCodeVariableDeclarator ("%s_type".printf (cl.get_lower_case_cname ()), new CCodeConstant ("NULL")));
424 cdecl.modifiers = CCodeModifiers.STATIC;
425 cfile.add_type_member_declaration (cdecl);
427 var type_fun = new CCodeFunction ("%s_type_get".printf (cl.get_lower_case_cname ()), "DovaType *");
428 if (cl.is_internal_symbol ()) {
429 type_fun.modifiers = CCodeModifiers.STATIC;
432 var object_type_symbol = cl as ObjectTypeSymbol;
433 if (object_type_symbol != null) {
434 foreach (var type_param in object_type_symbol.get_type_parameters ()) {
435 type_fun.add_parameter (new CCodeParameter ("%s_type".printf (type_param.name.down ()), "DovaType *"));
439 type_fun.block = new CCodeBlock ();
441 var type_init_block = new CCodeBlock ();
443 if (base_class == null) {
444 var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
445 sizeof_call.add_argument (new CCodeIdentifier ("%sPrivate".printf (cl.get_cname ())));
447 var calloc_call = new CCodeFunctionCall (new CCodeIdentifier ("calloc"));
448 calloc_call.add_argument (new CCodeConstant ("1"));
449 calloc_call.add_argument (new CCodeConstant ("sizeof (anyPrivate) + sizeof (DovaObjectPrivate) + sizeof (DovaTypePrivate) + sizeof (anyTypePrivate)"));
451 type_init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("%s_type".printf (cl.get_lower_case_cname ())), calloc_call)));
453 var set_size = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_set_object_size"));
454 set_size.add_argument (new CCodeIdentifier ("%s_type".printf (cl.get_lower_case_cname ())));
455 set_size.add_argument (sizeof_call);
456 type_init_block.add_statement (new CCodeExpressionStatement (set_size));
458 type_init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_any_type_offset"), new CCodeConstant ("sizeof (any) + sizeof (DovaObjectPrivate) + sizeof (DovaTypePrivate)"))));
460 set_size = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_set_type_size"));
461 set_size.add_argument (new CCodeIdentifier ("%s_type".printf (cl.get_lower_case_cname ())));
462 set_size.add_argument (new CCodeConstant ("sizeof (any) + sizeof (DovaObjectPrivate) + sizeof (DovaTypePrivate) + sizeof (anyTypePrivate)"));
463 type_init_block.add_statement (new CCodeExpressionStatement (set_size));
465 type_init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("%s_type".printf (cl.get_lower_case_cname ())), "type"), new CCodeFunctionCall (new CCodeIdentifier ("dova_type_type_get")))));
466 } else {
467 generate_method_declaration ((Method) object_class.scope.lookup ("alloc"), cfile);
468 generate_method_declaration ((Method) type_class.scope.lookup ("alloc"), cfile);
470 var base_type = new CCodeFunctionCall (new CCodeIdentifier ("%s_type_get".printf (base_class.get_lower_case_cname ())));
471 for (int i = 0; i < base_class.get_type_parameters ().size; i++) {
472 base_type.add_argument (new CCodeConstant ("NULL"));
475 var alloc_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_alloc"));
476 alloc_call.add_argument (base_type);
477 if (!(cl is Class) || has_instance_struct ((Class) cl)) {
478 alloc_call.add_argument (new CCodeConstant ("sizeof (%sPrivate)".printf (cl.get_cname ())));
479 } else {
480 alloc_call.add_argument (new CCodeConstant ("0"));
482 if ((!(cl is Class) || has_type_struct ((Class) cl)) && !(cl is Delegate)) {
483 alloc_call.add_argument (new CCodeConstant ("sizeof (%sTypePrivate)".printf (cl.get_cname ())));
484 } else {
485 alloc_call.add_argument (new CCodeConstant ("0"));
487 alloc_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("%s_type".printf (cl.get_lower_case_cname ()))));
488 alloc_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_%s_object_offset".printf (cl.get_lower_case_cname ()))));
489 alloc_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_%s_type_offset".printf (cl.get_lower_case_cname ()))));
491 type_init_block.add_statement (new CCodeExpressionStatement (alloc_call));
494 var type_init_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_type_init".printf (cl.get_lower_case_cname ())));
495 type_init_call.add_argument (new CCodeIdentifier ("%s_type".printf (cl.get_lower_case_cname ())));
497 if (object_type_symbol != null) {
498 for (int i = 0; i < object_type_symbol.get_type_parameters ().size; i++) {
499 type_init_call.add_argument (new CCodeConstant ("NULL"));
503 type_init_block.add_statement (new CCodeExpressionStatement (type_init_call));
505 type_fun.block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("%s_type".printf (cl.get_lower_case_cname ()))), type_init_block));
507 if (object_type_symbol != null && object_type_symbol.get_type_parameters ().size > 0) {
508 // generics
509 var specialized_type_get_block = new CCodeBlock ();
511 generate_property_accessor_declaration (((Property) type_class.scope.lookup ("next_type")).get_accessor, cfile);
512 generate_method_declaration ((Method) type_class.scope.lookup ("insert_type"), cfile);
514 var first = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_get_next_type"));
515 first.add_argument (new CCodeIdentifier ("%s_type".printf (cl.get_lower_case_cname ())));
517 cdecl = new CCodeDeclaration ("DovaType *");
518 cdecl.add_declarator (new CCodeVariableDeclarator ("result", first));
519 specialized_type_get_block.add_statement (cdecl);
521 var next = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_get_next_type"));
522 next.add_argument (new CCodeIdentifier ("result"));
524 var next_check = new CCodeBlock ();
525 next_check.add_statement (new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeMemberAccess.pointer (get_type_private_from_type (object_type_symbol, new CCodeIdentifier ("result")), "%s_type".printf (object_type_symbol.get_type_parameters ().get (0).name.down ())), new CCodeIdentifier ("%s_type".printf (object_type_symbol.get_type_parameters ().get (0).name.down ()))), new CCodeBreakStatement ()));
526 next_check.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), next)));
528 specialized_type_get_block.add_statement (new CCodeWhileStatement (new CCodeIdentifier ("result"), next_check));
530 var specialized_type_init_block = new CCodeBlock ();
532 generate_method_declaration ((Method) type_class.scope.lookup ("alloc"), cfile);
534 var base_type = new CCodeFunctionCall (new CCodeIdentifier ("%s_type_get".printf (base_class.get_lower_case_cname ())));
535 if (base_class_type != null) {
536 foreach (var type_arg in base_class_type.get_type_arguments ()) {
537 base_type.add_argument (get_type_id_expression (type_arg, true));
541 var alloc_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_alloc"));
542 alloc_call.add_argument (base_type);
543 if (!(cl is Class) || has_instance_struct ((Class) cl)) {
544 alloc_call.add_argument (new CCodeConstant ("sizeof (%sPrivate)".printf (cl.get_cname ())));
545 } else {
546 alloc_call.add_argument (new CCodeConstant ("0"));
548 if (!(cl is Class) || has_type_struct ((Class) cl)) {
549 alloc_call.add_argument (new CCodeConstant ("sizeof (%sTypePrivate)".printf (cl.get_cname ())));
550 } else {
551 alloc_call.add_argument (new CCodeConstant ("0"));
553 alloc_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
554 alloc_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_%s_object_offset".printf (cl.get_lower_case_cname ()))));
555 alloc_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_%s_type_offset".printf (cl.get_lower_case_cname ()))));
557 specialized_type_init_block.add_statement (new CCodeExpressionStatement (alloc_call));
559 type_init_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_type_init".printf (cl.get_lower_case_cname ())));
560 type_init_call.add_argument (new CCodeIdentifier ("result"));
562 foreach (var type_param in object_type_symbol.get_type_parameters ()) {
563 type_init_call.add_argument (new CCodeIdentifier ("%s_type".printf (type_param.name.down ())));
566 specialized_type_init_block.add_statement (new CCodeExpressionStatement (type_init_call));
568 var insert_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_insert_type"));
569 insert_call.add_argument (new CCodeIdentifier ("%s_type".printf (cl.get_lower_case_cname ())));
570 insert_call.add_argument (new CCodeIdentifier ("result"));
571 specialized_type_init_block.add_statement (new CCodeExpressionStatement (insert_call));
573 specialized_type_get_block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("result")), specialized_type_init_block));
575 specialized_type_get_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
577 type_fun.block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("%s_type".printf (object_type_symbol.get_type_parameters ().get (0).name.down ())), specialized_type_get_block));
580 type_fun.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("%s_type".printf (cl.get_lower_case_cname ()))));
582 cfile.add_function (type_fun);
584 var type_init_fun = new CCodeFunction ("%s_type_init".printf (cl.get_lower_case_cname ()));
585 if (cl.is_internal_symbol ()) {
586 type_init_fun.modifiers = CCodeModifiers.STATIC;
588 type_init_fun.add_parameter (new CCodeParameter ("type", "DovaType *"));
589 if (object_type_symbol != null) {
590 foreach (var type_param in object_type_symbol.get_type_parameters ()) {
591 type_init_fun.add_parameter (new CCodeParameter ("%s_type".printf (type_param.name.down ()), "DovaType *"));
594 type_init_fun.block = new CCodeBlock ();
596 if (base_class == null || cl == object_class || cl == value_class || cl == string_class) {
597 var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
598 sizeof_call.add_argument (new CCodeIdentifier ("void *"));
600 var set_size = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_set_value_size"));
601 set_size.add_argument (new CCodeIdentifier ("type"));
602 set_size.add_argument (sizeof_call);
603 type_init_fun.block.add_statement (new CCodeExpressionStatement (set_size));
605 declare_set_value_copy_function (cfile);
607 var value_copy_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_set_value_copy"));
608 value_copy_call.add_argument (new CCodeIdentifier ("type"));
609 value_copy_call.add_argument (new CCodeCastExpression (new CCodeIdentifier ("%s_copy".printf (cl.get_lower_case_cname ())), "void (*)(void *, intptr_t, void *, intptr_t)"));
610 type_init_fun.block.add_statement (new CCodeExpressionStatement (value_copy_call));
612 var function = new CCodeFunction ("%s_copy".printf (cl.get_lower_case_cname ()), "void");
613 function.modifiers = CCodeModifiers.STATIC;
614 function.add_parameter (new CCodeParameter ("dest", "any **"));
615 function.add_parameter (new CCodeParameter ("dest_index", "intptr_t"));
616 function.add_parameter (new CCodeParameter ("src", "any **"));
617 function.add_parameter (new CCodeParameter ("src_index", "intptr_t"));
619 function.block = new CCodeBlock ();
620 var cfrag = new CCodeFragment ();
621 function.block.add_statement (cfrag);
623 var dest = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("dest"), new CCodeIdentifier ("dest_index"));
624 var src = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("src"), new CCodeIdentifier ("src_index"));
626 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_unref".printf (cl.get_lower_case_cname ())));
627 unref_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, dest));
628 var unref_block = new CCodeBlock ();
629 unref_block.add_statement (new CCodeExpressionStatement (unref_call));
630 unref_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, dest), new CCodeConstant ("NULL"))));
631 function.block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, dest), unref_block));
633 var ref_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_ref".printf (cl.get_lower_case_cname ())));
634 ref_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, src));
635 var ref_block = new CCodeBlock ();
636 ref_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, dest), ref_call)));
637 function.block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("src"), ref_block));
639 cfile.add_function (function);
642 var value_equals_fun = new CCodeFunction ("%s_value_equals".printf (cl.get_lower_case_cname ()), "bool");
643 value_equals_fun.modifiers = CCodeModifiers.STATIC;
644 value_equals_fun.add_parameter (new CCodeParameter ("value", cl.get_cname () + "**"));
645 value_equals_fun.add_parameter (new CCodeParameter ("value_index", "intptr_t"));
646 value_equals_fun.add_parameter (new CCodeParameter ("other", cl.get_cname () + "**"));
647 value_equals_fun.add_parameter (new CCodeParameter ("other_index", "intptr_t"));
648 value_equals_fun.block = new CCodeBlock ();
649 var val = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("value"), new CCodeIdentifier ("value_index"));
650 var other = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("other"), new CCodeIdentifier ("other_index"));
651 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("any_equals"));
652 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, val));
653 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, other));
654 value_equals_fun.block.add_statement (new CCodeReturnStatement (ccall));
655 cfile.add_function (value_equals_fun);
657 declare_set_value_equals_function (cfile);
659 var value_equals_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_set_value_equals"));
660 value_equals_call.add_argument (new CCodeIdentifier ("type"));
661 value_equals_call.add_argument (new CCodeCastExpression (new CCodeIdentifier ("%s_value_equals".printf (cl.get_lower_case_cname ())), "bool (*)(void *, intptr_t, void *, intptr_t)"));
662 type_init_fun.block.add_statement (new CCodeExpressionStatement (value_equals_call));
666 var value_hash_fun = new CCodeFunction ("%s_value_hash".printf (cl.get_lower_case_cname ()), "uintptr_t");
667 value_hash_fun.modifiers = CCodeModifiers.STATIC;
668 value_hash_fun.add_parameter (new CCodeParameter ("value", cl.get_cname () + "**"));
669 value_hash_fun.add_parameter (new CCodeParameter ("value_index", "intptr_t"));
670 value_hash_fun.block = new CCodeBlock ();
671 var val = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("value"), new CCodeIdentifier ("value_index"));
672 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("any_hash"));
673 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, val));
674 value_hash_fun.block.add_statement (new CCodeReturnStatement (ccall));
675 cfile.add_function (value_hash_fun);
677 declare_set_value_hash_function (cfile);
679 var value_hash_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_set_value_hash"));
680 value_hash_call.add_argument (new CCodeIdentifier ("type"));
681 value_hash_call.add_argument (new CCodeCastExpression (new CCodeIdentifier ("%s_value_hash".printf (cl.get_lower_case_cname ())), "uintptr_t (*)(void *, intptr_t)"));
682 type_init_fun.block.add_statement (new CCodeExpressionStatement (value_hash_call));
685 // generate method to box value
686 var value_to_any_fun = new CCodeFunction ("%s_value_to_any".printf (cl.get_lower_case_cname ()), "any*");
687 value_to_any_fun.modifiers = CCodeModifiers.STATIC;
688 value_to_any_fun.add_parameter (new CCodeParameter ("value", cl.get_cname () + "**"));
689 value_to_any_fun.add_parameter (new CCodeParameter ("value_index", "intptr_t"));
690 value_to_any_fun.block = new CCodeBlock ();
691 var val = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("value"), new CCodeIdentifier ("value_index"));
692 string to_any_fun = "%s_ref".printf (cl.get_lower_case_cname ());
693 if (cl == string_class) {
694 to_any_fun = "string_to_any";
696 var ccall = new CCodeFunctionCall (new CCodeIdentifier (to_any_fun));
697 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, val));
698 value_to_any_fun.block.add_statement (new CCodeReturnStatement (ccall));
699 cfile.add_function (value_to_any_fun);
701 declare_set_value_to_any_function (cfile);
703 var value_to_any_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_set_value_to_any"));
704 value_to_any_call.add_argument (new CCodeIdentifier ("type"));
705 value_to_any_call.add_argument (new CCodeIdentifier ("%s_value_to_any".printf (cl.get_lower_case_cname ())));
706 type_init_fun.block.add_statement (new CCodeExpressionStatement (value_to_any_call));
708 // generate method to unbox value
709 var value_from_any_fun = new CCodeFunction ("%s_value_from_any".printf (cl.get_lower_case_cname ()));
710 value_from_any_fun.modifiers = CCodeModifiers.STATIC;
711 value_from_any_fun.add_parameter (new CCodeParameter ("any_", "any *"));
712 value_from_any_fun.add_parameter (new CCodeParameter ("value", cl.get_cname () + "**"));
713 value_from_any_fun.add_parameter (new CCodeParameter ("value_index", "intptr_t"));
714 value_from_any_fun.block = new CCodeBlock ();
715 string from_any_fun = "%s_ref".printf (cl.get_lower_case_cname ());
716 if (cl == string_class) {
717 from_any_fun = "string_from_any";
719 ccall = new CCodeFunctionCall (new CCodeIdentifier (from_any_fun));
720 ccall.add_argument (new CCodeIdentifier ("any_"));
721 value_from_any_fun.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, val), ccall)));
722 value_from_any_fun.block.add_statement (new CCodeReturnStatement (ccall));
723 cfile.add_function (value_from_any_fun);
725 declare_set_value_from_any_function (cfile);
727 var value_from_any_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_set_value_from_any"));
728 value_from_any_call.add_argument (new CCodeIdentifier ("type"));
729 value_from_any_call.add_argument (new CCodeIdentifier ("%s_value_from_any".printf (cl.get_lower_case_cname ())));
730 type_init_fun.block.add_statement (new CCodeExpressionStatement (value_from_any_call));
731 } else {
732 type_init_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_type_init".printf (base_class.get_lower_case_cname ())));
733 type_init_call.add_argument (new CCodeIdentifier ("type"));
735 if (base_class_type != null) {
736 foreach (var type_arg in base_class_type.get_type_arguments ()) {
737 type_init_call.add_argument (get_type_id_expression (type_arg, true));
741 type_init_fun.block.add_statement (new CCodeExpressionStatement (type_init_call));
743 if (object_type_symbol != null) {
744 foreach (var type_param in object_type_symbol.get_type_parameters ()) {
745 type_init_fun.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_type_private_from_type (object_type_symbol, new CCodeIdentifier ("type")), "%s_type".printf (type_param.name.down ())), new CCodeIdentifier ("%s_type".printf (type_param.name.down ())))));
750 cfile.add_function (type_init_fun);
752 return type_init_fun.block;
755 void add_finalize_function (Class cl) {
756 var function = new CCodeFunction ("%sfinalize".printf (cl.get_lower_case_cprefix ()), "void");
757 function.modifiers = CCodeModifiers.STATIC;
759 function.add_parameter (new CCodeParameter ("this", cl.get_cname () + "*"));
761 push_function (function);
763 cfile.add_function_declaration (function);
765 if (cl.destructor != null) {
766 cl.destructor.body.emit (this);
769 foreach (var f in cl.get_fields ()) {
770 if (f.binding == MemberBinding.INSTANCE) {
771 CCodeExpression lhs = null;
772 if (f.is_internal_symbol ()) {
773 var priv_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (cl.get_upper_case_cname (null))));
774 priv_call.add_argument (new CCodeIdentifier ("this"));
775 lhs = new CCodeMemberAccess.pointer (priv_call, f.get_cname ());
776 } else {
777 lhs = new CCodeMemberAccess.pointer (new CCodeIdentifier ("this"), f.get_cname ());
780 if (requires_destroy (f.variable_type)) {
781 var this_access = new MemberAccess.simple ("this");
782 this_access.value_type = get_data_type_for_symbol ((TypeSymbol) f.parent_symbol);
784 var field_st = f.parent_symbol as Struct;
785 if (field_st != null && !field_st.is_simple_type ()) {
786 set_cvalue (this_access, new CCodeIdentifier ("(*this)"));
787 } else {
788 set_cvalue (this_access, new CCodeIdentifier ("this"));
791 var ma = new MemberAccess (this_access, f.name);
792 ma.symbol_reference = f;
793 ccode.add_expression (get_unref_expression (lhs, f.variable_type, ma));
798 // chain up to finalize function of the base class
799 foreach (DataType base_type in cl.get_base_types ()) {
800 var object_type = (ObjectType) base_type;
801 if (object_type.type_symbol is Class) {
802 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_base_finalize"));
803 var type_get_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_type_get".printf (object_type.type_symbol.get_lower_case_cname ())));
804 foreach (var type_arg in base_type.get_type_arguments ()) {
805 type_get_call.add_argument (get_type_id_expression (type_arg, false));
807 ccall.add_argument (type_get_call);
808 ccall.add_argument (new CCodeIdentifier ("this"));
809 ccode.add_statement (new CCodeExpressionStatement (ccall));
813 pop_function ();
815 cfile.add_function (function);
818 public override void visit_class (Class cl) {
819 push_context (new EmitContext (cl));
821 generate_class_declaration (cl, cfile);
822 generate_class_private_declaration (cl, cfile);
824 if (!cl.is_internal_symbol ()) {
825 generate_class_declaration (cl, header_file);
828 cl.accept_children (this);
830 var type_init_block = generate_type_get_function (cl, cl.base_class);
832 foreach (DataType base_type in cl.get_base_types ()) {
833 var object_type = (ObjectType) base_type;
834 if (object_type.type_symbol is Interface) {
835 generate_interface_declaration ((Interface) object_type.type_symbol, cfile);
837 var type_init_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_type_init".printf (object_type.type_symbol.get_lower_case_cname ())));
838 type_init_call.add_argument (new CCodeIdentifier ("type"));
839 foreach (var type_arg in base_type.get_type_arguments ()) {
840 type_init_call.add_argument (get_type_id_expression (type_arg, true));
842 type_init_block.add_statement (new CCodeExpressionStatement (type_init_call));
846 // finalizer
847 if (cl.base_class != null && !cl.is_fundamental () && (cl.get_fields ().size > 0 || cl.destructor != null)) {
848 add_finalize_function (cl);
850 generate_method_declaration ((Method) object_class.scope.lookup ("finalize"), cfile);
852 var override_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_override_finalize"));
853 override_call.add_argument (new CCodeIdentifier ("type"));
854 override_call.add_argument (new CCodeIdentifier ("%sfinalize".printf (cl.get_lower_case_cprefix ())));
855 type_init_block.add_statement (new CCodeExpressionStatement (override_call));
858 foreach (Method m in cl.get_methods ()) {
859 if (m.is_virtual || m.overrides) {
860 var override_call = new CCodeFunctionCall (new CCodeIdentifier ("%soverride_%s".printf (m.base_method.parent_symbol.get_lower_case_cprefix (), m.name)));
861 override_call.add_argument (new CCodeIdentifier ("type"));
862 override_call.add_argument (new CCodeIdentifier (m.get_real_cname ()));
863 type_init_block.add_statement (new CCodeExpressionStatement (override_call));
864 } else if (m.base_interface_method != null) {
865 var override_call = new CCodeFunctionCall (new CCodeIdentifier ("%soverride_%s".printf (m.base_interface_method.parent_symbol.get_lower_case_cprefix (), m.name)));
866 override_call.add_argument (new CCodeIdentifier ("type"));
867 override_call.add_argument (new CCodeIdentifier (m.get_real_cname ()));
868 type_init_block.add_statement (new CCodeExpressionStatement (override_call));
872 foreach (Property prop in cl.get_properties ()) {
873 if (prop.is_virtual || prop.overrides) {
874 if (prop.get_accessor != null) {
875 var override_call = new CCodeFunctionCall (new CCodeIdentifier ("%soverride_get_%s".printf (prop.base_property.parent_symbol.get_lower_case_cprefix (), prop.name)));
876 override_call.add_argument (new CCodeIdentifier ("type"));
877 override_call.add_argument (new CCodeIdentifier (prop.get_accessor.get_cname ()));
878 type_init_block.add_statement (new CCodeExpressionStatement (override_call));
880 if (prop.set_accessor != null) {
881 var override_call = new CCodeFunctionCall (new CCodeIdentifier ("%soverride_set_%s".printf (prop.base_property.parent_symbol.get_lower_case_cprefix (), prop.name)));
882 override_call.add_argument (new CCodeIdentifier ("type"));
883 override_call.add_argument (new CCodeIdentifier (prop.set_accessor.get_cname ()));
884 type_init_block.add_statement (new CCodeExpressionStatement (override_call));
889 if (cl == type_class) {
890 var priv_call = new CCodeFunctionCall (new CCodeIdentifier ("DOVA_TYPE_GET_PRIVATE"));
891 priv_call.add_argument (new CCodeIdentifier ("type"));
893 var value_copy_function = new CCodeFunction ("dova_type_value_copy");
894 value_copy_function.add_parameter (new CCodeParameter ("type", "DovaType *"));
895 value_copy_function.add_parameter (new CCodeParameter ("dest", "void *"));
896 value_copy_function.add_parameter (new CCodeParameter ("dest_index", "intptr_t"));
897 value_copy_function.add_parameter (new CCodeParameter ("src", "void *"));
898 value_copy_function.add_parameter (new CCodeParameter ("src_index", "intptr_t"));
900 value_copy_function.block = new CCodeBlock ();
902 var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (priv_call, "value_copy"));
903 ccall.add_argument (new CCodeIdentifier ("dest"));
904 ccall.add_argument (new CCodeIdentifier ("dest_index"));
905 ccall.add_argument (new CCodeIdentifier ("src"));
906 ccall.add_argument (new CCodeIdentifier ("src_index"));
907 value_copy_function.block.add_statement (new CCodeExpressionStatement (ccall));
909 cfile.add_function (value_copy_function);
911 declare_set_value_copy_function (cfile);
912 declare_set_value_copy_function (header_file);
913 cfile.add_function (create_set_value_copy_function ());
915 var value_equals_function = new CCodeFunction ("dova_type_value_equals", "bool");
916 value_equals_function.add_parameter (new CCodeParameter ("type", "DovaType *"));
917 value_equals_function.add_parameter (new CCodeParameter ("value", "void *"));
918 value_equals_function.add_parameter (new CCodeParameter ("value_index", "intptr_t"));
919 value_equals_function.add_parameter (new CCodeParameter ("other", "void *"));
920 value_equals_function.add_parameter (new CCodeParameter ("other_index", "intptr_t"));
922 value_equals_function.block = new CCodeBlock ();
924 ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (priv_call, "value_equals"));
925 ccall.add_argument (new CCodeIdentifier ("value"));
926 ccall.add_argument (new CCodeIdentifier ("value_index"));
927 ccall.add_argument (new CCodeIdentifier ("other"));
928 ccall.add_argument (new CCodeIdentifier ("other_index"));
929 value_equals_function.block.add_statement (new CCodeReturnStatement (ccall));
931 cfile.add_function (value_equals_function);
933 declare_set_value_equals_function (cfile);
934 declare_set_value_equals_function (header_file);
935 cfile.add_function (create_set_value_equals_function ());
937 var value_hash_function = new CCodeFunction ("dova_type_value_hash", "uintptr_t");
938 value_hash_function.add_parameter (new CCodeParameter ("type", "DovaType *"));
939 value_hash_function.add_parameter (new CCodeParameter ("value", "void *"));
940 value_hash_function.add_parameter (new CCodeParameter ("value_index", "intptr_t"));
942 value_hash_function.block = new CCodeBlock ();
944 ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (priv_call, "value_hash"));
945 ccall.add_argument (new CCodeIdentifier ("value"));
946 ccall.add_argument (new CCodeIdentifier ("value_index"));
947 value_hash_function.block.add_statement (new CCodeReturnStatement (ccall));
949 cfile.add_function (value_hash_function);
951 declare_set_value_hash_function (cfile);
952 declare_set_value_hash_function (header_file);
953 cfile.add_function (create_set_value_hash_function ());
955 var value_to_any_function = new CCodeFunction ("dova_type_value_to_any", "DovaObject *");
956 value_to_any_function.add_parameter (new CCodeParameter ("type", "DovaType *"));
957 value_to_any_function.add_parameter (new CCodeParameter ("value", "void *"));
958 value_to_any_function.add_parameter (new CCodeParameter ("value_index", "intptr_t"));
960 value_to_any_function.block = new CCodeBlock ();
962 ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (priv_call, "value_to_any"));
963 ccall.add_argument (new CCodeIdentifier ("value"));
964 ccall.add_argument (new CCodeIdentifier ("value_index"));
965 value_to_any_function.block.add_statement (new CCodeReturnStatement (ccall));
967 cfile.add_function (value_to_any_function);
969 declare_set_value_to_any_function (cfile);
970 declare_set_value_to_any_function (header_file);
971 cfile.add_function (create_set_value_to_any_function ());
973 var value_from_any_function = new CCodeFunction ("dova_type_value_from_any", "void");
974 value_from_any_function.add_parameter (new CCodeParameter ("type", "DovaType *"));
975 value_from_any_function.add_parameter (new CCodeParameter ("any_", "any *"));
976 value_from_any_function.add_parameter (new CCodeParameter ("value", "void *"));
977 value_from_any_function.add_parameter (new CCodeParameter ("value_index", "intptr_t"));
979 value_from_any_function.block = new CCodeBlock ();
981 ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (priv_call, "value_from_any"));
982 ccall.add_argument (new CCodeIdentifier ("any_"));
983 ccall.add_argument (new CCodeIdentifier ("value"));
984 ccall.add_argument (new CCodeIdentifier ("value_index"));
985 value_from_any_function.block.add_statement (new CCodeReturnStatement (ccall));
987 cfile.add_function (value_from_any_function);
989 declare_set_value_from_any_function (cfile);
990 declare_set_value_from_any_function (header_file);
991 cfile.add_function (create_set_value_from_any_function ());
994 pop_context ();
997 public override void visit_interface (Interface iface) {
998 push_context (new EmitContext (iface));
1000 generate_interface_declaration (iface, cfile);
1002 var type_priv_struct = new CCodeStruct ("_%sTypePrivate".printf (iface.get_cname ()));
1004 foreach (var type_param in iface.get_type_parameters ()) {
1005 var type_param_decl = new CCodeDeclaration ("DovaType *");
1006 type_param_decl.add_declarator (new CCodeVariableDeclarator ("%s_type".printf (type_param.name.down ())));
1007 type_priv_struct.add_declaration (type_param_decl);
1010 foreach (Method m in iface.get_methods ()) {
1011 generate_virtual_method_declaration (m, cfile, type_priv_struct);
1014 if (!type_priv_struct.is_empty) {
1015 cfile.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_priv_struct.name), new CCodeVariableDeclarator ("%sTypePrivate".printf (iface.get_cname ()))));
1016 cfile.add_type_definition (type_priv_struct);
1019 var cdecl = new CCodeDeclaration ("DovaType *");
1020 cdecl.add_declarator (new CCodeVariableDeclarator ("%s_type".printf (iface.get_lower_case_cname ()), new CCodeConstant ("NULL")));
1021 cdecl.modifiers = CCodeModifiers.STATIC;
1022 cfile.add_type_member_declaration (cdecl);
1024 var type_fun = new CCodeFunction ("%s_type_get".printf (iface.get_lower_case_cname ()), "DovaType *");
1025 if (iface.is_internal_symbol ()) {
1026 type_fun.modifiers = CCodeModifiers.STATIC;
1028 foreach (var type_param in iface.get_type_parameters ()) {
1029 type_fun.add_parameter (new CCodeParameter ("%s_type".printf (type_param.name.down ()), "DovaType *"));
1031 type_fun.block = new CCodeBlock ();
1033 var type_init_block = new CCodeBlock ();
1035 var calloc_call = new CCodeFunctionCall (new CCodeIdentifier ("calloc"));
1036 calloc_call.add_argument (new CCodeConstant ("1"));
1038 if (!type_priv_struct.is_empty) {
1039 calloc_call.add_argument (new CCodeConstant ("dova_type_get_type_size (dova_type_type_get ()) + sizeof (%sTypePrivate)".printf (iface.get_cname ())));
1040 } else {
1041 calloc_call.add_argument (new CCodeConstant ("dova_type_get_type_size (dova_type_type_get ())"));
1044 type_init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("%s_type".printf (iface.get_lower_case_cname ())), calloc_call)));
1046 // call any_type_init to set value_copy and similar functions
1047 var any_type_init_call = new CCodeFunctionCall (new CCodeIdentifier ("any_type_init"));
1048 any_type_init_call.add_argument (new CCodeIdentifier ("%s_type".printf (iface.get_lower_case_cname ())));
1049 type_init_block.add_statement (new CCodeExpressionStatement (any_type_init_call));
1051 var type_init_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_type_init".printf (iface.get_lower_case_cname ())));
1052 type_init_call.add_argument (new CCodeIdentifier ("%s_type".printf (iface.get_lower_case_cname ())));
1053 foreach (var type_param in iface.get_type_parameters ()) {
1054 type_init_call.add_argument (new CCodeIdentifier ("%s_type".printf (type_param.name.down ())));
1056 type_init_block.add_statement (new CCodeExpressionStatement (type_init_call));
1058 type_fun.block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("%s_type".printf (iface.get_lower_case_cname ()))), type_init_block));
1060 type_fun.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("%s_type".printf (iface.get_lower_case_cname ()))));
1062 cfile.add_function (type_fun);
1064 var type_init_fun = new CCodeFunction ("%s_type_init".printf (iface.get_lower_case_cname ()));
1065 if (iface.is_internal_symbol ()) {
1066 type_init_fun.modifiers = CCodeModifiers.STATIC;
1068 type_init_fun.add_parameter (new CCodeParameter ("type", "DovaType *"));
1069 foreach (var type_param in iface.get_type_parameters ()) {
1070 type_init_fun.add_parameter (new CCodeParameter ("%s_type".printf (type_param.name.down ()), "DovaType *"));
1072 type_init_fun.block = new CCodeBlock ();
1074 foreach (DataType base_type in iface.get_prerequisites ()) {
1075 var object_type = (ObjectType) base_type;
1076 if (object_type.type_symbol is Interface) {
1077 type_init_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_type_init".printf (object_type.type_symbol.get_lower_case_cname ())));
1078 type_init_call.add_argument (new CCodeIdentifier ("type"));
1079 type_init_fun.block.add_statement (new CCodeExpressionStatement (type_init_call));
1083 var vtable_alloc = new CCodeFunctionCall (new CCodeIdentifier ("calloc"));
1084 vtable_alloc.add_argument (new CCodeConstant ("1"));
1085 vtable_alloc.add_argument (new CCodeConstant ("sizeof (%sTypePrivate)".printf (iface.get_cname ())));
1087 var type_get_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_type_get".printf (iface.get_lower_case_cname ())));
1088 foreach (var type_param in iface.get_type_parameters ()) {
1089 type_get_call.add_argument (new CCodeIdentifier ("%s_type".printf (type_param.name.down ())));
1092 if (!type_priv_struct.is_empty) {
1093 var add_interface_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_add_interface"));
1094 add_interface_call.add_argument (new CCodeIdentifier ("type"));
1095 add_interface_call.add_argument (type_get_call);
1096 add_interface_call.add_argument (vtable_alloc);
1097 type_init_fun.block.add_statement (new CCodeExpressionStatement (add_interface_call));
1100 cfile.add_function (type_init_fun);
1102 iface.accept_children (this);
1104 pop_context ();
1107 public override void generate_property_accessor_declaration (PropertyAccessor acc, CCodeFile decl_space) {
1108 if (add_symbol_declaration (decl_space, acc.prop, acc.get_cname ())) {
1109 return;
1112 var prop = (Property) acc.prop;
1114 generate_type_declaration (acc.value_type, decl_space);
1116 CCodeFunction function;
1118 if (acc.readable) {
1119 function = new CCodeFunction (acc.get_cname (), acc.value_type.get_cname ());
1120 } else {
1121 function = new CCodeFunction (acc.get_cname (), "void");
1124 if (prop.binding == MemberBinding.INSTANCE) {
1125 DataType this_type;
1126 if (prop.parent_symbol is Struct) {
1127 var st = (Struct) prop.parent_symbol;
1128 this_type = SemanticAnalyzer.get_data_type_for_symbol (st);
1129 } else {
1130 var t = (ObjectTypeSymbol) prop.parent_symbol;
1131 this_type = new ObjectType (t);
1134 generate_type_declaration (this_type, decl_space);
1135 var cselfparam = new CCodeParameter ("this", this_type.get_cname ());
1137 function.add_parameter (cselfparam);
1140 if (acc.writable) {
1141 var cvalueparam = new CCodeParameter ("value", acc.value_type.get_cname ());
1142 function.add_parameter (cvalueparam);
1145 if (prop.is_internal_symbol () || acc.is_internal_symbol ()) {
1146 function.modifiers |= CCodeModifiers.STATIC;
1148 decl_space.add_function_declaration (function);
1150 if (prop.is_abstract || prop.is_virtual) {
1151 string param_list = "(%s *this".printf (((ObjectTypeSymbol) prop.parent_symbol).get_cname ());
1152 if (!acc.readable) {
1153 param_list += ", ";
1154 param_list += acc.value_type.get_cname ();
1156 param_list += ")";
1158 var override_func = new CCodeFunction ("%soverride_%s_%s".printf (prop.parent_symbol.get_lower_case_cprefix (), acc.readable ? "get" : "set", prop.name));
1159 override_func.add_parameter (new CCodeParameter ("type", "DovaType *"));
1160 override_func.add_parameter (new CCodeParameter ("(*function) %s".printf (param_list), acc.readable ? acc.value_type.get_cname () : "void"));
1162 decl_space.add_function_declaration (override_func);
1166 public override void visit_property_accessor (PropertyAccessor acc) {
1167 push_context (new EmitContext (acc));
1169 var prop = (Property) acc.prop;
1171 // do not declare overriding properties and interface implementations
1172 if (prop.is_abstract || prop.is_virtual
1173 || (prop.base_property == null && prop.base_interface_property == null)) {
1174 generate_property_accessor_declaration (acc, cfile);
1176 if (!prop.is_internal_symbol ()
1177 && (acc.access == SymbolAccessibility.PUBLIC
1178 || acc.access == SymbolAccessibility.PROTECTED)) {
1179 generate_property_accessor_declaration (acc, header_file);
1183 DataType this_type;
1184 if (prop.parent_symbol is Struct) {
1185 var st = (Struct) prop.parent_symbol;
1186 this_type = SemanticAnalyzer.get_data_type_for_symbol (st);
1187 } else {
1188 var t = (ObjectTypeSymbol) prop.parent_symbol;
1189 this_type = new ObjectType (t);
1191 var cselfparam = new CCodeParameter ("this", this_type.get_cname ());
1192 var cvalueparam = new CCodeParameter ("value", acc.value_type.get_cname ());
1194 string cname = acc.get_cname ();
1196 if (prop.is_abstract || prop.is_virtual) {
1197 CCodeFunction function;
1198 if (acc.readable) {
1199 function = new CCodeFunction (acc.get_cname (), current_return_type.get_cname ());
1200 } else {
1201 function = new CCodeFunction (acc.get_cname (), "void");
1203 function.add_parameter (cselfparam);
1204 if (acc.writable) {
1205 function.add_parameter (cvalueparam);
1208 if (prop.is_internal_symbol () || !(acc.readable || acc.writable) || acc.is_internal_symbol ()) {
1209 // accessor function should be private if the property is an internal symbol
1210 function.modifiers |= CCodeModifiers.STATIC;
1213 push_function (function);
1215 var vcast = get_type_private_from_type ((ObjectTypeSymbol) prop.parent_symbol, get_type_from_instance (new CCodeIdentifier ("this")));
1217 if (acc.readable) {
1218 var vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, "get_%s".printf (prop.name)));
1219 vcall.add_argument (new CCodeIdentifier ("this"));
1220 ccode.add_return (vcall);
1221 } else {
1222 var vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, "set_%s".printf (prop.name)));
1223 vcall.add_argument (new CCodeIdentifier ("this"));
1224 vcall.add_argument (new CCodeIdentifier ("value"));
1225 ccode.add_expression (vcall);
1228 pop_function ();
1230 cfile.add_function (function);
1233 string param_list = "(%s *this".printf (((ObjectTypeSymbol) prop.parent_symbol).get_cname ());
1234 if (!acc.readable) {
1235 param_list += ", ";
1236 param_list += acc.value_type.get_cname ();
1238 param_list += ")";
1240 var override_func = new CCodeFunction ("%soverride_%s_%s".printf (prop.parent_symbol.get_lower_case_cprefix (), acc.readable ? "get" : "set", prop.name));
1241 override_func.add_parameter (new CCodeParameter ("type", "DovaType *"));
1242 override_func.add_parameter (new CCodeParameter ("(*function) %s".printf (param_list), acc.readable ? acc.value_type.get_cname () : "void"));
1244 push_function (override_func);
1246 vcast = get_type_private_from_type ((ObjectTypeSymbol) prop.parent_symbol, new CCodeIdentifier ("type"));
1248 ccode.add_assignment (new CCodeMemberAccess.pointer (vcast, "%s_%s".printf (acc.readable ? "get" : "set", prop.name)), new CCodeIdentifier ("function"));
1250 pop_function ();
1252 cfile.add_function (override_func);
1255 if (!prop.is_abstract) {
1256 CCodeFunction function;
1257 if (acc.writable) {
1258 function = new CCodeFunction (cname, "void");
1259 } else {
1260 function = new CCodeFunction (cname, acc.value_type.get_cname ());
1263 if (prop.binding == MemberBinding.INSTANCE) {
1264 function.add_parameter (cselfparam);
1266 if (acc.writable) {
1267 function.add_parameter (cvalueparam);
1270 if (prop.is_internal_symbol () || !(acc.readable || acc.writable) || acc.is_internal_symbol ()) {
1271 // accessor function should be private if the property is an internal symbol
1272 function.modifiers |= CCodeModifiers.STATIC;
1275 push_function (function);
1277 if (acc.result_var != null) {
1278 acc.result_var.accept (this);
1281 acc.body.emit (this);
1283 if (acc.readable) {
1284 var cdecl = new CCodeDeclaration (acc.value_type.get_cname ());
1285 cdecl.add_declarator (new CCodeVariableDeclarator.zero ("result", default_value_for_type (acc.value_type, true)));
1286 function.block.prepend_statement (cdecl);
1288 function.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
1291 cfile.add_function (function);
1294 pop_context ();
1297 public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
1298 if (add_symbol_declaration (decl_space, iface, iface.get_cname ())) {
1299 return;
1302 // typedef to DovaObject instead of dummy struct to avoid warnings/casts
1303 generate_class_declaration (object_class, decl_space);
1304 decl_space.add_type_declaration (new CCodeTypeDefinition ("DovaObject", new CCodeVariableDeclarator (iface.get_cname ())));
1306 generate_class_declaration (type_class, decl_space);
1308 var type_fun = new CCodeFunction ("%s_type_get".printf (iface.get_lower_case_cname ()), "DovaType *");
1309 if (iface.is_internal_symbol ()) {
1310 type_fun.modifiers = CCodeModifiers.STATIC;
1312 foreach (var type_param in iface.get_type_parameters ()) {
1313 type_fun.add_parameter (new CCodeParameter ("%s_type".printf (type_param.name.down ()), "DovaType *"));
1315 decl_space.add_function_declaration (type_fun);
1317 var type_init_fun = new CCodeFunction ("%s_type_init".printf (iface.get_lower_case_cname ()));
1318 if (iface.is_internal_symbol ()) {
1319 type_init_fun.modifiers = CCodeModifiers.STATIC;
1321 type_init_fun.add_parameter (new CCodeParameter ("type", "DovaType *"));
1322 foreach (var type_param in iface.get_type_parameters ()) {
1323 type_init_fun.add_parameter (new CCodeParameter ("%s_type".printf (type_param.name.down ()), "DovaType *"));
1325 decl_space.add_function_declaration (type_init_fun);
1329 public override bool method_has_wrapper (Method method) {
1330 return (method.get_attribute ("NoWrapper") == null);
1333 public override string? get_custom_creturn_type (Method m) {
1334 var attr = m.get_attribute ("CCode");
1335 if (attr != null) {
1336 string type = attr.get_string ("type");
1337 if (type != null) {
1338 return type;
1341 return null;
1344 public override void generate_method_declaration (Method m, CCodeFile decl_space) {
1345 if (add_symbol_declaration (decl_space, m, m.get_cname ())) {
1346 return;
1349 var function = new CCodeFunction (m.get_cname ());
1351 if (m.is_internal_symbol ()) {
1352 function.modifiers |= CCodeModifiers.STATIC;
1353 if (m.is_inline) {
1354 function.modifiers |= CCodeModifiers.INLINE;
1358 generate_cparameters (m, decl_space, function, null, new CCodeFunctionCall (new CCodeIdentifier ("fake")));
1360 decl_space.add_function_declaration (function);
1362 if (m.is_abstract || m.is_virtual) {
1363 var base_func = function.copy ();
1364 base_func.name = "%sbase_%s".printf (m.parent_symbol.get_lower_case_cprefix (), m.name);
1365 base_func.insert_parameter (0, new CCodeParameter ("base_type", "DovaType *"));
1366 decl_space.add_function_declaration (base_func);
1368 string param_list = "(%s *this".printf (((ObjectTypeSymbol) m.parent_symbol).get_cname ());
1369 foreach (var param in m.get_parameters ()) {
1370 param_list += ", ";
1371 param_list += param.variable_type.get_cname ();
1373 if (m.return_type is GenericType) {
1374 param_list += ", void *";
1376 param_list += ")";
1378 var override_func = new CCodeFunction ("%soverride_%s".printf (m.parent_symbol.get_lower_case_cprefix (), m.name));
1379 override_func.add_parameter (new CCodeParameter ("type", "DovaType *"));
1380 override_func.add_parameter (new CCodeParameter ("(*function) %s".printf (param_list), (m.return_type is GenericType) ? "void" : m.return_type.get_cname ()));
1381 decl_space.add_function_declaration (override_func);
1384 if (m is CreationMethod && m.parent_symbol is Class) {
1385 generate_class_declaration ((Class) m.parent_symbol, decl_space);
1387 // _init function
1388 function = new CCodeFunction (m.get_real_cname ());
1390 if (m.is_internal_symbol ()) {
1391 function.modifiers |= CCodeModifiers.STATIC;
1394 generate_cparameters (m, decl_space, function);
1396 decl_space.add_function_declaration (function);
1400 CCodeExpression get_type_from_instance (CCodeExpression instance_expression) {
1401 return new CCodeMemberAccess.pointer (new CCodeCastExpression (instance_expression, "DovaObject *"), "type");
1404 public override void visit_method (Method m) {
1405 push_context (new EmitContext (m));
1407 foreach (Parameter param in m.get_parameters ()) {
1408 param.accept (this);
1411 foreach (Expression precondition in m.get_preconditions ()) {
1412 precondition.emit (this);
1415 foreach (Expression postcondition in m.get_postconditions ()) {
1416 postcondition.emit (this);
1420 generate_method_declaration (m, cfile);
1422 if (!m.is_internal_symbol ()) {
1423 generate_method_declaration (m, header_file);
1426 var function = new CCodeFunction (m.get_real_cname ());
1428 generate_cparameters (m, cfile, function);
1430 // generate *_real_* functions for virtual methods
1431 if (!m.is_abstract) {
1432 if (m.base_method != null || m.base_interface_method != null) {
1433 // declare *_real_* function
1434 function.modifiers |= CCodeModifiers.STATIC;
1435 cfile.add_function_declaration (function);
1436 } else if (m.is_internal_symbol ()) {
1437 function.modifiers |= CCodeModifiers.STATIC;
1440 if (m.body != null) {
1441 push_function (function);
1443 if (context.module_init_method == m) {
1444 add_module_init ();
1447 if (m.closure) {
1448 // add variables for parent closure blocks
1449 // as closures only have one parameter for the innermost closure block
1450 var closure_block = current_closure_block;
1451 int block_id = get_block_id (closure_block);
1452 while (true) {
1453 var parent_closure_block = next_closure_block (closure_block.parent_symbol);
1454 if (parent_closure_block == null) {
1455 break;
1457 int parent_block_id = get_block_id (parent_closure_block);
1459 var parent_data = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id));
1460 var cdecl = new CCodeDeclaration ("Block%dData*".printf (parent_block_id));
1461 cdecl.add_declarator (new CCodeVariableDeclarator ("_data%d_".printf (parent_block_id), parent_data));
1463 ccode.add_statement (cdecl);
1465 closure_block = parent_closure_block;
1466 block_id = parent_block_id;
1469 // add self variable for closures
1470 // as closures have block data parameter
1471 if (m.binding == MemberBinding.INSTANCE) {
1472 var cself = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "this");
1473 var cdecl = new CCodeDeclaration ("%s *".printf (current_class.get_cname ()));
1474 cdecl.add_declarator (new CCodeVariableDeclarator ("this", cself));
1476 ccode.add_statement (cdecl);
1479 foreach (Parameter param in m.get_parameters ()) {
1480 if (param.ellipsis) {
1481 break;
1484 var t = param.variable_type.data_type;
1485 if (t != null && t.is_reference_type ()) {
1486 if (param.direction == ParameterDirection.OUT) {
1487 // ensure that the passed reference for output parameter is cleared
1488 var a = new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (param.name)), new CCodeConstant ("NULL"));
1489 var cblock = new CCodeBlock ();
1490 cblock.add_statement (new CCodeExpressionStatement (a));
1492 var condition = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (param.name), new CCodeConstant ("NULL"));
1493 var if_statement = new CCodeIfStatement (condition, cblock);
1494 ccode.add_statement (if_statement);
1499 if (m.result_var != null) {
1500 m.result_var.accept (this);
1503 m.body.emit (this);
1505 if (!(m.return_type is VoidType) && !(m.return_type is GenericType)) {
1506 var cdecl = new CCodeDeclaration (m.return_type.get_cname ());
1507 cdecl.add_declarator (new CCodeVariableDeclarator.zero ("result", default_value_for_type (m.return_type, true)));
1508 ccode.add_statement (cdecl);
1510 ccode.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
1513 var st = m.parent_symbol as Struct;
1514 if (m is CreationMethod && st != null && (st.is_boolean_type () || st.is_integer_type () || st.is_floating_type ())) {
1515 var cdecl = new CCodeDeclaration (st.get_cname ());
1516 cdecl.add_declarator (new CCodeVariableDeclarator ("this", new CCodeConstant ("0")));
1517 ccode.add_statement (cdecl);
1519 ccode.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("this")));
1522 cfile.add_function (function);
1526 if (m.is_abstract || m.is_virtual) {
1527 generate_class_declaration ((Class) object_class, cfile);
1529 var vfunc = new CCodeFunction (m.get_cname (), (m.return_type is GenericType) ? "void" : m.return_type.get_cname ());
1530 vfunc.block = new CCodeBlock ();
1532 vfunc.add_parameter (new CCodeParameter ("this", "%s *".printf (((ObjectTypeSymbol) m.parent_symbol).get_cname ())));
1533 foreach (TypeParameter type_param in m.get_type_parameters ()) {
1534 vfunc.add_parameter (new CCodeParameter ("%s_type".printf (type_param.name.down ()), "DovaType*"));
1536 foreach (Parameter param in m.get_parameters ()) {
1537 string ctypename = param.variable_type.get_cname ();
1538 if (param.direction != ParameterDirection.IN) {
1539 ctypename += "*";
1541 vfunc.add_parameter (new CCodeParameter (param.name, ctypename));
1543 if (m.return_type is GenericType) {
1544 vfunc.add_parameter (new CCodeParameter ("result", "void *"));
1547 if (m.get_full_name () == "any.equals") {
1548 // make this null-safe
1549 var null_block = new CCodeBlock ();
1550 null_block.add_statement (new CCodeReturnStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("other"))));
1551 vfunc.block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("this")), null_block));
1552 } else if (m.get_full_name () == "any.hash") {
1553 // make this null-safe
1554 var null_block = new CCodeBlock ();
1555 null_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("0")));
1556 vfunc.block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("this")), null_block));
1557 } else if (m.get_full_name () == "any.to_string") {
1558 // make this null-safe
1559 var null_string = new CCodeFunctionCall (new CCodeIdentifier ("string_create_from_cstring"));
1560 null_string.add_argument (new CCodeConstant ("\"(null)\""));
1561 var null_block = new CCodeBlock ();
1562 null_block.add_statement (new CCodeReturnStatement (null_string));
1563 vfunc.block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("this")), null_block));
1566 var vcast = get_type_private_from_type ((ObjectTypeSymbol) m.parent_symbol, get_type_from_instance (new CCodeIdentifier ("this")));
1568 var vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, m.vfunc_name));
1569 vcall.add_argument (new CCodeIdentifier ("this"));
1570 foreach (TypeParameter type_param in m.get_type_parameters ()) {
1571 vcall.add_argument (new CCodeIdentifier ("%s_type".printf (type_param.name.down ())));
1573 foreach (Parameter param in m.get_parameters ()) {
1574 vcall.add_argument (new CCodeIdentifier (param.name));
1576 if (m.return_type is GenericType) {
1577 vcall.add_argument (new CCodeIdentifier ("result"));
1580 if (m.return_type is VoidType || m.return_type is GenericType) {
1581 vfunc.block.add_statement (new CCodeExpressionStatement (vcall));
1582 } else {
1583 vfunc.block.add_statement (new CCodeReturnStatement (vcall));
1586 cfile.add_function (vfunc);
1589 vfunc = new CCodeFunction ("%sbase_%s".printf (m.parent_symbol.get_lower_case_cprefix (), m.name), (m.return_type is GenericType) ? "void" : m.return_type.get_cname ());
1590 vfunc.block = new CCodeBlock ();
1592 vfunc.add_parameter (new CCodeParameter ("base_type", "DovaType *"));
1593 vfunc.add_parameter (new CCodeParameter ("this", "%s *".printf (((ObjectTypeSymbol) m.parent_symbol).get_cname ())));
1594 foreach (TypeParameter type_param in m.get_type_parameters ()) {
1595 vfunc.add_parameter (new CCodeParameter ("%s_type".printf (type_param.name.down ()), "DovaType*"));
1597 foreach (Parameter param in m.get_parameters ()) {
1598 string ctypename = param.variable_type.get_cname ();
1599 if (param.direction != ParameterDirection.IN) {
1600 ctypename += "*";
1602 vfunc.add_parameter (new CCodeParameter (param.name, ctypename));
1604 if (m.return_type is GenericType) {
1605 vfunc.add_parameter (new CCodeParameter ("result", "void *"));
1608 var base_type = new CCodeIdentifier ("base_type");
1610 vcast = get_type_private_from_type ((ObjectTypeSymbol) m.parent_symbol, base_type);
1612 vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, m.vfunc_name));
1613 vcall.add_argument (new CCodeIdentifier ("this"));
1614 foreach (TypeParameter type_param in m.get_type_parameters ()) {
1615 vcall.add_argument (new CCodeIdentifier ("%s_type".printf (type_param.name.down ())));
1617 foreach (Parameter param in m.get_parameters ()) {
1618 vcall.add_argument (new CCodeIdentifier (param.name));
1620 if (m.return_type is GenericType) {
1621 vcall.add_argument (new CCodeIdentifier ("result"));
1624 if (m.return_type is VoidType || m.return_type is GenericType) {
1625 vfunc.block.add_statement (new CCodeExpressionStatement (vcall));
1626 } else {
1627 vfunc.block.add_statement (new CCodeReturnStatement (vcall));
1630 cfile.add_function (vfunc);
1633 string param_list = "(%s *this".printf (((ObjectTypeSymbol) m.parent_symbol).get_cname ());
1634 foreach (var param in m.get_parameters ()) {
1635 param_list += ", ";
1636 param_list += param.variable_type.get_cname ();
1638 if (m.return_type is GenericType) {
1639 param_list += ", void *";
1641 param_list += ")";
1643 var override_func = new CCodeFunction ("%soverride_%s".printf (m.parent_symbol.get_lower_case_cprefix (), m.name));
1644 override_func.add_parameter (new CCodeParameter ("type", "DovaType *"));
1645 override_func.add_parameter (new CCodeParameter ("(*function) %s".printf (param_list), (m.return_type is GenericType) ? "void" : m.return_type.get_cname ()));
1646 override_func.block = new CCodeBlock ();
1648 vcast = get_type_private_from_type ((ObjectTypeSymbol) m.parent_symbol, new CCodeIdentifier ("type"));
1650 override_func.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (vcast, m.name), new CCodeIdentifier ("function"))));
1652 cfile.add_function (override_func);
1655 pop_context ();
1657 if (m.entry_point) {
1658 generate_type_declaration (new ObjectType (array_class), cfile);
1660 // m is possible entry point, add appropriate startup code
1661 var cmain = new CCodeFunction ("main", "int");
1662 cmain.line = function.line;
1663 cmain.add_parameter (new CCodeParameter ("argc", "int"));
1664 cmain.add_parameter (new CCodeParameter ("argv", "char **"));
1666 push_function (cmain);
1668 var dova_init_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_init"));
1669 dova_init_call.add_argument (new CCodeIdentifier ("argc"));
1670 dova_init_call.add_argument (new CCodeIdentifier ("argv"));
1671 ccode.add_statement (new CCodeExpressionStatement (dova_init_call));
1673 add_module_init ();
1675 var cdecl = new CCodeDeclaration ("int");
1676 cdecl.add_declarator (new CCodeVariableDeclarator ("result", new CCodeConstant ("0")));
1677 ccode.add_statement (cdecl);
1679 var main_call = new CCodeFunctionCall (new CCodeIdentifier (function.name));
1681 if (m.get_parameters ().size == 1) {
1682 // create Dova array from C array
1683 // should be replaced by Dova list
1684 var array_creation = new CCodeFunctionCall (new CCodeIdentifier ("dova_array_new"));
1685 array_creation.add_argument (new CCodeFunctionCall (new CCodeIdentifier ("string_type_get")));
1686 array_creation.add_argument (new CCodeIdentifier ("argc"));
1688 cdecl = new CCodeDeclaration ("DovaArray*");
1689 cdecl.add_declarator (new CCodeVariableDeclarator ("args", array_creation));
1690 ccode.add_statement (cdecl);
1692 var array_data = new CCodeFunctionCall (new CCodeIdentifier ("dova_array_get_data"));
1693 array_data.add_argument (new CCodeIdentifier ("args"));
1695 cdecl = new CCodeDeclaration ("string_t*");
1696 cdecl.add_declarator (new CCodeVariableDeclarator ("args_data", array_data));
1697 ccode.add_statement (cdecl);
1699 cdecl = new CCodeDeclaration ("int");
1700 cdecl.add_declarator (new CCodeVariableDeclarator ("argi"));
1701 ccode.add_statement (cdecl);
1703 var string_creation = new CCodeFunctionCall (new CCodeIdentifier ("string_create_from_cstring"));
1704 string_creation.add_argument (new CCodeElementAccess (new CCodeIdentifier ("argv"), new CCodeIdentifier ("argi")));
1706 var loop_block = new CCodeBlock ();
1707 loop_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("args_data"), new CCodeIdentifier ("argi")), string_creation)));
1709 var for_stmt = new CCodeForStatement (new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("argi"), new CCodeIdentifier ("argc")), loop_block);
1710 for_stmt.add_initializer (new CCodeAssignment (new CCodeIdentifier ("argi"), new CCodeConstant ("0")));
1711 for_stmt.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("argi")));
1712 ccode.add_statement (for_stmt);
1714 main_call.add_argument (new CCodeIdentifier ("args"));
1717 if (m.return_type is VoidType) {
1718 // method returns void, always use 0 as exit code
1719 var main_stmt = new CCodeExpressionStatement (main_call);
1720 main_stmt.line = cmain.line;
1721 ccode.add_statement (main_stmt);
1722 } else {
1723 var main_stmt = new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), main_call));
1724 main_stmt.line = cmain.line;
1725 ccode.add_statement (main_stmt);
1728 if (m.get_parameters ().size == 1) {
1729 // destroy Dova array
1730 var unref = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_unref"));
1731 unref.add_argument (new CCodeIdentifier ("args"));
1732 ccode.add_statement (new CCodeExpressionStatement (unref));
1735 var ret_stmt = new CCodeReturnStatement (new CCodeIdentifier ("result"));
1736 ret_stmt.line = cmain.line;
1737 ccode.add_statement (ret_stmt);
1739 pop_function ();
1741 cfile.add_function (cmain);
1745 public override void visit_creation_method (CreationMethod m) {
1746 bool visible = !m.is_internal_symbol ();
1748 visit_method (m);
1750 DataType creturn_type;
1751 if (current_type_symbol is Class) {
1752 creturn_type = new ObjectType (current_class);
1753 } else {
1754 creturn_type = new VoidType ();
1757 // do not generate _new functions for creation methods of abstract classes
1758 if (current_type_symbol is Class && !current_class.is_abstract) {
1759 var vfunc = new CCodeFunction (m.get_cname ());
1761 var vblock = new CCodeBlock ();
1763 var cdecl = new CCodeDeclaration ("%s *".printf (current_type_symbol.get_cname ()));
1764 cdecl.add_declarator (new CCodeVariableDeclarator ("this"));
1765 vblock.add_statement (cdecl);
1767 var type_get = new CCodeFunctionCall (new CCodeIdentifier (current_class.get_lower_case_cname () + "_type_get"));
1768 foreach (var type_param in current_class.get_type_parameters ()) {
1769 type_get.add_argument (new CCodeIdentifier ("%s_type".printf (type_param.name.down ())));
1772 var alloc_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_alloc"));
1773 alloc_call.add_argument (type_get);
1774 vblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("this"), new CCodeCastExpression (alloc_call, "%s *".printf (current_type_symbol.get_cname ())))));
1776 // allocate memory for fields of generic types
1777 // this is only a temporary measure until this can be allocated inline at the end of the instance
1778 // this also won't work for subclasses of classes that have fields of generic types
1779 foreach (var f in current_class.get_fields ()) {
1780 if (f.binding != MemberBinding.INSTANCE || !(f.variable_type is GenericType)) {
1781 continue;
1784 var generic_type = (GenericType) f.variable_type;
1785 var type_get_value_size = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_get_value_size"));
1786 type_get_value_size.add_argument (new CCodeIdentifier ("%s_type".printf (generic_type.type_parameter.name.down ())));
1788 var calloc_call = new CCodeFunctionCall (new CCodeIdentifier ("calloc"));
1789 calloc_call.add_argument (new CCodeConstant ("1"));
1790 calloc_call.add_argument (type_get_value_size);
1791 var priv_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (current_class.get_upper_case_cname (null))));
1792 priv_call.add_argument (new CCodeIdentifier ("this"));
1794 vblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (priv_call, f.name), calloc_call)));
1797 var vcall = new CCodeFunctionCall (new CCodeIdentifier (m.get_real_cname ()));
1798 vcall.add_argument (new CCodeIdentifier ("this"));
1799 vblock.add_statement (new CCodeExpressionStatement (vcall));
1801 generate_cparameters (m, cfile, vfunc, null, vcall);
1802 CCodeStatement cstmt = new CCodeReturnStatement (new CCodeIdentifier ("this"));
1803 cstmt.line = vfunc.line;
1804 vblock.add_statement (cstmt);
1806 if (!visible) {
1807 vfunc.modifiers |= CCodeModifiers.STATIC;
1810 cfile.add_function_declaration (vfunc);
1812 vfunc.block = vblock;
1814 cfile.add_function (vfunc);
1818 private TypeSymbol? find_parent_type (Symbol sym) {
1819 while (sym != null) {
1820 if (sym is TypeSymbol) {
1821 return (TypeSymbol) sym;
1823 sym = sym.parent_symbol;
1825 return null;
1828 public override void generate_cparameters (Method m, CCodeFile decl_space, CCodeFunction func, CCodeFunctionDeclarator? vdeclarator = null, CCodeFunctionCall? vcall = null) {
1829 CCodeParameter instance_param = null;
1830 if (m.closure) {
1831 var closure_block = current_closure_block;
1832 int block_id = get_block_id (closure_block);
1833 instance_param = new CCodeParameter ("_data%d_".printf (block_id), "Block%dData*".printf (block_id));
1834 } else if (m.parent_symbol is Class && m is CreationMethod) {
1835 if (vcall == null) {
1836 instance_param = new CCodeParameter ("this", ((Class) m.parent_symbol).get_cname () + "*");
1838 } else if (m.binding == MemberBinding.INSTANCE || (m.parent_symbol is Struct && m is CreationMethod)) {
1839 TypeSymbol parent_type = find_parent_type (m);
1840 var this_type = get_data_type_for_symbol (parent_type);
1842 generate_type_declaration (this_type, decl_space);
1844 if (m.base_interface_method != null && !m.is_abstract && !m.is_virtual) {
1845 var base_type = new ObjectType ((Interface) m.base_interface_method.parent_symbol);
1846 instance_param = new CCodeParameter ("this", base_type.get_cname ());
1847 } else if (m.overrides) {
1848 var base_type = new ObjectType ((Class) m.base_method.parent_symbol);
1849 generate_type_declaration (base_type, decl_space);
1850 instance_param = new CCodeParameter ("this", base_type.get_cname ());
1851 } else {
1852 if (m.parent_symbol is Struct && m is CreationMethod) {
1853 var st = (Struct) m.parent_symbol;
1854 if (st.is_boolean_type () || st.is_integer_type () || st.is_floating_type ()) {
1855 // use return value
1856 } else {
1857 instance_param = new CCodeParameter ("*this", this_type.get_cname ());
1859 } else {
1860 instance_param = new CCodeParameter ("this", this_type.get_cname ());
1864 if (instance_param != null) {
1865 func.add_parameter (instance_param);
1866 if (vdeclarator != null) {
1867 vdeclarator.add_parameter (instance_param);
1871 if (m is CreationMethod) {
1872 generate_class_declaration ((Class) type_class, decl_space);
1874 if (m.parent_symbol is Class) {
1875 var cl = (Class) m.parent_symbol;
1876 foreach (TypeParameter type_param in cl.get_type_parameters ()) {
1877 var cparam = new CCodeParameter ("%s_type".printf (type_param.name.down ()), "DovaType*");
1878 if (vcall != null) {
1879 func.add_parameter (cparam);
1883 } else {
1884 foreach (TypeParameter type_param in m.get_type_parameters ()) {
1885 var cparam = new CCodeParameter ("%s_type".printf (type_param.name.down ()), "DovaType*");
1886 func.add_parameter (cparam);
1887 if (vdeclarator != null) {
1888 vdeclarator.add_parameter (cparam);
1890 if (vcall != null) {
1891 vcall.add_argument (new CCodeIdentifier ("%s_type".printf (type_param.name.down ())));
1896 foreach (Parameter param in m.get_parameters ()) {
1897 CCodeParameter cparam;
1898 if (!param.ellipsis) {
1899 string ctypename = param.variable_type.get_cname ();
1901 generate_type_declaration (param.variable_type, decl_space);
1903 if (param.direction != ParameterDirection.IN && !(param.variable_type is GenericType)) {
1904 ctypename += "*";
1907 cparam = new CCodeParameter (get_variable_cname (param.name), ctypename);
1908 } else {
1909 cparam = new CCodeParameter.with_ellipsis ();
1912 func.add_parameter (cparam);
1913 if (vdeclarator != null) {
1914 vdeclarator.add_parameter (cparam);
1916 if (vcall != null) {
1917 if (param.name != null) {
1918 vcall.add_argument (get_variable_cexpression (param.name));
1923 if (m.parent_symbol is Class && m is CreationMethod && vcall != null) {
1924 func.return_type = ((Class) m.parent_symbol).get_cname () + "*";
1925 } else {
1926 if (m.return_type is GenericType) {
1927 func.add_parameter (new CCodeParameter ("result", "void *"));
1928 if (vdeclarator != null) {
1929 vdeclarator.add_parameter (new CCodeParameter ("result", "void *"));
1931 } else {
1932 var st = m.parent_symbol as Struct;
1933 if (m is CreationMethod && st != null && (st.is_boolean_type () || st.is_integer_type () || st.is_floating_type ())) {
1934 func.return_type = st.get_cname ();
1935 } else {
1936 func.return_type = m.return_type.get_cname ();
1940 generate_type_declaration (m.return_type, decl_space);
1944 public override void visit_element_access (ElementAccess expr) {
1945 var array_type = expr.container.value_type as ArrayType;
1946 if (array_type != null) {
1947 // access to element in an array
1949 expr.accept_children (this);
1951 List<Expression> indices = expr.get_indices ();
1952 var cindex = get_cvalue (indices[0]);
1954 if (array_type.inline_allocated) {
1955 set_cvalue (expr, new CCodeElementAccess (get_cvalue (expr.container), cindex));
1956 } else {
1957 generate_property_accessor_declaration (((Property) array_class.scope.lookup ("data")).get_accessor, cfile);
1959 var ccontainer = new CCodeFunctionCall (new CCodeIdentifier ("dova_array_get_data"));
1960 ccontainer.add_argument (get_cvalue (expr.container));
1962 if (array_type.element_type is GenericType) {
1963 // generic array
1964 // calculate offset in bytes based on value size
1965 var value_size = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_get_value_size"));
1966 value_size.add_argument (get_type_id_expression (array_type.element_type));
1967 set_cvalue (expr, new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeCastExpression (ccontainer, "char*"), new CCodeBinaryExpression (CCodeBinaryOperator.MUL, value_size, cindex)));
1968 } else {
1969 set_cvalue (expr, new CCodeElementAccess (new CCodeCastExpression (ccontainer, "%s*".printf (array_type.element_type.get_cname ())), cindex));
1973 } else {
1974 base.visit_element_access (expr);
1978 void add_module_init () {
1979 foreach (var field in static_fields) {
1980 field.initializer.emit (this);
1982 var lhs = new CCodeIdentifier (field.get_cname ());
1983 var rhs = get_cvalue (field.initializer);
1985 ccode.add_assignment (lhs, rhs);