remove obsolete ref modifier and callback keyword
[vala-lang.git] / gobject / valacodegeneratorassignment.vala
blob56307cd6be881d73018837cb22dd249f4adf9397
1 /* valacodegeneratorassignment.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 public override void visit_end_assignment (Assignment! a) {
28 MemberAccess ma = null;
30 if (a.left is MemberAccess) {
31 ma = (MemberAccess)a.left;
34 if (a.left.symbol_reference != null && a.left.symbol_reference.node is Property) {
35 var prop = (Property) a.left.symbol_reference.node;
37 if (current_class != null && ma.inner == null && in_creation_method) {
38 // this property is used as a construction parameter
39 var cpointer = new CCodeIdentifier ("__params_it");
41 var ccomma = new CCodeCommaExpression ();
42 // set name in array for current parameter
43 var cnamemember = new CCodeMemberAccess.pointer (cpointer, "name");
44 var cnameassign = new CCodeAssignment (cnamemember, prop.get_canonical_cconstant ());
45 ccomma.append_expression (cnameassign);
47 var gvaluearg = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess.pointer (cpointer, "value"));
49 // initialize GValue in array for current parameter
50 var cvalueinit = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init"));
51 cvalueinit.add_argument (gvaluearg);
52 cvalueinit.add_argument (new CCodeIdentifier (prop.type_reference.data_type.get_type_id ()));
53 ccomma.append_expression (cvalueinit);
55 // set GValue for current parameter
56 var cvalueset = new CCodeFunctionCall (get_value_setter_function (prop.type_reference));
57 cvalueset.add_argument (gvaluearg);
58 cvalueset.add_argument ((CCodeExpression) a.right.ccodenode);
59 ccomma.append_expression (cvalueset);
61 // move pointer to next parameter in array
62 ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, cpointer));
64 a.ccodenode = ccomma;
65 } else {
66 CCodeExpression cexpr = (CCodeExpression) a.right.ccodenode;
68 if (!prop.no_accessor_method
69 && prop.type_reference.data_type != null
70 && prop.type_reference.data_type.is_reference_type ()
71 && a.right.static_type.data_type != null
72 && prop.type_reference.data_type != a.right.static_type.data_type) {
73 /* cast is necessary */
74 var ccast = new CCodeFunctionCall (new CCodeIdentifier (prop.type_reference.data_type.get_upper_case_cname (null)));
75 ccast.add_argument (cexpr);
76 cexpr = ccast;
79 if (a.operator != AssignmentOperator.SIMPLE) {
80 CCodeBinaryOperator cop;
81 if (a.operator == AssignmentOperator.BITWISE_OR) {
82 cop = CCodeBinaryOperator.BITWISE_OR;
83 } else if (a.operator == AssignmentOperator.BITWISE_AND) {
84 cop = CCodeBinaryOperator.BITWISE_AND;
85 } else if (a.operator == AssignmentOperator.BITWISE_XOR) {
86 cop = CCodeBinaryOperator.BITWISE_XOR;
87 } else if (a.operator == AssignmentOperator.ADD) {
88 cop = CCodeBinaryOperator.PLUS;
89 } else if (a.operator == AssignmentOperator.SUB) {
90 cop = CCodeBinaryOperator.MINUS;
91 } else if (a.operator == AssignmentOperator.MUL) {
92 cop = CCodeBinaryOperator.MUL;
93 } else if (a.operator == AssignmentOperator.DIV) {
94 cop = CCodeBinaryOperator.DIV;
95 } else if (a.operator == AssignmentOperator.PERCENT) {
96 cop = CCodeBinaryOperator.MOD;
97 } else if (a.operator == AssignmentOperator.SHIFT_LEFT) {
98 cop = CCodeBinaryOperator.SHIFT_LEFT;
99 } else if (a.operator == AssignmentOperator.SHIFT_RIGHT) {
100 cop = CCodeBinaryOperator.SHIFT_RIGHT;
102 cexpr = new CCodeBinaryExpression (cop, (CCodeExpression) a.left.ccodenode, new CCodeParenthesizedExpression (cexpr));
105 var ccall = get_property_set_call (prop, ma, cexpr);
107 // assignments are expressions, so return the current property value
108 var ccomma = new CCodeCommaExpression ();
109 ccomma.append_expression (ccall); // update property
110 ccomma.append_expression ((CCodeExpression) ma.ccodenode); // current property value
112 a.ccodenode = ccomma;
114 } else if (a.left.symbol_reference != null && a.left.symbol_reference.node is Signal) {
115 var sig = (Signal) a.left.symbol_reference.node;
117 var m = (Method) a.right.symbol_reference.node;
119 string connect_func;
120 bool disconnect = false;
122 if (a.operator == AssignmentOperator.ADD) {
123 connect_func = "g_signal_connect_object";
124 if (!m.instance) {
125 connect_func = "g_signal_connect";
127 } else if (a.operator == AssignmentOperator.SUB) {
128 connect_func = "g_signal_handlers_disconnect_matched";
129 disconnect = true;
130 } else {
131 a.error = true;
132 Report.error (a.source_reference, "Specified compound assignment type for signals not supported.");
133 return;
136 var ccall = new CCodeFunctionCall (new CCodeIdentifier (connect_func));
138 if (ma.inner != null) {
139 ccall.add_argument ((CCodeExpression) ma.inner.ccodenode);
140 } else {
141 ccall.add_argument (new CCodeIdentifier ("self"));
144 if (!disconnect) {
145 ccall.add_argument (sig.get_canonical_cconstant ());
146 } else {
147 ccall.add_argument (new CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA"));
149 // get signal id
150 var ccomma = new CCodeCommaExpression ();
151 var temp_decl = get_temp_variable_declarator (uint_type);
152 temp_vars.prepend (temp_decl);
153 var parse_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_parse_name"));
154 parse_call.add_argument (sig.get_canonical_cconstant ());
155 var decl_type = (DataType) sig.symbol.parent_symbol.node;
156 parse_call.add_argument (new CCodeIdentifier (decl_type.get_type_id ()));
157 parse_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_decl.name)));
158 parse_call.add_argument (new CCodeConstant ("NULL"));
159 parse_call.add_argument (new CCodeConstant ("FALSE"));
160 ccomma.append_expression (parse_call);
161 ccomma.append_expression (new CCodeIdentifier (temp_decl.name));
163 ccall.add_argument (ccomma);
165 ccall.add_argument (new CCodeConstant ("0"));
166 ccall.add_argument (new CCodeConstant ("NULL"));
169 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (m.get_cname ()), "GCallback"));
171 if (m.instance) {
172 if (a.right is MemberAccess) {
173 var right_ma = (MemberAccess) a.right;
174 if (right_ma.inner != null) {
175 ccall.add_argument ((CCodeExpression) right_ma.inner.ccodenode);
176 } else {
177 ccall.add_argument (new CCodeIdentifier ("self"));
179 } else if (a.right is LambdaExpression) {
180 ccall.add_argument (new CCodeIdentifier ("self"));
182 if (!disconnect) {
183 ccall.add_argument (new CCodeConstant ("0"));
185 } else {
186 ccall.add_argument (new CCodeConstant ("NULL"));
189 a.ccodenode = ccall;
190 } else {
191 /* explicitly use strong reference as ccast gets
192 * unrefed at end of inner block
194 CCodeExpression rhs = (CCodeExpression) a.right.ccodenode;
196 if (a.left.static_type.data_type != null
197 && a.right.static_type.data_type != null
198 && a.left.static_type.data_type.is_reference_type ()
199 && a.right.static_type.data_type != a.left.static_type.data_type) {
200 var ccast = new CCodeFunctionCall (new CCodeIdentifier (a.left.static_type.data_type.get_upper_case_cname (null)));
201 ccast.add_argument (rhs);
202 rhs = ccast;
205 bool unref_old = (memory_management && a.left.static_type.takes_ownership);
206 bool array = false;
207 if (a.left.static_type.data_type is Array) {
208 array = !(get_array_length_cexpression (a.left, 1) is CCodeConstant);
211 if (unref_old || array) {
212 var ccomma = new CCodeCommaExpression ();
214 var temp_decl = get_temp_variable_declarator (a.left.static_type);
215 temp_vars.prepend (temp_decl);
216 ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_decl.name), rhs));
217 if (unref_old) {
218 /* unref old value */
219 ccomma.append_expression (get_unref_expression ((CCodeExpression) a.left.ccodenode, a.left.static_type));
222 if (array) {
223 var lhs_array_len = get_array_length_cexpression (a.left, 1);
224 var rhs_array_len = get_array_length_cexpression (a.right, 1);
225 ccomma.append_expression (new CCodeAssignment (lhs_array_len, rhs_array_len));
228 ccomma.append_expression (new CCodeIdentifier (temp_decl.name));
230 rhs = ccomma;
233 var cop = CCodeAssignmentOperator.SIMPLE;
234 if (a.operator == AssignmentOperator.BITWISE_OR) {
235 cop = CCodeAssignmentOperator.BITWISE_OR;
236 } else if (a.operator == AssignmentOperator.BITWISE_AND) {
237 cop = CCodeAssignmentOperator.BITWISE_AND;
238 } else if (a.operator == AssignmentOperator.BITWISE_XOR) {
239 cop = CCodeAssignmentOperator.BITWISE_XOR;
240 } else if (a.operator == AssignmentOperator.ADD) {
241 cop = CCodeAssignmentOperator.ADD;
242 } else if (a.operator == AssignmentOperator.SUB) {
243 cop = CCodeAssignmentOperator.SUB;
244 } else if (a.operator == AssignmentOperator.MUL) {
245 cop = CCodeAssignmentOperator.MUL;
246 } else if (a.operator == AssignmentOperator.DIV) {
247 cop = CCodeAssignmentOperator.DIV;
248 } else if (a.operator == AssignmentOperator.PERCENT) {
249 cop = CCodeAssignmentOperator.PERCENT;
250 } else if (a.operator == AssignmentOperator.SHIFT_LEFT) {
251 cop = CCodeAssignmentOperator.SHIFT_LEFT;
252 } else if (a.operator == AssignmentOperator.SHIFT_RIGHT) {
253 cop = CCodeAssignmentOperator.SHIFT_RIGHT;
256 a.ccodenode = new CCodeAssignment ((CCodeExpression) a.left.ccodenode, rhs, cop);
260 private CCodeFunctionCall get_property_set_call (Property! prop, MemberAccess! ma, CCodeExpression! cexpr) {
261 var cl = (Class) prop.symbol.parent_symbol.node;
262 var set_func = "g_object_set";
264 var base_property = prop;
265 if (!prop.no_accessor_method) {
266 if (prop.base_property != null) {
267 base_property = prop.base_property;
268 } else if (prop.base_interface_property != null) {
269 base_property = prop.base_interface_property;
271 var base_property_type = (DataType) base_property.symbol.parent_symbol.node;
272 set_func = "%s_set_%s".printf (base_property_type.get_lower_case_cname (null), base_property.name);
275 var ccall = new CCodeFunctionCall (new CCodeIdentifier (set_func));
277 /* target instance is first argument */
278 CCodeExpression instance;
279 var req_cast = false;
281 if (ma.inner == null) {
282 instance = new CCodeIdentifier ("self");
283 /* require casts for inherited properties */
284 req_cast = (base_property.symbol.parent_symbol != current_type_symbol);
285 } else {
286 instance = (CCodeExpression) ma.inner.ccodenode;
287 /* require casts if the type of the used instance is
288 * different than the type which declared the property */
289 req_cast = base_property.symbol.parent_symbol.node != ma.inner.static_type.data_type;
292 if (req_cast && ((DataType) prop.symbol.parent_symbol.node).is_reference_type ()) {
293 var ccast = new CCodeFunctionCall (new CCodeIdentifier (((DataType) base_property.symbol.parent_symbol.node).get_upper_case_cname (null)));
294 ccast.add_argument (instance);
295 instance = ccast;
298 ccall.add_argument (instance);
300 if (prop.no_accessor_method) {
301 /* property name is second argument of g_object_set */
302 ccall.add_argument (prop.get_canonical_cconstant ());
305 ccall.add_argument (cexpr);
307 if (prop.no_accessor_method) {
308 ccall.add_argument (new CCodeConstant ("NULL"));
311 return ccall;