1 /* valacodegeneratorinvocationexpression.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 public override void visit_end_invocation_expression (InvocationExpression
! expr
) {
28 var ccall
= new
CCodeFunctionCall ((CCodeExpression
) expr
.call
.ccodenode
);
31 List
<weak FormalParameter
> params
;
33 if (!(expr
.call is MemberAccess
)) {
35 Report
.error (expr
.source_reference
, "unsupported method invocation");
39 var ma
= (MemberAccess
) expr
.call
;
41 if (expr
.call
.symbol_reference
.node is Invokable
) {
42 var i
= (Invokable
) expr
.call
.symbol_reference
.node
;
43 params
= i
.get_parameters ();
47 } else if (i is Signal
) {
48 ccall
= (CCodeFunctionCall
) expr
.call
.ccodenode
;
52 if (m is ArrayResizeMethod
) {
53 var array
= (Array
) m
.symbol
.parent_symbol
.node
;
54 ccall
.add_argument (new
CCodeIdentifier (array
.get_cname ()));
57 /* explicitly use strong reference as ccall gets unrefed
58 * at end of inner block
60 CCodeExpression instance
;
61 if (m
!= null && m
.instance
) {
63 if (m
.base_interface_method
!= null) {
64 base_method
= m
.base_interface_method
;
65 } else if (m
.base_method
!= null) {
66 base_method
= m
.base_method
;
70 if (ma
.inner
== null) {
71 instance
= new
CCodeIdentifier ("self");
72 /* require casts for overriden and inherited methods */
73 req_cast
= m
.overrides
|| m
.base_interface_method
!= null || (m
.symbol
.parent_symbol
!= current_type_symbol
);
75 instance
= (CCodeExpression
) ma
.inner
.ccodenode
;
76 /* reqiure casts if the type of the used instance is
77 * different than the type which declared the method */
78 req_cast
= base_method
.symbol
.parent_symbol
.node
!= ma
.inner
.static_type
.data_type
;
81 if (m
.instance_by_reference
&& (ma
.inner
!= null || m
.symbol
.parent_symbol
!= current_type_symbol
)) {
82 instance
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, instance
);
85 if (req_cast
&& ((DataType
) m
.symbol
.parent_symbol
.node
).is_reference_type ()) {
86 // FIXME: use C cast if debugging disabled
87 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (((DataType
) base_method
.symbol
.parent_symbol
.node
).get_upper_case_cname (null)));
88 ccall
.add_argument (instance
);
92 if (!m
.instance_last
) {
93 ccall
.add_argument (instance
);
97 bool ellipsis
= false;
100 weak List
<weak FormalParameter
> params_it
= params
;
101 foreach (Expression arg
in expr
.get_argument_list ()) {
102 /* explicitly use strong reference as ccall gets
103 * unrefed at end of inner block
105 CCodeExpression cexpr
= (CCodeExpression
) arg
.ccodenode
;
106 if (params_it
!= null) {
107 var param
= (FormalParameter
) params_it
.data
;
108 ellipsis
= param
.ellipsis
;
110 if (param
.type_reference
.data_type
!= null
111 && param
.type_reference
.data_type
.is_reference_type ()
112 && arg
.static_type
.data_type
!= null) {
113 if (!param
.no_array_length
&& param
.type_reference
.data_type is Array
) {
114 var arr
= (Array
) param
.type_reference
.data_type
;
115 for (int dim
= 1; dim
<= arr
.rank
; dim
++) {
116 ccall
.add_argument (get_array_length_cexpression (arg
, dim
));
119 if (param
.type_reference
.data_type
!= arg
.static_type
.data_type
) {
120 // FIXME: use C cast if debugging disabled
121 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (param
.type_reference
.data_type
.get_upper_case_cname (null)));
122 ccall
.add_argument (cexpr
);
125 } else if (param
.type_reference
.data_type is Callback
) {
126 cexpr
= new
CCodeCastExpression (cexpr
, param
.type_reference
.data_type
.get_cname ());
127 } else if (param
.type_reference
.data_type
== null
128 && arg
.static_type
.data_type is Struct
) {
129 /* convert integer to pointer if this is a generic method parameter */
130 var st
= (Struct
) arg
.static_type
.data_type
;
131 if (st
== bool_type
.data_type
|| st
.is_integer_type ()) {
132 var cconv
= new
CCodeFunctionCall (new
CCodeIdentifier ("GINT_TO_POINTER"));
133 cconv
.add_argument (cexpr
);
140 ccall
.add_argument (cexpr
);
143 if (params_it
!= null) {
144 params_it
= params_it
.next
;
147 while (params_it
!= null) {
148 var param
= (FormalParameter
) params_it
.data
;
150 if (param
.ellipsis
) {
155 if (param
.default_expression
== null) {
156 Report
.error (expr
.source_reference
, "no default expression for argument %d".printf (i
));
160 /* evaluate default expression here as the code
161 * generator might not have visited the formal
163 param
.default_expression
.accept (this
);
165 if (!param
.no_array_length
&& param
.type_reference
!= null &&
166 param
.type_reference
.data_type is Array
) {
167 var arr
= (Array
) param
.type_reference
.data_type
;
168 for (int dim
= 1; dim
<= arr
.rank
; dim
++) {
169 ccall
.add_argument (get_array_length_cexpression (param
.default_expression
, dim
));
173 ccall
.add_argument ((CCodeExpression
) param
.default_expression
.ccodenode
);
176 params_it
= params_it
.next
;
179 /* add length argument for methods returning arrays */
180 if (m
!= null && m
.return_type
.data_type is Array
) {
181 var arr
= (Array
) m
.return_type
.data_type
;
182 for (int dim
= 1; dim
<= arr
.rank
; dim
++) {
183 if (!m
.no_array_length
) {
184 var temp_decl
= get_temp_variable_declarator (int_type
);
185 var temp_ref
= new
CCodeIdentifier (temp_decl
.name
);
187 temp_vars
.prepend (temp_decl
);
189 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, temp_ref
));
191 expr
.append_array_size (temp_ref
);
193 expr
.append_array_size (new
CCodeConstant ("-1"));
198 if (m
!= null && m
.instance
&& m
.instance_last
) {
199 ccall
.add_argument (instance
);
200 } else if (ellipsis
) {
201 /* ensure variable argument list ends with NULL
202 * except when using printf-style arguments */
203 if (m
== null || !m
.printf_format
) {
204 ccall
.add_argument (new
CCodeConstant ("NULL"));
208 if (m
!= null && m
.instance
&& m
.returns_modified_pointer
) {
209 expr
.ccodenode
= new
CCodeAssignment (instance
, ccall
);
211 /* cast pointer to actual type if this is a generic method return value */
212 if (m
!= null && m
.return_type
.type_parameter
!= null && expr
.static_type
.data_type
!= null) {
213 if (expr
.static_type
.data_type is Struct
) {
214 var st
= (Struct
) expr
.static_type
.data_type
;
215 if (st
== uint_type
.data_type
) {
216 var cconv
= new
CCodeFunctionCall (new
CCodeIdentifier ("GPOINTER_TO_UINT"));
217 cconv
.add_argument (ccall
);
219 } else if (st
== bool_type
.data_type
|| st
.is_integer_type ()) {
220 var cconv
= new
CCodeFunctionCall (new
CCodeIdentifier ("GPOINTER_TO_INT"));
221 cconv
.add_argument (ccall
);
227 expr
.ccodenode
= ccall
;
229 visit_expression (expr
);
232 if (m is ArrayResizeMethod
) {
233 // FIXME: size expression must not be evaluated twice at runtime (potential side effects)
234 var new_size
= (CCodeExpression
) ((CodeNode
) expr
.get_argument_list ().data
).ccodenode
;
236 var temp_decl
= get_temp_variable_declarator (int_type
);
237 var temp_ref
= new
CCodeIdentifier (temp_decl
.name
);
239 temp_vars
.prepend (temp_decl
);
241 /* memset needs string.h */
242 string_h_needed
= true;
244 var clen
= get_array_length_cexpression (ma
.inner
, 1);
245 var celems
= (CCodeExpression
)ma
.inner
.ccodenode
;
246 var csizeof
= new
CCodeIdentifier ("sizeof (%s)".printf (ma
.inner
.static_type
.data_type
.get_cname ()));
247 var cdelta
= new
CCodeParenthesizedExpression (new
CCodeBinaryExpression (CCodeBinaryOperator
.MINUS
, temp_ref
, clen
));
248 var ccheck
= new
CCodeBinaryExpression (CCodeBinaryOperator
.GREATER_THAN
, temp_ref
, clen
);
250 var czero
= new
CCodeFunctionCall (new
CCodeIdentifier ("memset"));
251 czero
.add_argument (new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, celems
, clen
));
252 czero
.add_argument (new
CCodeConstant ("0"));
253 czero
.add_argument (new
CCodeBinaryExpression (CCodeBinaryOperator
.MUL
, csizeof
, cdelta
));
255 var ccomma
= new
CCodeCommaExpression ();
256 ccomma
.append_expression (new
CCodeAssignment (temp_ref
, new_size
));
257 ccomma
.append_expression ((CCodeExpression
) expr
.ccodenode
);
258 ccomma
.append_expression (new
CCodeConditionalExpression (ccheck
, czero
, new
CCodeConstant ("NULL")));
259 ccomma
.append_expression (new
CCodeAssignment (get_array_length_cexpression (ma
.inner
, 1), temp_ref
));
261 expr
.ccodenode
= ccomma
;