[vala] dova: Add implicit result variable



commit 6cb86f046f334eb092358ac0ba23e450a9845ed3
Author: Jürg Billeter <j bitron ch>
Date:   Sat Mar 13 21:44:21 2010 +0100

    dova: Add implicit result variable

 vala/valaclass.vala            |    4 ++--
 vala/valaenum.vala             |    4 ++++
 vala/valaflowanalyzer.vala     |   18 ++++++++++++++++--
 vala/valainterface.vala        |    4 ++--
 vala/valalambdaexpression.vala |    7 ++++++-
 vala/valanamespace.vala        |    2 +-
 vala/valaparser.vala           |   31 ++++++++++++++++++++++++++++++-
 vala/valapropertyaccessor.vala |   23 +++++++++++++++++++++--
 vala/valareturnstatement.vala  |    5 +++++
 vala/valastruct.vala           |    4 ++--
 10 files changed, 89 insertions(+), 13 deletions(-)
---
diff --git a/vala/valaclass.vala b/vala/valaclass.vala
index 04342d0..dd39f8f 100644
--- a/vala/valaclass.vala
+++ b/vala/valaclass.vala
@@ -322,11 +322,11 @@ public class Vala.Class : ObjectTypeSymbol {
 			m.this_parameter = new FormalParameter ("this", get_this_type ());
 			m.scope.add (m.this_parameter.name, m.this_parameter);
 		}
