Release 0.41.92
[vala-gnome.git] / codegen / valagtypemodule.vala
blob6b60f7ef3ffa6ec2dce7e499fff38fa0cda1413b
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
20 * Author:
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_name (param.variable_type);
36 if (param.direction != ParameterDirection.IN) {
37 ctypename = "%s *".printf (ctypename);
40 var cparam = new CCodeParameter (get_variable_cname (param.name), ctypename);
41 if (param.format_arg) {
42 cparam.modifiers = CCodeModifiers.FORMAT_ARG;
45 cparam_map.set (get_param_pos (get_ccode_pos (param)), cparam);
46 if (carg_map != null) {
47 carg_map.set (get_param_pos (get_ccode_pos (param)), get_variable_cexpression (param.name));
50 return cparam;
53 public override void generate_class_declaration (Class cl, CCodeFile decl_space) {
54 if (add_symbol_declaration (decl_space, cl, get_ccode_name (cl))) {
55 return;
58 if (cl.base_class != null) {
59 // base class declaration
60 // necessary for ref and unref function declarations
61 generate_class_declaration (cl.base_class, decl_space);
64 bool is_gtypeinstance = !cl.is_compact;
65 bool is_fundamental = is_gtypeinstance && cl.base_class == null;
66 bool is_gsource = cl.base_class == gsource_type;
68 if (is_gtypeinstance) {
69 decl_space.add_type_declaration (new CCodeNewline ());
70 var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (cl, null));
71 decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (cl), macro));
73 macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (get_ccode_type_id (cl), get_ccode_name (cl));
74 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_upper_case_name (cl, null)), macro));
76 macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (get_ccode_type_id (cl), get_ccode_name (cl));
77 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (get_ccode_upper_case_name (cl, null)), macro));
79 macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (get_ccode_type_id (cl));
80 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_check_function (cl)), macro));
82 macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (get_ccode_type_id (cl));
83 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (get_ccode_type_check_function (cl)), macro));
85 macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (get_ccode_type_id (cl), get_ccode_name (cl));
86 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (get_ccode_upper_case_name (cl, null)), macro));
87 decl_space.add_type_declaration (new CCodeNewline ());
90 if (cl.is_compact && cl.base_class != null) {
91 decl_space.add_type_declaration (new CCodeTypeDefinition (get_ccode_name (cl.base_class), new CCodeVariableDeclarator (get_ccode_name (cl))));
92 } else {
93 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (cl)), new CCodeVariableDeclarator (get_ccode_name (cl))));
96 if (is_fundamental) {
97 var ref_fun = new CCodeFunction ("%sref".printf (get_ccode_lower_case_prefix (cl)), "gpointer");
98 var unref_fun = new CCodeFunction ("%sunref".printf (get_ccode_lower_case_prefix (cl)), "void");
99 if (cl.is_private_symbol ()) {
100 ref_fun.modifiers = CCodeModifiers.STATIC;
101 unref_fun.modifiers = CCodeModifiers.STATIC;
102 } else if (context.hide_internal && cl.is_internal_symbol ()) {
103 ref_fun.modifiers = CCodeModifiers.INTERNAL;
104 unref_fun.modifiers = CCodeModifiers.INTERNAL;
107 ref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
108 unref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
110 decl_space.add_function_declaration (ref_fun);
111 decl_space.add_function_declaration (unref_fun);
113 // GParamSpec and GValue functions
114 var function = new CCodeFunction (get_ccode_param_spec_function (cl), "GParamSpec*");
115 function.add_parameter (new CCodeParameter ("name", "const gchar*"));
116 function.add_parameter (new CCodeParameter ("nick", "const gchar*"));
117 function.add_parameter (new CCodeParameter ("blurb", "const gchar*"));
118 function.add_parameter (new CCodeParameter ("object_type", "GType"));
119 function.add_parameter (new CCodeParameter ("flags", "GParamFlags"));
121 if (cl.is_private_symbol ()) {
122 // avoid C warning as this function is not always used
123 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
124 } else if (context.hide_internal && cl.is_internal_symbol ()) {
125 function.modifiers = CCodeModifiers.INTERNAL;
128 decl_space.add_function_declaration (function);
130 function = new CCodeFunction (get_ccode_set_value_function (cl), "void");
131 function.add_parameter (new CCodeParameter ("value", "GValue*"));
132 function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
134 if (cl.is_private_symbol ()) {
135 // avoid C warning as this function is not always used
136 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
137 } else if (context.hide_internal && cl.is_internal_symbol ()) {
138 // avoid C warning as this function is not always used
139 function.modifiers = CCodeModifiers.INTERNAL | CCodeModifiers.UNUSED;
142 decl_space.add_function_declaration (function);
144 function = new CCodeFunction (get_ccode_take_value_function (cl), "void");
145 function.add_parameter (new CCodeParameter ("value", "GValue*"));
146 function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
148 if (cl.is_private_symbol ()) {
149 // avoid C warning as this function is not always used
150 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
151 } else if (context.hide_internal && cl.is_internal_symbol ()) {
152 function.modifiers = CCodeModifiers.INTERNAL;
155 decl_space.add_function_declaration (function);
157 function = new CCodeFunction (get_ccode_get_value_function (cl), "gpointer");
158 function.add_parameter (new CCodeParameter ("value", "const GValue*"));
160 if (cl.is_private_symbol ()) {
161 // avoid C warning as this function is not always used
162 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
163 } else if (context.hide_internal && cl.is_internal_symbol ()) {
164 // avoid C warning as this function is not always used
165 function.modifiers = CCodeModifiers.INTERNAL | CCodeModifiers.UNUSED;
168 decl_space.add_function_declaration (function);
169 } else if (!is_gtypeinstance && !is_gsource) {
170 if (cl.base_class == null) {
171 var function = new CCodeFunction ("%sfree".printf (get_ccode_lower_case_prefix (cl)), "void");
172 if (cl.is_private_symbol ()) {
173 function.modifiers = CCodeModifiers.STATIC;
174 } else if (context.hide_internal && cl.is_internal_symbol ()) {
175 function.modifiers = CCodeModifiers.INTERNAL;
178 function.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl))));
180 decl_space.add_function_declaration (function);
184 if (is_gtypeinstance) {
185 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%sClass".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("%sClass".printf (get_ccode_name (cl)))));
187 var type_fun = new ClassRegisterFunction (cl);
188 type_fun.init_from_type (context, in_plugin, true);
189 decl_space.add_type_member_declaration (type_fun.get_declaration ());
193 public override void generate_class_struct_declaration (Class cl, CCodeFile decl_space) {
194 if (add_symbol_declaration (decl_space, cl, "struct _%s".printf (get_ccode_name (cl)))) {
195 return;
198 if (cl.base_class != null) {
199 // base class declaration
200 generate_class_struct_declaration (cl.base_class, decl_space);
202 foreach (DataType base_type in cl.get_base_types ()) {
203 var iface = base_type.data_type as Interface;
204 if (iface != null) {
205 generate_interface_declaration (iface, decl_space);
209 generate_class_declaration (cl, decl_space);
211 bool is_gtypeinstance = !cl.is_compact;
212 bool is_fundamental = is_gtypeinstance && cl.base_class == null;
214 var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (cl)));
215 var type_struct = new CCodeStruct ("_%sClass".printf (get_ccode_name (cl)));
217 if (cl.base_class != null) {
218 instance_struct.add_field (get_ccode_name (cl.base_class), "parent_instance");
219 } else if (is_fundamental) {
220 decl_space.add_include ("glib-object.h");
221 instance_struct.add_field ("GTypeInstance", "parent_instance");
222 instance_struct.add_field ("volatile int", "ref_count");
225 if (is_gtypeinstance) {
226 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %sPrivate".printf (instance_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (get_ccode_name (cl)))));
228 if (!context.abi_stability) {
229 instance_struct.add_field ("%sPrivate *".printf (get_ccode_name (cl)), "priv");
231 if (is_fundamental) {
232 type_struct.add_field ("GTypeClass", "parent_class");
233 } else {
234 type_struct.add_field ("%sClass".printf (get_ccode_name (cl.base_class)), "parent_class");
237 if (is_fundamental) {
238 type_struct.add_field ("void", "(*finalize) (%s *self)".printf (get_ccode_name (cl)));
242 bool has_struct_member = false;
243 if (context.abi_stability) {
244 foreach (Symbol s in cl.get_members ()) {
245 if (s is Method) {
246 var m = (Method) s;
247 generate_struct_method_declaration (cl, m, instance_struct, type_struct, decl_space, ref has_struct_member);
248 } else if (s is Signal) {
249 var sig = (Signal) s;
250 if (sig.default_handler != null) {
251 generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
253 } else if (s is Property) {
254 var prop = (Property) s;
255 generate_struct_property_declaration (cl, prop, instance_struct, type_struct, decl_space, ref has_struct_member);
256 } else if (s is Field) {
257 var f = (Field) s;
258 generate_struct_field_declaration (cl, f, instance_struct, type_struct, decl_space, ref has_struct_member);
259 } else {
260 assert_not_reached ();
263 } else {
264 foreach (Method m in cl.get_methods ()) {
265 generate_struct_method_declaration (cl, m, instance_struct, type_struct, decl_space, ref has_struct_member);
268 foreach (Signal sig in cl.get_signals ()) {
269 if (sig.default_handler != null) {
270 generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
274 foreach (Property prop in cl.get_properties ()) {
275 generate_struct_property_declaration (cl, prop, instance_struct, type_struct, decl_space, ref has_struct_member);
278 foreach (Field f in cl.get_fields ()) {
279 generate_struct_field_declaration (cl, f, instance_struct, type_struct, decl_space, ref has_struct_member);
283 if (cl.is_compact && cl.base_class == null && !has_struct_member) {
284 // add dummy member, C doesn't allow empty structs
285 instance_struct.add_field ("int", "dummy");
288 if (!cl.is_compact || cl.base_class == null) {
289 // derived compact classes do not have a struct
290 decl_space.add_type_definition (instance_struct);
293 if (is_gtypeinstance) {
294 if (context.abi_stability) {
295 instance_struct.add_field ("%sPrivate *".printf (get_ccode_name (cl)), "priv");
297 decl_space.add_type_definition (type_struct);
301 void generate_struct_method_declaration (Class cl, Method m, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space, ref bool has_struct_member) {
302 if (!cl.is_compact) {
303 generate_virtual_method_declaration (m, decl_space, type_struct);
304 } else if (cl.is_compact && cl.base_class == null) {
305 generate_virtual_method_declaration (m, decl_space, instance_struct);
306 has_struct_member |= (m.is_abstract || m.is_virtual);
310 void generate_struct_property_declaration (Class cl, Property prop, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space, ref bool has_struct_member) {
311 if (!prop.is_abstract && !prop.is_virtual) {
312 return;
314 generate_type_declaration (prop.property_type, decl_space);
316 var t = (ObjectTypeSymbol) prop.parent_symbol;
318 var this_type = new ObjectType (t);
319 var cselfparam = new CCodeParameter ("self", get_ccode_name (this_type));
321 if (prop.get_accessor != null) {
322 var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
323 vdeclarator.add_parameter (cselfparam);
324 string creturn_type;
325 if (prop.property_type.is_real_non_null_struct_type ()) {
326 var cvalueparam = new CCodeParameter ("result", "%s *".printf (get_ccode_name (prop.get_accessor.value_type)));
327 vdeclarator.add_parameter (cvalueparam);
328 creturn_type = "void";
329 } else {
330 creturn_type = get_ccode_name (prop.get_accessor.value_type);
333 var array_type = prop.property_type as ArrayType;
334 if (array_type != null) {
335 for (int dim = 1; dim <= array_type.rank; dim++) {
336 vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("result", dim), "int*"));
338 } else if ((prop.property_type is DelegateType) && ((DelegateType) prop.property_type).delegate_symbol.has_target) {
339 vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_cname ("result"), "gpointer*"));
342 var vdecl = new CCodeDeclaration (creturn_type);
343 vdecl.add_declarator (vdeclarator);
344 type_struct.add_declaration (vdecl);
346 if (cl.is_compact && cl.base_class == null) {
347 instance_struct.add_declaration (vdecl);
348 has_struct_member = true;
351 if (prop.set_accessor != null) {
352 CCodeParameter cvalueparam;
353 if (prop.property_type.is_real_non_null_struct_type ()) {
354 cvalueparam = new CCodeParameter ("value", "%s *".printf (get_ccode_name (prop.set_accessor.value_type)));
355 } else {
356 cvalueparam = new CCodeParameter ("value", get_ccode_name (prop.set_accessor.value_type));
359 var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
360 vdeclarator.add_parameter (cselfparam);
361 vdeclarator.add_parameter (cvalueparam);
363 var array_type = prop.property_type as ArrayType;
364 if (array_type != null) {
365 for (int dim = 1; dim <= array_type.rank; dim++) {
366 vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("value", dim), "int"));
368 } else if ((prop.property_type is DelegateType) && ((DelegateType) prop.property_type).delegate_symbol.has_target) {
369 vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_cname ("value"), "gpointer"));
372 var vdecl = new CCodeDeclaration ("void");
373 vdecl.add_declarator (vdeclarator);
374 type_struct.add_declaration (vdecl);
376 if (cl.is_compact && cl.base_class == null) {
377 instance_struct.add_declaration (vdecl);
378 has_struct_member = true;
383 void generate_struct_field_declaration (Class cl, Field f, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space, ref bool has_struct_member) {
384 if (f.access == SymbolAccessibility.PRIVATE) {
385 return;
388 CCodeModifiers modifiers = (f.is_volatile ? CCodeModifiers.VOLATILE : 0) | (f.version.deprecated ? CCodeModifiers.DEPRECATED : 0);
389 if (f.binding == MemberBinding.INSTANCE) {
390 generate_type_declaration (f.variable_type, decl_space);
392 instance_struct.add_field (get_ccode_name (f.variable_type), get_ccode_name (f), modifiers, get_ccode_declarator_suffix (f.variable_type));
393 has_struct_member = true;
394 if (f.variable_type is ArrayType && get_ccode_array_length (f)) {
395 // create fields to store array dimensions
396 var array_type = (ArrayType) f.variable_type;
398 if (!array_type.fixed_length) {
399 var len_type = int_type.copy ();
401 for (int dim = 1; dim <= array_type.rank; dim++) {
402 string length_cname;
403 if (get_ccode_array_length_name (f) != null) {
404 length_cname = get_ccode_array_length_name (f);
405 } else {
406 length_cname = get_array_length_cname (get_ccode_name (f), dim);
408 instance_struct.add_field (get_ccode_name (len_type), length_cname);
411 if (array_type.rank == 1 && f.is_internal_symbol ()) {
412 instance_struct.add_field (get_ccode_name (len_type), get_array_size_cname (get_ccode_name (f)));
415 } else if (f.variable_type is DelegateType && get_ccode_delegate_target (f)) {
416 var delegate_type = (DelegateType) f.variable_type;
417 if (delegate_type.delegate_symbol.has_target) {
418 // create field to store delegate target
419 instance_struct.add_field ("gpointer", get_ccode_delegate_target_name (f));
420 if (delegate_type.is_disposable ()) {
421 instance_struct.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_ccode_name (f)));
425 } else if (f.binding == MemberBinding.CLASS) {
426 type_struct.add_field (get_ccode_name (f.variable_type), get_ccode_name (f), modifiers);
430 public virtual void generate_virtual_method_declaration (Method m, CCodeFile decl_space, CCodeStruct type_struct) {
431 if (!m.is_abstract && !m.is_virtual) {
432 return;
435 var creturn_type = m.return_type;
436 if (m.return_type.is_real_non_null_struct_type ()) {
437 // structs are returned via out parameter
438 creturn_type = new VoidType ();
441 // add vfunc field to the type struct
442 var vdeclarator = new CCodeFunctionDeclarator (get_ccode_vfunc_name (m));
443 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
445 if (m.printf_format) {
446 vdeclarator.modifiers |= CCodeModifiers.PRINTF;
447 } else if (m.scanf_format) {
448 vdeclarator.modifiers |= CCodeModifiers.SCANF;
451 if (m.version.deprecated) {
452 vdeclarator.modifiers |= CCodeModifiers.DEPRECATED;
455 generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator);
457 var vdecl = new CCodeDeclaration (get_ccode_name (creturn_type));
458 vdecl.add_declarator (vdeclarator);
459 type_struct.add_declaration (vdecl);
462 void generate_class_private_declaration (Class cl, CCodeFile decl_space) {
463 if (decl_space.add_declaration ("%sPrivate".printf (get_ccode_name (cl)))) {
464 return;
467 bool is_gtypeinstance = !cl.is_compact;
468 bool has_class_locks = false;
470 var instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (get_ccode_name (cl)));
471 var type_priv_struct = new CCodeStruct ("_%sClassPrivate".printf (get_ccode_name (cl)));
473 if (is_gtypeinstance) {
474 /* create type, dup_func, and destroy_func fields for generic types */
475 foreach (TypeParameter type_param in cl.get_type_parameters ()) {
476 string func_name;
478 func_name = "%s_type".printf (type_param.name.down ());
479 instance_priv_struct.add_field ("GType", func_name);
481 func_name = "%s_dup_func".printf (type_param.name.down ());
482 instance_priv_struct.add_field ("GBoxedCopyFunc", func_name);
484 func_name = "%s_destroy_func".printf (type_param.name.down ());
485 instance_priv_struct.add_field ("GDestroyNotify", func_name);
489 foreach (Field f in cl.get_fields ()) {
490 CCodeModifiers modifiers = (f.is_volatile ? CCodeModifiers.VOLATILE : 0) | (f.version.deprecated ? CCodeModifiers.DEPRECATED : 0);
491 if (f.binding == MemberBinding.INSTANCE) {
492 if (f.access == SymbolAccessibility.PRIVATE) {
493 generate_type_declaration (f.variable_type, decl_space);
495 instance_priv_struct.add_field (get_ccode_name (f.variable_type), get_ccode_name (f), modifiers, get_ccode_declarator_suffix (f.variable_type));
496 if (f.variable_type is ArrayType && get_ccode_array_length (f)) {
497 // create fields to store array dimensions
498 var array_type = (ArrayType) f.variable_type;
499 var len_type = int_type.copy ();
501 if (!array_type.fixed_length) {
502 for (int dim = 1; dim <= array_type.rank; dim++) {
503 string length_cname;
504 if (get_ccode_array_length_name (f) != null) {
505 length_cname = get_ccode_array_length_name (f);
506 } else {
507 length_cname = get_array_length_cname (get_ccode_name (f), dim);
509 instance_priv_struct.add_field (get_ccode_name (len_type), length_cname);
512 if (array_type.rank == 1 && f.is_internal_symbol ()) {
513 instance_priv_struct.add_field (get_ccode_name (len_type), get_array_size_cname (get_ccode_name (f)));
516 } else if (f.variable_type is DelegateType && get_ccode_delegate_target (f)) {
517 var delegate_type = (DelegateType) f.variable_type;
518 if (delegate_type.delegate_symbol.has_target) {
519 // create field to store delegate target
520 instance_priv_struct.add_field ("gpointer", get_ccode_delegate_target_name (f));
521 if (delegate_type.is_disposable ()) {
522 instance_priv_struct.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_ccode_name (f)));
528 if (f.lock_used) {
529 cl.has_private_fields = true;
530 // add field for mutex
531 instance_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (f)));
533 } else if (f.binding == MemberBinding.CLASS) {
534 if (f.access == SymbolAccessibility.PRIVATE) {
535 type_priv_struct.add_field (get_ccode_name (f.variable_type), get_ccode_name (f), modifiers);
538 if (f.lock_used) {
539 has_class_locks = true;
540 // add field for mutex
541 type_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (f)));
546 foreach (Property prop in cl.get_properties ()) {
547 if (prop.binding == MemberBinding.INSTANCE) {
548 if (prop.lock_used) {
549 cl.has_private_fields = true;
550 // add field for mutex
551 instance_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (prop)));
553 } else if (prop.binding == MemberBinding.CLASS) {
554 if (prop.lock_used) {
555 has_class_locks = true;
556 // add field for mutex
557 type_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (prop)));
562 if (is_gtypeinstance) {
563 if (cl.has_class_private_fields || has_class_locks) {
564 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_priv_struct.name), new CCodeVariableDeclarator ("%sClassPrivate".printf (get_ccode_name (cl)))));
567 /* only add the *Private struct if it is not empty, i.e. we actually have private data */
568 if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
569 decl_space.add_type_definition (instance_priv_struct);
571 var parent_decl = new CCodeDeclaration ("gint");
572 var parent_var_decl = new CCodeVariableDeclarator ("%s_private_offset".printf (get_ccode_name (cl)));
573 parent_decl.add_declarator (parent_var_decl);
574 parent_decl.modifiers = CCodeModifiers.STATIC;
575 cfile.add_type_member_declaration (parent_decl);
577 var function = new CCodeFunction ("%s_get_instance_private".printf (get_ccode_lower_case_name (cl, null)), "gpointer");
578 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.INLINE;
579 function.add_parameter (new CCodeParameter ("self", "%s*".printf (get_ccode_name (cl))));
581 push_function (function);
583 function.block = new CCodeBlock ();
584 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_STRUCT_MEMBER_P"));
585 ccall.add_argument (new CCodeIdentifier ("self"));
586 ccall.add_argument (new CCodeIdentifier ("%s_private_offset".printf (get_ccode_name (cl))));
587 function.block.add_statement (new CCodeReturnStatement (ccall));
589 pop_function ();
590 cfile.add_function (function);
593 if (cl.has_class_private_fields || has_class_locks) {
594 decl_space.add_type_member_declaration (type_priv_struct);
596 string macro = "(G_TYPE_CLASS_GET_PRIVATE (klass, %s, %sClassPrivate))".printf (get_ccode_type_id (cl), get_ccode_name (cl));
597 decl_space.add_type_member_declaration (new CCodeMacroReplacement ("%s_GET_CLASS_PRIVATE(klass)".printf (get_ccode_upper_case_name (cl, null)), macro));
599 } else {
600 if (cl.has_private_fields) {
601 Report.error (cl.source_reference, "Private fields not supported in compact classes");
606 public override void visit_class (Class cl) {
607 push_context (new EmitContext (cl));
608 push_line (cl.source_reference);
610 var old_param_spec_struct = param_spec_struct;
611 var old_prop_enum = prop_enum;
612 var old_signal_enum = signal_enum;
613 var old_class_init_context = class_init_context;
614 var old_base_init_context = base_init_context;
615 var old_class_finalize_context = class_finalize_context;
616 var old_base_finalize_context = base_finalize_context;
617 var old_instance_init_context = instance_init_context;
618 var old_instance_finalize_context = instance_finalize_context;
620 bool is_gtypeinstance = !cl.is_compact;
621 bool is_gobject = is_gtypeinstance && cl.is_subtype_of (gobject_type);
622 bool is_fundamental = is_gtypeinstance && cl.base_class == null;
624 if (get_ccode_name (cl).length < 3) {
625 cl.error = true;
626 Report.error (cl.source_reference, "Class name `%s' is too short".printf (get_ccode_name (cl)));
627 return;
630 prop_enum = new CCodeEnum ();
631 prop_enum.add_value (new CCodeEnumValue ("%s_0_PROPERTY".printf (get_ccode_upper_case_name (cl, null))));
632 signal_enum = new CCodeEnum ();
633 class_init_context = new EmitContext (cl);
634 base_init_context = new EmitContext (cl);
635 class_finalize_context = new EmitContext (cl);
636 base_finalize_context = new EmitContext (cl);
637 instance_init_context = new EmitContext (cl);
638 instance_finalize_context = new EmitContext (cl);
640 generate_class_struct_declaration (cl, cfile);
641 generate_class_private_declaration (cl, cfile);
643 var last_prop = "%s_NUM_PROPERTIES".printf (get_ccode_upper_case_name (cl));
644 if (is_gobject) {
645 cfile.add_type_declaration (prop_enum);
647 var prop_array_decl = new CCodeDeclaration ("GParamSpec*");
648 prop_array_decl.modifiers |= CCodeModifiers.STATIC;
649 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))));
650 cfile.add_type_declaration (prop_array_decl);
653 if (!cl.is_internal_symbol ()) {
654 generate_class_struct_declaration (cl, header_file);
656 if (!cl.is_private_symbol ()) {
657 generate_class_struct_declaration (cl, internal_header_file);
660 if (is_gtypeinstance) {
661 begin_base_init_function (cl);
662 begin_class_init_function (cl);
663 begin_instance_init_function (cl);
665 begin_base_finalize_function (cl);
666 begin_class_finalize_function (cl);
667 begin_finalize_function (cl);
668 } else {
669 if (cl.is_compact || cl.base_class == null || cl.base_class == gsource_type) {
670 begin_instance_init_function (cl);
671 begin_finalize_function (cl);
675 cl.accept_children (this);
677 if (is_gtypeinstance) {
678 if (is_fundamental) {
679 param_spec_struct = new CCodeStruct ( "_%sParamSpec%s".printf(get_ccode_prefix (cl.parent_symbol), cl.name));
680 param_spec_struct.add_field ("GParamSpec", "parent_instance");
681 cfile.add_type_definition (param_spec_struct);
683 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))));
686 gvaluecollector_h_needed = true;
688 add_type_value_table_init_function (cl);
689 add_type_value_table_free_function (cl);
690 add_type_value_table_copy_function (cl);
691 add_type_value_table_peek_pointer_function (cl);
692 add_type_value_table_collect_value_function (cl);
693 add_type_value_table_lcopy_value_function (cl);
694 add_g_param_spec_type_function (cl);
695 add_g_value_get_function (cl);
696 add_g_value_set_function (cl);
697 add_g_value_take_function (cl);
699 var ref_count = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"), new CCodeConstant ("1"));
700 push_context (instance_init_context);
701 ccode.add_expression (ref_count);
702 pop_context ();
705 if (is_gobject) {
706 prop_enum.add_value (new CCodeEnumValue (last_prop));
709 if (cl.get_signals ().size > 0) {
710 var last_signal = "%s_NUM_SIGNALS".printf (get_ccode_upper_case_name (cl));
711 signal_enum.add_value (new CCodeEnumValue (last_signal));
712 cfile.add_type_declaration (signal_enum);
714 var signal_array_decl = new CCodeDeclaration ("guint");
715 signal_array_decl.modifiers |= CCodeModifiers.STATIC;
716 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))));
717 cfile.add_type_declaration (signal_array_decl);
721 if (cl.class_constructor != null) {
722 add_base_init_function (cl);
724 add_class_init_function (cl);
726 if (cl.class_destructor != null) {
727 add_base_finalize_function (cl);
730 if (cl.static_destructor != null) {
731 add_class_finalize_function (cl);
734 foreach (DataType base_type in cl.get_base_types ()) {
735 if (base_type.data_type is Interface) {
736 add_interface_init_function (cl, (Interface) base_type.data_type);
740 add_instance_init_function (cl);
742 if (!cl.is_compact && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
743 add_finalize_function (cl);
746 if (cl.comment != null) {
747 cfile.add_type_member_definition (new CCodeComment (cl.comment.content));
750 var type_fun = new ClassRegisterFunction (cl);
751 type_fun.init_from_type (context, in_plugin, false);
752 cfile.add_type_member_declaration (type_fun.get_source_declaration ());
753 cfile.add_type_member_definition (type_fun.get_definition ());
755 if (is_fundamental) {
756 var ref_count = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count");
758 // ref function
759 var ref_fun = new CCodeFunction ("%sref".printf (get_ccode_lower_case_prefix (cl)), "gpointer");
760 ref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
761 if (cl.is_private_symbol ()) {
762 ref_fun.modifiers = CCodeModifiers.STATIC;
763 } else if (context.hide_internal && cl.is_internal_symbol ()) {
764 ref_fun.modifiers = CCodeModifiers.INTERNAL;
766 push_function (ref_fun);
768 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self", new CCodeIdentifier ("instance")));
769 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_inc"));
770 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count));
771 ccode.add_expression (ccall);
772 ccode.add_return (new CCodeIdentifier ("instance"));
774 pop_function ();
775 cfile.add_function (ref_fun);
777 // unref function
778 var unref_fun = new CCodeFunction ("%sunref".printf (get_ccode_lower_case_prefix (cl)), "void");
779 unref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
780 if (cl.is_private_symbol ()) {
781 unref_fun.modifiers = CCodeModifiers.STATIC;
782 } else if (context.hide_internal && cl.is_internal_symbol ()) {
783 unref_fun.modifiers = CCodeModifiers.INTERNAL;
785 push_function (unref_fun);
787 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self", new CCodeIdentifier ("instance")));
788 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_dec_and_test"));
789 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count));
790 ccode.open_if (ccall);
792 var get_class = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS".printf (get_ccode_upper_case_name (cl, null))));
793 get_class.add_argument (new CCodeIdentifier ("self"));
795 // finalize class
796 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS".printf (get_ccode_upper_case_name (cl, null))));
797 ccast.add_argument (new CCodeIdentifier ("self"));
798 ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
799 ccall.add_argument (new CCodeIdentifier ("self"));
800 ccode.add_expression (ccall);
802 // free type instance
803 var free = new CCodeFunctionCall (new CCodeIdentifier ("g_type_free_instance"));
804 free.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GTypeInstance *"));
805 ccode.add_expression (free);
807 ccode.close ();
808 pop_function ();
809 cfile.add_function (unref_fun);
811 } else {
812 if (cl.is_compact || cl.base_class == null || cl.base_class == gsource_type) {
813 add_instance_init_function (cl);
814 add_finalize_function (cl);
818 param_spec_struct = old_param_spec_struct;
819 prop_enum = old_prop_enum;
820 signal_enum = old_signal_enum;
821 class_init_context = old_class_init_context;
822 base_init_context = old_base_init_context;
823 class_finalize_context = old_class_finalize_context;
824 base_finalize_context = old_base_finalize_context;
825 instance_init_context = old_instance_init_context;
826 instance_finalize_context = old_instance_finalize_context;
828 pop_line ();
829 pop_context ();
832 private void add_type_value_table_init_function (Class cl) {
833 var function = new CCodeFunction ("%s_init".printf (get_ccode_lower_case_name (cl, "value_")), "void");
834 function.add_parameter (new CCodeParameter ("value", "GValue*"));
835 function.modifiers = CCodeModifiers.STATIC;
837 push_function (function);
838 ccode.add_assignment (new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer"), new CCodeConstant ("NULL"));
839 pop_function ();
840 cfile.add_function (function);
843 private void add_type_value_table_free_function (Class cl) {
844 var function = new CCodeFunction ("%s_free_value".printf (get_ccode_lower_case_name (cl, "value_")), "void");
845 function.add_parameter (new CCodeParameter ("value", "GValue*"));
846 function.modifiers = CCodeModifiers.STATIC;
848 push_function (function);
850 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
851 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%sunref".printf (get_ccode_lower_case_prefix (cl))));
852 ccall.add_argument (vpointer);
854 ccode.open_if (vpointer);
855 ccode.add_expression (ccall);
856 ccode.close ();
858 pop_function ();
859 cfile.add_function (function);
862 private void add_type_value_table_copy_function (Class cl) {
863 var function = new CCodeFunction ("%s_copy_value".printf (get_ccode_lower_case_name (cl, "value_")), "void");
864 function.add_parameter (new CCodeParameter ("src_value", "const GValue*"));
865 function.add_parameter (new CCodeParameter ("dest_value", "GValue*"));
866 function.modifiers = CCodeModifiers.STATIC;
868 push_function (function);
870 var dest_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dest_value"), "data[0]"), "v_pointer");
871 var src_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("src_value"), "data[0]"), "v_pointer");
873 var ref_ccall = new CCodeFunctionCall (new CCodeIdentifier ("%sref".printf (get_ccode_lower_case_prefix (cl))));
874 ref_ccall.add_argument ( src_vpointer );
876 ccode.open_if (src_vpointer);
877 ccode.add_assignment (dest_vpointer, ref_ccall);
878 ccode.add_else ();
879 ccode.add_assignment (dest_vpointer, new CCodeConstant ("NULL"));
880 ccode.close ();
882 pop_function ();
883 cfile.add_function (function);
886 private void add_type_value_table_peek_pointer_function (Class cl) {
887 var function = new CCodeFunction ("%s_peek_pointer".printf (get_ccode_lower_case_name (cl, "value_")), "gpointer");
888 function.add_parameter (new CCodeParameter ("value", "const GValue*"));
889 function.modifiers = CCodeModifiers.STATIC;
891 push_function (function);
893 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
894 ccode.add_return (vpointer);
896 pop_function ();
897 cfile.add_function (function);
900 private void add_type_value_table_lcopy_value_function ( Class cl ) {
901 var function = new CCodeFunction ("%s_lcopy_value".printf (get_ccode_lower_case_name (cl, "value_")), "gchar*");
902 function.add_parameter (new CCodeParameter ("value", "const GValue*"));
903 function.add_parameter (new CCodeParameter ("n_collect_values", "guint"));
904 function.add_parameter (new CCodeParameter ("collect_values", "GTypeCValue*"));
905 function.add_parameter (new CCodeParameter ("collect_flags", "guint"));
906 function.modifiers = CCodeModifiers.STATIC;
908 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
909 var object_p_ptr = new CCodeIdentifier ("*object_p");
910 var null_ = new CCodeConstant ("NULL");
912 push_function (function);
914 ccode.add_declaration ("%s **".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("object_p", new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"), "v_pointer")));
916 var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME"));
917 value_type_name_fct.add_argument (new CCodeConstant ("value"));
919 var assert_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("object_p"));
920 ccode.open_if (assert_condition);
921 var assert_printf = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup_printf"));
922 assert_printf.add_argument (new CCodeConstant ("\"value location for `%s' passed as NULL\""));
923 assert_printf.add_argument (value_type_name_fct);
924 ccode.add_return (assert_printf);
925 ccode.close ();
927 var main_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, vpointer);
928 var main_else_if_condition = new CCodeBinaryExpression (CCodeBinaryOperator.BITWISE_AND, new CCodeIdentifier ("collect_flags"), new CCodeIdentifier ("G_VALUE_NOCOPY_CONTENTS"));
929 var ref_fct = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
930 ref_fct.add_argument (vpointer);
931 ccode.open_if (main_condition);
932 ccode.add_assignment (object_p_ptr, null_);
933 ccode.else_if (main_else_if_condition);
934 ccode.add_assignment (object_p_ptr, vpointer);
935 ccode.add_else ();
936 ccode.add_assignment (object_p_ptr, ref_fct);
937 ccode.close ();
939 ccode.add_return (null_);
940 pop_function ();
941 cfile.add_function (function);
944 private void add_type_value_table_collect_value_function (Class cl) {
945 var function = new CCodeFunction ("%s_collect_value".printf (get_ccode_lower_case_name (cl, "value_")), "gchar*");
946 function.add_parameter (new CCodeParameter ("value", "GValue*"));
947 function.add_parameter (new CCodeParameter ("n_collect_values", "guint"));
948 function.add_parameter (new CCodeParameter ("collect_values", "GTypeCValue*"));
949 function.add_parameter (new CCodeParameter ("collect_flags", "guint"));
950 function.modifiers = CCodeModifiers.STATIC;
952 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
954 push_function (function);
956 var collect_vpointer = new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"), "v_pointer");
958 ccode.open_if (collect_vpointer);
959 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("object", collect_vpointer));
960 var obj_identifier = new CCodeIdentifier ("object");
961 var l_expression = new CCodeMemberAccess (new CCodeMemberAccess.pointer (obj_identifier, "parent_instance"), "g_class");
962 var sub_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, l_expression, new CCodeConstant ("NULL"));
963 var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME"));
964 value_type_name_fct.add_argument (new CCodeConstant ("value"));
966 ccode.open_if (sub_condition);
967 var true_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
968 true_return.add_argument (new CCodeConstant ("\"invalid unclassed object pointer for value type `\""));
969 true_return.add_argument (value_type_name_fct);
970 true_return.add_argument (new CCodeConstant ("\"'\""));
971 true_return.add_argument (new CCodeConstant ("NULL"));
972 ccode.add_return (true_return);
974 var reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
975 var type_check = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
976 type_check.add_argument (new CCodeIdentifier ("object"));
977 reg_call.add_argument (type_check);
978 var stored_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
979 stored_type.add_argument (new CCodeIdentifier ("value"));
980 reg_call.add_argument (stored_type);
982 ccode.else_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, reg_call));
983 var false_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
984 var type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("g_type_name"));
985 type_name_fct.add_argument (type_check);
986 false_return.add_argument (new CCodeConstant ("\"invalid object type `\""));
987 false_return.add_argument (type_name_fct);
988 false_return.add_argument (new CCodeConstant ("\"' for value type `\""));
989 false_return.add_argument (value_type_name_fct);
990 false_return.add_argument (new CCodeConstant ("\"'\""));
991 false_return.add_argument (new CCodeConstant ("NULL"));
992 ccode.add_return (false_return);
994 ccode.close ();
996 var ref_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
997 ref_call.add_argument (new CCodeIdentifier ("object"));
998 ccode.add_assignment (vpointer, ref_call);
1000 ccode.add_else ();
1001 ccode.add_assignment (vpointer, new CCodeConstant ("NULL"));
1003 ccode.close ();
1005 ccode.add_return (new CCodeConstant ("NULL"));
1007 pop_function ();
1008 cfile.add_function (function);
1011 private void add_g_param_spec_type_function (Class cl) {
1012 var function = new CCodeFunction (get_ccode_param_spec_function (cl), "GParamSpec*");
1013 function.add_parameter (new CCodeParameter ("name", "const gchar*"));
1014 function.add_parameter (new CCodeParameter ("nick", "const gchar*"));
1015 function.add_parameter (new CCodeParameter ("blurb", "const gchar*"));
1016 function.add_parameter (new CCodeParameter ("object_type", "GType"));
1017 function.add_parameter (new CCodeParameter ("flags", "GParamFlags"));
1019 if (cl.is_private_symbol ()) {
1020 function.modifiers = CCodeModifiers.STATIC;
1021 } else if (context.hide_internal && cl.is_internal_symbol ()) {
1022 function.modifiers = CCodeModifiers.INTERNAL;
1025 push_function (function);
1027 ccode.add_declaration ("%sParamSpec%s*".printf (get_ccode_prefix (cl.parent_symbol), cl.name), new CCodeVariableDeclarator ("spec"));
1029 var subccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_is_a"));
1030 subccall.add_argument (new CCodeIdentifier ("object_type"));
1031 subccall.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1033 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail"));
1034 ccall.add_argument (subccall);
1035 ccall.add_argument (new CCodeIdentifier ("NULL"));
1036 ccode.add_expression (ccall);
1038 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_internal"));
1039 ccall.add_argument (new CCodeIdentifier ( "G_TYPE_PARAM_OBJECT" ));
1040 ccall.add_argument (new CCodeIdentifier ("name"));
1041 ccall.add_argument (new CCodeIdentifier ("nick"));
1042 ccall.add_argument (new CCodeIdentifier ("blurb"));
1043 ccall.add_argument (new CCodeIdentifier ("flags"));
1045 ccode.add_assignment (new CCodeIdentifier ("spec"), ccall);
1047 ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_PARAM_SPEC"));
1048 ccall.add_argument (new CCodeIdentifier ("spec"));
1050 ccode.add_assignment (new CCodeMemberAccess.pointer (ccall, "value_type"), new CCodeIdentifier ("object_type"));
1051 ccode.add_return (ccall);
1053 pop_function ();
1054 cfile.add_function (function);
1057 private void add_g_value_set_function (Class cl) {
1058 var function = new CCodeFunction (get_ccode_set_value_function (cl), "void");
1059 function.add_parameter (new CCodeParameter ("value", "GValue*"));
1060 function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
1062 if (cl.is_private_symbol ()) {
1063 function.modifiers = CCodeModifiers.STATIC;
1064 } else if (context.hide_internal && cl.is_internal_symbol ()) {
1065 function.modifiers = CCodeModifiers.INTERNAL;
1068 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
1070 push_function (function);
1072 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("old"));
1074 var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1075 ccall_typecheck.add_argument (new CCodeIdentifier ( "value" ));
1076 ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1078 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1079 ccall.add_argument (ccall_typecheck);
1080 ccode.add_expression (ccall);
1082 ccode.add_assignment (new CCodeConstant ("old"), vpointer);
1084 ccode.open_if (new CCodeIdentifier ("v_object"));
1085 ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
1086 ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" ));
1087 ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1089 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1090 ccall.add_argument (ccall_typecheck);
1091 ccode.add_expression (ccall);
1093 var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1094 ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" ));
1096 var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
1097 ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" ));
1099 var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
1100 ccall_typecompatible.add_argument (ccall_typefrominstance);
1101 ccall_typecompatible.add_argument (ccall_gvaluetype);
1103 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1104 ccall.add_argument (ccall_typecompatible);
1105 ccode.add_expression (ccall);
1107 ccode.add_assignment (vpointer, new CCodeConstant ("v_object"));
1109 ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
1110 ccall.add_argument (vpointer);
1111 ccode.add_expression (ccall);
1113 ccode.add_else ();
1114 ccode.add_assignment (vpointer, new CCodeConstant ("NULL"));
1115 ccode.close ();
1117 ccode.open_if (new CCodeIdentifier ("old"));
1118 ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (cl)));
1119 ccall.add_argument (new CCodeIdentifier ("old"));
1120 ccode.add_expression (ccall);
1121 ccode.close ();
1123 pop_function ();
1124 cfile.add_function (function);
1127 private void add_g_value_take_function (Class cl) {
1128 var function = new CCodeFunction (get_ccode_take_value_function (cl), "void");
1129 function.add_parameter (new CCodeParameter ("value", "GValue*"));
1130 function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
1132 if (cl.is_private_symbol ()) {
1133 function.modifiers = CCodeModifiers.STATIC;
1134 } else if (context.hide_internal && cl.is_internal_symbol ()) {
1135 function.modifiers = CCodeModifiers.INTERNAL;
1138 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
1140 push_function (function);
1142 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("old"));
1144 var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1145 ccall_typecheck.add_argument (new CCodeIdentifier ( "value" ));
1146 ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1148 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1149 ccall.add_argument (ccall_typecheck);
1150 ccode.add_expression (ccall);
1152 ccode.add_assignment (new CCodeConstant ("old"), vpointer);
1154 ccode.open_if (new CCodeIdentifier ("v_object"));
1156 ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
1157 ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" ));
1158 ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
1160 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1161 ccall.add_argument (ccall_typecheck);
1162 ccode.add_expression (ccall);
1164 var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1165 ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" ));
1167 var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
1168 ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" ));
1170 var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
1171 ccall_typecompatible.add_argument (ccall_typefrominstance);
1172 ccall_typecompatible.add_argument (ccall_gvaluetype);
1174 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
1175 ccall.add_argument (ccall_typecompatible);
1176 ccode.add_expression (ccall);
1178 ccode.add_assignment (vpointer, new CCodeConstant ("v_object"));
1180 ccode.add_else ();
1181 ccode.add_assignment (vpointer, new CCodeConstant ("NULL"));
1182 ccode.close ();
1184 ccode.open_if (new CCodeIdentifier ("old"));
1185 ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (cl)));
1186 ccall.add_argument (new CCodeIdentifier ("old"));
1187 ccode.add_expression (ccall);
1188 ccode.close ();
1190 pop_function ();
1191 cfile.add_function (function);
1194 private void add_g_value_get_function (Class cl) {
1195 var function = new CCodeFunction (get_ccode_get_value_function (cl), "gpointer");
1196 function.add_parameter (new CCodeParameter ("value", "const GValue*"));
1198 if (cl.is_private_symbol ()) {
1199 function.modifiers = CCodeModifiers.STATIC;
1200 } else if (context.hide_internal && cl.is_internal_symbol ()) {
1201 function.modifiers = CCodeModifiers.INTERNAL;
1204 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
1206 push_function (function);
1208 var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1209 ccall_typecheck.add_argument (new CCodeIdentifier ("value"));
1210 ccall_typecheck.add_argument (new CCodeIdentifier (get_ccode_type_id (cl)));
1212 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail"));
1213 ccall.add_argument (ccall_typecheck);
1214 ccall.add_argument (new CCodeIdentifier ("NULL"));
1215 ccode.add_expression (ccall);
1217 ccode.add_return (vpointer);
1219 pop_function ();
1220 cfile.add_function (function);
1223 private void begin_base_init_function (Class cl) {
1224 push_context (base_init_context);
1226 var base_init = new CCodeFunction ("%s_base_init".printf (get_ccode_lower_case_name (cl, null)), "void");
1227 base_init.add_parameter (new CCodeParameter ("klass", "%sClass *".printf (get_ccode_name (cl))));
1228 base_init.modifiers = CCodeModifiers.STATIC;
1230 push_function (base_init);
1232 pop_context ();
1235 private void add_base_init_function (Class cl) {
1236 cfile.add_function (base_init_context.ccode);
1239 public virtual void generate_class_init (Class cl) {
1242 public virtual void end_instance_init (Class cl) {
1245 private void begin_class_init_function (Class cl) {
1246 push_context (class_init_context);
1248 var func = new CCodeFunction ("%s_class_init".printf (get_ccode_lower_case_name (cl, null)));
1249 func.add_parameter (new CCodeParameter ("klass", "%sClass *".printf (get_ccode_name (cl))));
1250 func.modifiers = CCodeModifiers.STATIC;
1252 CCodeFunctionCall ccall;
1254 /* save pointer to parent class */
1255 var parent_decl = new CCodeDeclaration ("gpointer");
1256 var parent_var_decl = new CCodeVariableDeclarator ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null)));
1257 parent_var_decl.initializer = new CCodeConstant ("NULL");
1258 parent_decl.add_declarator (parent_var_decl);
1259 parent_decl.modifiers = CCodeModifiers.STATIC;
1260 cfile.add_type_member_declaration (parent_decl);
1262 push_function (func);
1264 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent"));
1265 ccall.add_argument (new CCodeIdentifier ("klass"));
1266 var parent_assignment = new CCodeAssignment (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null))), ccall);
1267 ccode.add_expression (parent_assignment);
1270 if (!cl.is_compact && !cl.is_subtype_of (gobject_type) && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
1271 // set finalize function
1272 var fundamental_class = cl;
1273 while (fundamental_class.base_class != null) {
1274 fundamental_class = fundamental_class.base_class;
1277 var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%sClass *".printf (get_ccode_name (fundamental_class)));
1278 var finalize_assignment = new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "finalize"), new CCodeIdentifier ("%sfinalize".printf (get_ccode_lower_case_prefix (cl))));
1279 ccode.add_expression (finalize_assignment);
1282 /* add struct for private fields */
1283 if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
1284 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_adjust_private_offset"));
1285 ccall.add_argument (new CCodeIdentifier ("klass"));
1286 ccall.add_argument (new CCodeIdentifier ("&%s_private_offset".printf (get_ccode_name (cl))));
1287 ccode.add_expression (ccall);
1290 /* connect overridden methods */
1291 foreach (Method m in cl.get_methods ()) {
1292 if (m.base_method == null) {
1293 continue;
1295 var base_type = (ObjectTypeSymbol) m.base_method.parent_symbol;
1297 // there is currently no default handler for abstract async methods
1298 if (!m.is_abstract || !m.coroutine) {
1299 CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (m));
1300 cfunc = cast_method_pointer (m.base_method, cfunc, base_type, (m.coroutine ? 1 : 3));
1301 var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%sClass *".printf (get_ccode_name (base_type)));
1302 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (m.base_method)), cfunc);
1304 if (m.coroutine) {
1305 cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m));
1306 cfunc = cast_method_pointer (m.base_method, cfunc, base_type, 2);
1307 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_finish_vfunc_name (m.base_method)), cfunc);
1312 /* connect default signal handlers */
1313 foreach (Signal sig in cl.get_signals ()) {
1314 if (sig.default_handler == null) {
1315 continue;
1317 var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%sClass *".printf (get_ccode_name (cl)));
1318 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (sig.default_handler)), new CCodeIdentifier (get_ccode_real_name (sig.default_handler)));
1321 /* connect overridden properties */
1322 foreach (Property prop in cl.get_properties ()) {
1323 if (prop.base_property == null) {
1324 continue;
1326 var base_type = prop.base_property.parent_symbol;
1328 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (get_ccode_upper_case_name (base_type))));
1329 ccast.add_argument (new CCodeIdentifier ("klass"));
1331 if (!get_ccode_no_accessor_method (prop.base_property) && !get_ccode_concrete_accessor (prop.base_property)) {
1332 if (prop.get_accessor != null) {
1333 string cname = get_ccode_real_name (prop.get_accessor);
1334 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), new CCodeIdentifier (cname));
1336 if (prop.set_accessor != null) {
1337 string cname = get_ccode_real_name (prop.set_accessor);
1338 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), new CCodeIdentifier (cname));
1343 generate_class_init (cl);
1345 if (!cl.is_compact) {
1346 /* create signals */
1347 foreach (Signal sig in cl.get_signals ()) {
1348 if (sig.comment != null) {
1349 ccode.add_statement (new CCodeComment (sig.comment.content));
1351 ccode.add_expression (get_signal_creation (sig, cl));
1355 pop_context ();
1358 private void add_class_init_function (Class cl) {
1359 cfile.add_function (class_init_context.ccode);
1362 private void add_generic_accessor_function (string base_name, string return_type, CCodeExpression? expression, TypeParameter p, Class cl, Interface iface) {
1363 string name = "%s_%s_%s".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface), base_name);
1365 var function = new CCodeFunction (name, return_type);
1366 function.modifiers = CCodeModifiers.STATIC;
1367 var this_type = get_data_type_for_symbol (cl);
1368 function.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
1369 push_function (function);
1370 ccode.add_return (expression);
1371 pop_function ();
1372 cfile.add_function (function);
1374 CCodeExpression cfunc = new CCodeIdentifier (function.name);
1375 string cast = "%s (*)".printf (return_type);
1376 string cast_args = "%s *".printf (get_ccode_name (iface));
1377 cast = "%s (%s)".printf (cast, cast_args);
1378 cfunc = new CCodeCastExpression (cfunc, cast);
1379 var ciface = new CCodeIdentifier ("iface");
1380 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, base_name), cfunc);
1383 private void add_interface_init_function (Class cl, Interface iface) {
1384 var iface_init = new CCodeFunction ("%s_%s_interface_init".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface)), "void");
1385 iface_init.add_parameter (new CCodeParameter ("iface", "%s *".printf (get_ccode_type_name (iface))));
1386 iface_init.modifiers = CCodeModifiers.STATIC;
1388 push_function (iface_init);
1390 CCodeFunctionCall ccall;
1392 /* save pointer to parent vtable */
1393 string parent_iface_var = "%s_%s_parent_iface".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface));
1394 var parent_decl = new CCodeDeclaration ("%s *".printf (get_ccode_type_name (iface)));
1395 var parent_var_decl = new CCodeVariableDeclarator (parent_iface_var);
1396 parent_var_decl.initializer = new CCodeConstant ("NULL");
1397 parent_decl.add_declarator (parent_var_decl);
1398 parent_decl.modifiers = CCodeModifiers.STATIC;
1399 cfile.add_type_member_declaration (parent_decl);
1400 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_interface_peek_parent"));
1401 ccall.add_argument (new CCodeIdentifier ("iface"));
1402 ccode.add_assignment (new CCodeIdentifier (parent_iface_var), ccall);
1404 foreach (Method m in cl.get_methods ()) {
1405 if (m.base_interface_method == null) {
1406 continue;
1409 var base_type = m.base_interface_method.parent_symbol;
1410 if (base_type != iface) {
1411 continue;
1414 var ciface = new CCodeIdentifier ("iface");
1415 CCodeExpression cfunc;
1416 if (m.is_abstract || m.is_virtual) {
1417 cfunc = new CCodeIdentifier (get_ccode_name (m));
1418 } else {
1419 cfunc = new CCodeIdentifier (get_ccode_real_name (m));
1421 cfunc = cast_method_pointer (m.base_interface_method, cfunc, iface, (m.coroutine ? 1 : 3));
1422 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m.base_interface_method)), cfunc);
1424 if (m.coroutine) {
1425 if (m.is_abstract || m.is_virtual) {
1426 cfunc = new CCodeIdentifier (get_ccode_finish_name (m));
1427 } else {
1428 cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m));
1430 cfunc = cast_method_pointer (m.base_interface_method, cfunc, iface, 2);
1431 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_finish_vfunc_name (m.base_interface_method)), cfunc);
1435 if (iface.get_attribute ("GenericAccessors") != null) {
1436 foreach (TypeParameter p in iface.get_type_parameters ()) {
1437 GenericType p_type = new GenericType (p);
1438 DataType p_data_type = p_type.get_actual_type (get_data_type_for_symbol (cl), null, cl);
1440 add_generic_accessor_function ("get_%s_type".printf (p.name.down ()),
1441 "GType",
1442 get_type_id_expression (p_data_type),
1443 p, cl, iface);
1445 add_generic_accessor_function ("get_%s_dup_func".printf (p.name.down ()),
1446 "GBoxedCopyFunc",
1447 get_dup_func_expression (p_data_type, null),
1448 p, cl, iface);
1450 add_generic_accessor_function ("get_%s_destroy_func".printf (p.name.down ()),
1451 "GDestroyNotify",
1452 get_destroy_func_expression (p_data_type),
1453 p, cl, iface);
1457 // connect inherited implementations
1458 foreach (Method m in iface.get_methods ()) {
1459 if (m.is_abstract) {
1460 Method cl_method = null;
1461 var base_class = cl;
1462 while (base_class != null && cl_method == null) {
1463 cl_method = base_class.scope.lookup (m.name) as Method;
1464 base_class = base_class.base_class;
1466 if (base_class != null && cl_method.parent_symbol != cl) {
1467 // method inherited from base class
1469 var base_method = cl_method;
1470 if (cl_method.base_method != null) {
1471 base_method = cl_method.base_method;
1472 } else if (cl_method.base_interface_method != null) {
1473 base_method = cl_method.base_interface_method;
1476 generate_method_declaration (base_method, cfile);
1478 CCodeExpression cfunc = new CCodeIdentifier (get_ccode_name (base_method));
1479 cfunc = cast_method_pointer (base_method, cfunc, iface);
1480 var ciface = new CCodeIdentifier ("iface");
1481 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m)), cfunc);
1486 foreach (Property prop in cl.get_properties ()) {
1487 if (prop.base_interface_property == null) {
1488 continue;
1491 var base_type = (ObjectTypeSymbol) prop.base_interface_property.parent_symbol;
1492 if (base_type != iface) {
1493 continue;
1496 var ciface = new CCodeIdentifier ("iface");
1498 if (!get_ccode_no_accessor_method (prop.base_interface_property) && !get_ccode_concrete_accessor (prop.base_interface_property)) {
1499 if (prop.get_accessor != null) {
1500 string cname = get_ccode_real_name (prop.get_accessor);
1501 if (prop.is_abstract || prop.is_virtual) {
1502 cname = get_ccode_name (prop.get_accessor);
1505 CCodeExpression cfunc = new CCodeIdentifier (cname);
1506 if (prop.is_abstract || prop.is_virtual) {
1507 cfunc = cast_property_accessor_pointer (prop.get_accessor, cfunc, base_type);
1509 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), cfunc);
1511 if (prop.set_accessor != null) {
1512 string cname = get_ccode_real_name (prop.set_accessor);
1513 if (prop.is_abstract || prop.is_virtual) {
1514 cname = get_ccode_name (prop.set_accessor);
1517 CCodeExpression cfunc = new CCodeIdentifier (cname);
1518 if (prop.is_abstract || prop.is_virtual) {
1519 cfunc = cast_property_accessor_pointer (prop.set_accessor, cfunc, base_type);
1521 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), cfunc);
1526 foreach (Property prop in iface.get_properties ()) {
1527 if (!prop.is_abstract) {
1528 continue;
1531 Property cl_prop = null;
1532 var base_class = cl;
1533 while (base_class != null && cl_prop == null) {
1534 cl_prop = base_class.scope.lookup (prop.name) as Property;
1535 base_class = base_class.base_class;
1537 if (base_class != null && cl_prop.parent_symbol != cl) {
1538 // property inherited from base class
1540 var base_property = cl_prop;
1541 if (cl_prop.base_property != null) {
1542 base_property = cl_prop.base_property;
1543 } else if (cl_prop.base_interface_property != null) {
1544 base_property = cl_prop.base_interface_property;
1547 var ciface = new CCodeIdentifier ("iface");
1549 if (base_property.get_accessor != null && prop.get_accessor != null) {
1550 generate_property_accessor_declaration (base_property.get_accessor, cfile);
1552 string cname = get_ccode_name (base_property.get_accessor);
1553 CCodeExpression cfunc = new CCodeIdentifier (cname);
1554 cfunc = cast_property_accessor_pointer (prop.get_accessor, cfunc, iface);
1555 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), cfunc);
1557 if (base_property.set_accessor != null && prop.set_accessor != null) {
1558 generate_property_accessor_declaration (base_property.set_accessor, cfile);
1560 string cname = get_ccode_name (base_property.set_accessor);
1561 CCodeExpression cfunc = new CCodeIdentifier (cname);
1562 cfunc = cast_property_accessor_pointer (prop.set_accessor, cfunc, iface);
1563 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), cfunc);
1568 pop_function ();
1569 cfile.add_function (iface_init);
1572 CCodeExpression cast_property_accessor_pointer (PropertyAccessor acc, CCodeExpression cfunc, ObjectTypeSymbol base_type) {
1573 string cast;
1574 if (acc.readable && acc.value_type.is_real_non_null_struct_type ()) {
1575 cast = "void (*) (%s *, %s *)".printf (get_ccode_name (base_type), get_ccode_name (acc.value_type));
1576 } else if (acc.readable) {
1577 cast = "%s (*) (%s *)".printf (get_ccode_name (acc.value_type), get_ccode_name (base_type));
1578 } else if (acc.value_type.is_real_non_null_struct_type ()) {
1579 cast = "void (*) (%s *, %s *)".printf (get_ccode_name (base_type), get_ccode_name (acc.value_type));
1580 } else {
1581 cast = "void (*) (%s *, %s)".printf (get_ccode_name (base_type), get_ccode_name (acc.value_type));
1583 return new CCodeCastExpression (cfunc, cast);
1586 CCodeExpression cast_method_pointer (Method m, CCodeExpression cfunc, ObjectTypeSymbol base_type, int direction = 3) {
1587 // Cast the function pointer to match the interface
1588 string cast;
1589 if (direction == 1 || m.return_type.is_real_non_null_struct_type ()) {
1590 cast = "void (*)";
1591 } else {
1592 cast = "%s (*)".printf (get_ccode_name (m.return_type));
1594 string cast_args = "%s *".printf (get_ccode_name (base_type));
1596 var vdeclarator = new CCodeFunctionDeclarator (get_ccode_vfunc_name (m));
1597 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
1599 generate_cparameters (m, cfile, cparam_map, new CCodeFunction ("fake"), vdeclarator, null, null, direction);
1601 // append C arguments in the right order
1602 int last_pos = -1;
1603 int min_pos;
1604 while (true) {
1605 min_pos = -1;
1606 foreach (int pos in cparam_map.get_keys ()) {
1607 if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
1608 min_pos = pos;
1611 if (last_pos != -1) { // Skip the 1st parameter
1612 if (min_pos == -1) {
1613 break;
1616 var tmp = cparam_map.get (min_pos);
1617 if (tmp.ellipsis) {
1618 cast_args = "%s, ...".printf (cast_args);
1619 } else {
1620 cast_args = "%s, %s".printf (cast_args, tmp.type_name);
1623 last_pos = min_pos;
1625 cast = "%s (%s)".printf (cast, cast_args);
1626 return new CCodeCastExpression (cfunc, cast);
1629 private void begin_instance_init_function (Class cl) {
1630 push_context (instance_init_context);
1632 var func = new CCodeFunction ("%s_instance_init".printf (get_ccode_lower_case_name (cl, null)));
1633 func.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl))));
1634 func.modifiers = CCodeModifiers.STATIC;
1636 push_function (func);
1638 bool is_gsource = cl.base_class == gsource_type;
1640 if (cl.is_compact) {
1641 // Add declaration, since the instance_init function is explicitly called
1642 // by the creation methods
1643 cfile.add_function_declaration (func);
1645 // connect overridden methods
1646 foreach (Method m in cl.get_methods ()) {
1647 if (m.base_method == null || is_gsource) {
1648 continue;
1650 var base_type = (ObjectTypeSymbol) m.base_method.parent_symbol;
1652 // there is currently no default handler for abstract async methods
1653 if (!m.is_abstract || !m.coroutine) {
1654 CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (m));
1655 cfunc = cast_method_pointer (m.base_method, cfunc, base_type, (m.coroutine ? 1 : 3));
1656 var ccast = new CCodeCastExpression (new CCodeIdentifier ("self"), "%s *".printf (get_ccode_name (base_type)));
1657 func.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (m.base_method)), cfunc);
1659 if (m.coroutine) {
1660 cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m));
1661 cfunc = cast_method_pointer (m.base_method, cfunc, base_type, 2);
1662 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_finish_vfunc_name (m.base_method)), cfunc);
1667 // connect overridden properties
1668 foreach (Property prop in cl.get_properties ()) {
1669 if (prop.base_property == null || is_gsource) {
1670 continue;
1672 var base_type = prop.base_property.parent_symbol;
1674 var ccast = new CCodeCastExpression (new CCodeIdentifier ("self"), "%s *".printf (get_ccode_name (base_type)));
1676 if (!get_ccode_no_accessor_method (prop.base_property) && !get_ccode_concrete_accessor (prop.base_property)) {
1677 if (prop.get_accessor != null) {
1678 string cname = get_ccode_real_name (prop.get_accessor);
1679 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), new CCodeIdentifier (cname));
1681 if (prop.set_accessor != null) {
1682 string cname = get_ccode_real_name (prop.set_accessor);
1683 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), new CCodeIdentifier (cname));
1689 if (!cl.is_compact && (cl.has_private_fields || cl.get_type_parameters ().size > 0)) {
1690 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_get_instance_private".printf (get_ccode_lower_case_name (cl, null))));
1691 ccall.add_argument (new CCodeIdentifier ("self"));
1692 func.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall);
1695 pop_context ();
1698 private void add_instance_init_function (Class cl) {
1699 push_context (instance_init_context);
1700 end_instance_init (cl);
1701 pop_context ();
1703 cfile.add_function (instance_init_context.ccode);
1706 private void begin_class_finalize_function (Class cl) {
1707 push_context (class_finalize_context);
1709 var function = new CCodeFunction ("%s_class_finalize".printf (get_ccode_lower_case_name (cl, null)), "void");
1710 function.modifiers = CCodeModifiers.STATIC;
1712 function.add_parameter (new CCodeParameter ("klass", "%sClass *".printf (get_ccode_name (cl))));
1714 push_function (function);
1716 if (cl.static_destructor != null) {
1717 cl.static_destructor.body.emit (this);
1720 pop_context ();
1723 private void add_class_finalize_function (Class cl) {
1724 cfile.add_function_declaration (class_finalize_context.ccode);
1725 cfile.add_function (class_finalize_context.ccode);
1728 private void begin_base_finalize_function (Class cl) {
1729 push_context (base_finalize_context);
1731 var function = new CCodeFunction ("%s_base_finalize".printf (get_ccode_lower_case_name (cl, null)), "void");
1732 function.modifiers = CCodeModifiers.STATIC;
1734 function.add_parameter (new CCodeParameter ("klass", "%sClass *".printf (get_ccode_name (cl))));
1736 push_function (function);
1738 if (cl.class_destructor != null) {
1739 cl.class_destructor.body.emit (this);
1742 pop_context ();
1745 private void add_base_finalize_function (Class cl) {
1746 push_context (base_finalize_context);
1748 cfile.add_function_declaration (ccode);
1749 cfile.add_function (ccode);
1751 pop_context ();
1754 private void begin_finalize_function (Class cl) {
1755 push_context (instance_finalize_context);
1757 bool is_gsource = cl.base_class == gsource_type;
1759 if (!cl.is_compact || is_gsource) {
1760 var fundamental_class = cl;
1761 while (fundamental_class.base_class != null) {
1762 fundamental_class = fundamental_class.base_class;
1765 var func = new CCodeFunction ("%s_finalize".printf (get_ccode_lower_case_name (cl, null)));
1766 func.add_parameter (new CCodeParameter ("obj", "%s *".printf (get_ccode_name (fundamental_class))));
1767 func.modifiers = CCodeModifiers.STATIC;
1769 push_function (func);
1771 if (is_gsource) {
1772 cfile.add_function_declaration (func);
1775 CCodeExpression ccast;
1776 if (!cl.is_compact) {
1777 ccast = generate_instance_cast (new CCodeIdentifier ("obj"), cl);
1778 } else {
1779 ccast = new CCodeCastExpression (new CCodeIdentifier ("obj"), "%s *".printf (get_ccode_name (cl)));
1782 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self"));
1783 ccode.add_assignment (new CCodeIdentifier ("self"), ccast);
1785 if (!cl.is_compact && cl.base_class == null) {
1786 // non-gobject class
1787 var call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_handlers_destroy"));
1788 call.add_argument (new CCodeIdentifier ("self"));
1789 ccode.add_expression (call);
1791 } else {
1792 var function = new CCodeFunction ("%sfree".printf (get_ccode_lower_case_prefix (cl)), "void");
1793 if (cl.is_private_symbol ()) {
1794 function.modifiers = CCodeModifiers.STATIC;
1795 } else if (context.hide_internal && cl.is_internal_symbol ()) {
1796 function.modifiers = CCodeModifiers.INTERNAL;
1799 function.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl))));
1801 push_function (function);
1804 if (cl.destructor != null) {
1805 cl.destructor.body.emit (this);
1807 if (current_method_inner_error) {
1808 ccode.add_declaration ("GError *", new CCodeVariableDeclarator.zero ("_inner_error_", new CCodeConstant ("NULL")));
1811 if (current_method_return) {
1812 // support return statements in destructors
1813 ccode.add_label ("_return");
1817 pop_context ();
1820 private void add_finalize_function (Class cl) {
1821 if (!cl.is_compact) {
1822 var fundamental_class = cl;
1823 while (fundamental_class.base_class != null) {
1824 fundamental_class = fundamental_class.base_class;
1827 // chain up to finalize function of the base class
1828 if (cl.base_class != null) {
1829 var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (get_ccode_upper_case_name (fundamental_class))));
1830 ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null))));
1831 var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
1832 ccall.add_argument (new CCodeIdentifier ("obj"));
1833 push_context (instance_finalize_context);
1834 ccode.add_expression (ccall);
1835 pop_context ();
1838 cfile.add_function_declaration (instance_finalize_context.ccode);
1839 } else if (cl.base_class == null) {
1840 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
1841 ccall.add_argument (new CCodeIdentifier (get_ccode_name (cl)));
1842 ccall.add_argument (new CCodeIdentifier ("self"));
1843 push_context (instance_finalize_context);
1844 ccode.add_expression (ccall);
1845 pop_context ();
1848 cfile.add_function (instance_finalize_context.ccode);
1851 public override CCodeExpression get_param_spec_cexpression (Property prop) {
1852 var cl = (TypeSymbol) prop.parent_symbol;
1853 var prop_array = new CCodeIdentifier ("%s_properties".printf (get_ccode_lower_case_name (cl)));
1854 var prop_enum_value = new CCodeIdentifier ("%s_PROPERTY".printf (get_ccode_upper_case_name (prop)));
1856 return new CCodeElementAccess (prop_array, prop_enum_value);
1859 public override CCodeExpression get_param_spec (Property prop) {
1860 var cspec = new CCodeFunctionCall ();
1861 cspec.add_argument (get_property_canonical_cconstant (prop));
1862 cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.nick)));
1863 cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.blurb)));
1866 if (prop.property_type.data_type is Class || prop.property_type.data_type is Interface) {
1867 string param_spec_name = get_ccode_param_spec_function (prop.property_type.data_type);
1868 cspec.call = new CCodeIdentifier (param_spec_name);
1869 if (param_spec_name == "g_param_spec_string") {
1870 cspec.add_argument (new CCodeConstant ("NULL"));
1871 } else if (param_spec_name == "g_param_spec_variant") {
1872 cspec.add_argument (new CCodeConstant ("G_VARIANT_TYPE_ANY"));
1873 cspec.add_argument (new CCodeConstant ("NULL"));
1874 } else if (get_ccode_type_id (prop.property_type.data_type) != "G_TYPE_POINTER") {
1875 cspec.add_argument (new CCodeIdentifier (get_ccode_type_id (prop.property_type.data_type)));
1877 } else if (prop.property_type.data_type is Enum) {
1878 var e = prop.property_type.data_type as Enum;
1879 if (get_ccode_has_type_id (e)) {
1880 if (e.is_flags) {
1881 cspec.call = new CCodeIdentifier ("g_param_spec_flags");
1882 } else {
1883 cspec.call = new CCodeIdentifier ("g_param_spec_enum");
1885 cspec.add_argument (new CCodeIdentifier (get_ccode_type_id (e)));
1886 } else {
1887 if (e.is_flags) {
1888 cspec.call = new CCodeIdentifier ("g_param_spec_uint");
1889 cspec.add_argument (new CCodeConstant ("0"));
1890 cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
1891 } else {
1892 cspec.call = new CCodeIdentifier ("g_param_spec_int");
1893 cspec.add_argument (new CCodeConstant ("G_MININT"));
1894 cspec.add_argument (new CCodeConstant ("G_MAXINT"));
1898 if (prop.initializer != null) {
1899 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1900 } else {
1901 cspec.add_argument (new CCodeConstant (get_ccode_default_value (prop.property_type.data_type)));
1903 } else if (prop.property_type.data_type is Struct) {
1904 var st = (Struct) prop.property_type.data_type;
1905 var type_id = get_ccode_type_id (st);
1906 if (type_id == "G_TYPE_INT") {
1907 cspec.call = new CCodeIdentifier ("g_param_spec_int");
1908 cspec.add_argument (new CCodeConstant ("G_MININT"));
1909 cspec.add_argument (new CCodeConstant ("G_MAXINT"));
1910 if (prop.initializer != null) {
1911 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1912 } else {
1913 cspec.add_argument (new CCodeConstant ("0"));
1915 } else if (type_id == "G_TYPE_UINT") {
1916 cspec.call = new CCodeIdentifier ("g_param_spec_uint");
1917 cspec.add_argument (new CCodeConstant ("0"));
1918 cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
1919 if (prop.initializer != null) {
1920 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1921 } else {
1922 cspec.add_argument (new CCodeConstant ("0U"));
1924 } else if (type_id == "G_TYPE_INT64") {
1925 cspec.call = new CCodeIdentifier ("g_param_spec_int64");
1926 cspec.add_argument (new CCodeConstant ("G_MININT64"));
1927 cspec.add_argument (new CCodeConstant ("G_MAXINT64"));
1928 if (prop.initializer != null) {
1929 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1930 } else {
1931 cspec.add_argument (new CCodeConstant ("0"));
1933 } else if (type_id == "G_TYPE_UINT64") {
1934 cspec.call = new CCodeIdentifier ("g_param_spec_uint64");
1935 cspec.add_argument (new CCodeConstant ("0"));
1936 cspec.add_argument (new CCodeConstant ("G_MAXUINT64"));
1937 if (prop.initializer != null) {
1938 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1939 } else {
1940 cspec.add_argument (new CCodeConstant ("0U"));
1942 } else if (type_id == "G_TYPE_LONG") {
1943 cspec.call = new CCodeIdentifier ("g_param_spec_long");
1944 cspec.add_argument (new CCodeConstant ("G_MINLONG"));
1945 cspec.add_argument (new CCodeConstant ("G_MAXLONG"));
1946 if (prop.initializer != null) {
1947 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1948 } else {
1949 cspec.add_argument (new CCodeConstant ("0L"));
1951 } else if (type_id == "G_TYPE_ULONG") {
1952 cspec.call = new CCodeIdentifier ("g_param_spec_ulong");
1953 cspec.add_argument (new CCodeConstant ("0"));
1954 cspec.add_argument (new CCodeConstant ("G_MAXULONG"));
1955 if (prop.initializer != null) {
1956 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1957 } else {
1958 cspec.add_argument (new CCodeConstant ("0UL"));
1960 } else if (type_id == "G_TYPE_BOOLEAN") {
1961 cspec.call = new CCodeIdentifier ("g_param_spec_boolean");
1962 if (prop.initializer != null) {
1963 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1964 } else {
1965 cspec.add_argument (new CCodeConstant ("FALSE"));
1967 } else if (type_id == "G_TYPE_CHAR") {
1968 cspec.call = new CCodeIdentifier ("g_param_spec_char");
1969 cspec.add_argument (new CCodeConstant ("G_MININT8"));
1970 cspec.add_argument (new CCodeConstant ("G_MAXINT8"));
1971 if (prop.initializer != null) {
1972 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1973 } else {
1974 cspec.add_argument (new CCodeConstant ("0"));
1976 } else if (type_id == "G_TYPE_UCHAR") {
1977 cspec.call = new CCodeIdentifier ("g_param_spec_uchar");
1978 cspec.add_argument (new CCodeConstant ("0"));
1979 cspec.add_argument (new CCodeConstant ("G_MAXUINT8"));
1980 if (prop.initializer != null) {
1981 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1982 } else {
1983 cspec.add_argument (new CCodeConstant ("0"));
1985 } else if (type_id == "G_TYPE_FLOAT") {
1986 cspec.call = new CCodeIdentifier ("g_param_spec_float");
1987 cspec.add_argument (new CCodeConstant ("-G_MAXFLOAT"));
1988 cspec.add_argument (new CCodeConstant ("G_MAXFLOAT"));
1989 if (prop.initializer != null) {
1990 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
1991 } else {
1992 cspec.add_argument (new CCodeConstant ("0.0F"));
1994 } else if (type_id == "G_TYPE_DOUBLE") {
1995 cspec.call = new CCodeIdentifier ("g_param_spec_double");
1996 cspec.add_argument (new CCodeConstant ("-G_MAXDOUBLE"));
1997 cspec.add_argument (new CCodeConstant ("G_MAXDOUBLE"));
1998 if (prop.initializer != null) {
1999 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2000 } else {
2001 cspec.add_argument (new CCodeConstant ("0.0"));
2003 } else if (type_id == "G_TYPE_GTYPE") {
2004 cspec.call = new CCodeIdentifier ("g_param_spec_gtype");
2005 if (prop.initializer != null) {
2006 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
2007 } else {
2008 cspec.add_argument (new CCodeConstant ("G_TYPE_NONE"));
2010 } else {
2011 cspec.call = new CCodeIdentifier ("g_param_spec_boxed");
2012 cspec.add_argument (new CCodeIdentifier (type_id));
2014 } else if (prop.property_type is ArrayType && ((ArrayType)prop.property_type).element_type.data_type == string_type.data_type) {
2015 cspec.call = new CCodeIdentifier ("g_param_spec_boxed");
2016 cspec.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
2017 } else {
2018 cspec.call = new CCodeIdentifier ("g_param_spec_pointer");
2021 var pflags = "G_PARAM_STATIC_STRINGS";
2022 if (prop.get_accessor != null && prop.get_accessor.access != SymbolAccessibility.PRIVATE) {
2023 pflags = "%s%s".printf (pflags, " | G_PARAM_READABLE");
2025 if (prop.set_accessor != null && prop.set_accessor.access != SymbolAccessibility.PRIVATE) {
2026 pflags = "%s%s".printf (pflags, " | G_PARAM_WRITABLE");
2027 if (prop.set_accessor.construction) {
2028 if (prop.set_accessor.writable) {
2029 pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT");
2030 } else {
2031 pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT_ONLY");
2035 if (context.require_glib_version (2, 42) && !prop.notify) {
2036 pflags = "%s%s".printf (pflags, " | G_PARAM_EXPLICIT_NOTIFY");
2038 if (prop.version.deprecated) {
2039 pflags = "%s%s".printf (pflags, " | G_PARAM_DEPRECATED");
2041 cspec.add_argument (new CCodeConstant (pflags));
2043 if (prop.parent_symbol is Interface) {
2044 return cspec;
2045 } else {
2046 return new CCodeAssignment (get_param_spec_cexpression (prop), cspec);
2050 public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
2051 if (add_symbol_declaration (decl_space, iface, get_ccode_name (iface))) {
2052 return;
2055 foreach (DataType prerequisite in iface.get_prerequisites ()) {
2056 var prereq_cl = prerequisite.data_type as Class;
2057 var prereq_iface = prerequisite.data_type as Interface;
2058 if (prereq_cl != null) {
2059 generate_class_declaration (prereq_cl, decl_space);
2060 } else if (prereq_iface != null) {
2061 generate_interface_declaration (prereq_iface, decl_space);
2065 var type_struct = new CCodeStruct ("_%s".printf (get_ccode_type_name (iface)));
2067 decl_space.add_type_declaration (new CCodeNewline ());
2068 var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (iface, null));
2069 decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (iface), macro));
2071 macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (get_ccode_type_id (iface), get_ccode_name (iface));
2072 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_upper_case_name (iface, null)), macro));
2074 macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (get_ccode_type_id (iface));
2075 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_check_function (iface)), macro));
2077 macro = "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %s))".printf (get_ccode_type_id (iface), get_ccode_type_name (iface));
2078 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_GET_INTERFACE(obj)".printf (get_ccode_upper_case_name (iface, null)), macro));
2079 decl_space.add_type_declaration (new CCodeNewline ());
2081 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (iface)), new CCodeVariableDeclarator (get_ccode_name (iface))));
2082 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator (get_ccode_type_name (iface))));
2084 type_struct.add_field ("GTypeInterface", "parent_iface");
2086 if (iface.get_attribute ("GenericAccessors") != null) {
2087 foreach (TypeParameter p in iface.get_type_parameters ()) {
2088 string method_name = "get_%s_type".printf (p.name.down ());
2089 var vdeclarator = new CCodeFunctionDeclarator (method_name);
2090 var this_type = get_data_type_for_symbol (iface);
2091 vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
2093 var vdecl = new CCodeDeclaration ("GType");
2094 vdecl.add_declarator (vdeclarator);
2095 type_struct.add_declaration (vdecl);
2097 method_name = "get_%s_dup_func".printf (p.name.down ());
2098 vdeclarator = new CCodeFunctionDeclarator (method_name);
2099 this_type = get_data_type_for_symbol (iface);
2100 vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
2102 vdecl = new CCodeDeclaration ("GBoxedCopyFunc");
2103 vdecl.add_declarator (vdeclarator);
2104 type_struct.add_declaration (vdecl);
2106 method_name = "get_%s_destroy_func".printf (p.name.down ());
2107 vdeclarator = new CCodeFunctionDeclarator (method_name);
2108 this_type = get_data_type_for_symbol (iface);
2109 vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
2111 vdecl = new CCodeDeclaration ("GDestroyNotify");
2112 vdecl.add_declarator (vdeclarator);
2113 type_struct.add_declaration (vdecl);
2117 foreach (Symbol sym in iface.get_virtuals ()) {
2118 Method m;
2119 Signal sig;
2120 Property prop;
2121 if ((m = sym as Method) != null) {
2122 generate_virtual_method_declaration (m, decl_space, type_struct);
2123 } else if ((sig = sym as Signal) != null) {
2124 if (sig.default_handler != null) {
2125 generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
2127 } else if ((prop = sym as Property) != null) {
2128 generate_type_declaration (prop.property_type, decl_space);
2130 var t = (ObjectTypeSymbol) prop.parent_symbol;
2132 bool returns_real_struct = prop.property_type.is_real_non_null_struct_type ();
2134 var this_type = new ObjectType (t);
2135 var cselfparam = new CCodeParameter ("self", get_ccode_name (this_type));
2137 if (prop.get_accessor != null) {
2138 var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
2139 vdeclarator.add_parameter (cselfparam);
2140 string creturn_type;
2141 if (returns_real_struct) {
2142 var cvalueparam = new CCodeParameter ("value", "%s *".printf (get_ccode_name (prop.get_accessor.value_type)));
2143 vdeclarator.add_parameter (cvalueparam);
2144 creturn_type = "void";
2145 } else {
2146 creturn_type = get_ccode_name (prop.get_accessor.value_type);
2149 var array_type = prop.property_type as ArrayType;
2150 if (array_type != null) {
2151 for (int dim = 1; dim <= array_type.rank; dim++) {
2152 vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("result", dim), "int*"));
2156 var vdecl = new CCodeDeclaration (creturn_type);
2157 vdecl.add_declarator (vdeclarator);
2158 type_struct.add_declaration (vdecl);
2160 if (prop.set_accessor != null) {
2161 var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
2162 vdeclarator.add_parameter (cselfparam);
2163 if (returns_real_struct) {
2164 var cvalueparam = new CCodeParameter ("value", "%s *".printf (get_ccode_name (prop.set_accessor.value_type)));
2165 vdeclarator.add_parameter (cvalueparam);
2166 } else {
2167 var cvalueparam = new CCodeParameter ("value", get_ccode_name (prop.set_accessor.value_type));
2168 vdeclarator.add_parameter (cvalueparam);
2171 var array_type = prop.property_type as ArrayType;
2172 if (array_type != null) {
2173 for (int dim = 1; dim <= array_type.rank; dim++) {
2174 vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("value", dim), "int"));
2178 var vdecl = new CCodeDeclaration ("void");
2179 vdecl.add_declarator (vdeclarator);
2180 type_struct.add_declaration (vdecl);
2182 } else {
2183 assert_not_reached ();
2187 decl_space.add_type_definition (type_struct);
2189 var type_fun = new InterfaceRegisterFunction (iface);
2190 type_fun.init_from_type (context, in_plugin, true);
2191 decl_space.add_type_member_declaration (type_fun.get_declaration ());
2194 public override void visit_interface (Interface iface) {
2195 push_context (new EmitContext (iface));
2196 push_line (iface.source_reference);
2198 var old_signal_enum = signal_enum;
2200 if (get_ccode_name (iface).length < 3) {
2201 iface.error = true;
2202 Report.error (iface.source_reference, "Interface name `%s' is too short".printf (get_ccode_name (iface)));
2203 return;
2206 signal_enum = new CCodeEnum ();
2208 generate_interface_declaration (iface, cfile);
2209 if (!iface.is_internal_symbol ()) {
2210 generate_interface_declaration (iface, header_file);
2212 if (!iface.is_private_symbol ()) {
2213 generate_interface_declaration (iface, internal_header_file);
2216 iface.accept_children (this);
2218 if (iface.get_signals ().size > 0) {
2219 var last_signal = "%s_NUM_SIGNALS".printf (get_ccode_upper_case_name (iface));
2220 signal_enum.add_value (new CCodeEnumValue (last_signal));
2221 cfile.add_type_declaration (signal_enum);
2223 var signal_array_decl = new CCodeDeclaration ("guint");
2224 signal_array_decl.modifiers |= CCodeModifiers.STATIC;
2225 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))));
2226 cfile.add_type_declaration (signal_array_decl);
2229 add_interface_default_init_function (iface);
2231 if (iface.comment != null) {
2232 cfile.add_type_member_definition (new CCodeComment (iface.comment.content));
2235 var type_fun = new InterfaceRegisterFunction (iface);
2236 type_fun.init_from_type (context, in_plugin, false);
2237 cfile.add_type_member_declaration (type_fun.get_source_declaration ());
2238 cfile.add_type_member_definition (type_fun.get_definition ());
2240 signal_enum = old_signal_enum;
2242 pop_line ();
2243 pop_context ();
2246 private void add_interface_default_init_function (Interface iface) {
2247 push_context (new EmitContext (iface));
2249 var default_init = new CCodeFunction ("%s_default_init".printf (get_ccode_lower_case_name (iface, null)), "void");
2250 default_init.add_parameter (new CCodeParameter ("iface", "%sIface *".printf (get_ccode_name (iface))));
2251 default_init.modifiers = CCodeModifiers.STATIC;
2253 push_function (default_init);
2255 if (iface.is_subtype_of (gobject_type)) {
2256 /* create properties */
2257 var props = iface.get_properties ();
2258 foreach (Property prop in props) {
2259 if (prop.is_abstract) {
2260 if (!is_gobject_property (prop)) {
2261 continue;
2264 if (prop.comment != null) {
2265 ccode.add_statement (new CCodeComment (prop.comment.content));
2268 var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_interface_install_property"));
2269 cinst.add_argument (new CCodeIdentifier ("iface"));
2270 cinst.add_argument (get_param_spec (prop));
2272 ccode.add_expression (cinst);
2277 var ciface = new CCodeIdentifier ("iface");
2279 /* connect default signal handlers */
2280 foreach (Signal sig in iface.get_signals ()) {
2281 if (sig.default_handler == null) {
2282 continue;
2284 var cname = get_ccode_real_name (sig.default_handler);
2285 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (sig.default_handler)), new CCodeIdentifier (cname));
2288 /* create signals */
2289 foreach (Signal sig in iface.get_signals ()) {
2290 if (sig.comment != null) {
2291 ccode.add_statement (new CCodeComment (sig.comment.content));
2293 ccode.add_expression (get_signal_creation (sig, iface));
2296 // connect default implementations
2297 foreach (Method m in iface.get_methods ()) {
2298 if (m.is_virtual) {
2299 var cname = get_ccode_real_name (m);
2300 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m)), new CCodeIdentifier (cname));
2301 if (m.coroutine) {
2302 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_finish_vfunc_name (m)), new CCodeIdentifier (get_ccode_finish_real_name (m)));
2307 foreach (Property prop in iface.get_properties ()) {
2308 if (prop.is_virtual) {
2309 if (prop.get_accessor != null) {
2310 string cname = get_ccode_real_name (prop.get_accessor);
2311 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), new CCodeIdentifier (cname));
2313 if (prop.set_accessor != null) {
2314 string cname = get_ccode_real_name (prop.set_accessor);
2315 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), new CCodeIdentifier (cname));
2320 pop_context ();
2322 cfile.add_function (default_init);
2325 public override void visit_struct (Struct st) {
2326 base.visit_struct (st);
2328 if (get_ccode_has_type_id (st)) {
2329 push_line (st.source_reference);
2330 var type_fun = new StructRegisterFunction (st);
2331 type_fun.init_from_type (context, false, false);
2332 cfile.add_type_member_definition (type_fun.get_definition ());
2333 pop_line ();
2337 public override void visit_enum (Enum en) {
2338 base.visit_enum (en);
2340 if (get_ccode_has_type_id (en)) {
2341 push_line (en.source_reference);
2342 var type_fun = new EnumRegisterFunction (en);
2343 type_fun.init_from_type (context, false, false);
2344 cfile.add_type_member_definition (type_fun.get_definition ());
2345 pop_line ();
2349 public override void visit_method_call (MethodCall expr) {
2350 var ma = expr.call as MemberAccess;
2351 var mtype = expr.call.value_type as MethodType;
2352 if (mtype == null || ma == null || ma.inner == null ||
2353 !(ma.inner.value_type is EnumValueType) || !get_ccode_has_type_id (ma.inner.value_type.data_type) ||
2354 mtype.method_symbol != ((EnumValueType) ma.inner.value_type).get_to_string_method ()) {
2355 base.visit_method_call (expr);
2356 return;
2358 // to_string() on a gtype enum
2360 bool is_flags = ((Enum) ((EnumValueType) ma.inner.value_type).type_symbol).is_flags;
2362 push_line (expr.source_reference);
2363 if (context.require_glib_version (2, 54)) {
2364 var to_string = new CCodeFunctionCall (new CCodeIdentifier ((is_flags ? "g_flags_to_string" : "g_enum_to_string")));
2365 to_string.add_argument (new CCodeIdentifier (get_ccode_type_id (ma.inner.value_type)));
2366 to_string.add_argument ((CCodeExpression) get_ccodenode (((MemberAccess) expr.call).inner));
2367 expr.value_type.value_owned = true;
2368 set_cvalue (expr, to_string);
2369 } else {
2370 var temp_var = get_temp_variable (new CType (is_flags ? "GFlagsValue*" : "GEnumValue*"), false, expr, false);
2371 emit_temp_var (temp_var);
2373 var class_ref = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_ref"));
2374 class_ref.add_argument (new CCodeIdentifier (get_ccode_type_id (ma.inner.value_type)));
2375 var get_value = new CCodeFunctionCall (new CCodeIdentifier (is_flags ? "g_flags_get_first_value" : "g_enum_get_value"));
2376 get_value.add_argument (class_ref);
2377 get_value.add_argument ((CCodeExpression) get_ccodenode (((MemberAccess) expr.call).inner));
2379 ccode.add_assignment (get_variable_cexpression (temp_var.name), get_value);
2380 var is_null_value = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_variable_cexpression (temp_var.name), new CCodeIdentifier ("NULL"));
2381 set_cvalue (expr, new CCodeConditionalExpression (is_null_value, new CCodeMemberAccess.pointer (get_variable_cexpression (temp_var.name), "value_name"), new CCodeIdentifier ("NULL")));
2383 pop_line ();
2386 public override void visit_property (Property prop) {
2387 var cl = current_type_symbol as Class;
2388 var st = current_type_symbol as Struct;
2390 var base_prop = prop;
2391 if (prop.base_property != null) {
2392 base_prop = prop.base_property;
2393 } else if (prop.base_interface_property != null) {
2394 base_prop = prop.base_interface_property;
2397 if (cl != null && cl.is_compact && (prop.get_accessor == null || prop.get_accessor.automatic_body)) {
2398 Report.error (prop.source_reference, "Properties without accessor bodies are not supported in compact classes");
2399 return;
2402 if (base_prop.get_attribute ("NoAccessorMethod") == null &&
2403 prop.name == "type" && ((cl != null && !cl.is_compact) || (st != null && get_ccode_has_type_id (st)))) {
2404 Report.error (prop.source_reference, "Property 'type' not allowed");
2405 return;
2407 base.visit_property (prop);
2410 public override void create_type_check_statement (CodeNode method_node, DataType ret_type, TypeSymbol t, bool non_null, string var_name) {
2411 var ccheck = new CCodeFunctionCall ();
2413 if (!context.assert) {
2414 return;
2415 } else if (context.checking && ((t is Class && !((Class) t).is_compact) || t is Interface)) {
2416 var ctype_check = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_check_function (t)));
2417 ctype_check.add_argument (new CCodeIdentifier (var_name));
2419 CCodeExpression cexpr = ctype_check;
2420 if (!non_null) {
2421 var cnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL"));
2423 cexpr = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cnull, ctype_check);
2425 ccheck.add_argument (cexpr);
2426 } else if (!non_null || (t is Struct && ((Struct) t).is_simple_type ())) {
2427 return;
2428 } else if (t == glist_type || t == gslist_type) {
2429 // NULL is empty list
2430 return;
2431 } else {
2432 var cnonnull = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL"));
2433 ccheck.add_argument (cnonnull);
2436 var cm = method_node as CreationMethod;
2437 if (cm != null && cm.parent_symbol is ObjectTypeSymbol) {
2438 ccheck.call = new CCodeIdentifier ("g_return_val_if_fail");
2439 ccheck.add_argument (new CCodeConstant ("NULL"));
2440 } else if (ret_type is VoidType) {
2441 /* void function */
2442 ccheck.call = new CCodeIdentifier ("g_return_if_fail");
2443 } else {
2444 ccheck.call = new CCodeIdentifier ("g_return_val_if_fail");
2446 var cdefault = default_value_for_type (ret_type, false);
2447 if (cdefault != null) {
2448 ccheck.add_argument (cdefault);
2449 } else if (ret_type.data_type is Struct && !((Struct) ret_type.data_type).is_simple_type ()) {
2450 ccheck.add_argument (new CCodeIdentifier ("result"));
2451 } else {
2452 return;
2456 ccode.add_expression (ccheck);