1 /* valaccodememberaccessmodule.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
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
25 public abstract class Vala
.CCodeMemberAccessModule
: CCodeControlFlowModule
{
26 public override void visit_member_access (MemberAccess expr
) {
27 CCodeExpression pub_inst
= null;
29 if (expr
.inner
!= null) {
30 pub_inst
= get_cvalue (expr
.inner
);
33 var array_type
= expr
.value_type as ArrayType
;
34 var delegate_type
= expr
.value_type as DelegateType
;
36 if (expr
.symbol_reference is Method
) {
37 var m
= (Method
) expr
.symbol_reference
;
39 if (!(m is DynamicMethod
|| m is ArrayMoveMethod
|| m is ArrayResizeMethod
)) {
40 generate_method_declaration (m
, cfile
);
42 if (!m
.external
&& m
.external_package
) {
43 // internal VAPI methods
44 // only add them once per source file
45 if (add_generated_external_symbol (m
)) {
51 if (expr
.inner is BaseAccess
) {
52 if (m
.base_method
!= null) {
53 var base_class
= (Class
) m
.base_method
.parent_symbol
;
54 var vcast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (base_class
.get_upper_case_cname (null))));
55 vcast
.add_argument (new
CCodeIdentifier ("%s_parent_class".printf (current_class
.get_lower_case_cname (null))));
57 set_cvalue (expr
, new CCodeMemberAccess
.pointer (vcast
, m
.vfunc_name
));
59 } else if (m
.base_interface_method
!= null) {
60 var base_iface
= (Interface
) m
.base_interface_method
.parent_symbol
;
61 string parent_iface_var
= "%s_%s_parent_iface".printf (current_class
.get_lower_case_cname (null), base_iface
.get_lower_case_cname (null));
63 set_cvalue (expr
, new CCodeMemberAccess
.pointer (new
CCodeIdentifier (parent_iface_var
), m
.vfunc_name
));
68 if (m
.base_method
!= null) {
69 if (!method_has_wrapper (m
.base_method
)) {
71 if (expr
.inner
!= null && !expr
.inner
.is_pure ()) {
72 // instance expression has side-effects
73 // store in temp. variable
74 var temp_var
= get_temp_variable (expr
.inner
.value_type
, true, null, false);
75 emit_temp_var (temp_var
);
76 var ctemp
= get_variable_cexpression (temp_var
.name
);
77 inst
= new
CCodeAssignment (ctemp
, pub_inst
);
78 set_cvalue (expr
.inner
, ctemp
);
80 var base_class
= (Class
) m
.base_method
.parent_symbol
;
81 var vclass
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_CLASS".printf (base_class
.get_upper_case_cname (null))));
82 vclass
.add_argument (inst
);
83 set_cvalue (expr
, new CCodeMemberAccess
.pointer (vclass
, m
.name
));
85 set_cvalue (expr
, new
CCodeIdentifier (m
.base_method
.get_cname ()));
87 } else if (m
.base_interface_method
!= null) {
88 set_cvalue (expr
, new
CCodeIdentifier (m
.base_interface_method
.get_cname ()));
89 } else if (m is CreationMethod
) {
90 set_cvalue (expr
, new
CCodeIdentifier (m
.get_real_cname ()));
92 set_cvalue (expr
, new
CCodeIdentifier (m
.get_cname ()));
95 set_delegate_target_destroy_notify (expr
, new
CCodeConstant ("NULL"));
96 if (m
.binding
== MemberBinding
.STATIC
) {
97 set_delegate_target (expr
, new
CCodeConstant ("NULL"));
98 } else if (m
.is_async_callback
) {
99 if (current_method
.closure
) {
100 var block
= ((Method
) m
.parent_symbol
).body
;
101 set_delegate_target (expr
, new CCodeMemberAccess
.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block
))), "_async_data_"));
103 set_delegate_target (expr
, new
CCodeIdentifier ("data"));
105 } else if (expr
.inner
!= null) {
106 // expr.inner is null in the special case of referencing the method in a constant initializer
107 var delegate_target
= (CCodeExpression
) get_ccodenode (expr
.inner
);
108 delegate_type
= expr
.target_type as DelegateType
;
109 if ((expr
.value_type
.value_owned
|| (delegate_type
!= null && delegate_type
.is_called_once
)) && expr
.inner
.value_type
.data_type
!= null && expr
.inner
.value_type
.data_type
.is_reference_counting ()) {
110 var ref_call
= new
CCodeFunctionCall (get_dup_func_expression (expr
.inner
.value_type
, expr
.source_reference
));
111 ref_call
.add_argument (delegate_target
);
112 delegate_target
= ref_call
;
113 set_delegate_target_destroy_notify (expr
, get_destroy_func_expression (expr
.inner
.value_type
));
115 set_delegate_target (expr
, delegate_target
);
117 } else if (expr
.symbol_reference is ArrayLengthField
) {
118 if (expr
.value_type is ArrayType
&& !(expr
.parent_node is ElementAccess
)) {
119 Report
.error (expr
.source_reference
, "unsupported use of length field of multi-dimensional array");
121 set_cvalue (expr
, get_array_length_cexpression (expr
.inner
, 1));
122 } else if (expr
.symbol_reference is Field
) {
123 var field
= (Field
) expr
.symbol_reference
;
124 expr
.target_value
= load_field (field
, expr
.inner
!= null ? expr
.inner
.target_value
: null);
125 } else if (expr
.symbol_reference is EnumValue
) {
126 var ev
= (EnumValue
) expr
.symbol_reference
;
128 generate_enum_declaration ((Enum
) ev
.parent_symbol
, cfile
);
130 set_cvalue (expr
, new
CCodeConstant (ev
.get_cname ()));
131 } else if (expr
.symbol_reference is Constant
) {
132 var c
= (Constant
) expr
.symbol_reference
;
134 generate_constant_declaration (c
, cfile
,
135 c
.source_reference
!= null && expr
.source_reference
!= null &&
136 c
.source_reference
.file
== expr
.source_reference
.file
);
138 string fn
= c
.get_full_name ();
139 if (fn
== "GLib.Log.FILE") {
140 string s
= Path
.get_basename (expr
.source_reference
.file
.filename
);
141 set_cvalue (expr
, new
CCodeConstant ("\"%s\"".printf (s
)));
142 } else if (fn
== "GLib.Log.LINE") {
143 int i
= expr
.source_reference
.first_line
;
144 set_cvalue (expr
, new
CCodeConstant ("%d".printf (i
)));
145 } else if (fn
== "GLib.Log.METHOD") {
147 if (current_method
!= null) {
148 s
= current_method
.get_full_name ();
150 set_cvalue (expr
, new
CCodeConstant ("\"%s\"".printf (s
)));
152 set_cvalue (expr
, new
CCodeIdentifier (c
.get_cname ()));
155 if (array_type
!= null) {
156 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_N_ELEMENTS"));
157 ccall
.add_argument (new
CCodeIdentifier (c
.get_cname ()));
158 append_array_length (expr
, ccall
);
160 } else if (expr
.symbol_reference is Property
) {
161 var prop
= (Property
) expr
.symbol_reference
;
163 if (!(prop is DynamicProperty
)) {
164 generate_property_accessor_declaration (prop
.get_accessor
, cfile
);
166 if (!prop
.external
&& prop
.external_package
) {
167 // internal VAPI properties
168 // only add them once per source file
169 if (add_generated_external_symbol (prop
)) {
170 visit_property (prop
);
175 if (expr
.inner is BaseAccess
) {
176 if (prop
.base_property
!= null) {
177 var base_class
= (Class
) prop
.base_property
.parent_symbol
;
178 var vcast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (base_class
.get_upper_case_cname (null))));
179 vcast
.add_argument (new
CCodeIdentifier ("%s_parent_class".printf (current_class
.get_lower_case_cname (null))));
181 var ccall
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (vcast
, "get_%s".printf (prop
.name
)));
182 ccall
.add_argument (get_cvalue (expr
.inner
));
183 set_cvalue (expr
, ccall
);
185 } else if (prop
.base_interface_property
!= null) {
186 var base_iface
= (Interface
) prop
.base_interface_property
.parent_symbol
;
187 string parent_iface_var
= "%s_%s_parent_iface".printf (current_class
.get_lower_case_cname (null), base_iface
.get_lower_case_cname (null));
189 var ccall
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (new
CCodeIdentifier (parent_iface_var
), "get_%s".printf (prop
.name
)));
190 ccall
.add_argument (get_cvalue (expr
.inner
));
191 set_cvalue (expr
, ccall
);
196 if (prop
.binding
== MemberBinding
.INSTANCE
&&
197 prop
.get_accessor
.automatic_body
&&
198 current_type_symbol
== prop
.parent_symbol
&&
199 current_type_symbol is Class
&&
200 prop
.base_property
== null &&
201 prop
.base_interface_property
== null &&
202 !(prop
.property_type is ArrayType
|| prop
.property_type is DelegateType
)) {
203 CCodeExpression inst
;
204 inst
= new CCodeMemberAccess
.pointer (pub_inst
, "priv");
205 set_cvalue (expr
, new CCodeMemberAccess
.pointer (inst
, prop
.field
.get_cname()));
206 } else if (!prop
.no_accessor_method
) {
207 var base_property
= prop
;
208 if (prop
.base_property
!= null) {
209 base_property
= prop
.base_property
;
210 } else if (prop
.base_interface_property
!= null) {
211 base_property
= prop
.base_interface_property
;
214 if (prop is DynamicProperty
) {
215 getter_cname
= get_dynamic_property_getter_cname ((DynamicProperty
) prop
);
217 getter_cname
= base_property
.get_accessor
.get_cname ();
219 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (getter_cname
));
221 if (prop
.binding
== MemberBinding
.INSTANCE
) {
222 if (prop
.parent_symbol is Struct
) {
223 // we need to pass struct instance by reference
224 var unary
= pub_inst as CCodeUnaryExpression
;
225 if (unary
!= null && unary
.operator
== CCodeUnaryOperator
.POINTER_INDIRECTION
) {
227 pub_inst
= unary
.inner
;
228 } else if (pub_inst is CCodeIdentifier
|| pub_inst is CCodeMemberAccess
) {
229 pub_inst
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, pub_inst
);
231 // if instance is e.g. a function call, we can't take the address of the expression
232 var temp_var
= get_temp_variable (expr
.inner
.target_type
, true, null, false);
233 emit_temp_var (temp_var
);
234 ccode
.add_assignment (get_variable_cexpression (temp_var
.name
), pub_inst
);
235 pub_inst
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_variable_cexpression (temp_var
.name
));
239 ccall
.add_argument (pub_inst
);
242 var temp_var
= get_temp_variable (base_property
.get_accessor
.value_type
, base_property
.get_accessor
.value_type
.value_owned
);
243 emit_temp_var (temp_var
);
244 var ctemp
= get_variable_cexpression (temp_var
.name
);
245 set_cvalue (expr
, ctemp
);
247 // Property access to real struct types is handled differently
248 // The value is returned by out parameter
249 if (base_property
.property_type
.is_real_non_null_struct_type ()) {
250 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, ctemp
));
251 ccode
.add_expression (ccall
);
253 ccode
.add_assignment (ctemp
, ccall
);
255 array_type
= base_property
.property_type as ArrayType
;
256 if (array_type
!= null && !base_property
.no_array_length
) {
257 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
258 temp_var
= get_temp_variable (int_type
);
259 ctemp
= get_variable_cexpression (temp_var
.name
);
260 emit_temp_var (temp_var
);
261 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, ctemp
));
262 append_array_length (expr
, ctemp
);
265 delegate_type
= base_property
.property_type as DelegateType
;
266 if (delegate_type
!= null && delegate_type
.delegate_symbol
.has_target
) {
267 temp_var
= get_temp_variable (new
PointerType (new
VoidType ()));
268 ctemp
= get_variable_cexpression (temp_var
.name
);
269 emit_temp_var (temp_var
);
270 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, ctemp
));
271 set_delegate_target (expr
, ctemp
);
272 set_delegate_target_destroy_notify (expr
, new
CCodeConstant ("NULL"));
277 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_get"));
278 ccall
.add_argument (pub_inst
);
280 // property name is second argument of g_object_get
281 ccall
.add_argument (prop
.get_canonical_cconstant ());
283 // g_object_get always returns owned values
284 // therefore, property getters of properties
285 // without accessor methods need to be marked as owned
286 if (!prop
.get_accessor
.value_type
.value_owned
) {
287 // only report error for types where there actually
288 // is a difference between `owned' and `unowned'
289 var owned_value_type
= prop
.get_accessor
.value_type
.copy ();
290 owned_value_type
.value_owned
= true;
291 if (requires_copy (owned_value_type
)) {
292 Report
.error (prop
.get_accessor
.source_reference
, "unowned return value for getter of property `%s' not supported without accessor".printf (prop
.get_full_name ()));
296 var temp_var
= get_temp_variable (expr
.value_type
);
297 var ctemp
= get_variable_cexpression (temp_var
.name
);
298 emit_temp_var (temp_var
);
299 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, ctemp
));
300 ccall
.add_argument (new
CCodeConstant ("NULL"));
301 ccode
.add_expression (ccall
);
302 set_cvalue (expr
, ctemp
);
304 } else if (expr
.symbol_reference is LocalVariable
) {
305 var local
= (LocalVariable
) expr
.symbol_reference
;
307 expr
.target_value
= get_local_cvalue (local
);
309 expr
.target_value
= load_local (local
);
312 if (expr
.parent_node is ReturnStatement
&&
313 current_return_type
.value_owned
&&
314 local
.variable_type
.value_owned
&&
316 !variable_accessible_in_finally (local
)) {
317 /* return expression is local variable taking ownership and
318 * current method is transferring ownership */
320 // don't ref expression
321 expr
.value_type
.value_owned
= true;
323 // don't unref variable
324 local
.active
= false;
326 } else if (expr
.symbol_reference is Parameter
) {
327 var param
= (Parameter
) expr
.symbol_reference
;
329 expr
.target_value
= get_parameter_cvalue (param
);
331 expr
.target_value
= load_parameter (param
);
336 /* Returns lvalue access to the given local variable */
337 public override TargetValue
get_local_cvalue (LocalVariable local
) {
338 var result
= new
GLibValue (local
.variable_type
.copy ());
340 var array_type
= local
.variable_type as ArrayType
;
341 var delegate_type
= local
.variable_type as DelegateType
;
342 if (local
.is_result
) {
343 // used in postconditions
344 // structs are returned as out parameter
345 if (local
.variable_type
!= null && local
.variable_type
.is_real_non_null_struct_type ()) {
346 result
.cvalue
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("result"));
348 result
.cvalue
= new
CCodeIdentifier ("result");
350 } else if (local
.captured
) {
351 // captured variables are stored on the heap
352 var block
= (Block
) local
.parent_symbol
;
353 result
.cvalue
= new CCodeMemberAccess
.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block
))), get_variable_cname (local
.name
));
354 if (array_type
!= null) {
355 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
356 result
.append_array_length_cvalue (new CCodeMemberAccess
.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block
))), get_array_length_cname (get_variable_cname (local
.name
), dim
)));
358 if (array_type
.rank
== 1) {
359 result
.array_size_cvalue
= new CCodeMemberAccess
.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block
))), get_array_size_cname (get_variable_cname (local
.name
)));
361 } else if (delegate_type
!= null && delegate_type
.delegate_symbol
.has_target
) {
362 result
.delegate_target_cvalue
= new CCodeMemberAccess
.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block
))), get_delegate_target_cname (get_variable_cname (local
.name
)));
363 result
.delegate_target_destroy_notify_cvalue
= new CCodeMemberAccess
.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block
))), get_delegate_target_destroy_notify_cname (get_variable_cname (local
.name
)));
366 result
.cvalue
= get_variable_cexpression (local
.name
);
367 if (array_type
!= null) {
368 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
369 result
.append_array_length_cvalue (get_variable_cexpression (get_array_length_cname (get_variable_cname (local
.name
), dim
)));
371 if (array_type
.rank
== 1) {
372 result
.array_size_cvalue
= get_variable_cexpression (get_array_size_cname (get_variable_cname (local
.name
)));
374 } else if (delegate_type
!= null && delegate_type
.delegate_symbol
.has_target
) {
375 if (is_in_coroutine ()) {
376 result
.delegate_target_cvalue
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("data"), get_delegate_target_cname (get_variable_cname (local
.name
)));
377 result
.delegate_target_destroy_notify_cvalue
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("data"), get_delegate_target_destroy_notify_cname (get_variable_cname (local
.name
)));
379 result
.delegate_target_cvalue
= new
CCodeIdentifier (get_delegate_target_cname (get_variable_cname (local
.name
)));
380 if (local
.variable_type
.value_owned
) {
381 result
.delegate_target_destroy_notify_cvalue
= new
CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (local
.name
)));
390 /* Returns access values to the given parameter */
391 public override TargetValue
get_parameter_cvalue (Parameter param
) {
392 var result
= new
GLibValue (param
.variable_type
.copy ());
393 if (param
.captured
|| is_in_coroutine ()) {
394 result
.value_type
.value_owned
= true;
397 var array_type
= result
.value_type as ArrayType
;
398 var delegate_type
= result
.value_type as DelegateType
;
400 if (param
.name
== "this") {
401 if (is_in_coroutine ()) {
403 result
.cvalue
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("data"), "self");
405 var st
= result
.value_type
.data_type as Struct
;
406 if (st
!= null && !st
.is_simple_type ()) {
407 result
.cvalue
= new
CCodeIdentifier ("(*self)");
409 result
.cvalue
= new
CCodeIdentifier ("self");
413 string name
= param
.name
;
415 if (param
.captured
) {
416 // captured variables are stored on the heap
417 var block
= param
.parent_symbol as Block
;
419 block
= ((Method
) param
.parent_symbol
).body
;
421 result
.cvalue
= new CCodeMemberAccess
.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block
))), get_variable_cname (param
.name
));
422 if (array_type
!= null) {
423 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
424 result
.append_array_length_cvalue (new CCodeMemberAccess
.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block
))), get_parameter_array_length_cname (param
, dim
)));
426 } else if (delegate_type
!= null && delegate_type
.delegate_symbol
.has_target
) {
427 result
.delegate_target_cvalue
= new CCodeMemberAccess
.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block
))), get_delegate_target_cname (get_variable_cname (param
.name
)));
428 result
.delegate_target_destroy_notify_cvalue
= new CCodeMemberAccess
.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block
))), get_delegate_target_destroy_notify_cname (get_variable_cname (param
.name
)));
430 } else if (is_in_coroutine ()) {
432 result
.cvalue
= get_variable_cexpression (param
.name
);
433 if (delegate_type
!= null && delegate_type
.delegate_symbol
.has_target
) {
434 result
.delegate_target_cvalue
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("data"), get_delegate_target_cname (get_variable_cname (param
.name
)));
435 result
.delegate_target_destroy_notify_cvalue
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("data"), get_delegate_target_destroy_notify_cname (get_variable_cname (param
.name
)));
438 var type_as_struct
= result
.value_type
.data_type as Struct
;
440 if (param
.direction
== ParameterDirection
.OUT
) {
444 if (param
.direction
== ParameterDirection
.REF
||
445 (param
.direction
== ParameterDirection
.IN
&& type_as_struct
!= null && !type_as_struct
.is_simple_type () && !result
.value_type
.nullable
)) {
446 result
.cvalue
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier (get_variable_cname (name
)));
448 // Property setters of non simple structs shall replace all occurences
449 // of the "value" formal parameter with a dereferencing version of that
451 if (current_property_accessor
!= null &&
452 current_property_accessor
.writable
&&
453 current_property_accessor
.value_parameter
== param
&&
454 current_property_accessor
.prop
.property_type
.is_real_struct_type () &&
455 !current_property_accessor
.prop
.property_type
.nullable
) {
456 result
.cvalue
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("value"));
458 result
.cvalue
= get_variable_cexpression (name
);
461 if (delegate_type
!= null && delegate_type
.delegate_symbol
.has_target
) {
462 CCodeExpression target_expr
= new
CCodeIdentifier (get_delegate_target_cname (get_variable_cname (name
)));
463 CCodeExpression delegate_target_destroy_notify
= new
CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (name
)));
464 if (param
.direction
== ParameterDirection
.REF
) {
465 // accessing argument of ref param
466 target_expr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, target_expr
);
467 delegate_target_destroy_notify
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, delegate_target_destroy_notify
);
469 result
.delegate_target_cvalue
= target_expr
;
470 if (result
.value_type
.value_owned
) {
471 result
.delegate_target_destroy_notify_cvalue
= delegate_target_destroy_notify
;
475 if (!param
.captured
&& array_type
!= null) {
476 if (!param
.no_array_length
&& !param
.array_null_terminated
) {
477 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
478 CCodeExpression length_expr
= get_variable_cexpression (get_parameter_array_length_cname (param
, dim
));
479 if (param
.direction
== ParameterDirection
.OUT
) {
480 length_expr
= get_variable_cexpression (get_array_length_cname (get_variable_cname (name
), dim
));
481 } else if (param
.direction
== ParameterDirection
.REF
) {
482 // accessing argument of ref param
483 length_expr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, length_expr
);
485 result
.append_array_length_cvalue (length_expr
);
494 /* Returns lvalue access to the given field */
495 public override TargetValue
get_field_cvalue (Field field
, TargetValue? instance
) {
496 var result
= new
GLibValue (field
.variable_type
.copy ());
498 var array_type
= field
.variable_type as ArrayType
;
499 var delegate_type
= field
.variable_type as DelegateType
;
500 if (field
.binding
== MemberBinding
.INSTANCE
) {
501 CCodeExpression pub_inst
= null;
503 if (instance
!= null) {
504 pub_inst
= get_cvalue_ (instance
);
507 var instance_target_type
= get_data_type_for_symbol ((TypeSymbol
) field
.parent_symbol
);
509 var cl
= instance_target_type
.data_type as Class
;
510 bool is_gtypeinstance
= ((instance_target_type
.data_type
== cl
) && (cl
== null || !cl
.is_compact
));
512 CCodeExpression inst
;
513 if (is_gtypeinstance
&& field
.access
== SymbolAccessibility
.PRIVATE
) {
514 inst
= new CCodeMemberAccess
.pointer (pub_inst
, "priv");
517 generate_class_struct_declaration (cl
, cfile
);
521 if (instance_target_type
.data_type
.is_reference_type () || (instance
!= null && instance
.value_type is PointerType
)) {
522 result
.cvalue
= new CCodeMemberAccess
.pointer (inst
, field
.get_cname ());
524 result
.cvalue
= new
CCodeMemberAccess (inst
, field
.get_cname ());
527 if (array_type
!= null && !field
.no_array_length
) {
528 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
529 CCodeExpression length_expr
= null;
532 if (field
.has_array_length_cname
) {
533 length_cname
= field
.get_array_length_cname ();
535 length_cname
= get_array_length_cname (field
.name
, dim
);
538 if (((TypeSymbol
) field
.parent_symbol
).is_reference_type ()) {
539 length_expr
= new CCodeMemberAccess
.pointer (inst
, length_cname
);
541 length_expr
= new
CCodeMemberAccess (inst
, length_cname
);
544 result
.append_array_length_cvalue (length_expr
);
546 if (array_type
.rank
== 1 && field
.is_internal_symbol ()) {
547 string size_cname
= get_array_size_cname (field
.name
);
549 if (((TypeSymbol
) field
.parent_symbol
).is_reference_type ()) {
550 set_array_size_cvalue (result
, new CCodeMemberAccess
.pointer (inst
, size_cname
));
552 set_array_size_cvalue (result
, new
CCodeMemberAccess (inst
, size_cname
));
555 } else if (delegate_type
!= null && delegate_type
.delegate_symbol
.has_target
&& !field
.no_delegate_target
) {
556 string target_cname
= get_delegate_target_cname (field
.get_cname ());
557 string target_destroy_notify_cname
= get_delegate_target_destroy_notify_cname (field
.get_cname ());
559 if (((TypeSymbol
) field
.parent_symbol
).is_reference_type ()) {
560 result
.delegate_target_cvalue
= new CCodeMemberAccess
.pointer (inst
, target_cname
);
561 if (field
.variable_type
.value_owned
) {
562 result
.delegate_target_destroy_notify_cvalue
= new CCodeMemberAccess
.pointer (inst
, target_destroy_notify_cname
);
565 result
.delegate_target_cvalue
= new
CCodeMemberAccess (inst
, target_cname
);
566 if (field
.variable_type
.value_owned
) {
567 result
.delegate_target_destroy_notify_cvalue
= new
CCodeMemberAccess (inst
, target_destroy_notify_cname
);
571 } else if (field
.binding
== MemberBinding
.CLASS
) {
572 var cl
= (Class
) field
.parent_symbol
;
573 var cast
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_upper_case_cname (null) + "_CLASS"));
575 CCodeExpression klass
;
576 if (instance
== null) {
577 if (in_static_or_class_context
) {
578 // Accessing the field from a static or class constructor
579 klass
= new
CCodeIdentifier ("klass");
581 // Accessing the field from within an instance method
582 var k
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT_GET_CLASS"));
583 k
.add_argument (new
CCodeIdentifier ("self"));
587 // Accessing the field of an instance
588 var k
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT_GET_CLASS"));
589 k
.add_argument (get_cvalue_ (instance
));
592 cast
.add_argument (klass
);
594 if (field
.access
== SymbolAccessibility
.PRIVATE
) {
595 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl
.get_upper_case_cname ())));
596 ccall
.add_argument (klass
);
597 result
.cvalue
= new CCodeMemberAccess
.pointer (ccall
, field
.get_cname ());
599 result
.cvalue
= new CCodeMemberAccess
.pointer (cast
, field
.get_cname ());
603 generate_field_declaration (field
, cfile
);
605 result
.cvalue
= new
CCodeIdentifier (field
.get_cname ());
607 if (array_type
!= null && !field
.no_array_length
) {
608 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
610 if (field
.has_array_length_cname
) {
611 length_cname
= field
.get_array_length_cname ();
613 length_cname
= get_array_length_cname (field
.get_cname (), dim
);
616 result
.append_array_length_cvalue (new
CCodeIdentifier (length_cname
));
618 if (array_type
.rank
== 1 && field
.is_internal_symbol ()) {
619 set_array_size_cvalue (result
, new
CCodeIdentifier (get_array_size_cname (field
.get_cname ())));
621 } else if (delegate_type
!= null && delegate_type
.delegate_symbol
.has_target
&& !field
.no_delegate_target
) {
622 result
.delegate_target_cvalue
= new
CCodeIdentifier (get_delegate_target_cname (field
.get_cname ()));
623 if (field
.variable_type
.value_owned
) {
624 result
.delegate_target_destroy_notify_cvalue
= new
CCodeIdentifier (get_delegate_target_destroy_notify_cname (field
.get_cname ()));
632 TargetValue
load_variable (Variable variable
, TargetValue value
) {
633 var result
= (GLibValue
) value
;
634 var array_type
= result
.value_type as ArrayType
;
635 var delegate_type
= result
.value_type as DelegateType
;
636 if (array_type
!= null) {
637 if (variable
.array_null_terminated
) {
638 requires_array_length
= true;
639 var len_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("_vala_array_length"));
640 len_call
.add_argument (result
.cvalue
);
642 result
.array_length_cvalues
= null;
643 result
.append_array_length_cvalue (len_call
);
644 } else if (variable
.has_array_length_cexpr
) {
645 var length_expr
= new
CCodeConstant (variable
.get_array_length_cexpr ());
647 result
.array_length_cvalues
= null;
648 result
.append_array_length_cvalue (length_expr
);
649 } else if (variable
.no_array_length
) {
650 result
.array_length_cvalues
= null;
651 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
652 result
.append_array_length_cvalue (new
CCodeConstant ("-1"));
654 } else if (variable
.array_length_type
!= null) {
655 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
656 // cast if variable does not use int for array length
657 result
.array_length_cvalues
[dim
- 1] = new
CCodeCastExpression (result
.array_length_cvalues
[dim
- 1], "gint");
660 } else if (delegate_type
!= null && delegate_type
.delegate_symbol
.has_target
) {
661 if (variable
.no_delegate_target
) {
662 result
.delegate_target_cvalue
= new
CCodeConstant ("NULL");
665 result
.delegate_target_destroy_notify_cvalue
= new
CCodeConstant ("NULL");
667 result
.value_type
.value_owned
= false;
671 /* Returns unowned access to the given local variable */
672 public override TargetValue
load_local (LocalVariable local
) {
673 return load_variable (local
, get_local_cvalue (local
));
676 /* Returns unowned access to the given parameter */
677 public override TargetValue
load_parameter (Parameter param
) {
678 return load_variable (param
, get_parameter_cvalue (param
));
681 /* Convenience method returning access to "this" */
682 public override TargetValue
load_this_parameter (TypeSymbol sym
) {
683 var param
= new
Parameter ("this", get_data_type_for_symbol (sym
));
684 return load_parameter (param
);
687 /* Returns unowned access to the given field */
688 public override TargetValue
load_field (Field field
, TargetValue? instance
) {
689 return load_variable (field
, get_field_cvalue (field
, instance
));