1 /* valagtypemodule.vala
3 * Copyright (C) 2006-2010 Jürg Billeter
4 * Copyright (C) 2006-2008 Raffaele Sandrini
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
26 public class Vala
.GTypeModule
: GErrorModule
{
27 public override void generate_parameter (FormalParameter param
, CCodeDeclarationSpace decl_space
, Map
<int,CCodeFormalParameter
> cparam_map
, Map
<int,CCodeExpression
>? carg_map
) {
28 if (!(param
.variable_type is ObjectType
)) {
29 base.generate_parameter (param
, decl_space
, cparam_map
, carg_map
);
33 generate_type_declaration (param
.variable_type
, decl_space
);
35 string ctypename
= param
.variable_type
.get_cname ();
37 if (param
.direction
!= ParameterDirection
.IN
) {
41 param
.ccodenode
= new
CCodeFormalParameter (get_variable_cname (param
.name
), ctypename
);
43 cparam_map
.set (get_param_pos (param
.cparameter_position
), (CCodeFormalParameter
) param
.ccodenode
);
44 if (carg_map
!= null) {
45 carg_map
.set (get_param_pos (param
.cparameter_position
), get_variable_cexpression (param
.name
));
49 public override void generate_class_declaration (Class cl
, CCodeDeclarationSpace decl_space
) {
50 if (decl_space
.add_symbol_declaration (cl
, cl
.get_cname ())) {
54 if (cl
.base_class
!= null) {
55 // base class declaration
56 // necessary for ref and unref function declarations
57 generate_class_declaration (cl
.base_class
, decl_space
);
60 bool is_gtypeinstance
= !cl
.is_compact
;
61 bool is_fundamental
= is_gtypeinstance
&& cl
.base_class
== null;
63 if (is_gtypeinstance
) {
64 decl_space
.add_type_declaration (new
CCodeNewline ());
65 var macro
= "(%s_get_type ())".printf (cl
.get_lower_case_cname (null));
66 decl_space
.add_type_declaration (new
CCodeMacroReplacement (cl
.get_type_id (), macro
));
68 macro
= "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (cl
.get_type_id (), cl
.get_cname ());
69 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s(obj)".printf (cl
.get_upper_case_cname (null)), macro
));
71 macro
= "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (cl
.get_type_id (), cl
.get_cname ());
72 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl
.get_upper_case_cname (null)), macro
));
74 macro
= "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (cl
.get_type_id ());
75 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s(obj)".printf (get_type_check_function (cl
)), macro
));
77 macro
= "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (cl
.get_type_id ());
78 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s_CLASS(klass)".printf (get_type_check_function (cl
)), macro
));
80 macro
= "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (cl
.get_type_id (), cl
.get_cname ());
81 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (cl
.get_upper_case_cname (null)), macro
));
82 decl_space
.add_type_declaration (new
CCodeNewline ());
85 if (cl
.is_compact
&& cl
.base_class
!= null) {
86 decl_space
.add_type_declaration (new
CCodeTypeDefinition (cl
.base_class
.get_cname (), new
CCodeVariableDeclarator (cl
.get_cname ())));
88 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct _%s".printf (cl
.get_cname ()), new
CCodeVariableDeclarator (cl
.get_cname ())));
92 var ref_fun
= new
CCodeFunction (cl
.get_lower_case_cprefix () + "ref", "gpointer");
93 var unref_fun
= new
CCodeFunction (cl
.get_lower_case_cprefix () + "unref", "void");
94 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
95 ref_fun
.modifiers
= CCodeModifiers
.STATIC
;
96 unref_fun
.modifiers
= CCodeModifiers
.STATIC
;
99 ref_fun
.add_parameter (new
CCodeFormalParameter ("instance", "gpointer"));
100 unref_fun
.add_parameter (new
CCodeFormalParameter ("instance", "gpointer"));
102 decl_space
.add_type_member_declaration (ref_fun
.copy ());
103 decl_space
.add_type_member_declaration (unref_fun
.copy ());
105 // GParamSpec and GValue functions
106 string function_name
= cl
.get_lower_case_cname ("param_spec_");
108 var function
= new
CCodeFunction (function_name
, "GParamSpec*");
109 function
.add_parameter (new
CCodeFormalParameter ("name", "const gchar*"));
110 function
.add_parameter (new
CCodeFormalParameter ("nick", "const gchar*"));
111 function
.add_parameter (new
CCodeFormalParameter ("blurb", "const gchar*"));
112 function
.add_parameter (new
CCodeFormalParameter ("object_type", "GType"));
113 function
.add_parameter (new
CCodeFormalParameter ("flags", "GParamFlags"));
115 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
116 function
.modifiers
= CCodeModifiers
.STATIC
;
117 // avoid C warning as this function is not always used
118 function
.attributes
= "G_GNUC_UNUSED";
121 decl_space
.add_type_member_declaration (function
);
123 function
= new
CCodeFunction (cl
.get_set_value_function (), "void");
124 function
.add_parameter (new
CCodeFormalParameter ("value", "GValue*"));
125 function
.add_parameter (new
CCodeFormalParameter ("v_object", "gpointer"));
127 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
128 function
.modifiers
= CCodeModifiers
.STATIC
;
129 // avoid C warning as this function is not always used
130 function
.attributes
= "G_GNUC_UNUSED";
133 decl_space
.add_type_member_declaration (function
);
135 function
= new
CCodeFunction (cl
.get_take_value_function (), "void");
136 function
.add_parameter (new
CCodeFormalParameter ("value", "GValue*"));
137 function
.add_parameter (new
CCodeFormalParameter ("v_object", "gpointer"));
139 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
140 function
.modifiers
= CCodeModifiers
.STATIC
;
141 // avoid C warning as this function is not always used
142 function
.attributes
= "G_GNUC_UNUSED";
145 decl_space
.add_type_member_declaration (function
);
147 function
= new
CCodeFunction (cl
.get_get_value_function (), "gpointer");
148 function
.add_parameter (new
CCodeFormalParameter ("value", "const GValue*"));
150 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
151 function
.modifiers
= CCodeModifiers
.STATIC
;
152 // avoid C warning as this function is not always used
153 function
.attributes
= "G_GNUC_UNUSED";
156 decl_space
.add_type_member_declaration (function
);
157 } else if (!is_gtypeinstance
) {
158 if (cl
.base_class
== null) {
159 var function
= new
CCodeFunction (cl
.get_lower_case_cprefix () + "free", "void");
160 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
161 function
.modifiers
= CCodeModifiers
.STATIC
;
164 function
.add_parameter (new
CCodeFormalParameter ("self", cl
.get_cname () + "*"));
166 decl_space
.add_type_member_declaration (function
);
170 if (is_gtypeinstance
) {
171 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct _%sClass".printf (cl
.get_cname ()), new
CCodeVariableDeclarator ("%sClass".printf (cl
.get_cname ()))));
173 var type_fun
= new
ClassRegisterFunction (cl
, context
);
174 type_fun
.init_from_type (in_plugin
);
175 decl_space
.add_type_member_declaration (type_fun
.get_declaration ());
179 public override void generate_class_struct_declaration (Class cl
, CCodeDeclarationSpace decl_space
) {
180 if (decl_space
.add_symbol_declaration (cl
, "struct _" + cl
.get_cname ())) {
184 if (cl
.base_class
!= null) {
185 // base class declaration
186 generate_class_struct_declaration (cl
.base_class
, decl_space
);
188 foreach (DataType base_type
in cl
.get_base_types ()) {
189 var iface
= base_type
.data_type as Interface
;
191 generate_interface_declaration (iface
, decl_space
);
195 generate_class_declaration (cl
, decl_space
);
197 bool is_gtypeinstance
= !cl
.is_compact
;
198 bool is_fundamental
= is_gtypeinstance
&& cl
.base_class
== null;
200 var instance_struct
= new
CCodeStruct ("_%s".printf (cl
.get_cname ()));
201 var type_struct
= new
CCodeStruct ("_%sClass".printf (cl
.get_cname ()));
203 if (cl
.base_class
!= null) {
204 instance_struct
.add_field (cl
.base_class
.get_cname (), "parent_instance");
205 } else if (is_fundamental
) {
206 decl_space
.add_include ("glib-object.h");
207 instance_struct
.add_field ("GTypeInstance", "parent_instance");
208 instance_struct
.add_field ("volatile int", "ref_count");
211 if (cl
.is_compact
&& cl
.base_class
== null && cl
.get_fields ().size
== 0) {
212 // add dummy member, C doesn't allow empty structs
213 instance_struct
.add_field ("int", "dummy");
216 if (is_gtypeinstance
) {
217 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct %sPrivate".printf (instance_struct
.name
), new
CCodeVariableDeclarator ("%sPrivate".printf (cl
.get_cname ()))));
219 instance_struct
.add_field ("%sPrivate *".printf (cl
.get_cname ()), "priv");
220 if (is_fundamental
) {
221 type_struct
.add_field ("GTypeClass", "parent_class");
223 type_struct
.add_field ("%sClass".printf (cl
.base_class
.get_cname ()), "parent_class");
226 if (is_fundamental
) {
227 type_struct
.add_field ("void", "(*finalize) (%s *self)".printf (cl
.get_cname ()));
231 foreach (Method m
in cl
.get_methods ()) {
232 generate_virtual_method_declaration (m
, decl_space
, type_struct
);
235 foreach (Signal sig
in cl
.get_signals ()) {
236 if (sig
.default_handler
!= null) {
237 generate_virtual_method_declaration (sig
.default_handler
, decl_space
, type_struct
);
241 foreach (Property prop
in cl
.get_properties ()) {
242 if (!prop
.is_abstract
&& !prop
.is_virtual
) {
245 generate_type_declaration (prop
.property_type
, decl_space
);
247 var t
= (ObjectTypeSymbol
) prop
.parent_symbol
;
249 var this_type
= new
ObjectType (t
);
250 var cselfparam
= new
CCodeFormalParameter ("self", this_type
.get_cname ());
252 if (prop
.get_accessor
!= null) {
253 var vdeclarator
= new
CCodeFunctionDeclarator ("get_%s".printf (prop
.name
));
254 vdeclarator
.add_parameter (cselfparam
);
256 if (prop
.property_type
.is_real_non_null_struct_type ()) {
257 var cvalueparam
= new
CCodeFormalParameter ("result", prop
.get_accessor
.value_type
.get_cname () + "*");
258 vdeclarator
.add_parameter (cvalueparam
);
259 creturn_type
= "void";
261 creturn_type
= prop
.get_accessor
.value_type
.get_cname ();
264 var array_type
= prop
.property_type as ArrayType
;
265 if (array_type
!= null) {
266 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
267 vdeclarator
.add_parameter (new
CCodeFormalParameter (get_array_length_cname ("result", dim
), "int*"));
269 } else if ((prop
.property_type is DelegateType
) && ((DelegateType
) prop
.property_type
).delegate_symbol
.has_target
) {
270 vdeclarator
.add_parameter (new
CCodeFormalParameter (get_delegate_target_cname ("result"), "gpointer*"));
273 var vdecl
= new
CCodeDeclaration (creturn_type
);
274 vdecl
.add_declarator (vdeclarator
);
275 type_struct
.add_declaration (vdecl
);
277 if (prop
.set_accessor
!= null) {
278 CCodeFormalParameter cvalueparam
;
279 if (prop
.property_type
.is_real_non_null_struct_type ()) {
280 cvalueparam
= new
CCodeFormalParameter ("value", prop
.set_accessor
.value_type
.get_cname () + "*");
282 cvalueparam
= new
CCodeFormalParameter ("value", prop
.set_accessor
.value_type
.get_cname ());
285 var vdeclarator
= new
CCodeFunctionDeclarator ("set_%s".printf (prop
.name
));
286 vdeclarator
.add_parameter (cselfparam
);
287 vdeclarator
.add_parameter (cvalueparam
);
289 var array_type
= prop
.property_type as ArrayType
;
290 if (array_type
!= null) {
291 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
292 vdeclarator
.add_parameter (new
CCodeFormalParameter (get_array_length_cname ("value", dim
), "int"));
294 } else if ((prop
.property_type is DelegateType
) && ((DelegateType
) prop
.property_type
).delegate_symbol
.has_target
) {
295 vdeclarator
.add_parameter (new
CCodeFormalParameter (get_delegate_target_cname ("value"), "gpointer"));
298 var vdecl
= new
CCodeDeclaration ("void");
299 vdecl
.add_declarator (vdeclarator
);
300 type_struct
.add_declaration (vdecl
);
304 foreach (Field f
in cl
.get_fields ()) {
305 string field_ctype
= f
.variable_type
.get_cname ();
307 field_ctype
= "volatile " + field_ctype
;
310 if (f
.access
!= SymbolAccessibility
.PRIVATE
) {
311 if (f
.binding
== MemberBinding
.INSTANCE
) {
312 generate_type_declaration (f
.variable_type
, decl_space
);
314 instance_struct
.add_field (field_ctype
, f
.get_cname (), f
.variable_type
.get_cdeclarator_suffix ());
315 if (f
.variable_type is ArrayType
&& !f
.no_array_length
) {
316 // create fields to store array dimensions
317 var array_type
= (ArrayType
) f
.variable_type
;
319 if (!array_type
.fixed_length
) {
320 var len_type
= int_type
.copy ();
322 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
323 instance_struct
.add_field (len_type
.get_cname (), get_array_length_cname (f
.name
, dim
));
326 if (array_type
.rank
== 1 && f
.is_internal_symbol ()) {
327 instance_struct
.add_field (len_type
.get_cname (), get_array_size_cname (f
.name
));
330 } else if (f
.variable_type is DelegateType
) {
331 var delegate_type
= (DelegateType
) f
.variable_type
;
332 if (delegate_type
.delegate_symbol
.has_target
) {
333 // create field to store delegate target
334 instance_struct
.add_field ("gpointer", get_delegate_target_cname (f
.name
));
335 if (delegate_type
.value_owned
) {
336 instance_struct
.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (f
.name
));
340 } else if (f
.binding
== MemberBinding
.CLASS
) {
341 type_struct
.add_field (field_ctype
, f
.get_cname ());
346 if (!cl
.is_compact
|| cl
.base_class
== null) {
347 // derived compact classes do not have a struct
348 decl_space
.add_type_definition (instance_struct
);
351 if (is_gtypeinstance
) {
352 decl_space
.add_type_definition (type_struct
);
356 public virtual void generate_virtual_method_declaration (Method m
, CCodeDeclarationSpace decl_space
, CCodeStruct type_struct
) {
357 if (!m
.is_abstract
&& !m
.is_virtual
) {
361 var creturn_type
= m
.return_type
;
362 if (m
.return_type
.is_real_non_null_struct_type ()) {
363 // structs are returned via out parameter
364 creturn_type
= new
VoidType ();
367 // add vfunc field to the type struct
368 var vdeclarator
= new
CCodeFunctionDeclarator (m
.vfunc_name
);
369 var cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
371 generate_cparameters (m
, decl_space
, cparam_map
, new
CCodeFunction ("fake"), vdeclarator
);
373 var vdecl
= new
CCodeDeclaration (creturn_type
.get_cname ());
374 vdecl
.add_declarator (vdeclarator
);
375 type_struct
.add_declaration (vdecl
);
378 void generate_class_private_declaration (Class cl
, CCodeDeclarationSpace decl_space
) {
379 if (decl_space
.add_declaration (cl
.get_cname () + "Private")) {
383 bool is_gtypeinstance
= !cl
.is_compact
;
384 bool has_instance_locks
= false;
385 bool has_class_locks
= false;
387 var instance_priv_struct
= new
CCodeStruct ("_%sPrivate".printf (cl
.get_cname ()));
388 var type_priv_struct
= new
CCodeStruct ("_%sClassPrivate".printf (cl
.get_cname ()));
390 if (is_gtypeinstance
) {
391 /* create type, dup_func, and destroy_func fields for generic types */
392 foreach (TypeParameter type_param
in cl
.get_type_parameters ()) {
395 func_name
= "%s_type".printf (type_param
.name
.down ());
396 instance_priv_struct
.add_field ("GType", func_name
);
398 func_name
= "%s_dup_func".printf (type_param
.name
.down ());
399 instance_priv_struct
.add_field ("GBoxedCopyFunc", func_name
);
401 func_name
= "%s_destroy_func".printf (type_param
.name
.down ());
402 instance_priv_struct
.add_field ("GDestroyNotify", func_name
);
406 foreach (Field f
in cl
.get_fields ()) {
407 string field_ctype
= f
.variable_type
.get_cname ();
409 field_ctype
= "volatile " + field_ctype
;
412 if (f
.binding
== MemberBinding
.INSTANCE
) {
413 if (f
.access
== SymbolAccessibility
.PRIVATE
) {
414 generate_type_declaration (f
.variable_type
, decl_space
);
416 instance_priv_struct
.add_field (field_ctype
, f
.get_cname (), f
.variable_type
.get_cdeclarator_suffix ());
417 if (f
.variable_type is ArrayType
&& !f
.no_array_length
) {
418 // create fields to store array dimensions
419 var array_type
= (ArrayType
) f
.variable_type
;
420 var len_type
= int_type
.copy ();
422 if (!array_type
.fixed_length
) {
423 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
424 instance_priv_struct
.add_field (len_type
.get_cname (), get_array_length_cname (f
.name
, dim
));
427 if (array_type
.rank
== 1 && f
.is_internal_symbol ()) {
428 instance_priv_struct
.add_field (len_type
.get_cname (), get_array_size_cname (f
.name
));
431 } else if (f
.variable_type is DelegateType
) {
432 var delegate_type
= (DelegateType
) f
.variable_type
;
433 if (delegate_type
.delegate_symbol
.has_target
) {
434 // create field to store delegate target
435 instance_priv_struct
.add_field ("gpointer", get_delegate_target_cname (f
.name
));
436 if (delegate_type
.value_owned
) {
437 instance_priv_struct
.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (f
.name
));
443 if (f
.get_lock_used ()) {
444 has_instance_locks
= true;
445 // add field for mutex
446 instance_priv_struct
.add_field (mutex_type
.get_cname (), get_symbol_lock_name (f
.name
));
448 } else if (f
.binding
== MemberBinding
.CLASS
) {
449 if (f
.access
== SymbolAccessibility
.PRIVATE
) {
450 type_priv_struct
.add_field (field_ctype
, f
.get_cname ());
453 if (f
.get_lock_used ()) {
454 has_class_locks
= true;
455 // add field for mutex
456 type_priv_struct
.add_field (mutex_type
.get_cname (), get_symbol_lock_name (f
.get_cname ()));
461 foreach (Property prop
in cl
.get_properties ()) {
462 if (prop
.binding
== MemberBinding
.INSTANCE
) {
463 if (prop
.get_lock_used ()) {
464 has_instance_locks
= true;
465 // add field for mutex
466 instance_priv_struct
.add_field (mutex_type
.get_cname (), get_symbol_lock_name (prop
.name
));
468 } else if (prop
.binding
== MemberBinding
.CLASS
) {
469 if (prop
.get_lock_used ()) {
470 has_class_locks
= true;
471 // add field for mutex
472 type_priv_struct
.add_field (mutex_type
.get_cname (), get_symbol_lock_name (prop
.name
));
477 if (is_gtypeinstance
) {
478 if (cl
.has_class_private_fields
|| has_class_locks
) {
479 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct %s".printf (type_priv_struct
.name
), new
CCodeVariableDeclarator ("%sClassPrivate".printf (cl
.get_cname ()))));
480 if (!context
.require_glib_version (2, 24)) {
481 var cdecl
= new
CCodeDeclaration ("GQuark");
482 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_vala_%s_class_private_quark".printf (cl
.get_lower_case_cname ()), new
CCodeConstant ("0")));
483 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
484 decl_space
.add_type_declaration (cdecl
);
488 /* only add the *Private struct if it is not empty, i.e. we actually have private data */
489 if (cl
.has_private_fields
|| cl
.get_type_parameters ().size
> 0 || has_instance_locks
) {
490 decl_space
.add_type_definition (instance_priv_struct
);
491 var macro
= "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl
.get_type_id (), cl
.get_cname ());
492 decl_space
.add_type_member_declaration (new
CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl
.get_upper_case_cname (null)), macro
));
495 if (cl
.has_class_private_fields
|| has_class_locks
) {
496 decl_space
.add_type_member_declaration (type_priv_struct
);
499 if (context
.require_glib_version (2, 24)) {
500 macro
= "(G_TYPE_CLASS_GET_PRIVATE (klass, %s, %sClassPrivate))".printf (cl
.get_type_id (), cl
.get_cname ());
502 macro
= "((%sClassPrivate *) g_type_get_qdata (G_TYPE_FROM_CLASS (klass), _vala_%s_class_private_quark))".printf (cl
.get_cname(), cl
.get_lower_case_cname ());
504 decl_space
.add_type_member_declaration (new
CCodeMacroReplacement ("%s_GET_CLASS_PRIVATE(klass)".printf (cl
.get_upper_case_cname (null)), macro
));
506 decl_space
.add_type_member_declaration (prop_enum
);
508 if (cl
.has_private_fields
) {
509 Report
.error (cl
.source_reference
, "Private fields not supported in compact classes");
514 public override void visit_class (Class cl
) {
515 push_context (new
EmitContext (cl
));
517 var old_param_spec_struct
= param_spec_struct
;
518 var old_prop_enum
= prop_enum
;
519 var old_class_init_fragment
= class_init_fragment
;
520 var old_base_init_fragment
= base_init_fragment
;
521 var old_class_finalize_fragment
= class_finalize_fragment
;
522 var old_base_finalize_fragment
= base_finalize_fragment
;
523 var old_instance_init_fragment
= instance_init_fragment
;
524 var old_instance_finalize_fragment
= instance_finalize_fragment
;
526 bool is_gtypeinstance
= !cl
.is_compact
;
527 bool is_fundamental
= is_gtypeinstance
&& cl
.base_class
== null;
529 if (cl
.get_cname().len () < 3) {
531 Report
.error (cl
.source_reference
, "Class name `%s' is too short".printf (cl
.get_cname ()));
535 prop_enum
= new
CCodeEnum ();
536 prop_enum
.add_value (new
CCodeEnumValue ("%s_DUMMY_PROPERTY".printf (cl
.get_upper_case_cname (null))));
537 class_init_fragment
= new
CCodeFragment ();
538 base_init_fragment
= new
CCodeFragment ();
539 class_finalize_fragment
= new
CCodeFragment ();
540 base_finalize_fragment
= new
CCodeFragment ();
541 instance_init_fragment
= new
CCodeFragment ();
542 instance_finalize_fragment
= new
CCodeFragment ();
545 generate_class_struct_declaration (cl
, source_declarations
);
546 generate_class_private_declaration (cl
, source_declarations
);
548 if (!cl
.is_internal_symbol ()) {
549 generate_class_struct_declaration (cl
, header_declarations
);
551 if (!cl
.is_private_symbol ()) {
552 generate_class_struct_declaration (cl
, internal_header_declarations
);
555 cl
.accept_children (this
);
557 if (is_gtypeinstance
) {
558 if (is_fundamental
) {
559 param_spec_struct
= new
CCodeStruct ( "_%sParamSpec%s".printf(cl
.parent_symbol
.get_cprefix (), cl
.name
));
560 param_spec_struct
.add_field ("GParamSpec", "parent_instance");
561 source_declarations
.add_type_definition (param_spec_struct
);
563 source_declarations
.add_type_declaration (new
CCodeTypeDefinition ("struct %s".printf (param_spec_struct
.name
), new
CCodeVariableDeclarator ( "%sParamSpec%s".printf(cl
.parent_symbol
.get_cprefix (), cl
.name
))));
566 gvaluecollector_h_needed
= true;
568 add_type_value_table_init_function (cl
);
569 add_type_value_table_free_function (cl
);
570 add_type_value_table_copy_function (cl
);
571 add_type_value_table_peek_pointer_function (cl
);
572 add_type_value_table_collect_value_function (cl
);
573 add_type_value_table_lcopy_value_function (cl
);
574 add_g_param_spec_type_function (cl
);
575 add_g_value_get_function (cl
);
576 add_g_value_set_function (cl
);
577 add_g_value_take_function (cl
);
579 var ref_count
= new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "ref_count"), new
CCodeConstant ("1"));
580 instance_init_fragment
.append (new
CCodeExpressionStatement (ref_count
));
584 if (cl
.class_constructor
!= null || (!context
.require_glib_version (2, 24) && cl
.has_class_private_fields
)) {
585 add_base_init_function (cl
);
587 add_class_init_function (cl
);
589 if (cl
.class_destructor
!= null || (!context
.require_glib_version (2, 24) && cl
.has_class_private_fields
)) {
590 add_base_finalize_function (cl
);
593 if (cl
.static_destructor
!= null) {
594 add_class_finalize_function (cl
);
597 foreach (DataType base_type
in cl
.get_base_types ()) {
598 if (base_type
.data_type is Interface
) {
599 add_interface_init_function (cl
, (Interface
) base_type
.data_type
);
603 add_instance_init_function (cl
);
605 if (!cl
.is_compact
&& (cl
.get_fields ().size
> 0 || cl
.destructor
!= null || cl
.is_fundamental ())) {
606 add_finalize_function (cl
);
609 if (cl
.comment
!= null) {
610 source_type_member_definition
.append (new
CCodeComment (cl
.comment
.content
));
613 var type_fun
= new
ClassRegisterFunction (cl
, context
);
614 type_fun
.init_from_type (in_plugin
);
615 source_declarations
.add_type_member_declaration (type_fun
.get_source_declaration ());
616 source_type_member_definition
.append (type_fun
.get_definition ());
618 if (is_fundamental
) {
619 var ref_fun
= new
CCodeFunction (cl
.get_lower_case_cprefix () + "ref", "gpointer");
620 var unref_fun
= new
CCodeFunction (cl
.get_lower_case_cprefix () + "unref", "void");
621 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
622 ref_fun
.modifiers
= CCodeModifiers
.STATIC
;
623 unref_fun
.modifiers
= CCodeModifiers
.STATIC
;
626 ref_fun
.add_parameter (new
CCodeFormalParameter ("instance", "gpointer"));
627 unref_fun
.add_parameter (new
CCodeFormalParameter ("instance", "gpointer"));
629 var ref_block
= new
CCodeBlock ();
630 var unref_block
= new
CCodeBlock ();
632 var cdecl
= new
CCodeDeclaration (cl
.get_cname () + "*");
633 cdecl
.add_declarator (new
CCodeVariableDeclarator ("self", new
CCodeIdentifier ("instance")));
634 ref_block
.add_statement (cdecl
);
635 unref_block
.add_statement (cdecl
);
637 var ref_count
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "ref_count");
639 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_atomic_int_inc"));
640 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, ref_count
));
641 ref_block
.add_statement (new
CCodeExpressionStatement (ccall
));
643 ref_block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("instance")));
645 var destroy_block
= new
CCodeBlock ();
646 var get_class
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_CLASS".printf (cl
.get_upper_case_cname (null))));
647 get_class
.add_argument (new
CCodeIdentifier ("self"));
650 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_CLASS".printf (cl
.get_upper_case_cname (null))));
651 ccast
.add_argument (new
CCodeIdentifier ("self"));
652 ccall
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (ccast
, "finalize"));
653 ccall
.add_argument (new
CCodeIdentifier ("self"));
654 destroy_block
.add_statement (new
CCodeExpressionStatement (ccall
));
656 // free type instance
657 var free
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_free_instance"));
658 free
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "GTypeInstance *"));
659 destroy_block
.add_statement (new
CCodeExpressionStatement (free
));
661 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_atomic_int_dec_and_test"));
662 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, ref_count
));
663 unref_block
.add_statement (new
CCodeIfStatement (ccall
, destroy_block
));
665 ref_fun
.block
= ref_block
;
666 unref_fun
.block
= unref_block
;
668 source_type_member_definition
.append (ref_fun
);
669 source_type_member_definition
.append (unref_fun
);
672 if (cl
.base_class
== null) {
673 // derived compact classes do not have fields
674 add_instance_init_function (cl
);
676 var function
= new
CCodeFunction (cl
.get_lower_case_cprefix () + "free", "void");
677 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
678 function
.modifiers
= CCodeModifiers
.STATIC
;
681 function
.add_parameter (new
CCodeFormalParameter ("self", cl
.get_cname () + "*"));
683 var cblock
= new
CCodeBlock ();
685 if (cl
.destructor
!= null) {
686 cblock
.add_statement (cl
.destructor
.ccodenode
);
689 cblock
.add_statement (instance_finalize_fragment
);
691 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_slice_free"));
692 ccall
.add_argument (new
CCodeIdentifier (cl
.get_cname ()));
693 ccall
.add_argument (new
CCodeIdentifier ("self"));
694 cblock
.add_statement (new
CCodeExpressionStatement (ccall
));
696 function
.block
= cblock
;
698 source_type_member_definition
.append (function
);
702 param_spec_struct
= old_param_spec_struct
;
703 prop_enum
= old_prop_enum
;
704 class_init_fragment
= old_class_init_fragment
;
705 base_init_fragment
= old_base_init_fragment
;
706 class_finalize_fragment
= old_class_finalize_fragment
;
707 base_finalize_fragment
= old_base_finalize_fragment
;
708 instance_init_fragment
= old_instance_init_fragment
;
709 instance_finalize_fragment
= old_instance_finalize_fragment
;
714 private void add_type_value_table_init_function (Class cl
) {
715 var function
= new
CCodeFunction ("%s_init".printf (cl
.get_lower_case_cname ("value_")), "void");
716 function
.add_parameter (new
CCodeFormalParameter ("value", "GValue*"));
717 function
.modifiers
= CCodeModifiers
.STATIC
;
719 var init_block
= new
CCodeBlock ();
720 function
.block
= init_block
;
722 init_block
.add_statement(new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer"),new
CCodeConstant ("NULL"), CCodeAssignmentOperator
.SIMPLE
)));
723 source_type_member_definition
.append (function
);
726 private void add_type_value_table_free_function (Class cl
) {
727 var function
= new
CCodeFunction ("%s_free_value".printf (cl
.get_lower_case_cname ("value_")), "void");
728 function
.add_parameter (new
CCodeFormalParameter ("value", "GValue*"));
729 function
.modifiers
= CCodeModifiers
.STATIC
;
731 var init_block
= new
CCodeBlock ();
732 function
.block
= init_block
;
734 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
735 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_lower_case_cprefix () + "unref"));
736 ccall
.add_argument ( vpointer
);
738 var ifbody
= new
CCodeBlock ();
739 ifbody
.add_statement ( new
CCodeExpressionStatement(ccall
) );
741 init_block
.add_statement(new
CCodeIfStatement (vpointer
, ifbody
));
742 source_type_member_definition
.append (function
);
745 private void add_type_value_table_copy_function (Class cl
) {
746 var function
= new
CCodeFunction ("%s_copy_value".printf (cl
.get_lower_case_cname ("value_")), "void");
747 function
.add_parameter (new
CCodeFormalParameter ("src_value", "const GValue*"));
748 function
.add_parameter (new
CCodeFormalParameter ("dest_value", "GValue*"));
749 function
.modifiers
= CCodeModifiers
.STATIC
;
751 var init_block
= new
CCodeBlock ();
752 function
.block
= init_block
;
754 var dest_vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("dest_value"), "data[0]"),"v_pointer");
755 var src_vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("src_value"), "data[0]"),"v_pointer");
757 var ref_ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_lower_case_cprefix () + "ref"));
758 ref_ccall
.add_argument ( src_vpointer
);
760 var true_stmt
= new
CCodeBlock ();
761 true_stmt
.add_statement(new
CCodeExpressionStatement(new
CCodeAssignment (dest_vpointer
, ref_ccall
, CCodeAssignmentOperator
.SIMPLE
)));
763 var false_stmt
= new
CCodeBlock ();
764 false_stmt
.add_statement (new
CCodeExpressionStatement( new
CCodeAssignment (dest_vpointer
, new
CCodeConstant ("NULL"), CCodeAssignmentOperator
.SIMPLE
)));
766 var if_statement
= new
CCodeIfStatement (src_vpointer
, true_stmt
, false_stmt
);
767 init_block
.add_statement (if_statement
);
769 source_type_member_definition
.append (function
);
772 private void add_type_value_table_peek_pointer_function (Class cl
) {
773 var function
= new
CCodeFunction ("%s_peek_pointer".printf (cl
.get_lower_case_cname ("value_")), "gpointer");
774 function
.add_parameter (new
CCodeFormalParameter ("value", "const GValue*"));
775 function
.modifiers
= CCodeModifiers
.STATIC
;
777 var init_block
= new
CCodeBlock ();
778 function
.block
= init_block
;
780 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
781 var ret
= new
CCodeReturnStatement ( vpointer
);
782 init_block
.add_statement (ret
);
784 source_type_member_definition
.append (function
);
787 private void add_type_value_table_lcopy_value_function ( Class cl
) {
788 var function
= new
CCodeFunction ("%s_lcopy_value".printf (cl
.get_lower_case_cname ("value_")), "gchar*");
789 function
.add_parameter (new
CCodeFormalParameter ("value", "const GValue*"));
790 function
.add_parameter (new
CCodeFormalParameter ("n_collect_values", "guint"));
791 function
.add_parameter (new
CCodeFormalParameter ("collect_values", "GTypeCValue*"));
792 function
.add_parameter (new
CCodeFormalParameter ("collect_flags", "guint"));
793 function
.modifiers
= CCodeModifiers
.STATIC
;
795 var vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"), "v_pointer");
796 var object_p_ptr
= new
CCodeIdentifier ("*object_p");
797 var null_
= new
CCodeConstant ("NULL");
799 var init_block
= new
CCodeBlock ();
801 var ctypedecl
= new
CCodeDeclaration (cl
.get_cname () + "**");
802 ctypedecl
.add_declarator (new
CCodeVariableDeclarator ("object_p", new
CCodeMemberAccess (new
CCodeIdentifier ("collect_values[0]"),"v_pointer")));
803 init_block
.add_statement (ctypedecl
);
805 var value_type_name_fct
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE_NAME"));
806 value_type_name_fct
.add_argument (new
CCodeConstant ("value"));
808 var assert_condition
= new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("object_p"));
809 function
.block
= init_block
;
810 var assert_true
= new
CCodeBlock ();
811 var assert_printf
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strdup_printf"));
812 assert_printf
.add_argument (new
CCodeConstant ("\"value location for `%s' passed as NULL\""));
813 assert_printf
.add_argument (value_type_name_fct
);
814 assert_true
.add_statement (new
CCodeReturnStatement (assert_printf
));
815 var if_assert
= new
CCodeIfStatement (assert_condition
, assert_true
);
816 init_block
.add_statement (if_assert
);
818 var main_else_true
= new
CCodeBlock ();
819 var main_else_if_true
= new
CCodeBlock ();
820 var main_else_if_condition
= new
CCodeBinaryExpression (CCodeBinaryOperator
.AND
, new
CCodeIdentifier ("collect_flags"), new
CCodeIdentifier ("G_VALUE_NOCOPY_CONTENTS"));
821 var main_else_if
= new
CCodeIfStatement (main_else_if_condition
, main_else_if_true
, main_else_true
);
823 var main_true
= new
CCodeBlock ();
824 var main_condition
= new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, vpointer
);
825 var if_main
= new
CCodeIfStatement (main_condition
, main_true
, main_else_if
);
826 init_block
.add_statement (if_main
);
828 var ref_fct
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_ref_function()));
829 ref_fct
.add_argument (vpointer
);
831 main_true
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (object_p_ptr
, null_
, CCodeAssignmentOperator
.SIMPLE
)));
832 main_else_if_true
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (object_p_ptr
, vpointer
, CCodeAssignmentOperator
.SIMPLE
)));
833 main_else_true
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (object_p_ptr
, ref_fct
, CCodeAssignmentOperator
.SIMPLE
)));
835 init_block
.add_statement (new
CCodeReturnStatement (null_
));
836 source_type_member_definition
.append (function
);
839 private void add_type_value_table_collect_value_function (Class cl
) {
840 var function
= new
CCodeFunction ("%s_collect_value".printf (cl
.get_lower_case_cname ("value_")), "gchar*");
841 function
.add_parameter (new
CCodeFormalParameter ("value", "GValue*"));
842 function
.add_parameter (new
CCodeFormalParameter ("n_collect_values", "guint"));
843 function
.add_parameter (new
CCodeFormalParameter ("collect_values", "GTypeCValue*"));
844 function
.add_parameter (new
CCodeFormalParameter ("collect_flags", "guint"));
845 function
.modifiers
= CCodeModifiers
.STATIC
;
847 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
849 var init_block
= new
CCodeBlock ();
850 function
.block
= init_block
;
852 var collect_vpointer
= new
CCodeMemberAccess (new
CCodeIdentifier ("collect_values[0]"), "v_pointer");
854 var true_stmt
= new
CCodeBlock ();
855 var false_stmt
= new
CCodeBlock ();
856 var if_statement
= new
CCodeIfStatement (collect_vpointer
, true_stmt
, false_stmt
);
857 init_block
.add_statement (if_statement
);
859 var obj_identifier
= new
CCodeIdentifier ("object");
861 var ctypedecl
= new
CCodeDeclaration (cl
.get_cname () + "*");
862 ctypedecl
.add_declarator (new
CCodeVariableDeclarator ("object", collect_vpointer
));
863 true_stmt
.add_statement (ctypedecl
);
865 var l_expression
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (obj_identifier
, "parent_instance"), "g_class");
866 var sub_condition
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, l_expression
, new
CCodeConstant ("NULL"));
867 var sub_true_stmt
= new
CCodeBlock ();
868 var sub_false_stmt
= new
CCodeBlock ();
870 var reg_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_type_compatible"));
871 var type_check
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
872 type_check
.add_argument (new
CCodeIdentifier ("object"));
873 reg_call
.add_argument (type_check
);
875 var type_name_fct
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_name"));
876 type_name_fct
.add_argument (type_check
);
878 var stored_type
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
879 stored_type
.add_argument (new
CCodeIdentifier ("value"));
880 reg_call
.add_argument (stored_type
);
882 var value_type_name_fct
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE_NAME"));
883 value_type_name_fct
.add_argument (new
CCodeConstant ("value"));
885 var true_return
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strconcat"));
886 true_return
.add_argument (new
CCodeConstant ("\"invalid unclassed object pointer for value type `\""));
887 true_return
.add_argument (value_type_name_fct
);
888 true_return
.add_argument (new
CCodeConstant ("\"'\""));
889 true_return
.add_argument (new
CCodeConstant ("NULL"));
890 sub_true_stmt
.add_statement (new
CCodeReturnStatement (true_return
));
892 var false_return
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strconcat"));
893 false_return
.add_argument (new
CCodeConstant ("\"invalid object type `\""));
894 false_return
.add_argument (type_name_fct
);
895 false_return
.add_argument (new
CCodeConstant ("\"' for value type `\""));
896 false_return
.add_argument (value_type_name_fct
);
897 false_return
.add_argument (new
CCodeConstant ("\"'\""));
898 false_return
.add_argument (new
CCodeConstant ("NULL"));
899 sub_false_stmt
.add_statement (new
CCodeReturnStatement (false_return
));
901 var sub_else_if_statement
= new
CCodeIfStatement (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, reg_call
), sub_false_stmt
);
902 sub_else_if_statement
.else_if
= true;
903 var sub_if_statement
= new
CCodeIfStatement (sub_condition
, sub_true_stmt
, sub_else_if_statement
);
904 true_stmt
.add_statement (sub_if_statement
);
906 var ref_call
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_ref_function ()));
907 ref_call
.add_argument (new
CCodeIdentifier ("object"));
909 var true_assignment
= new
CCodeExpressionStatement (new
CCodeAssignment (vpointer
, ref_call
, CCodeAssignmentOperator
.SIMPLE
));
910 true_stmt
.add_statement (true_assignment
);
912 var else_assigment
= new
CCodeExpressionStatement (new
CCodeAssignment (vpointer
, new
CCodeConstant ("NULL"), CCodeAssignmentOperator
.SIMPLE
));
913 false_stmt
.add_statement (else_assigment
);
915 init_block
.add_statement (new
CCodeReturnStatement (new
CCodeConstant ("NULL")));
916 source_type_member_definition
.append (function
);
919 private void add_g_param_spec_type_function (Class cl
) {
920 string function_name
= cl
.get_lower_case_cname ("param_spec_");
922 var function
= new
CCodeFunction (function_name
, "GParamSpec*");
923 function
.add_parameter (new
CCodeFormalParameter ("name", "const gchar*"));
924 function
.add_parameter (new
CCodeFormalParameter ("nick", "const gchar*"));
925 function
.add_parameter (new
CCodeFormalParameter ("blurb", "const gchar*"));
926 function
.add_parameter (new
CCodeFormalParameter ("object_type", "GType"));
927 function
.add_parameter (new
CCodeFormalParameter ("flags", "GParamFlags"));
929 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
930 function
.modifiers
= CCodeModifiers
.STATIC
;
933 var init_block
= new
CCodeBlock ();
934 function
.block
= init_block
;
936 var ctypedecl
= new
CCodeDeclaration ("%sParamSpec%s*".printf (cl
.parent_symbol
.get_cprefix (), cl
.name
));
937 ctypedecl
.add_declarator ( new
CCodeVariableDeclarator ("spec"));
938 init_block
.add_statement (ctypedecl
);
940 var subccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_is_a"));
941 subccall
.add_argument (new
CCodeIdentifier ("object_type"));
942 subccall
.add_argument (new
CCodeIdentifier ( cl
.get_type_id() ));
944 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_val_if_fail"));
945 ccall
.add_argument (subccall
);
946 ccall
.add_argument (new
CCodeIdentifier ("NULL"));
947 init_block
.add_statement (new
CCodeExpressionStatement (ccall
));
949 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_param_spec_internal"));
950 ccall
.add_argument (new
CCodeIdentifier ( "G_TYPE_PARAM_OBJECT" ));
951 ccall
.add_argument (new
CCodeIdentifier ("name"));
952 ccall
.add_argument (new
CCodeIdentifier ("nick"));
953 ccall
.add_argument (new
CCodeIdentifier ("blurb"));
954 ccall
.add_argument (new
CCodeIdentifier ("flags"));
956 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("spec"), ccall
, CCodeAssignmentOperator
.SIMPLE
)));
958 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_PARAM_SPEC"));
959 ccall
.add_argument (new
CCodeIdentifier ("spec"));
961 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccall
, "value_type"), new
CCodeIdentifier ("object_type"), CCodeAssignmentOperator
.SIMPLE
)));
962 init_block
.add_statement (new
CCodeReturnStatement (ccall
));
963 source_type_member_definition
.append (function
);
966 private void add_g_value_set_function (Class cl
) {
967 var function
= new
CCodeFunction (cl
.get_set_value_function (), "void");
968 function
.add_parameter (new
CCodeFormalParameter ("value", "GValue*"));
969 function
.add_parameter (new
CCodeFormalParameter ("v_object", "gpointer"));
971 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
972 function
.modifiers
= CCodeModifiers
.STATIC
;
975 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
977 var init_block
= new
CCodeBlock ();
978 function
.block
= init_block
;
980 var ctypedecl
= new
CCodeDeclaration (cl
.get_cname()+"*");
981 ctypedecl
.add_declarator ( new
CCodeVariableDeclarator ("old"));
982 init_block
.add_statement (ctypedecl
);
984 var ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
985 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "value" ));
986 ccall_typecheck
.add_argument (new
CCodeIdentifier ( cl
.get_type_id() ));
988 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
989 ccall
.add_argument (ccall_typecheck
);
990 init_block
.add_statement (new
CCodeExpressionStatement (ccall
));
992 init_block
.add_statement(new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeConstant ("old"), vpointer
, CCodeAssignmentOperator
.SIMPLE
)));
994 var true_stmt
= new
CCodeBlock ();
995 var false_stmt
= new
CCodeBlock ();
996 var if_statement
= new
CCodeIfStatement (new
CCodeIdentifier ("v_object"), true_stmt
, false_stmt
);
997 init_block
.add_statement (if_statement
);
1000 ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
1001 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "v_object" ));
1002 ccall_typecheck
.add_argument (new
CCodeIdentifier ( cl
.get_type_id() ));
1004 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1005 ccall
.add_argument (ccall_typecheck
);
1006 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
1008 var ccall_typefrominstance
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1009 ccall_typefrominstance
.add_argument (new
CCodeIdentifier ( "v_object" ));
1011 var ccall_gvaluetype
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
1012 ccall_gvaluetype
.add_argument (new
CCodeIdentifier ( "value" ));
1014 var ccall_typecompatible
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_type_compatible"));
1015 ccall_typecompatible
.add_argument (ccall_typefrominstance
);
1016 ccall_typecompatible
.add_argument (ccall_gvaluetype
);
1018 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1019 ccall
.add_argument (ccall_typecompatible
);
1020 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
1022 true_stmt
.add_statement(new
CCodeExpressionStatement (new
CCodeAssignment (vpointer
, new
CCodeConstant ("v_object"), CCodeAssignmentOperator
.SIMPLE
)));
1024 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_ref_function ()));
1025 ccall
.add_argument (vpointer
);
1026 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
1028 false_stmt
.add_statement(new
CCodeExpressionStatement (new
CCodeAssignment (vpointer
, new
CCodeConstant ("NULL"), CCodeAssignmentOperator
.SIMPLE
)));
1030 true_stmt
= new
CCodeBlock ();
1031 if_statement
= new
CCodeIfStatement (new
CCodeIdentifier ("old"), true_stmt
);
1032 init_block
.add_statement (if_statement
);
1034 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_unref_function ()));
1035 ccall
.add_argument (new
CCodeIdentifier ("old"));
1036 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
1037 source_type_member_definition
.append (function
);
1040 private void add_g_value_take_function (Class cl
) {
1041 var function
= new
CCodeFunction (cl
.get_take_value_function (), "void");
1042 function
.add_parameter (new
CCodeFormalParameter ("value", "GValue*"));
1043 function
.add_parameter (new
CCodeFormalParameter ("v_object", "gpointer"));
1045 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
1046 function
.modifiers
= CCodeModifiers
.STATIC
;
1049 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
1051 var init_block
= new
CCodeBlock ();
1052 function
.block
= init_block
;
1054 var ctypedecl
= new
CCodeDeclaration (cl
.get_cname()+"*");
1055 ctypedecl
.add_declarator ( new
CCodeVariableDeclarator ("old"));
1056 init_block
.add_statement (ctypedecl
);
1058 var ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1059 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "value" ));
1060 ccall_typecheck
.add_argument (new
CCodeIdentifier ( cl
.get_type_id() ));
1062 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1063 ccall
.add_argument (ccall_typecheck
);
1064 init_block
.add_statement (new
CCodeExpressionStatement (ccall
));
1066 init_block
.add_statement(new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeConstant ("old"), vpointer
, CCodeAssignmentOperator
.SIMPLE
)));
1068 var true_stmt
= new
CCodeBlock ();
1069 var false_stmt
= new
CCodeBlock ();
1070 var if_statement
= new
CCodeIfStatement (new
CCodeIdentifier ("v_object"), true_stmt
, false_stmt
);
1071 init_block
.add_statement (if_statement
);
1074 ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
1075 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "v_object" ));
1076 ccall_typecheck
.add_argument (new
CCodeIdentifier ( cl
.get_type_id() ));
1078 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1079 ccall
.add_argument (ccall_typecheck
);
1080 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
1082 var ccall_typefrominstance
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
1083 ccall_typefrominstance
.add_argument (new
CCodeIdentifier ( "v_object" ));
1085 var ccall_gvaluetype
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
1086 ccall_gvaluetype
.add_argument (new
CCodeIdentifier ( "value" ));
1088 var ccall_typecompatible
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_type_compatible"));
1089 ccall_typecompatible
.add_argument (ccall_typefrominstance
);
1090 ccall_typecompatible
.add_argument (ccall_gvaluetype
);
1092 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
1093 ccall
.add_argument (ccall_typecompatible
);
1094 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
1096 true_stmt
.add_statement(new
CCodeExpressionStatement (new
CCodeAssignment (vpointer
, new
CCodeConstant ("v_object"), CCodeAssignmentOperator
.SIMPLE
)));
1098 false_stmt
.add_statement(new
CCodeExpressionStatement (new
CCodeAssignment (vpointer
, new
CCodeConstant ("NULL"), CCodeAssignmentOperator
.SIMPLE
)));
1100 true_stmt
= new
CCodeBlock ();
1101 if_statement
= new
CCodeIfStatement (new
CCodeIdentifier ("old"), true_stmt
);
1102 init_block
.add_statement (if_statement
);
1104 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_unref_function ()));
1105 ccall
.add_argument (new
CCodeIdentifier ("old"));
1106 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
1107 source_type_member_definition
.append (function
);
1110 private void add_g_value_get_function (Class cl
) {
1111 var function
= new
CCodeFunction (cl
.get_get_value_function (), "gpointer");
1112 function
.add_parameter (new
CCodeFormalParameter ("value", "const GValue*"));
1114 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
1115 function
.modifiers
= CCodeModifiers
.STATIC
;
1118 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
1120 var init_block
= new
CCodeBlock ();
1121 function
.block
= init_block
;
1123 var ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
1124 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "value" ));
1125 ccall_typecheck
.add_argument (new
CCodeIdentifier ( cl
.get_type_id() ));
1127 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_val_if_fail"));
1128 ccall
.add_argument (ccall_typecheck
);
1129 ccall
.add_argument (new
CCodeIdentifier ( "NULL" ));
1130 init_block
.add_statement (new
CCodeExpressionStatement (ccall
));
1132 init_block
.add_statement (new
CCodeReturnStatement ( vpointer
));
1133 source_type_member_definition
.append (function
);
1136 private void add_base_init_function (Class cl
) {
1137 var base_init
= new
CCodeFunction ("%s_base_init".printf (cl
.get_lower_case_cname (null)), "void");
1138 base_init
.add_parameter (new
CCodeFormalParameter ("klass", "%sClass *".printf (cl
.get_cname ())));
1139 base_init
.modifiers
= CCodeModifiers
.STATIC
;
1141 var init_block
= new
CCodeBlock ();
1142 base_init
.block
= init_block
;
1144 if (!context
.require_glib_version (2, 24) && cl
.has_class_private_fields
) {
1145 var block
= new
CCodeBlock ();
1146 var cdecl
= new
CCodeDeclaration ("%sClassPrivate *".printf (cl
.get_cname ()));
1147 cdecl
.add_declarator (new
CCodeVariableDeclarator ("priv"));
1148 block
.add_statement (cdecl
);
1149 cdecl
= new
CCodeDeclaration ("%sClassPrivate *".printf (cl
.get_cname ()));
1150 cdecl
.add_declarator (new
CCodeVariableDeclarator ("parent_priv", new
CCodeConstant ("NULL")));
1151 block
.add_statement (cdecl
);
1152 cdecl
= new
CCodeDeclaration ("GType");
1153 cdecl
.add_declarator (new
CCodeVariableDeclarator ("parent_type"));
1154 block
.add_statement (cdecl
);
1156 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_parent"));
1157 var ccall2
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_CLASS"));
1158 ccall2
.add_argument (new
CCodeIdentifier ("klass"));
1159 ccall
.add_argument (ccall2
);
1160 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("parent_type"), ccall
)));
1162 var iftrue
= new
CCodeBlock ();
1163 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl
.get_upper_case_cname (null))));
1164 ccall2
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_peek"));
1165 ccall2
.add_argument (new
CCodeIdentifier ("parent_type"));
1166 ccall
.add_argument (ccall2
);
1167 iftrue
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("parent_priv"), ccall
)));
1168 block
.add_statement (new
CCodeIfStatement (new
CCodeIdentifier ("parent_type"), iftrue
));
1170 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_slice_new0"));
1171 ccall
.add_argument (new
CCodeIdentifier ("%sClassPrivate".printf(cl
.get_cname())));
1173 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("priv"), ccall
)));
1175 source_declarations
.add_include ("string.h");
1177 iftrue
= new
CCodeBlock ();
1178 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("memcpy"));
1179 ccall
.add_argument (new
CCodeIdentifier ("priv"));
1180 ccall
.add_argument (new
CCodeIdentifier ("parent_priv"));
1181 ccall
.add_argument (new
CCodeIdentifier ("sizeof (%sClassPrivate)".printf(cl
.get_cname())));
1182 iftrue
.add_statement (new
CCodeExpressionStatement (ccall
));
1184 block
.add_statement (new
CCodeIfStatement (new
CCodeIdentifier ("parent_priv"), iftrue
));
1186 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_set_qdata"));
1187 ccall2
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_CLASS"));
1188 ccall2
.add_argument (new
CCodeIdentifier ("klass"));
1189 ccall
.add_argument (ccall2
);
1190 ccall
.add_argument (new
CCodeIdentifier ("_vala_%s_class_private_quark".printf (cl
.get_lower_case_cname ())));
1191 ccall
.add_argument (new
CCodeIdentifier ("priv"));
1192 block
.add_statement (new
CCodeExpressionStatement (ccall
));
1194 init_block
.add_statement (block
);
1196 block
= new
CCodeBlock ();
1197 cdecl
= new
CCodeDeclaration ("%sClassPrivate *".printf (cl
.get_cname ()));
1198 cdecl
.add_declarator (new
CCodeVariableDeclarator ("priv"));
1199 block
.add_statement (cdecl
);
1201 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl
.get_upper_case_cname (null))));
1202 ccall
.add_argument (new
CCodeConstant ("klass"));
1203 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("priv"), ccall
)));
1205 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_slice_free"));
1206 ccall
.add_argument (new
CCodeIdentifier ("%sClassPrivate".printf (cl
.get_cname ())));
1207 ccall
.add_argument (new
CCodeIdentifier ("priv"));
1208 block
.add_statement (new
CCodeExpressionStatement (ccall
));
1209 base_finalize_fragment
.append (block
);
1212 init_block
.add_statement (base_init_fragment
);
1214 source_type_member_definition
.append (base_init
);
1217 public virtual void generate_class_init (Class cl
, CCodeBlock init_block
) {
1220 private void add_class_init_function (Class cl
) {
1221 var class_init
= new
CCodeFunction ("%s_class_init".printf (cl
.get_lower_case_cname (null)), "void");
1222 class_init
.add_parameter (new
CCodeFormalParameter ("klass", "%sClass *".printf (cl
.get_cname ())));
1223 class_init
.modifiers
= CCodeModifiers
.STATIC
;
1225 var init_block
= new
CCodeBlock ();
1226 class_init
.block
= init_block
;
1228 CCodeFunctionCall ccall
;
1230 /* save pointer to parent class */
1231 var parent_decl
= new
CCodeDeclaration ("gpointer");
1232 var parent_var_decl
= new
CCodeVariableDeclarator ("%s_parent_class".printf (cl
.get_lower_case_cname (null)));
1233 parent_var_decl
.initializer
= new
CCodeConstant ("NULL");
1234 parent_decl
.add_declarator (parent_var_decl
);
1235 parent_decl
.modifiers
= CCodeModifiers
.STATIC
;
1236 source_declarations
.add_type_member_declaration (parent_decl
);
1237 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_peek_parent"));
1238 ccall
.add_argument (new
CCodeIdentifier ("klass"));
1239 var parent_assignment
= new
CCodeAssignment (new
CCodeIdentifier ("%s_parent_class".printf (cl
.get_lower_case_cname (null))), ccall
);
1240 init_block
.add_statement (new
CCodeExpressionStatement (parent_assignment
));
1243 if (!cl
.is_compact
&& !cl
.is_subtype_of (gobject_type
) && (cl
.get_fields ().size
> 0 || cl
.destructor
!= null || cl
.is_fundamental ())) {
1244 // set finalize function
1245 var fundamental_class
= cl
;
1246 while (fundamental_class
.base_class
!= null) {
1247 fundamental_class
= fundamental_class
.base_class
;
1250 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (fundamental_class
.get_upper_case_cname (null))));
1251 ccall
.add_argument (new
CCodeIdentifier ("klass"));
1252 var finalize_assignment
= new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccall
, "finalize"), new
CCodeIdentifier (cl
.get_lower_case_cprefix () + "finalize"));
1253 init_block
.add_statement (new
CCodeExpressionStatement (finalize_assignment
));
1256 /* add struct for private fields */
1257 if (cl
.has_private_fields
|| cl
.get_type_parameters ().size
> 0) {
1258 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_add_private"));
1259 ccall
.add_argument (new
CCodeIdentifier ("klass"));
1260 ccall
.add_argument (new
CCodeConstant ("sizeof (%sPrivate)".printf (cl
.get_cname ())));
1261 init_block
.add_statement (new
CCodeExpressionStatement (ccall
));
1264 /* connect overridden methods */
1265 foreach (Method m
in cl
.get_methods ()) {
1266 if (m
.base_method
== null) {
1269 var base_type
= m
.base_method
.parent_symbol
;
1271 // there is currently no default handler for abstract async methods
1272 if (!m
.is_abstract
|| !m
.coroutine
) {
1273 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (((Class
) base_type
).get_upper_case_cname (null))));
1274 ccast
.add_argument (new
CCodeIdentifier ("klass"));
1276 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, m
.base_method
.vfunc_name
), new
CCodeIdentifier (m
.get_real_cname ()))));
1279 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, m
.base_method
.get_finish_vfunc_name ()), new
CCodeIdentifier (m
.get_finish_real_cname ()))));
1284 /* connect default signal handlers */
1285 foreach (Signal sig
in cl
.get_signals ()) {
1286 if (sig
.default_handler
== null) {
1289 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (cl
.get_upper_case_cname (null))));
1290 ccast
.add_argument (new
CCodeIdentifier ("klass"));
1291 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, sig
.default_handler
.vfunc_name
), new
CCodeIdentifier (sig
.default_handler
.get_real_cname ()))));
1294 /* connect overridden properties */
1295 foreach (Property prop
in cl
.get_properties ()) {
1296 if (prop
.base_property
== null) {
1299 var base_type
= prop
.base_property
.parent_symbol
;
1301 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (((Class
) base_type
).get_upper_case_cname (null))));
1302 ccast
.add_argument (new
CCodeIdentifier ("klass"));
1304 if (prop
.get_accessor
!= null) {
1305 string cname
= "%s_real_get_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
1306 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, "get_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
))));
1308 if (prop
.set_accessor
!= null) {
1309 string cname
= "%s_real_set_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
1310 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, "set_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
))));
1314 generate_class_init (cl
, init_block
);
1316 if (!cl
.is_compact
) {
1317 /* create signals */
1318 foreach (Signal sig
in cl
.get_signals ()) {
1319 if (sig
.comment
!= null) {
1320 init_block
.add_statement (new
CCodeComment (sig
.comment
.content
));
1322 init_block
.add_statement (new
CCodeExpressionStatement (get_signal_creation (sig
, cl
)));
1326 init_block
.add_statement (register_dbus_info (cl
));
1327 init_block
.add_statement (class_init_fragment
);
1329 source_type_member_definition
.append (class_init
);
1332 private void add_interface_init_function (Class cl
, Interface iface
) {
1333 var iface_init
= new
CCodeFunction ("%s_%s_interface_init".printf (cl
.get_lower_case_cname (null), iface
.get_lower_case_cname (null)), "void");
1334 iface_init
.add_parameter (new
CCodeFormalParameter ("iface", "%s *".printf (iface
.get_type_cname ())));
1335 iface_init
.modifiers
= CCodeModifiers
.STATIC
;
1337 var init_block
= new
CCodeBlock ();
1338 iface_init
.block
= init_block
;
1340 CCodeFunctionCall ccall
;
1342 /* save pointer to parent vtable */
1343 string parent_iface_var
= "%s_%s_parent_iface".printf (cl
.get_lower_case_cname (null), iface
.get_lower_case_cname (null));
1344 var parent_decl
= new
CCodeDeclaration (iface
.get_type_cname () + "*");
1345 var parent_var_decl
= new
CCodeVariableDeclarator (parent_iface_var
);
1346 parent_var_decl
.initializer
= new
CCodeConstant ("NULL");
1347 parent_decl
.add_declarator (parent_var_decl
);
1348 parent_decl
.modifiers
= CCodeModifiers
.STATIC
;
1349 source_declarations
.add_type_member_declaration (parent_decl
);
1350 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_interface_peek_parent"));
1351 ccall
.add_argument (new
CCodeIdentifier ("iface"));
1352 var parent_assignment
= new
CCodeAssignment (new
CCodeIdentifier (parent_iface_var
), ccall
);
1353 init_block
.add_statement (new
CCodeExpressionStatement (parent_assignment
));
1355 foreach (Method m
in cl
.get_methods ()) {
1356 if (m
.base_interface_method
== null) {
1360 var base_type
= m
.base_interface_method
.parent_symbol
;
1361 if (base_type
!= iface
) {
1365 var ciface
= new
CCodeIdentifier ("iface");
1366 CCodeExpression cfunc
;
1367 if (m
.is_abstract
|| m
.is_virtual
) {
1368 cfunc
= new
CCodeIdentifier (m
.get_cname ());
1369 cfunc
= cast_method_pointer (m
, cfunc
, iface
);
1371 cfunc
= new
CCodeIdentifier (m
.get_real_cname ());
1373 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, m
.base_interface_method
.vfunc_name
), cfunc
)));
1376 if (m
.is_abstract
|| m
.is_virtual
) {
1377 cfunc
= new
CCodeIdentifier (m
.get_finish_cname ());
1379 cfunc
= new
CCodeIdentifier (m
.get_finish_real_cname ());
1381 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, m
.base_interface_method
.get_finish_vfunc_name ()), cfunc
)));
1385 // connect inherited implementations
1386 foreach (Method m
in iface
.get_methods ()) {
1387 if (m
.is_abstract
) {
1388 Method cl_method
= null;
1389 var base_class
= cl
;
1390 while (base_class
!= null && cl_method
== null) {
1391 cl_method
= base_class
.scope
.lookup (m
.name
) as Method
;
1392 base_class
= base_class
.base_class
;
1394 if (base_class
!= null && cl_method
.parent_symbol
!= cl
) {
1395 // method inherited from base class
1397 var base_method
= cl_method
;
1398 if (cl_method
.base_method
!= null) {
1399 base_method
= cl_method
.base_method
;
1400 } else if (cl_method
.base_interface_method
!= null) {
1401 base_method
= cl_method
.base_interface_method
;
1404 generate_method_declaration (base_method
, source_declarations
);
1406 CCodeExpression cfunc
= new
CCodeIdentifier (base_method
.get_cname ());
1407 cfunc
= cast_method_pointer (base_method
, cfunc
, iface
);
1408 var ciface
= new
CCodeIdentifier ("iface");
1409 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, m
.vfunc_name
), cfunc
)));
1414 foreach (Property prop
in cl
.get_properties ()) {
1415 if (prop
.base_interface_property
== null) {
1419 var base_type
= (ObjectTypeSymbol
) prop
.base_interface_property
.parent_symbol
;
1420 if (base_type
!= iface
) {
1424 var ciface
= new
CCodeIdentifier ("iface");
1426 if (prop
.get_accessor
!= null) {
1427 string cname
= "%s_real_get_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
1428 if (prop
.is_abstract
|| prop
.is_virtual
) {
1429 cname
= "%s_get_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
1432 CCodeExpression cfunc
= new
CCodeIdentifier (cname
);
1433 if (prop
.is_abstract
|| prop
.is_virtual
) {
1434 cfunc
= cast_property_accessor_pointer (prop
.get_accessor
, cfunc
, base_type
);
1436 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, "get_%s".printf (prop
.name
)), cfunc
)));
1438 if (prop
.set_accessor
!= null) {
1439 string cname
= "%s_real_set_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
1440 if (prop
.is_abstract
|| prop
.is_virtual
) {
1441 cname
= "%s_set_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
1444 CCodeExpression cfunc
= new
CCodeIdentifier (cname
);
1445 if (prop
.is_abstract
|| prop
.is_virtual
) {
1446 cfunc
= cast_property_accessor_pointer (prop
.set_accessor
, cfunc
, base_type
);
1448 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, "set_%s".printf (prop
.name
)), cfunc
)));
1452 foreach (Property prop
in iface
.get_properties ()) {
1453 if (!prop
.is_abstract
) {
1457 Property cl_prop
= null;
1458 var base_class
= cl
;
1459 while (base_class
!= null && cl_prop
== null) {
1460 cl_prop
= base_class
.scope
.lookup (prop
.name
) as Property
;
1461 base_class
= base_class
.base_class
;
1463 if (base_class
!= null && cl_prop
.parent_symbol
!= cl
) {
1464 // property inherited from base class
1466 var base_property
= cl_prop
;
1467 if (cl_prop
.base_property
!= null) {
1468 base_property
= cl_prop
.base_property
;
1469 } else if (cl_prop
.base_interface_property
!= null) {
1470 base_property
= cl_prop
.base_interface_property
;
1473 var ciface
= new
CCodeIdentifier ("iface");
1475 if (base_property
.get_accessor
!= null) {
1476 generate_property_accessor_declaration (base_property
.get_accessor
, source_declarations
);
1478 string cname
= base_property
.get_accessor
.get_cname ();
1479 CCodeExpression cfunc
= new
CCodeIdentifier (cname
);
1480 cfunc
= cast_property_accessor_pointer (prop
.get_accessor
, cfunc
, iface
);
1481 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, "get_%s".printf (prop
.name
)), cfunc
)));
1483 if (base_property
.set_accessor
!= null) {
1484 generate_property_accessor_declaration (base_property
.set_accessor
, source_declarations
);
1486 string cname
= base_property
.set_accessor
.get_cname ();
1487 CCodeExpression cfunc
= new
CCodeIdentifier (cname
);
1488 cfunc
= cast_property_accessor_pointer (prop
.set_accessor
, cfunc
, iface
);
1489 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, "set_%s".printf (prop
.name
)), cfunc
)));
1494 source_type_member_definition
.append (iface_init
);
1497 CCodeExpression
cast_property_accessor_pointer (PropertyAccessor acc
, CCodeExpression cfunc
, ObjectTypeSymbol base_type
) {
1499 if (acc
.readable
&& acc
.value_type
.is_real_non_null_struct_type ()) {
1500 cast
= "void (*) (%s *, %s *)".printf (base_type
.get_cname (), acc
.value_type
.get_cname ());
1501 } else if (acc
.readable
) {
1502 cast
= "%s (*) (%s *)".printf (acc
.value_type
.get_cname (), base_type
.get_cname ());
1503 } else if (acc
.value_type
.is_real_non_null_struct_type ()) {
1504 cast
= "void (*) (%s *, %s *)".printf (base_type
.get_cname (), acc
.value_type
.get_cname ());
1506 cast
= "void (*) (%s *, %s)".printf (base_type
.get_cname (), acc
.value_type
.get_cname ());
1508 return new
CCodeCastExpression (cfunc
, cast
);
1511 CCodeExpression
cast_method_pointer (Method m
, CCodeExpression cfunc
, ObjectTypeSymbol base_type
) {
1512 // Cast the function pointer to match the interface
1513 string cast
= m
.return_type
.get_cname () + " (*)";
1514 string cast_args
= base_type
.get_cname () + "*";
1516 var vdeclarator
= new
CCodeFunctionDeclarator (m
.vfunc_name
);
1517 var cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
1519 generate_cparameters (m
, source_declarations
, cparam_map
, new
CCodeFunction ("fake"), vdeclarator
);
1521 // append C arguments in the right order
1526 foreach (int pos
in cparam_map
.get_keys ()) {
1527 if (pos
> last_pos
&& (min_pos
== -1 || pos
< min_pos
)) {
1531 if (last_pos
!= -1) { // Skip the 1st parameter
1532 if (min_pos
== -1) {
1535 cast_args
+= " ," + cparam_map
.get (min_pos
).type_name
;
1539 cast
+= "(" + cast_args
+ ")";
1540 return new
CCodeCastExpression (cfunc
, cast
);
1543 private void add_instance_init_function (Class cl
) {
1544 var instance_init
= new
CCodeFunction ("%s_instance_init".printf (cl
.get_lower_case_cname (null)), "void");
1545 instance_init
.add_parameter (new
CCodeFormalParameter ("self", "%s *".printf (cl
.get_cname ())));
1546 instance_init
.modifiers
= CCodeModifiers
.STATIC
;
1548 if (cl
.is_compact
) {
1549 // Add declaration, since the instance_init function is explicitly called
1550 // by the creation methods
1551 source_declarations
.add_type_member_declaration (instance_init
.copy ());
1554 var init_block
= new
CCodeBlock ();
1555 instance_init
.block
= init_block
;
1557 if (!cl
.is_compact
&& (cl
.has_private_fields
|| cl
.get_type_parameters ().size
> 0)) {
1558 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_PRIVATE".printf (cl
.get_upper_case_cname (null))));
1559 ccall
.add_argument (new
CCodeIdentifier ("self"));
1560 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "priv"), ccall
)));
1563 init_block
.add_statement (instance_init_fragment
);
1565 source_type_member_definition
.append (instance_init
);
1568 private void add_class_finalize_function (Class cl
) {
1569 var function
= new
CCodeFunction ("%s_class_finalize".printf (cl
.get_lower_case_cname (null)), "void");
1570 function
.modifiers
= CCodeModifiers
.STATIC
;
1572 function
.add_parameter (new
CCodeFormalParameter ("klass", cl
.get_cname () + "Class *"));
1573 source_declarations
.add_type_member_declaration (function
.copy ());
1575 var cblock
= new
CCodeBlock ();
1577 if (cl
.class_destructor
!= null) {
1578 cblock
.add_statement (cl
.class_destructor
.ccodenode
);
1581 cblock
.add_statement (class_finalize_fragment
);
1583 function
.block
= cblock
;
1584 source_type_member_definition
.append (function
);
1587 private void add_base_finalize_function (Class cl
) {
1588 var function
= new
CCodeFunction ("%s_base_finalize".printf (cl
.get_lower_case_cname (null)), "void");
1589 function
.modifiers
= CCodeModifiers
.STATIC
;
1591 function
.add_parameter (new
CCodeFormalParameter ("klass", cl
.get_cname () + "Class *"));
1592 source_declarations
.add_type_member_declaration (function
.copy ());
1594 var cblock
= new
CCodeBlock ();
1596 if (cl
.class_destructor
!= null) {
1597 cblock
.add_statement (cl
.class_destructor
.ccodenode
);
1600 cblock
.add_statement (base_finalize_fragment
);
1602 function
.block
= cblock
;
1603 source_type_member_definition
.append (function
);
1606 private void add_finalize_function (Class cl
) {
1607 var function
= new
CCodeFunction ("%s_finalize".printf (cl
.get_lower_case_cname (null)), "void");
1608 function
.modifiers
= CCodeModifiers
.STATIC
;
1610 var fundamental_class
= cl
;
1611 while (fundamental_class
.base_class
!= null) {
1612 fundamental_class
= fundamental_class
.base_class
;
1615 function
.add_parameter (new
CCodeFormalParameter ("obj", fundamental_class
.get_cname () + "*"));
1617 source_declarations
.add_type_member_declaration (function
.copy ());
1620 var cblock
= new
CCodeBlock ();
1622 CCodeFunctionCall ccall
= generate_instance_cast (new
CCodeIdentifier ("obj"), cl
);
1624 var cdecl
= new
CCodeDeclaration ("%s *".printf (cl
.get_cname ()));
1625 cdecl
.add_declarator (new
CCodeVariableDeclarator ("self", ccall
));
1627 cblock
.add_statement (cdecl
);
1629 if (cl
.destructor
!= null) {
1630 cblock
.add_statement (cl
.destructor
.ccodenode
);
1633 cblock
.add_statement (instance_finalize_fragment
);
1635 // chain up to finalize function of the base class
1636 if (cl
.base_class
!= null) {
1637 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (fundamental_class
.get_upper_case_cname ())));
1638 ccast
.add_argument (new
CCodeIdentifier ("%s_parent_class".printf (cl
.get_lower_case_cname (null))));
1639 ccall
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (ccast
, "finalize"));
1640 ccall
.add_argument (new
CCodeIdentifier ("obj"));
1641 cblock
.add_statement (new
CCodeExpressionStatement (ccall
));
1645 function
.block
= cblock
;
1647 source_type_member_definition
.append (function
);
1650 public override CCodeFunctionCall
get_param_spec (Property prop
) {
1651 var cspec
= new
CCodeFunctionCall ();
1652 cspec
.add_argument (prop
.get_canonical_cconstant ());
1653 cspec
.add_argument (new
CCodeConstant ("\"%s\"".printf (prop
.nick
)));
1654 cspec
.add_argument (new
CCodeConstant ("\"%s\"".printf (prop
.blurb
)));
1657 if (prop
.property_type
.data_type is Class
|| prop
.property_type
.data_type is Interface
) {
1658 string param_spec_name
= prop
.property_type
.data_type
.get_param_spec_function ();
1659 cspec
.call
= new
CCodeIdentifier (param_spec_name
);
1660 if (param_spec_name
== "g_param_spec_string") {
1661 cspec
.add_argument (new
CCodeConstant ("NULL"));
1662 } else if (param_spec_name
== "g_param_spec_variant") {
1663 cspec
.add_argument (new
CCodeConstant ("G_VARIANT_TYPE_ANY"));
1664 cspec
.add_argument (new
CCodeConstant ("NULL"));
1665 } else if (prop
.property_type
.data_type
.get_type_id () != "G_TYPE_POINTER") {
1666 cspec
.add_argument (new
CCodeIdentifier (prop
.property_type
.data_type
.get_type_id ()));
1668 } else if (prop
.property_type
.data_type is Enum
) {
1669 var e
= prop
.property_type
.data_type as Enum
;
1670 if (e
.has_type_id
) {
1672 cspec
.call
= new
CCodeIdentifier ("g_param_spec_flags");
1674 cspec
.call
= new
CCodeIdentifier ("g_param_spec_enum");
1676 cspec
.add_argument (new
CCodeIdentifier (e
.get_type_id ()));
1679 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uint");
1680 cspec
.add_argument (new
CCodeConstant ("0"));
1681 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT"));
1683 cspec
.call
= new
CCodeIdentifier ("g_param_spec_int");
1684 cspec
.add_argument (new
CCodeConstant ("G_MININT"));
1685 cspec
.add_argument (new
CCodeConstant ("G_MAXINT"));
1689 if (prop
.initializer
!= null) {
1690 cspec
.add_argument ((CCodeExpression
) prop
.initializer
.ccodenode
);
1692 cspec
.add_argument (new
CCodeConstant (prop
.property_type
.data_type
.get_default_value ()));
1694 } else if (prop
.property_type
.data_type is Struct
) {
1695 var st
= (Struct
) prop
.property_type
.data_type
;
1696 if (st
.get_type_id () == "G_TYPE_INT") {
1697 cspec
.call
= new
CCodeIdentifier ("g_param_spec_int");
1698 cspec
.add_argument (new
CCodeConstant ("G_MININT"));
1699 cspec
.add_argument (new
CCodeConstant ("G_MAXINT"));
1700 if (prop
.initializer
!= null) {
1701 cspec
.add_argument ((CCodeExpression
) prop
.initializer
.ccodenode
);
1703 cspec
.add_argument (new
CCodeConstant ("0"));
1705 } else if (st
.get_type_id () == "G_TYPE_UINT") {
1706 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uint");
1707 cspec
.add_argument (new
CCodeConstant ("0"));
1708 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT"));
1709 if (prop
.initializer
!= null) {
1710 cspec
.add_argument ((CCodeExpression
) prop
.initializer
.ccodenode
);
1712 cspec
.add_argument (new
CCodeConstant ("0U"));
1714 } else if (st
.get_type_id () == "G_TYPE_INT64") {
1715 cspec
.call
= new
CCodeIdentifier ("g_param_spec_int64");
1716 cspec
.add_argument (new
CCodeConstant ("G_MININT64"));
1717 cspec
.add_argument (new
CCodeConstant ("G_MAXINT64"));
1718 if (prop
.initializer
!= null) {
1719 cspec
.add_argument ((CCodeExpression
) prop
.initializer
.ccodenode
);
1721 cspec
.add_argument (new
CCodeConstant ("0"));
1723 } else if (st
.get_type_id () == "G_TYPE_UINT64") {
1724 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uint64");
1725 cspec
.add_argument (new
CCodeConstant ("0"));
1726 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT64"));
1727 if (prop
.initializer
!= null) {
1728 cspec
.add_argument ((CCodeExpression
) prop
.initializer
.ccodenode
);
1730 cspec
.add_argument (new
CCodeConstant ("0U"));
1732 } else if (st
.get_type_id () == "G_TYPE_LONG") {
1733 cspec
.call
= new
CCodeIdentifier ("g_param_spec_long");
1734 cspec
.add_argument (new
CCodeConstant ("G_MINLONG"));
1735 cspec
.add_argument (new
CCodeConstant ("G_MAXLONG"));
1736 if (prop
.initializer
!= null) {
1737 cspec
.add_argument ((CCodeExpression
) prop
.initializer
.ccodenode
);
1739 cspec
.add_argument (new
CCodeConstant ("0L"));
1741 } else if (st
.get_type_id () == "G_TYPE_ULONG") {
1742 cspec
.call
= new
CCodeIdentifier ("g_param_spec_ulong");
1743 cspec
.add_argument (new
CCodeConstant ("0"));
1744 cspec
.add_argument (new
CCodeConstant ("G_MAXULONG"));
1745 if (prop
.initializer
!= null) {
1746 cspec
.add_argument ((CCodeExpression
) prop
.initializer
.ccodenode
);
1748 cspec
.add_argument (new
CCodeConstant ("0UL"));
1750 } else if (st
.get_type_id () == "G_TYPE_BOOLEAN") {
1751 cspec
.call
= new
CCodeIdentifier ("g_param_spec_boolean");
1752 if (prop
.initializer
!= null) {
1753 cspec
.add_argument ((CCodeExpression
) prop
.initializer
.ccodenode
);
1755 cspec
.add_argument (new
CCodeConstant ("FALSE"));
1757 } else if (st
.get_type_id () == "G_TYPE_CHAR") {
1758 cspec
.call
= new
CCodeIdentifier ("g_param_spec_char");
1759 cspec
.add_argument (new
CCodeConstant ("G_MININT8"));
1760 cspec
.add_argument (new
CCodeConstant ("G_MAXINT8"));
1761 if (prop
.initializer
!= null) {
1762 cspec
.add_argument ((CCodeExpression
) prop
.initializer
.ccodenode
);
1764 cspec
.add_argument (new
CCodeConstant ("0"));
1766 } else if (st
.get_type_id () == "G_TYPE_UCHAR") {
1767 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uchar");
1768 cspec
.add_argument (new
CCodeConstant ("0"));
1769 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT8"));
1770 if (prop
.initializer
!= null) {
1771 cspec
.add_argument ((CCodeExpression
) prop
.initializer
.ccodenode
);
1773 cspec
.add_argument (new
CCodeConstant ("0"));
1775 }else if (st
.get_type_id () == "G_TYPE_FLOAT") {
1776 cspec
.call
= new
CCodeIdentifier ("g_param_spec_float");
1777 cspec
.add_argument (new
CCodeConstant ("-G_MAXFLOAT"));
1778 cspec
.add_argument (new
CCodeConstant ("G_MAXFLOAT"));
1779 if (prop
.initializer
!= null) {
1780 cspec
.add_argument ((CCodeExpression
) prop
.initializer
.ccodenode
);
1782 cspec
.add_argument (new
CCodeConstant ("0.0F"));
1784 } else if (st
.get_type_id () == "G_TYPE_DOUBLE") {
1785 cspec
.call
= new
CCodeIdentifier ("g_param_spec_double");
1786 cspec
.add_argument (new
CCodeConstant ("-G_MAXDOUBLE"));
1787 cspec
.add_argument (new
CCodeConstant ("G_MAXDOUBLE"));
1788 if (prop
.initializer
!= null) {
1789 cspec
.add_argument ((CCodeExpression
) prop
.initializer
.ccodenode
);
1791 cspec
.add_argument (new
CCodeConstant ("0.0"));
1793 } else if (st
.get_type_id () == "G_TYPE_GTYPE") {
1794 cspec
.call
= new
CCodeIdentifier ("g_param_spec_gtype");
1795 if (prop
.initializer
!= null) {
1796 cspec
.add_argument ((CCodeExpression
) prop
.initializer
.ccodenode
);
1798 cspec
.add_argument (new
CCodeConstant ("G_TYPE_NONE"));
1801 cspec
.call
= new
CCodeIdentifier ("g_param_spec_boxed");
1802 cspec
.add_argument (new
CCodeIdentifier (st
.get_type_id ()));
1804 } else if (prop
.property_type is ArrayType
&& ((ArrayType
)prop
.property_type
).element_type
.data_type
== string_type
.data_type
) {
1805 cspec
.call
= new
CCodeIdentifier ("g_param_spec_boxed");
1806 cspec
.add_argument (new
CCodeIdentifier ("G_TYPE_STRV"));
1808 cspec
.call
= new
CCodeIdentifier ("g_param_spec_pointer");
1811 var pflags
= "G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB";
1812 if (prop
.get_accessor
!= null && prop
.get_accessor
.access
!= SymbolAccessibility
.PRIVATE
) {
1813 pflags
= "%s%s".printf (pflags
, " | G_PARAM_READABLE");
1815 if (prop
.set_accessor
!= null && prop
.set_accessor
.access
!= SymbolAccessibility
.PRIVATE
) {
1816 pflags
= "%s%s".printf (pflags
, " | G_PARAM_WRITABLE");
1817 if (prop
.set_accessor
.construction
) {
1818 if (prop
.set_accessor
.writable
) {
1819 pflags
= "%s%s".printf (pflags
, " | G_PARAM_CONSTRUCT");
1821 pflags
= "%s%s".printf (pflags
, " | G_PARAM_CONSTRUCT_ONLY");
1825 cspec
.add_argument (new
CCodeConstant (pflags
));
1830 public override void generate_interface_declaration (Interface iface
, CCodeDeclarationSpace decl_space
) {
1831 if (decl_space
.add_symbol_declaration (iface
, iface
.get_cname ())) {
1835 foreach (DataType prerequisite
in iface
.get_prerequisites ()) {
1836 var prereq_cl
= prerequisite
.data_type as Class
;
1837 var prereq_iface
= prerequisite
.data_type as Interface
;
1838 if (prereq_cl
!= null) {
1839 generate_class_declaration (prereq_cl
, decl_space
);
1840 } else if (prereq_iface
!= null) {
1841 generate_interface_declaration (prereq_iface
, decl_space
);
1845 var type_struct
= new
CCodeStruct ("_%s".printf (iface
.get_type_cname ()));
1847 decl_space
.add_type_declaration (new
CCodeNewline ());
1848 var macro
= "(%s_get_type ())".printf (iface
.get_lower_case_cname (null));
1849 decl_space
.add_type_declaration (new
CCodeMacroReplacement (iface
.get_type_id (), macro
));
1851 macro
= "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (iface
.get_type_id (), iface
.get_cname ());
1852 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s(obj)".printf (iface
.get_upper_case_cname (null)), macro
));
1854 macro
= "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (iface
.get_type_id ());
1855 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s(obj)".printf (get_type_check_function (iface
)), macro
));
1857 macro
= "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %s))".printf (iface
.get_type_id (), iface
.get_type_cname ());
1858 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s_GET_INTERFACE(obj)".printf (iface
.get_upper_case_cname (null)), macro
));
1859 decl_space
.add_type_declaration (new
CCodeNewline ());
1861 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct _%s".printf (iface
.get_cname ()), new
CCodeVariableDeclarator (iface
.get_cname ())));
1862 decl_space
.add_type_declaration (new
CCodeTypeDefinition ("struct %s".printf (type_struct
.name
), new
CCodeVariableDeclarator (iface
.get_type_cname ())));
1864 type_struct
.add_field ("GTypeInterface", "parent_iface");
1866 foreach (Method m
in iface
.get_methods ()) {
1867 generate_virtual_method_declaration (m
, decl_space
, type_struct
);
1870 foreach (Property prop
in iface
.get_properties ()) {
1871 if (!prop
.is_abstract
&& !prop
.is_virtual
) {
1874 generate_type_declaration (prop
.property_type
, decl_space
);
1876 var t
= (ObjectTypeSymbol
) prop
.parent_symbol
;
1878 bool returns_real_struct
= prop
.property_type
.is_real_non_null_struct_type ();
1880 var this_type
= new
ObjectType (t
);
1881 var cselfparam
= new
CCodeFormalParameter ("self", this_type
.get_cname ());
1883 if (prop
.get_accessor
!= null) {
1884 var vdeclarator
= new
CCodeFunctionDeclarator ("get_%s".printf (prop
.name
));
1885 vdeclarator
.add_parameter (cselfparam
);
1886 string creturn_type
;
1887 if (returns_real_struct
) {
1888 var cvalueparam
= new
CCodeFormalParameter ("value", prop
.get_accessor
.value_type
.get_cname () + "*");
1889 vdeclarator
.add_parameter (cvalueparam
);
1890 creturn_type
= "void";
1892 creturn_type
= prop
.get_accessor
.value_type
.get_cname ();
1895 var array_type
= prop
.property_type as ArrayType
;
1896 if (array_type
!= null) {
1897 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1898 vdeclarator
.add_parameter (new
CCodeFormalParameter (get_array_length_cname ("result", dim
), "int*"));
1902 var vdecl
= new
CCodeDeclaration (creturn_type
);
1903 vdecl
.add_declarator (vdeclarator
);
1904 type_struct
.add_declaration (vdecl
);
1906 if (prop
.set_accessor
!= null) {
1907 var vdeclarator
= new
CCodeFunctionDeclarator ("set_%s".printf (prop
.name
));
1908 vdeclarator
.add_parameter (cselfparam
);
1909 if (returns_real_struct
) {
1910 var cvalueparam
= new
CCodeFormalParameter ("value", prop
.set_accessor
.value_type
.get_cname () + "*");
1911 vdeclarator
.add_parameter (cvalueparam
);
1913 var cvalueparam
= new
CCodeFormalParameter ("value", prop
.set_accessor
.value_type
.get_cname ());
1914 vdeclarator
.add_parameter (cvalueparam
);
1917 var array_type
= prop
.property_type as ArrayType
;
1918 if (array_type
!= null) {
1919 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1920 vdeclarator
.add_parameter (new
CCodeFormalParameter (get_array_length_cname ("value", dim
), "int"));
1924 var vdecl
= new
CCodeDeclaration ("void");
1925 vdecl
.add_declarator (vdeclarator
);
1926 type_struct
.add_declaration (vdecl
);
1930 decl_space
.add_type_definition (type_struct
);
1932 var type_fun
= create_interface_register_function (iface
);
1933 type_fun
.init_from_type (in_plugin
);
1934 decl_space
.add_type_member_declaration (type_fun
.get_declaration ());
1937 public override void visit_interface (Interface iface
) {
1938 push_context (new
EmitContext (iface
));
1940 if (iface
.get_cname().len () < 3) {
1942 Report
.error (iface
.source_reference
, "Interface name `%s' is too short".printf (iface
.get_cname ()));
1946 generate_interface_declaration (iface
, source_declarations
);
1947 if (!iface
.is_internal_symbol ()) {
1948 generate_interface_declaration (iface
, header_declarations
);
1950 if (!iface
.is_private_symbol ()) {
1951 generate_interface_declaration (iface
, internal_header_declarations
);
1954 iface
.accept_children (this
);
1956 add_interface_base_init_function (iface
);
1958 if (iface
.comment
!= null) {
1959 source_type_member_definition
.append (new
CCodeComment (iface
.comment
.content
));
1962 var type_fun
= create_interface_register_function (iface
);
1963 type_fun
.init_from_type (in_plugin
);
1964 source_declarations
.add_type_member_declaration (type_fun
.get_source_declaration ());
1965 source_type_member_definition
.append (type_fun
.get_definition ());
1970 public virtual TypeRegisterFunction
create_interface_register_function (Interface iface
) {
1971 return new
InterfaceRegisterFunction (iface
, context
);
1974 private void add_interface_base_init_function (Interface iface
) {
1975 var base_init
= new
CCodeFunction ("%s_base_init".printf (iface
.get_lower_case_cname (null)), "void");
1976 base_init
.add_parameter (new
CCodeFormalParameter ("iface", "%sIface *".printf (iface
.get_cname ())));
1977 base_init
.modifiers
= CCodeModifiers
.STATIC
;
1979 var init_block
= new
CCodeBlock ();
1981 /* make sure not to run the initialization code twice */
1982 base_init
.block
= new
CCodeBlock ();
1983 var decl
= new
CCodeDeclaration (bool_type
.get_cname ());
1984 decl
.modifiers
|= CCodeModifiers
.STATIC
;
1985 decl
.add_declarator (new
CCodeVariableDeclarator ("initialized", new
CCodeConstant ("FALSE")));
1986 base_init
.block
.add_statement (decl
);
1987 var cif
= new
CCodeIfStatement (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("initialized")), init_block
);
1988 base_init
.block
.add_statement (cif
);
1989 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("initialized"), new
CCodeConstant ("TRUE"))));
1991 if (iface
.is_subtype_of (gobject_type
)) {
1992 /* create properties */
1993 var props
= iface
.get_properties ();
1994 foreach (Property prop
in props
) {
1995 if (prop
.is_abstract
) {
1996 if (!is_gobject_property (prop
)) {
2000 if (prop
.comment
!= null) {
2001 init_block
.add_statement (new
CCodeComment (prop
.comment
.content
));
2004 var cinst
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_interface_install_property"));
2005 cinst
.add_argument (new
CCodeIdentifier ("iface"));
2006 cinst
.add_argument (get_param_spec (prop
));
2008 init_block
.add_statement (new
CCodeExpressionStatement (cinst
));
2013 /* create signals */
2014 foreach (Signal sig
in iface
.get_signals ()) {
2015 if (sig
.comment
!= null) {
2016 init_block
.add_statement (new
CCodeComment (sig
.comment
.content
));
2018 init_block
.add_statement (new
CCodeExpressionStatement (get_signal_creation (sig
, iface
)));
2021 // connect default implementations
2022 foreach (Method m
in iface
.get_methods ()) {
2024 var ciface
= new
CCodeIdentifier ("iface");
2025 var cname
= m
.get_real_cname ();
2026 base_init
.block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, m
.vfunc_name
), new
CCodeIdentifier (cname
))));
2030 init_block
.add_statement (register_dbus_info (iface
));
2032 source_type_member_definition
.append (base_init
);
2035 public override void visit_struct (Struct st
) {
2036 base.visit_struct (st
);
2038 if (st
.has_type_id
) {
2039 var type_fun
= new
StructRegisterFunction (st
, context
);
2040 type_fun
.init_from_type (false);
2041 source_type_member_definition
.append (type_fun
.get_definition ());
2045 public override void visit_enum (Enum en
) {
2046 base.visit_enum (en
);
2048 if (en
.has_type_id
) {
2049 var type_fun
= new
EnumRegisterFunction (en
, context
);
2050 type_fun
.init_from_type (false);
2051 source_type_member_definition
.append (type_fun
.get_definition ());
2055 public override void visit_method_call (MethodCall expr
) {
2056 var ma
= expr
.call as MemberAccess
;
2057 var mtype
= expr
.call
.value_type as MethodType
;
2058 if (mtype
== null || mtype
.method_symbol
.get_full_name () != "GLib.Enum.to_string" ||
2059 ma
== null || ma
.inner
.value_type
.get_type_id () == null) {
2060 base.visit_method_call (expr
);
2064 var ccomma
= new
CCodeCommaExpression ();
2065 var temp_var
= get_temp_variable (new
CType ("GEnumValue*"), false, expr
, false);
2066 temp_vars
.add (temp_var
);
2068 var class_ref
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_ref"));
2069 class_ref
.add_argument (new
CCodeIdentifier (ma
.inner
.value_type
.get_type_id ()));
2070 var get_value
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_enum_get_value"));
2071 get_value
.add_argument (class_ref
);
2072 get_value
.add_argument ((CCodeExpression
) get_ccodenode (((MemberAccess
) expr
.call
).inner
));
2074 ccomma
.append_expression (new
CCodeAssignment (get_variable_cexpression (temp_var
.name
), get_value
));
2075 var is_null_value
= new
CCodeBinaryExpression (CCodeBinaryOperator
.INEQUALITY
, get_variable_cexpression (temp_var
.name
), new
CCodeIdentifier ("NULL"));
2076 ccomma
.append_expression (new
CCodeConditionalExpression (is_null_value
, new CCodeMemberAccess
.pointer (get_variable_cexpression (temp_var
.name
), "value_name"), new
CCodeIdentifier ("NULL")));
2077 expr
.ccodenode
= ccomma
;
2080 public override void visit_property (Property prop
) {
2081 var cl
= current_type_symbol as Class
;
2082 var st
= current_type_symbol as Struct
;
2083 if (prop
.name
== "type" && ((cl
!= null && !cl
.is_compact
) || (st
!= null && st
.has_type_id
))) {
2084 Report
.error (prop
.source_reference
, "Property 'type' not allowed");
2087 base.visit_property (prop
);