Allow for blocks of statements, instead of only single statements

This commit is contained in:
Deukhoofd 2018-11-12 17:45:50 +01:00
parent ec7a32240f
commit e9391193bb
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
10 changed files with 108 additions and 51 deletions

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Immutable;
using Upsilon.BaseTypes.Number;
using Upsilon.Parser;
using Type = Upsilon.BaseTypes.Type;
@ -16,9 +17,9 @@ namespace Upsilon.Binder
_scope = new BoundScope(parentScope);
}
public BoundScript BindScript(ScriptSyntax e)
public BoundScript BindScript(BlockStatementSyntax e)
{
var bound = BindStatement(e.Statement);
var bound = BindStatement(e);
return new BoundScript(bound);
}
@ -28,11 +29,13 @@ namespace Upsilon.Binder
{
case SyntaxKind.ExpressionStatement:
return BindExpressionStatement((ExpressionStatementSyntax) s);
case SyntaxKind.AssignmentExpression:
case SyntaxKind.AssignmentStatement:
return BindAssignmentStatement((AssignmentExpressionSyntax) s);
case SyntaxKind.BlockStatement:
return BindBlockStatement((BlockStatementSyntax) s);
}
return null;
throw new NotImplementedException(s.Kind.ToString());
}
public BoundExpression BindExpression(ExpressionSyntax e)
@ -116,6 +119,18 @@ namespace Upsilon.Binder
return BindExpression(e.Expression);
}
private BoundExpression BindVariableExpression(VariableExpressionSyntax e)
{
var name = e.Identifier.Name;
if (!_scope.TryGetVariable(name, out var variable))
{
_diagnostics.LogUnknownVariable(e.Identifier.Span, name);
return new BoundLiteralExpression(null, Type.Nil);
}
return new BoundVariableExpression(variable);
}
private BoundStatement BindExpressionStatement(ExpressionStatementSyntax s)
{
var exp = BindExpression(s.Expression);
@ -148,16 +163,16 @@ namespace Upsilon.Binder
return new BoundVariableAssignment(variable, boundExpression);
}
private BoundExpression BindVariableExpression(VariableExpressionSyntax e)
{
var name = e.Identifier.Name;
if (!_scope.TryGetVariable(name, out var variable))
{
_diagnostics.LogUnknownVariable(e.Identifier.Span, name);
return new BoundLiteralExpression(null, Type.Nil);
}
return new BoundVariableExpression(variable);
private BoundStatement BindBlockStatement(BlockStatementSyntax e)
{
var arr = ImmutableArray.CreateBuilder<BoundStatement>();
foreach (var statementSyntax in e.Statements)
{
var bound = BindStatement(statementSyntax);
arr.Add(bound);
}
return new BoundBlockStatement(arr.ToImmutable());
}
}
}

View File

@ -0,0 +1,16 @@
using System.Collections.Immutable;
namespace Upsilon.Binder
{
public class BoundBlockStatement : BoundStatement
{
public BoundBlockStatement(ImmutableArray<BoundStatement> statements)
{
Statements = statements;
}
public override BoundKind Kind => BoundKind.BoundBlockStatement;
public ImmutableArray<BoundStatement> Statements { get; }
}
}

View File

@ -11,6 +11,7 @@ namespace Upsilon.Binder
// Statements
BoundAssignmentStatement,
BoundExpressionStatement
BoundExpressionStatement,
BoundBlockStatement
}
}

View File

@ -9,7 +9,7 @@ namespace Upsilon.Evaluator
{
private readonly Diagnostics _diagnostics;
private object _value;
public Script Script { get; }
private Script Script { get; }
private readonly Dictionary<VariableSymbol, object> _variables = new Dictionary<VariableSymbol, object>();
public Evaluator(Script script, Diagnostics diagnostics)
@ -37,12 +37,16 @@ namespace Upsilon.Evaluator
case BoundKind.BoundAssignmentStatement:
EvaluateAssignmentStatement((BoundVariableAssignment) e);
break;
case BoundKind.BoundBlockStatement:
EvaluateBoundBlockStatement((BoundBlockStatement) e);
break;
default:
EvaluateExpressionStatement((BoundExpressionStatement) e);
break;
}
}
private void EvaluateExpressionStatement(BoundExpressionStatement e)
{
_value = EvaluateExpression(e.Expression);
@ -104,12 +108,11 @@ namespace Upsilon.Evaluator
}
}
private object EvaluateAssignmentStatement(BoundVariableAssignment e)
private void EvaluateAssignmentStatement(BoundVariableAssignment e)
{
var val = EvaluateExpression(e.BoundExpression);
_variables[e.Variable] = val;
_value = val;
return val;
}
private object EvaluateVariableExpression(BoundVariableExpression e)
@ -117,5 +120,12 @@ namespace Upsilon.Evaluator
return _variables[e.Variable];
}
private void EvaluateBoundBlockStatement(BoundBlockStatement boundBlockStatement)
{
foreach (var boundStatement in boundBlockStatement.Statements)
{
EvaluateStatement(boundStatement);
}
}
}
}

View File

@ -9,7 +9,7 @@ namespace Upsilon.Evaluator
{
private SourceText ScriptString { get; }
private Evaluator Evaluator { get; }
private readonly ScriptSyntax _parsed;
private readonly BlockStatementSyntax _parsed;
public Diagnostics Diagnostics { get; }
private Binder.Binder Binder { get; }

View File

@ -15,10 +15,10 @@ namespace Upsilon.Parser
_diagnostics = diagnostics;
}
public static ScriptSyntax Parse(string text, Diagnostics diagnostics)
public static BlockStatementSyntax Parse(string text, Diagnostics diagnostics)
{
var tokens = Lexer.Lex(text, diagnostics);
return new Parser(tokens, diagnostics).ParseScriptSyntax();
return (BlockStatementSyntax) new Parser(tokens, diagnostics).ParseScriptSyntax();
}
private SyntaxToken Current => Get(0);
@ -47,11 +47,10 @@ namespace Upsilon.Parser
return new SyntaxToken(kind, Current.Span.Start, "", null);
}
public ScriptSyntax ParseScriptSyntax()
public StatementSyntax ParseScriptSyntax()
{
var statement = ParseStatement();
var eof = MatchToken(SyntaxKind.EndOfFile);
return new ScriptSyntax(statement, eof);
var statement = ParseBlockStatement();
return statement;
}
public StatementSyntax ParseStatement()
@ -68,6 +67,18 @@ namespace Upsilon.Parser
return ParseExpressionStatement();
}
public StatementSyntax ParseBlockStatement()
{
var statements = ImmutableArray.CreateBuilder<StatementSyntax>();
while (Current.Kind != SyntaxKind.EndKeyword && Current.Kind != SyntaxKind.EndOfFile)
{
var next = ParseStatement();
statements.Add(next);
}
var endToken = NextToken();
return new BlockStatementSyntax(statements.ToImmutable(), endToken);
}
public ExpressionStatementSyntax ParseExpressionStatement()
{
var expression = ParseExpression();

View File

@ -13,7 +13,7 @@ namespace Upsilon.Parser
Expression = expression;
}
public override SyntaxKind Kind => SyntaxKind.AssignmentExpression;
public override SyntaxKind Kind => SyntaxKind.AssignmentStatement;
public SyntaxToken LocalToken { get; }
public IdentifierToken Identifier { get; }

View File

@ -0,0 +1,27 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Upsilon.Text;
namespace Upsilon.Parser
{
public sealed class BlockStatementSyntax : StatementSyntax
{
public BlockStatementSyntax(ImmutableArray<StatementSyntax> statements, SyntaxToken endToken)
{
Statements = statements;
EndToken = endToken;
var first = statements.FirstOrDefault();
if (first != null)
Span = new TextSpan(first.Span.Start, endToken.Span.End);
}
public ImmutableArray<StatementSyntax> Statements { get; }
public SyntaxToken EndToken { get; }
public override SyntaxKind Kind => SyntaxKind.BlockStatement;
public override IEnumerable<SyntaxNode> ChildNodes()
{
return Statements;
}
}
}

View File

@ -1,24 +0,0 @@
using System.Collections.Generic;
namespace Upsilon.Parser
{
public class ScriptSyntax : StatementSyntax
{
public ScriptSyntax(StatementSyntax statement, SyntaxToken endOfFileToken)
{
Statement = statement;
EndOfFileToken = endOfFileToken;
}
public override SyntaxKind Kind => SyntaxKind.ScriptUnit;
public StatementSyntax Statement { get; }
public SyntaxToken EndOfFileToken { get; }
public override IEnumerable<SyntaxNode> ChildNodes()
{
yield return Statement;
yield return EndOfFileToken;
}
}
}

View File

@ -36,7 +36,7 @@ namespace Upsilon.Parser
BinaryExpression,
LiteralExpression,
ParenthesizedExpression,
AssignmentExpression,
AssignmentStatement,
VariableExpression,
BadExpression,
@ -44,6 +44,7 @@ namespace Upsilon.Parser
ScriptUnit,
// statements
ExpressionStatement
ExpressionStatement,
BlockStatement
}
}