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); return BindNumericForStatement((NumericForStatementSyntax) s);
case SyntaxKind.GenericForStatement: case SyntaxKind.GenericForStatement:
return BindGenericForStatement((GenericForStatementSyntax) s); return BindGenericForStatement((GenericForStatementSyntax) s);
case SyntaxKind.WhileStatement:
return BindWhileStatement((WhileStatementSyntax) s);
case SyntaxKind.BreakStatement: case SyntaxKind.BreakStatement:
return new BoundBreakStatement(s.Span); return new BoundBreakStatement(s.Span);
@ -860,5 +862,15 @@ namespace Upsilon.Binder
return new BoundGenericForStatement(array.ToImmutable(), boundEnumerableExpression, block, e.Span); 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, BoundNumericForStatement,
BoundGenericForStatement, BoundGenericForStatement,
BoundBreakStatement, 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.BoundNumericForStatement:
case BoundKind.BoundGenericForStatement: case BoundKind.BoundGenericForStatement:
case BoundKind.BoundBreakStatement: case BoundKind.BoundBreakStatement:
case BoundKind.BoundWhileStatement:
EvaluateStatement((BoundStatement) b); EvaluateStatement((BoundStatement) b);
break; break;
default: default:
@ -180,6 +181,9 @@ namespace Upsilon.Evaluator
case BoundKind.BoundGenericForStatement: case BoundKind.BoundGenericForStatement:
EvaluateGenericForStatement((BoundGenericForStatement) e); EvaluateGenericForStatement((BoundGenericForStatement) e);
break; break;
case BoundKind.BoundWhileStatement:
EvaluateWhileStatement((BoundWhileStatement) e);
break;
default: default:
EvaluateExpressionStatement((BoundExpressionStatement) e); EvaluateExpressionStatement((BoundExpressionStatement) e);
break; 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(); return ParseForStatement();
} }
if (Current.Kind == SyntaxKind.WhileKeyword)
{
return ParseWhileStatement();
}
if (Current.Kind == SyntaxKind.BreakKeyword) if (Current.Kind == SyntaxKind.BreakKeyword)
{ {
return new BreakStatementSyntax(NextToken()); return new BreakStatementSyntax(NextToken());
@ -196,6 +200,17 @@ namespace Upsilon.Parser
doKeyword, (BlockStatementSyntax) block, endKeyword); 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() private ExpressionSyntax ParseFunctionExpression()
{ {
var functionToken = MatchToken(SyntaxKind.FunctionKeyword); 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; return SyntaxKind.ReturnKeyword;
case "for": case "for":
return SyntaxKind.ForKeyword; return SyntaxKind.ForKeyword;
case "while":
return SyntaxKind.WhileKeyword;
case "in": case "in":
return SyntaxKind.InKeyword; return SyntaxKind.InKeyword;
case "do": case "do":

View File

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