1 /* valadovamemberaccessmodule.vala
3 * Copyright (C) 2006-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>
25 public abstract class Vala
.DovaMemberAccessModule
: DovaControlFlowModule
{
26 public override void visit_member_access (MemberAccess expr
) {
27 CCodeExpression pub_inst
= null;
28 DataType base_type
= null;
30 if (expr
.inner
!= null) {
31 pub_inst
= get_cvalue (expr
.inner
);
33 if (expr
.inner
.value_type
!= null) {
34 base_type
= expr
.inner
.value_type
;
38 if (expr
.symbol_reference is Method
) {
39 var m
= (Method
) expr
.symbol_reference
;
41 if (!(m is DynamicMethod
)) {
42 generate_method_declaration (m
, cfile
);
44 if (!m
.external
&& m
.external_package
) {
45 // internal VAPI methods
46 // only add them once per source file
47 if (add_generated_external_symbol (m
)) {
53 if (expr
.inner is BaseAccess
) {
54 if (m
.base_method
!= null) {
55 var base_class
= (Class
) m
.base_method
.parent_symbol
;
57 set_cvalue (expr
, new
CCodeIdentifier ("%s_base_%s".printf (base_class
.get_lower_case_cname (null), m
.name
)));
59 } else if (m
.base_interface_method
!= null) {
60 var base_iface
= (Interface
) m
.base_interface_method
.parent_symbol
;
62 set_cvalue (expr
, new
CCodeIdentifier ("%s_base_%s".printf (base_iface
.get_lower_case_cname (null), m
.name
)));
67 if (m
.base_method
!= null) {
68 if (!method_has_wrapper (m
.base_method
)) {
70 if (expr
.inner
!= null && !expr
.inner
.is_pure ()) {
71 // instance expression has side-effects
72 // store in temp. variable
73 var temp_var
= get_temp_variable (expr
.inner
.value_type
);
74 emit_temp_var (temp_var
);
75 var ctemp
= new
CCodeIdentifier (temp_var
.name
);
76 inst
= new
CCodeAssignment (ctemp
, pub_inst
);
77 set_cvalue (expr
.inner
, ctemp
);
79 var base_class
= (Class
) m
.base_method
.parent_symbol
;
80 var vclass
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_CLASS".printf (base_class
.get_upper_case_cname (null))));
81 vclass
.add_argument (inst
);
82 set_cvalue (expr
, new CCodeMemberAccess
.pointer (vclass
, m
.name
));
84 set_cvalue (expr
, new
CCodeIdentifier (m
.base_method
.get_cname ()));
86 } else if (m
.base_interface_method
!= null) {
87 set_cvalue (expr
, new
CCodeIdentifier (m
.base_interface_method
.get_cname ()));
88 } else if (m is CreationMethod
) {
89 set_cvalue (expr
, new
CCodeIdentifier (m
.get_real_cname ()));
91 set_cvalue (expr
, new
CCodeIdentifier (m
.get_cname ()));
93 } else if (expr
.symbol_reference is ArrayLengthField
) {
94 generate_property_accessor_declaration (((Property
) array_class
.scope
.lookup ("length")).get_accessor
, cfile
);
96 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dova_array_get_length"));
97 ccall
.add_argument (pub_inst
);
98 set_cvalue (expr
, ccall
);
99 } else if (expr
.symbol_reference is Field
) {
100 var f
= (Field
) expr
.symbol_reference
;
101 expr
.target_value
= load_field (f
, expr
.inner
);
102 } else if (expr
.symbol_reference is EnumValue
) {
103 var ev
= (EnumValue
) expr
.symbol_reference
;
105 generate_enum_declaration ((Enum
) ev
.parent_symbol
, cfile
);
107 set_cvalue (expr
, new
CCodeConstant (ev
.get_cname ()));
108 } else if (expr
.symbol_reference is Constant
) {
109 var c
= (Constant
) expr
.symbol_reference
;
111 generate_constant_declaration (c
, cfile
);
113 set_cvalue (expr
, new
CCodeIdentifier (c
.get_cname ()));
114 } else if (expr
.symbol_reference is Property
) {
115 var prop
= (Property
) expr
.symbol_reference
;
117 if (!(prop is DynamicProperty
)) {
118 generate_property_accessor_declaration (prop
.get_accessor
, cfile
);
120 if (!prop
.external
&& prop
.external_package
) {
121 // internal VAPI properties
122 // only add them once per source file
123 if (add_generated_external_symbol (prop
)) {
124 visit_property (prop
);
129 if (expr
.inner is BaseAccess
) {
130 if (prop
.base_property
!= null) {
131 var base_class
= (Class
) prop
.base_property
.parent_symbol
;
132 var vcast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (base_class
.get_upper_case_cname (null))));
133 vcast
.add_argument (new
CCodeIdentifier ("%s_parent_class".printf (current_class
.get_lower_case_cname (null))));
135 var ccall
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (vcast
, "get_%s".printf (prop
.name
)));
136 ccall
.add_argument (get_cvalue (expr
.inner
));
137 set_cvalue (expr
, ccall
);
139 } else if (prop
.base_interface_property
!= null) {
140 var base_iface
= (Interface
) prop
.base_interface_property
.parent_symbol
;
141 string parent_iface_var
= "%s_%s_parent_iface".printf (current_class
.get_lower_case_cname (null), base_iface
.get_lower_case_cname (null));
143 var ccall
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (new
CCodeIdentifier (parent_iface_var
), "get_%s".printf (prop
.name
)));
144 ccall
.add_argument (get_cvalue (expr
.inner
));
145 set_cvalue (expr
, ccall
);
150 var base_property
= prop
;
151 if (prop
.base_property
!= null) {
152 base_property
= prop
.base_property
;
153 } else if (prop
.base_interface_property
!= null) {
154 base_property
= prop
.base_interface_property
;
156 string getter_cname
= base_property
.get_accessor
.get_cname ();
157 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (getter_cname
));
159 if (prop
.binding
== MemberBinding
.INSTANCE
) {
160 ccall
.add_argument (pub_inst
);
163 set_cvalue (expr
, ccall
);
164 } else if (expr
.symbol_reference is LocalVariable
) {
165 var local
= (LocalVariable
) expr
.symbol_reference
;
166 expr
.target_value
= load_local (local
);
167 } else if (expr
.symbol_reference is Parameter
) {
168 var p
= (Parameter
) expr
.symbol_reference
;
169 expr
.target_value
= load_parameter (p
);
173 public TargetValue
get_local_cvalue (LocalVariable local
) {
174 var result
= new
DovaValue (local
.variable_type
);
176 if (local
.is_result
) {
177 // used in postconditions
178 result
.cvalue
= new
CCodeIdentifier ("result");
179 } else if (local
.captured
) {
180 // captured variables are stored on the heap
181 var block
= (Block
) local
.parent_symbol
;
182 result
.cvalue
= new CCodeMemberAccess
.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block
))), get_variable_cname (local
.name
));
184 result
.cvalue
= get_variable_cexpression (local
.name
);
190 public TargetValue
get_parameter_cvalue (Parameter p
) {
191 var result
= new
DovaValue (p
.variable_type
);
193 if (p
.name
== "this") {
194 if (current_method
!= null && current_method
.coroutine
) {
196 result
.cvalue
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("data"), "this");
198 var st
= current_type_symbol as Struct
;
199 if (st
!= null && !st
.is_boolean_type () && !st
.is_integer_type () && !st
.is_floating_type () && (!st
.is_simple_type () || current_method is CreationMethod
)) {
200 result
.cvalue
= new
CCodeIdentifier ("(*this)");
202 result
.cvalue
= new
CCodeIdentifier ("this");
207 // captured variables are stored on the heap
208 var block
= p
.parent_symbol as Block
;
210 block
= ((Method
) p
.parent_symbol
).body
;
212 result
.cvalue
= new CCodeMemberAccess
.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block
))), get_variable_cname (p
.name
));
214 if (current_method
!= null && current_method
.coroutine
) {
216 result
.cvalue
= get_variable_cexpression (p
.name
);
218 var type_as_struct
= p
.variable_type
.data_type as Struct
;
219 if (p
.direction
!= ParameterDirection
.IN
220 || (type_as_struct
!= null && !type_as_struct
.is_simple_type () && !p
.variable_type
.nullable
)) {
221 if (p
.variable_type is GenericType
) {
222 result
.cvalue
= get_variable_cexpression (p
.name
);
224 result
.cvalue
= new
CCodeIdentifier ("(*%s)".printf (get_variable_cname (p
.name
)));
227 // Property setters of non simple structs shall replace all occurences
228 // of the "value" formal parameter with a dereferencing version of that
230 if (current_property_accessor
!= null &&
231 current_property_accessor
.writable
&&
232 current_property_accessor
.value_parameter
== p
&&
233 current_property_accessor
.prop
.property_type
.is_real_struct_type ()) {
234 result
.cvalue
= new
CCodeIdentifier ("(*value)");
236 result
.cvalue
= get_variable_cexpression (p
.name
);
246 public TargetValue
get_field_cvalue (Field f
, Expression? instance
) {
247 var result
= new
DovaValue (f
.variable_type
);
249 if (f
.binding
== MemberBinding
.INSTANCE
) {
250 CCodeExpression pub_inst
= null;
252 if (instance
!= null) {
253 pub_inst
= get_cvalue (instance
);
256 var instance_target_type
= get_data_type_for_symbol ((TypeSymbol
) f
.parent_symbol
);
258 var cl
= instance_target_type
.data_type as Class
;
259 bool dova_priv
= false;
260 if ((f
.access
== SymbolAccessibility
.PRIVATE
|| f
.access
== SymbolAccessibility
.INTERNAL
)) {
264 CCodeExpression inst
;
266 var priv_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_GET_PRIVATE".printf (cl
.get_upper_case_cname (null))));
267 priv_call
.add_argument (pub_inst
);
272 if (instance_target_type
.data_type
.is_reference_type () || (instance
!= null && instance
.value_type is PointerType
)) {
273 result
.cvalue
= new CCodeMemberAccess
.pointer (inst
, f
.get_cname ());
275 result
.cvalue
= new
CCodeMemberAccess (inst
, f
.get_cname ());
278 generate_field_declaration (f
, cfile
);
280 result
.cvalue
= new
CCodeIdentifier (f
.get_cname ());
286 TargetValue
load_variable (Variable variable
, TargetValue value
) {
290 public override TargetValue
load_local (LocalVariable local
) {
291 return load_variable (local
, get_local_cvalue (local
));
294 public override TargetValue
load_parameter (Parameter param
) {
295 return load_variable (param
, get_parameter_cvalue (param
));
298 public override TargetValue
load_field (Field field
, Expression? instance
) {
299 return load_variable (field
, get_field_cvalue (field
, instance
));