1 /* valadovavaluemodule.vala
3 * Copyright (C) 2009-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>
23 public class Vala
.DovaValueModule
: DovaObjectModule
{
24 public override void visit_creation_method (CreationMethod m
) {
25 if (current_type_symbol is Class
&&
26 (current_class
.base_class
== null ||
27 current_class
.base_class
.get_full_name () != "Dova.Value")) {
28 base.visit_creation_method (m
);
35 public override void generate_struct_declaration (Struct st
, CCodeFile decl_space
) {
36 base.generate_struct_declaration (st
, decl_space
);
38 if (add_symbol_declaration (decl_space
, st
, st
.get_copy_function ())) {
42 generate_class_declaration (type_class
, decl_space
);
44 var type_fun
= new
CCodeFunction ("%s_type_get".printf (st
.get_lower_case_cname ()), "DovaType *");
45 if (st
.is_internal_symbol ()) {
46 type_fun
.modifiers
= CCodeModifiers
.STATIC
;
48 decl_space
.add_function_declaration (type_fun
);
50 var type_init_fun
= new
CCodeFunction ("%s_type_init".printf (st
.get_lower_case_cname ()));
51 type_init_fun
.add_parameter (new
CCodeParameter ("type", "DovaType *"));
52 if (st
.is_internal_symbol ()) {
53 type_init_fun
.modifiers
= CCodeModifiers
.STATIC
;
55 decl_space
.add_function_declaration (type_init_fun
);
57 var function
= new
CCodeFunction (st
.get_copy_function (), "void");
58 if (st
.is_internal_symbol ()) {
59 function
.modifiers
= CCodeModifiers
.STATIC
;
62 function
.add_parameter (new
CCodeParameter ("dest", st
.get_cname () + "*"));
63 function
.add_parameter (new
CCodeParameter ("dest_index", "intptr_t"));
64 function
.add_parameter (new
CCodeParameter ("src", st
.get_cname () + "*"));
65 function
.add_parameter (new
CCodeParameter ("src_index", "intptr_t"));
67 decl_space
.add_function_declaration (function
);
70 public override void visit_struct (Struct st
) {
71 base.visit_struct (st
);
73 var cdecl
= new
CCodeDeclaration ("intptr_t");
74 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_%s_object_offset".printf (st
.get_lower_case_cname ()), new
CCodeConstant ("0")));
75 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
76 cfile
.add_type_member_declaration (cdecl
);
78 string macro
= "((%s *) (((char *) o) + _%s_object_offset))".printf (st
.get_cname (), st
.get_lower_case_cname ());
79 cfile
.add_type_member_declaration (new
CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (st
.get_upper_case_cname (null)), macro
));
82 cdecl
= new
CCodeDeclaration ("DovaType *");
83 cdecl
.add_declarator (new
CCodeVariableDeclarator ("%s_type".printf (st
.get_lower_case_cname ()), new
CCodeConstant ("NULL")));
84 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
85 cfile
.add_type_member_declaration (cdecl
);
87 var type_fun
= new
CCodeFunction ("%s_type_get".printf (st
.get_lower_case_cname ()), "DovaType *");
88 type_fun
.block
= new
CCodeBlock ();
90 var type_init_block
= new
CCodeBlock ();
92 generate_method_declaration ((Method
) object_class
.scope
.lookup ("alloc"), cfile
);
93 generate_property_accessor_declaration (((Property
) type_class
.scope
.lookup ("base_type")).get_accessor
, cfile
);
94 generate_property_accessor_declaration (((Property
) type_class
.scope
.lookup ("base_type")).set_accessor
, cfile
);
95 generate_property_accessor_declaration (((Property
) type_class
.scope
.lookup ("object_size")).get_accessor
, cfile
);
96 generate_property_accessor_declaration (((Property
) type_class
.scope
.lookup ("object_size")).set_accessor
, cfile
);
97 generate_property_accessor_declaration (((Property
) type_class
.scope
.lookup ("type_size")).get_accessor
, cfile
);
98 generate_property_accessor_declaration (((Property
) type_class
.scope
.lookup ("type_size")).set_accessor
, cfile
);
99 generate_property_accessor_declaration (((Property
) type_class
.scope
.lookup ("value_size")).set_accessor
, cfile
);
101 generate_class_declaration ((Class
) context
.root
.scope
.lookup ("Dova").scope
.lookup ("Value"), cfile
);
103 var base_type
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_value_type_get"));
105 var base_type_size
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_get_type_size"));
106 base_type_size
.add_argument (base_type
);
108 var calloc_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("calloc"));
109 calloc_call
.add_argument (new
CCodeConstant ("1"));
110 calloc_call
.add_argument (base_type_size
);
112 type_init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ())), calloc_call
)));
114 generate_class_declaration ((Class
) object_class
, cfile
);
116 type_init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeCastExpression (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ())), "DovaObject *"), "type"), new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_type_get")))));
118 var set_base_type
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_base_type"));
119 set_base_type
.add_argument (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ())));
120 set_base_type
.add_argument (base_type
);
121 type_init_block
.add_statement (new
CCodeExpressionStatement (set_base_type
));
123 var base_size
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_get_object_size"));
124 base_size
.add_argument (base_type
);
126 type_init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_%s_object_offset".printf (st
.get_lower_case_cname ())), base_size
)));
128 var sizeof_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("sizeof"));
129 sizeof_call
.add_argument (new
CCodeIdentifier (st
.get_cname ()));
130 var set_size
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_object_size"));
131 set_size
.add_argument (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ())));
132 set_size
.add_argument (new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, base_size
, sizeof_call
));
133 type_init_block
.add_statement (new
CCodeExpressionStatement (set_size
));
135 set_size
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_value_size"));
136 set_size
.add_argument (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ())));
137 set_size
.add_argument (sizeof_call
);
138 type_init_block
.add_statement (new
CCodeExpressionStatement (set_size
));
140 set_size
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_type_size"));
141 set_size
.add_argument (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ())));
142 set_size
.add_argument (base_type_size
);
143 type_init_block
.add_statement (new
CCodeExpressionStatement (set_size
));
145 var type_init_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_type_init".printf (st
.get_lower_case_cname ())));
146 type_init_call
.add_argument (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ())));
147 type_init_block
.add_statement (new
CCodeExpressionStatement (type_init_call
));
149 // workaround: set value_size again as it is currently overwritten by dova_object_type_init
150 set_size
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_value_size"));
151 set_size
.add_argument (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ())));
152 set_size
.add_argument (sizeof_call
);
153 type_init_block
.add_statement (new
CCodeExpressionStatement (set_size
));
155 type_fun
.block
.add_statement (new
CCodeIfStatement (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ()))), type_init_block
));
157 type_fun
.block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("%s_type".printf (st
.get_lower_case_cname ()))));
159 cfile
.add_function (type_fun
);
161 var type_init_fun
= new
CCodeFunction ("%s_type_init".printf (st
.get_lower_case_cname ()));
162 type_init_fun
.add_parameter (new
CCodeParameter ("type", "DovaType *"));
163 type_init_fun
.block
= new
CCodeBlock ();
165 type_init_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_value_type_init"));
166 type_init_call
.add_argument (new
CCodeIdentifier ("type"));
167 type_init_fun
.block
.add_statement (new
CCodeExpressionStatement (type_init_call
));
169 declare_set_value_copy_function (cfile
);
171 var value_copy_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_value_copy"));
172 value_copy_call
.add_argument (new
CCodeIdentifier ("type"));
173 value_copy_call
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("%s_copy".printf (st
.get_lower_case_cname ())), "void (*)(void *, intptr_t, void *, intptr_t)"));
174 type_init_fun
.block
.add_statement (new
CCodeExpressionStatement (value_copy_call
));
176 if (st
.scope
.lookup ("equals") is Method
) {
177 var value_equals_fun
= new
CCodeFunction ("%s_value_equals".printf (st
.get_lower_case_cname ()), "bool");
178 value_equals_fun
.modifiers
= CCodeModifiers
.STATIC
;
179 value_equals_fun
.add_parameter (new
CCodeParameter ("value", st
.get_cname () + "*"));
180 value_equals_fun
.add_parameter (new
CCodeParameter ("value_index", "intptr_t"));
181 value_equals_fun
.add_parameter (new
CCodeParameter ("other", st
.get_cname () + "*"));
182 value_equals_fun
.add_parameter (new
CCodeParameter ("other_index", "intptr_t"));
183 value_equals_fun
.block
= new
CCodeBlock ();
184 var val
= new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, new
CCodeIdentifier ("value"), new
CCodeIdentifier ("value_index"));
185 var other
= new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, new
CCodeIdentifier ("other"), new
CCodeIdentifier ("other_index"));
186 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_equals".printf (st
.get_lower_case_cname ())));
187 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, val
));
188 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, other
));
189 value_equals_fun
.block
.add_statement (new
CCodeReturnStatement (ccall
));
190 cfile
.add_function (value_equals_fun
);
192 declare_set_value_equals_function (cfile
);
194 var value_equals_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_value_equals"));
195 value_equals_call
.add_argument (new
CCodeIdentifier ("type"));
196 value_equals_call
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("%s_value_equals".printf (st
.get_lower_case_cname ())), "bool (*)(void *, intptr_t, void *, intptr_t)"));
197 type_init_fun
.block
.add_statement (new
CCodeExpressionStatement (value_equals_call
));
200 if (st
.scope
.lookup ("hash") is Method
) {
201 var value_hash_fun
= new
CCodeFunction ("%s_value_hash".printf (st
.get_lower_case_cname ()), "uintptr_t");
202 value_hash_fun
.modifiers
= CCodeModifiers
.STATIC
;
203 value_hash_fun
.add_parameter (new
CCodeParameter ("value", st
.get_cname () + "*"));
204 value_hash_fun
.add_parameter (new
CCodeParameter ("value_index", "intptr_t"));
205 value_hash_fun
.block
= new
CCodeBlock ();
206 var val
= new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, new
CCodeIdentifier ("value"), new
CCodeIdentifier ("value_index"));
207 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_hash".printf (st
.get_lower_case_cname ())));
208 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, val
));
209 value_hash_fun
.block
.add_statement (new
CCodeReturnStatement (ccall
));
210 cfile
.add_function (value_hash_fun
);
212 declare_set_value_hash_function (cfile
);
214 var value_hash_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_value_hash"));
215 value_hash_call
.add_argument (new
CCodeIdentifier ("type"));
216 value_hash_call
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("%s_value_hash".printf (st
.get_lower_case_cname ())), "uintptr_t (*)(void *, intptr_t)"));
217 type_init_fun
.block
.add_statement (new
CCodeExpressionStatement (value_hash_call
));
220 // generate method to box values
221 var value_to_any_fun
= new
CCodeFunction ("%s_value_to_any".printf (st
.get_lower_case_cname ()), "DovaObject*");
222 value_to_any_fun
.modifiers
= CCodeModifiers
.STATIC
;
223 value_to_any_fun
.add_parameter (new
CCodeParameter ("value", "void *"));
224 value_to_any_fun
.add_parameter (new
CCodeParameter ("value_index", "intptr_t"));
225 value_to_any_fun
.block
= new
CCodeBlock ();
226 var alloc_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_object_alloc"));
227 alloc_call
.add_argument (new
CCodeFunctionCall (new
CCodeIdentifier ("%s_type_get".printf (st
.get_lower_case_cname ()))));
228 cdecl
= new
CCodeDeclaration ("DovaObject *");
229 cdecl
.add_declarator (new
CCodeVariableDeclarator ("result", alloc_call
));
230 value_to_any_fun
.block
.add_statement (cdecl
);
231 var priv_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_PRIVATE".printf (st
.get_upper_case_cname (null))));
232 priv_call
.add_argument (new
CCodeIdentifier ("result"));
233 var copy_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_copy".printf (st
.get_lower_case_cname ())));
234 copy_call
.add_argument (priv_call
);
235 copy_call
.add_argument (new
CCodeConstant ("0"));
236 copy_call
.add_argument (new
CCodeIdentifier ("value"));
237 copy_call
.add_argument (new
CCodeIdentifier ("value_index"));
238 value_to_any_fun
.block
.add_statement (new
CCodeExpressionStatement (copy_call
));
239 value_to_any_fun
.block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("result")));
240 cfile
.add_function (value_to_any_fun
);
242 declare_set_value_to_any_function (cfile
);
244 var value_to_any_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_value_to_any"));
245 value_to_any_call
.add_argument (new
CCodeIdentifier ("type"));
246 value_to_any_call
.add_argument (new
CCodeIdentifier ("%s_value_to_any".printf (st
.get_lower_case_cname ())));
247 type_init_fun
.block
.add_statement (new
CCodeExpressionStatement (value_to_any_call
));
249 // generate method to unbox values
250 var value_from_any_fun
= new
CCodeFunction ("%s_value_from_any".printf (st
.get_lower_case_cname ()));
251 value_from_any_fun
.modifiers
= CCodeModifiers
.STATIC
;
252 value_from_any_fun
.add_parameter (new
CCodeParameter ("any_", "any *"));
253 value_from_any_fun
.add_parameter (new
CCodeParameter ("value", st
.get_cname () + "*"));
254 value_from_any_fun
.add_parameter (new
CCodeParameter ("value_index", "intptr_t"));
255 value_from_any_fun
.block
= new
CCodeBlock ();
256 priv_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_PRIVATE".printf (st
.get_upper_case_cname (null))));
257 priv_call
.add_argument (new
CCodeIdentifier ("any_"));
258 copy_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_copy".printf (st
.get_lower_case_cname ())));
259 copy_call
.add_argument (new
CCodeIdentifier ("value"));
260 copy_call
.add_argument (new
CCodeIdentifier ("value_index"));
261 copy_call
.add_argument (priv_call
);
262 copy_call
.add_argument (new
CCodeConstant ("0"));
263 value_from_any_fun
.block
.add_statement (new
CCodeExpressionStatement (copy_call
));
264 cfile
.add_function (value_from_any_fun
);
266 declare_set_value_from_any_function (cfile
);
268 var value_from_any_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_set_value_from_any"));
269 value_from_any_call
.add_argument (new
CCodeIdentifier ("type"));
270 value_from_any_call
.add_argument (new
CCodeIdentifier ("%s_value_from_any".printf (st
.get_lower_case_cname ())));
271 type_init_fun
.block
.add_statement (new
CCodeExpressionStatement (value_from_any_call
));
273 cfile
.add_function (type_init_fun
);
275 add_struct_copy_function (st
);
278 void add_struct_copy_function (Struct st
) {
279 var function
= new
CCodeFunction (st
.get_copy_function (), "void");
280 if (st
.is_internal_symbol ()) {
281 function
.modifiers
= CCodeModifiers
.STATIC
;
284 function
.add_parameter (new
CCodeParameter ("dest", st
.get_cname () + "*"));
285 function
.add_parameter (new
CCodeParameter ("dest_index", "intptr_t"));
286 function
.add_parameter (new
CCodeParameter ("src", st
.get_cname () + "*"));
287 function
.add_parameter (new
CCodeParameter ("src_index", "intptr_t"));
289 var cblock
= new
CCodeBlock ();
290 var cfrag
= new
CCodeFragment ();
291 cblock
.add_statement (cfrag
);
293 var dest
= new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, new
CCodeIdentifier ("dest"), new
CCodeIdentifier ("dest_index"));
294 var src
= new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, new
CCodeIdentifier ("src"), new
CCodeIdentifier ("src_index"));
296 foreach (var f
in st
.get_fields ()) {
297 if (f
.binding
== MemberBinding
.INSTANCE
) {
298 var field
= new CCodeMemberAccess
.pointer (dest
, f
.name
);
300 var array_type
= f
.variable_type as ArrayType
;
301 if (array_type
!= null && array_type
.fixed_length
) {
302 for (int i
= 0; i
< array_type
.length
; i
++) {
303 var element
= new
CCodeElementAccess (field
, new
CCodeConstant (i
.to_string ()));
305 if (requires_destroy (array_type
.element_type
)) {
306 cblock
.add_statement (new
CCodeExpressionStatement (get_unref_expression (element
, array_type
.element_type
)));
312 if (requires_destroy (f
.variable_type
)) {
313 var this_access
= new MemberAccess
.simple ("this");
314 this_access
.value_type
= get_data_type_for_symbol ((TypeSymbol
) f
.parent_symbol
);
315 set_cvalue (this_access
, new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, dest
));
316 var ma
= new
MemberAccess (this_access
, f
.name
);
317 ma
.symbol_reference
= f
;
318 ma
.value_type
= f
.variable_type
.copy ();
319 cblock
.add_statement (new
CCodeExpressionStatement (get_unref_expression (field
, f
.variable_type
, ma
)));
324 var copy_block
= new
CCodeBlock ();
326 if (st
.get_fields ().size
== 0) {
327 copy_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, dest
), new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, src
))));
329 foreach (var f
in st
.get_fields ()) {
330 if (f
.binding
== MemberBinding
.INSTANCE
) {
331 CCodeExpression copy
= new CCodeMemberAccess
.pointer (src
, f
.name
);
332 var dest_field
= new CCodeMemberAccess
.pointer (dest
, f
.name
);
334 var array_type
= f
.variable_type as ArrayType
;
335 if (array_type
!= null && array_type
.fixed_length
) {
336 for (int i
= 0; i
< array_type
.length
; i
++) {
337 CCodeExpression copy_element
= new
CCodeElementAccess (copy
, new
CCodeConstant (i
.to_string ()));
338 var dest_field_element
= new
CCodeElementAccess (dest_field
, new
CCodeConstant (i
.to_string ()));
340 if (requires_copy (array_type
.element_type
)) {
341 copy_element
= get_ref_cexpression (array_type
.element_type
, copy_element
, null, f
);
344 copy_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (dest_field_element
, copy_element
)));
349 if (requires_copy (f
.variable_type
)) {
350 var this_access
= new MemberAccess
.simple ("this");
351 this_access
.value_type
= get_data_type_for_symbol ((TypeSymbol
) f
.parent_symbol
);
352 set_cvalue (this_access
, new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, src
));
353 var ma
= new
MemberAccess (this_access
, f
.name
);
354 ma
.symbol_reference
= f
;
355 copy
= get_ref_cexpression (f
.variable_type
, copy
, ma
, f
);
358 copy_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (dest_field
, copy
)));
363 cblock
.add_statement (new
CCodeIfStatement (new
CCodeIdentifier ("src"), copy_block
));
365 function
.block
= cblock
;
367 cfile
.add_function (function
);
370 public override void visit_assignment (Assignment assignment
) {
371 var generic_type
= assignment
.left
.value_type as GenericType
;
372 if (generic_type
== null) {
373 base.visit_assignment (assignment
);
377 var dest
= assignment
.left
;
378 CCodeExpression cdest
;
379 CCodeExpression dest_index
= new
CCodeConstant ("0");
380 var src
= assignment
.right
;
381 CCodeExpression csrc
;
382 CCodeExpression src_index
= new
CCodeConstant ("0");
384 if (src is NullLiteral
) {
386 set_cvalue (assignment
, new
CCodeConstant ("0"));
390 var dest_ea
= dest as ElementAccess
;
391 var src_ea
= src as ElementAccess
;
393 if (dest_ea
!= null) {
394 dest
= dest_ea
.container
;
396 var array_type
= dest
.value_type as ArrayType
;
397 if (array_type
!= null && !array_type
.inline_allocated
) {
398 generate_property_accessor_declaration (((Property
) array_class
.scope
.lookup ("data")).get_accessor
, cfile
);
400 var data_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_array_get_data"));
401 data_call
.add_argument ((CCodeExpression
) get_ccodenode (dest
));
404 cdest
= (CCodeExpression
) get_ccodenode (dest
);
406 dest_index
= (CCodeExpression
) get_ccodenode (dest_ea
.get_indices ().get (0));
408 cdest
= (CCodeExpression
) get_ccodenode (dest
);
411 if (src_ea
!= null) {
412 src
= src_ea
.container
;
414 var array_type
= src
.value_type as ArrayType
;
415 if (array_type
!= null && !array_type
.inline_allocated
) {
416 generate_property_accessor_declaration (((Property
) array_class
.scope
.lookup ("data")).get_accessor
, cfile
);
418 var data_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_array_get_data"));
419 data_call
.add_argument ((CCodeExpression
) get_ccodenode (src
));
422 csrc
= (CCodeExpression
) get_ccodenode (src
);
424 src_index
= (CCodeExpression
) get_ccodenode (src_ea
.get_indices ().get (0));
426 csrc
= (CCodeExpression
) get_ccodenode (src
);
429 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_value_copy"));
430 if (generic_type
.type_parameter
.parent_symbol is TypeSymbol
) {
432 ccall
.add_argument (new CCodeMemberAccess
.pointer (get_type_private_from_type ((ObjectTypeSymbol
) generic_type
.type_parameter
.parent_symbol
, new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("this"), "type")), "%s_type".printf (generic_type
.type_parameter
.name
.down ())));
435 ccall
.add_argument (new
CCodeIdentifier ("%s_type".printf (generic_type
.type_parameter
.name
.down ())));
437 ccall
.add_argument (cdest
);
438 ccall
.add_argument (dest_index
);
439 ccall
.add_argument (csrc
);
440 ccall
.add_argument (src_index
);
441 set_cvalue (assignment
, ccall
);
444 public override void visit_binary_expression (BinaryExpression expr
) {
445 var generic_type
= expr
.left
.value_type as GenericType
;
446 if (generic_type
== null) {
447 base.visit_binary_expression (expr
);
451 CCodeExpression cleft
;
452 CCodeExpression left_index
= new
CCodeConstant ("0");
453 CCodeExpression cright
;
454 CCodeExpression right_index
= new
CCodeConstant ("0");
456 var left_ea
= expr
.left as ElementAccess
;
457 var right_ea
= expr
.right as ElementAccess
;
459 if (left_ea
!= null) {
460 generate_property_accessor_declaration (((Property
) array_class
.scope
.lookup ("data")).get_accessor
, cfile
);
462 var data_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_array_get_data"));
463 data_call
.add_argument ((CCodeExpression
) get_ccodenode (left_ea
.container
));
465 left_index
= (CCodeExpression
) get_ccodenode (left_ea
.get_indices ().get (0));
467 cleft
= (CCodeExpression
) get_ccodenode (expr
.left
);
470 if (right_ea
!= null) {
471 generate_property_accessor_declaration (((Property
) array_class
.scope
.lookup ("data")).get_accessor
, cfile
);
473 var data_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_array_get_data"));
474 data_call
.add_argument ((CCodeExpression
) get_ccodenode (right_ea
.container
));
476 right_index
= (CCodeExpression
) get_ccodenode (right_ea
.get_indices ().get (0));
478 cright
= (CCodeExpression
) get_ccodenode (expr
.right
);
481 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_value_equals"));
482 ccall
.add_argument (get_type_id_expression (generic_type
));
483 ccall
.add_argument (cleft
);
484 ccall
.add_argument (left_index
);
485 ccall
.add_argument (cright
);
486 ccall
.add_argument (right_index
);
488 if (expr
.operator
== BinaryOperator
.EQUALITY
) {
489 set_cvalue (expr
, ccall
);
491 set_cvalue (expr
, new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, ccall
));
495 public override void visit_method_call (MethodCall expr
) {
496 var ma
= expr
.call as MemberAccess
;
497 if (ma
== null || ma
.inner
== null || !(ma
.inner
.value_type is GenericType
)) {
498 base.visit_method_call (expr
);
502 // handle method calls on generic types
504 expr
.accept_children (this
);
506 if (ma
.member_name
== "hash") {
508 CCodeExpression cval
;
509 CCodeExpression val_index
= new
CCodeConstant ("0");
511 var val_ea
= val as ElementAccess
;
512 if (val_ea
!= null) {
513 val
= val_ea
.container
;
515 generate_property_accessor_declaration (((Property
) array_class
.scope
.lookup ("data")).get_accessor
, cfile
);
517 var data_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_array_get_data"));
518 data_call
.add_argument ((CCodeExpression
) get_ccodenode (val
));
520 val_index
= (CCodeExpression
) get_ccodenode (val_ea
.get_indices ().get (0));
522 cval
= (CCodeExpression
) get_ccodenode (val
);
525 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_type_value_hash"));
526 ccall
.add_argument (get_type_id_expression (ma
.inner
.value_type
));
527 ccall
.add_argument (cval
);
528 ccall
.add_argument (val_index
);
530 set_cvalue (expr
, ccall
);
534 public override void visit_list_literal (ListLiteral expr
) {
535 var ce
= new
CCodeCommaExpression ();
536 int length
= expr
.get_expressions ().size
;
539 ce
.append_expression (new
CCodeConstant ("NULL"));
541 var array_type
= new
ArrayType (expr
.element_type
, 1, expr
.source_reference
);
542 array_type
.inline_allocated
= true;
543 array_type
.fixed_length
= true;
544 array_type
.length
= length
;
546 var temp_var
= get_temp_variable (array_type
, true, expr
);
547 var name_cnode
= get_variable_cexpression (temp_var
.name
);
549 emit_temp_var (temp_var
);
552 foreach (Expression e
in expr
.get_expressions ()) {
553 ce
.append_expression (new
CCodeAssignment (new
CCodeElementAccess (name_cnode
, new
CCodeConstant (i
.to_string ())), get_cvalue (e
)));
557 ce
.append_expression (name_cnode
);
560 var list_creation
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_list_new"));
561 list_creation
.add_argument (get_type_id_expression (expr
.element_type
));
562 list_creation
.add_argument (new
CCodeConstant (length
.to_string ()));
563 list_creation
.add_argument (ce
);
565 set_cvalue (expr
, list_creation
);
568 public override void visit_set_literal (SetLiteral expr
) {
569 var ce
= new
CCodeCommaExpression ();
570 int length
= expr
.get_expressions ().size
;
573 ce
.append_expression (new
CCodeConstant ("NULL"));
575 var array_type
= new
ArrayType (expr
.element_type
, 1, expr
.source_reference
);
576 array_type
.inline_allocated
= true;
577 array_type
.fixed_length
= true;
578 array_type
.length
= length
;
580 var temp_var
= get_temp_variable (array_type
, true, expr
);
581 var name_cnode
= get_variable_cexpression (temp_var
.name
);
583 emit_temp_var (temp_var
);
586 foreach (Expression e
in expr
.get_expressions ()) {
587 ce
.append_expression (new
CCodeAssignment (new
CCodeElementAccess (name_cnode
, new
CCodeConstant (i
.to_string ())), get_cvalue (e
)));
591 ce
.append_expression (name_cnode
);
594 var set_creation
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_set_new"));
595 set_creation
.add_argument (get_type_id_expression (expr
.element_type
));
596 set_creation
.add_argument (new
CCodeConstant (length
.to_string ()));
597 set_creation
.add_argument (ce
);
599 set_cvalue (expr
, set_creation
);
602 public override void visit_map_literal (MapLiteral expr
) {
603 var key_ce
= new
CCodeCommaExpression ();
604 var value_ce
= new
CCodeCommaExpression ();
605 int length
= expr
.get_keys ().size
;
608 key_ce
.append_expression (new
CCodeConstant ("NULL"));
609 value_ce
.append_expression (new
CCodeConstant ("NULL"));
611 var key_array_type
= new
ArrayType (expr
.map_key_type
, 1, expr
.source_reference
);
612 key_array_type
.inline_allocated
= true;
613 key_array_type
.fixed_length
= true;
614 key_array_type
.length
= length
;
616 var key_temp_var
= get_temp_variable (key_array_type
, true, expr
);
617 var key_name_cnode
= get_variable_cexpression (key_temp_var
.name
);
619 emit_temp_var (key_temp_var
);
621 var value_array_type
= new
ArrayType (expr
.map_value_type
, 1, expr
.source_reference
);
622 value_array_type
.inline_allocated
= true;
623 value_array_type
.fixed_length
= true;
624 value_array_type
.length
= length
;
626 var value_temp_var
= get_temp_variable (value_array_type
, true, expr
);
627 var value_name_cnode
= get_variable_cexpression (value_temp_var
.name
);
629 emit_temp_var (value_temp_var
);
631 for (int i
= 0; i
< length
; i
++) {
632 key_ce
.append_expression (new
CCodeAssignment (new
CCodeElementAccess (key_name_cnode
, new
CCodeConstant (i
.to_string ())), get_cvalue (expr
.get_keys ().get (i
))));
633 value_ce
.append_expression (new
CCodeAssignment (new
CCodeElementAccess (value_name_cnode
, new
CCodeConstant (i
.to_string ())), get_cvalue (expr
.get_values ().get (i
))));
636 key_ce
.append_expression (key_name_cnode
);
637 value_ce
.append_expression (value_name_cnode
);
640 var map_creation
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_map_new"));
641 map_creation
.add_argument (get_type_id_expression (expr
.map_key_type
));
642 map_creation
.add_argument (get_type_id_expression (expr
.map_value_type
));
643 map_creation
.add_argument (new
CCodeConstant (length
.to_string ()));
644 map_creation
.add_argument (key_ce
);
645 map_creation
.add_argument (value_ce
);
647 set_cvalue (expr
, map_creation
);
650 public override void visit_tuple (Tuple tuple
) {
651 var type_array_type
= new
ArrayType (new
PointerType (new
VoidType ()), 1, tuple
.source_reference
);
652 type_array_type
.inline_allocated
= true;
653 type_array_type
.fixed_length
= true;
654 type_array_type
.length
= tuple
.get_expressions ().size
;
656 var type_temp_var
= get_temp_variable (type_array_type
, true, tuple
);
657 var type_name_cnode
= get_variable_cexpression (type_temp_var
.name
);
658 emit_temp_var (type_temp_var
);
660 var array_type
= new
ArrayType (new
PointerType (new
VoidType ()), 1, tuple
.source_reference
);
661 array_type
.inline_allocated
= true;
662 array_type
.fixed_length
= true;
663 array_type
.length
= tuple
.get_expressions ().size
;
665 var temp_var
= get_temp_variable (array_type
, true, tuple
);
666 var name_cnode
= get_variable_cexpression (temp_var
.name
);
667 emit_temp_var (temp_var
);
669 var type_ce
= new
CCodeCommaExpression ();
670 var ce
= new
CCodeCommaExpression ();
673 foreach (Expression e
in tuple
.get_expressions ()) {
674 var element_type
= tuple
.value_type
.get_type_arguments ().get (i
);
676 type_ce
.append_expression (new
CCodeAssignment (new
CCodeElementAccess (type_name_cnode
, new
CCodeConstant (i
.to_string ())), get_type_id_expression (element_type
)));
678 var cexpr
= get_cvalue (e
);
680 var unary
= cexpr as CCodeUnaryExpression
;
681 if (unary
!= null && unary
.operator
== CCodeUnaryOperator
.POINTER_INDIRECTION
) {
684 } else if (cexpr is CCodeIdentifier
|| cexpr is CCodeMemberAccess
) {
685 cexpr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, cexpr
);
687 // if cexpr is e.g. a function call, we can't take the address of the expression
690 var element_temp_var
= get_temp_variable (element_type
);
691 emit_temp_var (element_temp_var
);
692 ce
.append_expression (new
CCodeAssignment (get_variable_cexpression (element_temp_var
.name
), cexpr
));
693 cexpr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (element_temp_var
.name
));
696 ce
.append_expression (new
CCodeAssignment (new
CCodeElementAccess (name_cnode
, new
CCodeConstant (i
.to_string ())), cexpr
));
701 type_ce
.append_expression (type_name_cnode
);
702 ce
.append_expression (name_cnode
);
704 var tuple_creation
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_tuple_new"));
705 tuple_creation
.add_argument (new
CCodeConstant (tuple
.get_expressions ().size
.to_string ()));
706 tuple_creation
.add_argument (type_ce
);
707 tuple_creation
.add_argument (ce
);
709 set_cvalue (tuple
, tuple_creation
);