1 /* valagasyncmodule.vala
3 * Copyright (C) 2008-2009 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 internal class Vala
.GAsyncModule
: GSignalModule
{
26 public GAsyncModule (CCodeGenerator codegen
, CCodeModule? next
) {
30 CCodeStruct
generate_data_struct (Method m
) {
31 string dataname
= Symbol
.lower_case_to_camel_case (m
.get_cname ()) + "Data";
32 var data
= new
CCodeStruct ("_" + dataname
);
34 data
.add_field ("int", "_state_");
35 data
.add_field ("GAsyncResult*", "_res_");
36 data
.add_field ("GSimpleAsyncResult*", "_async_result");
38 if (m
.binding
== MemberBinding
.INSTANCE
) {
39 var type_sym
= (TypeSymbol
) m
.parent_symbol
;
40 data
.add_field (type_sym
.get_cname () + "*", "self");
43 foreach (FormalParameter param
in m
.get_parameters ()) {
44 var param_type
= param
.parameter_type
.copy ();
45 param_type
.value_owned
= true;
46 data
.add_field (param_type
.get_cname (), get_variable_cname (param
.name
));
48 if (param
.parameter_type is ArrayType
) {
49 var array_type
= (ArrayType
) param
.parameter_type
;
50 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
51 data
.add_field ("gint", get_array_length_cname (get_variable_cname (param
.name
), dim
));
53 } else if (param
.parameter_type is DelegateType
) {
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
)));
59 if (!(m
.return_type is VoidType
)) {
60 data
.add_field (m
.return_type
.get_cname (), "result");
61 if (m
.return_type is ArrayType
) {
62 var array_type
= (ArrayType
) m
.return_type
;
63 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
64 data
.add_field ("gint", get_array_length_cname ("result", dim
));
66 } else if (m
.return_type is DelegateType
) {
67 data
.add_field ("gpointer", get_delegate_target_cname ("result"));
68 data
.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname ("result"));
75 CCodeFunction
generate_free_function (Method m
) {
76 var dataname
= Symbol
.lower_case_to_camel_case (m
.get_cname ()) + "Data";
78 var freefunc
= new
CCodeFunction (m
.get_real_cname () + "_data_free", "void");
79 freefunc
.modifiers
= CCodeModifiers
.STATIC
;
80 freefunc
.add_parameter (new
CCodeFormalParameter ("_data", "gpointer"));
82 var freeblock
= new
CCodeBlock ();
83 freefunc
.block
= freeblock
;
85 var datadecl
= new
CCodeDeclaration (dataname
+ "*");
86 datadecl
.add_declarator (new
CCodeVariableDeclarator ("data", new
CCodeIdentifier ("_data")));
87 freeblock
.add_statement (datadecl
);
89 var old_symbol
= current_symbol
;
92 foreach (FormalParameter param
in m
.get_parameters ()) {
93 if (param
.direction
!= ParameterDirection
.OUT
) {
94 var param_type
= param
.parameter_type
.copy ();
95 param_type
.value_owned
= true;
97 if (requires_destroy (param_type
)) {
98 var ma
= new MemberAccess
.simple (param
.name
);
99 ma
.symbol_reference
= param
;
100 ma
.value_type
= param
.parameter_type
.copy ();
101 freeblock
.add_statement (new
CCodeExpressionStatement (get_unref_expression (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("data"), get_variable_cname (param
.name
)), param
.parameter_type
, ma
)));
106 if (requires_destroy (m
.return_type
)) {
107 /* this is very evil. */
108 var v
= new
LocalVariable (m
.return_type
, ".result");
109 var ma
= new MemberAccess
.simple (".result");
110 ma
.symbol_reference
= v
;
111 var unref_expr
= get_unref_expression (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("data"), "result"), m
.return_type
, ma
);
112 freeblock
.add_statement (new
CCodeExpressionStatement (unref_expr
));
115 current_symbol
= old_symbol
;
117 var freecall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_slice_free"));
118 freecall
.add_argument (new
CCodeIdentifier (dataname
));
119 freecall
.add_argument (new
CCodeIdentifier ("data"));
120 freeblock
.add_statement (new
CCodeExpressionStatement (freecall
));
125 CCodeFunction
generate_async_function (Method m
) {
126 var asyncblock
= new
CCodeBlock ();
128 // logic copied from valaccodemethodmodule
129 if (m
.overrides
|| (m
.base_interface_method
!= null && !m
.is_abstract
&& !m
.is_virtual
)) {
133 base_method
= m
.base_method
;
135 base_method
= m
.base_interface_method
;
138 var base_expression_type
= new
ObjectType ((ObjectTypeSymbol
) base_method
.parent_symbol
);
139 var type_symbol
= m
.parent_symbol as ObjectTypeSymbol
;
141 var self_target_type
= new
ObjectType (type_symbol
);
142 var cself
= transform_expression (new
CCodeIdentifier ("base"), base_expression_type
, self_target_type
);
143 var cdecl
= new
CCodeDeclaration ("%s *".printf (type_symbol
.get_cname ()));
144 cdecl
.add_declarator (new
CCodeVariableDeclarator ("self", cself
));
145 asyncblock
.add_statement (cdecl
);
148 var dataname
= Symbol
.lower_case_to_camel_case (m
.get_cname ()) + "Data";
149 var asyncfunc
= new
CCodeFunction (m
.get_real_cname (), "void");
150 var cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
152 var dataalloc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_slice_new0"));
153 dataalloc
.add_argument (new
CCodeIdentifier (dataname
));
155 var data_var
= new
CCodeIdentifier ("_data_");
157 var datadecl
= new
CCodeDeclaration (dataname
+ "*");
158 datadecl
.add_declarator (new
CCodeVariableDeclarator ("_data_"));
159 asyncblock
.add_statement (datadecl
);
160 asyncblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (data_var
, dataalloc
)));
162 var create_result
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_simple_async_result_new"));
164 var cl
= m
.parent_symbol as Class
;
165 if (m
.binding
== MemberBinding
.INSTANCE
&&
166 cl
!= null && cl
.is_subtype_of (gobject_type
)) {
167 var gobject_cast
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT"));
168 gobject_cast
.add_argument (new
CCodeIdentifier ("self"));
170 create_result
.add_argument (gobject_cast
);
172 create_result
.add_argument (new
CCodeConstant ("NULL"));
175 create_result
.add_argument (new
CCodeIdentifier ("_callback_"));
176 create_result
.add_argument (new
CCodeIdentifier ("_user_data_"));
177 create_result
.add_argument (new
CCodeIdentifier (m
.get_real_cname ()));
179 asyncblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (data_var
, "_async_result"), create_result
)));
181 var set_op_res_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_simple_async_result_set_op_res_gpointer"));
182 set_op_res_call
.add_argument (new CCodeMemberAccess
.pointer (data_var
, "_async_result"));
183 set_op_res_call
.add_argument (data_var
);
184 set_op_res_call
.add_argument (new
CCodeIdentifier (m
.get_real_cname () + "_data_free"));
185 asyncblock
.add_statement (new
CCodeExpressionStatement (set_op_res_call
));
187 if (m
.binding
== MemberBinding
.INSTANCE
) {
188 asyncblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (data_var
, "self"), new
CCodeIdentifier ("self"))));
191 foreach (FormalParameter param
in m
.get_parameters ()) {
192 if (param
.direction
!= ParameterDirection
.OUT
) {
193 var param_type
= param
.parameter_type
.copy ();
194 param_type
.value_owned
= true;
196 // create copy if necessary as variables in async methods may need to be kept alive
197 CCodeExpression cparam
= get_variable_cexpression (param
.name
);
198 if (requires_copy (param_type
) && !param
.parameter_type
.value_owned
) {
199 var ma
= new MemberAccess
.simple (param
.name
);
200 ma
.symbol_reference
= param
;
201 cparam
= get_ref_cexpression (param
.parameter_type
, cparam
, ma
, param
);
204 asyncblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (data_var
, get_variable_cname (param
.name
)), cparam
)));
205 if (param
.parameter_type is ArrayType
) {
206 var array_type
= (ArrayType
) param
.parameter_type
;
207 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
208 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
)))));
210 } else if (param
.parameter_type is DelegateType
) {
211 var deleg_type
= (DelegateType
) param
.parameter_type
;
212 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
))))));
213 if (deleg_type
.value_owned
) {
214 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
))))));
220 var cfrag
= new
CCodeFragment ();
221 append_temp_decl (cfrag
, temp_vars
);
223 asyncblock
.add_statement (cfrag
);
225 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (m
.get_real_cname () + "_co"));
226 ccall
.add_argument (data_var
);
227 asyncblock
.add_statement (new
CCodeExpressionStatement (ccall
));
229 cparam_map
.set (get_param_pos (-1), new
CCodeFormalParameter ("_callback_", "GAsyncReadyCallback"));
230 cparam_map
.set (get_param_pos (-0.9), new
CCodeFormalParameter ("_user_data_", "gpointer"));
232 generate_cparameters (m
, source_declarations
, cparam_map
, asyncfunc
, null, null, null, 1);
234 if (m
.base_method
!= null || m
.base_interface_method
!= null) {
235 // declare *_real_* function
236 asyncfunc
.modifiers
|= CCodeModifiers
.STATIC
;
237 source_declarations
.add_type_member_declaration (asyncfunc
.copy ());
238 } else if (m
.is_private_symbol ()) {
239 asyncfunc
.modifiers
|= CCodeModifiers
.STATIC
;
242 asyncfunc
.block
= asyncblock
;
247 void append_struct (CCodeStruct structure
) {
248 var typename
= new
CCodeVariableDeclarator (structure
.name
.substring (1));
249 var typedef
= new
CCodeTypeDefinition ("struct " + structure
.name
, typename
);
250 source_declarations
.add_type_declaration (typedef
);
251 source_declarations
.add_type_definition (structure
);
254 void append_function (CCodeFunction function
) {
255 var block
= function
.block
;
256 function
.block
= null;
258 source_declarations
.add_type_member_declaration (function
.copy ());
260 function
.block
= block
;
261 source_type_member_definition
.append (function
);
264 public override void generate_method_declaration (Method m
, CCodeDeclarationSpace decl_space
) {
266 if (decl_space
.add_symbol_declaration (m
, m
.get_cname ())) {
270 var asyncfunc
= new
CCodeFunction (m
.get_cname (), "void");
271 var cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
272 cparam_map
.set (get_param_pos (-1), new
CCodeFormalParameter ("_callback_", "GAsyncReadyCallback"));
273 cparam_map
.set (get_param_pos (-0.9), new
CCodeFormalParameter ("_user_data_", "gpointer"));
275 generate_cparameters (m
, decl_space
, cparam_map
, asyncfunc
, null, null, null, 1);
277 if (m
.is_private_symbol ()) {
278 asyncfunc
.modifiers
|= CCodeModifiers
.STATIC
;
281 decl_space
.add_type_member_declaration (asyncfunc
);
283 var finishfunc
= new
CCodeFunction (m
.get_finish_cname ());
284 cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
285 cparam_map
.set (get_param_pos (0.1), new
CCodeFormalParameter ("_res_", "GAsyncResult*"));
287 generate_cparameters (m
, decl_space
, cparam_map
, finishfunc
, null, null, null, 2);
289 if (m
.is_private_symbol ()) {
290 finishfunc
.modifiers
|= CCodeModifiers
.STATIC
;
293 decl_space
.add_type_member_declaration (finishfunc
);
295 base.generate_method_declaration (m
, decl_space
);
299 public override void visit_method (Method m
) {
301 source_declarations
.add_include ("gio/gio.h");
302 if (!m
.is_internal_symbol ()) {
303 header_declarations
.add_include ("gio/gio.h");
306 if (!m
.is_abstract
) {
307 var data
= generate_data_struct (m
);
309 append_function (generate_free_function (m
));
310 source_type_member_definition
.append (generate_async_function (m
));
311 source_type_member_definition
.append (generate_finish_function (m
));
312 append_function (generate_ready_function (m
));
314 // append the _co function
315 closure_struct
= data
;
316 base.visit_method (m
);
317 closure_struct
= null;
319 // only append data struct here to make sure all struct member
320 // types are declared before the struct definition
321 append_struct (data
);
324 if (m
.is_abstract
|| m
.is_virtual
) {
325 // generate virtual function wrappers
326 var cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
327 var carg_map
= new HashMap
<int,CCodeExpression
> (direct_hash
, direct_equal
);
328 generate_vfunc (m
, new
VoidType (), cparam_map
, carg_map
, "", 1);
330 cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
331 carg_map
= new HashMap
<int,CCodeExpression
> (direct_hash
, direct_equal
);
332 generate_vfunc (m
, m
.return_type
, cparam_map
, carg_map
, "_finish", 2);
335 base.visit_method (m
);
340 CCodeFunction
generate_finish_function (Method m
) {
341 string dataname
= Symbol
.lower_case_to_camel_case (m
.get_cname ()) + "Data";
343 var finishfunc
= new
CCodeFunction (m
.get_finish_real_cname ());
345 var cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
347 var finishblock
= new
CCodeBlock ();
349 var return_type
= m
.return_type
;
350 if (!(return_type is VoidType
)) {
351 var cdecl
= new
CCodeDeclaration (m
.return_type
.get_cname ());
352 cdecl
.add_declarator (new
CCodeVariableDeclarator ("result"));
353 finishblock
.add_statement (cdecl
);
356 var data_var
= new
CCodeIdentifier ("_data_");
358 var datadecl
= new
CCodeDeclaration (dataname
+ "*");
359 datadecl
.add_declarator (new
CCodeVariableDeclarator ("_data_"));
360 finishblock
.add_statement (datadecl
);
362 var simple_async_result_cast
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_SIMPLE_ASYNC_RESULT"));
363 simple_async_result_cast
.add_argument (new
CCodeIdentifier ("_res_"));
365 if (m
.get_error_types ().size
> 0) {
366 // propagate error from async method
367 var propagate_error
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_simple_async_result_propagate_error"));
368 propagate_error
.add_argument (simple_async_result_cast
);
369 propagate_error
.add_argument (new
CCodeIdentifier ("error"));
370 var errorblock
= new
CCodeBlock ();
371 if (return_type is VoidType
) {
372 errorblock
.add_statement (new
CCodeReturnStatement ());
374 errorblock
.add_statement (new
CCodeReturnStatement (default_value_for_type (return_type
, false)));
376 finishblock
.add_statement (new
CCodeIfStatement (propagate_error
, errorblock
));
379 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_simple_async_result_get_op_res_gpointer"));
380 ccall
.add_argument (simple_async_result_cast
);
381 finishblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (data_var
, ccall
)));
383 foreach (FormalParameter param
in m
.get_parameters ()) {
384 if (param
.direction
!= ParameterDirection
.IN
) {
385 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
)))));
386 finishblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (data_var
, get_variable_cname (param
.name
)), new
CCodeConstant ("NULL"))));
390 if (!(return_type is VoidType
)) {
391 finishblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("result"), new CCodeMemberAccess
.pointer (data_var
, "result"))));
392 if (return_type is ArrayType
) {
393 var array_type
= (ArrayType
) return_type
;
394 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
395 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
)))));
397 } else if (return_type is DelegateType
) {
398 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")))));
400 if (!(return_type is ValueType
) || return_type
.nullable
) {
401 finishblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (data_var
, "result"), new
CCodeConstant ("NULL"))));
403 finishblock
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("result")));
406 cparam_map
.set (get_param_pos (0.1), new
CCodeFormalParameter ("_res_", "GAsyncResult*"));
408 generate_cparameters (m
, source_declarations
, cparam_map
, finishfunc
, null, null, null, 2);
410 if (m
.is_private_symbol () || m
.base_method
!= null || m
.base_interface_method
!= null) {
411 finishfunc
.modifiers
|= CCodeModifiers
.STATIC
;
414 finishfunc
.block
= finishblock
;
419 CCodeFunction
generate_ready_function (Method m
) {
420 // generate ready callback handler
421 var dataname
= Symbol
.lower_case_to_camel_case (m
.get_cname ()) + "Data";
423 var readyfunc
= new
CCodeFunction (m
.get_cname () + "_ready", "void");
425 readyfunc
.add_parameter (new
CCodeFormalParameter ("source_object", "GObject*"));
426 readyfunc
.add_parameter (new
CCodeFormalParameter ("_res_", "GAsyncResult*"));
427 readyfunc
.add_parameter (new
CCodeFormalParameter ("_user_data_", "gpointer"));
429 var readyblock
= new
CCodeBlock ();
431 var datadecl
= new
CCodeDeclaration (dataname
+ "*");
432 datadecl
.add_declarator (new
CCodeVariableDeclarator ("data"));
433 readyblock
.add_statement (datadecl
);
434 readyblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("data"), new
CCodeIdentifier ("_user_data_"))));
435 readyblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("data"), "_res_"), new
CCodeIdentifier ("_res_"))));
437 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (m
.get_real_cname () + "_co"));
438 ccall
.add_argument (new
CCodeIdentifier ("data"));
439 readyblock
.add_statement (new
CCodeExpressionStatement (ccall
));
441 readyfunc
.modifiers
|= CCodeModifiers
.STATIC
;
443 readyfunc
.block
= readyblock
;
448 public override void generate_virtual_method_declaration (Method m
, CCodeDeclarationSpace decl_space
, CCodeStruct type_struct
) {
450 base.generate_virtual_method_declaration (m
, decl_space
, type_struct
);
454 if (!m
.is_abstract
&& !m
.is_virtual
) {
458 // add vfunc field to the type struct
459 var vdeclarator
= new
CCodeFunctionDeclarator (m
.vfunc_name
);
460 var cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
462 generate_cparameters (m
, decl_space
, cparam_map
, new
CCodeFunction ("fake"), vdeclarator
, null, null, 1);
464 var vdecl
= new
CCodeDeclaration ("void");
465 vdecl
.add_declarator (vdeclarator
);
466 type_struct
.add_declaration (vdecl
);
468 // add vfunc field to the type struct
469 vdeclarator
= new
CCodeFunctionDeclarator (m
.get_finish_vfunc_name ());
470 cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
472 generate_cparameters (m
, decl_space
, cparam_map
, new
CCodeFunction ("fake"), vdeclarator
, null, null, 2);
474 vdecl
= new
CCodeDeclaration (m
.return_type
.get_cname ());
475 vdecl
.add_declarator (vdeclarator
);
476 type_struct
.add_declaration (vdecl
);
479 public override void visit_yield_statement (YieldStatement stmt
) {
480 if (current_method
== null || !current_method
.coroutine
) {
481 stmt
.ccodenode
= new
CCodeEmptyStatement ();
485 if (stmt
.yield_expression
== null) {
486 var cfrag
= new
CCodeFragment ();
487 stmt
.ccodenode
= cfrag
;
489 int state
= next_coroutine_state
++;
491 cfrag
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("data"), "_state_"), new
CCodeConstant (state
.to_string ()))));
492 cfrag
.append (new
CCodeReturnStatement (new
CCodeConstant ("FALSE")));
493 cfrag
.append (new
CCodeCaseStatement (new
CCodeConstant (state
.to_string ())));
494 cfrag
.append (new
CCodeEmptyStatement ());
499 stmt
.accept_children (codegen
);
501 if (stmt
.yield_expression
.error
) {
506 stmt
.ccodenode
= new
CCodeExpressionStatement ((CCodeExpression
) stmt
.yield_expression
.ccodenode
);
508 if (stmt
.tree_can_fail
&& stmt
.yield_expression
.tree_can_fail
) {
509 // simple case, no node breakdown necessary
511 var cfrag
= new
CCodeFragment ();
513 cfrag
.append (stmt
.ccodenode
);
515 head
.add_simple_check (stmt
.yield_expression
, cfrag
);
517 stmt
.ccodenode
= cfrag
;
520 /* free temporary objects */
522 if (((List
<LocalVariable
>) temp_vars
).size
== 0) {
523 /* nothing to do without temporary variables */
527 var cfrag
= new
CCodeFragment ();
528 append_temp_decl (cfrag
, temp_vars
);
530 cfrag
.append (stmt
.ccodenode
);
532 foreach (LocalVariable local
in temp_ref_vars
) {
533 var ma
= new MemberAccess
.simple (local
.name
);
534 ma
.symbol_reference
= local
;
535 cfrag
.append (new
CCodeExpressionStatement (get_unref_expression (new
CCodeIdentifier (local
.name
), local
.variable_type
, ma
)));
538 stmt
.ccodenode
= cfrag
;
541 temp_ref_vars
.clear ();
544 public override CCodeStatement
return_with_exception (CCodeExpression error_expr
)
546 if (!current_method
.coroutine
) {
547 return base.return_with_exception (error_expr
);
550 var block
= new
CCodeBlock ();
552 var set_error
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_simple_async_result_set_from_error"));
553 set_error
.add_argument (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("data"), "_async_result"));
554 set_error
.add_argument (error_expr
);
555 block
.add_statement (new
CCodeExpressionStatement (set_error
));
557 var free_error
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_error_free"));
558 free_error
.add_argument (error_expr
);
559 block
.add_statement (new
CCodeExpressionStatement (free_error
));
561 var free_locals
= new
CCodeFragment ();
562 append_local_free (current_symbol
, free_locals
, false);
563 block
.add_statement (free_locals
);
565 block
.add_statement (complete_async ());
570 public override void visit_return_statement (ReturnStatement stmt
) {
571 base.visit_return_statement (stmt
);
573 if (current_method
== null || !current_method
.coroutine
) {
577 var cfrag
= (CCodeFragment
) stmt
.ccodenode
;
579 cfrag
.append (complete_async ());
582 public override void generate_cparameters (Method m
, CCodeDeclarationSpace decl_space
, Map
<int,CCodeFormalParameter
> cparam_map
, CCodeFunction func
, CCodeFunctionDeclarator? vdeclarator
= null, Map
<int,CCodeExpression
>? carg_map
= null, CCodeFunctionCall? vcall
= null, int direction
= 3) {
584 decl_space
.add_include ("gio/gio.h");
586 if (direction
== 1) {
587 cparam_map
.set (get_param_pos (-1), new
CCodeFormalParameter ("_callback_", "GAsyncReadyCallback"));
588 cparam_map
.set (get_param_pos (-0.9), new
CCodeFormalParameter ("_user_data_", "gpointer"));
589 if (carg_map
!= null) {
590 carg_map
.set (get_param_pos (-1), new
CCodeIdentifier ("_callback_"));
591 carg_map
.set (get_param_pos (-0.9), new
CCodeIdentifier ("_user_data_"));
593 } else if (direction
== 2) {
594 cparam_map
.set (get_param_pos (0.1), new
CCodeFormalParameter ("_res_", "GAsyncResult*"));
595 if (carg_map
!= null) {
596 carg_map
.set (get_param_pos (0.1), new
CCodeIdentifier ("_res_"));
600 base.generate_cparameters (m
, decl_space
, cparam_map
, func
, vdeclarator
, carg_map
, vcall
, direction
);