Release 0.6.0
[vala-lang.git] / gobject / valaccodeassignmentmodule.vala
blob332bb4f034d7003a9ae1eeb93ba1f06d64191604
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
20 * Author:
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
25 using GLib;
26 using Gee;
28 /**
29 * The link between an assignment and generated code.
31 internal class Vala.CCodeAssignmentModule : CCodeMemberAccessModule {
32 public CCodeAssignmentModule (CCodeGenerator codegen, CCodeModule? next) {
33 base (codegen, 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);
43 } else {
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;
74 } else {
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
88 return ccomma;
89 } else {
90 return ccall;
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);
101 bool array = false;
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));
129 if (unref_old) {
130 /* unref old value */
131 ccomma.append_expression (get_unref_expression (lhs, assignment.left.value_type, assignment.left));
134 if (array) {
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));
158 rhs = ccomma;
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;
191 return codenode;
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;
199 return;
202 if (assignment.left.symbol_reference is Property) {
203 assignment.ccodenode = emit_property_assignment (assignment);
204 } else {
205 assignment.ccodenode = emit_simple_assignment (assignment);