girparser: Simplify postprocessing callbacks. Use symbols info for records.
[vala-lang.git] / codegen / valaccodememberaccessmodule.vala
blob7c14732fa4a3f4d9ac27d4d0588464481f2465ab
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
20 * Author:
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)) {
46 visit_method (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));
58 return;
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));
64 return;
68 if (m.base_method != null) {
69 if (!method_has_wrapper (m.base_method)) {
70 var inst = pub_inst;
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));
84 } else {
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 ()));
91 } else {
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_"));
102 } else {
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") {
146 string s = "";
147 if (current_method != null) {
148 s = current_method.get_full_name ();
150 set_cvalue (expr, new CCodeConstant ("\"%s\"".printf (s)));
151 } else {
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);
184 return;
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);
192 return;
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;
213 string getter_cname;
214 if (prop is DynamicProperty) {
215 getter_cname = get_dynamic_property_getter_cname ((DynamicProperty) prop);
216 } else {
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) {
226 // *expr => expr
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);
230 } else {
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);
252 } else {
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);
264 } else {
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"));
276 } else {
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;
306 if (expr.lvalue) {
307 expr.target_value = get_local_cvalue (local);
308 } else {
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 &&
315 !local.captured &&
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;
328 if (expr.lvalue) {
329 expr.target_value = get_parameter_cvalue (param);
330 } else {
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"));
347 } else {
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)));
365 } else {
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)));
378 } else {
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)));
387 return result;
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 ()) {
402 // use closure
403 result.cvalue = new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "self");
404 } else {
405 var st = result.value_type.data_type as Struct;
406 if (st != null && !st.is_simple_type ()) {
407 result.cvalue = new CCodeIdentifier ("(*self)");
408 } else {
409 result.cvalue = new CCodeIdentifier ("self");
412 } else {
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;
418 if (block == null) {
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 ()) {
431 // use closure
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)));
437 } else {
438 var type_as_struct = result.value_type.data_type as Struct;
440 if (param.direction == ParameterDirection.OUT) {
441 name = "_" + name;
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)));
447 } else {
448 // Property setters of non simple structs shall replace all occurences
449 // of the "value" formal parameter with a dereferencing version of that
450 // parameter.
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"));
457 } else {
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);
491 return result;
494 /* Returns lvalue access to the given field */
495 public override TargetValue get_field_cvalue (Field field, TargetValue? instance) {
496 var value_type = field.variable_type.copy ();
497 if (instance != null) {
498 value_type = value_type.get_actual_type (instance.value_type, null, field);
501 var result = new GLibValue (value_type);
503 var array_type = result.value_type as ArrayType;
504 var delegate_type = result.value_type as DelegateType;
505 if (field.binding == MemberBinding.INSTANCE) {
506 CCodeExpression pub_inst = null;
508 if (instance != null) {
509 pub_inst = get_cvalue_ (instance);
512 var instance_target_type = get_data_type_for_symbol ((TypeSymbol) field.parent_symbol);
514 var cl = instance_target_type.data_type as Class;
515 bool is_gtypeinstance = ((instance_target_type.data_type == cl) && (cl == null || !cl.is_compact));
517 CCodeExpression inst;
518 if (is_gtypeinstance && field.access == SymbolAccessibility.PRIVATE) {
519 inst = new CCodeMemberAccess.pointer (pub_inst, "priv");
520 } else {
521 if (cl != null) {
522 generate_class_struct_declaration (cl, cfile);
524 inst = pub_inst;
526 if (instance_target_type.data_type.is_reference_type () || (instance != null && instance.value_type is PointerType)) {
527 result.cvalue = new CCodeMemberAccess.pointer (inst, field.get_cname ());
528 } else {
529 result.cvalue = new CCodeMemberAccess (inst, field.get_cname ());
532 if (array_type != null && !field.no_array_length) {
533 for (int dim = 1; dim <= array_type.rank; dim++) {
534 CCodeExpression length_expr = null;
536 string length_cname;
537 if (field.has_array_length_cname) {
538 length_cname = field.get_array_length_cname ();
539 } else {
540 length_cname = get_array_length_cname (field.name, dim);
543 if (((TypeSymbol) field.parent_symbol).is_reference_type ()) {
544 length_expr = new CCodeMemberAccess.pointer (inst, length_cname);
545 } else {
546 length_expr = new CCodeMemberAccess (inst, length_cname);
549 result.append_array_length_cvalue (length_expr);
551 if (array_type.rank == 1 && field.is_internal_symbol ()) {
552 string size_cname = get_array_size_cname (field.name);
554 if (((TypeSymbol) field.parent_symbol).is_reference_type ()) {
555 set_array_size_cvalue (result, new CCodeMemberAccess.pointer (inst, size_cname));
556 } else {
557 set_array_size_cvalue (result, new CCodeMemberAccess (inst, size_cname));
560 } else if (delegate_type != null && delegate_type.delegate_symbol.has_target && !field.no_delegate_target) {
561 string target_cname = get_delegate_target_cname (field.get_cname ());
562 string target_destroy_notify_cname = get_delegate_target_destroy_notify_cname (field.get_cname ());
564 if (((TypeSymbol) field.parent_symbol).is_reference_type ()) {
565 result.delegate_target_cvalue = new CCodeMemberAccess.pointer (inst, target_cname);
566 if (result.value_type.value_owned) {
567 result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess.pointer (inst, target_destroy_notify_cname);
569 } else {
570 result.delegate_target_cvalue = new CCodeMemberAccess (inst, target_cname);
571 if (result.value_type.value_owned) {
572 result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess (inst, target_destroy_notify_cname);
576 } else if (field.binding == MemberBinding.CLASS) {
577 var cl = (Class) field.parent_symbol;
578 var cast = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null) + "_CLASS"));
580 CCodeExpression klass;
581 if (instance == null) {
582 if (in_static_or_class_context) {
583 // Accessing the field from a static or class constructor
584 klass = new CCodeIdentifier ("klass");
585 } else {
586 // Accessing the field from within an instance method
587 var k = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_GET_CLASS"));
588 k.add_argument (new CCodeIdentifier ("self"));
589 klass = k;
591 } else {
592 // Accessing the field of an instance
593 var k = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_GET_CLASS"));
594 k.add_argument (get_cvalue_ (instance));
595 klass = k;
597 cast.add_argument (klass);
599 if (field.access == SymbolAccessibility.PRIVATE) {
600 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname ())));
601 ccall.add_argument (klass);
602 result.cvalue = new CCodeMemberAccess.pointer (ccall, field.get_cname ());
603 } else {
604 result.cvalue = new CCodeMemberAccess.pointer (cast, field.get_cname ());
607 } else {
608 generate_field_declaration (field, cfile);
610 result.cvalue = new CCodeIdentifier (field.get_cname ());
612 if (array_type != null && !field.no_array_length) {
613 for (int dim = 1; dim <= array_type.rank; dim++) {
614 string length_cname;
615 if (field.has_array_length_cname) {
616 length_cname = field.get_array_length_cname ();
617 } else {
618 length_cname = get_array_length_cname (field.get_cname (), dim);
621 result.append_array_length_cvalue (new CCodeIdentifier (length_cname));
623 if (array_type.rank == 1 && field.is_internal_symbol ()) {
624 set_array_size_cvalue (result, new CCodeIdentifier (get_array_size_cname (field.get_cname ())));
626 } else if (delegate_type != null && delegate_type.delegate_symbol.has_target && !field.no_delegate_target) {
627 result.delegate_target_cvalue = new CCodeIdentifier (get_delegate_target_cname (field.get_cname ()));
628 if (result.value_type.value_owned) {
629 result.delegate_target_destroy_notify_cvalue = new CCodeIdentifier (get_delegate_target_destroy_notify_cname (field.get_cname ()));
634 return result;
637 TargetValue load_variable (Variable variable, TargetValue value) {
638 var result = (GLibValue) value;
639 var array_type = result.value_type as ArrayType;
640 var delegate_type = result.value_type as DelegateType;
641 if (array_type != null) {
642 if (variable.array_null_terminated) {
643 requires_array_length = true;
644 var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length"));
645 len_call.add_argument (result.cvalue);
647 result.array_length_cvalues = null;
648 result.append_array_length_cvalue (len_call);
649 } else if (variable.has_array_length_cexpr) {
650 var length_expr = new CCodeConstant (variable.get_array_length_cexpr ());
652 result.array_length_cvalues = null;
653 result.append_array_length_cvalue (length_expr);
654 } else if (variable.no_array_length) {
655 result.array_length_cvalues = null;
656 for (int dim = 1; dim <= array_type.rank; dim++) {
657 result.append_array_length_cvalue (new CCodeConstant ("-1"));
659 } else if (variable.array_length_type != null) {
660 for (int dim = 1; dim <= array_type.rank; dim++) {
661 // cast if variable does not use int for array length
662 result.array_length_cvalues[dim - 1] = new CCodeCastExpression (result.array_length_cvalues[dim - 1], "gint");
665 } else if (delegate_type != null && delegate_type.delegate_symbol.has_target) {
666 if (variable.no_delegate_target) {
667 result.delegate_target_cvalue = new CCodeConstant ("NULL");
670 result.delegate_target_destroy_notify_cvalue = new CCodeConstant ("NULL");
672 result.value_type.value_owned = false;
673 return result;
676 /* Returns unowned access to the given local variable */
677 public override TargetValue load_local (LocalVariable local) {
678 return load_variable (local, get_local_cvalue (local));
681 /* Returns unowned access to the given parameter */
682 public override TargetValue load_parameter (Parameter param) {
683 return load_variable (param, get_parameter_cvalue (param));
686 /* Convenience method returning access to "this" */
687 public override TargetValue load_this_parameter (TypeSymbol sym) {
688 var param = new Parameter ("this", get_data_type_for_symbol (sym));
689 return load_parameter (param);
692 /* Returns unowned access to the given field */
693 public override TargetValue load_field (Field field, TargetValue? instance) {
694 return load_variable (field, get_field_cvalue (field, instance));