From 80998eab14a636552f2a51c2efffbfed7415d227 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Tue, 21 May 2019 20:59:26 +0200 Subject: [PATCH] More work on binder, implements basic literal expressions --- src/Binder/Binder.cpp | 45 +++++- src/Binder/Binder.hpp | 10 +- .../BoundExpressions/BoundExpression.hpp | 133 ++++++++++++++++++ src/Binder/BoundStatements/BoundStatement.hpp | 18 +++ src/Script.cpp | 6 + src/Script.hpp | 2 + src/ScriptType.hpp | 40 ++++++ 7 files changed, 251 insertions(+), 3 deletions(-) create mode 100644 src/Binder/BoundExpressions/BoundExpression.hpp create mode 100644 src/ScriptType.hpp diff --git a/src/Binder/Binder.cpp b/src/Binder/Binder.cpp index 5b57469..aa4d92b 100644 --- a/src/Binder/Binder.cpp +++ b/src/Binder/Binder.cpp @@ -2,5 +2,48 @@ #include "Binder.hpp" BoundScriptStatement *Binder::Bind(ParsedScriptStatement *s) { - return nullptr; + auto binder = Binder(); + auto statements = s->GetStatements(); + vector boundStatements (statements.size()); + for (int i = 0; i < statements.size(); i++){ + boundStatements[i] = binder.BindStatement(statements[i]); + } + return new BoundScriptStatement(boundStatements); } + +BoundStatement* Binder::BindStatement(ParsedStatement* statement){ + switch (statement -> GetKind()) { + case ParsedStatementKind ::Script: throw; // This shouldn't happen. + case ParsedStatementKind ::Block: return this -> BindBlockStatement(statement); + case ParsedStatementKind ::Expression: return this -> BindExpressionStatement(statement); + } +} + +BoundStatement *Binder::BindBlockStatement(ParsedStatement *statement) { + auto statements = ((ParsedBlockStatement*)statement)->GetStatements(); + vector boundStatements (statements.size()); + for (int i = 0; i < statements.size(); i++){ + boundStatements[i] = this -> BindStatement(statements[i]); + } + return new BoundBlockStatement(boundStatements); +} + +BoundStatement *Binder::BindExpressionStatement(ParsedStatement *statement) { + auto exp = ((ParsedExpressionStatement*)statement)->GetExpression(); + return new BoundExpressionStatement(this -> BindExpression(exp)); +} + +BoundExpression* Binder::BindExpression(ParsedExpression* expression){ + switch (expression -> GetKind()){ + case ParsedExpressionKind ::LiteralInteger: + return new BoundLiteralIntegerExpression(((LiteralIntegerExpression*)expression)->GetValue(), expression->GetStartPosition(), expression->GetLength()); + case ParsedExpressionKind ::LiteralFloat: + return new BoundLiteralFloatExpression(((LiteralFloatExpression*)expression)->GetValue(), expression->GetStartPosition(), expression->GetLength()); + case ParsedExpressionKind ::LiteralBool: + return new BoundLiteralBoolExpression(((LiteralBoolExpression*)expression)->GetValue(), expression->GetStartPosition(), expression->GetLength()); + + case ParsedExpressionKind ::Bad: + return new BoundBadExpression(expression->GetStartPosition(), expression-> GetLength()); + } +} + diff --git a/src/Binder/Binder.hpp b/src/Binder/Binder.hpp index 9b88292..83acc62 100644 --- a/src/Binder/Binder.hpp +++ b/src/Binder/Binder.hpp @@ -1,13 +1,19 @@ #ifndef PORYGONLANG_BINDER_HPP #define PORYGONLANG_BINDER_HPP - -#include "../Parser/ParsedStatements/ParsedScriptStatement.hpp" +#include "../Parser/ParsedStatements/ParsedStatement.hpp" #include "BoundStatements/BoundStatement.hpp" + class Binder { + BoundStatement *BindStatement(ParsedStatement *statement); + BoundStatement *BindBlockStatement(ParsedStatement *statement); public: static BoundScriptStatement* Bind(ParsedScriptStatement* s); + + BoundExpression *BindExpression(ParsedExpression *expression); + + BoundStatement *BindExpressionStatement(ParsedStatement *statement); }; diff --git a/src/Binder/BoundExpressions/BoundExpression.hpp b/src/Binder/BoundExpressions/BoundExpression.hpp new file mode 100644 index 0000000..3ce003d --- /dev/null +++ b/src/Binder/BoundExpressions/BoundExpression.hpp @@ -0,0 +1,133 @@ +#include + + +#ifndef PORYGONLANG_BOUNDEXPRESSION_HPP +#define PORYGONLANG_BOUNDEXPRESSION_HPP + +#include +#include "../../ScriptType.hpp" + +using namespace std; + +enum class BoundExpressionKind{ + Bad, + + LiteralInteger, + LiteralFloat, + LiteralString, + LiteralBool, + + Unary, + Binary, + Parenthesized, +}; + +class BoundExpression{ + unsigned int _start; + unsigned int _length; + ScriptType* _type; +public: + BoundExpression(unsigned int start, unsigned int length, ScriptType* type){ + _start = start; + _length = length; + _type = type; + } + virtual ~BoundExpression(){ + delete _type; + }; + + virtual BoundExpressionKind GetKind() = 0; + virtual ScriptType* GetType(){ + return _type; + }; + + unsigned int GetStartPosition(){ + return _start; + } + unsigned int GetLength(){ + return _length; + } +}; + +class BoundBadExpression : public BoundExpression{ +public: + BoundBadExpression(unsigned int start, unsigned int length) : BoundExpression(start, length, new ScriptType(TypeClass::Error)){} + + BoundExpressionKind GetKind() final{ + return BoundExpressionKind ::Bad; + } +}; + +class BoundLiteralIntegerExpression : public BoundExpression{ + long _value; +public: + BoundLiteralIntegerExpression(long value, unsigned int start, unsigned int length) + : BoundExpression(start, length, new NumericScriptType(true, false)){ + _value = value; + } + + BoundExpressionKind GetKind() final{ + return BoundExpressionKind ::LiteralInteger; + } + + long GetValue(){ + return _value; + } +}; + +class BoundLiteralFloatExpression : public BoundExpression{ + double _value; +public: + BoundLiteralFloatExpression(double value, unsigned int start, unsigned int length) + : BoundExpression(start, length, new NumericScriptType(true, true)){ + _value = value; + } + + BoundExpressionKind GetKind() final{ + return BoundExpressionKind ::LiteralFloat; + } + + double GetValue(){ + return _value; + } +}; + +class BoundLiteralStringExpression : public BoundExpression{ + string _value; +public: + BoundLiteralStringExpression(string value, unsigned int start, unsigned int length) + : BoundExpression(start, length, new ScriptType(TypeClass::String)){ + _value = std::move(value); + } + + BoundExpressionKind GetKind() final{ + return BoundExpressionKind ::LiteralString; + } + + string GetValue(){ + return _value; + } +}; + +class BoundLiteralBoolExpression : public BoundExpression{ + bool _value; +public: + BoundLiteralBoolExpression(bool value, unsigned int start, unsigned int length) + : BoundExpression(start, length, new ScriptType(TypeClass::Bool)){ + _value = value; + } + + BoundExpressionKind GetKind() final{ + return BoundExpressionKind ::LiteralBool; + } + + bool GetValue(){ + return _value; + } +}; + + + + + +#endif //PORYGONLANG_BOUNDEXPRESSION_HPP diff --git a/src/Binder/BoundStatements/BoundStatement.hpp b/src/Binder/BoundStatements/BoundStatement.hpp index ba617c7..58b5b4c 100644 --- a/src/Binder/BoundStatements/BoundStatement.hpp +++ b/src/Binder/BoundStatements/BoundStatement.hpp @@ -5,11 +5,14 @@ #define PORYGONLANG_BOUNDSTATEMENT_HPP #include +#include "../BoundExpressions/BoundExpression.hpp" + using namespace std; enum class BoundStatementKind{ Script, Block, + Expression, }; class BoundStatement{ @@ -46,4 +49,19 @@ public: } }; +class BoundExpressionStatement : public BoundStatement{ + BoundExpression* _expression; +public: + explicit BoundExpressionStatement(BoundExpression* expression){ + _expression = expression; + } + ~BoundExpressionStatement() final{ + delete _expression; + } + + BoundStatementKind GetKind() final{ + return BoundStatementKind ::Expression; + } +}; + #endif //PORYGONLANG_BOUNDSTATEMENT_HPP diff --git a/src/Script.cpp b/src/Script.cpp index 7a7e3a3..043f18c 100644 --- a/src/Script.cpp +++ b/src/Script.cpp @@ -4,6 +4,7 @@ #include "Script.hpp" #include "Parser/Lexer.hpp" #include "Parser/Parser.hpp" +#include "Binder/Binder.hpp" Script Script::Create(string script) { auto s = Script(); @@ -13,6 +14,7 @@ Script Script::Create(string script) { Script::~Script() { delete this -> Diagnostics; + delete this -> BoundScript; } void Script::Parse(string script) { @@ -24,5 +26,9 @@ void Script::Parse(string script) { delete token; } lexResult.clear(); + if (!Diagnostics->HasErrors()){ + this->BoundScript = Binder::Bind(parseResult); + } + delete parseResult; } diff --git a/src/Script.hpp b/src/Script.hpp index 6e661c6..61deb63 100644 --- a/src/Script.hpp +++ b/src/Script.hpp @@ -6,6 +6,7 @@ #include #include "Diagnostics/Diagnostics.hpp" +#include "Binder/BoundStatements/BoundStatement.hpp" using namespace std; @@ -15,6 +16,7 @@ class Script { }; void Parse(string script); + BoundScriptStatement* BoundScript; public: static Script Create(string script); Diagnostics* Diagnostics; diff --git a/src/ScriptType.hpp b/src/ScriptType.hpp new file mode 100644 index 0000000..e5bb763 --- /dev/null +++ b/src/ScriptType.hpp @@ -0,0 +1,40 @@ + +#ifndef PORYGONLANG_SCRIPTTYPE_HPP +#define PORYGONLANG_SCRIPTTYPE_HPP + +enum class TypeClass{ + Error, + Nil, + Number, + Bool, + String, + Function, + UserData, + Table, +}; + +class ScriptType{ + TypeClass _class; +public: + explicit ScriptType(TypeClass c){ + _class = c; + } + + explicit virtual operator TypeClass(){ + return _class; + } +}; + +class NumericScriptType : public ScriptType{ + // Are we aware of whether this is a float or not? + bool _awareOfFloat; + // Is this value a float? + bool _isFloat; +public: + explicit NumericScriptType(bool floatAware, bool isFloat) : ScriptType(TypeClass::Number){ + _awareOfFloat = floatAware; + _isFloat = isFloat; + } +}; + +#endif //PORYGONLANG_SCRIPTTYPE_HPP