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
20 * Jürg Billeter <j@bitron.ch>
21 * Raffaele Sandrini <rasa@gmx.ch>
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
));
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
);
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
;
120 bool disconnect
= false;
122 if (a
.operator
== AssignmentOperator
.ADD
) {
123 connect_func
= "g_signal_connect_object";
125 connect_func
= "g_signal_connect";
127 } else if (a
.operator
== AssignmentOperator
.SUB
) {
128 connect_func
= "g_signal_handlers_disconnect_matched";
132 Report
.error (a
.source_reference
, "Specified compound assignment type for signals not supported.");
136 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (connect_func
));
138 if (ma
.inner
!= null) {
139 ccall
.add_argument ((CCodeExpression
) ma
.inner
.ccodenode
);
141 ccall
.add_argument (new
CCodeIdentifier ("self"));
145 ccall
.add_argument (sig
.get_canonical_cconstant ());
147 ccall
.add_argument (new
CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA"));
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"));
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
);
177 ccall
.add_argument (new
CCodeIdentifier ("self"));
179 } else if (a
.right is LambdaExpression
) {
180 ccall
.add_argument (new
CCodeIdentifier ("self"));
183 ccall
.add_argument (new
CCodeConstant ("0"));
186 ccall
.add_argument (new
CCodeConstant ("NULL"));
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
);
205 bool unref_old
= (memory_management
&& a
.left
.static_type
.takes_ownership
);
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
));
218 /* unref old value */
219 ccomma
.append_expression (get_unref_expression ((CCodeExpression
) a
.left
.ccodenode
, a
.left
.static_type
));
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
));
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
);
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
);
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"));