1 /* valagtypemodule.vala
3 * Copyright (C) 2006-2010 Jürg Billeter
4 * Copyright (C) 2006-2008 Raffaele Sandrini
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
26 public class Vala.GTypeModule : GErrorModule {
27 public override CCodeParameter generate_parameter (Parameter param, CCodeFile decl_space, Map<int,CCodeParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
28 if (!(param.variable_type is ObjectType)) {
29 return base.generate_parameter (param, decl_space, cparam_map, carg_map);
32 generate_type_declaration (param.variable_type, decl_space);
34 string? ctypename = get_ccode_type (param);
35 if (ctypename == null) {
36 ctypename = get_ccode_name (param.variable_type);
38 if (param.direction != ParameterDirection.IN) {
39 ctypename = "%s*".printf (ctypename);
43 var cparam = new CCodeParameter (get_ccode_name (param), ctypename);
44 if (param.format_arg) {
45 cparam.modifiers = CCodeModifiers.FORMAT_ARG;
48 cparam_map.set (get_param_pos (get_ccode_pos (param)), cparam);
49 if (carg_map != null) {
50 carg_map.set (get_param_pos (get_ccode_pos (param)), get_parameter_cexpression (param));
56 public override void generate_class_declaration (Class cl, CCodeFile decl_space) {
57 if (add_symbol_declaration (decl_space, cl, get_ccode_name (cl))) {
61 if (cl.base_class != null) {
62 // base class declaration
63 // necessary for ref and unref function declarations
64 generate_class_declaration (cl.base_class, decl_space);
67 bool is_gtypeinstance = !cl.is_compact;
68 bool is_fundamental = is_gtypeinstance && cl.base_class == null;
69 bool is_gsource = cl.is_subtype_of (gsource_type);
71 if (is_gtypeinstance) {
72 decl_space.add_include ("glib-object.h");
74 decl_space.add_type_declaration (new CCodeNewline ());
75 var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (cl, null));
76 decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (cl), macro));
78 macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (get_ccode_type_id (cl), get_ccode_name (cl));
79 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_cast_function (cl)), macro));
81 if (!(cl.is_sealed && decl_space.file_type == CCodeFileType.PUBLIC_HEADER)) {
82 macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %s))".printf (get_ccode_type_id (cl), get_ccode_type_name (cl));
83 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(klass)".printf (get_ccode_class_type_function (cl)), macro));
86 macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (get_ccode_type_id (cl));
87 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_check_function (cl)), macro));
89 if (!(cl.is_sealed && decl_space.file_type == CCodeFileType.PUBLIC_HEADER)) {
90 macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (get_ccode_type_id (cl));
91 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(klass)".printf (get_ccode_class_type_check_function (cl)), macro));
94 if (!(cl.is_sealed && decl_space.file_type == CCodeFileType.PUBLIC_HEADER)) {
95 macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %s))".printf (get_ccode_type_id (cl), get_ccode_type_name (cl));
96 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_get_function (cl)), macro));
98 decl_space.add_type_declaration (new CCodeNewline ());
101 if (!(!cl.is_compact || cl.base_class == null || compact_class_has_instance_struct_member (cl))) {
102 decl_space.add_type_declaration (new CCodeTypeDefinition (get_ccode_name (cl.base_class), new CCodeVariableDeclarator (get_ccode_name (cl))));
104 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (cl)), new CCodeVariableDeclarator (get_ccode_name (cl))));
107 if (is_fundamental) {
108 var ref_fun = new CCodeFunction (get_ccode_ref_function (cl), "gpointer");
109 var unref_fun = new CCodeFunction (get_ccode_unref_function (cl), "void");
110 if (cl.is_private_symbol ()) {
111 ref_fun.modifiers = CCodeModifiers.STATIC;
112 unref_fun.modifiers = CCodeModifiers.STATIC;
113 } else if (context.hide_internal && cl.is_internal_symbol ()) {
114 ref_fun.modifiers = CCodeModifiers.INTERNAL;
115 unref_fun.modifiers = CCodeModifiers.INTERNAL;
117 ref_fun.modifiers = CCodeModifiers.EXTERN;
118 unref_fun.modifiers = CCodeModifiers.EXTERN;
119 requires_vala_extern = true;
122 ref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
123 unref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
125 decl_space.add_function_declaration (ref_fun);
126 decl_space.add_function_declaration (unref_fun);
128 // GParamSpec and GValue functions
129 var function = new CCodeFunction (get_ccode_param_spec_function (cl), "GParamSpec*");
130 function.add_parameter (new CCodeParameter ("name", "const gchar*"));
131 function.add_parameter (new CCodeParameter ("nick", "const gchar*"));
132 function.add_parameter (new CCodeParameter ("blurb", "const gchar*"));
133 function.add_parameter (new CCodeParameter ("object_type", "GType"));
134 function.add_parameter (new CCodeParameter ("flags", "GParamFlags"));
136 if (cl.is_private_symbol ()) {
137 // avoid C warning as this function is not always used
138 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
139 } else if (context.hide_internal && cl.is_internal_symbol ()) {
140 function.modifiers = CCodeModifiers.INTERNAL;
142 function.modifiers = CCodeModifiers.EXTERN;
143 requires_vala_extern = true;
146 decl_space.add_function_declaration (function);
148 function = new CCodeFunction (get_ccode_set_value_function (cl), "void");
149 function.add_parameter (new CCodeParameter ("value", "GValue*"));
150 function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
152 if (cl.is_private_symbol ()) {
153 // avoid C warning as this function is not always used
154 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
155 } else if (context.hide_internal && cl.is_internal_symbol ()) {
156 // avoid C warning as this function is not always used
157 function.modifiers = CCodeModifiers.INTERNAL | CCodeModifiers.UNUSED;
159 function.modifiers = CCodeModifiers.EXTERN;
160 requires_vala_extern = true;
163 decl_space.add_function_declaration (function);
165 function = new CCodeFunction (get_ccode_take_value_function (cl), "void");
166 function.add_parameter (new CCodeParameter ("value", "GValue*"));
167 function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
169 if (cl.is_private_symbol ()) {
170 // avoid C warning as this function is not always used
171 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
172 } else if (context.hide_internal && cl.is_internal_symbol ()) {
173 function.modifiers = CCodeModifiers.INTERNAL;
175 function.modifiers = CCodeModifiers.EXTERN;
176 requires_vala_extern = true;
179 decl_space.add_function_declaration (function);
181 function = new CCodeFunction (get_ccode_get_value_function (cl), "gpointer");
182 function.add_parameter (new CCodeParameter ("value", "const GValue*"));
184 if (cl.is_private_symbol ()) {
185 // avoid C warning as this function is not always used
186 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
187 } else if (context.hide_internal && cl.is_internal_symbol ()) {
188 // avoid C warning as this function is not always used
189 function.modifiers = CCodeModifiers.INTERNAL | CCodeModifiers.UNUSED;
191 function.modifiers = CCodeModifiers.EXTERN;
192 requires_vala_extern = true;
195 decl_space.add_function_declaration (function);
196 } else if (!is_gtypeinstance && !is_gsource) {
197 if (cl.base_class == null) {
198 var function = new CCodeFunction (get_ccode_free_function (cl), "void");
199 if (cl.is_private_symbol ()) {
200 function.modifiers = CCodeModifiers.STATIC;
201 } else if (context.hide_internal && cl.is_internal_symbol ()) {
202 function.modifiers = CCodeModifiers.INTERNAL;
204 function.modifiers = CCodeModifiers.EXTERN;
205 requires_vala_extern = true;
208 function.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl))));
210 decl_space.add_function_declaration (function);
214 if (is_gtypeinstance && !(cl.is_sealed && decl_space.file_type == CCodeFileType.PUBLIC_HEADER)) {
215 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_type_name (cl)), new CCodeVariableDeclarator (get_ccode_type_name (cl))));
217 var type_fun = new ClassRegisterFunction (cl);
218 type_fun.init_from_type (context, in_plugin, true);
219 decl_space.add_type_member_declaration (type_fun.get_declaration ());
221 requires_vala_extern = true;
225 while (base_class.base_class != null) {
226 base_class = base_class.base_class;
228 // Custom unref-methods need to be emitted before G_DEFINE_AUTOPTR_CLEANUP_FUNC,
229 // so we guard against that special case and handle it in generate_method_declaration.
230 if (!(base_class.is_compact && is_reference_counting (base_class))
231 && (context.header_filename == null|| decl_space.file_type == CCodeFileType.PUBLIC_HEADER
232 || (decl_space.file_type == CCodeFileType.INTERNAL_HEADER && base_class.is_internal_symbol()))) {
233 string autoptr_cleanup_func;
234 if (is_reference_counting (base_class)) {
235 autoptr_cleanup_func = get_ccode_unref_function (base_class);
237 autoptr_cleanup_func = get_ccode_free_function (base_class);
239 if (autoptr_cleanup_func == null || autoptr_cleanup_func == "") {
240 Report.error (cl.source_reference, "internal error: autoptr_cleanup_func not available");
242 decl_space.add_type_member_declaration (new CCodeIdentifier ("G_DEFINE_AUTOPTR_CLEANUP_FUNC (%s, %s)".printf (get_ccode_name (cl), autoptr_cleanup_func)));
243 decl_space.add_type_member_declaration (new CCodeNewline ());
247 public override void generate_class_struct_declaration (Class cl, CCodeFile decl_space) {
248 if (add_symbol_declaration (decl_space, cl, "struct _%s".printf (get_ccode_name (cl)))) {
252 if (cl.base_class != null) {
253 // base class declaration
254 generate_class_struct_declaration (cl.base_class, decl_space);
256 foreach (DataType base_type in cl.get_base_types ()) {
257 unowned Interface? iface = base_type.type_symbol as Interface;
259 generate_interface_declaration (iface, decl_space);
263 generate_class_declaration (cl, decl_space);
265 if (cl.is_sealed && decl_space.file_type == CCodeFileType.PUBLIC_HEADER) {
269 bool is_gtypeinstance = !cl.is_compact;
270 bool is_fundamental = is_gtypeinstance && cl.base_class == null;
272 var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (cl)));
273 var type_struct = new CCodeStruct ("_%s".printf (get_ccode_type_name (cl)));
275 if (cl.base_class != null) {
276 instance_struct.add_field (get_ccode_name (cl.base_class), "parent_instance");
277 } else if (is_fundamental) {
278 instance_struct.add_field ("GTypeInstance", "parent_instance");
279 instance_struct.add_field ("volatile int", "ref_count");
282 if (is_gtypeinstance) {
283 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %sPrivate".printf (instance_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (get_ccode_name (cl)))));
285 if (!context.abi_stability) {
286 instance_struct.add_field ("%sPrivate *".printf (get_ccode_name (cl)), "priv");
288 if (is_fundamental) {
289 type_struct.add_field ("GTypeClass", "parent_class");
291 type_struct.add_field (get_ccode_type_name (cl.base_class), "parent_class");
294 if (is_fundamental) {
295 type_struct.add_field ("void", "(*finalize) (%s *self)".printf (get_ccode_name (cl)));
299 if (context.abi_stability) {
300 foreach (Symbol s in cl.get_members ()) {
303 generate_struct_method_declaration (cl, m, instance_struct, type_struct, decl_space);
304 } else if (s is Signal) {
305 var sig = (Signal) s;
306 if (sig.default_handler != null) {
307 if (sig.is_virtual) {
308 generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
310 generate_method_declaration (sig.default_handler, cfile);
313 } else if (s is Property) {
314 var prop = (Property) s;
315 generate_struct_property_declaration (cl, prop, instance_struct, type_struct, decl_space);
316 } else if (s is Field) {
317 if (s.access != SymbolAccessibility.PRIVATE || cl.is_opaque) {
318 generate_struct_field_declaration ((Field) s, instance_struct, type_struct, decl_space);
321 Report.error (s.source_reference, "internal: Unsupported symbol");
325 foreach (Method m in cl.get_methods ()) {
326 generate_struct_method_declaration (cl, m, instance_struct, type_struct, decl_space);
329 foreach (Signal sig in cl.get_signals ()) {
330 if (sig.default_handler != null) {
331 if (sig.is_virtual) {
332 generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
334 generate_method_declaration (sig.default_handler, cfile);
339 foreach (Property prop in cl.get_properties ()) {
340 generate_struct_property_declaration (cl, prop, instance_struct, type_struct, decl_space);
343 foreach (Field f in cl.get_fields ()) {
344 if (f.access != SymbolAccessibility.PRIVATE || cl.is_opaque) {
345 generate_struct_field_declaration (f, instance_struct, type_struct, decl_space);
350 if (cl.is_compact && cl.base_class == null && !compact_class_has_instance_struct_member (cl)) {
351 // add dummy member, C doesn't allow empty structs
352 instance_struct.add_field ("int", "dummy");
355 if (!cl.is_compact || cl.base_class == null || compact_class_has_instance_struct_member (cl)) {
356 decl_space.add_type_definition (instance_struct);
359 if (is_gtypeinstance) {
360 if (context.abi_stability) {
361 instance_struct.add_field ("%sPrivate *".printf (get_ccode_name (cl)), "priv");
363 decl_space.add_type_definition (type_struct);
367 bool compact_class_has_instance_struct_member (Class cl) {
368 assert (cl.is_compact);
369 foreach (Symbol s in cl.get_members ()) {
371 unowned Method m = (Method) s;
372 if (m.is_abstract || m.is_virtual) {
375 } else if (s is Property) {
376 unowned Property prop = (Property) s;
377 if (prop.is_abstract || prop.is_virtual) {
380 } else if (s is Field) {
381 if (s.access != SymbolAccessibility.PRIVATE || cl.is_opaque) {
382 unowned Field f = (Field) s;
383 if (f.binding == MemberBinding.INSTANCE) {
388 Report.error (s.source_reference, "internal: Unsupported symbol");
394 void generate_struct_method_declaration (ObjectTypeSymbol type_sym, Method m, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space) {
395 unowned Class? cl = type_sym as Class;
396 if (type_sym is Interface || (cl != null && !cl.is_compact)) {
397 generate_virtual_method_declaration (m, decl_space, type_struct);
398 } else if (cl != null && cl.is_compact && cl.base_class == null) {
399 generate_virtual_method_declaration (m, decl_space, instance_struct);
403 void generate_struct_property_declaration (ObjectTypeSymbol type_sym, Property prop, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space) {
404 if (!prop.is_abstract && !prop.is_virtual) {
407 generate_type_declaration (prop.property_type, decl_space);
409 unowned ObjectTypeSymbol t = (ObjectTypeSymbol) prop.parent_symbol;
410 unowned Class? cl = type_sym as Class;
412 var this_type = new ObjectType (t);
413 var cselfparam = new CCodeParameter ("self", get_ccode_name (this_type));
415 if (prop.get_accessor != null) {
416 var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
417 vdeclarator.add_parameter (cselfparam);
418 var creturn_type = get_callable_creturn_type (prop.get_accessor.get_method ());
419 if (prop.property_type.is_real_non_null_struct_type ()) {
420 var cvalueparam = new CCodeParameter ("result", "%s *".printf (get_ccode_name (prop.get_accessor.value_type)));
421 vdeclarator.add_parameter (cvalueparam);
424 var array_type = prop.property_type as ArrayType;
425 if (array_type != null && get_ccode_array_length (prop)) {
426 var length_ctype = get_ccode_array_length_type (prop) + "*";
427 for (int dim = 1; dim <= array_type.rank; dim++) {
428 vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("result", dim), length_ctype));
430 } else if ((prop.property_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) prop.property_type).delegate_symbol.has_target) {
431 vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_cname ("result"), "gpointer*"));
434 var vdecl = new CCodeDeclaration (get_ccode_name (creturn_type));
435 vdecl.add_declarator (vdeclarator);
436 type_struct.add_declaration (vdecl);
438 if (cl != null && cl.is_compact && cl.base_class == null) {
439 instance_struct.add_declaration (vdecl);
442 if (prop.set_accessor != null) {
443 CCodeParameter cvalueparam;
444 if (prop.property_type.is_real_non_null_struct_type ()) {
445 cvalueparam = new CCodeParameter ("value", "%s *".printf (get_ccode_name (prop.set_accessor.value_type)));
447 cvalueparam = new CCodeParameter ("value", get_ccode_name (prop.set_accessor.value_type));
450 var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
451 vdeclarator.add_parameter (cselfparam);
452 vdeclarator.add_parameter (cvalueparam);
454 var array_type = prop.property_type as ArrayType;
455 if (array_type != null && get_ccode_array_length (prop)) {
456 var length_ctype = get_ccode_array_length_type (prop);
457 for (int dim = 1; dim <= array_type.rank; dim++) {
458 vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("value", dim), length_ctype));
460 } else if ((prop.property_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) prop.property_type).delegate_symbol.has_target) {
461 vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_cname ("value"), "gpointer"));
462 if (prop.set_accessor.value_type.value_owned) {
463 vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_destroy_notify_cname ("value"), get_ccode_name (delegate_target_destroy_type)));
467 var vdecl = new CCodeDeclaration ("void");
468 vdecl.add_declarator (vdeclarator);
469 type_struct.add_declaration (vdecl);
471 if (cl != null && cl.is_compact && cl.base_class == null) {
472 instance_struct.add_declaration (vdecl);
477 void generate_struct_field_declaration (Field f, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space) {
478 CCodeModifiers modifiers = (f.is_volatile ? CCodeModifiers.VOLATILE : 0) | (f.version.deprecated ? CCodeModifiers.DEPRECATED : 0);
479 if (f.binding == MemberBinding.INSTANCE) {
480 append_field (instance_struct, f, decl_space);
481 } else if (f.binding == MemberBinding.CLASS) {
482 type_struct.add_field (get_ccode_name (f.variable_type), get_ccode_name (f), modifiers);
486 public override bool generate_method_declaration (Method m, CCodeFile decl_space) {
487 if (base.generate_method_declaration (m, decl_space)) {
488 // Custom unref-methods need to be emitted before G_DEFINE_AUTOPTR_CLEANUP_FUNC,
489 // in addition to the non-ref-countable case in generate_class_declaration.
490 unowned Class? cl = m.parent_symbol as Class;
491 if (cl != null && cl.is_compact && get_ccode_unref_function (cl) == get_ccode_name (m)
492 && (context.header_filename == null || decl_space.file_type == CCodeFileType.PUBLIC_HEADER
493 || (decl_space.file_type == CCodeFileType.INTERNAL_HEADER && cl.is_internal_symbol()))) {
494 decl_space.add_type_member_declaration (new CCodeIdentifier ("G_DEFINE_AUTOPTR_CLEANUP_FUNC (%s, %s)".printf (get_ccode_name (cl), get_ccode_name (m))));
495 decl_space.add_type_member_declaration (new CCodeNewline ());
504 public virtual void generate_virtual_method_declaration (Method m, CCodeFile decl_space, CCodeStruct type_struct) {
505 if (!m.is_abstract && !m.is_virtual) {
509 var creturn_type = get_callable_creturn_type (m);
511 // add vfunc field to the type struct
512 var vdeclarator = new CCodeFunctionDeclarator (get_ccode_vfunc_name (m));
513 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
515 if (m.printf_format) {
516 vdeclarator.modifiers |= CCodeModifiers.PRINTF;
517 } else if (m.scanf_format) {
518 vdeclarator.modifiers |= CCodeModifiers.SCANF;
521 if (m.version.deprecated) {
522 vdeclarator.modifiers |= CCodeModifiers.DEPRECATED;
525 generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator);
527 var vdecl = new CCodeDeclaration (get_ccode_name (creturn_type));
528 vdecl.add_declarator (vdeclarator);
529 type_struct.add_declaration (vdecl);
532 void generate_class_private_declaration (Class cl, CCodeFile decl_space) {
533 if (cl.is_opaque || decl_space.add_declaration ("%sPrivate".printf (get_ccode_name (cl)))) {
537 bool is_gtypeinstance = !cl.is_compact;
538 bool has_class_locks = false;
540 var instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (get_ccode_name (cl)));
541 var type_priv_struct = new CCodeStruct ("_%sPrivate".printf (get_ccode_type_name (cl)));
543 if (is_gtypeinstance) {
544 /* create type, dup_func, and destroy_func fields for generic types */
545 foreach (TypeParameter type_param in cl.get_type_parameters ()) {
546 instance_priv_struct.add_field ("GType", get_ccode_type_id (type_param));
547 instance_priv_struct.add_field ("GBoxedCopyFunc", get_ccode_copy_function (type_param));
548 instance_priv_struct.add_field ("GDestroyNotify", get_ccode_destroy_function (type_param));
552 foreach (Field f in cl.get_fields ()) {
553 if (f.access == SymbolAccessibility.PRIVATE) {
554 generate_struct_field_declaration (f, instance_priv_struct, type_priv_struct, decl_space);
557 if (f.binding == MemberBinding.INSTANCE) {
558 cl.has_private_fields = true;
559 // add field for mutex
560 instance_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (f)));
561 } else if (f.binding == MemberBinding.CLASS) {
562 has_class_locks = true;
563 // add field for mutex
564 type_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (f)));
569 foreach (Property prop in cl.get_properties ()) {
570 if (prop.binding == MemberBinding.INSTANCE) {
571 if (prop.lock_used) {
572 cl.has_private_fields = true;
573 // add field for mutex
574 instance_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (prop)));
576 } else if (prop.binding == MemberBinding.CLASS) {
577 if (prop.lock_used) {
578 has_class_locks = true;
579 // add field for mutex
580 type_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (prop)));
585 if (is_gtypeinstance) {
586 if (cl.has_class_private_fields || has_class_locks) {
587 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_priv_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (get_ccode_type_name (cl)))));
590 /* only add the *Private struct if it is not empty, i.e. we actually have private data */
591 if (cl.has_private_fields || cl.has_type_parameters ()) {
592 decl_space.add_type_definition (instance_priv_struct);
594 var parent_decl = new CCodeDeclaration ("gint");
595 var parent_var_decl = new CCodeVariableDeclarator ("%s_private_offset".printf (get_ccode_name (cl)));
596 parent_decl.add_declarator (parent_var_decl);
597 parent_decl.modifiers = CCodeModifiers.STATIC;
598 cfile.add_type_member_declaration (parent_decl);
600 var function = new CCodeFunction ("%s_get_instance_private".printf (get_ccode_lower_case_name (cl, null)), "gpointer");
601 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.INLINE;
602 function.add_parameter (new CCodeParameter ("self", "%s*".printf (get_ccode_name (cl))));
604 push_function (function);
606 function.block = new CCodeBlock ();
607 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_STRUCT_MEMBER_P"));
608 ccall.add_argument (new CCodeIdentifier ("self"));
609 ccall.add_argument (new CCodeIdentifier ("%s_private_offset".printf (get_ccode_name (cl))));
610 function.block.add_statement (new CCodeReturnStatement (ccall));
613 cfile.add_function (function);
616 if (cl.has_class_private_fields || has_class_locks) {
617 decl_space.add_type_definition (type_priv_struct);
619 string macro = "(G_TYPE_CLASS_GET_PRIVATE (klass, %s, %sPrivate))".printf (get_ccode_type_id (cl), get_ccode_type_name (cl));
620 decl_space.add_type_member_declaration (new CCodeMacroReplacement ("%s(klass)".printf (get_ccode_class_get_private_function (cl)), macro));
625 public override void visit_class (Class cl) {
626 push_context (new EmitContext (cl));
627 push_line (cl.source_reference);
629 var old_param_spec_struct = param_spec_struct;
630 var old_prop_enum = prop_enum;
631 var old_signal_enum = signal_enum;
632 var old_class_init_context = class_init_context;
633 var old_base_init_context = base_init_context;
634 var old_class_finalize_context = class_finalize_context;
635 var old_base_finalize_context = base_finalize_context;
636 var old_instance_init_context = instance_init_context;
637 var old_instance_finalize_context = instance_finalize_context;
639 bool is_gtypeinstance = !cl.is_compact;
640 bool is_gobject = is_gtypeinstance && cl.is_subtype_of (gobject_type);
641 bool is_fundamental = is_gtypeinstance && cl.base_class == null;
643 if (get_ccode_name (cl).length < 3) {
645 Report.error (cl.source_reference, "Class name `%s' is too short", get_ccode_name (cl));
649 prop_enum = new CCodeEnum ();
650 prop_enum.add_value (new CCodeEnumValue ("%s_0_PROPERTY".printf (get_ccode_upper_case_name (cl, null))));
651 signal_enum = new CCodeEnum ();
652 class_init_context = new EmitContext (cl);
653 base_init_context = new EmitContext (cl);
654 class_finalize_context = new EmitContext (cl);
655 base_finalize_context = new EmitContext (cl);
656 instance_init_context = new EmitContext (cl);
657 instance_finalize_context = new EmitContext (cl);
659 generate_class_struct_declaration (cl, cfile);
660 generate_class_private_declaration (cl, cfile);
662 var last_prop = "%s_NUM_PROPERTIES".printf (get_ccode_upper_case_name (cl));
664 cfile.add_type_declaration (prop_enum);
666 var prop_array_decl = new CCodeDeclaration ("GParamSpec*");
667 prop_array_decl.modifiers |= CCodeModifiers.STATIC;
668 prop_array_decl.add_declarator (new CCodeVariableDeclarator ("%s_properties".printf (get_ccode_lower_case_name (cl)), null, new CCodeDeclaratorSuffix.with_array (new CCodeIdentifier (last_prop))));
669 cfile.add_type_declaration (prop_array_decl);
672 if (!cl.is_internal_symbol () || cl.is_sealed) {
674 generate_class_struct_declaration (cl, header_file);
676 generate_class_declaration (cl, header_file);
679 if (!cl.is_private_symbol () || cl.is_sealed) {
680 generate_class_struct_declaration (cl, internal_header_file);
683 if (is_gtypeinstance) {
684 begin_base_init_function (cl);
685 begin_class_init_function (cl);
686 begin_instance_init_function (cl);
688 begin_base_finalize_function (cl);
689 begin_class_finalize_function (cl);
690 begin_finalize_function (cl);
692 if (cl.is_compact || cl.base_class == null || cl.is_subtype_of (gsource_type)) {
693 begin_instance_init_function (cl);
694 begin_finalize_function (cl);
698 cl.accept_children (this);
700 if (is_gtypeinstance) {
701 if (is_fundamental) {
702 param_spec_struct = new CCodeStruct ( "_%sParamSpec%s".printf(get_ccode_prefix (cl.parent_symbol), cl.name));
703 param_spec_struct.add_field ("GParamSpec", "parent_instance");
704 cfile.add_type_definition (param_spec_struct);
706 cfile.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (param_spec_struct.name), new CCodeVariableDeclarator ( "%sParamSpec%s".printf(get_ccode_prefix (cl.parent_symbol), cl.name))));
708 add_type_value_table_init_function (cl);
709 add_type_value_table_free_function (cl);
710 add_type_value_table_copy_function (cl);
711 add_type_value_table_peek_pointer_function (cl);
712 add_type_value_table_collect_value_function (cl);
713 add_type_value_table_lcopy_value_function (cl);
714 add_g_param_spec_type_function (cl);
715 add_g_value_get_function (cl);
716 add_g_value_set_function (cl);
717 add_g_value_take_function (cl);
719 var ref_count = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"), new CCodeConstant ("1"));
720 push_context (instance_init_context);
721 ccode.add_expression (ref_count);
726 prop_enum.add_value (new CCodeEnumValue (last_prop));
729 if (cl.get_signals ().size > 0) {
730 var last_signal = "%s_NUM_SIGNALS".printf (get_ccode_upper_case_name (cl));
731 signal_enum.add_value (new CCodeEnumValue (last_signal));
732 cfile.add_type_declaration (signal_enum);
734 var signal_array_decl = new CCodeDeclaration ("guint");
735 signal_array_decl.modifiers |= CCodeModifiers.STATIC;
736 signal_array_decl.add_declarator (new CCodeVariableDeclarator ("%s_signals".printf (get_ccode_lower_case_name (cl)), new CCodeConstant ("{0}"), new CCodeDeclaratorSuffix.with_array (new CCodeIdentifier (last_signal))));
737 cfile.add_type_declaration (signal_array_decl);
741 if (cl.class_constructor != null) {
742 add_base_init_function (cl);
744 add_class_init_function (cl);
746 if (cl.class_destructor != null) {
747 add_base_finalize_function (cl);
750 if (cl.static_destructor != null) {
751 add_class_finalize_function (cl);
754 foreach (DataType base_type in cl.get_base_types ()) {
755 if (base_type.type_symbol is Interface) {
756 add_interface_init_function (cl, (Interface) base_type.type_symbol);
760 add_instance_init_function (cl);
762 if (!cl.is_compact && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
763 add_finalize_function (cl);
766 if (cl.comment != null) {
767 cfile.add_type_member_definition (new CCodeComment (cl.comment.content));
770 var type_fun = new ClassRegisterFunction (cl);
771 type_fun.init_from_type (context, in_plugin, false);
772 cfile.add_type_member_declaration (type_fun.get_source_declaration ());
773 cfile.add_type_member_definition (type_fun.get_definition ());
775 if (is_fundamental) {
776 var ref_count = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count");
779 var ref_fun = new CCodeFunction (get_ccode_ref_function (cl), "gpointer");
780 ref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
781 if (cl.is_private_symbol ()) {
782 ref_fun.modifiers = CCodeModifiers.STATIC;
783 } else if (context.hide_internal && cl.is_internal_symbol ()) {
784 ref_fun.modifiers = CCodeModifiers.INTERNAL;
786 push_function (ref_fun);
788 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self", new CCodeIdentifier ("instance")));
789 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_inc"));
790 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count));
791 ccode.add_expression (ccall);
792 ccode.add_return (new CCodeIdentifier ("instance"));
795 cfile.add_function (ref_fun);
798 var unref_fun = new CCodeFunction (get_ccode_unref_function (cl), "void");
799 unref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
800 if (cl.is_private_symbol ()) {
801 unref_fun.modifiers = CCodeModifiers.STATIC;
802 } else if (context.hide_internal && cl.is_internal_symbol ()) {
803 unref_fun.modifiers = CCodeModifiers.INTERNAL;
805 push_function (unref_fun);
807 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self", new CCodeIdentifier ("instance")));
808 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_dec_and_test"));
809 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count));
810 ccode.open_if (ccall);
812 var get_class = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (cl)));
813 get_class.add_argument (new CCodeIdentifier ("self"));
816 var ccast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (cl)));
817 ccast.add_argument (new CCodeIdentifier ("self"));
818 ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
819 ccall.add_argument (new CCodeIdentifier ("self"));
820 ccode.add_expression (ccall);
822 // free type instance
823 var free = new CCodeFunctionCall (new CCodeIdentifier ("g_type_free_instance"));
824 free.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GTypeInstance *"));
825 ccode.add_expression (free);
829 cfile.add_function (unref_fun);
832 if (cl.is_compact || cl.base_class == null || cl.is_subtype_of (gsource_type)) {
833 add_instance_init_function (cl);
834 add_finalize_function (cl);
838 param_spec_struct = old_param_spec_struct;
839 prop_enum = old_prop_enum;
840 signal_enum = old_signal_enum;
841 class_init_context = old_class_init_context;
842 base_init_context = old_base_init_context;
843 class_finalize_context = old_class_finalize_context;
844 base_finalize_context = old_base_finalize_context;
845 instance_init_context = old_instance_init_context;
846 instance_finalize_context = old_instance_finalize_context;
852 private void add_type_value_table_init_function (Class cl) {
853 var function = new CCodeFunction ("%s_init".printf (get_ccode_lower_case_name (cl, "value_")), "void");
854 function.add_parameter (new CCodeParameter ("value", "GValue*"));
855 function.modifiers = CCodeModifiers.STATIC;
857 push_function (function);
858 ccode.add_assignment (new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer"), new CCodeConstant ("NULL"));
860 cfile.add_function (function);
863 private void add_type_value_table_free_function (Class cl) {
864 var function = new CCodeFunction ("%s_free_value".printf (get_ccode_lower_case_name (cl, "value_")), "void");
865 function.add_parameter (new CCodeParameter ("value", "GValue*"));
866 function.modifiers = CCodeModifiers.STATIC;
868 push_function (function);
870 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
871 var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (cl)));
872 ccall.add_argument (vpointer);
874 ccode.open_if (vpointer);
875 ccode.add_expression (ccall);
879 cfile.add_function (function);
882 private void add_type_value_table_copy_function (Class cl) {
883 var function = new CCodeFunction ("%s_copy_value".printf (get_ccode_lower_case_name (cl, "value_")), "void");
884 function.add_parameter (new CCodeParameter ("src_value", "const GValue*"));
885 function.add_parameter (new CCodeParameter ("dest_value", "GValue*"));
886 function.modifiers = CCodeModifiers.STATIC;
888 push_function (function);
890 var dest_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dest_value"), "data[0]"), "v_pointer");
891 var src_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("src_value"), "data[0]"), "v_pointer");
893 var ref_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
894 ref_ccall.add_argument ( src_vpointer );
896 ccode.open_if (src_vpointer);
897 ccode.add_assignment (dest_vpointer, ref_ccall);
899 ccode.add_assignment (dest_vpointer, new CCodeConstant ("NULL"));
903 cfile.add_function (function);
906 private void add_type_value_table_peek_pointer_function (Class cl) {
907 var function = new CCodeFunction ("%s_peek_pointer".printf (get_ccode_lower_case_name (cl, "value_")), "gpointer");
908 function.add_parameter (new CCodeParameter ("value", "const GValue*"));
909 function.modifiers = CCodeModifiers.STATIC;
911 push_function (function);
913 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
914 ccode.add_return (vpointer);
917 cfile.add_function (function);
920 private void add_type_value_table_lcopy_value_function ( Class cl ) {
921 // Required for GTypeCValue
922 cfile.add_include ("gobject/gvaluecollector.h");
924 var function = new CCodeFunction ("%s_lcopy_value".printf (get_ccode_lower_case_name (cl, "value_")), "gchar*");
925 function.add_parameter (new CCodeParameter ("value", "const GValue*"));
926 function.add_parameter (new CCodeParameter ("n_collect_values", "guint"));
927 function.add_parameter (new CCodeParameter ("collect_values", "GTypeCValue*"));
928 function.add_parameter (new CCodeParameter ("collect_flags", "guint"));
929 function.modifiers = CCodeModifiers.STATIC;
931 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
932 var object_p_ptr = new CCodeIdentifier ("*object_p");
933 var null_ = new CCodeConstant ("NULL");
935 push_function (function);
937 ccode.add_declaration ("%s **".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("object_p", new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"), "v_pointer")));
939 var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME"));
940 value_type_name_fct.add_argument (new CCodeConstant ("value"));
942 var assert_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("object_p"));
943 ccode.open_if (assert_condition);
944 var assert_printf = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup_printf"));
945 assert_printf.add_argument (new CCodeConstant ("\"value location for `%s' passed as NULL\""));
946 assert_printf.add_argument (value_type_name_fct);
947 ccode.add_return (assert_printf);
950 var main_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, vpointer);
951 var main_else_if_condition = new CCodeBinaryExpression (CCodeBinaryOperator.BITWISE_AND, new CCodeIdentifier ("collect_flags"), new CCodeIdentifier ("G_VALUE_NOCOPY_CONTENTS"));
952 var ref_fct = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
953 ref_fct.add_argument (vpointer);
954 ccode.open_if (main_condition);
955 ccode.add_assignment (object_p_ptr, null_);
956 ccode.else_if (main_else_if_condition);
957 ccode.add_assignment (object_p_ptr, vpointer);
959 ccode.add_assignment (object_p_ptr, ref_fct);
962 ccode.add_return (null_);
964 cfile.add_function (function);
967 private void add_type_value_table_collect_value_function (Class cl) {
968 // Required for GTypeCValue
969 cfile.add_include ("gobject/gvaluecollector.h");
971 var function = new CCodeFunction ("%s_collect_value".printf (get_ccode_lower_case_name (cl, "value_")), "gchar*");
972 function.add_parameter (new CCodeParameter ("value", "GValue*"));
973 function.add_parameter (new CCodeParameter ("n_collect_values", "guint"));
974 function.add_parameter (new CCodeParameter ("collect_values", "GTypeCValue*"));
975 function.add_parameter (new CCodeParameter ("collect_flags", "guint"));
976 function.modifiers = CCodeModifiers.STATIC;
978 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
980 push_function (function);
982 var collect_vpointer = new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"), "v_pointer");
984 ccode.open_if (collect_vpointer);
985 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("object", collect_vpointer));
986 var obj_identifier = new CCodeIdentifier ("object");
987 var l_expression = new CCodeMemberAccess (new CCodeMemberAccess.pointer (obj_identifier, "parent_instance"), "g_class");
988 var sub_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, l_expression, new CCodeConstant ("NULL"));
989 var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME"));
990 value_type_name_fct.add_argument (new CCodeConstant ("value"));
992 ccode.open_if (sub_condition);
993 var true_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
994 true_return.add_argument (new CCodeConstant ("\"invalid unclassed object pointer for value type `\""));
995 true_return.add_argument (value_type_name_fct);
996 true_return.add_argument (new CCodeConstant ("\"'\""));
997 true_return.add_argument (new CCodeConstant ("NULL"));
998 ccode.add_return (true_return);
1000 var reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
1001 var type_check = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1002 type_check.add_argument (new CCodeIdentifier ("object"));
1003 reg_call.add_argument (type_check);
1004 var stored_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
1005 stored_type.add_argument (new CCodeIdentifier ("value"));
1006 reg_call.add_argument (stored_type);
1008 ccode.else_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, reg_call));
1009 var false_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
1010 var type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("g_type_name"));
1011 type_name_fct.add_argument (type_check);
1012 false_return.add_argument (new CCodeConstant ("\"invalid object type `\""));
1013 false_return.add_argument (type_name_fct);
1014 false_return.add_argument (new CCodeConstant ("\"' for value type `\""));
1015 false_return.add_argument (value_type_name_fct);
1016 false_return.add_argument (new CCodeConstant ("\"'\""));
1017 false_return.add_argument (new CCodeConstant ("NULL"));
1018 ccode.add_return (false_return);
1022 var ref_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
1023 ref_call.add_argument (new CCodeIdentifier ("object"));
1024 ccode.add_assignment (vpointer, ref_call);
1027 ccode.add_assignment (vpointer, new CCodeConstant ("NULL"));
1031 ccode.add_return (new CCodeConstant ("NULL"));
1034 cfile.add_function (function);
1037 private void add_g_param_spec_type_function (Class cl) {
1038 var function = new CCodeFunction (get_ccode_param_spec_function (cl), "GParamSpec*");
1039 function.add_parameter (new CCodeParameter ("name", "const gchar*"));
1040 function.add_parameter (new CCodeParameter ("nick", "const gchar*"));
1041 function.add_parameter (new CCodeParameter ("blurb", "const gchar*"));
1042 function.add_parameter (new CCodeParameter ("object_type", "GType"));
1043 function.add_parameter (new CCodeParameter ("flags", "GParamFlags"));
1045 if (cl.is_private_symbol ()) {
1046 function.modifiers = CCodeModifiers.STATIC;
1047 } else if (context.hide_internal && cl.is_internal_symbol ()) {
1048 function.modifiers = CCodeModifiers.INTERNAL;
1051 push_function (function);
1053 ccode.add_declaration ("%sParamSpec%s*".printf (get_ccode_prefix (cl.parent_symbol), cl.name), new CCodeVariableDeclarator ("spec"));
1055 var subccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_is_a"));
1056 subccall.add_argument (new CCodeIdentifier ("object_type"));
1057 subccall.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1059 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail"));
1060 ccall.add_argument (subccall);
1061 ccall.add_argument (new CCodeConstant ("NULL"));
1062 ccode.add_expression (ccall);
1064 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_internal"));
1065 ccall.add_argument (new CCodeIdentifier ( "G_TYPE_PARAM_OBJECT" ));
1066 ccall.add_argument (new CCodeIdentifier ("name"));
1067 ccall.add_argument (new CCodeIdentifier ("nick"));
1068 ccall.add_argument (new CCodeIdentifier ("blurb"));
1069 ccall.add_argument (new CCodeIdentifier ("flags"));
1071 ccode.add_assignment (new CCodeIdentifier ("spec"), ccall);
1073 ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_PARAM_SPEC"));
1074 ccall.add_argument (new CCodeIdentifier ("spec"));
1076 ccode.add_assignment (new CCodeMemberAccess.pointer (ccall, "value_type"), new CCodeIdentifier ("object_type"));
1077 ccode.add_return (ccall);
1080 cfile.add_function (function);
1083 private void add_g_value_set_function (Class cl) {
1084 var function = new CCodeFunction (get_ccode_set_value_function (cl), "void");
1085 function.add_parameter (new CCodeParameter ("value", "GValue*"));
1086 function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
1088 if (cl.is_private_symbol ()) {
1089 function.modifiers = CCodeModifiers.STATIC;
1090 } else if (context.hide_internal && cl.is_internal_symbol ()) {
1091 function.modifiers = CCodeModifiers.INTERNAL;
1094 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
1096 push_function (function);
1098 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("old"));
1100 var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1101 ccall_typecheck.add_argument (new CCodeIdentifier ( "value" ));
1102 ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1104 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1105 ccall.add_argument (ccall_typecheck);
1106 ccode.add_expression (ccall);
1108 ccode.add_assignment (new CCodeConstant ("old"), vpointer);
1110 ccode.open_if (new CCodeIdentifier ("v_object"));
1111 ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
1112 ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" ));
1113 ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1115 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1116 ccall.add_argument (ccall_typecheck);
1117 ccode.add_expression (ccall);
1119 var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1120 ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" ));
1122 var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
1123 ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" ));
1125 var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
1126 ccall_typecompatible.add_argument (ccall_typefrominstance);
1127 ccall_typecompatible.add_argument (ccall_gvaluetype);
1129 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1130 ccall.add_argument (ccall_typecompatible);
1131 ccode.add_expression (ccall);
1133 ccode.add_assignment (vpointer, new CCodeConstant ("v_object"));
1135 ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
1136 ccall.add_argument (vpointer);
1137 ccode.add_expression (ccall);
1140 ccode.add_assignment (vpointer, new CCodeConstant ("NULL"));
1143 ccode.open_if (new CCodeIdentifier ("old"));
1144 ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (cl)));
1145 ccall.add_argument (new CCodeIdentifier ("old"));
1146 ccode.add_expression (ccall);
1150 cfile.add_function (function);
1153 private void add_g_value_take_function (Class cl) {
1154 var function = new CCodeFunction (get_ccode_take_value_function (cl), "void");
1155 function.add_parameter (new CCodeParameter ("value", "GValue*"));
1156 function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
1158 if (cl.is_private_symbol ()) {
1159 function.modifiers = CCodeModifiers.STATIC;
1160 } else if (context.hide_internal && cl.is_internal_symbol ()) {
1161 function.modifiers = CCodeModifiers.INTERNAL;
1164 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
1166 push_function (function);
1168 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("old"));
1170 var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1171 ccall_typecheck.add_argument (new CCodeIdentifier ( "value" ));
1172 ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1174 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1175 ccall.add_argument (ccall_typecheck);
1176 ccode.add_expression (ccall);
1178 ccode.add_assignment (new CCodeConstant ("old"), vpointer);
1180 ccode.open_if (new CCodeIdentifier ("v_object"));
1182 ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
1183 ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" ));
1184 ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1186 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1187 ccall.add_argument (ccall_typecheck);
1188 ccode.add_expression (ccall);
1190 var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1191 ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" ));
1193 var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
1194 ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" ));
1196 var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
1197 ccall_typecompatible.add_argument (ccall_typefrominstance);
1198 ccall_typecompatible.add_argument (ccall_gvaluetype);
1200 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1201 ccall.add_argument (ccall_typecompatible);
1202 ccode.add_expression (ccall);
1204 ccode.add_assignment (vpointer, new CCodeConstant ("v_object"));
1207 ccode.add_assignment (vpointer, new CCodeConstant ("NULL"));
1210 ccode.open_if (new CCodeIdentifier ("old"));
1211 ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (cl)));
1212 ccall.add_argument (new CCodeIdentifier ("old"));
1213 ccode.add_expression (ccall);
1217 cfile.add_function (function);
1220 private void add_g_value_get_function (Class cl) {
1221 var function = new CCodeFunction (get_ccode_get_value_function (cl), "gpointer");
1222 function.add_parameter (new CCodeParameter ("value", "const GValue*"));
1224 if (cl.is_private_symbol ()) {
1225 function.modifiers = CCodeModifiers.STATIC;
1226 } else if (context.hide_internal && cl.is_internal_symbol ()) {
1227 function.modifiers = CCodeModifiers.INTERNAL;
1230 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
1232 push_function (function);
1234 var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1235 ccall_typecheck.add_argument (new CCodeIdentifier ("value"));
1236 ccall_typecheck.add_argument (new CCodeIdentifier (get_ccode_type_id (cl)));
1238 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail"));
1239 ccall.add_argument (ccall_typecheck);
1240 ccall.add_argument (new CCodeConstant ("NULL"));
1241 ccode.add_expression (ccall);
1243 ccode.add_return (vpointer);
1246 cfile.add_function (function);
1249 private void begin_base_init_function (Class cl) {
1250 push_context (base_init_context);
1252 var base_init = new CCodeFunction ("%s_base_init".printf (get_ccode_lower_case_name (cl, null)), "void");
1253 base_init.add_parameter (new CCodeParameter ("klass", "%s *".printf (get_ccode_type_name (cl))));
1254 base_init.modifiers = CCodeModifiers.STATIC;
1256 push_function (base_init);
1261 private void add_base_init_function (Class cl) {
1262 cfile.add_function (base_init_context.ccode);
1265 public virtual void generate_class_init (Class cl) {
1268 public virtual void end_instance_init (Class cl) {
1271 private void begin_class_init_function (Class cl) {
1272 push_context (class_init_context);
1274 var func = new CCodeFunction ("%s_class_init".printf (get_ccode_lower_case_name (cl, null)));
1275 func.add_parameter (new CCodeParameter ("klass", "%s *".printf (get_ccode_type_name (cl))));
1276 func.add_parameter (new CCodeParameter ("klass_data", "gpointer"));
1277 func.modifiers = CCodeModifiers.STATIC;
1279 CCodeFunctionCall ccall;
1281 /* save pointer to parent class */
1282 var parent_decl = new CCodeDeclaration ("gpointer");
1283 var parent_var_decl = new CCodeVariableDeclarator ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null)));
1284 parent_var_decl.initializer = new CCodeConstant ("NULL");
1285 parent_decl.add_declarator (parent_var_decl);
1286 parent_decl.modifiers = CCodeModifiers.STATIC;
1287 cfile.add_type_member_declaration (parent_decl);
1289 push_function (func);
1291 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent"));
1292 ccall.add_argument (new CCodeIdentifier ("klass"));
1293 var parent_assignment = new CCodeAssignment (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null))), ccall);
1294 ccode.add_expression (parent_assignment);
1297 if (!cl.is_compact && !cl.is_subtype_of (gobject_type) && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
1298 // set finalize function
1299 var fundamental_class = cl;
1300 while (fundamental_class.base_class != null) {
1301 fundamental_class = fundamental_class.base_class;
1304 var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%s *".printf (get_ccode_type_name (fundamental_class)));
1305 var finalize_assignment = new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "finalize"), new CCodeIdentifier ("%sfinalize".printf (get_ccode_lower_case_prefix (cl))));
1306 ccode.add_expression (finalize_assignment);
1309 /* add struct for private fields */
1310 if (cl.has_private_fields || cl.has_type_parameters ()) {
1311 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_adjust_private_offset"));
1312 ccall.add_argument (new CCodeIdentifier ("klass"));
1313 ccall.add_argument (new CCodeIdentifier ("&%s_private_offset".printf (get_ccode_name (cl))));
1314 ccode.add_expression (ccall);
1317 /* connect overridden methods */
1318 foreach (Method m in cl.get_methods ()) {
1319 if (m.base_method == null) {
1322 var base_type = (ObjectTypeSymbol) m.base_method.parent_symbol;
1324 // there is currently no default handler for abstract async methods
1325 if (!m.is_abstract || !m.coroutine) {
1326 generate_method_declaration (m.base_method, cfile);
1328 CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (m));
1329 cfunc = cast_method_pointer (m.base_method, cfunc, base_type, (m.coroutine ? 1 : 3));
1330 var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%s *".printf (get_ccode_type_name (base_type)));
1331 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (m.base_method)), cfunc);
1334 cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m));
1335 cfunc = cast_method_pointer (m.base_method, cfunc, base_type, 2);
1336 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_finish_vfunc_name (m.base_method)), cfunc);
1341 /* connect default signal handlers */
1342 foreach (Signal sig in cl.get_signals ()) {
1343 if (sig.default_handler == null || !sig.is_virtual) {
1347 var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%s *".printf (get_ccode_type_name (cl)));
1348 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (sig.default_handler)), new CCodeIdentifier (get_ccode_real_name (sig.default_handler)));
1351 /* connect overridden properties */
1352 foreach (Property prop in cl.get_properties ()) {
1353 if (prop.base_property == null) {
1356 var base_type = (Class) prop.base_property.parent_symbol;
1358 var ccast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function (base_type)));
1359 ccast.add_argument (new CCodeIdentifier ("klass"));
1361 if (!get_ccode_no_accessor_method (prop.base_property) && !get_ccode_concrete_accessor (prop.base_property)) {
1362 if (prop.get_accessor != null) {
1363 generate_property_accessor_declaration (prop.base_property.get_accessor, cfile);
1365 string cname = get_ccode_real_name (prop.get_accessor);
1366 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), new CCodeIdentifier (cname));
1368 if (prop.set_accessor != null) {
1369 generate_property_accessor_declaration (prop.base_property.set_accessor, cfile);
1371 string cname = get_ccode_real_name (prop.set_accessor);
1372 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), new CCodeIdentifier (cname));
1377 generate_class_init (cl);
1379 if (!cl.is_compact) {
1380 /* create signals */
1381 foreach (Signal sig in cl.get_signals ()) {
1382 if (sig.comment != null) {
1383 ccode.add_statement (new CCodeComment (sig.comment.content));
1385 ccode.add_expression (get_signal_creation (sig, cl));
1392 private void add_class_init_function (Class cl) {
1393 cfile.add_function (class_init_context.ccode);
1396 private void add_generic_accessor_function (string base_name, string return_type, CCodeExpression? expression, TypeParameter p, Class cl, Interface iface) {
1397 string name = "%s_%s_%s".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface), base_name);
1399 var function = new CCodeFunction (name, return_type);
1400 function.modifiers = CCodeModifiers.STATIC;
1401 var this_type = SemanticAnalyzer.get_data_type_for_symbol (cl);
1402 function.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
1403 push_function (function);
1404 ccode.add_return (expression);
1406 cfile.add_function (function);
1408 CCodeExpression cfunc = new CCodeIdentifier (function.name);
1409 string cast = "%s (*)".printf (return_type);
1410 string cast_args = "%s *".printf (get_ccode_name (iface));
1411 cast = "%s (%s)".printf (cast, cast_args);
1412 cfunc = new CCodeCastExpression (cfunc, cast);
1413 var ciface = new CCodeIdentifier ("iface");
1414 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, base_name), cfunc);
1417 private void add_interface_init_function (Class cl, Interface iface) {
1418 var iface_init = new CCodeFunction ("%s_%s_interface_init".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface)), "void");
1419 iface_init.add_parameter (new CCodeParameter ("iface", "%s *".printf (get_ccode_type_name (iface))));
1420 iface_init.add_parameter (new CCodeParameter ("iface_data", "gpointer"));
1421 iface_init.modifiers = CCodeModifiers.STATIC;
1423 push_function (iface_init);
1425 CCodeFunctionCall ccall;
1427 /* save pointer to parent vtable */
1428 string parent_iface_var = "%s_%s_parent_iface".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface));
1429 var parent_decl = new CCodeDeclaration ("%s *".printf (get_ccode_type_name (iface)));
1430 var parent_var_decl = new CCodeVariableDeclarator (parent_iface_var);
1431 parent_var_decl.initializer = new CCodeConstant ("NULL");
1432 parent_decl.add_declarator (parent_var_decl);
1433 parent_decl.modifiers = CCodeModifiers.STATIC;
1434 cfile.add_type_member_declaration (parent_decl);
1435 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_interface_peek_parent"));
1436 ccall.add_argument (new CCodeIdentifier ("iface"));
1437 ccode.add_assignment (new CCodeIdentifier (parent_iface_var), ccall);
1439 foreach (Method m in cl.get_methods ()) {
1440 if (m.base_interface_method == null) {
1444 var base_type = m.base_interface_method.parent_symbol;
1445 if (base_type != iface) {
1449 generate_method_declaration (m.base_interface_method, cfile);
1451 var ciface = new CCodeIdentifier ("iface");
1452 CCodeExpression cfunc;
1453 if (m.is_abstract || m.is_virtual) {
1454 cfunc = new CCodeIdentifier (get_ccode_name (m));
1456 cfunc = new CCodeIdentifier (get_ccode_real_name (m));
1458 cfunc = cast_method_pointer (m.base_interface_method, cfunc, iface, (m.coroutine ? 1 : 3));
1459 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m.base_interface_method)), cfunc);
1462 if (m.is_abstract || m.is_virtual) {
1463 cfunc = new CCodeIdentifier (get_ccode_finish_name (m));
1465 cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m));
1467 cfunc = cast_method_pointer (m.base_interface_method, cfunc, iface, 2);
1468 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_finish_vfunc_name (m.base_interface_method)), cfunc);
1472 if (iface.get_attribute ("GenericAccessors") != null) {
1473 foreach (TypeParameter p in iface.get_type_parameters ()) {
1474 GenericType p_type = new GenericType (p);
1475 DataType p_data_type = p_type.get_actual_type (SemanticAnalyzer.get_data_type_for_symbol (cl), null, cl);
1477 add_generic_accessor_function ("get_%s".printf (get_ccode_type_id (p)),
1479 get_type_id_expression (p_data_type),
1482 add_generic_accessor_function ("get_%s".printf (get_ccode_copy_function (p)),
1484 get_dup_func_expression (p_data_type, p_data_type.source_reference),
1487 add_generic_accessor_function ("get_%s".printf (get_ccode_destroy_function (p)),
1489 get_destroy_func_expression (p_data_type),
1494 // connect inherited implementations
1495 var it = cl.get_implicit_implementations ().map_iterator ();
1496 while (it.next ()) {
1497 Method m = it.get_key ();
1498 if (m.parent_symbol == iface) {
1499 Method base_method = it.get_value ();
1501 generate_method_declaration (base_method, cfile);
1503 CCodeExpression cfunc = new CCodeIdentifier (get_ccode_name (base_method));
1504 cfunc = cast_method_pointer (m, cfunc, iface);
1505 var ciface = new CCodeIdentifier ("iface");
1506 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m)), cfunc);
1510 foreach (Property prop in cl.get_properties ()) {
1511 if (prop.base_interface_property == null) {
1515 var base_type = (ObjectTypeSymbol) prop.base_interface_property.parent_symbol;
1516 if (base_type != iface) {
1520 var ciface = new CCodeIdentifier ("iface");
1522 if (!get_ccode_no_accessor_method (prop.base_interface_property) && !get_ccode_concrete_accessor (prop.base_interface_property)) {
1523 if (prop.get_accessor != null) {
1524 generate_property_accessor_declaration (prop.base_interface_property.get_accessor, cfile);
1526 string cname = get_ccode_real_name (prop.get_accessor);
1527 if (prop.is_abstract || prop.is_virtual) {
1528 cname = get_ccode_name (prop.get_accessor);
1531 CCodeExpression cfunc = new CCodeIdentifier (cname);
1532 if (prop.is_abstract || prop.is_virtual) {
1533 cfunc = cast_property_accessor_pointer (prop.get_accessor, cfunc, base_type);
1535 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), cfunc);
1537 if (prop.set_accessor != null) {
1538 generate_property_accessor_declaration (prop.base_interface_property.set_accessor, cfile);
1540 string cname = get_ccode_real_name (prop.set_accessor);
1541 if (prop.is_abstract || prop.is_virtual) {
1542 cname = get_ccode_name (prop.set_accessor);
1545 CCodeExpression cfunc = new CCodeIdentifier (cname);
1546 if (prop.is_abstract || prop.is_virtual) {
1547 cfunc = cast_property_accessor_pointer (prop.set_accessor, cfunc, base_type);
1549 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), cfunc);
1554 foreach (Property prop in iface.get_properties ()) {
1555 if (!prop.is_abstract) {
1559 Property cl_prop = null;
1560 var base_class = cl;
1561 while (base_class != null && cl_prop == null) {
1562 cl_prop = base_class.scope.lookup (prop.name) as Property;
1563 base_class = base_class.base_class;
1565 if (base_class != null && cl_prop.parent_symbol != cl) {
1566 // property inherited from base class
1568 var base_property = cl_prop;
1569 if (cl_prop.base_property != null) {
1570 base_property = cl_prop.base_property;
1571 } else if (cl_prop.base_interface_property != null) {
1572 base_property = cl_prop.base_interface_property;
1575 // Our base class provides this interface implementation
1576 if (prop == base_property) {
1580 var ciface = new CCodeIdentifier ("iface");
1582 if (base_property.get_accessor != null && prop.get_accessor != null) {
1583 generate_property_accessor_declaration (base_property.get_accessor, cfile);
1585 string cname = get_ccode_name (base_property.get_accessor);
1586 CCodeExpression cfunc = new CCodeIdentifier (cname);
1587 cfunc = cast_property_accessor_pointer (prop.get_accessor, cfunc, iface);
1588 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), cfunc);
1590 if (base_property.set_accessor != null && prop.set_accessor != null) {
1591 generate_property_accessor_declaration (base_property.set_accessor, cfile);
1593 string cname = get_ccode_name (base_property.set_accessor);
1594 CCodeExpression cfunc = new CCodeIdentifier (cname);
1595 cfunc = cast_property_accessor_pointer (prop.set_accessor, cfunc, iface);
1596 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), cfunc);
1602 cfile.add_function (iface_init);
1605 CCodeExpression cast_property_accessor_pointer (PropertyAccessor acc, CCodeExpression cfunc, ObjectTypeSymbol base_type) {
1607 if (acc.readable && acc.value_type.is_real_non_null_struct_type ()) {
1608 cast = "void (*) (%s *, %s *)".printf (get_ccode_name (base_type), get_ccode_name (acc.value_type));
1609 } else if (acc.readable) {
1610 cast = "%s (*) (%s *)".printf (get_ccode_name (acc.value_type), get_ccode_name (base_type));
1611 } else if (acc.value_type.is_real_non_null_struct_type ()) {
1612 cast = "void (*) (%s *, %s *)".printf (get_ccode_name (base_type), get_ccode_name (acc.value_type));
1614 cast = "void (*) (%s *, %s)".printf (get_ccode_name (base_type), get_ccode_name (acc.value_type));
1616 return new CCodeCastExpression (cfunc, cast);
1619 CCodeExpression cast_method_pointer (Method m, CCodeExpression cfunc, ObjectTypeSymbol base_type, int direction = 3) {
1620 // Cast the function pointer to match the interface
1622 if (direction == 1 || m.return_type.is_real_non_null_struct_type ()) {
1625 cast = "%s (*)".printf (get_ccode_name (m.return_type));
1628 var vdeclarator = new CCodeFunctionDeclarator (get_ccode_vfunc_name (m));
1629 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
1631 generate_cparameters (m, cfile, cparam_map, new CCodeFunction ("fake"), vdeclarator, null, null, direction);
1633 // append C arguments in the right order
1636 string cast_args = "";
1639 foreach (int pos in cparam_map.get_keys ()) {
1640 if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
1644 if (min_pos == -1) {
1647 if (last_pos != -1) {
1648 cast_args = "%s, ".printf (cast_args);
1650 var cparam = cparam_map.get (min_pos);
1651 if (cparam.ellipsis) {
1652 cast_args = "%s...".printf (cast_args);
1654 cast_args = "%s%s".printf (cast_args, cparam.type_name);
1658 cast = "%s (%s)".printf (cast, cast_args);
1659 return new CCodeCastExpression (cfunc, cast);
1662 private void begin_instance_init_function (Class cl) {
1663 push_context (instance_init_context);
1665 var func = new CCodeFunction ("%s_instance_init".printf (get_ccode_lower_case_name (cl, null)));
1666 func.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl))));
1667 if (!cl.is_compact) {
1668 func.add_parameter (new CCodeParameter ("klass", "gpointer"));
1670 func.modifiers = CCodeModifiers.STATIC;
1672 push_function (func);
1674 bool is_gsource = cl.is_subtype_of (gsource_type);
1676 if (cl.is_compact) {
1677 // Add declaration, since the instance_init function is explicitly called
1678 // by the creation methods
1679 cfile.add_function_declaration (func);
1681 // connect overridden methods
1682 foreach (Method m in cl.get_methods ()) {
1683 if (m.base_method == null || is_gsource) {
1686 var base_type = (ObjectTypeSymbol) m.base_method.parent_symbol;
1688 // there is currently no default handler for abstract async methods
1689 if (!m.is_abstract || !m.coroutine) {
1690 generate_method_declaration (m.base_method, cfile);
1692 CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (m));
1693 cfunc = cast_method_pointer (m.base_method, cfunc, base_type, (m.coroutine ? 1 : 3));
1694 var ccast = new CCodeCastExpression (new CCodeIdentifier ("self"), "%s *".printf (get_ccode_name (base_type)));
1695 func.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (m.base_method)), cfunc);
1698 cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m));
1699 cfunc = cast_method_pointer (m.base_method, cfunc, base_type, 2);
1700 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_finish_vfunc_name (m.base_method)), cfunc);
1705 // connect overridden properties
1706 foreach (Property prop in cl.get_properties ()) {
1707 if (prop.base_property == null || is_gsource) {
1710 var base_type = prop.base_property.parent_symbol;
1712 var ccast = new CCodeCastExpression (new CCodeIdentifier ("self"), "%s *".printf (get_ccode_name (base_type)));
1714 if (!get_ccode_no_accessor_method (prop.base_property) && !get_ccode_concrete_accessor (prop.base_property)) {
1715 if (prop.get_accessor != null) {
1716 generate_property_accessor_declaration (prop.base_property.get_accessor, cfile);
1718 string cname = get_ccode_real_name (prop.get_accessor);
1719 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), new CCodeIdentifier (cname));
1721 if (prop.set_accessor != null) {
1722 generate_property_accessor_declaration (prop.base_property.set_accessor, cfile);
1724 string cname = get_ccode_real_name (prop.set_accessor);
1725 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), new CCodeIdentifier (cname));
1731 if (!cl.is_compact && (cl.has_private_fields || cl.has_type_parameters ())) {
1732 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_get_instance_private".printf (get_ccode_lower_case_name (cl, null))));
1733 ccall.add_argument (new CCodeIdentifier ("self"));
1734 func.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall);
1740 private void add_instance_init_function (Class cl) {
1741 push_context (instance_init_context);
1742 end_instance_init (cl);
1745 cfile.add_function (instance_init_context.ccode);
1748 private void begin_class_finalize_function (Class cl) {
1749 push_context (class_finalize_context);
1751 var function = new CCodeFunction ("%s_class_finalize".printf (get_ccode_lower_case_name (cl, null)), "void");
1752 function.modifiers = CCodeModifiers.STATIC;
1754 function.add_parameter (new CCodeParameter ("klass", "%s *".printf (get_ccode_type_name (cl))));
1756 push_function (function);
1758 if (cl.static_destructor != null) {
1759 cl.static_destructor.body.emit (this);
1761 if (current_method_inner_error) {
1762 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL")));
1765 if (current_method_return) {
1766 // support return statements in destructors
1767 ccode.add_label ("_return");
1768 ccode.add_statement (new CCodeEmptyStatement ());
1775 private void add_class_finalize_function (Class cl) {
1776 cfile.add_function_declaration (class_finalize_context.ccode);
1777 cfile.add_function (class_finalize_context.ccode);
1780 private void begin_base_finalize_function (Class cl) {
1781 push_context (base_finalize_context);
1783 var function = new CCodeFunction ("%s_base_finalize".printf (get_ccode_lower_case_name (cl, null)), "void");
1784 function.modifiers = CCodeModifiers.STATIC;
1786 function.add_parameter (new CCodeParameter ("klass", "%s *".printf (get_ccode_type_name (cl))));
1787 function.add_parameter (new CCodeParameter ("klass_data", "gpointer"));
1789 push_function (function);
1791 if (cl.class_destructor != null) {
1792 cl.class_destructor.body.emit (this);
1794 if (current_method_inner_error) {
1795 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL")));
1798 if (current_method_return) {
1799 // support return statements in destructors
1800 ccode.add_label ("_return");
1801 ccode.add_statement (new CCodeEmptyStatement ());
1808 private void add_base_finalize_function (Class cl) {
1809 push_context (base_finalize_context);
1811 cfile.add_function_declaration (ccode);
1812 cfile.add_function (ccode);
1817 private void begin_finalize_function (Class cl) {
1818 push_context (instance_finalize_context);
1820 bool is_gsource = cl.is_subtype_of (gsource_type);
1822 if (!cl.is_compact || is_gsource) {
1823 var fundamental_class = cl;
1824 while (fundamental_class.base_class != null) {
1825 fundamental_class = fundamental_class.base_class;
1828 var func = new CCodeFunction ("%sfinalize".printf (get_ccode_lower_case_prefix (cl)));
1829 func.add_parameter (new CCodeParameter ("obj", "%s *".printf (get_ccode_name (fundamental_class))));
1830 func.modifiers = CCodeModifiers.STATIC;
1832 push_function (func);
1835 cfile.add_function_declaration (func);
1838 CCodeExpression ccast;
1839 if (!cl.is_compact) {
1840 ccast = generate_instance_cast (new CCodeIdentifier ("obj"), cl);
1842 ccast = new CCodeCastExpression (new CCodeIdentifier ("obj"), "%s *".printf (get_ccode_name (cl)));
1845 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self"));
1846 ccode.add_assignment (new CCodeIdentifier ("self"), ccast);
1848 if (!cl.is_compact && cl.base_class == null) {
1849 // non-gobject class
1850 var call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_handlers_destroy"));
1851 call.add_argument (new CCodeIdentifier ("self"));
1852 ccode.add_expression (call);
1854 } else if (cl.base_class == null) {
1855 var function = new CCodeFunction (get_ccode_free_function (cl), "void");
1856 if (cl.is_private_symbol ()) {
1857 function.modifiers = CCodeModifiers.STATIC;
1858 } else if (context.hide_internal && cl.is_internal_symbol ()) {
1859 function.modifiers = CCodeModifiers.INTERNAL;
1862 function.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl))));
1864 push_function (function);
1867 if (cl.destructor != null) {
1868 cl.destructor.body.emit (this);
1870 if (current_method_inner_error) {
1871 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL")));
1874 if (current_method_return) {
1875 // support return statements in destructors
1876 ccode.add_label ("_return");
1883 private void add_finalize_function (Class cl) {
1884 if (!cl.is_compact) {
1885 var fundamental_class = cl;
1886 while (fundamental_class.base_class != null) {
1887 fundamental_class = fundamental_class.base_class;
1890 // chain up to finalize function of the base class
1891 if (cl.base_class != null) {
1892 var ccast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function (fundamental_class)));
1893 ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null))));
1894 var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
1895 ccall.add_argument (new CCodeIdentifier ("obj"));
1896 push_context (instance_finalize_context);
1897 ccode.add_expression (ccall);
1901 cfile.add_function_declaration (instance_finalize_context.ccode);
1902 cfile.add_function (instance_finalize_context.ccode);
1903 } else if (cl.base_class == null) {
1904 // g_slice_free needs glib.h
1905 cfile.add_include ("glib.h");
1906 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
1907 ccall.add_argument (new CCodeIdentifier (get_ccode_name (cl)));
1908 ccall.add_argument (new CCodeIdentifier ("self"));
1909 push_context (instance_finalize_context);
1910 ccode.add_expression (ccall);
1913 cfile.add_function (instance_finalize_context.ccode);
1914 } else if (cl.is_subtype_of (gsource_type)) {
1915 cfile.add_function (instance_finalize_context.ccode);
1919 public override CCodeExpression get_param_spec_cexpression (Property prop) {
1920 var cl = (TypeSymbol) prop.parent_symbol;
1921 var prop_array = new CCodeIdentifier ("%s_properties".printf (get_ccode_lower_case_name (cl)));
1922 var prop_enum_value = new CCodeIdentifier ("%s_PROPERTY".printf (get_ccode_upper_case_name (prop)));
1924 return new CCodeElementAccess (prop_array, prop_enum_value);
1927 public override CCodeExpression get_param_spec (Property prop) {
1928 var cspec = new CCodeFunctionCall ();
1929 cspec.add_argument (get_property_canonical_cconstant (prop));
1930 cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.nick)));
1931 cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.blurb)));
1933 unowned TypeSymbol? type_symbol = prop.property_type.type_symbol;
1934 if (type_symbol is Class || type_symbol is Interface) {
1935 string param_spec_name = get_ccode_param_spec_function (type_symbol);
1936 cspec.call = new CCodeIdentifier (param_spec_name);
1937 if (param_spec_name == "g_param_spec_string") {
1938 cspec.add_argument (new CCodeConstant ("NULL"));
1939 } else if (param_spec_name == "g_param_spec_variant") {
1940 cspec.add_argument (new CCodeConstant ("G_VARIANT_TYPE_ANY"));
1941 cspec.add_argument (new CCodeConstant ("NULL"));
1942 } else if (param_spec_name == "gtk_param_spec_expression") {
1943 // No additional parameter required
1944 } else if (get_ccode_type_id (type_symbol) != "G_TYPE_POINTER") {
1945 cspec.add_argument (new CCodeIdentifier (get_ccode_type_id (type_symbol)));
1947 } else if (type_symbol is Enum) {
1948 unowned Enum e = (Enum) type_symbol;
1949 if (get_ccode_has_type_id (e)) {
1951 cspec.call = new CCodeIdentifier ("g_param_spec_flags");
1953 cspec.call = new CCodeIdentifier ("g_param_spec_enum");
1955 cspec.add_argument (new CCodeIdentifier (get_ccode_type_id (e)));
1958 cspec.call = new CCodeIdentifier ("g_param_spec_uint");
1959 cspec.add_argument (new CCodeConstant ("0"));
1960 cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
1962 cspec.call = new CCodeIdentifier ("g_param_spec_int");
1963 cspec.add_argument (new CCodeConstant ("G_MININT"));
1964 cspec.add_argument (new CCodeConstant ("G_MAXINT"));
1968 if (prop.initializer != null) {
1969 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1971 cspec.add_argument (new CCodeConstant (get_ccode_default_value (type_symbol)));
1973 } else if (type_symbol is Struct) {
1974 unowned Struct st = (Struct) type_symbol;
1975 var type_id = get_ccode_type_id (st);
1976 if (type_id == "G_TYPE_INT") {
1977 cspec.call = new CCodeIdentifier ("g_param_spec_int");
1978 cspec.add_argument (new CCodeConstant ("G_MININT"));
1979 cspec.add_argument (new CCodeConstant ("G_MAXINT"));
1980 if (prop.initializer != null) {
1981 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1983 cspec.add_argument (new CCodeConstant ("0"));
1985 } else if (type_id == "G_TYPE_UINT") {
1986 cspec.call = new CCodeIdentifier ("g_param_spec_uint");
1987 cspec.add_argument (new CCodeConstant ("0"));
1988 cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
1989 if (prop.initializer != null) {
1990 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1992 cspec.add_argument (new CCodeConstant ("0U"));
1994 } else if (type_id == "G_TYPE_INT64") {
1995 cspec.call = new CCodeIdentifier ("g_param_spec_int64");
1996 cspec.add_argument (new CCodeConstant ("G_MININT64"));
1997 cspec.add_argument (new CCodeConstant ("G_MAXINT64"));
1998 if (prop.initializer != null) {
1999 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2001 cspec.add_argument (new CCodeConstant ("0"));
2003 } else if (type_id == "G_TYPE_UINT64") {
2004 cspec.call = new CCodeIdentifier ("g_param_spec_uint64");
2005 cspec.add_argument (new CCodeConstant ("0"));
2006 cspec.add_argument (new CCodeConstant ("G_MAXUINT64"));
2007 if (prop.initializer != null) {
2008 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2010 cspec.add_argument (new CCodeConstant ("0U"));
2012 } else if (type_id == "G_TYPE_LONG") {
2013 cspec.call = new CCodeIdentifier ("g_param_spec_long");
2014 cspec.add_argument (new CCodeConstant ("G_MINLONG"));
2015 cspec.add_argument (new CCodeConstant ("G_MAXLONG"));
2016 if (prop.initializer != null) {
2017 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2019 cspec.add_argument (new CCodeConstant ("0L"));
2021 } else if (type_id == "G_TYPE_ULONG") {
2022 cspec.call = new CCodeIdentifier ("g_param_spec_ulong");
2023 cspec.add_argument (new CCodeConstant ("0"));
2024 cspec.add_argument (new CCodeConstant ("G_MAXULONG"));
2025 if (prop.initializer != null) {
2026 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2028 cspec.add_argument (new CCodeConstant ("0UL"));
2030 } else if (type_id == "G_TYPE_BOOLEAN") {
2031 cspec.call = new CCodeIdentifier ("g_param_spec_boolean");
2032 if (prop.initializer != null) {
2033 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2035 cspec.add_argument (new CCodeConstant ("FALSE"));
2037 } else if (type_id == "G_TYPE_CHAR") {
2038 cspec.call = new CCodeIdentifier ("g_param_spec_char");
2039 cspec.add_argument (new CCodeConstant ("G_MININT8"));
2040 cspec.add_argument (new CCodeConstant ("G_MAXINT8"));
2041 if (prop.initializer != null) {
2042 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2044 cspec.add_argument (new CCodeConstant ("0"));
2046 } else if (type_id == "G_TYPE_UCHAR") {
2047 cspec.call = new CCodeIdentifier ("g_param_spec_uchar");
2048 cspec.add_argument (new CCodeConstant ("0"));
2049 cspec.add_argument (new CCodeConstant ("G_MAXUINT8"));
2050 if (prop.initializer != null) {
2051 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2053 cspec.add_argument (new CCodeConstant ("0"));
2055 } else if (type_id == "G_TYPE_FLOAT") {
2056 cspec.call = new CCodeIdentifier ("g_param_spec_float");
2057 cspec.add_argument (new CCodeConstant ("-G_MAXFLOAT"));
2058 cspec.add_argument (new CCodeConstant ("G_MAXFLOAT"));
2059 if (prop.initializer != null) {
2060 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2062 cspec.add_argument (new CCodeConstant ("0.0F"));
2064 } else if (type_id == "G_TYPE_DOUBLE") {
2065 cspec.call = new CCodeIdentifier ("g_param_spec_double");
2066 cspec.add_argument (new CCodeConstant ("-G_MAXDOUBLE"));
2067 cspec.add_argument (new CCodeConstant ("G_MAXDOUBLE"));
2068 if (prop.initializer != null) {
2069 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2071 cspec.add_argument (new CCodeConstant ("0.0"));
2073 } else if (type_id == "G_TYPE_GTYPE") {
2074 cspec.call = new CCodeIdentifier ("g_param_spec_gtype");
2075 if (prop.initializer != null) {
2076 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2078 cspec.add_argument (new CCodeConstant ("G_TYPE_NONE"));
2081 cspec.call = new CCodeIdentifier ("g_param_spec_boxed");
2082 cspec.add_argument (new CCodeIdentifier (type_id));
2084 } else if (prop.property_type is ArrayType && ((ArrayType)prop.property_type).element_type.type_symbol == string_type.type_symbol) {
2085 cspec.call = new CCodeIdentifier ("g_param_spec_boxed");
2086 cspec.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
2088 cspec.call = new CCodeIdentifier ("g_param_spec_pointer");
2091 var pflags = "G_PARAM_STATIC_STRINGS";
2092 if (prop.get_accessor != null && prop.get_accessor.access != SymbolAccessibility.PRIVATE) {
2093 pflags = "%s%s".printf (pflags, " | G_PARAM_READABLE");
2095 if (prop.set_accessor != null && prop.set_accessor.access != SymbolAccessibility.PRIVATE) {
2096 pflags = "%s%s".printf (pflags, " | G_PARAM_WRITABLE");
2097 if (prop.set_accessor.construction) {
2098 if (prop.set_accessor.writable) {
2099 pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT");
2101 pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT_ONLY");
2106 pflags = "%s%s".printf (pflags, " | G_PARAM_EXPLICIT_NOTIFY");
2108 if (prop.version.deprecated) {
2109 pflags = "%s%s".printf (pflags, " | G_PARAM_DEPRECATED");
2111 cspec.add_argument (new CCodeConstant (pflags));
2113 if (prop.parent_symbol is Interface) {
2116 return new CCodeAssignment (get_param_spec_cexpression (prop), cspec);
2120 public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
2121 if (add_symbol_declaration (decl_space, iface, get_ccode_name (iface))) {
2125 decl_space.add_include ("glib-object.h");
2127 var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (iface)));
2128 var type_struct = new CCodeStruct ("_%s".printf (get_ccode_type_name (iface)));
2130 decl_space.add_type_declaration (new CCodeNewline ());
2131 var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (iface, null));
2132 decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (iface), macro));
2134 macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (get_ccode_type_id (iface), get_ccode_name (iface));
2135 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_cast_function (iface)), macro));
2137 macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (get_ccode_type_id (iface));
2138 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_check_function (iface)), macro));
2140 macro = "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %s))".printf (get_ccode_type_id (iface), get_ccode_type_name (iface));
2141 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_get_function (iface)), macro));
2142 decl_space.add_type_declaration (new CCodeNewline ());
2144 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (iface)), new CCodeVariableDeclarator (get_ccode_name (iface))));
2145 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator (get_ccode_type_name (iface))));
2147 foreach (DataType prerequisite in iface.get_prerequisites ()) {
2148 unowned Class? prereq_cl = prerequisite.type_symbol as Class;
2149 unowned Interface? prereq_iface = prerequisite.type_symbol as Interface;
2150 if (prereq_cl != null) {
2151 generate_class_declaration (prereq_cl, decl_space);
2152 } else if (prereq_iface != null) {
2153 generate_interface_declaration (prereq_iface, decl_space);
2157 type_struct.add_field ("GTypeInterface", "parent_iface");
2159 if (iface.get_attribute ("GenericAccessors") != null) {
2160 foreach (TypeParameter p in iface.get_type_parameters ()) {
2161 var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (get_ccode_type_id (p)));
2162 var this_type = SemanticAnalyzer.get_data_type_for_symbol (iface);
2163 vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
2165 var vdecl = new CCodeDeclaration ("GType");
2166 vdecl.add_declarator (vdeclarator);
2167 type_struct.add_declaration (vdecl);
2169 vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (get_ccode_copy_function (p)));
2170 this_type = SemanticAnalyzer.get_data_type_for_symbol (iface);
2171 vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
2173 vdecl = new CCodeDeclaration ("GBoxedCopyFunc");
2174 vdecl.add_declarator (vdeclarator);
2175 type_struct.add_declaration (vdecl);
2177 vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (get_ccode_destroy_function (p)));
2178 this_type = SemanticAnalyzer.get_data_type_for_symbol (iface);
2179 vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
2181 vdecl = new CCodeDeclaration ("GDestroyNotify");
2182 vdecl.add_declarator (vdeclarator);
2183 type_struct.add_declaration (vdecl);
2187 foreach (Symbol sym in iface.get_virtuals ()) {
2191 if ((m = sym as Method) != null) {
2192 generate_struct_method_declaration (iface, m, instance_struct, type_struct, decl_space);
2193 } else if ((sig = sym as Signal) != null) {
2194 if (sig.default_handler != null) {
2195 if (sig.is_virtual) {
2196 generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
2198 generate_method_declaration (sig.default_handler, cfile);
2201 } else if ((prop = sym as Property) != null) {
2202 generate_struct_property_declaration (iface, prop, instance_struct, type_struct, decl_space);
2204 Report.error (sym.source_reference, "internal: Unsupported symbol");
2208 decl_space.add_type_definition (type_struct);
2210 var type_fun = new InterfaceRegisterFunction (iface);
2211 type_fun.init_from_type (context, in_plugin, true);
2212 decl_space.add_type_member_declaration (type_fun.get_declaration ());
2214 requires_vala_extern = true;
2217 public override void visit_interface (Interface iface) {
2218 push_context (new EmitContext (iface));
2219 push_line (iface.source_reference);
2221 var old_signal_enum = signal_enum;
2223 if (get_ccode_name (iface).length < 3) {
2225 Report.error (iface.source_reference, "Interface name `%s' is too short", get_ccode_name (iface));
2229 signal_enum = new CCodeEnum ();
2231 generate_interface_declaration (iface, cfile);
2232 if (!iface.is_internal_symbol ()) {
2233 generate_interface_declaration (iface, header_file);
2235 if (!iface.is_private_symbol ()) {
2236 generate_interface_declaration (iface, internal_header_file);
2239 iface.accept_children (this);
2241 if (iface.get_signals ().size > 0) {
2242 var last_signal = "%s_NUM_SIGNALS".printf (get_ccode_upper_case_name (iface));
2243 signal_enum.add_value (new CCodeEnumValue (last_signal));
2244 cfile.add_type_declaration (signal_enum);
2246 var signal_array_decl = new CCodeDeclaration ("guint");
2247 signal_array_decl.modifiers |= CCodeModifiers.STATIC;
2248 signal_array_decl.add_declarator (new CCodeVariableDeclarator ("%s_signals".printf (get_ccode_lower_case_name (iface)), new CCodeConstant ("{0}"), new CCodeDeclaratorSuffix.with_array (new CCodeIdentifier (last_signal))));
2249 cfile.add_type_declaration (signal_array_decl);
2252 add_interface_default_init_function (iface);
2254 if (iface.comment != null) {
2255 cfile.add_type_member_definition (new CCodeComment (iface.comment.content));
2258 var type_fun = new InterfaceRegisterFunction (iface);
2259 type_fun.init_from_type (context, in_plugin, false);
2260 cfile.add_type_member_declaration (type_fun.get_source_declaration ());
2261 cfile.add_type_member_definition (type_fun.get_definition ());
2263 signal_enum = old_signal_enum;
2269 private void add_interface_default_init_function (Interface iface) {
2270 push_context (new EmitContext (iface));
2272 var default_init = new CCodeFunction ("%s_default_init".printf (get_ccode_lower_case_name (iface, null)), "void");
2273 default_init.add_parameter (new CCodeParameter ("iface", "%s *".printf (get_ccode_type_name (iface))));
2274 default_init.add_parameter (new CCodeParameter ("iface_data", "gpointer"));
2275 default_init.modifiers = CCodeModifiers.STATIC;
2277 push_function (default_init);
2279 if (iface.is_subtype_of (gobject_type)) {
2280 /* create properties */
2281 var props = iface.get_properties ();
2282 foreach (Property prop in props) {
2283 if (prop.is_abstract) {
2284 if (!context.analyzer.is_gobject_property (prop)) {
2288 if (prop.comment != null) {
2289 ccode.add_statement (new CCodeComment (prop.comment.content));
2292 var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_interface_install_property"));
2293 cinst.add_argument (new CCodeIdentifier ("iface"));
2294 cinst.add_argument (get_param_spec (prop));
2296 ccode.add_expression (cinst);
2301 var ciface = new CCodeIdentifier ("iface");
2303 /* connect default signal handlers */
2304 foreach (Signal sig in iface.get_signals ()) {
2305 if (sig.default_handler == null || !sig.is_virtual) {
2308 var cname = get_ccode_real_name (sig.default_handler);
2309 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (sig.default_handler)), new CCodeIdentifier (cname));
2312 /* create signals */
2313 foreach (Signal sig in iface.get_signals ()) {
2314 if (sig.comment != null) {
2315 ccode.add_statement (new CCodeComment (sig.comment.content));
2317 ccode.add_expression (get_signal_creation (sig, iface));
2320 // connect default implementations
2321 foreach (Method m in iface.get_methods ()) {
2323 var cname = get_ccode_real_name (m);
2324 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m)), new CCodeIdentifier (cname));
2326 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_finish_vfunc_name (m)), new CCodeIdentifier (get_ccode_finish_real_name (m)));
2331 foreach (Property prop in iface.get_properties ()) {
2332 if (prop.is_virtual) {
2333 if (prop.get_accessor != null) {
2334 string cname = get_ccode_real_name (prop.get_accessor);
2335 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), new CCodeIdentifier (cname));
2337 if (prop.set_accessor != null) {
2338 string cname = get_ccode_real_name (prop.set_accessor);
2339 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), new CCodeIdentifier (cname));
2346 cfile.add_function (default_init);
2349 public override void visit_struct (Struct st) {
2350 // custom simple type structs cannot have a type id which depends on head-allocation
2351 if (st.get_attribute ("SimpleType") != null && !st.has_attribute_argument ("CCode", "type_id")) {
2352 st.set_attribute_bool ("CCode", "has_type_id", false);
2355 base.visit_struct (st);
2357 if (st.is_boolean_type () || st.is_integer_type () || st.is_floating_type ()) {
2358 // Skip GType handling for these struct types,
2359 // like in CCodeStructModule.generate_struct_declaration()
2363 if (get_ccode_has_type_id (st)) {
2364 if (get_ccode_name (st).length < 3) {
2366 Report.error (st.source_reference, "Struct name `%s' is too short", get_ccode_name (st));
2370 push_line (st.source_reference);
2371 var type_fun = new StructRegisterFunction (st);
2372 type_fun.init_from_type (context, false, false);
2373 cfile.add_type_member_definition (type_fun.get_definition ());
2378 public override void visit_enum (Enum en) {
2379 base.visit_enum (en);
2381 if (get_ccode_has_type_id (en)) {
2382 if (get_ccode_name (en).length < 3) {
2384 Report.error (en.source_reference, "Enum name `%s' is too short", get_ccode_name (en));
2388 push_line (en.source_reference);
2389 var type_fun = new EnumRegisterFunction (en);
2390 type_fun.init_from_type (context, false, false);
2391 cfile.add_type_member_definition (type_fun.get_definition ());
2396 public override void visit_method_call (MethodCall expr) {
2397 var ma = expr.call as MemberAccess;
2398 var mtype = expr.call.value_type as MethodType;
2399 if (mtype == null || ma == null || ma.inner == null ||
2400 !(ma.inner.value_type is EnumValueType) || !get_ccode_has_type_id (ma.inner.value_type.type_symbol) ||
2401 mtype.method_symbol != ((EnumValueType) ma.inner.value_type).get_to_string_method ()) {
2402 base.visit_method_call (expr);
2405 // to_string() on a gtype enum
2407 bool is_flags = ((Enum) ((EnumValueType) ma.inner.value_type).type_symbol).is_flags;
2409 push_line (expr.source_reference);
2410 if (context.require_glib_version (2, 54)) {
2411 var to_string = new CCodeFunctionCall (new CCodeIdentifier ((is_flags ? "g_flags_to_string" : "g_enum_to_string")));
2412 to_string.add_argument (new CCodeIdentifier (get_ccode_type_id (ma.inner.value_type)));
2413 to_string.add_argument ((CCodeExpression) get_ccodenode (((MemberAccess) expr.call).inner));
2414 expr.value_type.value_owned = true;
2415 set_cvalue (expr, to_string);
2417 var temp_var = get_temp_variable (new CType (is_flags ? "GFlagsValue*" : "GEnumValue*", "NULL"), false, expr, false);
2418 emit_temp_var (temp_var);
2420 var class_ref = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_ref"));
2421 class_ref.add_argument (new CCodeIdentifier (get_ccode_type_id (ma.inner.value_type)));
2422 var get_value = new CCodeFunctionCall (new CCodeIdentifier (is_flags ? "g_flags_get_first_value" : "g_enum_get_value"));
2423 get_value.add_argument (class_ref);
2424 get_value.add_argument ((CCodeExpression) get_ccodenode (((MemberAccess) expr.call).inner));
2426 ccode.add_assignment (get_variable_cexpression (temp_var.name), get_value);
2427 var is_null_value = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_variable_cexpression (temp_var.name), new CCodeConstant ("NULL"));
2428 set_cvalue (expr, new CCodeConditionalExpression (is_null_value, new CCodeMemberAccess.pointer (get_variable_cexpression (temp_var.name), "value_name"), new CCodeConstant ("NULL")));
2433 public override void visit_property (Property prop) {
2434 var cl = current_type_symbol as Class;
2435 var st = current_type_symbol as Struct;
2437 var base_prop = prop;
2438 if (prop.base_property != null) {
2439 base_prop = prop.base_property;
2440 } else if (prop.base_interface_property != null) {
2441 base_prop = prop.base_interface_property;
2444 if (base_prop.get_attribute ("NoAccessorMethod") == null &&
2445 prop.name == "type" && ((cl != null && !cl.is_compact) || (st != null && get_ccode_has_type_id (st)))) {
2446 Report.error (prop.source_reference, "Property 'type' not allowed");
2449 base.visit_property (prop);
2452 public override void create_type_check_statement (CodeNode method_node, DataType ret_type, TypeSymbol t, bool non_null, string var_name) {
2453 var ccheck = new CCodeFunctionCall ();
2455 if (!context.assert) {
2457 } else if (context.checking && ((t is Class && !((Class) t).is_compact) || t is Interface)) {
2458 if (!get_ccode_has_type_id (t)) {
2462 CCodeFunctionCall ctype_check;
2463 if (t.external_package) {
2464 ctype_check = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
2465 ctype_check.add_argument (new CCodeIdentifier (var_name));
2466 ctype_check.add_argument (new CCodeIdentifier (get_ccode_type_id (t)));
2468 ctype_check = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_check_function (t)));
2469 ctype_check.add_argument (new CCodeIdentifier (var_name));
2472 CCodeExpression cexpr = ctype_check;
2474 var cnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL"));
2476 cexpr = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cnull, ctype_check);
2478 ccheck.add_argument (cexpr);
2479 } else if (!non_null || (t is Struct && ((Struct) t).is_simple_type ())) {
2481 } else if (t == glist_type || t == gslist_type) {
2482 // NULL is empty list
2485 var cnonnull = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL"));
2486 ccheck.add_argument (cnonnull);
2489 // g_return_* needs glib.h
2490 cfile.add_include ("glib.h");
2492 var cm = method_node as CreationMethod;
2493 if (cm != null && !cm.coroutine && cm.parent_symbol is ObjectTypeSymbol) {
2494 ccheck.call = new CCodeIdentifier ("g_return_val_if_fail");
2495 ccheck.add_argument (new CCodeConstant ("NULL"));
2496 } else if (ret_type is VoidType) {
2498 ccheck.call = new CCodeIdentifier ("g_return_if_fail");
2500 ccheck.call = new CCodeIdentifier ("g_return_val_if_fail");
2502 var cdefault = default_value_for_type (ret_type, false);
2503 if (cdefault != null) {
2504 ccheck.add_argument (cdefault);
2505 } else if (ret_type.type_symbol is Struct && !((Struct) ret_type.type_symbol).is_simple_type ()) {
2506 ccheck.add_argument (new CCodeIdentifier ("result"));
2512 ccode.add_expression (ccheck);
2515 public override void visit_cast_expression (CastExpression expr) {
2516 unowned ObjectTypeSymbol? type_symbol = expr.type_reference.type_symbol as ObjectTypeSymbol;
2518 if (type_symbol == null || (type_symbol is Class && ((Class) type_symbol).is_compact)) {
2519 base.visit_cast_expression (expr);
2523 generate_type_declaration (expr.type_reference, cfile);
2525 // checked cast for strict subtypes of GTypeInstance
2526 if (expr.is_silent_cast) {
2527 TargetValue to_cast = expr.inner.target_value;
2528 CCodeExpression cexpr;
2529 if (!get_lvalue (to_cast)) {
2530 to_cast = store_temp_value (to_cast, expr);
2532 cexpr = get_cvalue_ (to_cast);
2533 var ccheck = create_type_check (cexpr, expr.type_reference);
2534 var ccast = new CCodeCastExpression (cexpr, get_ccode_name (expr.type_reference));
2535 var cnull = new CCodeConstant ("NULL");
2536 var cast_value = new GLibValue (expr.value_type, new CCodeConditionalExpression (ccheck, ccast, cnull));
2537 if (requires_destroy (expr.inner.value_type)) {
2538 var casted = store_temp_value (cast_value, expr);
2539 ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, get_cvalue_ (casted), new CCodeConstant ("NULL")));
2540 ccode.add_expression (destroy_value (to_cast));
2542 expr.target_value = ((GLibValue) casted).copy ();
2544 expr.target_value = cast_value;
2547 set_cvalue (expr, generate_instance_cast (get_cvalue (expr.inner), expr.type_reference.type_symbol));