1 /* valagsignalmodule.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 internal class Vala
.GSignalModule
: GObjectModule
{
27 public GSignalModule (CCodeGenerator codegen
, CCodeModule? next
) {
31 private string get_marshaller_type_name (DataType t
, bool dbus
= false) {
32 if (t is PointerType
|| t
.type_parameter
!= null) {
34 } else if (t is ErrorType
) {
36 } else if (t is ArrayType
) {
40 if (((ArrayType
) t
).element_type
.data_type
== string_type
.data_type
) {
43 return ("POINTER_INT");
46 } else if (t is VoidType
) {
48 } else if (dbus
&& t
.get_type_signature ().has_prefix ("(")) {
50 } else if (t
.data_type is Enum
) {
51 var en
= (Enum
) t
.data_type
;
59 return en
.get_marshaller_type_name ();
62 return t
.data_type
.get_marshaller_type_name ();
66 private string get_marshaller_type_name_for_parameter (FormalParameter param
, bool dbus
= false) {
67 if (param
.direction
!= ParameterDirection
.IN
) {
70 return get_marshaller_type_name (param
.parameter_type
, dbus
);
74 public override string get_marshaller_function (Gee
.List
<FormalParameter
> params
, DataType return_type
, string? prefix
= null, bool dbus
= false) {
75 var signature
= get_marshaller_signature (params
, return_type
, dbus
);
79 if (predefined_marshal_set
.contains (signature
)) {
80 prefix
= "g_cclosure_marshal";
82 prefix
= "g_cclosure_user_marshal";
86 ret
= "%s_%s_".printf (prefix
, get_marshaller_type_name (return_type
, dbus
));
88 if (params
== null || params
.size
== 0) {
91 foreach (FormalParameter p
in params
) {
92 ret
= "%s_%s".printf (ret
, get_marshaller_type_name_for_parameter (p
, dbus
));
99 private string?
get_value_type_name_from_type_reference (DataType t
) {
100 if (t is PointerType
|| t
.type_parameter
!= null) {
102 } else if (t is VoidType
) {
104 } else if (t
.data_type
== string_type
.data_type
) {
105 return "const char*";
106 } else if (t
.data_type is Class
|| t
.data_type is Interface
) {
108 } else if (t
.data_type is Struct
) {
109 var st
= (Struct
) t
.data_type
;
110 if (st
.is_simple_type ()) {
111 return t
.data_type
.get_cname ();
115 } else if (t
.data_type is Enum
) {
117 } else if (t is ArrayType
) {
119 } else if (t is ErrorType
) {
126 private string?
get_value_type_name_from_parameter (FormalParameter p
) {
127 if (p
.direction
!= ParameterDirection
.IN
) {
130 return get_value_type_name_from_type_reference (p
.parameter_type
);
134 private string get_marshaller_signature (Gee
.List
<FormalParameter
> params
, DataType return_type
, bool dbus
= false) {
137 signature
= "%s:".printf (get_marshaller_type_name (return_type
, dbus
));
138 if (params
== null || params
.size
== 0) {
139 signature
= signature
+ "VOID";
142 foreach (FormalParameter p
in params
) {
144 signature
= signature
+ get_marshaller_type_name_for_parameter (p
, dbus
);
147 signature
= "%s,%s".printf (signature
, get_marshaller_type_name_for_parameter (p
, dbus
));
155 public override void visit_signal (Signal sig
) {
156 // parent_symbol may be null for dynamic signals
158 var cl
= sig
.parent_symbol as Class
;
159 if (cl
!= null && cl
.is_compact
) {
161 Report
.error (sig
.source_reference
, "Signals are not supported in compact classes");
165 sig
.accept_children (codegen
);
167 generate_marshaller (sig
.get_parameters (), sig
.return_type
);
170 public override void generate_marshaller (Gee
.List
<FormalParameter
> params
, DataType return_type
, bool dbus
= false) {
174 /* check whether a signal with the same signature already exists for this source file (or predefined) */
175 signature
= get_marshaller_signature (params
, return_type
, dbus
);
176 if (predefined_marshal_set
.contains (signature
) || user_marshal_set
.contains (signature
)) {
180 var signal_marshaller
= new
CCodeFunction (get_marshaller_function (params
, return_type
, null, dbus
), "void");
181 signal_marshaller
.modifiers
= CCodeModifiers
.STATIC
;
183 signal_marshaller
.add_parameter (new
CCodeFormalParameter ("closure", "GClosure *"));
184 signal_marshaller
.add_parameter (new
CCodeFormalParameter ("return_value", "GValue *"));
185 signal_marshaller
.add_parameter (new
CCodeFormalParameter ("n_param_values", "guint"));
186 signal_marshaller
.add_parameter (new
CCodeFormalParameter ("param_values", "const GValue *"));
187 signal_marshaller
.add_parameter (new
CCodeFormalParameter ("invocation_hint", "gpointer"));
188 signal_marshaller
.add_parameter (new
CCodeFormalParameter ("marshal_data", "gpointer"));
190 source_signal_marshaller_declaration
.append (signal_marshaller
.copy ());
192 var marshaller_body
= new
CCodeBlock ();
194 var callback_decl
= new
CCodeFunctionDeclarator (get_marshaller_function (params
, return_type
, "GMarshalFunc", dbus
));
195 callback_decl
.add_parameter (new
CCodeFormalParameter ("data1", "gpointer"));
197 foreach (FormalParameter p
in params
) {
198 callback_decl
.add_parameter (new
CCodeFormalParameter ("arg_%d".printf (n_params
), get_value_type_name_from_parameter (p
)));
200 if (p
.parameter_type
.is_array () && !dbus
) {
201 callback_decl
.add_parameter (new
CCodeFormalParameter ("arg_%d".printf (n_params
), "gint"));
205 callback_decl
.add_parameter (new
CCodeFormalParameter ("data2", "gpointer"));
206 marshaller_body
.add_statement (new
CCodeTypeDefinition (get_value_type_name_from_type_reference (return_type
), callback_decl
));
208 var var_decl
= new
CCodeDeclaration (get_marshaller_function (params
, return_type
, "GMarshalFunc", dbus
));
209 var_decl
.modifiers
= CCodeModifiers
.REGISTER
;
210 var_decl
.add_declarator (new
CCodeVariableDeclarator ("callback"));
211 marshaller_body
.add_statement (var_decl
);
213 var_decl
= new
CCodeDeclaration ("GCClosure *");
214 var_decl
.modifiers
= CCodeModifiers
.REGISTER
;
215 var_decl
.add_declarator (new
CCodeVariableDeclarator ("cc", new
CCodeCastExpression (new
CCodeIdentifier ("closure"), "GCClosure *")));
216 marshaller_body
.add_statement (var_decl
);
218 var_decl
= new
CCodeDeclaration ("gpointer");
219 var_decl
.modifiers
= CCodeModifiers
.REGISTER
;
220 var_decl
.add_declarator (new
CCodeVariableDeclarator ("data1"));
221 var_decl
.add_declarator (new
CCodeVariableDeclarator ("data2"));
222 marshaller_body
.add_statement (var_decl
);
224 CCodeFunctionCall fc
;
226 if (return_type
.data_type
!= null || return_type
.is_array ()) {
227 var_decl
= new
CCodeDeclaration (get_value_type_name_from_type_reference (return_type
));
228 var_decl
.add_declarator (new
CCodeVariableDeclarator ("v_return"));
229 marshaller_body
.add_statement (var_decl
);
231 fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
232 fc
.add_argument (new
CCodeBinaryExpression (CCodeBinaryOperator
.INEQUALITY
, new
CCodeIdentifier ("return_value"), new
CCodeConstant ("NULL")));
233 marshaller_body
.add_statement (new
CCodeExpressionStatement (fc
));
236 fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
237 fc
.add_argument (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, new
CCodeIdentifier ("n_param_values"), new
CCodeConstant (n_params
.to_string())));
238 marshaller_body
.add_statement (new
CCodeExpressionStatement (fc
));
240 var data
= new
CCodeMemberAccess (new
CCodeIdentifier ("closure"), "data", true);
241 var param
= new
CCodeMemberAccess (new
CCodeMemberAccess (new
CCodeIdentifier ("param_values"), "data[0]", true), "v_pointer");
242 var cond
= new
CCodeFunctionCall (new
CCodeConstant ("G_CCLOSURE_SWAP_DATA"));
243 cond
.add_argument (new
CCodeIdentifier ("closure"));
244 var true_block
= new
CCodeBlock ();
245 true_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("data1"), data
)));
246 true_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("data2"), param
)));
247 var false_block
= new
CCodeBlock ();
248 false_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("data1"), param
)));
249 false_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("data2"), data
)));
250 marshaller_body
.add_statement (new
CCodeIfStatement (cond
, true_block
, false_block
));
252 var c_assign
= new
CCodeAssignment (new
CCodeIdentifier ("callback"), new
CCodeCastExpression (new
CCodeConditionalExpression (new
CCodeIdentifier ("marshal_data"), new
CCodeIdentifier ("marshal_data"), new
CCodeMemberAccess (new
CCodeIdentifier ("cc"), "callback", true)), get_marshaller_function (params
, return_type
, "GMarshalFunc", dbus
)));
253 marshaller_body
.add_statement (new
CCodeExpressionStatement (c_assign
));
255 fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("callback"));
256 fc
.add_argument (new
CCodeIdentifier ("data1"));
258 foreach (FormalParameter p
in params
) {
259 string get_value_function
;
260 bool is_array
= p
.parameter_type
.is_array ();
261 if (p
.direction
!= ParameterDirection
.IN
) {
262 get_value_function
= "g_value_get_pointer";
263 } else if (is_array
) {
265 get_value_function
= "g_value_get_boxed";
267 if (((ArrayType
) p
.parameter_type
).element_type
.data_type
== string_type
.data_type
) {
268 get_value_function
= "g_value_get_boxed";
270 get_value_function
= "g_value_get_pointer";
273 } else if (p
.parameter_type is PointerType
|| p
.parameter_type
.type_parameter
!= null) {
274 get_value_function
= "g_value_get_pointer";
275 } else if (p
.parameter_type is ErrorType
) {
276 get_value_function
= "g_value_get_pointer";
277 } else if (dbus
&& p
.parameter_type
.get_type_signature ().has_prefix ("(")) {
278 get_value_function
= "g_value_get_boxed";
279 } else if (dbus
&& p
.parameter_type
.data_type is Enum
) {
280 var en
= (Enum
) p
.parameter_type
.data_type
;
282 get_value_function
= "g_value_get_uint";
284 get_value_function
= "g_value_get_int";
287 get_value_function
= p
.parameter_type
.data_type
.get_get_value_function ();
289 var inner_fc
= new
CCodeFunctionCall (new
CCodeIdentifier (get_value_function
));
290 inner_fc
.add_argument (new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, new
CCodeIdentifier ("param_values"), new
CCodeIdentifier (i
.to_string ())));
291 fc
.add_argument (inner_fc
);
293 if (is_array
&& !dbus
) {
294 inner_fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_get_int"));
295 inner_fc
.add_argument (new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, new
CCodeIdentifier ("param_values"), new
CCodeIdentifier (i
.to_string ())));
296 fc
.add_argument (inner_fc
);
300 fc
.add_argument (new
CCodeIdentifier ("data2"));
302 if (return_type
.data_type
!= null || return_type
.is_array ()) {
303 marshaller_body
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("v_return"), fc
)));
305 CCodeFunctionCall set_fc
;
306 if (return_type
.is_array ()) {
308 set_fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_take_boxed"));
310 if (((ArrayType
) return_type
).element_type
.data_type
== string_type
.data_type
) {
311 set_fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_take_boxed"));
313 set_fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_set_pointer"));
316 } else if (return_type
.type_parameter
!= null) {
317 set_fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_set_pointer"));
318 } else if (return_type is ErrorType
) {
319 set_fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_set_pointer"));
320 } else if (return_type
.data_type
== string_type
.data_type
) {
321 set_fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_take_string"));
322 } else if (return_type
.data_type is Class
|| return_type
.data_type is Interface
) {
323 set_fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_take_object"));
324 } else if (dbus
&& return_type
.get_type_signature ().has_prefix ("(")) {
325 set_fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_take_boxed"));
326 } else if (dbus
&& return_type
.data_type is Enum
) {
327 var en
= (Enum
) return_type
.data_type
;
329 set_fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_set_uint"));
331 set_fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_set_int"));
334 set_fc
= new
CCodeFunctionCall (new
CCodeIdentifier (return_type
.data_type
.get_set_value_function ()));
336 set_fc
.add_argument (new
CCodeIdentifier ("return_value"));
337 set_fc
.add_argument (new
CCodeIdentifier ("v_return"));
339 marshaller_body
.add_statement (new
CCodeExpressionStatement (set_fc
));
341 marshaller_body
.add_statement (new
CCodeExpressionStatement (fc
));
344 signal_marshaller
.block
= marshaller_body
;
346 source_signal_marshaller_definition
.append (signal_marshaller
);
347 user_marshal_set
.add (signature
);
350 public override CCodeFunctionCall
get_signal_creation (Signal sig
, TypeSymbol type
) {
351 var csignew
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_signal_new"));
352 csignew
.add_argument (new
CCodeConstant ("\"%s\"".printf (sig
.get_cname ())));
353 csignew
.add_argument (new
CCodeIdentifier (type
.get_type_id ()));
354 csignew
.add_argument (new
CCodeConstant ("G_SIGNAL_RUN_LAST"));
355 csignew
.add_argument (new
CCodeConstant ("0"));
356 csignew
.add_argument (new
CCodeConstant ("NULL"));
357 csignew
.add_argument (new
CCodeConstant ("NULL"));
359 string marshaller
= head
.get_marshaller_function (sig
.get_parameters (), sig
.return_type
);
361 var marshal_arg
= new
CCodeIdentifier (marshaller
);
362 csignew
.add_argument (marshal_arg
);
364 var params
= sig
.get_parameters ();
365 if (sig
.return_type is PointerType
|| sig
.return_type
.type_parameter
!= null) {
366 csignew
.add_argument (new
CCodeConstant ("G_TYPE_POINTER"));
367 } else if (sig
.return_type is ErrorType
) {
368 csignew
.add_argument (new
CCodeConstant ("G_TYPE_POINTER"));
369 } else if (sig
.return_type
.data_type
== null) {
370 csignew
.add_argument (new
CCodeConstant ("G_TYPE_NONE"));
372 csignew
.add_argument (new
CCodeConstant (sig
.return_type
.data_type
.get_type_id ()));
376 foreach (FormalParameter param
in params
) {
378 if (param
.parameter_type
.is_array ()) {
383 csignew
.add_argument (new
CCodeConstant ("%d".printf (params_len
)));
384 foreach (FormalParameter param
in params
) {
385 if (param
.parameter_type
.is_array ()) {
386 if (((ArrayType
) param
.parameter_type
).element_type
.data_type
== string_type
.data_type
) {
387 csignew
.add_argument (new
CCodeConstant ("G_TYPE_STRV"));
389 csignew
.add_argument (new
CCodeConstant ("G_TYPE_POINTER"));
391 csignew
.add_argument (new
CCodeConstant ("G_TYPE_INT"));
392 } else if (param
.parameter_type is PointerType
|| param
.parameter_type
.type_parameter
!= null || param
.direction
!= ParameterDirection
.IN
) {
393 csignew
.add_argument (new
CCodeConstant ("G_TYPE_POINTER"));
394 } else if (param
.parameter_type is ErrorType
) {
395 csignew
.add_argument (new
CCodeConstant ("G_TYPE_POINTER"));
397 csignew
.add_argument (new
CCodeConstant (param
.parameter_type
.data_type
.get_type_id ()));
401 marshal_arg
.name
= marshaller
;
406 public virtual CCodeExpression
get_dbus_g_type (DataType data_type
) {
407 return new
CCodeConstant (data_type
.data_type
.get_type_id ());
410 public override void visit_element_access (ElementAccess expr
) {
411 if (expr
.container is MemberAccess
&& expr
.container
.symbol_reference is Signal
) {
412 // detailed signal emission
413 var sig
= (Signal
) expr
.symbol_reference
;
414 var ma
= (MemberAccess
) expr
.container
;
415 expr
.accept_children (codegen
);
417 var detail_expr
= expr
.get_indices ().get (0) as StringLiteral
;
418 string signal_detail
= detail_expr
.eval ();
420 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_signal_emit_by_name"));
421 ccall
.add_argument ((CCodeExpression
) ma
.inner
.ccodenode
);
422 ccall
.add_argument (sig
.get_canonical_cconstant (signal_detail
));
424 expr
.ccodenode
= ccall
;
426 base.visit_element_access (expr
);
430 CCodeExpression?
emit_signal_assignment (Assignment assignment
) {
431 var sig
= (Signal
) assignment
.left
.symbol_reference
;
433 var m
= (Method
) assignment
.right
.symbol_reference
;
434 var target_type_symbol
= m
.parent_symbol as TypeSymbol
;
437 bool disconnect
= false;
439 if (assignment
.operator
== AssignmentOperator
.ADD
) {
440 if (sig is DynamicSignal
) {
441 connect_func
= head
.get_dynamic_signal_connect_wrapper_name ((DynamicSignal
) sig
);
443 if (m
.binding
== MemberBinding
.INSTANCE
) {
444 if (target_type_symbol
!= null && target_type_symbol
.is_subtype_of (gobject_type
)) {
445 connect_func
= "g_signal_connect_object";
447 connect_func
= "g_signal_connect";
450 connect_func
= "g_signal_connect";
453 } else if (assignment
.operator
== AssignmentOperator
.SUB
) {
454 if (sig is DynamicSignal
) {
455 connect_func
= head
.get_dynamic_signal_disconnect_wrapper_name ((DynamicSignal
) sig
);
457 connect_func
= "g_signal_handlers_disconnect_matched";
461 assignment
.error
= true;
462 Report
.error (assignment
.source_reference
, "Specified compound assignment type for signals not supported.");
466 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (connect_func
));
468 string signal_detail
= null;
470 // first argument: instance of sender
472 if (assignment
.left is ElementAccess
) {
473 var ea
= (ElementAccess
) assignment
.left
;
474 ma
= (MemberAccess
) ea
.container
;
475 var detail_expr
= ea
.get_indices ().get (0) as StringLiteral
;
476 if (detail_expr
== null) {
477 assignment
.error
= true;
478 Report
.error (detail_expr
.source_reference
, "internal error: only literal string details supported");
481 signal_detail
= detail_expr
.eval ();
483 ma
= (MemberAccess
) assignment
.left
;
485 if (ma
.inner
!= null) {
486 ccall
.add_argument ((CCodeExpression
) get_ccodenode (ma
.inner
));
488 ccall
.add_argument (new
CCodeIdentifier ("self"));
491 if (sig is DynamicSignal
) {
492 // dynamic_signal_connect or dynamic_signal_disconnect
494 // second argument: signal name
495 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (sig
.name
)));
496 } else if (!disconnect
) {
497 // g_signal_connect_object or g_signal_connect
499 // second argument: signal name
500 ccall
.add_argument (sig
.get_canonical_cconstant (signal_detail
));
502 // g_signal_handlers_disconnect_matched
504 // second argument: mask
505 if (signal_detail
== null) {
506 ccall
.add_argument (new
CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA"));
508 ccall
.add_argument (new
CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA"));
512 var ccomma
= new
CCodeCommaExpression ();
513 var temp_decl
= get_temp_variable (uint_type
);
514 temp_vars
.insert (0, temp_decl
);
515 var parse_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_signal_parse_name"));
516 parse_call
.add_argument (sig
.get_canonical_cconstant (signal_detail
));
517 var decl_type
= (TypeSymbol
) sig
.parent_symbol
;
518 parse_call
.add_argument (new
CCodeIdentifier (decl_type
.get_type_id ()));
519 parse_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (temp_decl
.name
)));
520 if (signal_detail
== null) {
521 parse_call
.add_argument (new
CCodeConstant ("NULL"));
523 var detail_temp_decl
= get_temp_variable (gquark_type
);
524 temp_vars
.insert (0, detail_temp_decl
);
525 parse_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (detail_temp_decl
.name
)));
527 parse_call
.add_argument (new
CCodeConstant ("FALSE"));
528 ccomma
.append_expression (parse_call
);
529 ccomma
.append_expression (new
CCodeIdentifier (temp_decl
.name
));
531 // third argument: signal_id
532 ccall
.add_argument (ccomma
);
534 // fourth argument: detail
535 ccall
.add_argument (new
CCodeConstant ("0"));
536 // fifth argument: closure
537 ccall
.add_argument (new
CCodeConstant ("NULL"));
540 // third resp. sixth argument: handler
541 ccall
.add_argument (new
CCodeCastExpression ((CCodeExpression
) assignment
.right
.ccodenode
, "GCallback"));
543 if (m
.binding
== MemberBinding
.INSTANCE
) {
544 // g_signal_connect_object or g_signal_handlers_disconnect_matched
545 // or dynamic_signal_connect or dynamic_signal_disconnect
547 // fourth resp. seventh argument: object/user_data
548 if (assignment
.right is MemberAccess
) {
549 var right_ma
= (MemberAccess
) assignment
.right
;
550 if (right_ma
.inner
!= null) {
551 ccall
.add_argument ((CCodeExpression
) right_ma
.inner
.ccodenode
);
553 ccall
.add_argument (new
CCodeIdentifier ("self"));
555 } else if (assignment
.right is LambdaExpression
) {
556 ccall
.add_argument (new
CCodeIdentifier ("self"));
558 if (!disconnect
&& !(sig is DynamicSignal
)
559 && target_type_symbol
!= null && target_type_symbol
.is_subtype_of (gobject_type
)) {
560 // g_signal_connect_object
562 // fifth argument: connect_flags
563 ccall
.add_argument (new
CCodeConstant ("0"));
566 // g_signal_connect or g_signal_handlers_disconnect_matched
567 // or dynamic_signal_connect or dynamic_signal_disconnect
569 // fourth resp. seventh argument: user_data
570 ccall
.add_argument (new
CCodeConstant ("NULL"));
576 public override void visit_assignment (Assignment assignment
) {
577 if (assignment
.left
.symbol_reference is Signal
) {
578 assignment
.right
.accept (codegen
);
580 if (assignment
.left
.error
|| assignment
.right
.error
) {
581 assignment
.error
= true;
585 assignment
.ccodenode
= emit_signal_assignment (assignment
);
587 base.visit_assignment (assignment
);
591 public override void visit_member_access (MemberAccess expr
) {
592 if (expr
.symbol_reference is Signal
) {
593 expr
.accept_children (codegen
);
595 CCodeExpression pub_inst
= null;
597 if (expr
.inner
!= null) {
598 pub_inst
= (CCodeExpression
) expr
.inner
.ccodenode
;
601 var sig
= (Signal
) expr
.symbol_reference
;
602 var cl
= (TypeSymbol
) sig
.parent_symbol
;
604 if (expr
.inner is BaseAccess
&& sig
.is_virtual
) {
605 var m
= sig
.get_method_handler ();
606 var base_class
= (Class
) m
.parent_symbol
;
607 var vcast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (base_class
.get_upper_case_cname (null))));
608 vcast
.add_argument (new
CCodeIdentifier ("%s_parent_class".printf (current_class
.get_lower_case_cname (null))));
610 expr
.ccodenode
= new CCodeMemberAccess
.pointer (vcast
, m
.name
);
614 if (sig
.has_emitter
) {
615 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_%s".printf (cl
.get_lower_case_cname (null), sig
.name
)));
617 ccall
.add_argument (pub_inst
);
618 expr
.ccodenode
= ccall
;
620 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_signal_emit_by_name"));
621 ccall
.add_argument (pub_inst
);
623 ccall
.add_argument (sig
.get_canonical_cconstant ());
625 expr
.ccodenode
= ccall
;
628 base.visit_member_access (expr
);