From: Jürg Billeter Date: Sat, 13 Mar 2010 20:44:21 +0000 (+0100) Subject: dova: Add implicit result variable X-Git-Tag: 0.8.0~190 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6cb86f046f334eb092358ac0ba23e450a9845ed3;p=thirdparty%2Fvala.git dova: Add implicit result variable --- diff --git a/vala/valaclass.vala b/vala/valaclass.vala index 04342d0fb..dd39f8f18 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 7c6391c54..0e488adb6 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 a047128cf..a90e15750 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 076ba2efc..a76998aa7 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 facaed95b..a6c2dba9b 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 8ddeb9dff..e3a0f9037 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 90ad36d6d..c7490e1ef 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 f9eaa79e9..0f02efb37 100644 --- a/vala/valapropertyaccessor.vala +++ b/vala/valapropertyaccessor.vala @@ -89,6 +89,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 26af73ead..399ca696e 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 f5d732529..737663576 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) {