[vala] GAsync: Require yield expression for async method calls



commit 9b7c66c114b5603b1ae6d96bb357558f5e544a51
Author: Jürg Billeter <j bitron ch>
Date:   Sun Sep 13 12:12:13 2009 +0200

    GAsync: Require yield expression for async method calls

 codegen/valaccodemethodcallmodule.vala |    8 +++++---
 vala/valamethodcall.vala               |    6 ++++++
 vala/valaparser.vala                   |   19 ++++++++++++++++++-
 3 files changed, 29 insertions(+), 4 deletions(-)
---
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index e881f9d..cf149ca 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -69,9 +69,7 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
 
 		HashMap<int,CCodeExpression> in_arg_map, out_arg_map;
 
-		if (m != null && m.coroutine
-		    && ((current_method != null && current_method.coroutine)
-		        || (ma.member_name == "begin" && ma.inner.symbol_reference == ma.symbol_reference))) {
+		if (m != null && m.coroutine) {
 			// async call
 
 			in_arg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
@@ -82,6 +80,10 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
 			if (ma.member_name == "begin" && ma.inner.symbol_reference == ma.symbol_reference) {
 				// no finish call
 				ccall = async_call;
+			} else if (!expr.is_yield_expression) {
+				Report.warning (expr.source_reference, "Calling async methods requires use of `yield' or `begin'");
+
+				ccall = async_call;
 			} else {
 				ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname () + "_finish"));
 
diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala
index 5f9f909..65ee4d6 100644
--- a/vala/valamethodcall.vala
+++ b/vala/valamethodcall.vala
@@ -38,6 +38,8 @@ public class Vala.MethodCall : Expression {
 		}
 	}
 
+	public bool is_yield_expression { get; set; }
+
 	public Expression _call;
 	
 	private Gee.List<Expression> argument_list = new ArrayList<Expression> ();
@@ -403,6 +405,10 @@ public class Vala.MethodCall : Expression {
 
 		if (mtype is MethodType) {
 			var m = ((MethodType) mtype).method_symbol;
+			if (is_yield_expression && !m.coroutine) {
+				error = true;
+				Report.error (source_reference, "yield expression requires async method");
+			}
 			foreach (DataType error_type in m.get_error_types ()) {
 				may_throw = true;
 
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index 9dfe7d3..6a1ebaf 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -547,6 +547,9 @@ public class Vala.Parser : CodeVisitor {
 		case TokenType.NEW:
 			expr = parse_object_or_array_creation_expression ();
 			break;
+		case TokenType.YIELD:
+			expr = parse_yield_expression ();
+			break;
 		case TokenType.SIZEOF:
 			expr = parse_sizeof_expression ();
 			break;
@@ -813,6 +816,15 @@ public class Vala.Parser : CodeVisitor {
 		return new MemberInitializer (id, expr, get_src (begin));
 	}
 
+	Expression parse_yield_expression () throws ParseError {
+		var begin = get_location ();
+		expect (TokenType.YIELD);
+		var member = parse_member_name ();
+		var call = (MethodCall) parse_method_call (begin, member);
+		call.is_yield_expression = true;
+		return call;
+	}
+
 	Expression parse_sizeof_expression () throws ParseError {
 		var begin = get_location ();
 		expect (TokenType.SIZEOF);
@@ -1651,8 +1663,13 @@ public class Vala.Parser : CodeVisitor {
 	Statement parse_yield_statement () throws ParseError {
 		var begin = get_location ();
 		expect (TokenType.YIELD);
+		if (current () != TokenType.SEMICOLON && current () != TokenType.RETURN) {
+			// yield expression
+			prev ();
+			return parse_expression_statement ();
+		}
 		Expression expr = null;
-		if (current () != TokenType.SEMICOLON) {
+		if (accept (TokenType.RETURN)) {
 			expr = parse_expression ();
 		}
 		expect (TokenType.SEMICOLON);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]