posix: Fix SockAddr cname.
[vala-lang.git] / codegen / valagasyncmodule.vala
blobe8c93b90cc697b2bcc356775282fb5fd96cc72cf
1 /* valagasyncmodule.vala
3 * Copyright (C) 2008-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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 using GLib;
25 public class Vala.GAsyncModule : GSignalModule {
26 CCodeStruct generate_data_struct (Method m) {
27 string dataname = Symbol.lower_case_to_camel_case (m.get_cname ()) + "Data";
28 var data = new CCodeStruct ("_" + dataname);
30 data.add_field ("int", "_state_");
31 data.add_field ("GAsyncResult*", "_res_");
32 data.add_field ("GSimpleAsyncResult*", "_async_result");
34 if (m.binding == MemberBinding.INSTANCE) {
35 var type_sym = (TypeSymbol) m.parent_symbol;
36 data.add_field (type_sym.get_cname () + "*", "self");
39 foreach (FormalParameter param in m.get_parameters ()) {
40 var param_type = param.variable_type.copy ();
41 param_type.value_owned = true;
42 data.add_field (param_type.get_cname (), get_variable_cname (param.name));
44 if (param.variable_type is ArrayType) {
45 var array_type = (ArrayType) param.variable_type;
46 if (!param.no_array_length) {
47 for (int dim = 1; dim <= array_type.rank; dim++) {
48 data.add_field ("gint", get_array_length_cname (get_variable_cname (param.name), dim));
51 } else if (param.variable_type is DelegateType) {
52 var deleg_type = (DelegateType) param.variable_type;
53 if (deleg_type.delegate_symbol.has_target) {
54 data.add_field ("gpointer", get_delegate_target_cname (get_variable_cname (param.name)));
55 data.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)));
60 if (!(m.return_type is VoidType)) {
61 data.add_field (m.return_type.get_cname (), "result");
62 if (m.return_type is ArrayType) {
63 var array_type = (ArrayType) m.return_type;
64 if (!m.no_array_length) {
65 for (int dim = 1; dim <= array_type.rank; dim++) {
66 data.add_field ("gint", get_array_length_cname ("result", dim));
69 } else if (m.return_type is DelegateType) {
70 var deleg_type = (DelegateType) m.return_type;
71 if (deleg_type.delegate_symbol.has_target) {
72 data.add_field ("gpointer", get_delegate_target_cname ("result"));
73 data.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname ("result"));
78 return data;
81 CCodeFunction generate_free_function (Method m) {
82 var dataname = Symbol.lower_case_to_camel_case (m.get_cname ()) + "Data";
84 var freefunc = new CCodeFunction (m.get_real_cname () + "_data_free", "void");
85 freefunc.modifiers = CCodeModifiers.STATIC;
86 freefunc.add_parameter (new CCodeFormalParameter ("_data", "gpointer"));
88 var freeblock = new CCodeBlock ();
89 freefunc.block = freeblock;
91 var datadecl = new CCodeDeclaration (dataname + "*");
92 datadecl.add_declarator (new CCodeVariableDeclarator ("data", new CCodeIdentifier ("_data")));
93 freeblock.add_statement (datadecl);
95 push_context (new EmitContext (m));
97 foreach (FormalParameter param in m.get_parameters ()) {
98 if (param.direction != ParameterDirection.OUT) {
99 var param_type = param.variable_type.copy ();
100 param_type.value_owned = true;
102 if (requires_destroy (param_type)) {
103 var ma = new MemberAccess.simple (param.name);
104 ma.symbol_reference = param;
105 ma.value_type = param.variable_type.copy ();
106 freeblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_variable_cname (param.name)), param.variable_type, ma)));
111 if (requires_destroy (m.return_type)) {
112 /* this is very evil. */
113 var v = new LocalVariable (m.return_type, ".result");
114 var ma = new MemberAccess.simple (".result");
115 ma.symbol_reference = v;
116 var unref_expr = get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "result"), m.return_type, ma);
117 freeblock.add_statement (new CCodeExpressionStatement (unref_expr));
120 var cl = m.parent_symbol as Class;
121 if (m.binding == MemberBinding.INSTANCE && cl != null) {
122 var unref_func = cl.get_unref_function ();
124 if (unref_func != null) {
125 var unref_call = new CCodeFunctionCall (new CCodeIdentifier (unref_func));
126 unref_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "self"));
127 freeblock.add_statement (new CCodeExpressionStatement (unref_call));
131 pop_context ();
133 var freecall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
134 freecall.add_argument (new CCodeIdentifier (dataname));
135 freecall.add_argument (new CCodeIdentifier ("data"));
136 freeblock.add_statement (new CCodeExpressionStatement (freecall));
138 return freefunc;
141 CCodeFunction generate_async_function (Method m) {
142 var asyncblock = new CCodeBlock ();
144 // logic copied from valaccodemethodmodule
145 if (m.overrides || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) {
146 Method base_method;
148 if (m.overrides) {
149 base_method = m.base_method;
150 } else {
151 base_method = m.base_interface_method;
154 var base_expression_type = new ObjectType ((ObjectTypeSymbol) base_method.parent_symbol);
155 var type_symbol = m.parent_symbol as ObjectTypeSymbol;
157 var self_target_type = new ObjectType (type_symbol);
158 var cself = transform_expression (new CCodeIdentifier ("base"), base_expression_type, self_target_type);
159 var cdecl = new CCodeDeclaration ("%s *".printf (type_symbol.get_cname ()));
160 cdecl.add_declarator (new CCodeVariableDeclarator ("self", cself));
161 asyncblock.add_statement (cdecl);
164 var dataname = Symbol.lower_case_to_camel_case (m.get_cname ()) + "Data";
165 var asyncfunc = new CCodeFunction (m.get_real_cname (), "void");
166 var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
168 var dataalloc = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0"));
169 dataalloc.add_argument (new CCodeIdentifier (dataname));
171 var data_var = new CCodeIdentifier ("_data_");
173 var datadecl = new CCodeDeclaration (dataname + "*");
174 datadecl.add_declarator (new CCodeVariableDeclarator ("_data_"));
175 asyncblock.add_statement (datadecl);
176 asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (data_var, dataalloc)));
178 var create_result = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_new"));
180 var cl = m.parent_symbol as Class;
181 if (m.binding == MemberBinding.INSTANCE &&
182 cl != null && cl.is_subtype_of (gobject_type)) {
183 var gobject_cast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT"));
184 gobject_cast.add_argument (new CCodeIdentifier ("self"));
186 create_result.add_argument (gobject_cast);
187 } else {
188 if (context.require_glib_version (2, 20)) {
189 create_result.add_argument (new CCodeConstant ("NULL"));
190 } else {
191 var object_creation = new CCodeFunctionCall (new CCodeIdentifier ("g_object_newv"));
192 object_creation.add_argument (new CCodeConstant ("G_TYPE_OBJECT"));
193 object_creation.add_argument (new CCodeConstant ("0"));
194 object_creation.add_argument (new CCodeConstant ("NULL"));
196 create_result.add_argument (object_creation);
200 create_result.add_argument (new CCodeIdentifier ("_callback_"));
201 create_result.add_argument (new CCodeIdentifier ("_user_data_"));
202 create_result.add_argument (new CCodeIdentifier (m.get_real_cname ()));
204 asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, "_async_result"), create_result)));
206 var set_op_res_call = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_set_op_res_gpointer"));
207 set_op_res_call.add_argument (new CCodeMemberAccess.pointer (data_var, "_async_result"));
208 set_op_res_call.add_argument (data_var);
209 set_op_res_call.add_argument (new CCodeIdentifier (m.get_real_cname () + "_data_free"));
210 asyncblock.add_statement (new CCodeExpressionStatement (set_op_res_call));
212 if (m.binding == MemberBinding.INSTANCE) {
213 CCodeExpression self_expr = new CCodeIdentifier ("self");
214 string? ref_function = null;
216 if (cl != null && (ref_function = cl.get_ref_function ()) != null) {
217 var refcall = new CCodeFunctionCall (new CCodeIdentifier (ref_function));
218 refcall.add_argument (self_expr);
219 self_expr = refcall;
222 asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, "self"), self_expr)));
225 foreach (FormalParameter param in m.get_parameters ()) {
226 if (param.direction != ParameterDirection.OUT) {
227 var param_type = param.variable_type.copy ();
228 param_type.value_owned = true;
230 // create copy if necessary as variables in async methods may need to be kept alive
231 CCodeExpression cparam = get_variable_cexpression (param.name);
232 if (param.variable_type.is_real_non_null_struct_type ()) {
233 cparam = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, cparam);
235 if (requires_copy (param_type) && !param.variable_type.value_owned) {
236 var ma = new MemberAccess.simple (param.name);
237 ma.symbol_reference = param;
238 cparam = get_ref_cexpression (param.variable_type, cparam, ma, param);
241 asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name)), cparam)));
242 if (param.variable_type is ArrayType) {
243 var array_type = (ArrayType) param.variable_type;
244 if (!param.no_array_length) {
245 for (int dim = 1; dim <= array_type.rank; dim++) {
246 asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_array_length_cname (get_variable_cname (param.name), dim)), new CCodeIdentifier (get_array_length_cname (get_variable_cname (param.name), dim)))));
249 } else if (param.variable_type is DelegateType) {
250 var deleg_type = (DelegateType) param.variable_type;
251 if (deleg_type.delegate_symbol.has_target) {
252 asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_delegate_target_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (param.name))))));
253 if (deleg_type.value_owned) {
254 asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))))));
261 var cfrag = new CCodeFragment ();
262 append_temp_decl (cfrag, temp_vars);
263 temp_vars.clear ();
264 asyncblock.add_statement (cfrag);
266 var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_real_cname () + "_co"));
267 ccall.add_argument (data_var);
268 asyncblock.add_statement (new CCodeExpressionStatement (ccall));
270 cparam_map.set (get_param_pos (-1), new CCodeFormalParameter ("_callback_", "GAsyncReadyCallback"));
271 cparam_map.set (get_param_pos (-0.9), new CCodeFormalParameter ("_user_data_", "gpointer"));
273 generate_cparameters (m, cfile, cparam_map, asyncfunc, null, null, null, 1);
275 if (m.base_method != null || m.base_interface_method != null) {
276 // declare *_real_* function
277 asyncfunc.modifiers |= CCodeModifiers.STATIC;
278 cfile.add_type_member_declaration (asyncfunc.copy ());
279 } else if (m.is_private_symbol ()) {
280 asyncfunc.modifiers |= CCodeModifiers.STATIC;
283 asyncfunc.block = asyncblock;
285 return asyncfunc;
288 void append_struct (CCodeStruct structure) {
289 var typename = new CCodeVariableDeclarator (structure.name.substring (1));
290 var typedef = new CCodeTypeDefinition ("struct " + structure.name, typename);
291 cfile.add_type_declaration (typedef);
292 cfile.add_type_definition (structure);
295 void append_function (CCodeFunction function) {
296 var block = function.block;
297 function.block = null;
299 cfile.add_type_member_declaration (function.copy ());
301 function.block = block;
302 cfile.add_function (function);
305 public override void generate_method_declaration (Method m, CCodeFile decl_space) {
306 if (m.coroutine) {
307 if (add_symbol_declaration (decl_space, m, m.get_cname ())) {
308 return;
311 var asyncfunc = new CCodeFunction (m.get_cname (), "void");
312 var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
313 cparam_map.set (get_param_pos (-1), new CCodeFormalParameter ("_callback_", "GAsyncReadyCallback"));
314 cparam_map.set (get_param_pos (-0.9), new CCodeFormalParameter ("_user_data_", "gpointer"));
316 generate_cparameters (m, decl_space, cparam_map, asyncfunc, null, null, null, 1);
318 if (m.is_private_symbol ()) {
319 asyncfunc.modifiers |= CCodeModifiers.STATIC;
322 decl_space.add_type_member_declaration (asyncfunc);
324 var finishfunc = new CCodeFunction (m.get_finish_cname ());
325 cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
326 cparam_map.set (get_param_pos (0.1), new CCodeFormalParameter ("_res_", "GAsyncResult*"));
328 generate_cparameters (m, decl_space, cparam_map, finishfunc, null, null, null, 2);
330 if (m.is_private_symbol ()) {
331 finishfunc.modifiers |= CCodeModifiers.STATIC;
334 decl_space.add_type_member_declaration (finishfunc);
335 } else {
336 base.generate_method_declaration (m, decl_space);
340 public override void visit_method (Method m) {
341 if (m.coroutine) {
342 cfile.add_include ("gio/gio.h");
343 if (!m.is_internal_symbol ()) {
344 header_file.add_include ("gio/gio.h");
347 if (!m.is_abstract && m.body != null) {
348 var data = generate_data_struct (m);
350 append_function (generate_free_function (m));
351 cfile.add_function (generate_async_function (m));
352 cfile.add_function (generate_finish_function (m));
353 append_function (generate_ready_function (m));
355 // append the _co function
356 closure_struct = data;
357 base.visit_method (m);
358 closure_struct = null;
360 // only append data struct here to make sure all struct member
361 // types are declared before the struct definition
362 append_struct (data);
363 } else {
364 generate_method_declaration (m, cfile);
366 if (!m.is_internal_symbol ()) {
367 generate_method_declaration (m, header_file);
369 if (!m.is_private_symbol ()) {
370 generate_method_declaration (m, internal_header_file);
374 if (m.is_abstract || m.is_virtual) {
375 // generate virtual function wrappers
376 var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
377 var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
378 generate_vfunc (m, new VoidType (), cparam_map, carg_map, "", 1);
380 cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
381 carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
382 generate_vfunc (m, m.return_type, cparam_map, carg_map, "_finish", 2);
384 } else {
385 base.visit_method (m);
390 CCodeFunction generate_finish_function (Method m) {
391 string dataname = Symbol.lower_case_to_camel_case (m.get_cname ()) + "Data";
393 var finishfunc = new CCodeFunction (m.get_finish_real_cname ());
395 var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
397 var finishblock = new CCodeBlock ();
399 var return_type = m.return_type;
400 if (!(return_type is VoidType) && !return_type.is_real_non_null_struct_type ()) {
401 var cdecl = new CCodeDeclaration (m.return_type.get_cname ());
402 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
403 finishblock.add_statement (cdecl);
406 var data_var = new CCodeIdentifier ("_data_");
408 var datadecl = new CCodeDeclaration (dataname + "*");
409 datadecl.add_declarator (new CCodeVariableDeclarator ("_data_"));
410 finishblock.add_statement (datadecl);
412 var simple_async_result_cast = new CCodeFunctionCall (new CCodeIdentifier ("G_SIMPLE_ASYNC_RESULT"));
413 simple_async_result_cast.add_argument (new CCodeIdentifier ("_res_"));
415 if (m.get_error_types ().size > 0) {
416 // propagate error from async method
417 var propagate_error = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_propagate_error"));
418 propagate_error.add_argument (simple_async_result_cast);
419 propagate_error.add_argument (new CCodeIdentifier ("error"));
420 var errorblock = new CCodeBlock ();
421 if (return_type is VoidType || return_type.is_real_non_null_struct_type ()) {
422 errorblock.add_statement (new CCodeReturnStatement ());
423 } else {
424 errorblock.add_statement (new CCodeReturnStatement (default_value_for_type (return_type, false)));
426 finishblock.add_statement (new CCodeIfStatement (propagate_error, errorblock));
429 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_get_op_res_gpointer"));
430 ccall.add_argument (simple_async_result_cast);
431 finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (data_var, ccall)));
433 foreach (FormalParameter param in m.get_parameters ()) {
434 if (param.direction != ParameterDirection.IN) {
435 finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (param.name)), new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name)))));
436 if (!(param.variable_type is ValueType) || param.variable_type.nullable) {
437 finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name)), new CCodeConstant ("NULL"))));
442 if (return_type.is_real_non_null_struct_type ()) {
443 // structs are returned via out parameter
444 CCodeExpression cexpr = new CCodeMemberAccess.pointer (data_var, "result");
445 if (requires_copy (return_type)) {
446 cexpr = get_ref_cexpression (return_type, cexpr, null, return_type);
448 finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result")), cexpr)));
449 } else if (!(return_type is VoidType)) {
450 finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), new CCodeMemberAccess.pointer (data_var, "result"))));
451 if (return_type is ArrayType) {
452 var array_type = (ArrayType) return_type;
453 if (!m.no_array_length) {
454 for (int dim = 1; dim <= array_type.rank; dim++) {
455 finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_array_length_cname ("result", dim))), new CCodeMemberAccess.pointer (data_var, get_array_length_cname ("result", dim)))));
458 } else if (return_type is DelegateType && ((DelegateType) return_type).delegate_symbol.has_target) {
459 finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_delegate_target_cname ("result"))), new CCodeMemberAccess.pointer (data_var, get_delegate_target_cname ("result")))));
461 if (!(return_type is ValueType) || return_type.nullable) {
462 finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, "result"), new CCodeConstant ("NULL"))));
464 finishblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
467 var cfrag = new CCodeFragment ();
468 append_temp_decl (cfrag, temp_vars);
469 temp_vars.clear ();
470 finishblock.add_statement (cfrag);
472 cparam_map.set (get_param_pos (0.1), new CCodeFormalParameter ("_res_", "GAsyncResult*"));
474 generate_cparameters (m, cfile, cparam_map, finishfunc, null, null, null, 2);
476 if (m.is_private_symbol () || m.base_method != null || m.base_interface_method != null) {
477 finishfunc.modifiers |= CCodeModifiers.STATIC;
480 finishfunc.block = finishblock;
482 return finishfunc;
485 CCodeFunction generate_ready_function (Method m) {
486 // generate ready callback handler
487 var dataname = Symbol.lower_case_to_camel_case (m.get_cname ()) + "Data";
489 var readyfunc = new CCodeFunction (m.get_cname () + "_ready", "void");
491 readyfunc.add_parameter (new CCodeFormalParameter ("source_object", "GObject*"));
492 readyfunc.add_parameter (new CCodeFormalParameter ("_res_", "GAsyncResult*"));
493 readyfunc.add_parameter (new CCodeFormalParameter ("_user_data_", "gpointer"));
495 var readyblock = new CCodeBlock ();
497 var datadecl = new CCodeDeclaration (dataname + "*");
498 datadecl.add_declarator (new CCodeVariableDeclarator ("data"));
499 readyblock.add_statement (datadecl);
500 readyblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("data"), new CCodeIdentifier ("_user_data_"))));
501 readyblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_res_"), new CCodeIdentifier ("_res_"))));
503 var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_real_cname () + "_co"));
504 ccall.add_argument (new CCodeIdentifier ("data"));
505 readyblock.add_statement (new CCodeExpressionStatement (ccall));
507 readyfunc.modifiers |= CCodeModifiers.STATIC;
509 readyfunc.block = readyblock;
511 return readyfunc;
514 public override void generate_virtual_method_declaration (Method m, CCodeFile decl_space, CCodeStruct type_struct) {
515 if (!m.coroutine) {
516 base.generate_virtual_method_declaration (m, decl_space, type_struct);
517 return;
520 if (!m.is_abstract && !m.is_virtual) {
521 return;
524 var creturn_type = m.return_type;
525 if (m.return_type.is_real_non_null_struct_type ()) {
526 // structs are returned via out parameter
527 creturn_type = new VoidType ();
530 // add vfunc field to the type struct
531 var vdeclarator = new CCodeFunctionDeclarator (m.vfunc_name);
532 var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
534 generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator, null, null, 1);
536 var vdecl = new CCodeDeclaration ("void");
537 vdecl.add_declarator (vdeclarator);
538 type_struct.add_declaration (vdecl);
540 // add vfunc field to the type struct
541 vdeclarator = new CCodeFunctionDeclarator (m.get_finish_vfunc_name ());
542 cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
544 generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator, null, null, 2);
546 vdecl = new CCodeDeclaration (creturn_type.get_cname ());
547 vdecl.add_declarator (vdeclarator);
548 type_struct.add_declaration (vdecl);
551 public override void visit_yield_statement (YieldStatement stmt) {
552 if (current_method == null || !current_method.coroutine) {
553 stmt.ccodenode = new CCodeEmptyStatement ();
554 return;
557 if (stmt.yield_expression == null) {
558 var cfrag = new CCodeFragment ();
559 stmt.ccodenode = cfrag;
561 int state = next_coroutine_state++;
563 state_switch_statement.add_statement (new CCodeCaseStatement (new CCodeConstant (state.to_string ())));
564 state_switch_statement.add_statement (new CCodeGotoStatement ("_state_%d".printf (state)));
566 cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"), new CCodeConstant (state.to_string ()))));
567 cfrag.append (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
568 cfrag.append (new CCodeLabel ("_state_%d".printf (state)));
569 cfrag.append (new CCodeEmptyStatement ());
571 return;
574 if (stmt.yield_expression.error) {
575 stmt.error = true;
576 return;
579 stmt.ccodenode = new CCodeExpressionStatement ((CCodeExpression) stmt.yield_expression.ccodenode);
581 if (stmt.tree_can_fail && stmt.yield_expression.tree_can_fail) {
582 // simple case, no node breakdown necessary
584 var cfrag = new CCodeFragment ();
586 cfrag.append (stmt.ccodenode);
588 add_simple_check (stmt.yield_expression, cfrag);
590 stmt.ccodenode = cfrag;
593 /* free temporary objects */
595 if (((List<LocalVariable>) temp_vars).size == 0) {
596 /* nothing to do without temporary variables */
597 return;
600 var cfrag = new CCodeFragment ();
601 append_temp_decl (cfrag, temp_vars);
603 cfrag.append (stmt.ccodenode);
605 foreach (LocalVariable local in temp_ref_vars) {
606 var ma = new MemberAccess.simple (local.name);
607 ma.symbol_reference = local;
608 cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (local.name), local.variable_type, ma)));
611 stmt.ccodenode = cfrag;
613 temp_vars.clear ();
614 temp_ref_vars.clear ();
617 public override CCodeStatement return_with_exception (CCodeExpression error_expr)
619 if (!current_method.coroutine) {
620 return base.return_with_exception (error_expr);
623 var block = new CCodeBlock ();
625 var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_set_from_error"));
626 set_error.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_async_result"));
627 set_error.add_argument (error_expr);
628 block.add_statement (new CCodeExpressionStatement (set_error));
630 var free_error = new CCodeFunctionCall (new CCodeIdentifier ("g_error_free"));
631 free_error.add_argument (error_expr);
632 block.add_statement (new CCodeExpressionStatement (free_error));
634 var free_locals = new CCodeFragment ();
635 append_local_free (current_symbol, free_locals, false);
636 block.add_statement (free_locals);
638 block.add_statement (complete_async ());
640 return block;
643 public override void visit_return_statement (ReturnStatement stmt) {
644 base.visit_return_statement (stmt);
646 if (current_method == null || !current_method.coroutine) {
647 return;
650 var cfrag = (CCodeFragment) stmt.ccodenode;
652 cfrag.append (complete_async ());
655 public override void generate_cparameters (Method m, CCodeFile decl_space, Map<int,CCodeFormalParameter> cparam_map, CCodeFunction func, CCodeFunctionDeclarator? vdeclarator = null, Map<int,CCodeExpression>? carg_map = null, CCodeFunctionCall? vcall = null, int direction = 3) {
656 if (m.coroutine) {
657 decl_space.add_include ("gio/gio.h");
659 if (direction == 1) {
660 cparam_map.set (get_param_pos (-1), new CCodeFormalParameter ("_callback_", "GAsyncReadyCallback"));
661 cparam_map.set (get_param_pos (-0.9), new CCodeFormalParameter ("_user_data_", "gpointer"));
662 if (carg_map != null) {
663 carg_map.set (get_param_pos (-1), new CCodeIdentifier ("_callback_"));
664 carg_map.set (get_param_pos (-0.9), new CCodeIdentifier ("_user_data_"));
666 } else if (direction == 2) {
667 cparam_map.set (get_param_pos (0.1), new CCodeFormalParameter ("_res_", "GAsyncResult*"));
668 if (carg_map != null) {
669 carg_map.set (get_param_pos (0.1), new CCodeIdentifier ("_res_"));
673 base.generate_cparameters (m, decl_space, cparam_map, func, vdeclarator, carg_map, vcall, direction);
677 // vim:sw=8 noet