Implements break statement
This commit is contained in:
parent
d2c14d213c
commit
2db4d0607e
|
@ -70,6 +70,8 @@ namespace Upsilon.Binder
|
|||
return BindMultiAssignmentStatement((MultiAssignmentStatementSyntax) s);
|
||||
case SyntaxKind.NumericForStatement:
|
||||
return BindNumericForStatement((NumericForStatementSyntax) s);
|
||||
case SyntaxKind.BreakStatement:
|
||||
return new BoundBreakStatement();
|
||||
}
|
||||
|
||||
throw new NotImplementedException(s.Kind.ToString());
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace Upsilon.Binder
|
|||
BoundFunctionCallExpression,
|
||||
BoundTableExpression,
|
||||
BoundIndexExpression,
|
||||
BoundFunctionExpression,
|
||||
|
||||
// Statements
|
||||
BoundAssignmentStatement,
|
||||
|
@ -18,13 +19,13 @@ namespace Upsilon.Binder
|
|||
BoundBlockStatement,
|
||||
BoundIfStatement,
|
||||
BoundElseStatement,
|
||||
BoundFunctionExpression,
|
||||
BoundPromise,
|
||||
BoundReturnStatement,
|
||||
BoundFunctionAssignmentStatement,
|
||||
BoundTableAssigmentStatement,
|
||||
BoundFullstopIndexExpression,
|
||||
BoundMultiAssignmentStatement,
|
||||
BoundNumericForStatement
|
||||
BoundNumericForStatement,
|
||||
BoundBreakStatement
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
namespace Upsilon.Binder
|
||||
{
|
||||
public class BoundBreakStatement : BoundStatement
|
||||
{
|
||||
public override BoundKind Kind => BoundKind.BoundBreakStatement;
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ namespace Upsilon.Evaluator
|
|||
private LuaType _returnValue;
|
||||
internal EvaluationScope Scope { get; private set; }
|
||||
private bool HasReturned { get; set; }
|
||||
private bool HasBroken { get; set; }
|
||||
|
||||
internal Evaluator(Diagnostics diagnostics, Dictionary<string, LuaType> variables)
|
||||
{
|
||||
|
@ -132,6 +133,9 @@ namespace Upsilon.Evaluator
|
|||
case BoundKind.BoundNumericForStatement:
|
||||
EvaluateNumericForStatement((BoundNumericForStatement) e);
|
||||
break;
|
||||
case BoundKind.BoundBreakStatement:
|
||||
HasBroken = true;
|
||||
return;
|
||||
default:
|
||||
EvaluateExpressionStatement((BoundExpressionStatement) e);
|
||||
break;
|
||||
|
@ -332,30 +336,27 @@ namespace Upsilon.Evaluator
|
|||
{
|
||||
if (HasReturned)
|
||||
return;
|
||||
if (HasBroken)
|
||||
return;
|
||||
EvaluateStatement(boundStatement);
|
||||
}
|
||||
}
|
||||
|
||||
private void EvaluateBoundIfStatement(BoundIfStatement boundBlockStatement)
|
||||
{
|
||||
var innerEvaluator = new Evaluator(_diagnostics, Scope);
|
||||
var condition = innerEvaluator.EvaluateExpression(boundBlockStatement.Condition.Expression);
|
||||
var condition = EvaluateExpression(boundBlockStatement.Condition.Expression);
|
||||
if ((LuaBoolean) condition)
|
||||
{
|
||||
innerEvaluator.EvaluateStatement(boundBlockStatement.Block);
|
||||
EvaluateStatement(boundBlockStatement.Block);
|
||||
}
|
||||
else if (boundBlockStatement.NextElseIf != null)
|
||||
{
|
||||
innerEvaluator.EvaluateStatement(boundBlockStatement.NextElseIf);
|
||||
EvaluateStatement(boundBlockStatement.NextElseIf);
|
||||
}
|
||||
else if (boundBlockStatement.ElseStatement != null)
|
||||
{
|
||||
innerEvaluator.EvaluateStatement(boundBlockStatement.ElseStatement.Block);
|
||||
EvaluateStatement(boundBlockStatement.ElseStatement.Block);
|
||||
}
|
||||
HasReturned = innerEvaluator.HasReturned;
|
||||
if (HasReturned)
|
||||
_returnValue = innerEvaluator._returnValue;
|
||||
_lastValue = innerEvaluator._lastValue;
|
||||
}
|
||||
|
||||
private void EvaluateBoundFunctionAssigmentStatement(BoundFunctionAssignmentStatement e)
|
||||
|
@ -508,6 +509,8 @@ namespace Upsilon.Evaluator
|
|||
for (; startVal.Value <= stopVal.Value; startVal.Value = startVal.Value + step)
|
||||
{
|
||||
innerEvaluator.EvaluateBoundBlockStatement(e.Block);
|
||||
if (innerEvaluator.HasBroken)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (step < 0)
|
||||
|
@ -515,6 +518,8 @@ namespace Upsilon.Evaluator
|
|||
for (; startVal.Value >= stopVal.Value; startVal.Value = startVal.Value + step)
|
||||
{
|
||||
innerEvaluator.EvaluateBoundBlockStatement(e.Block);
|
||||
if (innerEvaluator.HasBroken)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,6 +91,10 @@ namespace Upsilon.Parser
|
|||
{
|
||||
return ParseForStatement();
|
||||
}
|
||||
if (Current.Kind == SyntaxKind.BreakKeyword)
|
||||
{
|
||||
return new BreakStatementSyntax(NextToken());
|
||||
}
|
||||
|
||||
return ParseExpressionStatement();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Upsilon.Parser
|
||||
{
|
||||
public class BreakStatementSyntax : StatementSyntax
|
||||
{
|
||||
public SyntaxToken BreakKeyword { get; }
|
||||
public BreakStatementSyntax(SyntaxToken breakKeyword)
|
||||
{
|
||||
BreakKeyword = breakKeyword;
|
||||
}
|
||||
|
||||
public override SyntaxKind Kind => SyntaxKind.BreakStatement;
|
||||
public override IEnumerable<SyntaxNode> ChildNodes()
|
||||
{
|
||||
yield return BreakKeyword;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -40,6 +40,8 @@ namespace Upsilon.Parser
|
|||
return SyntaxKind.InKeyword;
|
||||
case "do":
|
||||
return SyntaxKind.DoKeyword;
|
||||
case "break":
|
||||
return SyntaxKind.BreakKeyword;
|
||||
default:
|
||||
return SyntaxKind.Identifier;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ namespace Upsilon.Parser
|
|||
ForKeyword,
|
||||
InKeyword,
|
||||
DoKeyword,
|
||||
BreakKeyword,
|
||||
|
||||
Identifier,
|
||||
|
||||
|
@ -76,6 +77,7 @@ namespace Upsilon.Parser
|
|||
ReturnStatement,
|
||||
FunctionAssignmentStatement,
|
||||
TableAssignmentStatement,
|
||||
NumericForStatement
|
||||
NumericForStatement,
|
||||
BreakStatement
|
||||
}
|
||||
}
|
|
@ -59,5 +59,25 @@ return a";
|
|||
Assert.Equal(15, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NumericForLoopBreakTest()
|
||||
{
|
||||
const string input = @"
|
||||
a = 0
|
||||
for i=0,10 do
|
||||
a = a + i
|
||||
if i == 5 then
|
||||
break
|
||||
end
|
||||
end
|
||||
return a
|
||||
";
|
||||
var script = new Script(input, BoundScope, StaticScope);
|
||||
Assert.Empty(script.Diagnostics.Messages);
|
||||
var result = script.Evaluate<long>();
|
||||
Assert.Empty(script.Diagnostics.Messages);
|
||||
Assert.Equal(15, result);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -14,9 +14,10 @@ namespace UpsilonTests.GeneralTests
|
|||
{
|
||||
const string input = @"
|
||||
a = 10
|
||||
if true then
|
||||
function testFunc()
|
||||
local a = 100
|
||||
end
|
||||
testFunc()
|
||||
";
|
||||
var script = new Script(input, BoundScope, StaticScope);
|
||||
Assert.Empty(script.Diagnostics.Messages);
|
||||
|
|
Loading…
Reference in New Issue