compiler: Prefix headers for set_cheader_override() if includedir is given
[vala-gnome.git] / codegen / valaccodeassignmentmodule.vala
blob76004f7856d52963585377e4b6e1b84c410d114a
1 /* valaccodeassignmentmodule.vala
3 * Copyright (C) 2006-2010 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;
27 /**
28 * The link between an assignment and generated code.
30 public class Vala.CCodeAssignmentModule : CCodeMemberAccessModule {
31 TargetValue emit_simple_assignment (Assignment assignment) {
32 Variable variable = (Variable) assignment.left.symbol_reference;
34 if (requires_destroy (assignment.left.value_type)) {
35 /* unref old value */
36 ccode.add_expression (destroy_value (assignment.left.target_value));
39 if (assignment.operator == AssignmentOperator.SIMPLE) {
40 store_value (assignment.left.target_value, assignment.right.target_value);
41 } else {
42 CCodeAssignmentOperator cop;
43 if (assignment.operator == AssignmentOperator.BITWISE_OR) {
44 cop = CCodeAssignmentOperator.BITWISE_OR;
45 } else if (assignment.operator == AssignmentOperator.BITWISE_AND) {
46 cop = CCodeAssignmentOperator.BITWISE_AND;
47 } else if (assignment.operator == AssignmentOperator.BITWISE_XOR) {
48 cop = CCodeAssignmentOperator.BITWISE_XOR;
49 } else if (assignment.operator == AssignmentOperator.ADD) {
50 cop = CCodeAssignmentOperator.ADD;
51 } else if (assignment.operator == AssignmentOperator.SUB) {
52 cop = CCodeAssignmentOperator.SUB;
53 } else if (assignment.operator == AssignmentOperator.MUL) {
54 cop = CCodeAssignmentOperator.MUL;
55 } else if (assignment.operator == AssignmentOperator.DIV) {
56 cop = CCodeAssignmentOperator.DIV;
57 } else if (assignment.operator == AssignmentOperator.PERCENT) {
58 cop = CCodeAssignmentOperator.PERCENT;
59 } else if (assignment.operator == AssignmentOperator.SHIFT_LEFT) {
60 cop = CCodeAssignmentOperator.SHIFT_LEFT;
61 } else if (assignment.operator == AssignmentOperator.SHIFT_RIGHT) {
62 cop = CCodeAssignmentOperator.SHIFT_RIGHT;
63 } else {
64 assert_not_reached ();
67 CCodeExpression codenode = new CCodeAssignment (get_cvalue (assignment.left), get_cvalue (assignment.right), cop);
68 ccode.add_expression (codenode);
71 if (assignment.left.value_type is ArrayType && (((ArrayType) assignment.left.value_type).inline_allocated)) {
72 return load_variable (variable, assignment.left.target_value);
73 } else {
74 return store_temp_value (assignment.left.target_value, assignment);
78 public override void visit_assignment (Assignment assignment) {
79 if (assignment.left.error || assignment.right.error) {
80 assignment.error = true;
81 return;
84 if (assignment.left.symbol_reference is Property) {
85 var ma = assignment.left as MemberAccess;
86 var prop = (Property) assignment.left.symbol_reference;
88 store_property (prop, ma.inner, assignment.right.target_value);
89 assignment.target_value = assignment.right.target_value;
90 } else if (assignment.left.symbol_reference is Variable && is_simple_struct_creation ((Variable) assignment.left.symbol_reference, assignment.right)) {
91 // delegate to visit_object_creation_expression
92 } else {
93 assignment.target_value = emit_simple_assignment (assignment);
97 public override void store_value (TargetValue lvalue, TargetValue value) {
98 var array_type = lvalue.value_type as ArrayType;
100 if (array_type != null && array_type.fixed_length) {
101 cfile.add_include ("string.h");
103 // it is necessary to use memcpy for fixed-length (stack-allocated) arrays
104 // simple assignments do not work in C
105 var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
106 sizeof_call.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type)));
107 var size = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, get_ccodenode (array_type.length), sizeof_call);
109 var ccopy = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
110 ccopy.add_argument (get_cvalue_ (lvalue));
111 ccopy.add_argument (get_cvalue_ (value));
112 ccopy.add_argument (size);
113 ccode.add_expression (ccopy);
115 return;
118 var cexpr = get_cvalue_ (value);
119 if (get_ctype (lvalue) != null) {
120 cexpr = new CCodeCastExpression (cexpr, get_ctype (lvalue));
123 ccode.add_assignment (get_cvalue_ (lvalue), cexpr);
125 if (array_type != null && ((GLibValue) lvalue).array_length_cvalues != null) {
126 var glib_value = (GLibValue) value;
127 if (glib_value.array_length_cvalues != null) {
128 for (int dim = 1; dim <= array_type.rank; dim++) {
129 ccode.add_assignment (get_array_length_cvalue (lvalue, dim), get_array_length_cvalue (value, dim));
131 } else if (glib_value.array_null_terminated) {
132 requires_array_length = true;
133 var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length"));
134 len_call.add_argument (get_cvalue_ (value));
136 ccode.add_assignment (get_array_length_cvalue (lvalue, 1), len_call);
137 } else {
138 for (int dim = 1; dim <= array_type.rank; dim++) {
139 ccode.add_assignment (get_array_length_cvalue (lvalue, dim), new CCodeConstant ("-1"));
143 if (array_type.rank == 1 && get_array_size_cvalue (lvalue) != null) {
144 ccode.add_assignment (get_array_size_cvalue (lvalue), get_array_length_cvalue (lvalue, 1));
148 var delegate_type = lvalue.value_type as DelegateType;
149 if (delegate_type != null && delegate_type.delegate_symbol.has_target) {
150 if (get_delegate_target_cvalue (lvalue) != null) {
151 ccode.add_assignment (get_delegate_target_cvalue (lvalue), get_delegate_target_cvalue (value));
152 var lvalue_destroy_notify = get_delegate_target_destroy_notify_cvalue (lvalue);
153 var rvalue_destroy_notify = get_delegate_target_destroy_notify_cvalue (value);
154 if (lvalue_destroy_notify != null) {
155 if (rvalue_destroy_notify != null) {
156 ccode.add_assignment (lvalue_destroy_notify, rvalue_destroy_notify);
157 } else {
158 ccode.add_assignment (lvalue_destroy_notify, new CCodeConstant ("NULL"));
165 public override void store_local (LocalVariable local, TargetValue value, bool initializer) {
166 if (!initializer && requires_destroy (local.variable_type)) {
167 /* unref old value */
168 ccode.add_expression (destroy_local (local));
171 store_value (get_local_cvalue (local), value);
174 public override void store_parameter (Parameter param, TargetValue _value, bool capturing_parameter = false) {
175 var value = _value;
177 bool capturing_parameter_in_coroutine = capturing_parameter && is_in_coroutine ();
179 var param_type = param.variable_type.copy ();
180 if (param.captured || is_in_coroutine ()) {
181 if (!param_type.value_owned && !no_implicit_copy (param_type)) {
182 // parameter value has been implicitly copied into a heap data structure
183 // treat parameter as owned
184 param_type.value_owned = true;
186 var old_coroutine = is_in_coroutine ();
187 if (old_coroutine) {
188 current_method.coroutine = false;
191 if (requires_copy (param_type) && !capturing_parameter_in_coroutine) {
192 // do not copy value when capturing parameter in coroutine
193 // as the value was already copied on coroutine initialization
194 value = copy_value (value, param);
197 if (old_coroutine) {
198 current_method.coroutine = true;
203 if (requires_destroy (param_type)) {
204 /* unref old value */
205 ccode.add_expression (destroy_parameter (param));
208 store_value (get_parameter_cvalue (param), value);
211 public override void store_field (Field field, TargetValue? instance, TargetValue value) {
212 var lvalue = get_field_cvalue (field, instance);
213 var type = lvalue.value_type;
214 if (lvalue.actual_value_type != null) {
215 type = lvalue.actual_value_type;
217 if (requires_destroy (type)) {
218 /* unref old value */
219 ccode.add_expression (destroy_field (field, instance));
222 store_value (lvalue, value);