Allow for blocks of statements, instead of only single statements
This commit is contained in:
parent
ec7a32240f
commit
e9391193bb
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ namespace Upsilon.Binder
|
||||||
|
|
||||||
// Statements
|
// Statements
|
||||||
BoundAssignmentStatement,
|
BoundAssignmentStatement,
|
||||||
BoundExpressionStatement
|
BoundExpressionStatement,
|
||||||
|
BoundBlockStatement
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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; }
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue