1 /* valacodegeneratorsignal.vala
3 * Copyright (C) 2006-2007 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 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 <rasa@gmx.ch>
26 public class Vala
.CodeGenerator
{
27 private string get_marshaller_type_name (TypeReference t
) {
28 if (t
.type_parameter
!= null) {
30 } else if (t
.data_type
== null) {
33 return t
.data_type
.get_marshaller_type_name ();
37 private string get_signal_marshaller_function (Signal
! sig
, string prefix
= null) {
38 var signature
= get_signal_signature (sig
);
40 var params
= sig
.get_parameters ();
43 // FIXME remove equality check with cast in next revision
44 if (predefined_marshal_list
.lookup (signature
) != (bool) null) {
45 prefix
= "g_cclosure_marshal";
47 prefix
= "g_cclosure_user_marshal";
51 ret
= "%s_%s_".printf (prefix
, get_marshaller_type_name (sig
.return_type
));
56 foreach (FormalParameter p
in params
) {
57 ret
= "%s_%s".printf (ret
, get_marshaller_type_name (p
.type_reference
));
64 private string get_value_type_name_from_type_reference (TypeReference
! t
) {
65 if (t
.type_parameter
!= null) {
67 } else if (t
.data_type
== null) {
69 } else if (t
.data_type is Class
|| t
.data_type is Interface
) {
71 } else if (t
.data_type is Struct
) {
72 if (((Struct
) t
.data_type
).is_reference_type ()) {
75 return t
.data_type
.get_cname ();
77 } else if (t
.data_type is Enum
) {
79 } else if (t
.data_type is Flags
) {
81 } else if (t
.data_type is Array
) {
88 private string get_signal_signature (Signal
! sig
) {
90 var params
= sig
.get_parameters ();
92 signature
= "%s:".printf (get_marshaller_type_name (sig
.return_type
));
94 signature
= signature
+ "VOID";
97 foreach (FormalParameter p
in params
) {
99 signature
= signature
+ get_marshaller_type_name (p
.type_reference
);
102 signature
= "%s,%s".printf (signature
, get_marshaller_type_name (p
.type_reference
));
110 public override void visit_signal (Signal
! sig
) {
111 sig
.accept_children (this
);
114 var params
= sig
.get_parameters ();
117 /* check whether a signal with the same signature already exists for this source file (or predefined) */
118 signature
= get_signal_signature (sig
);
119 // FIXME remove equality checks with cast in next revision
120 if (predefined_marshal_list
.lookup (signature
) != (bool) null || user_marshal_list
.lookup (signature
) != (bool) null) {
124 var signal_marshaller
= new
CCodeFunction (get_signal_marshaller_function (sig
), "void");
125 signal_marshaller
.modifiers
= CCodeModifiers
.STATIC
;
127 signal_marshaller
.add_parameter (new
CCodeFormalParameter ("closure", "GClosure *"));
128 signal_marshaller
.add_parameter (new
CCodeFormalParameter ("return_value", "GValue *"));
129 signal_marshaller
.add_parameter (new
CCodeFormalParameter ("n_param_values", "guint"));
130 signal_marshaller
.add_parameter (new
CCodeFormalParameter ("param_values", "const GValue *"));
131 signal_marshaller
.add_parameter (new
CCodeFormalParameter ("invocation_hint", "gpointer"));
132 signal_marshaller
.add_parameter (new
CCodeFormalParameter ("marshal_data", "gpointer"));
134 source_signal_marshaller_declaration
.append (signal_marshaller
.copy ());
136 var marshaller_body
= new
CCodeBlock ();
138 var callback_decl
= new
CCodeFunctionDeclarator (get_signal_marshaller_function (sig
, "GMarshalFunc"));
139 callback_decl
.add_parameter (new
CCodeFormalParameter ("data1", "gpointer"));
141 foreach (FormalParameter p
in params
) {
142 callback_decl
.add_parameter (new
CCodeFormalParameter ("arg_%d".printf (n_params
), get_value_type_name_from_type_reference (p
.type_reference
)));
145 callback_decl
.add_parameter (new
CCodeFormalParameter ("data2", "gpointer"));
146 marshaller_body
.add_statement (new
CCodeTypeDefinition (get_value_type_name_from_type_reference (sig
.return_type
), callback_decl
));
148 var var_decl
= new
CCodeDeclaration (get_signal_marshaller_function (sig
, "GMarshalFunc"));
149 var_decl
.modifiers
= CCodeModifiers
.REGISTER
;
150 var_decl
.add_declarator (new
CCodeVariableDeclarator ("callback"));
151 marshaller_body
.add_statement (var_decl
);
153 var_decl
= new
CCodeDeclaration ("GCClosure *");
154 var_decl
.modifiers
= CCodeModifiers
.REGISTER
;
155 var_decl
.add_declarator (new CCodeVariableDeclarator
.with_initializer ("cc", new
CCodeCastExpression (new
CCodeIdentifier ("closure"), "GCClosure *")));
156 marshaller_body
.add_statement (var_decl
);
158 var_decl
= new
CCodeDeclaration ("gpointer");
159 var_decl
.modifiers
= CCodeModifiers
.REGISTER
;
160 var_decl
.add_declarator (new
CCodeVariableDeclarator ("data1"));
161 var_decl
.add_declarator (new
CCodeVariableDeclarator ("data2"));
162 marshaller_body
.add_statement (var_decl
);
164 CCodeFunctionCall fc
;
166 if (sig
.return_type
.data_type
!= null) {
167 var_decl
= new
CCodeDeclaration (get_value_type_name_from_type_reference (sig
.return_type
));
168 var_decl
.add_declarator (new
CCodeVariableDeclarator ("v_return"));
169 marshaller_body
.add_statement (var_decl
);
171 fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
172 fc
.add_argument (new
CCodeBinaryExpression (CCodeBinaryOperator
.INEQUALITY
, new
CCodeIdentifier ("return_value"), new
CCodeConstant ("NULL")));
173 marshaller_body
.add_statement (new
CCodeExpressionStatement (fc
));
176 fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_return_if_fail"));
177 fc
.add_argument (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, new
CCodeIdentifier ("n_param_values"), new
CCodeConstant (n_params
.to_string())));
178 marshaller_body
.add_statement (new
CCodeExpressionStatement (fc
));
180 var data
= new
CCodeMemberAccess (new
CCodeIdentifier ("closure"), "data", true);
181 var param
= new
CCodeMemberAccess (new
CCodeMemberAccess (new
CCodeIdentifier ("param_values"), "data[0]", true), "v_pointer");
182 var cond
= new
CCodeFunctionCall (new
CCodeConstant ("G_CCLOSURE_SWAP_DATA"));
183 cond
.add_argument (new
CCodeIdentifier ("closure"));
184 var true_block
= new
CCodeBlock ();
185 true_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("data1"), data
)));
186 true_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("data2"), param
)));
187 var false_block
= new
CCodeBlock ();
188 false_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("data1"), param
)));
189 false_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("data2"), data
)));
190 marshaller_body
.add_statement (new
CCodeIfStatement (cond
, true_block
, false_block
));
192 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_signal_marshaller_function (sig
, "GMarshalFunc")));
193 marshaller_body
.add_statement (new
CCodeExpressionStatement (c_assign
));
195 fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("callback"));
196 fc
.add_argument (new
CCodeIdentifier ("data1"));
198 foreach (FormalParameter p
in params
) {
199 string get_value_function
;
200 if (p
.type_reference
.type_parameter
!= null) {
201 get_value_function
= "g_value_get_pointer";
203 get_value_function
= p
.type_reference
.data_type
.get_get_value_function ();
205 var inner_fc
= new
CCodeFunctionCall (new
CCodeIdentifier (get_value_function
));
206 inner_fc
.add_argument (new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, new
CCodeIdentifier ("param_values"), new
CCodeIdentifier (i
.to_string ())));
207 fc
.add_argument (inner_fc
);
210 fc
.add_argument (new
CCodeIdentifier ("data2"));
212 if (sig
.return_type
.data_type
!= null) {
213 marshaller_body
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("v_return"), fc
)));
215 CCodeFunctionCall set_fc
;
216 if (sig
.return_type
.type_parameter
!= null) {
217 set_fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_set_pointer"));
218 } else if (sig
.return_type
.data_type is Class
|| sig
.return_type
.data_type is Interface
) {
219 set_fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_take_object"));
220 } else if (sig
.return_type
.data_type
== string_type
.data_type
) {
221 set_fc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_take_string"));
223 set_fc
= new
CCodeFunctionCall (new
CCodeIdentifier (sig
.return_type
.data_type
.get_set_value_function ()));
225 set_fc
.add_argument (new
CCodeIdentifier ("return_value"));
226 set_fc
.add_argument (new
CCodeIdentifier ("v_return"));
228 marshaller_body
.add_statement (new
CCodeExpressionStatement (set_fc
));
230 marshaller_body
.add_statement (new
CCodeExpressionStatement (fc
));
233 signal_marshaller
.block
= marshaller_body
;
235 source_signal_marshaller_definition
.append (signal_marshaller
);
236 user_marshal_list
.insert (signature
, true);