From 2cdb9abdb6b1e637837c9fe698381dbff8b0ba3f Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Wed, 22 May 2019 12:22:52 +0200 Subject: [PATCH] Implements binding unary expressions --- src/Binder/Binder.cpp | 62 ++++++++++++++----- src/Binder/Binder.hpp | 7 ++- .../BoundExpressions/BoundExpression.hpp | 23 ++++++- src/Binder/BoundOperators.hpp | 8 ++- src/Diagnostics/DiagnosticCode.hpp | 3 + 5 files changed, 83 insertions(+), 20 deletions(-) diff --git a/src/Binder/Binder.cpp b/src/Binder/Binder.cpp index 6c1560d..9a14c71 100644 --- a/src/Binder/Binder.cpp +++ b/src/Binder/Binder.cpp @@ -1,8 +1,9 @@ #include "Binder.hpp" -BoundScriptStatement *Binder::Bind(ParsedScriptStatement *s) { +BoundScriptStatement *Binder::Bind(Script* script, ParsedScriptStatement *s) { auto binder = Binder(); + binder.ScriptData = script; auto statements = s->GetStatements(); vector boundStatements (statements.size()); for (int i = 0; i < statements.size(); i++){ @@ -44,6 +45,8 @@ BoundExpression* Binder::BindExpression(ParsedExpression* expression){ case ParsedExpressionKind ::Binary: return this -> BindBinaryOperator((BinaryExpression*)expression); + case ParsedExpressionKind ::Unary: + return this -> BindUnaryOperator((UnaryExpression*)expression); case ParsedExpressionKind ::Parenthesized: return BindExpression(((ParenthesizedExpression*)expression)->GetInnerExpression()); @@ -67,10 +70,10 @@ BoundExpression* Binder::BindBinaryOperator(BinaryExpression* expression){ auto rightNumeric = (NumericScriptType*)boundRightType; if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ return new BoundBinaryExpression(boundLeft, boundRight, - BoundBinaryOperator::Addition, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat())); + BoundBinaryOperation::Addition, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat())); } else{ - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperator::Addition, new NumericScriptType(false, false)); + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Addition, new NumericScriptType(false, false)); } } //TODO: String Concatenation @@ -81,10 +84,10 @@ BoundExpression* Binder::BindBinaryOperator(BinaryExpression* expression){ auto rightNumeric = (NumericScriptType*)boundRightType; if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ return new BoundBinaryExpression(boundLeft, boundRight, - BoundBinaryOperator::Subtraction, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat())); + BoundBinaryOperation::Subtraction, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat())); } else{ - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperator::Subtraction, new NumericScriptType(false, false)); + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Subtraction, new NumericScriptType(false, false)); } } break; @@ -94,10 +97,10 @@ BoundExpression* Binder::BindBinaryOperator(BinaryExpression* expression){ auto rightNumeric = (NumericScriptType*)boundRightType; if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ return new BoundBinaryExpression(boundLeft, boundRight, - BoundBinaryOperator::Multiplication, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat())); + BoundBinaryOperation::Multiplication, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat())); } else{ - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperator::Multiplication, new NumericScriptType(false, false)); + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Multiplication, new NumericScriptType(false, false)); } } break; @@ -107,26 +110,57 @@ BoundExpression* Binder::BindBinaryOperator(BinaryExpression* expression){ auto rightNumeric = (NumericScriptType*)boundRightType; if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ return new BoundBinaryExpression(boundLeft, boundRight, - BoundBinaryOperator::Division, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat())); + BoundBinaryOperation::Division, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat())); } else{ - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperator::Division, new NumericScriptType(false, false)); + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Division, new NumericScriptType(false, false)); } } break; case BinaryOperatorKind ::Equality: - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperator::Equality, new ScriptType(TypeClass::Bool)); + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Equality, new ScriptType(TypeClass::Bool)); case BinaryOperatorKind ::LogicalAnd: if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool) - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperator::LogicalAnd, new ScriptType(TypeClass::Bool)); + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LogicalAnd, new ScriptType(TypeClass::Bool)); break; case BinaryOperatorKind ::LogicalOr: if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool) - return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperator::LogicalOr, new ScriptType(TypeClass::Bool)); + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LogicalOr, new ScriptType(TypeClass::Bool)); break; default: break; } - //TODO: Log error - return new BoundBadExpression(boundLeft->GetStartPosition(), boundRight->GetEndPosition() - boundLeft->GetStartPosition()); + this -> ScriptData -> Diagnostics->LogError(DiagnosticCode::NoBinaryOperationFound, expression->GetStartPosition(), expression->GetLength()); + return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); +} + +BoundExpression* Binder::BindUnaryOperator(UnaryExpression* expression){ + auto operand = this -> BindExpression(expression->GetOperand()); + auto operandType = operand -> GetType(); + switch (expression->GetOperatorKind()){ + case UnaryOperatorKind ::Identity: + if (operandType->GetClass() == TypeClass::Number){ + // Identity won't change anything during evaluation, so just return the inner operand. + return operand; + } + break; + case UnaryOperatorKind ::Negation: + if (operandType->GetClass() == TypeClass::Number){ + auto innerType = (NumericScriptType*)operandType; + return new BoundUnaryExpression(operand, BoundUnaryOperation::Negation, new NumericScriptType(innerType->IsAwareOfFloat(), + innerType->IsFloat()), expression->GetStartPosition(), expression->GetLength()); + } + break; + case UnaryOperatorKind ::LogicalNegation: + if (operandType->GetClass() == TypeClass::Bool){ + return new BoundUnaryExpression(operand, BoundUnaryOperation::LogicalNegation, new ScriptType(TypeClass::Bool), + expression->GetStartPosition(), expression->GetLength()); + } + break; + default: + break; + } + this -> ScriptData -> Diagnostics->LogError(DiagnosticCode::NoUnaryOperationFound, expression->GetStartPosition(), expression->GetLength()); + return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); + } \ No newline at end of file diff --git a/src/Binder/Binder.hpp b/src/Binder/Binder.hpp index 288877c..a08b1be 100644 --- a/src/Binder/Binder.hpp +++ b/src/Binder/Binder.hpp @@ -3,18 +3,21 @@ #define PORYGONLANG_BINDER_HPP #include "../Parser/ParsedStatements/ParsedStatement.hpp" #include "BoundStatements/BoundStatement.hpp" +#include "../Script.hpp" class Binder { + Script* ScriptData; + BoundStatement *BindStatement(ParsedStatement *statement); BoundStatement *BindBlockStatement(ParsedStatement *statement); BoundStatement *BindExpressionStatement(ParsedStatement *statement); BoundExpression *BindExpression(ParsedExpression *expression); BoundExpression *BindBinaryOperator(BinaryExpression *expression); - + BoundExpression *BindUnaryOperator(UnaryExpression *expression); public: - static BoundScriptStatement* Bind(ParsedScriptStatement* s); + static BoundScriptStatement* Bind(Script* script, ParsedScriptStatement* s); }; diff --git a/src/Binder/BoundExpressions/BoundExpression.hpp b/src/Binder/BoundExpressions/BoundExpression.hpp index a95bc03..3ff515b 100644 --- a/src/Binder/BoundExpressions/BoundExpression.hpp +++ b/src/Binder/BoundExpressions/BoundExpression.hpp @@ -133,13 +133,13 @@ public: class BoundBinaryExpression : public BoundExpression { BoundExpression* _left; BoundExpression* _right; - BoundBinaryOperator _operator; + BoundBinaryOperation _operation; public: - BoundBinaryExpression(BoundExpression* left, BoundExpression* right, BoundBinaryOperator op, ScriptType* result) + BoundBinaryExpression(BoundExpression* left, BoundExpression* right, BoundBinaryOperation op, ScriptType* result) : BoundExpression(left->GetStartPosition(), right->GetEndPosition() - left->GetStartPosition(), result){ _left = left; _right = right; - _operator = op; + _operation = op; } ~BoundBinaryExpression() final{ delete _left; @@ -151,7 +151,24 @@ public: } }; +class BoundUnaryExpression : public BoundExpression { + BoundExpression* _operand; + BoundUnaryOperation _operation; +public: + BoundUnaryExpression(BoundExpression* operand, BoundUnaryOperation op, ScriptType* result, unsigned int start, unsigned int length) + :BoundExpression(start, length, result){ + _operand = operand; + _operation = op; + } + ~BoundUnaryExpression() final{ + delete _operand; + } + + BoundExpressionKind GetKind() final{ + return BoundExpressionKind ::Unary; + } +}; diff --git a/src/Binder/BoundOperators.hpp b/src/Binder/BoundOperators.hpp index c92365c..32dadb7 100644 --- a/src/Binder/BoundOperators.hpp +++ b/src/Binder/BoundOperators.hpp @@ -2,7 +2,7 @@ #ifndef PORYGONLANG_BOUNDOPERATORS_HPP #define PORYGONLANG_BOUNDOPERATORS_HPP -enum class BoundBinaryOperator{ +enum class BoundBinaryOperation{ Addition, Subtraction, Multiplication, @@ -13,4 +13,10 @@ enum class BoundBinaryOperator{ Concatenation }; +enum class BoundUnaryOperation{ + Identity, + Negation, + LogicalNegation, +}; + #endif //PORYGONLANG_BOUNDOPERATORS_HPP diff --git a/src/Diagnostics/DiagnosticCode.hpp b/src/Diagnostics/DiagnosticCode.hpp index 87b7a52..72fb34c 100644 --- a/src/Diagnostics/DiagnosticCode.hpp +++ b/src/Diagnostics/DiagnosticCode.hpp @@ -5,6 +5,9 @@ enum class DiagnosticCode{ UnexpectedCharacter, UnexpectedToken, + + NoBinaryOperationFound, + NoUnaryOperationFound, }; #endif //PORYGONLANG_DIAGNOSTICCODE_HPP