From ec7a32240f95e47f62bbb579fc86b8605ac18099 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Mon, 12 Nov 2018 16:21:59 +0100 Subject: [PATCH] Initial work on the concept of statements --- Upsilon/Binder/Binder.cs | 30 ++++++++++++---- Upsilon/Binder/BoundAssignmenExpression.cs | 3 +- Upsilon/Binder/BoundExpressionStatement.cs | 13 +++++++ Upsilon/Binder/BoundKind.cs | 7 ++-- Upsilon/Binder/BoundScript.cs | 6 ++-- Upsilon/Binder/BoundStatement.cs | 6 ++++ Upsilon/Binder/BoundVariableAssignment.cs | 16 +++++++++ Upsilon/Evaluator/Evaluator.cs | 29 ++++++++++++--- Upsilon/Parser/Parser.cs | 35 ++++++++++++------- .../AssignmentExpressionSyntax.cs | 2 +- .../ExpressionStatementSyntax.cs | 20 +++++++++++ .../ScriptSyntax.cs | 6 ++-- .../Parser/StatementSyntax/StatementSyntax.cs | 7 ++++ Upsilon/Parser/SyntaxKeyWords.cs | 2 ++ Upsilon/Parser/SyntaxKind.cs | 4 +++ Upsilon/Upsilon.csproj.DotSettings | 3 +- 16 files changed, 155 insertions(+), 34 deletions(-) create mode 100644 Upsilon/Binder/BoundExpressionStatement.cs create mode 100644 Upsilon/Binder/BoundStatement.cs create mode 100644 Upsilon/Binder/BoundVariableAssignment.cs rename Upsilon/Parser/{ExpressionSyntax => StatementSyntax}/AssignmentExpressionSyntax.cs (92%) create mode 100644 Upsilon/Parser/StatementSyntax/ExpressionStatementSyntax.cs rename Upsilon/Parser/{ExpressionSyntax => StatementSyntax}/ScriptSyntax.cs (70%) create mode 100644 Upsilon/Parser/StatementSyntax/StatementSyntax.cs diff --git a/Upsilon/Binder/Binder.cs b/Upsilon/Binder/Binder.cs index 16c3ef8..2889067 100644 --- a/Upsilon/Binder/Binder.cs +++ b/Upsilon/Binder/Binder.cs @@ -18,10 +18,23 @@ namespace Upsilon.Binder public BoundScript BindScript(ScriptSyntax e) { - var bound = BindExpression(e.Statement); + var bound = BindStatement(e.Statement); return new BoundScript(bound); } + public BoundStatement BindStatement(StatementSyntax s) + { + switch (s.Kind) + { + case SyntaxKind.ExpressionStatement: + return BindExpressionStatement((ExpressionStatementSyntax) s); + case SyntaxKind.AssignmentExpression: + return BindAssignmentStatement((AssignmentExpressionSyntax) s); + } + + return null; + } + public BoundExpression BindExpression(ExpressionSyntax e) { switch (e.Kind) @@ -34,8 +47,6 @@ namespace Upsilon.Binder return BindLiteralExpression((LiteralExpressionSyntax) e); case SyntaxKind.ParenthesizedExpression: return BindParenthesizedExpression((ParenthesizedExpressionSyntax) e); - case SyntaxKind.AssignmentExpression: - return BindAssignmentExpression((AssignmentExpressionSyntax) e); case SyntaxKind.VariableExpression: return BindVariableExpression((VariableExpressionSyntax) e); case SyntaxKind.BadExpression: @@ -105,7 +116,13 @@ namespace Upsilon.Binder return BindExpression(e.Expression); } - private BoundExpression BindAssignmentExpression(AssignmentExpressionSyntax e) + private BoundStatement BindExpressionStatement(ExpressionStatementSyntax s) + { + var exp = BindExpression(s.Expression); + return new BoundExpressionStatement(exp); + } + + private BoundStatement BindAssignmentStatement(AssignmentExpressionSyntax e) { var name = e.Identifier.Name; var boundExpression = BindExpression(e.Expression); @@ -123,11 +140,12 @@ namespace Upsilon.Binder if (boundExpression.Type != variable.Type) { _diagnostics.LogCannotConvert(boundExpression.Type, variable.Type, e.Span); - return boundExpression; + throw new NotImplementedException(); + //return boundExpression; } } - return new BoundAssignmenExpression(variable, boundExpression); + return new BoundVariableAssignment(variable, boundExpression); } private BoundExpression BindVariableExpression(VariableExpressionSyntax e) diff --git a/Upsilon/Binder/BoundAssignmenExpression.cs b/Upsilon/Binder/BoundAssignmenExpression.cs index 3f6cf90..dc9304a 100644 --- a/Upsilon/Binder/BoundAssignmenExpression.cs +++ b/Upsilon/Binder/BoundAssignmenExpression.cs @@ -2,6 +2,7 @@ using Upsilon.BaseTypes; namespace Upsilon.Binder { + /* public class BoundAssignmenExpression : BoundExpression { public BoundAssignmenExpression(VariableSymbol variable, BoundExpression expression) @@ -15,5 +16,5 @@ namespace Upsilon.Binder public override BoundKind Kind => BoundKind.BoundAssignmentExpression; public override Type Type { get; } - } + }*/ } \ No newline at end of file diff --git a/Upsilon/Binder/BoundExpressionStatement.cs b/Upsilon/Binder/BoundExpressionStatement.cs new file mode 100644 index 0000000..c4ac943 --- /dev/null +++ b/Upsilon/Binder/BoundExpressionStatement.cs @@ -0,0 +1,13 @@ +namespace Upsilon.Binder +{ + public class BoundExpressionStatement : BoundStatement + { + public BoundExpression Expression { get; } + public override BoundKind Kind => BoundKind.BoundExpressionStatement; + + public BoundExpressionStatement(BoundExpression expression) + { + Expression = expression; + } + } +} \ No newline at end of file diff --git a/Upsilon/Binder/BoundKind.cs b/Upsilon/Binder/BoundKind.cs index 8ed3eb1..c724c28 100644 --- a/Upsilon/Binder/BoundKind.cs +++ b/Upsilon/Binder/BoundKind.cs @@ -7,7 +7,10 @@ namespace Upsilon.Binder BoundLiteralExpression, BoundBinaryExpression, BoundUnaryExpression, - BoundAssignmentExpression, - VariableExpression + VariableExpression, + + // Statements + BoundAssignmentStatement, + BoundExpressionStatement } } \ No newline at end of file diff --git a/Upsilon/Binder/BoundScript.cs b/Upsilon/Binder/BoundScript.cs index b6bf5d8..9132563 100644 --- a/Upsilon/Binder/BoundScript.cs +++ b/Upsilon/Binder/BoundScript.cs @@ -1,14 +1,14 @@ namespace Upsilon.Binder { - public class BoundScript : BoundNode + public class BoundScript : BoundStatement { - public BoundScript(BoundExpression statement) + public BoundScript(BoundStatement statement) { Statement = statement; } public override BoundKind Kind => BoundKind.BoundScript; - public BoundExpression Statement { get; } + public BoundStatement Statement { get; } } } \ No newline at end of file diff --git a/Upsilon/Binder/BoundStatement.cs b/Upsilon/Binder/BoundStatement.cs new file mode 100644 index 0000000..4f2b707 --- /dev/null +++ b/Upsilon/Binder/BoundStatement.cs @@ -0,0 +1,6 @@ +namespace Upsilon.Binder +{ + public abstract class BoundStatement : BoundNode + { + } +} \ No newline at end of file diff --git a/Upsilon/Binder/BoundVariableAssignment.cs b/Upsilon/Binder/BoundVariableAssignment.cs new file mode 100644 index 0000000..1cb0f4c --- /dev/null +++ b/Upsilon/Binder/BoundVariableAssignment.cs @@ -0,0 +1,16 @@ +namespace Upsilon.Binder +{ + public class BoundVariableAssignment : BoundStatement + { + public VariableSymbol Variable { get; } + public BoundExpression BoundExpression { get; } + + public BoundVariableAssignment(VariableSymbol variable, BoundExpression boundExpression) + { + Variable = variable; + BoundExpression = boundExpression; + } + + public override BoundKind Kind => BoundKind.BoundAssignmentStatement; + } +} \ No newline at end of file diff --git a/Upsilon/Evaluator/Evaluator.cs b/Upsilon/Evaluator/Evaluator.cs index 82063d4..0f1c1e8 100644 --- a/Upsilon/Evaluator/Evaluator.cs +++ b/Upsilon/Evaluator/Evaluator.cs @@ -8,6 +8,7 @@ namespace Upsilon.Evaluator public class Evaluator { private readonly Diagnostics _diagnostics; + private object _value; public Script Script { get; } private readonly Dictionary _variables = new Dictionary(); @@ -25,7 +26,26 @@ namespace Upsilon.Evaluator public object Evaluate(BoundScript e) { - return EvaluateExpression(e.Statement); + EvaluateStatement(e.Statement); + return _value; + } + + private void EvaluateStatement(BoundStatement e) + { + switch (e.Kind) + { + case BoundKind.BoundAssignmentStatement: + EvaluateAssignmentStatement((BoundVariableAssignment) e); + break; + default: + EvaluateExpressionStatement((BoundExpressionStatement) e); + break; + } + } + + private void EvaluateExpressionStatement(BoundExpressionStatement e) + { + _value = EvaluateExpression(e.Expression); } private object EvaluateExpression(BoundExpression e) @@ -38,8 +58,6 @@ namespace Upsilon.Evaluator return EvaluateBinaryExpression((BoundBinaryExpression) e); case BoundKind.BoundUnaryExpression: return EvaluateUnaryExpression((BoundUnaryExpression) e); - case BoundKind.BoundAssignmentExpression: - return EvaluateAssignmentExpression((BoundAssignmenExpression) e); case BoundKind.VariableExpression: return EvaluateVariableExpression((BoundVariableExpression) e); default: @@ -86,10 +104,11 @@ namespace Upsilon.Evaluator } } - private object EvaluateAssignmentExpression(BoundAssignmenExpression e) + private object EvaluateAssignmentStatement(BoundVariableAssignment e) { - var val = EvaluateExpression(e.Expression); + var val = EvaluateExpression(e.BoundExpression); _variables[e.Variable] = val; + _value = val; return val; } diff --git a/Upsilon/Parser/Parser.cs b/Upsilon/Parser/Parser.cs index 2f28030..b02f282 100644 --- a/Upsilon/Parser/Parser.cs +++ b/Upsilon/Parser/Parser.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Immutable; using Upsilon.Text; @@ -50,25 +49,37 @@ namespace Upsilon.Parser public ScriptSyntax ParseScriptSyntax() { - var expression = ParseExpression(); + var statement = ParseStatement(); var eof = MatchToken(SyntaxKind.EndOfFile); - return new ScriptSyntax(expression, eof); + return new ScriptSyntax(statement, eof); + } + + public StatementSyntax ParseStatement() + { + if (Current.Kind == SyntaxKind.Identifier && Next.Kind == SyntaxKind.Equals) + { + return ParseAssignmentExpression(); + } + if (Current.Kind == SyntaxKind.LocalKeyword && Next.Kind == SyntaxKind.Identifier) + { + return ParseAssignmentExpression(); + } + + return ParseExpressionStatement(); + } + + public ExpressionStatementSyntax ParseExpressionStatement() + { + var expression = ParseExpression(); + return new ExpressionStatementSyntax(expression); } public ExpressionSyntax ParseExpression() { - if (Current.Kind == SyntaxKind.Identifier && Next.Kind == SyntaxKind.Equals) - { - return AssignmentExpression(); - } - if (Current.Kind == SyntaxKind.LocalKeyword && Next.Kind == SyntaxKind.Identifier) - { - return AssignmentExpression(); - } return ParseBinaryExpression(); } - private AssignmentExpressionSyntax AssignmentExpression() + private AssignmentExpressionSyntax ParseAssignmentExpression() { SyntaxToken localKeyword = null; if (Current.Kind == SyntaxKind.LocalKeyword) diff --git a/Upsilon/Parser/ExpressionSyntax/AssignmentExpressionSyntax.cs b/Upsilon/Parser/StatementSyntax/AssignmentExpressionSyntax.cs similarity index 92% rename from Upsilon/Parser/ExpressionSyntax/AssignmentExpressionSyntax.cs rename to Upsilon/Parser/StatementSyntax/AssignmentExpressionSyntax.cs index f0d67bc..1e941da 100644 --- a/Upsilon/Parser/ExpressionSyntax/AssignmentExpressionSyntax.cs +++ b/Upsilon/Parser/StatementSyntax/AssignmentExpressionSyntax.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; namespace Upsilon.Parser { - public class AssignmentExpressionSyntax : ExpressionSyntax + public class AssignmentExpressionSyntax : StatementSyntax { public AssignmentExpressionSyntax(SyntaxToken localToken, IdentifierToken identifier, SyntaxToken equalsToken, ExpressionSyntax expression) diff --git a/Upsilon/Parser/StatementSyntax/ExpressionStatementSyntax.cs b/Upsilon/Parser/StatementSyntax/ExpressionStatementSyntax.cs new file mode 100644 index 0000000..1916aea --- /dev/null +++ b/Upsilon/Parser/StatementSyntax/ExpressionStatementSyntax.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace Upsilon.Parser +{ + public class ExpressionStatementSyntax : StatementSyntax + { + public ExpressionSyntax Expression { get; } + + public ExpressionStatementSyntax(ExpressionSyntax expression) + { + Expression = expression; + } + + public override SyntaxKind Kind => SyntaxKind.ExpressionStatement; + public override IEnumerable ChildNodes() + { + yield return Expression; + } + } +} \ No newline at end of file diff --git a/Upsilon/Parser/ExpressionSyntax/ScriptSyntax.cs b/Upsilon/Parser/StatementSyntax/ScriptSyntax.cs similarity index 70% rename from Upsilon/Parser/ExpressionSyntax/ScriptSyntax.cs rename to Upsilon/Parser/StatementSyntax/ScriptSyntax.cs index c050fcc..8b45ca4 100644 --- a/Upsilon/Parser/ExpressionSyntax/ScriptSyntax.cs +++ b/Upsilon/Parser/StatementSyntax/ScriptSyntax.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; namespace Upsilon.Parser { - public class ScriptSyntax : SyntaxNode + public class ScriptSyntax : StatementSyntax { - public ScriptSyntax(ExpressionSyntax statement, SyntaxToken endOfFileToken) + public ScriptSyntax(StatementSyntax statement, SyntaxToken endOfFileToken) { Statement = statement; EndOfFileToken = endOfFileToken; @@ -12,7 +12,7 @@ namespace Upsilon.Parser public override SyntaxKind Kind => SyntaxKind.ScriptUnit; - public ExpressionSyntax Statement { get; } + public StatementSyntax Statement { get; } public SyntaxToken EndOfFileToken { get; } public override IEnumerable ChildNodes() diff --git a/Upsilon/Parser/StatementSyntax/StatementSyntax.cs b/Upsilon/Parser/StatementSyntax/StatementSyntax.cs new file mode 100644 index 0000000..cc7addc --- /dev/null +++ b/Upsilon/Parser/StatementSyntax/StatementSyntax.cs @@ -0,0 +1,7 @@ +namespace Upsilon.Parser +{ + public abstract class StatementSyntax : SyntaxNode + { + + } +} \ No newline at end of file diff --git a/Upsilon/Parser/SyntaxKeyWords.cs b/Upsilon/Parser/SyntaxKeyWords.cs index 987a629..fcb983c 100644 --- a/Upsilon/Parser/SyntaxKeyWords.cs +++ b/Upsilon/Parser/SyntaxKeyWords.cs @@ -18,6 +18,8 @@ namespace Upsilon.Parser return SyntaxKind.OrKeyword; case "local": return SyntaxKind.LocalKeyword; + case "end": + return SyntaxKind.EndKeyword; default: return SyntaxKind.Identifier; } diff --git a/Upsilon/Parser/SyntaxKind.cs b/Upsilon/Parser/SyntaxKind.cs index 7a145c3..95479fa 100644 --- a/Upsilon/Parser/SyntaxKind.cs +++ b/Upsilon/Parser/SyntaxKind.cs @@ -27,6 +27,7 @@ namespace Upsilon.Parser AndKeyword, OrKeyword, LocalKeyword, + EndKeyword, Identifier, @@ -41,5 +42,8 @@ namespace Upsilon.Parser // script unit ScriptUnit, + + // statements + ExpressionStatement } } \ No newline at end of file diff --git a/Upsilon/Upsilon.csproj.DotSettings b/Upsilon/Upsilon.csproj.DotSettings index 3366c42..4cddffc 100644 --- a/Upsilon/Upsilon.csproj.DotSettings +++ b/Upsilon/Upsilon.csproj.DotSettings @@ -1,2 +1,3 @@  - True \ No newline at end of file + True + True \ No newline at end of file