Commit 6cb86f04 authored by Jürg Billeter's avatar Jürg Billeter

dova: Add implicit result variable

parent c8ea2a25
......@@ -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) {
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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));
}
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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);
}
......
......@@ -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;
......
......@@ -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) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment