Implements break statement

This commit is contained in:
Deukhoofd 2018-11-23 15:27:48 +01:00
parent d2c14d213c
commit 2db4d0607e
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
10 changed files with 76 additions and 13 deletions

View File

@ -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());

View File

@ -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
}
}

View File

@ -0,0 +1,7 @@
namespace Upsilon.Binder
{
public class BoundBreakStatement : BoundStatement
{
public override BoundKind Kind => BoundKind.BoundBreakStatement;
}
}

View File

@ -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;
}
}
}

View File

@ -91,6 +91,10 @@ namespace Upsilon.Parser
{
return ParseForStatement();
}
if (Current.Kind == SyntaxKind.BreakKeyword)
{
return new BreakStatementSyntax(NextToken());
}
return ParseExpressionStatement();
}

View File

@ -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;
}
}
}

View File

@ -40,6 +40,8 @@ namespace Upsilon.Parser
return SyntaxKind.InKeyword;
case "do":
return SyntaxKind.DoKeyword;
case "break":
return SyntaxKind.BreakKeyword;
default:
return SyntaxKind.Identifier;
}

View File

@ -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
}
}

View File

@ -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);
}
}
}

View File

@ -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);