1 /* valagobjectmodule.vala
3 * Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Jürg Billeter <j@bitron.ch>
21 * Raffaele Sandrini <raffaele@sandrini.ch>
26 public class Vala
.GObjectModule
: GTypeModule
{
27 int dynamic_property_id
;
28 int signal_wrapper_id
;
30 public GObjectModule (CCodeGenerator codegen
, CCodeModule? next
) {
34 public override void visit_class (Class cl
) {
35 var old_symbol
= current_symbol
;
36 var old_type_symbol
= current_type_symbol
;
37 var old_class
= current_class
;
38 var old_instance_struct
= instance_struct
;
39 var old_param_spec_struct
= param_spec_struct
;
40 var old_type_struct
= type_struct
;
41 var old_instance_priv_struct
= instance_priv_struct
;
42 var old_prop_enum
= prop_enum
;
43 var old_class_init_fragment
= class_init_fragment
;
44 var old_instance_init_fragment
= instance_init_fragment
;
45 var old_instance_finalize_fragment
= instance_finalize_fragment
;
47 current_type_symbol
= cl
;
50 bool is_gtypeinstance
= !cl
.is_compact
;
51 bool is_gobject
= cl
.is_subtype_of (gobject_type
);
52 bool is_fundamental
= is_gtypeinstance
&& cl
.base_class
== null;
54 if (cl
.get_cname().len () < 3) {
56 Report
.error (cl
.source_reference
, "Class name `%s' is too short".printf (cl
.get_cname ()));
61 instance_struct
= new
CCodeStruct ("_%s".printf (cl
.get_cname ()));
62 type_struct
= new
CCodeStruct ("_%sClass".printf (cl
.get_cname ()));
63 instance_priv_struct
= new
CCodeStruct ("_%sPrivate".printf (cl
.get_cname ()));
64 prop_enum
= new
CCodeEnum ();
65 prop_enum
.add_value (new
CCodeEnumValue ("%s_DUMMY_PROPERTY".printf (cl
.get_upper_case_cname (null))));
66 class_init_fragment
= new
CCodeFragment ();
67 instance_init_fragment
= new
CCodeFragment ();
68 instance_finalize_fragment
= new
CCodeFragment ();
71 CCodeFragment decl_frag
;
72 CCodeFragment def_frag
;
73 if (cl
.access
!= SymbolAccessibility
.PRIVATE
) {
74 decl_frag
= header_type_declaration
;
75 def_frag
= header_type_definition
;
77 decl_frag
= source_type_declaration
;
78 def_frag
= source_type_definition
;
81 if (is_gtypeinstance
) {
82 decl_frag
.append (new
CCodeNewline ());
83 var macro
= "(%s_get_type ())".printf (cl
.get_lower_case_cname (null));
84 decl_frag
.append (new
CCodeMacroReplacement (cl
.get_type_id (), macro
));
86 macro
= "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (cl
.get_type_id (), cl
.get_cname ());
87 decl_frag
.append (new
CCodeMacroReplacement ("%s(obj)".printf (cl
.get_upper_case_cname (null)), macro
));
89 macro
= "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (cl
.get_type_id (), cl
.get_cname ());
90 decl_frag
.append (new
CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl
.get_upper_case_cname (null)), macro
));
92 macro
= "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (cl
.get_type_id ());
93 decl_frag
.append (new
CCodeMacroReplacement ("%s(obj)".printf (get_type_check_function (cl
)), macro
));
95 macro
= "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (cl
.get_type_id ());
96 decl_frag
.append (new
CCodeMacroReplacement ("%s_CLASS(klass)".printf (get_type_check_function (cl
)), macro
));
98 macro
= "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (cl
.get_type_id (), cl
.get_cname ());
99 decl_frag
.append (new
CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (cl
.get_upper_case_cname (null)), macro
));
100 decl_frag
.append (new
CCodeNewline ());
104 if (cl
.source_reference
.file
.cycle
== null) {
105 decl_frag
.append (new
CCodeTypeDefinition ("struct %s".printf (instance_struct
.name
), new
CCodeVariableDeclarator (cl
.get_cname ())));
108 if (cl
.base_class
!= null) {
109 instance_struct
.add_field (cl
.base_class
.get_cname (), "parent_instance");
110 } else if (is_fundamental
) {
111 instance_struct
.add_field ("GTypeInstance", "parent_instance");
112 instance_struct
.add_field ("volatile int", "ref_count");
115 if (cl
.is_compact
&& cl
.base_class
== null && cl
.get_fields ().size
== 0) {
116 // add dummy member, C doesn't allow empty structs
117 instance_struct
.add_field ("int", "dummy");
120 if (is_gtypeinstance
) {
121 if (cl
.source_reference
.file
.cycle
== null) {
122 decl_frag
.append (new
CCodeTypeDefinition ("struct %s".printf (type_struct
.name
), new
CCodeVariableDeclarator ("%sClass".printf (cl
.get_cname ()))));
124 decl_frag
.append (new
CCodeTypeDefinition ("struct %s".printf (instance_priv_struct
.name
), new
CCodeVariableDeclarator ("%sPrivate".printf (cl
.get_cname ()))));
126 instance_struct
.add_field ("%sPrivate *".printf (cl
.get_cname ()), "priv");
127 if (is_fundamental
) {
128 type_struct
.add_field ("GTypeClass", "parent_class");
129 type_struct
.add_field ("void", "(*finalize) (%s *self)".printf (cl
.get_cname ()));
131 type_struct
.add_field ("%sClass".printf (cl
.base_class
.get_cname ()), "parent_class");
135 if (cl
.source_reference
.comment
!= null) {
136 def_frag
.append (new
CCodeComment (cl
.source_reference
.comment
));
138 def_frag
.append (instance_struct
);
140 if (is_gtypeinstance
) {
141 def_frag
.append (type_struct
);
142 /* only add the *Private struct if it is not empty, i.e. we actually have private data */
143 if (cl
.has_private_fields
|| cl
.get_type_parameters ().size
> 0) {
144 source_type_member_declaration
.append (instance_priv_struct
);
145 var macro
= "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl
.get_type_id (), cl
.get_cname ());
146 source_type_member_declaration
.append (new
CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl
.get_upper_case_cname (null)), macro
));
148 source_type_member_declaration
.append (prop_enum
);
151 cl
.accept_children (codegen
);
153 if (is_gtypeinstance
) {
154 if (is_fundamental
) {
155 param_spec_struct
= new
CCodeStruct ( "_%sParamSpec%s".printf(cl
.parent_symbol
.get_cprefix (), cl
.name
));
156 param_spec_struct
.add_field ("GParamSpec", "parent_instance");
157 def_frag
.append (param_spec_struct
);
159 decl_frag
.append (new
CCodeTypeDefinition ("struct %s".printf (param_spec_struct
.name
), new
CCodeVariableDeclarator ( "%sParamSpec%s".printf(cl
.parent_symbol
.get_cprefix (), cl
.name
))));
162 gvaluecollector_h_needed
= true;
164 add_type_value_table_init_function (cl
);
165 add_type_value_table_free_function (cl
);
166 add_type_value_table_copy_function (cl
);
167 add_type_value_table_peek_pointer_function (cl
);
168 add_type_value_table_collect_value_function (cl
);
169 add_type_value_table_lcopy_value_function (cl
);
170 add_g_param_spec_type_function (cl
);
171 add_g_value_get_function (cl
);
172 add_g_value_set_function (cl
);
174 var ref_count
= new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "ref_count"), new
CCodeConstant ("1"));
175 instance_init_fragment
.append (new
CCodeExpressionStatement (ref_count
));
176 } else if (is_gobject
) {
177 if (class_has_readable_properties (cl
) || cl
.get_type_parameters ().size
> 0) {
178 add_get_property_function (cl
);
180 if (class_has_writable_properties (cl
) || cl
.get_type_parameters ().size
> 0) {
181 add_set_property_function (cl
);
184 add_class_init_function (cl
);
186 foreach (DataType base_type
in cl
.get_base_types ()) {
187 if (base_type
.data_type is Interface
) {
188 add_interface_init_function (cl
, (Interface
) base_type
.data_type
);
192 add_instance_init_function (cl
);
194 if (!cl
.is_compact
&& (cl
.get_fields ().size
> 0 || cl
.destructor
!= null || cl
.is_fundamental ())) {
195 add_finalize_function (cl
);
198 var type_fun
= new
ClassRegisterFunction (cl
, context
);
199 type_fun
.init_from_type (in_plugin
);
200 if (cl
.access
!= SymbolAccessibility
.PRIVATE
) {
201 header_type_member_declaration
.append (type_fun
.get_declaration ());
203 source_type_member_declaration
.append (type_fun
.get_declaration ());
205 source_type_member_definition
.append (type_fun
.get_definition ());
208 // FIXME resolve potential dependency issues, i.e. base types have to be registered before derived types
209 var register_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_register_type".printf (cl
.get_lower_case_cname (null))));
210 register_call
.add_argument (new
CCodeIdentifier (module_init_param_name
));
211 module_init_fragment
.append (new
CCodeExpressionStatement (register_call
));
214 if (is_fundamental
) {
215 var ref_fun
= new
CCodeFunction (cl
.get_lower_case_cprefix () + "ref", "gpointer");
216 var unref_fun
= new
CCodeFunction (cl
.get_lower_case_cprefix () + "unref", "void");
217 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
218 ref_fun
.modifiers
= CCodeModifiers
.STATIC
;
219 unref_fun
.modifiers
= CCodeModifiers
.STATIC
;
222 ref_fun
.add_parameter (new
CCodeFormalParameter ("instance", "gpointer"));
223 unref_fun
.add_parameter (new
CCodeFormalParameter ("instance", "gpointer"));
225 if (cl
.access
!= SymbolAccessibility
.PRIVATE
) {
226 header_type_member_declaration
.append (ref_fun
.copy ());
227 header_type_member_declaration
.append (unref_fun
.copy ());
229 source_type_member_declaration
.append (ref_fun
.copy ());
230 source_type_member_declaration
.append (unref_fun
.copy ());
233 var ref_block
= new
CCodeBlock ();
234 var unref_block
= new
CCodeBlock ();
236 var cdecl
= new
CCodeDeclaration (cl
.get_cname () + "*");
237 cdecl
.add_declarator (new CCodeVariableDeclarator
.with_initializer ("self", new
CCodeIdentifier ("instance")));
238 ref_block
.add_statement (cdecl
);
239 unref_block
.add_statement (cdecl
);
241 var ref_count
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "ref_count");
243 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_atomic_int_inc"));
244 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, ref_count
));
245 ref_block
.add_statement (new
CCodeExpressionStatement (ccall
));
247 ref_block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("instance")));
249 var destroy_block
= new
CCodeBlock ();
250 var get_class
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_CLASS".printf (cl
.get_upper_case_cname (null))));
251 get_class
.add_argument (new
CCodeIdentifier ("self"));
254 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_CLASS".printf (cl
.get_upper_case_cname (null))));
255 ccast
.add_argument (new
CCodeIdentifier ("self"));
256 ccall
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (ccast
, "finalize"));
257 ccall
.add_argument (new
CCodeIdentifier ("self"));
258 destroy_block
.add_statement (new
CCodeExpressionStatement (ccall
));
260 // free type instance
261 var free
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_free_instance"));
262 free
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "GTypeInstance *"));
263 destroy_block
.add_statement (new
CCodeExpressionStatement (free
));
265 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_atomic_int_dec_and_test"));
266 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, ref_count
));
267 unref_block
.add_statement (new
CCodeIfStatement (ccall
, destroy_block
));
269 ref_fun
.block
= ref_block
;
270 unref_fun
.block
= unref_block
;
272 source_type_member_definition
.append (ref_fun
);
273 source_type_member_definition
.append (unref_fun
);
276 add_instance_init_function (cl
);
278 var function
= new
CCodeFunction (cl
.get_lower_case_cprefix () + "free", "void");
279 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
280 function
.modifiers
= CCodeModifiers
.STATIC
;
283 function
.add_parameter (new
CCodeFormalParameter ("self", cl
.get_cname () + "*"));
285 if (cl
.access
!= SymbolAccessibility
.PRIVATE
) {
286 header_type_member_declaration
.append (function
.copy ());
288 source_type_member_declaration
.append (function
.copy ());
291 var cblock
= new
CCodeBlock ();
293 cblock
.add_statement (instance_finalize_fragment
);
295 if (cl
.destructor
!= null) {
296 cblock
.add_statement (cl
.destructor
.ccodenode
);
299 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_slice_free"));
300 ccall
.add_argument (new
CCodeIdentifier (cl
.get_cname ()));
301 ccall
.add_argument (new
CCodeIdentifier ("self"));
302 cblock
.add_statement (new
CCodeExpressionStatement (ccall
));
304 function
.block
= cblock
;
306 source_type_member_definition
.append (function
);
309 current_symbol
= old_symbol
;
310 current_type_symbol
= old_type_symbol
;
311 current_class
= old_class
;
312 instance_struct
= old_instance_struct
;
313 param_spec_struct
= old_param_spec_struct
;
314 type_struct
= old_type_struct
;
315 instance_priv_struct
= old_instance_priv_struct
;
316 prop_enum
= old_prop_enum
;
317 class_init_fragment
= old_class_init_fragment
;
318 instance_init_fragment
= old_instance_init_fragment
;
319 instance_finalize_fragment
= old_instance_finalize_fragment
;
322 private void add_type_value_table_init_function (Class cl
) {
323 var function
= new
CCodeFunction ("%s_init".printf (cl
.get_lower_case_cname ("value_")), "void");
324 function
.add_parameter (new
CCodeFormalParameter ("value", "GValue*"));
325 function
.modifiers
= CCodeModifiers
.STATIC
;
327 var init_block
= new
CCodeBlock ();
328 function
.block
= init_block
;
330 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
)));
331 source_type_member_definition
.append (function
);
334 private void add_type_value_table_free_function (Class cl
) {
335 var function
= new
CCodeFunction ("%s_free_value".printf (cl
.get_lower_case_cname ("value_")), "void");
336 function
.add_parameter (new
CCodeFormalParameter ("value", "GValue*"));
337 function
.modifiers
= CCodeModifiers
.STATIC
;
339 var init_block
= new
CCodeBlock ();
340 function
.block
= init_block
;
342 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
343 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_lower_case_cprefix () + "unref"));
344 ccall
.add_argument ( vpointer
);
346 var ifbody
= new
CCodeBlock ();
347 ifbody
.add_statement ( new
CCodeExpressionStatement(ccall
) );
349 init_block
.add_statement(new
CCodeIfStatement (vpointer
, ifbody
));
350 source_type_member_definition
.append (function
);
353 private void add_type_value_table_copy_function (Class cl
) {
354 var function
= new
CCodeFunction ("%s_copy_value".printf (cl
.get_lower_case_cname ("value_")), "void");
355 function
.add_parameter (new
CCodeFormalParameter ("src_value", "const GValue*"));
356 function
.add_parameter (new
CCodeFormalParameter ("dest_value", "GValue*"));
357 function
.modifiers
= CCodeModifiers
.STATIC
;
359 var init_block
= new
CCodeBlock ();
360 function
.block
= init_block
;
362 var dest_vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("dest_value"), "data[0]"),"v_pointer");
363 var src_vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("src_value"), "data[0]"),"v_pointer");
365 var ref_ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_lower_case_cprefix () + "ref"));
366 ref_ccall
.add_argument ( src_vpointer
);
368 var true_stmt
= new
CCodeBlock ();
369 true_stmt
.add_statement(new
CCodeExpressionStatement(new
CCodeAssignment (dest_vpointer
, ref_ccall
, CCodeAssignmentOperator
.SIMPLE
)));
371 var false_stmt
= new
CCodeBlock ();
372 false_stmt
.add_statement (new
CCodeExpressionStatement( new
CCodeAssignment (dest_vpointer
, new
CCodeConstant ("NULL"), CCodeAssignmentOperator
.SIMPLE
)));
374 var if_statement
= new
CCodeIfStatement (src_vpointer
, true_stmt
, false_stmt
);
375 init_block
.add_statement (if_statement
);
377 source_type_member_definition
.append (function
);
380 private void add_type_value_table_peek_pointer_function (Class cl
) {
381 var function
= new
CCodeFunction ("%s_peek_pointer".printf (cl
.get_lower_case_cname ("value_")), "gpointer");
382 function
.add_parameter (new
CCodeFormalParameter ("value", "const GValue*"));
383 function
.modifiers
= CCodeModifiers
.STATIC
;
385 var init_block
= new
CCodeBlock ();
386 function
.block
= init_block
;
388 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
389 var ret
= new
CCodeReturnStatement ( vpointer
);
390 init_block
.add_statement (ret
);
392 source_type_member_definition
.append (function
);
395 private void add_type_value_table_lcopy_value_function ( Class cl
) {
396 var function
= new
CCodeFunction ("%s_lcopy_value".printf (cl
.get_lower_case_cname ("value_")), "gchar*");
397 function
.add_parameter (new
CCodeFormalParameter ("value", "const GValue*"));
398 function
.add_parameter (new
CCodeFormalParameter ("n_collect_values", "guint"));
399 function
.add_parameter (new
CCodeFormalParameter ("collect_values", "GTypeCValue*"));
400 function
.add_parameter (new
CCodeFormalParameter ("collect_flags", "guint"));
401 function
.modifiers
= CCodeModifiers
.STATIC
;
403 var vpointer
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"), "v_pointer");
404 var object_p_ptr
= new
CCodeIdentifier ("*object_p");
405 var null_
= new
CCodeConstant ("NULL");
407 var init_block
= new
CCodeBlock ();
409 var ctypedecl
= new
CCodeDeclaration (cl
.get_cname () + "**");
410 ctypedecl
.add_declarator (new CCodeVariableDeclarator
.with_initializer ("object_p", new
CCodeMemberAccess (new
CCodeIdentifier ("collect_values[0]"),"v_pointer")));
411 init_block
.add_statement (ctypedecl
);
413 var value_type_name_fct
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE_NAME"));
414 value_type_name_fct
.add_argument (new
CCodeConstant ("value"));
416 var assert_condition
= new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("object_p"));
417 function
.block
= init_block
;
418 var assert_true
= new
CCodeBlock ();
419 var assert_printf
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strdup_printf"));
420 assert_printf
.add_argument (new
CCodeConstant ("\"value location for `%s' passed as NULL\""));
421 assert_printf
.add_argument (value_type_name_fct
);
422 assert_true
.add_statement (new
CCodeReturnStatement (assert_printf
));
423 var if_assert
= new
CCodeIfStatement (assert_condition
, assert_true
);
424 init_block
.add_statement (if_assert
);
426 var main_else_true
= new
CCodeBlock ();
427 var main_else_if_true
= new
CCodeBlock ();
428 var main_else_if_condition
= new
CCodeBinaryExpression (CCodeBinaryOperator
.AND
, new
CCodeIdentifier ("collect_flags"), new
CCodeIdentifier ("G_VALUE_NOCOPY_CONTENTS"));
429 var main_else_if
= new
CCodeIfStatement (main_else_if_condition
, main_else_if_true
, main_else_true
);
431 var main_true
= new
CCodeBlock ();
432 var main_condition
= new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, vpointer
);
433 var if_main
= new
CCodeIfStatement (main_condition
, main_true
, main_else_if
);
434 init_block
.add_statement (if_main
);
436 var ref_fct
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_ref_function()));
437 ref_fct
.add_argument (vpointer
);
439 main_true
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (object_p_ptr
, null_
, CCodeAssignmentOperator
.SIMPLE
)));
440 main_else_if_true
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (object_p_ptr
, vpointer
, CCodeAssignmentOperator
.SIMPLE
)));
441 main_else_true
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (object_p_ptr
, ref_fct
, CCodeAssignmentOperator
.SIMPLE
)));
443 init_block
.add_statement (new
CCodeReturnStatement (null_
));
444 source_type_member_definition
.append (function
);
447 private void add_type_value_table_collect_value_function (Class cl
) {
448 var function
= new
CCodeFunction ("%s_collect_value".printf (cl
.get_lower_case_cname ("value_")), "gchar*");
449 function
.add_parameter (new
CCodeFormalParameter ("value", "GValue*"));
450 function
.add_parameter (new
CCodeFormalParameter ("n_collect_values", "guint"));
451 function
.add_parameter (new
CCodeFormalParameter ("collect_values", "GTypeCValue*"));
452 function
.add_parameter (new
CCodeFormalParameter ("collect_flags", "guint"));
453 function
.modifiers
= CCodeModifiers
.STATIC
;
455 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
457 var init_block
= new
CCodeBlock ();
458 function
.block
= init_block
;
460 var collect_vpointer
= new
CCodeMemberAccess (new
CCodeIdentifier ("collect_values[0]"), "v_pointer");
462 var true_stmt
= new
CCodeBlock ();
463 var false_stmt
= new
CCodeBlock ();
464 var if_statement
= new
CCodeIfStatement (collect_vpointer
, true_stmt
, false_stmt
);
465 init_block
.add_statement (if_statement
);
467 var obj_identifier
= new
CCodeIdentifier ("object");
469 var ctypedecl
= new
CCodeDeclaration (cl
.get_cname () + "*");
470 ctypedecl
.add_declarator (new CCodeVariableDeclarator
.with_initializer ("object", collect_vpointer
));
471 true_stmt
.add_statement (ctypedecl
);
473 var l_expression
= new
CCodeMemberAccess (new CCodeMemberAccess
.pointer (obj_identifier
, "parent_instance"), "g_class");
474 var sub_condition
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, l_expression
, new
CCodeConstant ("NULL"));
475 var sub_true_stmt
= new
CCodeBlock ();
476 var sub_false_stmt
= new
CCodeBlock ();
478 var reg_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_type_compatible"));
479 var type_check
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
480 type_check
.add_argument (new
CCodeIdentifier ("object"));
481 reg_call
.add_argument (type_check
);
483 var type_name_fct
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_name"));
484 type_name_fct
.add_argument (type_check
);
486 var stored_type
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
487 stored_type
.add_argument (new
CCodeIdentifier ("value"));
488 reg_call
.add_argument (stored_type
);
490 var value_type_name_fct
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE_NAME"));
491 value_type_name_fct
.add_argument (new
CCodeConstant ("value"));
493 var true_return
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strconcat"));
494 true_return
.add_argument (new
CCodeConstant ("\"invalid unclassed object pointer for value type `\""));
495 true_return
.add_argument (value_type_name_fct
);
496 true_return
.add_argument (new
CCodeConstant ("\"'\""));
497 true_return
.add_argument (new
CCodeConstant ("NULL"));
498 sub_true_stmt
.add_statement (new
CCodeReturnStatement (true_return
));
500 var false_return
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strconcat"));
501 false_return
.add_argument (new
CCodeConstant ("\"invalid object type `\""));
502 false_return
.add_argument (type_name_fct
);
503 false_return
.add_argument (new
CCodeConstant ("\"' for value type `\""));
504 false_return
.add_argument (value_type_name_fct
);
505 false_return
.add_argument (new
CCodeConstant ("\"'\""));
506 false_return
.add_argument (new
CCodeConstant ("NULL"));
507 sub_false_stmt
.add_statement (new
CCodeReturnStatement (false_return
));
509 var sub_else_if_statement
= new
CCodeIfStatement (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, reg_call
), sub_false_stmt
);
510 sub_else_if_statement
.else_if
= true;
511 var sub_if_statement
= new
CCodeIfStatement (sub_condition
, sub_true_stmt
, sub_else_if_statement
);
512 true_stmt
.add_statement (sub_if_statement
);
514 var ref_call
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_ref_function ()));
515 ref_call
.add_argument (new
CCodeIdentifier ("object"));
517 var true_assignment
= new
CCodeExpressionStatement (new
CCodeAssignment (vpointer
, ref_call
, CCodeAssignmentOperator
.SIMPLE
));
518 true_stmt
.add_statement (true_assignment
);
520 var else_assigment
= new
CCodeExpressionStatement (new
CCodeAssignment (vpointer
, new
CCodeConstant ("NULL"), CCodeAssignmentOperator
.SIMPLE
));
521 false_stmt
.add_statement (else_assigment
);
523 init_block
.add_statement (new
CCodeReturnStatement (new
CCodeConstant ("NULL")));
524 source_type_member_definition
.append (function
);
527 private void add_g_param_spec_type_function (Class cl
) {
528 var function_name
= cl
.get_lower_case_cname ("param_spec_");
530 var function
= new
CCodeFunction (function_name
, "GParamSpec*");
531 function
.add_parameter (new
CCodeFormalParameter ("name", "const gchar*"));
532 function
.add_parameter (new
CCodeFormalParameter ("nick", "const gchar*"));
533 function
.add_parameter (new
CCodeFormalParameter ("blurb", "const gchar*"));
534 function
.add_parameter (new
CCodeFormalParameter ("object_type", "GType"));
535 function
.add_parameter (new
CCodeFormalParameter ("flags", "GParamFlags"));
537 cl
.set_param_spec_function ( function_name
);
539 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
540 function
.modifiers
= CCodeModifiers
.STATIC
;
541 source_type_member_declaration
.append (function
.copy ());
543 header_type_member_declaration
.append (function
.copy ());
546 var init_block
= new
CCodeBlock ();
547 function
.block
= init_block
;
549 var ctypedecl
= new
CCodeDeclaration ("%sParamSpec%s*".printf (cl
.parent_symbol
.get_cprefix (), cl
.name
));
550 ctypedecl
.add_declarator ( new
CCodeVariableDeclarator ("spec"));
551 init_block
.add_statement (ctypedecl
);
553 var subccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_is_a"));
554 subccall
.add_argument (new
CCodeIdentifier ("object_type"));
555 subccall
.add_argument (new
CCodeIdentifier ( cl
.get_type_id() ));
557 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_val_if_fail"));
558 ccall
.add_argument (subccall
);
559 ccall
.add_argument (new
CCodeIdentifier ("NULL"));
560 init_block
.add_statement (new
CCodeExpressionStatement (ccall
));
562 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_param_spec_internal"));
563 ccall
.add_argument (new
CCodeIdentifier ( "G_TYPE_PARAM_OBJECT" ));
564 ccall
.add_argument (new
CCodeIdentifier ("name"));
565 ccall
.add_argument (new
CCodeIdentifier ("nick"));
566 ccall
.add_argument (new
CCodeIdentifier ("blurb"));
567 ccall
.add_argument (new
CCodeIdentifier ("flags"));
569 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("spec"), ccall
, CCodeAssignmentOperator
.SIMPLE
)));
571 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_PARAM_SPEC"));
572 ccall
.add_argument (new
CCodeIdentifier ("spec"));
574 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccall
, "value_type"), new
CCodeIdentifier ("object_type"), CCodeAssignmentOperator
.SIMPLE
)));
575 init_block
.add_statement (new
CCodeReturnStatement (ccall
));
576 source_type_member_definition
.append (function
);
579 private void add_g_value_set_function (Class cl
) {
580 var function
= new
CCodeFunction (cl
.get_set_value_function (), "void");
581 function
.add_parameter (new
CCodeFormalParameter ("value", "GValue*"));
582 function
.add_parameter (new
CCodeFormalParameter ("v_object", "gpointer"));
584 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
585 function
.modifiers
= CCodeModifiers
.STATIC
;
586 source_type_member_declaration
.append (function
.copy ());
588 header_type_member_declaration
.append (function
.copy ());
591 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
593 var init_block
= new
CCodeBlock ();
594 function
.block
= init_block
;
596 var ctypedecl
= new
CCodeDeclaration (cl
.get_cname()+"*");
597 ctypedecl
.add_declarator ( new
CCodeVariableDeclarator ("old"));
598 init_block
.add_statement (ctypedecl
);
600 var ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
601 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "value" ));
602 ccall_typecheck
.add_argument (new
CCodeIdentifier ( cl
.get_type_id() ));
604 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
605 ccall
.add_argument (ccall_typecheck
);
606 init_block
.add_statement (new
CCodeExpressionStatement (ccall
));
608 init_block
.add_statement(new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeConstant ("old"), vpointer
, CCodeAssignmentOperator
.SIMPLE
)));
610 var true_stmt
= new
CCodeBlock ();
611 var false_stmt
= new
CCodeBlock ();
612 var if_statement
= new
CCodeIfStatement (new
CCodeIdentifier ("v_object"), true_stmt
, false_stmt
);
613 init_block
.add_statement (if_statement
);
616 ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
617 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "v_object" ));
618 ccall_typecheck
.add_argument (new
CCodeIdentifier ( cl
.get_type_id() ));
620 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
621 ccall
.add_argument (ccall_typecheck
);
622 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
624 var ccall_typefrominstance
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
625 ccall_typefrominstance
.add_argument (new
CCodeIdentifier ( "v_object" ));
627 var ccall_gvaluetype
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_VALUE_TYPE"));
628 ccall_gvaluetype
.add_argument (new
CCodeIdentifier ( "value" ));
630 var ccall_typecompatible
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_type_compatible"));
631 ccall_typecompatible
.add_argument (ccall_typefrominstance
);
632 ccall_typecompatible
.add_argument (ccall_gvaluetype
);
634 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
635 ccall
.add_argument (ccall_typecompatible
);
636 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
638 true_stmt
.add_statement(new
CCodeExpressionStatement (new
CCodeAssignment (vpointer
, new
CCodeConstant ("v_object"), CCodeAssignmentOperator
.SIMPLE
)));
640 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_ref_function ()));
641 ccall
.add_argument (vpointer
);
642 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
644 false_stmt
.add_statement(new
CCodeExpressionStatement (new
CCodeAssignment (vpointer
, new
CCodeConstant ("NULL"), CCodeAssignmentOperator
.SIMPLE
)));
646 true_stmt
= new
CCodeBlock ();
647 if_statement
= new
CCodeIfStatement (new
CCodeIdentifier ("old"), true_stmt
);
648 init_block
.add_statement (if_statement
);
650 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_unref_function ()));
651 ccall
.add_argument (new
CCodeIdentifier ("old"));
652 true_stmt
.add_statement (new
CCodeExpressionStatement (ccall
));
653 source_type_member_definition
.append (function
);
656 private void add_g_value_get_function (Class cl
) {
657 var function
= new
CCodeFunction (cl
.get_get_value_function (), "gpointer");
658 function
.add_parameter (new
CCodeFormalParameter ("value", "const GValue*"));
660 if (cl
.access
== SymbolAccessibility
.PRIVATE
) {
661 function
.modifiers
= CCodeModifiers
.STATIC
;
662 source_type_member_declaration
.append (function
.copy ());
664 header_type_member_declaration
.append (function
.copy ());
667 var vpointer
= new
CCodeMemberAccess(new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("value"), "data[0]"),"v_pointer");
669 var init_block
= new
CCodeBlock ();
670 function
.block
= init_block
;
672 var ccall_typecheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
673 ccall_typecheck
.add_argument (new
CCodeIdentifier ( "value" ));
674 ccall_typecheck
.add_argument (new
CCodeIdentifier ( cl
.get_type_id() ));
676 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_val_if_fail"));
677 ccall
.add_argument (ccall_typecheck
);
678 ccall
.add_argument (new
CCodeIdentifier ( "NULL" ));
679 init_block
.add_statement (new
CCodeExpressionStatement (ccall
));
681 init_block
.add_statement (new
CCodeReturnStatement ( vpointer
));
682 source_type_member_definition
.append (function
);
685 private void add_class_init_function (Class cl
) {
686 var class_init
= new
CCodeFunction ("%s_class_init".printf (cl
.get_lower_case_cname (null)), "void");
687 class_init
.add_parameter (new
CCodeFormalParameter ("klass", "%sClass *".printf (cl
.get_cname ())));
688 class_init
.modifiers
= CCodeModifiers
.STATIC
;
690 var init_block
= new
CCodeBlock ();
691 class_init
.block
= init_block
;
693 CCodeFunctionCall ccall
;
695 /* save pointer to parent class */
696 var parent_decl
= new
CCodeDeclaration ("gpointer");
697 var parent_var_decl
= new
CCodeVariableDeclarator ("%s_parent_class".printf (cl
.get_lower_case_cname (null)));
698 parent_var_decl
.initializer
= new
CCodeConstant ("NULL");
699 parent_decl
.add_declarator (parent_var_decl
);
700 parent_decl
.modifiers
= CCodeModifiers
.STATIC
;
701 source_type_member_declaration
.append (parent_decl
);
702 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_peek_parent"));
703 ccall
.add_argument (new
CCodeIdentifier ("klass"));
704 var parent_assignment
= new
CCodeAssignment (new
CCodeIdentifier ("%s_parent_class".printf (cl
.get_lower_case_cname (null))), ccall
);
705 init_block
.add_statement (new
CCodeExpressionStatement (parent_assignment
));
708 if (!cl
.is_compact
&& !cl
.is_subtype_of (gobject_type
) && (cl
.get_fields ().size
> 0 || cl
.destructor
!= null || cl
.is_fundamental ())) {
709 // set finalize function
710 var fundamental_class
= cl
;
711 while (fundamental_class
.base_class
!= null) {
712 fundamental_class
= fundamental_class
.base_class
;
715 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (fundamental_class
.get_upper_case_cname (null))));
716 ccall
.add_argument (new
CCodeIdentifier ("klass"));
717 var finalize_assignment
= new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccall
, "finalize"), new
CCodeIdentifier (cl
.get_lower_case_cprefix () + "finalize"));
718 init_block
.add_statement (new
CCodeExpressionStatement (finalize_assignment
));
721 /* add struct for private fields */
722 if (cl
.has_private_fields
|| cl
.get_type_parameters ().size
> 0) {
723 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_add_private"));
724 ccall
.add_argument (new
CCodeIdentifier ("klass"));
725 ccall
.add_argument (new
CCodeConstant ("sizeof (%sPrivate)".printf (cl
.get_cname ())));
726 init_block
.add_statement (new
CCodeExpressionStatement (ccall
));
729 if (cl
.is_subtype_of (gobject_type
)) {
730 /* set property handlers */
731 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT_CLASS"));
732 ccall
.add_argument (new
CCodeIdentifier ("klass"));
733 if (class_has_readable_properties (cl
) || cl
.get_type_parameters ().size
> 0) {
734 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccall
, "get_property"), new
CCodeIdentifier ("%s_get_property".printf (cl
.get_lower_case_cname (null))))));
736 if (class_has_writable_properties (cl
) || cl
.get_type_parameters ().size
> 0) {
737 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccall
, "set_property"), new
CCodeIdentifier ("%s_set_property".printf (cl
.get_lower_case_cname (null))))));
740 /* set constructor */
741 if (cl
.constructor
!= null) {
742 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT_CLASS"));
743 ccast
.add_argument (new
CCodeIdentifier ("klass"));
744 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, "constructor"), new
CCodeIdentifier ("%s_constructor".printf (cl
.get_lower_case_cname (null))))));
747 /* set finalize function */
748 if (cl
.get_fields ().size
> 0 || cl
.destructor
!= null) {
749 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT_CLASS"));
750 ccast
.add_argument (new
CCodeIdentifier ("klass"));
751 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, "finalize"), new
CCodeIdentifier ("%s_finalize".printf (cl
.get_lower_case_cname (null))))));
755 /* connect overridden methods */
756 foreach (Method m
in cl
.get_methods ()) {
757 if (m
.base_method
== null) {
760 var base_type
= m
.base_method
.parent_symbol
;
762 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (((Class
) base_type
).get_upper_case_cname (null))));
763 ccast
.add_argument (new
CCodeIdentifier ("klass"));
764 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, m
.base_method
.vfunc_name
), new
CCodeIdentifier (m
.get_real_cname ()))));
767 /* connect overridden properties */
768 foreach (Property prop
in cl
.get_properties ()) {
769 if (prop
.base_property
== null) {
772 var base_type
= prop
.base_property
.parent_symbol
;
774 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (((Class
) base_type
).get_upper_case_cname (null))));
775 ccast
.add_argument (new
CCodeIdentifier ("klass"));
777 if (prop
.get_accessor
!= null) {
778 string cname
= "%s_real_get_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
779 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, "get_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
))));
781 if (prop
.set_accessor
!= null) {
782 string cname
= "%s_real_set_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
783 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ccast
, "set_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
))));
787 /* initialize class fields */
788 var fields
= cl
.get_fields ();
789 foreach (Field field
in fields
) {
790 if (field
.binding
!= MemberBinding
.CLASS
|| field
.initializer
== null) {
793 CCodeExpression left
= new
CCodeMemberAccess (new
CCodeIdentifier ("klass"),
794 field
.get_cname (), true);
795 CCodeExpression right
= (CCodeExpression
)field
.initializer
.ccodenode
;
796 CCodeAssignment assign
= new
CCodeAssignment (left
, right
);
797 init_block
.add_statement (new
CCodeExpressionStatement (assign
));
800 if (cl
.is_subtype_of (gobject_type
)) {
801 /* create type, dup_func, and destroy_func properties for generic types */
802 foreach (TypeParameter type_param
in cl
.get_type_parameters ()) {
803 string func_name
, enum_value
;
804 CCodeConstant func_name_constant
;
805 CCodeFunctionCall cinst
, cspec
;
807 func_name
= "%s_type".printf (type_param
.name
.down ());
808 func_name_constant
= new
CCodeConstant ("\"%s-type\"".printf (type_param
.name
.down ()));
809 enum_value
= "%s_%s".printf (cl
.get_lower_case_cname (null), func_name
).up ();
810 cinst
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_class_install_property"));
811 cinst
.add_argument (ccall
);
812 cinst
.add_argument (new
CCodeConstant (enum_value
));
813 cspec
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_param_spec_gtype"));
814 cspec
.add_argument (func_name_constant
);
815 cspec
.add_argument (new
CCodeConstant ("\"type\""));
816 cspec
.add_argument (new
CCodeConstant ("\"type\""));
817 cspec
.add_argument (new
CCodeIdentifier ("G_TYPE_NONE"));
818 cspec
.add_argument (new
CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY"));
819 cinst
.add_argument (cspec
);
820 init_block
.add_statement (new
CCodeExpressionStatement (cinst
));
821 prop_enum
.add_value (new
CCodeEnumValue (enum_value
));
823 instance_priv_struct
.add_field ("GType", func_name
);
826 func_name
= "%s_dup_func".printf (type_param
.name
.down ());
827 func_name_constant
= new
CCodeConstant ("\"%s-dup-func\"".printf (type_param
.name
.down ()));
828 enum_value
= "%s_%s".printf (cl
.get_lower_case_cname (null), func_name
).up ();
829 cinst
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_class_install_property"));
830 cinst
.add_argument (ccall
);
831 cinst
.add_argument (new
CCodeConstant (enum_value
));
832 cspec
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_param_spec_pointer"));
833 cspec
.add_argument (func_name_constant
);
834 cspec
.add_argument (new
CCodeConstant ("\"dup func\""));
835 cspec
.add_argument (new
CCodeConstant ("\"dup func\""));
836 cspec
.add_argument (new
CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY"));
837 cinst
.add_argument (cspec
);
838 init_block
.add_statement (new
CCodeExpressionStatement (cinst
));
839 prop_enum
.add_value (new
CCodeEnumValue (enum_value
));
841 instance_priv_struct
.add_field ("GBoxedCopyFunc", func_name
);
844 func_name
= "%s_destroy_func".printf (type_param
.name
.down ());
845 func_name_constant
= new
CCodeConstant ("\"%s-destroy-func\"".printf (type_param
.name
.down ()));
846 enum_value
= "%s_%s".printf (cl
.get_lower_case_cname (null), func_name
).up ();
847 cinst
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_class_install_property"));
848 cinst
.add_argument (ccall
);
849 cinst
.add_argument (new
CCodeConstant (enum_value
));
850 cspec
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_param_spec_pointer"));
851 cspec
.add_argument (func_name_constant
);
852 cspec
.add_argument (new
CCodeConstant ("\"destroy func\""));
853 cspec
.add_argument (new
CCodeConstant ("\"destroy func\""));
854 cspec
.add_argument (new
CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY"));
855 cinst
.add_argument (cspec
);
856 init_block
.add_statement (new
CCodeExpressionStatement (cinst
));
857 prop_enum
.add_value (new
CCodeEnumValue (enum_value
));
859 instance_priv_struct
.add_field ("GDestroyNotify", func_name
);
862 /* create properties */
863 var props
= cl
.get_properties ();
864 foreach (Property prop
in props
) {
865 // FIXME: omit real struct types for now since they cannot be expressed as gobject property yet
866 if (prop
.property_type
.is_real_struct_type ()) {
869 if (prop
.access
== SymbolAccessibility
.PRIVATE
) {
870 // don't register private properties
874 if (prop
.overrides
|| prop
.base_interface_property
!= null) {
875 var cinst
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_class_override_property"));
876 cinst
.add_argument (ccall
);
877 cinst
.add_argument (new
CCodeConstant (prop
.get_upper_case_cname ()));
878 cinst
.add_argument (prop
.get_canonical_cconstant ());
880 init_block
.add_statement (new
CCodeExpressionStatement (cinst
));
882 var cinst
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_class_install_property"));
883 cinst
.add_argument (ccall
);
884 cinst
.add_argument (new
CCodeConstant (prop
.get_upper_case_cname ()));
885 cinst
.add_argument (head
.get_param_spec (prop
));
887 init_block
.add_statement (new
CCodeExpressionStatement (cinst
));
890 } else if (!cl
.is_compact
) {
891 /* create type, dup_func, and destroy_func fields for generic types */
892 foreach (TypeParameter type_param
in cl
.get_type_parameters ()) {
895 func_name
= "%s_type".printf (type_param
.name
.down ());
896 instance_priv_struct
.add_field ("GType", func_name
);
898 func_name
= "%s_dup_func".printf (type_param
.name
.down ());
899 instance_priv_struct
.add_field ("GBoxedCopyFunc", func_name
);
901 func_name
= "%s_destroy_func".printf (type_param
.name
.down ());
902 instance_priv_struct
.add_field ("GDestroyNotify", func_name
);
906 if (!cl
.is_compact
) {
908 foreach (Signal sig
in cl
.get_signals ()) {
909 init_block
.add_statement (new
CCodeExpressionStatement (head
.get_signal_creation (sig
, cl
)));
913 init_block
.add_statement (head
.register_dbus_info (cl
));
914 init_block
.add_statement (class_init_fragment
);
916 source_type_member_definition
.append (class_init
);
919 private void add_interface_init_function (Class cl
, Interface iface
) {
920 var iface_init
= new
CCodeFunction ("%s_%s_interface_init".printf (cl
.get_lower_case_cname (null), iface
.get_lower_case_cname (null)), "void");
921 iface_init
.add_parameter (new
CCodeFormalParameter ("iface", "%s *".printf (iface
.get_type_cname ())));
922 iface_init
.modifiers
= CCodeModifiers
.STATIC
;
924 var init_block
= new
CCodeBlock ();
925 iface_init
.block
= init_block
;
927 CCodeFunctionCall ccall
;
929 /* save pointer to parent vtable */
930 string parent_iface_var
= "%s_%s_parent_iface".printf (cl
.get_lower_case_cname (null), iface
.get_lower_case_cname (null));
931 var parent_decl
= new
CCodeDeclaration (iface
.get_type_cname () + "*");
932 var parent_var_decl
= new
CCodeVariableDeclarator (parent_iface_var
);
933 parent_var_decl
.initializer
= new
CCodeConstant ("NULL");
934 parent_decl
.add_declarator (parent_var_decl
);
935 parent_decl
.modifiers
= CCodeModifiers
.STATIC
;
936 source_type_member_declaration
.append (parent_decl
);
937 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_interface_peek_parent"));
938 ccall
.add_argument (new
CCodeIdentifier ("iface"));
939 var parent_assignment
= new
CCodeAssignment (new
CCodeIdentifier (parent_iface_var
), ccall
);
940 init_block
.add_statement (new
CCodeExpressionStatement (parent_assignment
));
942 foreach (Method m
in cl
.get_methods ()) {
943 if (m
.base_interface_method
== null) {
947 var base_type
= m
.base_interface_method
.parent_symbol
;
948 if (base_type
!= iface
) {
952 var ciface
= new
CCodeIdentifier ("iface");
953 string cname
= m
.get_real_cname ();
954 if (m
.is_abstract
|| m
.is_virtual
) {
955 // FIXME results in C compiler warning
956 cname
= m
.get_cname ();
958 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, m
.base_interface_method
.vfunc_name
), new
CCodeIdentifier (cname
))));
961 // connect inherited implementations
962 foreach (Method m
in iface
.get_methods ()) {
964 Method cl_method
= null;
966 while (base_class
!= null && cl_method
== null) {
967 cl_method
= base_class
.scope
.lookup (m
.name
) as Method
;
968 base_class
= base_class
.base_class
;
970 if (base_class
!= null && cl_method
.parent_symbol
!= cl
) {
971 // method inherited from base class
973 var base_method
= cl_method
;
974 if (cl_method
.base_method
!= null) {
975 base_method
= cl_method
.base_method
;
976 } else if (cl_method
.base_interface_method
!= null) {
977 base_method
= cl_method
.base_interface_method
;
980 var ciface
= new
CCodeIdentifier ("iface");
981 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, m
.vfunc_name
), new
CCodeIdentifier (base_method
.get_cname ()))));
986 foreach (Property prop
in cl
.get_properties ()) {
987 if (prop
.base_interface_property
== null) {
991 var base_type
= prop
.base_interface_property
.parent_symbol
;
992 if (base_type
!= iface
) {
996 var ciface
= new
CCodeIdentifier ("iface");
998 if (prop
.get_accessor
!= null) {
999 string cname
= "%s_real_get_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
1000 if (prop
.is_abstract
|| prop
.is_virtual
) {
1001 cname
= "%s_get_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
1003 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, "get_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
))));
1005 if (prop
.set_accessor
!= null) {
1006 string cname
= "%s_real_set_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
1007 if (prop
.is_abstract
|| prop
.is_virtual
) {
1008 cname
= "%s_set_%s".printf (cl
.get_lower_case_cname (null), prop
.name
);
1010 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, "set_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
))));
1014 foreach (Property prop
in iface
.get_properties ()) {
1015 if (!prop
.is_abstract
) {
1019 Property cl_prop
= null;
1020 var base_class
= cl
;
1021 while (base_class
!= null && cl_prop
== null) {
1022 cl_prop
= base_class
.scope
.lookup (prop
.name
) as Property
;
1023 base_class
= base_class
.base_class
;
1025 if (base_class
!= null && cl_prop
.parent_symbol
!= cl
) {
1026 // property inherited from base class
1028 var base_property
= cl_prop
;
1029 if (cl_prop
.base_property
!= null) {
1030 base_property
= cl_prop
.base_property
;
1031 } else if (cl_prop
.base_interface_property
!= null) {
1032 base_property
= cl_prop
.base_interface_property
;
1035 var ciface
= new
CCodeIdentifier ("iface");
1037 if (base_property
.get_accessor
!= null) {
1038 string cname
= base_property
.get_accessor
.get_cname ();
1039 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, "get_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
))));
1041 if (base_property
.set_accessor
!= null) {
1042 string cname
= base_property
.set_accessor
.get_cname ();
1043 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (ciface
, "set_%s".printf (prop
.name
)), new
CCodeIdentifier (cname
))));
1048 source_type_member_definition
.append (iface_init
);
1051 private void add_instance_init_function (Class cl
) {
1052 var instance_init
= new
CCodeFunction ("%s_instance_init".printf (cl
.get_lower_case_cname (null)), "void");
1053 instance_init
.add_parameter (new
CCodeFormalParameter ("self", "%s *".printf (cl
.get_cname ())));
1054 instance_init
.modifiers
= CCodeModifiers
.STATIC
;
1056 if (cl
.is_compact
) {
1057 // Add declaration, since the instance_init function is explicitly called
1058 // by the creation methods
1059 source_type_member_declaration
.append (instance_init
.copy ());
1062 var init_block
= new
CCodeBlock ();
1063 instance_init
.block
= init_block
;
1065 if (!cl
.is_compact
&& (cl
.has_private_fields
|| cl
.get_type_parameters ().size
> 0)) {
1066 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_PRIVATE".printf (cl
.get_upper_case_cname (null))));
1067 ccall
.add_argument (new
CCodeIdentifier ("self"));
1068 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "priv"), ccall
)));
1071 init_block
.add_statement (instance_init_fragment
);
1073 source_type_member_definition
.append (instance_init
);
1076 private void add_finalize_function (Class cl
) {
1077 var function
= new
CCodeFunction ("%s_finalize".printf (cl
.get_lower_case_cname (null)), "void");
1078 function
.modifiers
= CCodeModifiers
.STATIC
;
1080 var fundamental_class
= cl
;
1081 while (fundamental_class
.base_class
!= null) {
1082 fundamental_class
= fundamental_class
.base_class
;
1085 function
.add_parameter (new
CCodeFormalParameter ("obj", fundamental_class
.get_cname () + "*"));
1087 source_type_member_declaration
.append (function
.copy ());
1090 var cblock
= new
CCodeBlock ();
1092 CCodeFunctionCall ccall
= new
InstanceCast (new
CCodeIdentifier ("obj"), cl
);
1094 var cdecl
= new
CCodeDeclaration ("%s *".printf (cl
.get_cname ()));
1095 cdecl
.add_declarator (new CCodeVariableDeclarator
.with_initializer ("self", ccall
));
1097 cblock
.add_statement (cdecl
);
1099 if (cl
.destructor
!= null) {
1100 cblock
.add_statement (cl
.destructor
.ccodenode
);
1103 cblock
.add_statement (instance_finalize_fragment
);
1105 // chain up to finalize function of the base class
1106 if (cl
.base_class
!= null) {
1107 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (fundamental_class
.get_upper_case_cname ())));
1108 ccast
.add_argument (new
CCodeIdentifier ("%s_parent_class".printf (cl
.get_lower_case_cname (null))));
1109 ccall
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (ccast
, "finalize"));
1110 ccall
.add_argument (new
CCodeIdentifier ("obj"));
1111 cblock
.add_statement (new
CCodeExpressionStatement (ccall
));
1115 function
.block
= cblock
;
1117 source_type_member_definition
.append (function
);
1120 private bool class_has_readable_properties (Class cl
) {
1121 foreach (Property prop
in cl
.get_properties ()) {
1122 if (prop
.get_accessor
!= null) {
1129 private bool class_has_writable_properties (Class cl
) {
1130 foreach (Property prop
in cl
.get_properties ()) {
1131 if (prop
.set_accessor
!= null) {
1138 private void add_get_property_function (Class cl
) {
1139 var get_prop
= new
CCodeFunction ("%s_get_property".printf (cl
.get_lower_case_cname (null)), "void");
1140 get_prop
.modifiers
= CCodeModifiers
.STATIC
;
1141 get_prop
.add_parameter (new
CCodeFormalParameter ("object", "GObject *"));
1142 get_prop
.add_parameter (new
CCodeFormalParameter ("property_id", "guint"));
1143 get_prop
.add_parameter (new
CCodeFormalParameter ("value", "GValue *"));
1144 get_prop
.add_parameter (new
CCodeFormalParameter ("pspec", "GParamSpec *"));
1146 var block
= new
CCodeBlock ();
1148 CCodeFunctionCall ccall
= new
InstanceCast (new
CCodeIdentifier ("object"), cl
);
1149 var cdecl
= new
CCodeDeclaration ("%s *".printf (cl
.get_cname ()));
1150 cdecl
.add_declarator (new CCodeVariableDeclarator
.with_initializer ("self", ccall
));
1151 block
.add_statement (cdecl
);
1153 var cswitch
= new
CCodeSwitchStatement (new
CCodeIdentifier ("property_id"));
1154 var props
= cl
.get_properties ();
1155 foreach (Property prop
in props
) {
1156 // FIXME: omit real struct types for now since they cannot be expressed as gobject property yet
1157 if (prop
.get_accessor
== null || prop
.is_abstract
|| prop
.property_type
.is_real_struct_type ()) {
1160 if (prop
.access
== SymbolAccessibility
.PRIVATE
) {
1161 // don't register private properties
1165 string prefix
= cl
.get_lower_case_cname (null);
1166 CCodeExpression cself
= new
CCodeIdentifier ("self");
1167 if (prop
.base_property
!= null) {
1168 var base_type
= (Class
) prop
.base_property
.parent_symbol
;
1169 prefix
= base_type
.get_lower_case_cname (null);
1170 cself
= transform_expression (cself
, new
ObjectType (cl
), new
ObjectType (base_type
));
1171 } else if (prop
.base_interface_property
!= null) {
1172 var base_type
= (Interface
) prop
.base_interface_property
.parent_symbol
;
1173 prefix
= base_type
.get_lower_case_cname (null);
1174 cself
= transform_expression (cself
, new
ObjectType (cl
), new
ObjectType (base_type
));
1177 cswitch
.add_statement (new
CCodeCaseStatement (new
CCodeIdentifier (prop
.get_upper_case_cname ())));
1178 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_get_%s".printf (prefix
, prop
.name
)));
1179 ccall
.add_argument (cself
);
1180 var csetcall
= new
CCodeFunctionCall ();
1181 csetcall
.call
= head
.get_value_setter_function (prop
.property_type
);
1182 csetcall
.add_argument (new
CCodeIdentifier ("value"));
1183 csetcall
.add_argument (ccall
);
1184 cswitch
.add_statement (new
CCodeExpressionStatement (csetcall
));
1185 cswitch
.add_statement (new
CCodeBreakStatement ());
1187 cswitch
.add_statement (new
CCodeLabel ("default"));
1188 cswitch
.add_statement (get_invalid_property_id_warn_statement ());
1189 cswitch
.add_statement (new
CCodeBreakStatement ());
1191 block
.add_statement (cswitch
);
1193 get_prop
.block
= block
;
1195 source_type_member_definition
.append (get_prop
);
1198 private void add_set_property_function (Class cl
) {
1199 var set_prop
= new
CCodeFunction ("%s_set_property".printf (cl
.get_lower_case_cname (null)), "void");
1200 set_prop
.modifiers
= CCodeModifiers
.STATIC
;
1201 set_prop
.add_parameter (new
CCodeFormalParameter ("object", "GObject *"));
1202 set_prop
.add_parameter (new
CCodeFormalParameter ("property_id", "guint"));
1203 set_prop
.add_parameter (new
CCodeFormalParameter ("value", "const GValue *"));
1204 set_prop
.add_parameter (new
CCodeFormalParameter ("pspec", "GParamSpec *"));
1206 var block
= new
CCodeBlock ();
1208 CCodeFunctionCall ccall
= new
InstanceCast (new
CCodeIdentifier ("object"), cl
);
1209 var cdecl
= new
CCodeDeclaration ("%s *".printf (cl
.get_cname ()));
1210 cdecl
.add_declarator (new CCodeVariableDeclarator
.with_initializer ("self", ccall
));
1211 block
.add_statement (cdecl
);
1213 var cswitch
= new
CCodeSwitchStatement (new
CCodeIdentifier ("property_id"));
1214 var props
= cl
.get_properties ();
1215 foreach (Property prop
in props
) {
1216 // FIXME: omit real struct types for now since they cannot be expressed as gobject property yet
1217 if (prop
.set_accessor
== null || prop
.is_abstract
|| prop
.property_type
.is_real_struct_type ()) {
1220 if (prop
.access
== SymbolAccessibility
.PRIVATE
) {
1221 // don't register private properties
1225 string prefix
= cl
.get_lower_case_cname (null);
1226 CCodeExpression cself
= new
CCodeIdentifier ("self");
1227 if (prop
.base_property
!= null) {
1228 var base_type
= (Class
) prop
.base_property
.parent_symbol
;
1229 prefix
= base_type
.get_lower_case_cname (null);
1230 cself
= transform_expression (cself
, new
ObjectType (cl
), new
ObjectType (base_type
));
1231 } else if (prop
.base_interface_property
!= null) {
1232 var base_type
= (Interface
) prop
.base_interface_property
.parent_symbol
;
1233 prefix
= base_type
.get_lower_case_cname (null);
1234 cself
= transform_expression (cself
, new
ObjectType (cl
), new
ObjectType (base_type
));
1237 cswitch
.add_statement (new
CCodeCaseStatement (new
CCodeIdentifier (prop
.get_upper_case_cname ())));
1238 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_set_%s".printf (prefix
, prop
.name
)));
1239 ccall
.add_argument (cself
);
1240 var cgetcall
= new
CCodeFunctionCall ();
1241 if (prop
.property_type
.data_type
!= null) {
1242 cgetcall
.call
= new
CCodeIdentifier (prop
.property_type
.data_type
.get_get_value_function ());
1244 cgetcall
.call
= new
CCodeIdentifier ("g_value_get_pointer");
1246 cgetcall
.add_argument (new
CCodeIdentifier ("value"));
1247 ccall
.add_argument (cgetcall
);
1248 cswitch
.add_statement (new
CCodeExpressionStatement (ccall
));
1249 cswitch
.add_statement (new
CCodeBreakStatement ());
1251 cswitch
.add_statement (new
CCodeLabel ("default"));
1252 cswitch
.add_statement (get_invalid_property_id_warn_statement ());
1253 cswitch
.add_statement (new
CCodeBreakStatement ());
1255 block
.add_statement (cswitch
);
1257 /* type, dup func, and destroy func properties for generic types */
1258 foreach (TypeParameter type_param
in cl
.get_type_parameters ()) {
1259 string func_name
, enum_value
;
1260 CCodeMemberAccess cfield
;
1261 CCodeFunctionCall cgetcall
;
1263 func_name
= "%s_type".printf (type_param
.name
.down ());
1264 enum_value
= "%s_%s".printf (cl
.get_lower_case_cname (null), func_name
).up ();
1265 cswitch
.add_statement (new
CCodeCaseStatement (new
CCodeIdentifier (enum_value
)));
1266 cfield
= new CCodeMemberAccess
.pointer (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "priv"), func_name
);
1267 cgetcall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_get_gtype"));
1268 cgetcall
.add_argument (new
CCodeIdentifier ("value"));
1269 cswitch
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (cfield
, cgetcall
)));
1270 cswitch
.add_statement (new
CCodeBreakStatement ());
1272 func_name
= "%s_dup_func".printf (type_param
.name
.down ());
1273 enum_value
= "%s_%s".printf (cl
.get_lower_case_cname (null), func_name
).up ();
1274 cswitch
.add_statement (new
CCodeCaseStatement (new
CCodeIdentifier (enum_value
)));
1275 cfield
= new CCodeMemberAccess
.pointer (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "priv"), func_name
);
1276 cgetcall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_get_pointer"));
1277 cgetcall
.add_argument (new
CCodeIdentifier ("value"));
1278 cswitch
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (cfield
, cgetcall
)));
1279 cswitch
.add_statement (new
CCodeBreakStatement ());
1281 func_name
= "%s_destroy_func".printf (type_param
.name
.down ());
1282 enum_value
= "%s_%s".printf (cl
.get_lower_case_cname (null), func_name
).up ();
1283 cswitch
.add_statement (new
CCodeCaseStatement (new
CCodeIdentifier (enum_value
)));
1284 cfield
= new CCodeMemberAccess
.pointer (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("self"), "priv"), func_name
);
1285 cgetcall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_get_pointer"));
1286 cgetcall
.add_argument (new
CCodeIdentifier ("value"));
1287 cswitch
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (cfield
, cgetcall
)));
1288 cswitch
.add_statement (new
CCodeBreakStatement ());
1291 set_prop
.block
= block
;
1293 source_type_member_definition
.append (set_prop
);
1296 private CCodeStatement
get_invalid_property_id_warn_statement () {
1297 // warn on invalid property id
1298 var cwarn
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT_WARN_INVALID_PROPERTY_ID"));
1299 cwarn
.add_argument (new
CCodeIdentifier ("object"));
1300 cwarn
.add_argument (new
CCodeIdentifier ("property_id"));
1301 cwarn
.add_argument (new
CCodeIdentifier ("pspec"));
1302 return new
CCodeExpressionStatement (cwarn
);
1305 public override CCodeFunctionCall
get_param_spec (Property prop
) {
1306 var cspec
= new
CCodeFunctionCall ();
1307 cspec
.add_argument (prop
.get_canonical_cconstant ());
1308 cspec
.add_argument (new
CCodeConstant ("\"%s\"".printf (prop
.nick
)));
1309 cspec
.add_argument (new
CCodeConstant ("\"%s\"".printf (prop
.blurb
)));
1312 if ((prop
.property_type
.data_type is Class
&& !(((Class
) prop
.property_type
.data_type
).is_compact
)) || prop
.property_type
.data_type is Interface
) {
1313 string param_spec_name
= prop
.property_type
.data_type
.get_param_spec_function ();
1314 if (param_spec_name
== null) {
1315 cspec
.call
= new
CCodeIdentifier ("g_param_spec_pointer");
1317 cspec
.call
= new
CCodeIdentifier ( param_spec_name
);
1318 cspec
.add_argument (new
CCodeIdentifier (prop
.property_type
.data_type
.get_type_id ()));
1320 } else if (prop
.property_type
.data_type
== string_type
.data_type
) {
1321 cspec
.call
= new
CCodeIdentifier ("g_param_spec_string");
1322 cspec
.add_argument (new
CCodeConstant ("NULL"));
1323 } else if (prop
.property_type
.data_type is Enum
) {
1324 var e
= prop
.property_type
.data_type as Enum
;
1325 if (e
.has_type_id
) {
1327 cspec
.call
= new
CCodeIdentifier ("g_param_spec_flags");
1329 cspec
.call
= new
CCodeIdentifier ("g_param_spec_enum");
1331 cspec
.add_argument (new
CCodeIdentifier (e
.get_type_id ()));
1334 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uint");
1335 cspec
.add_argument (new
CCodeConstant ("0"));
1336 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT"));
1338 cspec
.call
= new
CCodeIdentifier ("g_param_spec_int");
1339 cspec
.add_argument (new
CCodeConstant ("G_MININT"));
1340 cspec
.add_argument (new
CCodeConstant ("G_MAXINT"));
1344 if (prop
.default_expression
!= null) {
1345 cspec
.add_argument ((CCodeExpression
) prop
.default_expression
.ccodenode
);
1347 cspec
.add_argument (new
CCodeConstant (prop
.property_type
.data_type
.get_default_value ()));
1349 } else if (prop
.property_type
.data_type is Struct
) {
1350 var st
= (Struct
) prop
.property_type
.data_type
;
1351 if (st
.get_type_id () == "G_TYPE_INT") {
1352 cspec
.call
= new
CCodeIdentifier ("g_param_spec_int");
1353 cspec
.add_argument (new
CCodeConstant ("G_MININT"));
1354 cspec
.add_argument (new
CCodeConstant ("G_MAXINT"));
1355 if (prop
.default_expression
!= null) {
1356 cspec
.add_argument ((CCodeExpression
) prop
.default_expression
.ccodenode
);
1358 cspec
.add_argument (new
CCodeConstant ("0"));
1360 } else if (st
.get_type_id () == "G_TYPE_UINT") {
1361 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uint");
1362 cspec
.add_argument (new
CCodeConstant ("0"));
1363 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT"));
1364 if (prop
.default_expression
!= null) {
1365 cspec
.add_argument ((CCodeExpression
) prop
.default_expression
.ccodenode
);
1367 cspec
.add_argument (new
CCodeConstant ("0U"));
1369 } else if (st
.get_type_id () == "G_TYPE_INT64") {
1370 cspec
.call
= new
CCodeIdentifier ("g_param_spec_int64");
1371 cspec
.add_argument (new
CCodeConstant ("G_MININT64"));
1372 cspec
.add_argument (new
CCodeConstant ("G_MAXINT64"));
1373 if (prop
.default_expression
!= null) {
1374 cspec
.add_argument ((CCodeExpression
) prop
.default_expression
.ccodenode
);
1376 cspec
.add_argument (new
CCodeConstant ("0"));
1378 } else if (st
.get_type_id () == "G_TYPE_UINT64") {
1379 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uint64");
1380 cspec
.add_argument (new
CCodeConstant ("0"));
1381 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT64"));
1382 if (prop
.default_expression
!= null) {
1383 cspec
.add_argument ((CCodeExpression
) prop
.default_expression
.ccodenode
);
1385 cspec
.add_argument (new
CCodeConstant ("0U"));
1387 } else if (st
.get_type_id () == "G_TYPE_LONG") {
1388 cspec
.call
= new
CCodeIdentifier ("g_param_spec_long");
1389 cspec
.add_argument (new
CCodeConstant ("G_MINLONG"));
1390 cspec
.add_argument (new
CCodeConstant ("G_MAXLONG"));
1391 if (prop
.default_expression
!= null) {
1392 cspec
.add_argument ((CCodeExpression
) prop
.default_expression
.ccodenode
);
1394 cspec
.add_argument (new
CCodeConstant ("0L"));
1396 } else if (st
.get_type_id () == "G_TYPE_ULONG") {
1397 cspec
.call
= new
CCodeIdentifier ("g_param_spec_ulong");
1398 cspec
.add_argument (new
CCodeConstant ("0"));
1399 cspec
.add_argument (new
CCodeConstant ("G_MAXULONG"));
1400 if (prop
.default_expression
!= null) {
1401 cspec
.add_argument ((CCodeExpression
) prop
.default_expression
.ccodenode
);
1403 cspec
.add_argument (new
CCodeConstant ("0UL"));
1405 } else if (st
.get_type_id () == "G_TYPE_BOOLEAN") {
1406 cspec
.call
= new
CCodeIdentifier ("g_param_spec_boolean");
1407 if (prop
.default_expression
!= null) {
1408 cspec
.add_argument ((CCodeExpression
) prop
.default_expression
.ccodenode
);
1410 cspec
.add_argument (new
CCodeConstant ("FALSE"));
1412 } else if (st
.get_type_id () == "G_TYPE_CHAR") {
1413 cspec
.call
= new
CCodeIdentifier ("g_param_spec_char");
1414 cspec
.add_argument (new
CCodeConstant ("G_MININT8"));
1415 cspec
.add_argument (new
CCodeConstant ("G_MAXINT8"));
1416 if (prop
.default_expression
!= null) {
1417 cspec
.add_argument ((CCodeExpression
) prop
.default_expression
.ccodenode
);
1419 cspec
.add_argument (new
CCodeConstant ("0"));
1421 } else if (st
.get_type_id () == "G_TYPE_UCHAR") {
1422 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uchar");
1423 cspec
.add_argument (new
CCodeConstant ("0"));
1424 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT8"));
1425 if (prop
.default_expression
!= null) {
1426 cspec
.add_argument ((CCodeExpression
) prop
.default_expression
.ccodenode
);
1428 cspec
.add_argument (new
CCodeConstant ("0"));
1430 }else if (st
.get_type_id () == "G_TYPE_FLOAT") {
1431 cspec
.call
= new
CCodeIdentifier ("g_param_spec_float");
1432 cspec
.add_argument (new
CCodeConstant ("-G_MAXFLOAT"));
1433 cspec
.add_argument (new
CCodeConstant ("G_MAXFLOAT"));
1434 if (prop
.default_expression
!= null) {
1435 cspec
.add_argument ((CCodeExpression
) prop
.default_expression
.ccodenode
);
1437 cspec
.add_argument (new
CCodeConstant ("0.0F"));
1439 } else if (st
.get_type_id () == "G_TYPE_DOUBLE") {
1440 cspec
.call
= new
CCodeIdentifier ("g_param_spec_double");
1441 cspec
.add_argument (new
CCodeConstant ("-G_MAXDOUBLE"));
1442 cspec
.add_argument (new
CCodeConstant ("G_MAXDOUBLE"));
1443 if (prop
.default_expression
!= null) {
1444 cspec
.add_argument ((CCodeExpression
) prop
.default_expression
.ccodenode
);
1446 cspec
.add_argument (new
CCodeConstant ("0.0"));
1448 } else if (st
.get_type_id () == "G_TYPE_GTYPE") {
1449 cspec
.call
= new
CCodeIdentifier ("g_param_spec_gtype");
1450 if (prop
.default_expression
!= null) {
1451 cspec
.add_argument ((CCodeExpression
) prop
.default_expression
.ccodenode
);
1453 cspec
.add_argument (new
CCodeConstant ("G_TYPE_NONE"));
1456 cspec
.call
= new
CCodeIdentifier ("g_param_spec_pointer");
1459 cspec
.call
= new
CCodeIdentifier ("g_param_spec_pointer");
1462 var pflags
= "G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB";
1463 if (prop
.get_accessor
!= null) {
1464 pflags
= "%s%s".printf (pflags
, " | G_PARAM_READABLE");
1466 if (prop
.set_accessor
!= null) {
1467 pflags
= "%s%s".printf (pflags
, " | G_PARAM_WRITABLE");
1468 if (prop
.set_accessor
.construction
) {
1469 if (prop
.set_accessor
.writable
) {
1470 pflags
= "%s%s".printf (pflags
, " | G_PARAM_CONSTRUCT");
1472 pflags
= "%s%s".printf (pflags
, " | G_PARAM_CONSTRUCT_ONLY");
1476 cspec
.add_argument (new
CCodeConstant (pflags
));
1481 public override CCodeExpression
get_construct_property_assignment (CCodeConstant canonical_cconstant
, DataType property_type
, CCodeExpression value
) {
1482 // this property is used as a construction parameter
1483 var cpointer
= new
CCodeIdentifier ("__params_it");
1485 var ccomma
= new
CCodeCommaExpression ();
1486 // set name in array for current parameter
1487 var cnamemember
= new CCodeMemberAccess
.pointer (cpointer
, "name");
1488 var cnameassign
= new
CCodeAssignment (cnamemember
, canonical_cconstant
);
1489 ccomma
.append_expression (cnameassign
);
1491 var gvaluearg
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new CCodeMemberAccess
.pointer (cpointer
, "value"));
1493 // initialize GValue in array for current parameter
1494 var cvalueinit
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_init"));
1495 cvalueinit
.add_argument (gvaluearg
);
1496 cvalueinit
.add_argument (new
CCodeIdentifier (property_type
.get_type_id ()));
1497 ccomma
.append_expression (cvalueinit
);
1499 // set GValue for current parameter
1500 var cvalueset
= new
CCodeFunctionCall (get_value_setter_function (property_type
));
1501 cvalueset
.add_argument (gvaluearg
);
1502 cvalueset
.add_argument (value
);
1503 ccomma
.append_expression (cvalueset
);
1505 // move pointer to next parameter in array
1506 ccomma
.append_expression (new
CCodeUnaryExpression (CCodeUnaryOperator
.POSTFIX_INCREMENT
, cpointer
));
1511 public override void visit_constructor (Constructor c
) {
1512 current_method_inner_error
= false;
1513 in_constructor
= true;
1515 if (c
.binding
== MemberBinding
.CLASS
|| c
.binding
== MemberBinding
.STATIC
) {
1516 in_static_or_class_ctor
= true;
1518 c
.accept_children (codegen
);
1519 in_static_or_class_ctor
= false;
1521 in_constructor
= false;
1523 var cl
= (Class
) c
.parent_symbol
;
1525 if (c
.binding
== MemberBinding
.INSTANCE
) {
1526 function
= new
CCodeFunction ("%s_constructor".printf (cl
.get_lower_case_cname (null)), "GObject *");
1527 function
.modifiers
= CCodeModifiers
.STATIC
;
1529 function
.add_parameter (new
CCodeFormalParameter ("type", "GType"));
1530 function
.add_parameter (new
CCodeFormalParameter ("n_construct_properties", "guint"));
1531 function
.add_parameter (new
CCodeFormalParameter ("construct_properties", "GObjectConstructParam *"));
1533 source_type_member_declaration
.append (function
.copy ());
1536 var cblock
= new
CCodeBlock ();
1537 var cdecl
= new
CCodeDeclaration ("GObject *");
1538 cdecl
.add_declarator (new
CCodeVariableDeclarator ("obj"));
1539 cblock
.add_statement (cdecl
);
1541 cdecl
= new
CCodeDeclaration ("%sClass *".printf (cl
.get_cname ()));
1542 cdecl
.add_declarator (new
CCodeVariableDeclarator ("klass"));
1543 cblock
.add_statement (cdecl
);
1545 cdecl
= new
CCodeDeclaration ("GObjectClass *");
1546 cdecl
.add_declarator (new
CCodeVariableDeclarator ("parent_class"));
1547 cblock
.add_statement (cdecl
);
1550 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_peek"));
1551 ccall
.add_argument (new
CCodeIdentifier (cl
.get_type_id ()));
1552 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (cl
.get_upper_case_cname (null))));
1553 ccast
.add_argument (ccall
);
1554 cblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("klass"), ccast
)));
1556 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_class_peek_parent"));
1557 ccall
.add_argument (new
CCodeIdentifier ("klass"));
1558 ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT_CLASS"));
1559 ccast
.add_argument (ccall
);
1560 cblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("parent_class"), ccast
)));
1563 ccall
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("parent_class"), "constructor"));
1564 ccall
.add_argument (new
CCodeIdentifier ("type"));
1565 ccall
.add_argument (new
CCodeIdentifier ("n_construct_properties"));
1566 ccall
.add_argument (new
CCodeIdentifier ("construct_properties"));
1567 cblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("obj"), ccall
)));
1570 ccall
= new
InstanceCast (new
CCodeIdentifier ("obj"), cl
);
1572 cdecl
= new
CCodeDeclaration ("%s *".printf (cl
.get_cname ()));
1573 cdecl
.add_declarator (new CCodeVariableDeclarator
.with_initializer ("self", ccall
));
1574 cblock
.add_statement (cdecl
);
1576 if (current_method_inner_error
) {
1577 /* always separate error parameter and inner_error local variable
1578 * as error may be set to NULL but we're always interested in inner errors
1580 cdecl
= new
CCodeDeclaration ("GError *");
1581 cdecl
.add_declarator (new CCodeVariableDeclarator
.with_initializer ("inner_error", new
CCodeConstant ("NULL")));
1582 cblock
.add_statement (cdecl
);
1586 cblock
.add_statement (c
.body
.ccodenode
);
1588 cblock
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("obj")));
1590 function
.block
= cblock
;
1592 if (c
.source_reference
.comment
!= null) {
1593 source_type_member_definition
.append (new
CCodeComment (c
.source_reference
.comment
));
1595 source_type_member_definition
.append (function
);
1596 } else if (c
.binding
== MemberBinding
.CLASS
) {
1597 // class constructor
1599 var base_init
= new
CCodeFunction ("%s_base_init".printf (cl
.get_lower_case_cname (null)), "void");
1600 base_init
.add_parameter (new
CCodeFormalParameter ("klass", "%sClass *".printf (cl
.get_cname ())));
1601 base_init
.modifiers
= CCodeModifiers
.STATIC
;
1603 source_type_member_declaration
.append (base_init
.copy ());
1605 var block
= (CCodeBlock
) c
.body
.ccodenode
;
1606 if (current_method_inner_error
) {
1607 /* always separate error parameter and inner_error local variable
1608 * as error may be set to NULL but we're always interested in inner errors
1610 var cdecl
= new
CCodeDeclaration ("GError *");
1611 cdecl
.add_declarator (new CCodeVariableDeclarator
.with_initializer ("inner_error", new
CCodeConstant ("NULL")));
1612 block
.prepend_statement (cdecl
);
1615 base_init
.block
= block
;
1617 source_type_member_definition
.append (base_init
);
1618 } else if (c
.binding
== MemberBinding
.STATIC
) {
1619 // static class constructor
1620 // add to class_init
1622 if (current_method_inner_error
) {
1623 /* always separate error parameter and inner_error local variable
1624 * as error may be set to NULL but we're always interested in inner errors
1626 var cdecl
= new
CCodeDeclaration ("GError *");
1627 cdecl
.add_declarator (new CCodeVariableDeclarator
.with_initializer ("inner_error", new
CCodeConstant ("NULL")));
1628 class_init_fragment
.append (cdecl
);
1631 class_init_fragment
.append (c
.body
.ccodenode
);
1633 Report
.error (c
.source_reference
, "internal error: constructors must have instance, class, or static binding");
1637 public override string get_dynamic_property_getter_cname (DynamicProperty prop
) {
1638 if (prop
.dynamic_type
.data_type
== null
1639 || !prop
.dynamic_type
.data_type
.is_subtype_of (gobject_type
)) {
1640 return base.get_dynamic_property_getter_cname (prop
);
1643 string getter_cname
= "_dynamic_get_%s%d".printf (prop
.name
, dynamic_property_id
++);
1645 var func
= new
CCodeFunction (getter_cname
, prop
.property_type
.get_cname ());
1646 func
.modifiers
|= CCodeModifiers
.STATIC
| CCodeModifiers
.INLINE
;
1648 func
.add_parameter (new
CCodeFormalParameter ("obj", prop
.dynamic_type
.get_cname ()));
1650 var block
= new
CCodeBlock ();
1651 generate_gobject_property_getter_wrapper (prop
, block
);
1653 // append to C source file
1654 source_type_member_declaration
.append (func
.copy ());
1657 source_type_member_definition
.append (func
);
1659 return getter_cname
;
1662 public override string get_dynamic_property_setter_cname (DynamicProperty prop
) {
1663 if (prop
.dynamic_type
.data_type
== null
1664 || !prop
.dynamic_type
.data_type
.is_subtype_of (gobject_type
)) {
1665 return base.get_dynamic_property_setter_cname (prop
);
1668 string setter_cname
= "_dynamic_set_%s%d".printf (prop
.name
, dynamic_property_id
++);
1670 var func
= new
CCodeFunction (setter_cname
, "void");
1671 func
.modifiers
|= CCodeModifiers
.STATIC
| CCodeModifiers
.INLINE
;
1673 func
.add_parameter (new
CCodeFormalParameter ("obj", prop
.dynamic_type
.get_cname ()));
1674 func
.add_parameter (new
CCodeFormalParameter ("value", prop
.property_type
.get_cname ()));
1676 var block
= new
CCodeBlock ();
1677 generate_gobject_property_setter_wrapper (prop
, block
);
1679 // append to C source file
1680 source_type_member_declaration
.append (func
.copy ());
1683 source_type_member_definition
.append (func
);
1685 return setter_cname
;
1688 void generate_gobject_property_getter_wrapper (DynamicProperty node
, CCodeBlock block
) {
1689 var cdecl
= new
CCodeDeclaration (node
.property_type
.get_cname ());
1690 cdecl
.add_declarator (new
CCodeVariableDeclarator ("result"));
1691 block
.add_statement (cdecl
);
1693 var call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_get"));
1694 call
.add_argument (new
CCodeIdentifier ("obj"));
1695 call
.add_argument (node
.get_canonical_cconstant ());
1696 call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("result")));
1697 call
.add_argument (new
CCodeConstant ("NULL"));
1699 block
.add_statement (new
CCodeExpressionStatement (call
));
1701 block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("result")));
1704 void generate_gobject_property_setter_wrapper (DynamicProperty node
, CCodeBlock block
) {
1705 var call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_set"));
1706 call
.add_argument (new
CCodeIdentifier ("obj"));
1707 call
.add_argument (node
.get_canonical_cconstant ());
1708 call
.add_argument (new
CCodeIdentifier ("value"));
1709 call
.add_argument (new
CCodeConstant ("NULL"));
1711 block
.add_statement (new
CCodeExpressionStatement (call
));
1714 public override string get_dynamic_signal_cname (DynamicSignal node
) {
1715 return "dynamic_%s%d_".printf (node
.name
, signal_wrapper_id
++);
1718 public override string get_dynamic_signal_connect_wrapper_name (DynamicSignal sig
) {
1719 if (sig
.dynamic_type
.data_type
== null
1720 || !sig
.dynamic_type
.data_type
.is_subtype_of (gobject_type
)) {
1721 return base.get_dynamic_signal_connect_wrapper_name (sig
);
1724 string connect_wrapper_name
= "_%sconnect".printf (get_dynamic_signal_cname (sig
));
1725 var func
= new
CCodeFunction (connect_wrapper_name
, "void");
1726 func
.add_parameter (new
CCodeFormalParameter ("obj", "gpointer"));
1727 func
.add_parameter (new
CCodeFormalParameter ("signal_name", "const char *"));
1728 func
.add_parameter (new
CCodeFormalParameter ("handler", "GCallback"));
1729 func
.add_parameter (new
CCodeFormalParameter ("data", "gpointer"));
1730 var block
= new
CCodeBlock ();
1731 generate_gobject_connect_wrapper (sig
, block
);
1733 // append to C source file
1734 source_type_member_declaration
.append (func
.copy ());
1737 source_type_member_definition
.append (func
);
1739 return connect_wrapper_name
;
1742 void generate_gobject_connect_wrapper (DynamicSignal sig
, CCodeBlock block
) {
1743 var m
= (Method
) sig
.handler
.symbol_reference
;
1745 sig
.accept (codegen
);
1747 string connect_func
= "g_signal_connect_object";
1748 if (m
.binding
!= MemberBinding
.INSTANCE
) {
1749 connect_func
= "g_signal_connect";
1752 var call
= new
CCodeFunctionCall (new
CCodeIdentifier (connect_func
));
1753 call
.add_argument (new
CCodeIdentifier ("obj"));
1754 call
.add_argument (new
CCodeIdentifier ("signal_name"));
1755 call
.add_argument (new
CCodeIdentifier ("handler"));
1756 call
.add_argument (new
CCodeIdentifier ("data"));
1758 if (m
.binding
== MemberBinding
.INSTANCE
) {
1759 call
.add_argument (new
CCodeConstant ("0"));
1762 block
.add_statement (new
CCodeExpressionStatement (call
));