Implements while loops

This commit is contained in:
Deukhoofd 2018-12-07 19:17:49 +01:00
parent fa967383d6
commit eb1eb81c1b
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
8 changed files with 119 additions and 3 deletions

View File

@ -95,6 +95,8 @@ namespace Upsilon.Binder
return BindNumericForStatement((NumericForStatementSyntax) s);
case SyntaxKind.GenericForStatement:
return BindGenericForStatement((GenericForStatementSyntax) s);
case SyntaxKind.WhileStatement:
return BindWhileStatement((WhileStatementSyntax) s);
case SyntaxKind.BreakStatement:
return new BoundBreakStatement(s.Span);
@ -860,5 +862,15 @@ namespace Upsilon.Binder
return new BoundGenericForStatement(array.ToImmutable(), boundEnumerableExpression, block, e.Span);
}
private BoundStatement BindWhileStatement(WhileStatementSyntax e)
{
Scope = new BoundScope(Scope);
var condition = BindExpression(e.Expression);
var block = BindBlockStatement((BlockStatementSyntax) e.Block);
return new BoundWhileStatement(condition, block, e.Span);
}
}
}

View File

@ -29,6 +29,6 @@ namespace Upsilon.Binder
BoundNumericForStatement,
BoundGenericForStatement,
BoundBreakStatement,
BoundWhileStatement
}
}

View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using Upsilon.Text;
namespace Upsilon.Binder
{
internal class BoundWhileStatement : BoundStatement
{
public BoundExpression Condition { get; }
public BoundStatement Block { get; }
public BoundWhileStatement(BoundExpression condition, BoundStatement block, TextSpan eSpan)
:base(eSpan)
{
Condition = condition;
Block = block;
}
public override BoundKind Kind => BoundKind.BoundWhileStatement;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
{
if (characterPosition >= Condition.Span.Start && characterPosition <= Condition.Span.End)
foreach (var boundNode in Condition.GetNodeAtPosition(characterPosition))
yield return boundNode;
if (characterPosition >= Block.Span.Start && characterPosition <= Block.Span.End)
foreach (var boundNode in Block.GetNodeAtPosition(characterPosition))
yield return boundNode;
yield return this;
}
}
}

View File

@ -136,6 +136,7 @@ namespace Upsilon.Evaluator
case BoundKind.BoundNumericForStatement:
case BoundKind.BoundGenericForStatement:
case BoundKind.BoundBreakStatement:
case BoundKind.BoundWhileStatement:
EvaluateStatement((BoundStatement) b);
break;
default:
@ -180,6 +181,9 @@ namespace Upsilon.Evaluator
case BoundKind.BoundGenericForStatement:
EvaluateGenericForStatement((BoundGenericForStatement) e);
break;
case BoundKind.BoundWhileStatement:
EvaluateWhileStatement((BoundWhileStatement) e);
break;
default:
EvaluateExpressionStatement((BoundExpressionStatement) e);
break;
@ -664,5 +668,16 @@ namespace Upsilon.Evaluator
}
}
}
private void EvaluateWhileStatement(BoundWhileStatement e)
{
var innerEvaluator = new Evaluator(_diagnostics, Scope, _script);
var block = (BoundBlockStatement) e.Block;
while ((ScriptBoolean)EvaluateExpression(e.Condition))
{
innerEvaluator.EvaluateBoundBlockStatement(block);
}
}
}
}

View File

@ -90,6 +90,10 @@ namespace Upsilon.Parser
{
return ParseForStatement();
}
if (Current.Kind == SyntaxKind.WhileKeyword)
{
return ParseWhileStatement();
}
if (Current.Kind == SyntaxKind.BreakKeyword)
{
return new BreakStatementSyntax(NextToken());
@ -196,6 +200,17 @@ namespace Upsilon.Parser
doKeyword, (BlockStatementSyntax) block, endKeyword);
}
private StatementSyntax ParseWhileStatement()
{
var whileToken = MatchToken(SyntaxKind.WhileKeyword);
var expression = ParseExpression();
var doToken = MatchToken(SyntaxKind.DoKeyword);
var block = ParseBlockStatement(new[] {SyntaxKind.EndKeyword});
var endKeyword = MatchToken(SyntaxKind.EndKeyword);
return new WhileStatementSyntax(whileToken, expression, doToken, block, endKeyword);
}
private ExpressionSyntax ParseFunctionExpression()
{
var functionToken = MatchToken(SyntaxKind.FunctionKeyword);

View File

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using Upsilon.Text;
namespace Upsilon.Parser
{
internal class WhileStatementSyntax : StatementSyntax
{
public SyntaxToken WhileToken { get; }
public ExpressionSyntax Expression { get; }
public SyntaxToken DoToken { get; }
public StatementSyntax Block { get; }
public SyntaxToken EndKeyword { get; }
public WhileStatementSyntax(SyntaxToken whileToken, ExpressionSyntax expression, SyntaxToken doToken,
StatementSyntax block, SyntaxToken endKeyword)
{
WhileToken = whileToken;
Expression = expression;
DoToken = doToken;
Block = block;
EndKeyword = endKeyword;
Span = new TextSpan(whileToken.Span.Start, endKeyword.Span.End);
}
public override SyntaxKind Kind => SyntaxKind.WhileStatement;
public override IEnumerable<SyntaxNode> ChildNodes()
{
yield return WhileToken;
yield return Expression;
yield return DoToken;
yield return Block;
yield return EndKeyword;
}
}
}

View File

@ -36,6 +36,8 @@ namespace Upsilon.Parser
return SyntaxKind.ReturnKeyword;
case "for":
return SyntaxKind.ForKeyword;
case "while":
return SyntaxKind.WhileKeyword;
case "in":
return SyntaxKind.InKeyword;
case "do":

View File

@ -33,6 +33,8 @@ namespace Upsilon.Parser
LessEquals,
Greater,
GreaterEquals,
PercentSign,
RoofSign,
// key words
TrueKeyword,
@ -50,6 +52,7 @@ namespace Upsilon.Parser
FunctionKeyword,
ReturnKeyword,
ForKeyword,
WhileKeyword,
InKeyword,
DoKeyword,
BreakKeyword,
@ -87,7 +90,6 @@ namespace Upsilon.Parser
NumericForStatement,
BreakStatement,
GenericForStatement,
PercentSign,
RoofSign
WhileStatement
}
}