1 /* valadovaassignmentmodule.vala
3 * Copyright (C) 2006-2010 Jürg Billeter
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.1 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>
24 * The link between an assignment and generated code.
26 public class Vala
.DovaAssignmentModule
: DovaMemberAccessModule
{
27 CCodeExpression?
emit_simple_assignment (Assignment assignment
) {
28 CCodeExpression rhs
= get_cvalue (assignment
.right
);
29 CCodeExpression lhs
= (CCodeExpression
) get_ccodenode (assignment
.left
);
31 bool unref_old
= requires_destroy (assignment
.left
.value_type
);
34 if (!is_pure_ccode_expression (lhs
)) {
35 /* Assign lhs to temp var to avoid repeating side effect */
36 var lhs_value_type
= assignment
.left
.value_type
.copy ();
37 string lhs_temp_name
= "_tmp%d_".printf (next_temp_var_id
++);
38 var lhs_temp
= new
LocalVariable (lhs_value_type
, "*" + lhs_temp_name
);
39 emit_temp_var (lhs_temp
);
40 ccode
.add_assignment (get_variable_cexpression (lhs_temp_name
), new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, lhs
));
41 lhs
= new
CCodeParenthesizedExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, get_variable_cexpression (lhs_temp_name
)));
44 var temp_decl
= get_temp_variable (assignment
.left
.value_type
);
45 emit_temp_var (temp_decl
);
46 ccode
.add_assignment (get_variable_cexpression (temp_decl
.name
), rhs
);
49 ccode
.add_expression (get_unref_expression (lhs
, assignment
.left
.value_type
, assignment
.left
));
52 rhs
= get_variable_cexpression (temp_decl
.name
);
55 var cop
= CCodeAssignmentOperator
.SIMPLE
;
56 if (assignment
.operator
== AssignmentOperator
.BITWISE_OR
) {
57 cop
= CCodeAssignmentOperator
.BITWISE_OR
;
58 } else if (assignment
.operator
== AssignmentOperator
.BITWISE_AND
) {
59 cop
= CCodeAssignmentOperator
.BITWISE_AND
;
60 } else if (assignment
.operator
== AssignmentOperator
.BITWISE_XOR
) {
61 cop
= CCodeAssignmentOperator
.BITWISE_XOR
;
62 } else if (assignment
.operator
== AssignmentOperator
.ADD
) {
63 cop
= CCodeAssignmentOperator
.ADD
;
64 } else if (assignment
.operator
== AssignmentOperator
.SUB
) {
65 cop
= CCodeAssignmentOperator
.SUB
;
66 } else if (assignment
.operator
== AssignmentOperator
.MUL
) {
67 cop
= CCodeAssignmentOperator
.MUL
;
68 } else if (assignment
.operator
== AssignmentOperator
.DIV
) {
69 cop
= CCodeAssignmentOperator
.DIV
;
70 } else if (assignment
.operator
== AssignmentOperator
.PERCENT
) {
71 cop
= CCodeAssignmentOperator
.PERCENT
;
72 } else if (assignment
.operator
== AssignmentOperator
.SHIFT_LEFT
) {
73 cop
= CCodeAssignmentOperator
.SHIFT_LEFT
;
74 } else if (assignment
.operator
== AssignmentOperator
.SHIFT_RIGHT
) {
75 cop
= CCodeAssignmentOperator
.SHIFT_RIGHT
;
78 CCodeExpression codenode
= new
CCodeAssignment (lhs
, rhs
, cop
);
80 ccode
.add_expression (codenode
);
82 if (assignment
.parent_node is ExpressionStatement
) {
89 CCodeExpression?
emit_fixed_length_array_assignment (Assignment assignment
, ArrayType array_type
) {
90 CCodeExpression rhs
= get_cvalue (assignment
.right
);
91 CCodeExpression lhs
= (CCodeExpression
) get_ccodenode (assignment
.left
);
93 // it is necessary to use memcpy for fixed-length (stack-allocated) arrays
94 // simple assignments do not work in C
95 var sizeof_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("sizeof"));
96 sizeof_call
.add_argument (new
CCodeIdentifier (array_type
.element_type
.get_cname ()));
97 var size
= new
CCodeBinaryExpression (CCodeBinaryOperator
.MUL
, new
CCodeConstant ("%d".printf (array_type
.length
)), sizeof_call
);
98 var ccopy
= new
CCodeFunctionCall (new
CCodeIdentifier ("memcpy"));
99 ccopy
.add_argument (lhs
);
100 ccopy
.add_argument (rhs
);
101 ccopy
.add_argument (size
);
103 ccode
.add_expression (ccopy
);
105 if (assignment
.parent_node is ExpressionStatement
) {
112 public override void visit_assignment (Assignment assignment
) {
113 if (assignment
.left
.error
|| assignment
.right
.error
) {
114 assignment
.error
= true;
118 if (assignment
.left
.symbol_reference is Property
) {
119 var ma
= assignment
.left as MemberAccess
;
120 var prop
= (Property
) assignment
.left
.symbol_reference
;
122 store_property (prop
, ma
.inner
, assignment
.right
.target_value
);
124 set_cvalue (assignment
, get_ccodenode (assignment
.right
));
126 var array_type
= assignment
.left
.value_type as ArrayType
;
127 if (array_type
!= null && array_type
.fixed_length
) {
128 set_cvalue (assignment
, emit_fixed_length_array_assignment (assignment
, array_type
));
130 set_cvalue (assignment
, emit_simple_assignment (assignment
));
135 void store_variable (Variable variable
, TargetValue lvalue
, TargetValue value
, bool initializer
) {
136 if (!initializer
&& requires_destroy (variable
.variable_type
)) {
137 /* unref old value */
138 ccode
.add_expression (destroy_value (lvalue
));
141 ccode
.add_assignment (get_cvalue_ (lvalue
), get_cvalue_ (value
));
144 public override void store_local (LocalVariable local
, TargetValue value
, bool initializer
) {
145 store_variable (local
, get_local_cvalue (local
), value
, initializer
);
148 public override void store_parameter (Parameter param
, TargetValue value
) {
149 store_variable (param
, get_parameter_cvalue (param
), value
, false);
152 public override void store_field (Field field
, Expression? instance
, TargetValue value
) {
153 store_variable (field
, get_field_cvalue (field
, instance
), value
, false);