1 /* valacodegeneratormemberaccess.vala
3 * Copyright (C) 2006-2007 Jürg Billeter, Raffaele Sandrini
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 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>
21 * Raffaele Sandrini <rasa@gmx.ch>
26 public class Vala
.CodeGenerator
{
27 private void process_cmember (MemberAccess
! expr
, CCodeExpression pub_inst
, DataType base_type
) {
28 if (expr
.symbol_reference
.node is Method
) {
29 var m
= (Method
) expr
.symbol_reference
.node
;
31 if (expr
.inner is BaseAccess
) {
32 if (m
.base_interface_method
!= null) {
33 var base_iface
= (Interface
) m
.base_interface_method
.symbol
.parent_symbol
.node
;
34 string parent_iface_var
= "%s_%s_parent_iface".printf (current_class
.get_lower_case_cname (null), base_iface
.get_lower_case_cname (null));
36 expr
.ccodenode
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier (parent_iface_var
), m
.name
);
38 } else if (m
.base_method
!= null) {
39 var base_class
= (Class
) m
.base_method
.symbol
.parent_symbol
.node
;
40 var vcast
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_CLASS".printf (base_class
.get_upper_case_cname (null))));
41 vcast
.add_argument (new
CCodeIdentifier ("%s_parent_class".printf (current_class
.get_lower_case_cname (null))));
43 expr
.ccodenode
= new CCodeMemberAccess
.pointer (vcast
, m
.name
);
48 if (m
.base_interface_method
!= null) {
49 expr
.ccodenode
= new
CCodeIdentifier (m
.base_interface_method
.get_cname ());
50 } else if (m
.base_method
!= null) {
51 expr
.ccodenode
= new
CCodeIdentifier (m
.base_method
.get_cname ());
53 expr
.ccodenode
= new
CCodeIdentifier (m
.get_cname ());
55 } else if (expr
.symbol_reference
.node is ArrayLengthField
) {
56 expr
.ccodenode
= get_array_length_cexpression (expr
.inner
, 1);
57 } else if (expr
.symbol_reference
.node is Field
) {
58 var f
= (Field
) expr
.symbol_reference
.node
;
60 CCodeExpression typed_inst
;
61 if (f
.symbol
.parent_symbol
.node
!= base_type
) {
62 // FIXME: use C cast if debugging disabled
63 typed_inst
= new
CCodeFunctionCall (new
CCodeIdentifier (((DataType
) f
.symbol
.parent_symbol
.node
).get_upper_case_cname (null)));
64 ((CCodeFunctionCall
) typed_inst
).add_argument (pub_inst
);
66 typed_inst
= pub_inst
;
69 if (f
.access
== MemberAccessibility
.PRIVATE
) {
70 inst
= new CCodeMemberAccess
.pointer (typed_inst
, "priv");
74 if (((DataType
) f
.symbol
.parent_symbol
.node
).is_reference_type ()) {
75 expr
.ccodenode
= new CCodeMemberAccess
.pointer (inst
, f
.get_cname ());
77 expr
.ccodenode
= new
CCodeMemberAccess (inst
, f
.get_cname ());
80 expr
.ccodenode
= new
CCodeIdentifier (f
.get_cname ());
82 } else if (expr
.symbol_reference
.node is Constant
) {
83 var c
= (Constant
) expr
.symbol_reference
.node
;
84 expr
.ccodenode
= new
CCodeIdentifier (c
.get_cname ());
85 } else if (expr
.symbol_reference
.node is Property
) {
86 var prop
= (Property
) expr
.symbol_reference
.node
;
88 if (!prop
.no_accessor_method
) {
89 var base_property
= prop
;
90 if (prop
.base_property
!= null) {
91 base_property
= prop
.base_property
;
92 } else if (prop
.base_interface_property
!= null) {
93 base_property
= prop
.base_interface_property
;
95 var base_property_type
= (DataType
) base_property
.symbol
.parent_symbol
.node
;
96 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_get_%s".printf (base_property_type
.get_lower_case_cname (null), base_property
.name
)));
98 CCodeExpression typed_pub_inst
= pub_inst
;
100 /* cast if necessary */
101 if (base_property_type
!= base_type
) {
102 // FIXME: use C cast if debugging disabled
103 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier (base_property_type
.get_upper_case_cname (null)));
104 ccast
.add_argument (pub_inst
);
105 typed_pub_inst
= ccast
;
108 ccall
.add_argument (typed_pub_inst
);
109 expr
.ccodenode
= ccall
;
111 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_get"));
113 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT"));
114 ccast
.add_argument (pub_inst
);
115 ccall
.add_argument (ccast
);
117 // property name is second argument of g_object_get
118 ccall
.add_argument (prop
.get_canonical_cconstant ());
121 // we need a temporary variable to save the property value
122 var temp_decl
= get_temp_variable_declarator (expr
.static_type
);
123 temp_vars
.prepend (temp_decl
);
125 var ctemp
= new
CCodeIdentifier (temp_decl
.name
);
126 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, ctemp
));
129 ccall
.add_argument (new
CCodeConstant ("NULL"));
131 var ccomma
= new
CCodeCommaExpression ();
132 ccomma
.append_expression (ccall
);
133 ccomma
.append_expression (ctemp
);
134 expr
.ccodenode
= ccomma
;
136 } else if (expr
.symbol_reference
.node is EnumValue
) {
137 var ev
= (EnumValue
) expr
.symbol_reference
.node
;
138 expr
.ccodenode
= new
CCodeConstant (ev
.get_cname ());
139 } else if (expr
.symbol_reference
.node is VariableDeclarator
) {
140 var decl
= (VariableDeclarator
) expr
.symbol_reference
.node
;
141 expr
.ccodenode
= new
CCodeIdentifier (get_variable_cname (decl
.name
));
142 } else if (expr
.symbol_reference
.node is FormalParameter
) {
143 var p
= (FormalParameter
) expr
.symbol_reference
.node
;
144 if (p
.name
== "this") {
145 expr
.ccodenode
= pub_inst
;
147 if (p
.type_reference
.is_out
|| p
.type_reference
.is_ref
) {
148 expr
.ccodenode
= new
CCodeIdentifier ("(*%s)".printf (p
.name
));
150 expr
.ccodenode
= new
CCodeIdentifier (p
.name
);
153 } else if (expr
.symbol_reference
.node is Signal
) {
154 var sig
= (Signal
) expr
.symbol_reference
.node
;
155 var cl
= (DataType
) sig
.symbol
.parent_symbol
.node
;
157 if (sig
.has_emitter
) {
158 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("%s_%s".printf (cl
.get_lower_case_cname (null), sig
.name
)));
160 /* explicitly use strong reference as ccast
161 * gets unrefed at the end of the inner block
163 CCodeExpression typed_pub_inst
= pub_inst
;
165 /* cast if necessary */
166 if (cl
!= base_type
) {
167 // FIXME: use C cast if debugging disabled
168 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier (cl
.get_upper_case_cname (null)));
169 ccast
.add_argument (pub_inst
);
170 typed_pub_inst
= ccast
;
173 ccall
.add_argument (typed_pub_inst
);
174 expr
.ccodenode
= ccall
;
176 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_signal_emit_by_name"));
178 // FIXME: use C cast if debugging disabled
179 var ccast
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT"));
180 ccast
.add_argument (pub_inst
);
181 ccall
.add_argument (ccast
);
183 ccall
.add_argument (sig
.get_canonical_cconstant ());
185 expr
.ccodenode
= ccall
;
190 public override void visit_member_access (MemberAccess
! expr
) {
191 CCodeExpression pub_inst
= null;
192 DataType base_type
= null;
194 if (expr
.inner
== null) {
195 pub_inst
= new
CCodeIdentifier ("self");
197 if (current_type_symbol
!= null) {
198 /* base type is available if this is a type method */
199 base_type
= (DataType
) current_type_symbol
.node
;
201 if (!base_type
.is_reference_type ()) {
202 pub_inst
= new
CCodeIdentifier ("(*self)");
206 pub_inst
= (CCodeExpression
) expr
.inner
.ccodenode
;
208 if (expr
.inner
.static_type
!= null) {
209 base_type
= expr
.inner
.static_type
.data_type
;
213 process_cmember (expr
, pub_inst
, base_type
);
215 visit_expression (expr
);