remove obsolete ref modifier and callback keyword
[vala-lang.git] / gobject / valacodegeneratorsignal.vala
blob0fbf3dd66cba9c0d9a82cd6f24116a33b487d82e
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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
21 * Raffaele Sandrini <rasa@gmx.ch>
24 using GLib;
26 public class Vala.CodeGenerator {
27 private string get_marshaller_type_name (TypeReference t) {
28 if (t.type_parameter != null) {
29 return ("POINTER");
30 } else if (t.data_type == null) {
31 return ("VOID");
32 } else {
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);
39 string ret;
40 var params = sig.get_parameters ();
42 if (prefix == null) {
43 // FIXME remove equality check with cast in next revision
44 if (predefined_marshal_list.lookup (signature) != (bool) null) {
45 prefix = "g_cclosure_marshal";
46 } else {
47 prefix = "g_cclosure_user_marshal";
51 ret = "%s_%s_".printf (prefix, get_marshaller_type_name (sig.return_type));
53 if (params == null) {
54 ret = ret + "_VOID";
55 } else {
56 foreach (FormalParameter p in params) {
57 ret = "%s_%s".printf (ret, get_marshaller_type_name (p.type_reference));
61 return ret;
64 private string get_value_type_name_from_type_reference (TypeReference! t) {
65 if (t.type_parameter != null) {
66 return "gpointer";
67 } else if (t.data_type == null) {
68 return "void";
69 } else if (t.data_type is Class || t.data_type is Interface) {
70 return "GObject *";
71 } else if (t.data_type is Struct) {
72 if (((Struct) t.data_type).is_reference_type ()) {
73 return "gpointer";
74 } else {
75 return t.data_type.get_cname ();
77 } else if (t.data_type is Enum) {
78 return "gint";
79 } else if (t.data_type is Flags) {
80 return "guint";
81 } else if (t.data_type is Array) {
82 return "gpointer";
85 return null;
88 private string get_signal_signature (Signal! sig) {
89 string signature;
90 var params = sig.get_parameters ();
92 signature = "%s:".printf (get_marshaller_type_name (sig.return_type));
93 if (params == null) {
94 signature = signature + "VOID";
95 } else {
96 bool first = true;
97 foreach (FormalParameter p in params) {
98 if (first) {
99 signature = signature + get_marshaller_type_name (p.type_reference);
100 first = false;
101 } else {
102 signature = "%s,%s".printf (signature, get_marshaller_type_name (p.type_reference));
107 return signature;
110 public override void visit_signal (Signal! sig) {
111 sig.accept_children (this);
113 string signature;
114 var params = sig.get_parameters ();
115 int n_params, i;
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) {
121 return;
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"));
140 n_params = 1;
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)));
143 n_params++;
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"));
197 i = 1;
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";
202 } else {
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);
208 i++;
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"));
222 } else {
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));
229 } else {
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);