]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
GAsync: Support async creation methods
authorJürg Billeter <j@bitron.ch>
Sun, 24 Jun 2012 18:50:44 +0000 (20:50 +0200)
committerJürg Billeter <j@bitron.ch>
Sun, 24 Jun 2012 18:51:12 +0000 (20:51 +0200)
Fixes bug 659886.

codegen/valaccodebasemodule.vala
codegen/valaccodemethodcallmodule.vala
codegen/valaccodemethodmodule.vala
codegen/valagasyncmodule.vala
vala/valaobjectcreationexpression.vala
vala/valaparser.vala

index ccaca21ee99460cb6dae850bdfa1bbb5e5b7fb55..7c4d28bc7becda1f63a1cfb4e7b3f32c7dd6ff1e 100644 (file)
@@ -2129,6 +2129,14 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                }
        }
 
+       public CCodeExpression get_this_cexpression () {
+               if (is_in_coroutine ()) {
+                       return new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "self");
+               } else {
+                       return new CCodeIdentifier ("self");
+               }
+       }
+
        public string get_local_cname (LocalVariable local) {
                var cname = get_variable_cname (local.name);
                if (is_in_coroutine ()) {
@@ -3532,9 +3540,9 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                        // do not call return as member cleanup and chain up to base finalizer
                        // stil need to be executed
                        ccode.add_goto ("_return");
+               } else if (is_in_coroutine ()) {
                } else if (current_method is CreationMethod) {
                        ccode.add_return (new CCodeIdentifier ("self"));
-               } else if (is_in_coroutine ()) {
                } else if (current_return_type is VoidType || current_return_type.is_real_non_null_struct_type ()) {
                        // structs are returned via out parameter
                        ccode.add_return ();
@@ -4332,6 +4340,9 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                        var params = m.get_parameters ();
                        CCodeFunctionCall creation_call;
 
+                       CCodeFunctionCall async_call = null;
+                       CCodeFunctionCall finish_call = null;
+
                        generate_method_declaration (m, cfile);
 
                        var cl = expr.type_reference.data_type as Class;
@@ -4362,17 +4373,32 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 
                        generate_type_declaration (expr.type_reference, cfile);
 
-                       var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
+                       var in_arg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
+                       var out_arg_map = in_arg_map;
+
+                       if (m != null && m.coroutine) {
+                               // async call
+
+                               async_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (m)));
+                               finish_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_finish_name (m)));
+
+                               creation_call = finish_call;
+
+                               // output arguments used separately
+                               out_arg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
+                               // pass GAsyncResult stored in closure to finish function
+                               out_arg_map.set (get_param_pos (0.1), new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_res_"));
+                       }
 
                        if (cl != null && !cl.is_compact) {
-                               add_generic_type_arguments (carg_map, expr.type_reference.get_type_arguments (), expr);
+                               add_generic_type_arguments (in_arg_map, expr.type_reference.get_type_arguments (), expr);
                        } else if (cl != null && get_ccode_simple_generics (m)) {
                                int type_param_index = 0;
                                foreach (var type_arg in expr.type_reference.get_type_arguments ()) {
                                        if (requires_copy (type_arg)) {
-                                               carg_map.set (get_param_pos (-1 + 0.1 * type_param_index + 0.03), get_destroy0_func_expression (type_arg));
+                                               in_arg_map.set (get_param_pos (-1 + 0.1 * type_param_index + 0.03), get_destroy0_func_expression (type_arg));
                                        } else {
-                                               carg_map.set (get_param_pos (-1 + 0.1 * type_param_index + 0.03), new CCodeConstant ("NULL"));
+                                               in_arg_map.set (get_param_pos (-1 + 0.1 * type_param_index + 0.03), new CCodeConstant ("NULL"));
                                        }
                                        type_param_index++;
                                }
@@ -4385,11 +4411,18 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                        Iterator<Parameter> params_it = params.iterator ();
                        foreach (Expression arg in expr.get_argument_list ()) {
                                CCodeExpression cexpr = get_cvalue (arg);
+
+                               var carg_map = in_arg_map;
+
                                Parameter param = null;
                                if (params_it.next ()) {
                                        param = params_it.get ();
                                        ellipsis = param.ellipsis;
                                        if (!ellipsis) {
+                                               if (param.direction == ParameterDirection.OUT) {
+                                                       carg_map = out_arg_map;
+                                               }
+
                                                // g_array_new: element size
                                                if (cl == garray_type && param.name == "element_size") {
                                                        var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
@@ -4450,39 +4483,80 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                // method can fail
                                current_method_inner_error = true;
                                // add &inner_error before the ellipsis arguments
-                               carg_map.set (get_param_pos (-1), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_")));
+                               out_arg_map.set (get_param_pos (-1), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_")));
                        }
 
                        if (ellipsis) {
                                /* ensure variable argument list ends with NULL
                                 * except when using printf-style arguments */
                                if (m == null) {
-                                       carg_map.set (get_param_pos (-1, true), new CCodeConstant ("NULL"));
+                                       in_arg_map.set (get_param_pos (-1, true), new CCodeConstant ("NULL"));
                                } else if (!m.printf_format && !m.scanf_format && get_ccode_sentinel (m) != "") {
-                                       carg_map.set (get_param_pos (-1, true), new CCodeConstant (get_ccode_sentinel (m)));
+                                       in_arg_map.set (get_param_pos (-1, true), new CCodeConstant (get_ccode_sentinel (m)));
                                }
                        }
 
                        if ((st != null && !st.is_simple_type ()) && get_ccode_instance_pos (m) < 0) {
                                // instance parameter is at the end in a struct creation method
-                               carg_map.set (get_param_pos (-3), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance));
+                               out_arg_map.set (get_param_pos (-3), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance));
+                       }
+
+                       if (m != null && m.coroutine) {
+                               if (expr.is_yield_expression) {
+                                       // asynchronous call
+                                       in_arg_map.set (get_param_pos (-1), new CCodeIdentifier (generate_ready_function (current_method)));
+                                       in_arg_map.set (get_param_pos (-0.9), new CCodeIdentifier ("_data_"));
+                               }
                        }
 
                        // append C arguments in the right order
-                       int last_pos = -1;
+
+                       int last_pos;
                        int min_pos;
-                       while (true) {
-                               min_pos = -1;
-                               foreach (int pos in carg_map.get_keys ()) {
-                                       if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
-                                               min_pos = pos;
+
+                       if (async_call != creation_call) {
+                               // don't append out arguments for .begin() calls
+                               last_pos = -1;
+                               while (true) {
+                                       min_pos = -1;
+                                       foreach (int pos in out_arg_map.get_keys ()) {
+                                               if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
+                                                       min_pos = pos;
+                                               }
                                        }
+                                       if (min_pos == -1) {
+                                               break;
+                                       }
+                                       creation_call.add_argument (out_arg_map.get (min_pos));
+                                       last_pos = min_pos;
                                }
-                               if (min_pos == -1) {
-                                       break;
+                       }
+
+                       if (async_call != null) {
+                               last_pos = -1;
+                               while (true) {
+                                       min_pos = -1;
+                                       foreach (int pos in in_arg_map.get_keys ()) {
+                                               if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
+                                                       min_pos = pos;
+                                               }
+                                       }
+                                       if (min_pos == -1) {
+                                               break;
+                                       }
+                                       async_call.add_argument (in_arg_map.get (min_pos));
+                                       last_pos = min_pos;
                                }
-                               creation_call.add_argument (carg_map.get (min_pos));
-                               last_pos = min_pos;
+                       }
+
+                       if (expr.is_yield_expression) {
+                               // set state before calling async function to support immediate callbacks
+                               int state = next_coroutine_state++;
+
+                               ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_"), new CCodeConstant (state.to_string ()));
+                               ccode.add_expression (async_call);
+                               ccode.add_return (new CCodeConstant ("FALSE"));
+                               ccode.add_label ("_state_%d".printf (state));
                        }
 
                        creation_expr = creation_call;
index bb27040781fdbb08b8982bbe621b50de00752ed0..f164ae1c6a466c83619a8097e95f2816738286a9 100644 (file)
@@ -125,10 +125,10 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                if (m is CreationMethod && m.parent_symbol is Class) {
                        if (context.profile == Profile.GOBJECT) {
                                if (!((Class) m.parent_symbol).is_compact) {
-                                       ccall.add_argument (new CCodeIdentifier ("object_type"));
+                                       ccall.add_argument (get_variable_cexpression ("object_type"));
                                }
                        } else {
-                               ccall.add_argument (new CCodeIdentifier ("self"));
+                               ccall.add_argument (get_this_cexpression ());
                        }
 
                        if (!current_class.is_compact) {
@@ -158,7 +158,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                }
                        }
                } else if (m is CreationMethod && m.parent_symbol is Struct) {
-                       ccall.add_argument (new CCodeIdentifier ("self"));
+                       ccall.add_argument (get_this_cexpression ());
                } else if (m != null && m.get_type_parameters ().size > 0 && !get_ccode_has_generic_type_parameter (m) && !get_ccode_simple_generics (m) && (ccall != finish_call || expr.is_yield_expression)) {
                        // generic method
                        // don't add generic arguments for .end() calls
@@ -217,7 +217,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                } else {
                                        // Accessing the method from within an instance method
                                        var k = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_GET_CLASS"));
-                                       k.add_argument (new CCodeIdentifier ("self"));
+                                       k.add_argument (get_this_cexpression ());
                                        klass = k;
                                }
                        } else {
@@ -282,12 +282,12 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                        }
                        generate_dynamic_method_wrapper ((DynamicMethod) m);
                } else if (m is CreationMethod && context.profile == Profile.GOBJECT && m.parent_symbol is Class) {
-                       ccode.add_assignment (new CCodeIdentifier ("self"), new CCodeCastExpression (ccall, CCodeBaseModule.get_ccode_name (current_class) + "*"));
+                       ccode.add_assignment (get_this_cexpression (), new CCodeCastExpression (ccall, CCodeBaseModule.get_ccode_name (current_class) + "*"));
 
                        if (current_method.body.captured) {
                                // capture self after setting it
                                var ref_call = new CCodeFunctionCall (get_dup_func_expression (new ObjectType (current_class), expr.source_reference));
-                               ref_call.add_argument (new CCodeIdentifier ("self"));
+                               ref_call.add_argument (get_this_cexpression ());
 
                                ccode.add_assignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (current_method.body))), "self"), ref_call);
                        }
