1 /* valaccodeassignmentmodule.vala
3 * Copyright (C) 2006-2009 Jürg Billeter
4 * Copyright (C) 2006-2008 Raffaele Sandrini
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
29 * The link between an assignment and generated code.
31 internal class Vala
.CCodeAssignmentModule
: CCodeMemberAccessModule
{
32 public CCodeAssignmentModule (CCodeGenerator codegen
, CCodeModule? next
) {
36 CCodeExpression
emit_property_assignment (Assignment assignment
) {
37 var ma
= assignment
.left as MemberAccess
;
39 var prop
= (Property
) assignment
.left
.symbol_reference
;
41 if (prop
.set_accessor
.construction
&& current_type_symbol is Class
&& current_class
.is_subtype_of (gobject_type
) && in_creation_method
) {
42 return head
.get_construct_property_assignment (prop
.get_canonical_cconstant (), prop
.property_type
, (CCodeExpression
) assignment
.right
.ccodenode
);
44 CCodeExpression cexpr
= (CCodeExpression
) assignment
.right
.ccodenode
;
46 if (!prop
.no_accessor_method
) {
47 if (prop
.property_type
.is_real_struct_type ()) {
48 cexpr
= get_address_of_expression (assignment
.right
, cexpr
);
52 if (assignment
.operator
!= AssignmentOperator
.SIMPLE
) {
53 CCodeBinaryOperator cop
;
54 if (assignment
.operator
== AssignmentOperator
.BITWISE_OR
) {
55 cop
= CCodeBinaryOperator
.BITWISE_OR
;
56 } else if (assignment
.operator
== AssignmentOperator
.BITWISE_AND
) {
57 cop
= CCodeBinaryOperator
.BITWISE_AND
;
58 } else if (assignment
.operator
== AssignmentOperator
.BITWISE_XOR
) {
59 cop
= CCodeBinaryOperator
.BITWISE_XOR
;
60 } else if (assignment
.operator
== AssignmentOperator
.ADD
) {
61 cop
= CCodeBinaryOperator
.PLUS
;
62 } else if (assignment
.operator
== AssignmentOperator
.SUB
) {
63 cop
= CCodeBinaryOperator
.MINUS
;
64 } else if (assignment
.operator
== AssignmentOperator
.MUL
) {
65 cop
= CCodeBinaryOperator
.MUL
;
66 } else if (assignment
.operator
== AssignmentOperator
.DIV
) {
67 cop
= CCodeBinaryOperator
.DIV
;
68 } else if (assignment
.operator
== AssignmentOperator
.PERCENT
) {
69 cop
= CCodeBinaryOperator
.MOD
;
70 } else if (assignment
.operator
== AssignmentOperator
.SHIFT_LEFT
) {
71 cop
= CCodeBinaryOperator
.SHIFT_LEFT
;
72 } else if (assignment
.operator
== AssignmentOperator
.SHIFT_RIGHT
) {
73 cop
= CCodeBinaryOperator
.SHIFT_RIGHT
;
75 assert_not_reached ();
77 cexpr
= new
CCodeBinaryExpression (cop
, (CCodeExpression
) get_ccodenode (assignment
.left
), cexpr
);
80 var ccall
= get_property_set_call (prop
, ma
, cexpr
);
82 // assignments are expressions, so return the current property value, except if we're sure that it can't be used
83 if (!(assignment
.parent_node is ExpressionStatement
)) {
84 var ccomma
= new
CCodeCommaExpression ();
85 ccomma
.append_expression (ccall
); // update property
86 ccomma
.append_expression ((CCodeExpression
) get_ccodenode (ma
)); // current property value
95 CCodeExpression
emit_simple_assignment (Assignment assignment
) {
96 CCodeExpression rhs
= (CCodeExpression
) assignment
.right
.ccodenode
;
97 CCodeExpression lhs
= (CCodeExpression
) get_ccodenode (assignment
.left
);
98 CCodeCommaExpression outer_ccomma
= null;
100 bool unref_old
= requires_destroy (assignment
.left
.value_type
);
102 bool instance_delegate
= false;
103 if (assignment
.left
.value_type is ArrayType
) {
104 var array_field
= assignment
.left
.symbol_reference as Field
;
105 array
= (array_field
== null || !array_field
.no_array_length
);
106 } else if (assignment
.left
.value_type is DelegateType
) {
107 var delegate_type
= (DelegateType
) assignment
.left
.value_type
;
108 instance_delegate
= delegate_type
.delegate_symbol
.has_target
;
111 if (unref_old
|| array
|| instance_delegate
) {
112 var ccomma
= new
CCodeCommaExpression ();
114 if (!is_pure_ccode_expression (lhs
)) {
115 /* Assign lhs to temp var to avoid repeating side effect */
116 outer_ccomma
= new
CCodeCommaExpression ();
118 var lhs_value_type
= assignment
.left
.value_type
.copy ();
119 string lhs_temp_name
= "_tmp%d".printf (next_temp_var_id
++);
120 var lhs_temp
= new
LocalVariable (lhs_value_type
, "*" + lhs_temp_name
);
121 temp_vars
.insert (0, lhs_temp
);
122 outer_ccomma
.append_expression (new
CCodeAssignment (get_variable_cexpression (lhs_temp_name
), new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, lhs
)));
123 lhs
= new
CCodeParenthesizedExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, get_variable_cexpression (lhs_temp_name
)));
126 var temp_decl
= get_temp_variable (assignment
.left
.value_type
);
127 temp_vars
.insert (0, temp_decl
);
128 ccomma
.append_expression (new
CCodeAssignment (get_variable_cexpression (temp_decl
.name
), rhs
));
130 /* unref old value */
131 ccomma
.append_expression (get_unref_expression (lhs
, assignment
.left
.value_type
, assignment
.left
));
135 var array_type
= (ArrayType
) assignment
.left
.value_type
;
136 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
137 var lhs_array_len
= head
.get_array_length_cexpression (assignment
.left
, dim
);
138 var rhs_array_len
= head
.get_array_length_cexpression (assignment
.right
, dim
);
139 ccomma
.append_expression (new
CCodeAssignment (lhs_array_len
, rhs_array_len
));
141 if (array_type
.rank
== 1) {
142 var array_var
= assignment
.left
.symbol_reference
;
143 if (array_var
!= null && array_var
.is_internal_symbol ()
144 && (array_var is LocalVariable
|| array_var is Field
)) {
145 var lhs_array_size
= head
.get_array_size_cexpression (assignment
.left
);
146 var rhs_array_len
= head
.get_array_length_cexpression (assignment
.left
, 1);
147 ccomma
.append_expression (new
CCodeAssignment (lhs_array_size
, rhs_array_len
));
150 } else if (instance_delegate
) {
151 var lhs_delegate_target
= get_delegate_target_cexpression (assignment
.left
);
152 var rhs_delegate_target
= get_delegate_target_cexpression (assignment
.right
);
153 ccomma
.append_expression (new
CCodeAssignment (lhs_delegate_target
, rhs_delegate_target
));
156 ccomma
.append_expression (get_variable_cexpression (temp_decl
.name
));
161 var cop
= CCodeAssignmentOperator
.SIMPLE
;
162 if (assignment
.operator
== AssignmentOperator
.BITWISE_OR
) {
163 cop
= CCodeAssignmentOperator
.BITWISE_OR
;
164 } else if (assignment
.operator
== AssignmentOperator
.BITWISE_AND
) {
165 cop
= CCodeAssignmentOperator
.BITWISE_AND
;
166 } else if (assignment
.operator
== AssignmentOperator
.BITWISE_XOR
) {
167 cop
= CCodeAssignmentOperator
.BITWISE_XOR
;
168 } else if (assignment
.operator
== AssignmentOperator
.ADD
) {
169 cop
= CCodeAssignmentOperator
.ADD
;
170 } else if (assignment
.operator
== AssignmentOperator
.SUB
) {
171 cop
= CCodeAssignmentOperator
.SUB
;
172 } else if (assignment
.operator
== AssignmentOperator
.MUL
) {
173 cop
= CCodeAssignmentOperator
.MUL
;
174 } else if (assignment
.operator
== AssignmentOperator
.DIV
) {
175 cop
= CCodeAssignmentOperator
.DIV
;
176 } else if (assignment
.operator
== AssignmentOperator
.PERCENT
) {
177 cop
= CCodeAssignmentOperator
.PERCENT
;
178 } else if (assignment
.operator
== AssignmentOperator
.SHIFT_LEFT
) {
179 cop
= CCodeAssignmentOperator
.SHIFT_LEFT
;
180 } else if (assignment
.operator
== AssignmentOperator
.SHIFT_RIGHT
) {
181 cop
= CCodeAssignmentOperator
.SHIFT_RIGHT
;
184 CCodeExpression codenode
= new
CCodeAssignment (lhs
, rhs
, cop
);
186 if (outer_ccomma
!= null) {
187 outer_ccomma
.append_expression (codenode
);
188 codenode
= outer_ccomma
;
194 public override void visit_assignment (Assignment assignment
) {
195 assignment
.right
.accept (codegen
);
197 if (assignment
.left
.error
|| assignment
.right
.error
) {
198 assignment
.error
= true;
202 if (assignment
.left
.symbol_reference is Property
) {
203 assignment
.ccodenode
= emit_property_assignment (assignment
);
205 assignment
.ccodenode
= emit_simple_assignment (assignment
);