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;
using System.Collections.Immutable;
using Upsilon.BaseTypes.Number; using Upsilon.BaseTypes.Number;
using Upsilon.Parser; using Upsilon.Parser;
using Type = Upsilon.BaseTypes.Type; using Type = Upsilon.BaseTypes.Type;
@ -16,9 +17,9 @@ namespace Upsilon.Binder
_scope = new BoundScope(parentScope); _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); return new BoundScript(bound);
} }
@ -28,11 +29,13 @@ namespace Upsilon.Binder
{ {
case SyntaxKind.ExpressionStatement: case SyntaxKind.ExpressionStatement:
return BindExpressionStatement((ExpressionStatementSyntax) s); return BindExpressionStatement((ExpressionStatementSyntax) s);
case SyntaxKind.AssignmentExpression: case SyntaxKind.AssignmentStatement:
return BindAssignmentStatement((AssignmentExpressionSyntax) s); return BindAssignmentStatement((AssignmentExpressionSyntax) s);
case SyntaxKind.BlockStatement:
return BindBlockStatement((BlockStatementSyntax) s);
} }
return null; throw new NotImplementedException(s.Kind.ToString());
} }
public BoundExpression BindExpression(ExpressionSyntax e) public BoundExpression BindExpression(ExpressionSyntax e)
@ -116,6 +119,18 @@ namespace Upsilon.Binder
return BindExpression(e.Expression); 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) private BoundStatement BindExpressionStatement(ExpressionStatementSyntax s)
{ {
var exp = BindExpression(s.Expression); var exp = BindExpression(s.Expression);
@ -148,16 +163,16 @@ namespace Upsilon.Binder
return new BoundVariableAssignment(variable, boundExpression); 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 // Statements
BoundAssignmentStatement, BoundAssignmentStatement,
BoundExpressionStatement BoundExpressionStatement,
BoundBlockStatement
} }
} }

View File

@ -9,7 +9,7 @@ namespace Upsilon.Evaluator
{ {
private readonly Diagnostics _diagnostics; private readonly Diagnostics _diagnostics;
private object _value; private object _value;
public Script Script { get; } private Script Script { get; }
private readonly Dictionary<VariableSymbol, object> _variables = new Dictionary<VariableSymbol, object>(); private readonly Dictionary<VariableSymbol, object> _variables = new Dictionary<VariableSymbol, object>();
public Evaluator(Script script, Diagnostics diagnostics) public Evaluator(Script script, Diagnostics diagnostics)
@ -37,12 +37,16 @@ namespace Upsilon.Evaluator
case BoundKind.BoundAssignmentStatement: case BoundKind.BoundAssignmentStatement:
EvaluateAssignmentStatement((BoundVariableAssignment) e); EvaluateAssignmentStatement((BoundVariableAssignment) e);
break; break;
case BoundKind.BoundBlockStatement:
EvaluateBoundBlockStatement((BoundBlockStatement) e);
break;
default: default:
EvaluateExpressionStatement((BoundExpressionStatement) e); EvaluateExpressionStatement((BoundExpressionStatement) e);
break; break;
} }
} }
private void EvaluateExpressionStatement(BoundExpressionStatement e) private void EvaluateExpressionStatement(BoundExpressionStatement e)
{ {
_value = EvaluateExpression(e.Expression); _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); var val = EvaluateExpression(e.BoundExpression);
_variables[e.Variable] = val; _variables[e.Variable] = val;
_value = val; _value = val;
return val;
} }
private object EvaluateVariableExpression(BoundVariableExpression e) private object EvaluateVariableExpression(BoundVariableExpression e)
@ -117,5 +120,12 @@ namespace Upsilon.Evaluator
return _variables[e.Variable]; 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 SourceText ScriptString { get; }
private Evaluator Evaluator { get; } private Evaluator Evaluator { get; }
private readonly ScriptSyntax _parsed; private readonly BlockStatementSyntax _parsed;
public Diagnostics Diagnostics { get; } public Diagnostics Diagnostics { get; }
private Binder.Binder Binder { get; } private Binder.Binder Binder { get; }

View File

@ -15,10 +15,10 @@ namespace Upsilon.Parser
_diagnostics = diagnostics; _diagnostics = diagnostics;
} }
public static ScriptSyntax Parse(string text, Diagnostics diagnostics) public static BlockStatementSyntax Parse(string text, Diagnostics diagnostics)
{ {
var tokens = Lexer.Lex(text, 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); private SyntaxToken Current => Get(0);
@ -47,11 +47,10 @@ namespace Upsilon.Parser
return new SyntaxToken(kind, Current.Span.Start, "", null); return new SyntaxToken(kind, Current.Span.Start, "", null);
} }
public ScriptSyntax ParseScriptSyntax() public StatementSyntax ParseScriptSyntax()
{ {
var statement = ParseStatement(); var statement = ParseBlockStatement();
var eof = MatchToken(SyntaxKind.EndOfFile); return statement;
return new ScriptSyntax(statement, eof);
} }
public StatementSyntax ParseStatement() public StatementSyntax ParseStatement()
@ -68,6 +67,18 @@ namespace Upsilon.Parser
return ParseExpressionStatement(); 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() public ExpressionStatementSyntax ParseExpressionStatement()
{ {
var expression = ParseExpression(); var expression = ParseExpression();

View File

@ -13,7 +13,7 @@ namespace Upsilon.Parser
Expression = expression; Expression = expression;
} }
public override SyntaxKind Kind => SyntaxKind.AssignmentExpression; public override SyntaxKind Kind => SyntaxKind.AssignmentStatement;
public SyntaxToken LocalToken { get; } public SyntaxToken LocalToken { get; }
public IdentifierToken Identifier { 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, BinaryExpression,
LiteralExpression, LiteralExpression,
ParenthesizedExpression, ParenthesizedExpression,
AssignmentExpression, AssignmentStatement,
VariableExpression, VariableExpression,
BadExpression, BadExpression,
@ -44,6 +44,7 @@ namespace Upsilon.Parser
ScriptUnit, ScriptUnit,
// statements // statements
ExpressionStatement ExpressionStatement,
BlockStatement
} }
} }