index 24085d280e8420a45af93d360275b6568cf918c8..5559898b2fb63931aff42b4408bd2a5a6754a6c6 100644 (file)
@@ -552,15 +552,17 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 
                                if (m is CreationMethod) {
                                        if (in_gobject_creation_method) {
-                                               ccode.add_declaration ("%s *".printf (get_ccode_name (current_type_symbol)), new CCodeVariableDeclarator.zero ("self", new CCodeConstant ("NULL")));
+                                               if (!m.coroutine) {
+                                                       ccode.add_declaration ("%s *".printf (get_ccode_name (current_type_symbol)), new CCodeVariableDeclarator.zero ("self", new CCodeConstant ("NULL")));
+                                               }
                                        } else if (is_gtypeinstance_creation_method (m)) {
                                                var cl = (Class) m.parent_symbol;
                                                ccode.add_declaration (get_ccode_name (cl) + "*", new CCodeVariableDeclarator.zero ("self", new CCodeConstant ("NULL")));
 
                                                if (cl.is_fundamental ()) {
                                                        var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_create_instance"));
-                                                       ccall.add_argument (new CCodeIdentifier ("object_type"));
-                                                       ccode.add_assignment (new CCodeIdentifier ("self"), new CCodeCastExpression (ccall, get_ccode_name (cl) + "*"));
+                                                       ccall.add_argument (get_variable_cexpression ("object_type"));
+                                                       ccode.add_assignment (get_this_cexpression (), new CCodeCastExpression (ccall, get_ccode_name (cl) + "*"));
 
                                                        /* type, dup func, and destroy func fields for generic types */
                                                        foreach (TypeParameter type_param in current_class.get_type_parameters ()) {
@@ -584,19 +586,21 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
                                                }
                                        } else if (current_type_symbol is Class) {
                                                var cl = (Class) m.parent_symbol;
-                                               ccode.add_declaration (get_ccode_name (cl) + "*", new CCodeVariableDeclarator ("self"));
+                                               if (!m.coroutine) {
+                                                       ccode.add_declaration (get_ccode_name (cl) + "*", new CCodeVariableDeclarator ("self"));
+                                               }
 
                                                if (!((CreationMethod) m).chain_up) {
                                                        // TODO implicitly chain up to base class as in add_object_creation
                                                        var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0"));
                                                        ccall.add_argument (new CCodeIdentifier (get_ccode_name (cl)));
-                                                       ccode.add_assignment (new CCodeIdentifier ("self"), ccall);
+                                                       ccode.add_assignment (get_this_cexpression (), ccall);
                                                }
 
                                                if (cl.base_class == null) {
                                                        // derived compact classes do not have fields
                                                        var cinitcall = new CCodeFunctionCall (new CCodeIdentifier ("%s_instance_init".printf (get_ccode_lower_case_name (cl, null))));
-                                                       cinitcall.add_argument (new CCodeIdentifier ("self"));
+                                                       cinitcall.add_argument (get_this_cexpression ());
                                                        ccode.add_expression (cinitcall);
                                                }
                                        } else {
@@ -714,7 +718,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
                                                ccode.add_expression (cfreeparams);
                                        }
 
-                                       if (current_type_symbol is Class) {
+                                       if (current_type_symbol is Class && !m.coroutine) {
                                                CCodeExpression cresult = new CCodeIdentifier ("self");
                                                if (get_ccode_type (m) != null) {
                                                        cresult = new CCodeCastExpression (cresult, get_ccode_type (m));
@@ -859,7 +863,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
                        cparam_map.set (get_param_pos (get_ccode_instance_pos (m)), instance_param);
                } else if (m.parent_symbol is Class && m is CreationMethod) {
                        var cl = (Class) m.parent_symbol;
-                       if (!cl.is_compact && vcall == null) {
+                       if (!cl.is_compact && vcall == null && (direction & 1) == 1) {
                                cparam_map.set (get_param_pos (get_ccode_instance_pos (m)), new CCodeParameter ("object_type", "GType"));
                        }
                } else if (m.binding == MemberBinding.INSTANCE || (m.parent_symbol is Struct && m is CreationMethod)) {
index bee5cebfa4fb4bf6831831389fb3218c91b5eee2..05d1e422bbbcb0504d925dd316bc57cb62bd03ca 100644 (file)
@@ -32,6 +32,10 @@ public class Vala.GAsyncModule : GSignalModule {
                data.add_field ("GAsyncResult*", "_res_");
                data.add_field ("GSimpleAsyncResult*", "_async_result");
 
+               if (m is CreationMethod) {
+                       data.add_field ("GType", "object_type");
+               }
+
                if (m.binding == MemberBinding.INSTANCE) {
                        var type_sym = (TypeSymbol) m.parent_symbol;
                        if (type_sym is ObjectTypeSymbol) {
@@ -205,7 +209,7 @@ public class Vala.GAsyncModule : GSignalModule {
                var create_result = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_new"));
 
                var cl = m.parent_symbol as Class;
-               if (m.binding == MemberBinding.INSTANCE &&
+               if (!(m is CreationMethod) && m.binding == MemberBinding.INSTANCE &&
                    cl != null && cl.is_subtype_of (gobject_type)) {
                        var gobject_cast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT"));
                        gobject_cast.add_argument (new CCodeIdentifier ("self"));
@@ -236,7 +240,9 @@ public class Vala.GAsyncModule : GSignalModule {
                set_op_res_call.add_argument (new CCodeIdentifier (get_ccode_real_name (m) + "_data_free"));
                ccode.add_expression (set_op_res_call);
 
-               if (m.binding == MemberBinding.INSTANCE) {
+               if (m is CreationMethod) {
+                       ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, "object_type"), new CCodeIdentifier ("object_type"));
+               } else if (m.binding == MemberBinding.INSTANCE) {
                        var this_type = m.this_parameter.variable_type.copy ();
                        this_type.value_owned = true;
 
@@ -308,30 +314,62 @@ public class Vala.GAsyncModule : GSignalModule {
                                return;
                        }
 
+                       var cl = m.parent_symbol as Class;
+
                        var asyncfunc = new CCodeFunction (get_ccode_name (m), "void");
                        var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
-                       cparam_map.set (get_param_pos (-1), new CCodeParameter ("_callback_", "GAsyncReadyCallback"));
-                       cparam_map.set (get_param_pos (-0.9), new CCodeParameter ("_user_data_", "gpointer"));
-
-                       generate_cparameters (m, decl_space, cparam_map, asyncfunc, null, null, null, 1);
+                       var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
 
                        if (m.is_private_symbol ()) {
                                asyncfunc.modifiers |= CCodeModifiers.STATIC;
                        }
 
-                       decl_space.add_function_declaration (asyncfunc);
+                       // do not generate _new functions for creation methods of abstract classes
+                       if (!(m is CreationMethod && cl != null && cl.is_abstract)) {
+                               generate_cparameters (m, decl_space, cparam_map, asyncfunc, null, carg_map, new CCodeFunctionCall (new CCodeIdentifier ("fake")), 1);
+
+                               decl_space.add_function_declaration (asyncfunc);
+                       }
 
                        var finishfunc = new CCodeFunction (get_ccode_finish_name (m));
                        cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
-                       cparam_map.set (get_param_pos (0.1), new CCodeParameter ("_res_", "GAsyncResult*"));
-
-                       generate_cparameters (m, decl_space, cparam_map, finishfunc, null, null, null, 2);
+                       carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
 
                        if (m.is_private_symbol ()) {
                                finishfunc.modifiers |= CCodeModifiers.STATIC;
                        }
 
-                       decl_space.add_function_declaration (finishfunc);
+                       // do not generate _new functions for creation methods of abstract classes
+                       if (!(m is CreationMethod && cl != null && cl.is_abstract)) {
+                               generate_cparameters (m, decl_space, cparam_map, finishfunc, null, carg_map, new CCodeFunctionCall (new CCodeIdentifier ("fake")), 2);
+
+                               decl_space.add_function_declaration (finishfunc);
+                       }
+
+                       if (m is CreationMethod && cl != null) {
+                               // _construct function
+                               var function = new CCodeFunction (get_ccode_real_name (m));
+
+                               if (m.is_private_symbol ()) {
+                                       function.modifiers |= CCodeModifiers.STATIC;
+                               }
+
+                               cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
+                               generate_cparameters (m, decl_space, cparam_map, function, null, null, null, 1);
+
+                               decl_space.add_function_declaration (function);
+
+                               function = new CCodeFunction (get_ccode_finish_real_name (m));
+
+                               if (m.is_private_symbol ()) {
+                                       function.modifiers |= CCodeModifiers.STATIC;
+                               }
+
+                               cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
+                               generate_cparameters (m, decl_space, cparam_map, function, null, null, null, 2);
+
+                               decl_space.add_function_declaration (function);
+                       }
                } else {
                        base.generate_method_declaration (m, decl_space);
                }
@@ -386,6 +424,69 @@ public class Vala.GAsyncModule : GSignalModule {
                }
        }
 
+       public override void visit_creation_method (CreationMethod m) {
+               if (!m.coroutine) {
+                       base.visit_creation_method (m);
+               } else {
+                       push_line (m.source_reference);
+
+                       bool visible = !m.is_private_symbol ();
+
+                       visit_method (m);
+
+                       if (m.source_type == SourceFileType.FAST) {
+                               return;
+                       }
+
+                       // do not generate _new functions for creation methods of abstract classes
+                       if (current_type_symbol is Class && !current_class.is_compact && !current_class.is_abstract) {
+                               var vfunc = new CCodeFunction (get_ccode_name (m));
+
+                               var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
+                               var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
+
+                               push_function (vfunc);
+
+                               var vcall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_real_name (m)));
+                               vcall.add_argument (new CCodeIdentifier (get_ccode_type_id (current_class)));
+
+                               generate_cparameters (m, cfile, cparam_map, vfunc, null, carg_map, vcall, 1);
+                               ccode.add_expression (vcall);
+
+                               if (!visible) {
+                                       vfunc.modifiers |= CCodeModifiers.STATIC;
+                               }
+
+                               pop_function ();
+
+                               cfile.add_function (vfunc);
+
+
+                               vfunc = new CCodeFunction (get_ccode_finish_name (m));
+
+                               cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
+                               carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
+
+                               push_function (vfunc);
+
+                               vcall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_finish_real_name (m)));
+
+                               generate_cparameters (m, cfile, cparam_map, vfunc, null, carg_map, vcall, 2);
+                               ccode.add_return (vcall);
+
+                               if (!visible) {
+                                       vfunc.modifiers |= CCodeModifiers.STATIC;
+                               }
+
+                               pop_function ();
+
+                               cfile.add_function (vfunc);
+                       }
+
+                       pop_line ();
+               }
+       }
+
        void generate_finish_function (Method m) {
                push_context (new EmitContext ());
 
@@ -406,7 +507,12 @@ public class Vala.GAsyncModule : GSignalModule {
                push_function (finishfunc);
 
                var return_type = m.return_type;
-               if (!(return_type is VoidType) && !return_type.is_real_non_null_struct_type ()) {
+               if (m is CreationMethod) {
+                       var type_sym = (TypeSymbol) m.parent_symbol;
+                       if (type_sym is ObjectTypeSymbol) {
+                               ccode.add_declaration (get_ccode_name (type_sym) + "*", new CCodeVariableDeclarator ("result"));
+                       }
+               } else if (!(return_type is VoidType) && !return_type.is_real_non_null_struct_type ()) {
                        ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator ("result"));
                }
 
@@ -443,7 +549,11 @@ public class Vala.GAsyncModule : GSignalModule {
                }
                emit_context.pop_symbol ();
 
-               if (return_type.is_real_non_null_struct_type ()) {
+               if (m is CreationMethod) {
+                       ccode.add_assignment (new CCodeIdentifier ("result"), new CCodeMemberAccess.pointer (data_var, "self"));
+                       ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, "self"), new CCodeConstant ("NULL"));
+                       ccode.add_return (new CCodeIdentifier ("result"));
+               } else if (return_type.is_real_non_null_struct_type ()) {
                        // structs are returned via out parameter
                        CCodeExpression cexpr = new CCodeMemberAccess.pointer (data_var, "result");
                        if (requires_copy (return_type)) {
index a274de01370853c25a5392821f8397301a4b74c9..d96fb650356e924ea1a5f2da6f88322bda97ed91 100644 (file)
@@ -43,6 +43,8 @@ public class Vala.ObjectCreationExpression : Expression {
         */
        public MemberAccess member_name { get; set; }
 
+       public bool is_yield_expression { get; set; }
+
        public bool struct_creation { get; set; }
 
        private List<Expression> argument_list = new ArrayList<Expression> ();
index 099ed073a9ff2646df35d0602ec72934334078c0..caecb62dab5d3d92d1ed3218a20cf15caeaf0102 100644 (file)
@@ -978,16 +978,23 @@ public class Vala.Parser : CodeVisitor {
 
        Expression parse_yield_expression () throws ParseError {
                expect (TokenType.YIELD);
+
                var expr = parse_expression ();
 
                var call = expr as MethodCall;
-               if (call == null) {
+               var object_creation = expr as ObjectCreationExpression;
+               if (call == null && object_creation == null) {
                        Report.error (expr.source_reference, "syntax error, expected method call");
                        throw new ParseError.SYNTAX ("expected method call");
                }
 
-               call.is_yield_expression = true;
-               return call;
+               if (call != null) {
+                       call.is_yield_expression = true;
+               } else if (object_creation != null) {
+                       object_creation.is_yield_expression = true;
+               }
+
+               return expr;
        }
 
        Expression parse_sizeof_expression () throws ParseError {