-		if (!(m.return_type is VoidType) && m.get_postconditions ().size > 0) {
+		if (!(m.return_type is VoidType) && (CodeContext.get ().profile == Profile.DOVA || m.get_postconditions ().size > 0)) {
 			if (m.result_var != null) {
 				m.scope.remove (m.result_var.name);
 			}
-			m.result_var = new LocalVariable (m.return_type.copy (), "result");
+			m.result_var = new LocalVariable (m.return_type.copy (), "result", null, source_reference);
 			m.result_var.is_result = true;
 		}
 		if (m is CreationMethod) {
diff --git a/vala/valaenum.vala b/vala/valaenum.vala
index 7c6391c..0e488ad 100644
--- a/vala/valaenum.vala
+++ b/vala/valaenum.vala
@@ -81,6 +81,10 @@ public class Vala.Enum : TypeSymbol {
 			m.this_parameter = new FormalParameter ("this", new EnumValueType (this));
 			m.scope.add (m.this_parameter.name, m.this_parameter);
 		}
+		if (!(m.return_type is VoidType) && (CodeContext.get ().profile == Profile.DOVA || m.get_postconditions ().size > 0)) {
+			m.result_var = new LocalVariable (m.return_type.copy (), "result", null, source_reference);
+			m.result_var.is_result = true;
+		}
 
 		methods.add (m);
 		scope.add (m.name, m);
diff --git a/vala/valaflowanalyzer.vala b/vala/valaflowanalyzer.vala
index a047128..a90e157 100644
--- a/vala/valaflowanalyzer.vala
+++ b/vala/valaflowanalyzer.vala
@@ -168,6 +168,13 @@ public class Vala.FlowAnalyzer : CodeVisitor {
 		m.entry_block = new BasicBlock.entry ();
 		m.exit_block = new BasicBlock.exit ();
 
+		if (context.profile == Profile.DOVA && !(m.return_type is VoidType)) {
+			// ensure result is defined at end of method
+			var result_ma = new MemberAccess.simple ("result", m.source_reference);
+			result_ma.symbol_reference = m.result_var;
+			m.exit_block.add_node (result_ma);
+		}
+
 		current_block = new BasicBlock ();
 		m.entry_block.connect (current_block);
 		current_block.add_node (m);
@@ -181,7 +188,7 @@ public class Vala.FlowAnalyzer : CodeVisitor {
 		if (current_block != null) {
 			// end of method body reachable
 
-			if (!(m.return_type is VoidType)) {
+			if (context.profile != Profile.DOVA && !(m.return_type is VoidType)) {
 				Report.error (m.source_reference, "missing return statement at end of method or lambda body");
 				m.error = true;
 			}
@@ -483,6 +490,13 @@ public class Vala.FlowAnalyzer : CodeVisitor {
 		acc.entry_block = new BasicBlock.entry ();
 		acc.exit_block = new BasicBlock.exit ();
 
+		if (context.profile == Profile.DOVA && acc.readable) {
+			// ensure result is defined at end of method
+			var result_ma = new MemberAccess.simple ("result", acc.source_reference);
+			result_ma.symbol_reference = acc.result_var;
+			acc.exit_block.add_node (result_ma);
+		}
+
 		current_block = new BasicBlock ();
 		acc.entry_block.connect (current_block);
 
@@ -495,7 +509,7 @@ public class Vala.FlowAnalyzer : CodeVisitor {
 		if (current_block != null) {
 			// end of property accessor body reachable
 
-			if (acc.readable) {
+			if (context.profile != Profile.DOVA && acc.readable) {
 				Report.error (acc.source_reference, "missing return statement at end of property getter body");
 				acc.error = true;
 			}
diff --git a/vala/valainterface.vala b/vala/valainterface.vala
index 076ba2e..a76998a 100644
--- a/vala/valainterface.vala
+++ b/vala/valainterface.vala
@@ -138,8 +138,8 @@ public class Vala.Interface : ObjectTypeSymbol {
 			m.this_parameter = new FormalParameter ("this", get_this_type ());
 			m.scope.add (m.this_parameter.name, m.this_parameter);
 		}
-		if (!(m.return_type is VoidType) && m.get_postconditions ().size > 0) {
-			m.result_var = new LocalVariable (m.return_type.copy (), "result");
+		if (!(m.return_type is VoidType) && (CodeContext.get ().profile == Profile.DOVA || m.get_postconditions ().size > 0)) {
+			m.result_var = new LocalVariable (m.return_type.copy (), "result", null, source_reference);
 			m.result_var.is_result = true;
 		}
 
diff --git a/vala/valalambdaexpression.vala b/vala/valalambdaexpression.vala
index facaed9..a6c2dba 100644
--- a/vala/valalambdaexpression.vala
+++ b/vala/valalambdaexpression.vala
@@ -200,7 +200,12 @@ public class Vala.LambdaExpression : Expression {
 			block.scope.parent_scope = method.scope;
 
 			if (method.return_type.data_type != null) {
-				block.add_statement (new ReturnStatement (expression_body, source_reference));
+				if (analyzer.context.profile == Profile.DOVA) {
+					block.add_statement (new ExpressionStatement (new Assignment (new MemberAccess.simple ("result", source_reference), expression_body, AssignmentOperator.SIMPLE, source_reference), source_reference));
+					block.add_statement (new ReturnStatement (null, source_reference));
+				} else {
+					block.add_statement (new ReturnStatement (expression_body, source_reference));
+				}
 			} else {
 				block.add_statement (new ExpressionStatement (expression_body, source_reference));
 			}
diff --git a/vala/valanamespace.vala b/vala/valanamespace.vala
index 8ddeb9d..e3a0f90 100644
--- a/vala/valanamespace.vala
+++ b/vala/valanamespace.vala
@@ -391,7 +391,7 @@ public class Vala.Namespace : Symbol {
 			m.error = true;
 			return;
 		}
-		if (!(m.return_type is VoidType) && m.get_postconditions ().size > 0) {
+		if (!(m.return_type is VoidType) && (CodeContext.get ().profile == Profile.DOVA || m.get_postconditions ().size > 0)) {
 			m.result_var = new LocalVariable (m.return_type.copy (), "result", null, source_reference);
 			m.result_var.is_result = true;
 		}
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index 90ad36d..c7490e1 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -1418,6 +1418,19 @@ public class Vala.Parser : CodeVisitor {
 				}
 
 				if (!is_decl) {
+					if (context.profile == Profile.DOVA && stmt is ReturnStatement) {
+						// split
+						//     return foo;
+						// into
+						//     result = foo;
+						//     return;
+						var ret_stmt = (ReturnStatement) stmt;
+						if (ret_stmt.return_expression != null) {
+							var assignment = new Assignment (new MemberAccess.simple ("result"), ret_stmt.return_expression);
+							ret_stmt.return_expression = null;
+							block.add_statement (new ExpressionStatement (assignment));
+						}
+					}
 					block.add_statement (stmt);
 				}
 			} catch (ParseError e) {
@@ -1475,7 +1488,23 @@ public class Vala.Parser : CodeVisitor {
 		comment = scanner.pop_comment ();
 
 		var block = new Block (get_src (get_location ()));
-		block.add_statement (parse_embedded_statement_without_block ());
+
+		var stmt = parse_embedded_statement_without_block ();
+		if (context.profile == Profile.DOVA && stmt is ReturnStatement) {
+			// split
+			//     return foo;
+			// into
+			//     result = foo;
+			//     return;
+			var ret_stmt = (ReturnStatement) stmt;
+			if (ret_stmt.return_expression != null) {
+				var assignment = new Assignment (new MemberAccess.simple ("result"), ret_stmt.return_expression);
+				ret_stmt.return_expression = null;
+				block.add_statement (new ExpressionStatement (assignment));
+			}
+		}
+		block.add_statement (stmt);
+
 		return block;
 
 	}
diff --git a/vala/valapropertyaccessor.vala b/vala/valapropertyaccessor.vala
index f9eaa79..0f02efb 100644
--- a/vala/valapropertyaccessor.vala
+++ b/vala/valapropertyaccessor.vala
@@ -90,6 +90,11 @@ public class Vala.PropertyAccessor : Symbol {
 	public FormalParameter value_parameter { get; set; }
 
 	/**
+	 * Specifies the generated `result' variable in a get accessor.
+	 */
+	public LocalVariable? result_var { get; set; }
+
+	/**
 	 * The publicly accessible name of the function that performs the
 	 * access in C code.
 	 */
@@ -137,6 +142,10 @@ public class Vala.PropertyAccessor : Symbol {
 	public override void accept_children (CodeVisitor visitor) {
 		value_type.accept (visitor);
 
+		if (result_var != null) {
+			result_var.accept (visitor);
+		}
+
 		if (body != null) {
 			body.accept (visitor);
 		}
@@ -186,7 +195,12 @@ public class Vala.PropertyAccessor : Symbol {
 				body = new Block (source_reference);
 				var ma = new MemberAccess.simple ("_%s".printf (prop.name), source_reference);
 				if (readable) {
-					body.add_statement (new ReturnStatement (ma, source_reference));
+					if (analyzer.context.profile == Profile.DOVA) {
+						body.add_statement (new ExpressionStatement (new Assignment (new MemberAccess.simple ("result", source_reference), ma, AssignmentOperator.SIMPLE, source_reference), source_reference));
+						body.add_statement (new ReturnStatement (null, source_reference));
+					} else {
+						body.add_statement (new ReturnStatement (ma, source_reference));
+					}
 				} else {
 					var assignment = new Assignment (ma, new MemberAccess.simple ("value", source_reference), AssignmentOperator.SIMPLE, source_reference);
 					body.add_statement (new ExpressionStatement (assignment));
@@ -195,7 +209,12 @@ public class Vala.PropertyAccessor : Symbol {
 		}
 
 		if (body != null) {
-			if (writable || construction) {
+			if (readable && analyzer.context.profile == Profile.DOVA) {
+				result_var = new LocalVariable (value_type.copy (), "result", null, source_reference);
+				result_var.is_result = true;
+
+				result_var.check (analyzer);
+			} else if (writable || construction) {
 				value_parameter = new FormalParameter ("value", value_type, source_reference);
 				body.scope.add (value_parameter.name, value_parameter);
 			}
diff --git a/vala/valareturnstatement.vala b/vala/valareturnstatement.vala
index 26af73e..399ca69 100644
--- a/vala/valareturnstatement.vala
+++ b/vala/valareturnstatement.vala
@@ -93,6 +93,11 @@ public class Vala.ReturnStatement : CodeNode, Statement {
 			return false;
 		}
 
+		if (analyzer.context.profile == Profile.DOVA) {
+			// no return expressions in Dova profile
+			return !error;
+		}
+
 		if (return_expression == null) {
 			if (!(analyzer.current_return_type is VoidType)) {
 				error = true;
diff --git a/vala/valastruct.vala b/vala/valastruct.vala
index f5d7325..7376635 100644
--- a/vala/valastruct.vala
+++ b/vala/valastruct.vala
@@ -181,8 +181,8 @@ public class Vala.Struct : TypeSymbol {
 			m.this_parameter = new FormalParameter ("this", SemanticAnalyzer.get_data_type_for_symbol (this));
 			m.scope.add (m.this_parameter.name, m.this_parameter);
 		}
-		if (!(m.return_type is VoidType) && m.get_postconditions ().size > 0) {
-			m.result_var = new LocalVariable (m.return_type.copy (), "result");
+		if (!(m.return_type is VoidType) && (CodeContext.get ().profile == Profile.DOVA || m.get_postconditions ().size > 0)) {
+			m.result_var = new LocalVariable (m.return_type.copy (), "result", null, source_reference);
 			m.result_var.is_result = true;
 		}
 		if (m is CreationMethod) {



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