[vala] GAsync: Support async creation methods
- From: JÃrg Billeter <juergbi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala] GAsync: Support async creation methods
- Date: Sun, 24 Jun 2012 18:53:07 +0000 (UTC)
commit 6be0b6a71b3fa53a38eb0fc055d1ea952ec973f7
Author: JÃrg Billeter <j bitron ch>
Date: Sun Jun 24 20:50:44 2012 +0200
GAsync: Support async creation methods
Fixes bug 659886.
codegen/valaccodebasemodule.vala | 112 ++++++++++++++++++++++-----
codegen/valaccodemethodcallmodule.vala | 12 ++--
codegen/valaccodemethodmodule.vala | 20 +++--
codegen/valagasyncmodule.vala | 136 +++++++++++++++++++++++++++++---
vala/valaobjectcreationexpression.vala | 2 +
vala/valaparser.vala | 13 +++-
6 files changed, 246 insertions(+), 49 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index ccaca21..7c4d28b 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -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;
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index bb27040..f164ae1 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -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);
}
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index 24085d2..5559898 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -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)) {
diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala
index bee5ceb..05d1e42 100644
--- a/codegen/valagasyncmodule.vala
+++ b/codegen/valagasyncmodule.vala
@@ -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)) {
diff --git a/vala/valaobjectcreationexpression.vala b/vala/valaobjectcreationexpression.vala
index a274de0..d96fb65 100644
--- a/vala/valaobjectcreationexpression.vala
+++ b/vala/valaobjectcreationexpression.vala
@@ -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> ();
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index 099ed07..caecb62 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -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 {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]