Commit b2117a4c authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter

Parse yield statements

2008-11-01  Jürg Billeter  <j@bitron.ch>

	* vala/Makefile.am:
	* vala/valacfgbuilder.vala:
	* vala/valacodevisitor.vala:
	* vala/valamethod.vala:
	* vala/valanullchecker.vala:
	* vala/valaparser.vala:
	* vala/valascanner.vala:
	* vala/valasemanticanalyzer.vala:
	* vala/valasymbolresolver.vala:
	* vala/valatokentype.vala:
	* vala/valayieldstatement.vala:
	* gobject/valaccodegenerator.vala:

	Parse yield statements

svn path=/trunk/; revision=1947
parent 2a578b83
2008-11-01 Jürg Billeter <j@bitron.ch>
* vala/Makefile.am:
* vala/valacfgbuilder.vala:
* vala/valacodevisitor.vala:
* vala/valamethod.vala:
* vala/valanullchecker.vala:
* vala/valaparser.vala:
* vala/valascanner.vala:
* vala/valasemanticanalyzer.vala:
* vala/valasymbolresolver.vala:
* vala/valatokentype.vala:
* vala/valayieldstatement.vala:
* gobject/valaccodegenerator.vala:
Parse yield statements
2008-10-31 Jürg Billeter <j@bitron.ch>
* vala/valaproperty.vala:
......
......@@ -2680,6 +2680,57 @@ public class Vala.CCodeGenerator : CodeGenerator {
}
}
public override void visit_yield_statement (YieldStatement stmt) {
if (stmt.yield_expression == null) {
stmt.ccodenode = new CCodeFragment ();
return;
}
stmt.accept_children (this);
if (stmt.yield_expression.error) {
stmt.error = true;
return;
}
stmt.ccodenode = new CCodeExpressionStatement ((CCodeExpression) stmt.yield_expression.ccodenode);
if (stmt.tree_can_fail && stmt.yield_expression.tree_can_fail) {
// simple case, no node breakdown necessary
var cfrag = new CCodeFragment ();
cfrag.append (stmt.ccodenode);
add_simple_check (stmt.yield_expression, cfrag);
stmt.ccodenode = cfrag;
}
/* free temporary objects */
if (((Gee.List<LocalVariable>) temp_vars).size == 0) {
/* nothing to do without temporary variables */
return;
}
var cfrag = new CCodeFragment ();
append_temp_decl (cfrag, temp_vars);
cfrag.append (stmt.ccodenode);
foreach (LocalVariable local in temp_ref_vars) {
var ma = new MemberAccess.simple (local.name);
ma.symbol_reference = local;
cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (local.name), local.variable_type, ma)));
}
stmt.ccodenode = cfrag;
temp_vars.clear ();
temp_ref_vars.clear ();
}
public override void visit_throw_statement (ThrowStatement stmt) {
stmt.accept_children (this);
......
......@@ -144,6 +144,7 @@ libvalacore_la_VALASOURCES = \
valavaluetype.vala \
valavoidtype.vala \
valawhilestatement.vala \
valayieldstatement.vala \
$(NULL)
libvalacore_la_SOURCES = \
......
......@@ -579,6 +579,14 @@ public class Vala.CFGBuilder : CodeVisitor {
}
}
public override void visit_yield_statement (YieldStatement stmt) {
if (unreachable (stmt)) {
return;
}
stmt.accept_children (this);
}
public override void visit_throw_statement (ThrowStatement stmt) {
if (unreachable (stmt)) {
return;
......
......@@ -355,6 +355,14 @@ public abstract class Vala.CodeVisitor {
public virtual void visit_return_statement (ReturnStatement stmt) {
}
/**
* Visit operation called for yield statement.
*
* @param y a yield statement
*/
public virtual void visit_yield_statement (YieldStatement y) {
}
/**
* Visit operation called for throw statements.
*
......
......@@ -200,6 +200,8 @@ public class Vala.Method : Member {
*/
public bool has_construct_function { get; set; default = true; }
public bool coroutine { get; set; }
private Gee.List<FormalParameter> parameters = new ArrayList<FormalParameter> ();
private string cname;
private string _vfunc_name;
......
......@@ -176,6 +176,10 @@ public class Vala.NullChecker : CodeVisitor {
}
}
public override void visit_yield_statement (YieldStatement stmt) {
stmt.accept_children (this);
}
public override void visit_throw_statement (ThrowStatement stmt) {
stmt.accept_children (this);
......
......@@ -232,6 +232,8 @@ public class Vala.Parser : CodeVisitor {
case TokenType.VOLATILE:
case TokenType.WEAK:
case TokenType.WHILE:
case TokenType.YIELD:
case TokenType.YIELDS:
next ();
return;
}
......@@ -1205,6 +1207,9 @@ public class Vala.Parser : CodeVisitor {
case TokenType.RETURN:
stmt = parse_return_statement ();
break;
case TokenType.YIELD:
stmt = parse_yield_statement ();
break;
case TokenType.THROW:
stmt = parse_throw_statement ();
break;
......@@ -1325,6 +1330,7 @@ public class Vala.Parser : CodeVisitor {
case TokenType.BREAK: return parse_break_statement ();
case TokenType.CONTINUE: return parse_continue_statement ();
case TokenType.RETURN: return parse_return_statement ();
case TokenType.YIELD: return parse_yield_statement ();
case TokenType.THROW: return parse_throw_statement ();
case TokenType.TRY: return parse_try_statement ();
case TokenType.LOCK: return parse_lock_statement ();
......@@ -1584,6 +1590,17 @@ public class Vala.Parser : CodeVisitor {
return new ReturnStatement (expr, get_src_com (begin));
}
Statement parse_yield_statement () throws ParseError {
var begin = get_location ();
expect (TokenType.YIELD);
Expression expr = null;
if (current () != TokenType.SEMICOLON) {
expr = parse_expression ();
}
expect (TokenType.SEMICOLON);
return new YieldStatement (expr, get_src (begin));
}
Statement parse_throw_statement () throws ParseError {
var begin = get_location ();
expect (TokenType.THROW);
......@@ -1841,6 +1858,7 @@ public class Vala.Parser : CodeVisitor {
case TokenType.TRY:
case TokenType.VAR:
case TokenType.WHILE:
case TokenType.YIELD:
return RecoveryState.STATEMENT_BEGIN;
default:
next ();
......@@ -2157,6 +2175,9 @@ public class Vala.Parser : CodeVisitor {
} while (accept (TokenType.COMMA));
}
expect (TokenType.CLOSE_PARENS);
if (accept (TokenType.YIELDS)) {
method.coroutine = true;
}
if (accept (TokenType.THROWS)) {
do {
method.add_error_type (parse_type ());
......@@ -2730,6 +2751,9 @@ public class Vala.Parser : CodeVisitor {
} while (accept (TokenType.COMMA));
}
expect (TokenType.CLOSE_PARENS);
if (accept (TokenType.YIELDS)) {
method.coroutine = true;
}
if (accept (TokenType.THROWS)) {
do {
method.add_error_type (parse_type ());
......
......@@ -175,6 +175,9 @@ public class Vala.Scanner {
case 'w':
if (matches (begin, "while")) return TokenType.WHILE;
break;
case 'y':
if (matches (begin, "yield")) return TokenType.YIELD;
break;
}
break;
case 6:
......@@ -231,6 +234,9 @@ public class Vala.Scanner {
break;
}
break;
case 'y':
if (matches (begin, "yields")) return TokenType.YIELDS;
break;
}
break;
case 7:
......
......@@ -1164,6 +1164,10 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
stmt.add_error_types (stmt.return_expression.get_error_types ());
}
public override void visit_yield_statement (YieldStatement stmt) {
stmt.check (this);
}
public override void visit_throw_statement (ThrowStatement stmt) {
stmt.error_expression.target_type = new ErrorType (null, null, stmt.source_reference);
stmt.error_expression.target_type.value_owned = true;
......@@ -2094,7 +2098,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
if (ret_type is VoidType) {
// void return type
if (!(expr.parent_node is ExpressionStatement)
&& !(expr.parent_node is ForStatement)) {
&& !(expr.parent_node is ForStatement)
&& !(expr.parent_node is YieldStatement)) {
// A void method invocation can be in the initializer or
// iterator of a for statement
expr.error = true;
......
......@@ -354,6 +354,10 @@ public class Vala.SymbolResolver : CodeVisitor {
stmt.accept_children (this);
}
public override void visit_yield_statement (YieldStatement stmt) {
stmt.accept_children (this);
}
public override void visit_throw_statement (ThrowStatement stmt) {
stmt.accept_children (this);
}
......
......@@ -139,7 +139,9 @@ public enum Vala.TokenType {
VOID,
VOLATILE,
WEAK,
WHILE;
WHILE,
YIELD,
YIELDS;
public weak string to_string () {
switch (this) {
......@@ -255,6 +257,8 @@ public enum Vala.TokenType {
case VOLATILE: return "`volatile'";
case WEAK: return "`weak'";
case WHILE: return "`while'";
case YIELD: return "`yield'";
case YIELDS: return "`yields'";
default: return "unknown token";
}
}
......
/* valayieldstatement.vala
*
* Copyright (C) 2008 Jürg Billeter
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Author:
* Jürg Billeter <j@bitron.ch>
*/
/**
* Represents a yield statement in the source code.
*/
public class Vala.YieldStatement : CodeNode, Statement {
/**
* The expression to yield or the method call to yield to.
*/
public Expression? yield_expression {
get { return _yield_expression; }
set {
_yield_expression = value;
if (_yield_expression != null) {
_yield_expression.parent_node = this;
}
}
}
private Expression _yield_expression;
/**
* Creates a new yield statement.
*
* @param yield_expression the yield expression
* @param source_reference reference to source code
* @return newly created yield statement
*/
public YieldStatement (Expression? yield_expression, SourceReference? source_reference = null) {
this.yield_expression = yield_expression;
this.source_reference = source_reference;
}
public override void accept (CodeVisitor visitor) {
visitor.visit_yield_statement (this);
}
public override void accept_children (CodeVisitor visitor) {
if (yield_expression != null) {
yield_expression.accept (visitor);
visitor.visit_end_full_expression (yield_expression);
}
}
public override void replace_expression (Expression old_node, Expression new_node) {
if (yield_expression == old_node) {
yield_expression = new_node;
}
}
public override bool check (SemanticAnalyzer analyzer) {
if (yield_expression != null) {
yield_expression.accept (analyzer);
error = yield_expression.error;
}
return !error;
}
}
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