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