remove obsolete ref modifier and callback keyword
[vala-lang.git] / gobject / valacodegeneratorinvocationexpression.vala
blobcabe05d59a11d19fee37ec1f8fe605d7d8cb59f5
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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
21 * Raffaele Sandrini <rasa@gmx.ch>
24 using GLib;
26 public class Vala.CodeGenerator {
27 public override void visit_end_invocation_expression (InvocationExpression! expr) {
28 var ccall = new CCodeFunctionCall ((CCodeExpression) expr.call.ccodenode);
30 Method m = null;
31 List<weak FormalParameter> params;
33 if (!(expr.call is MemberAccess)) {
34 expr.error = true;
35 Report.error (expr.source_reference, "unsupported method invocation");
36 return;
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 ();
45 if (i is Method) {
46 m = (Method) i;
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) {
62 var base_method = m;
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;
69 var req_cast = false;
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);
74 } else {
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);
89 instance = ccall;
92 if (!m.instance_last) {
93 ccall.add_argument (instance);
97 bool ellipsis = false;
99 var i = 1;
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;
109 if (!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);
123 cexpr = ccall;
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);
134 cexpr = cconv;
140 ccall.add_argument (cexpr);
141 i++;
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) {
151 ellipsis = true;
152 break;
155 if (param.default_expression == null) {
156 Report.error (expr.source_reference, "no default expression for argument %d".printf (i));
157 return;
160 /* evaluate default expression here as the code
161 * generator might not have visited the formal
162 * parameter yet */
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);
174 i++;
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);
192 } else {
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);
210 } else {
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);
218 ccall = cconv;
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);
222 ccall = cconv;
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;