diff --git a/src/Binder/Binder.cpp b/src/Binder/Binder.cpp index dc060a3..6c1560d 100644 --- a/src/Binder/Binder.cpp +++ b/src/Binder/Binder.cpp @@ -42,6 +42,9 @@ BoundExpression* Binder::BindExpression(ParsedExpression* expression){ case ParsedExpressionKind ::LiteralBool: return new BoundLiteralBoolExpression(((LiteralBoolExpression*)expression)->GetValue(), expression->GetStartPosition(), expression->GetLength()); + case ParsedExpressionKind ::Binary: + return this -> BindBinaryOperator((BinaryExpression*)expression); + case ParsedExpressionKind ::Parenthesized: return BindExpression(((ParenthesizedExpression*)expression)->GetInnerExpression()); @@ -50,3 +53,80 @@ BoundExpression* Binder::BindExpression(ParsedExpression* expression){ } } +BoundExpression* Binder::BindBinaryOperator(BinaryExpression* expression){ + auto boundLeft = this -> BindExpression(expression->GetLeft()); + auto boundRight = this -> BindExpression(expression->GetRight()); + + auto boundLeftType = boundLeft->GetType(); + auto boundRightType = boundRight->GetType(); + + switch (expression->GetOperatorKind()){ + case BinaryOperatorKind ::Addition: + if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number){ + auto leftNumeric = (NumericScriptType*)boundLeftType; + auto rightNumeric = (NumericScriptType*)boundRightType; + if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ + return new BoundBinaryExpression(boundLeft, boundRight, + BoundBinaryOperator::Addition, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat())); + } + else{ + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperator::Addition, new NumericScriptType(false, false)); + } + } + //TODO: String Concatenation + break; + case BinaryOperatorKind ::Subtraction: + if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number){ + auto leftNumeric = (NumericScriptType*)boundLeftType; + auto rightNumeric = (NumericScriptType*)boundRightType; + if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ + return new BoundBinaryExpression(boundLeft, boundRight, + BoundBinaryOperator::Subtraction, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat())); + } + else{ + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperator::Subtraction, new NumericScriptType(false, false)); + } + } + break; + case BinaryOperatorKind ::Multiplication: + if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number){ + auto leftNumeric = (NumericScriptType*)boundLeftType; + auto rightNumeric = (NumericScriptType*)boundRightType; + if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ + return new BoundBinaryExpression(boundLeft, boundRight, + BoundBinaryOperator::Multiplication, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat())); + } + else{ + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperator::Multiplication, new NumericScriptType(false, false)); + } + } + break; + case BinaryOperatorKind ::Division: + if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number){ + auto leftNumeric = (NumericScriptType*)boundLeftType; + auto rightNumeric = (NumericScriptType*)boundRightType; + if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ + return new BoundBinaryExpression(boundLeft, boundRight, + BoundBinaryOperator::Division, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat())); + } + else{ + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperator::Division, new NumericScriptType(false, false)); + } + } + break; + case BinaryOperatorKind ::Equality: + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperator::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)); + break; + case BinaryOperatorKind ::LogicalOr: + if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool) + return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperator::LogicalOr, new ScriptType(TypeClass::Bool)); + break; + default: + break; + } + //TODO: Log error + return new BoundBadExpression(boundLeft->GetStartPosition(), boundRight->GetEndPosition() - boundLeft->GetStartPosition()); +} \ No newline at end of file diff --git a/src/Binder/Binder.hpp b/src/Binder/Binder.hpp index 83acc62..288877c 100644 --- a/src/Binder/Binder.hpp +++ b/src/Binder/Binder.hpp @@ -8,12 +8,14 @@ class Binder { BoundStatement *BindStatement(ParsedStatement *statement); BoundStatement *BindBlockStatement(ParsedStatement *statement); + BoundStatement *BindExpressionStatement(ParsedStatement *statement); + + BoundExpression *BindExpression(ParsedExpression *expression); + BoundExpression *BindBinaryOperator(BinaryExpression *expression); + 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 index 3ce003d..a95bc03 100644 --- a/src/Binder/BoundExpressions/BoundExpression.hpp +++ b/src/Binder/BoundExpressions/BoundExpression.hpp @@ -6,6 +6,7 @@ #include #include "../../ScriptType.hpp" +#include "../BoundOperators.hpp" using namespace std; @@ -47,6 +48,9 @@ public: unsigned int GetLength(){ return _length; } + unsigned int GetEndPosition(){ + return _start + _length - 1; + } }; class BoundBadExpression : public BoundExpression{ @@ -126,6 +130,27 @@ public: } }; +class BoundBinaryExpression : public BoundExpression { + BoundExpression* _left; + BoundExpression* _right; + BoundBinaryOperator _operator; +public: + BoundBinaryExpression(BoundExpression* left, BoundExpression* right, BoundBinaryOperator op, ScriptType* result) + : BoundExpression(left->GetStartPosition(), right->GetEndPosition() - left->GetStartPosition(), result){ + _left = left; + _right = right; + _operator = op; + } + ~BoundBinaryExpression() final{ + delete _left; + delete _right; + } + + BoundExpressionKind GetKind() final{ + return BoundExpressionKind ::Binary; + } +}; + diff --git a/src/Binder/BoundOperators.hpp b/src/Binder/BoundOperators.hpp new file mode 100644 index 0000000..c92365c --- /dev/null +++ b/src/Binder/BoundOperators.hpp @@ -0,0 +1,16 @@ + +#ifndef PORYGONLANG_BOUNDOPERATORS_HPP +#define PORYGONLANG_BOUNDOPERATORS_HPP + +enum class BoundBinaryOperator{ + Addition, + Subtraction, + Multiplication, + Division, + Equality, + LogicalAnd, + LogicalOr, + Concatenation +}; + +#endif //PORYGONLANG_BOUNDOPERATORS_HPP diff --git a/src/ScriptType.hpp b/src/ScriptType.hpp index e5bb763..1262dd3 100644 --- a/src/ScriptType.hpp +++ b/src/ScriptType.hpp @@ -20,7 +20,7 @@ public: _class = c; } - explicit virtual operator TypeClass(){ + TypeClass GetClass(){ return _class; } }; @@ -35,6 +35,14 @@ public: _awareOfFloat = floatAware; _isFloat = isFloat; } + + bool IsAwareOfFloat(){ + return _awareOfFloat; + } + + bool IsFloat(){ + return _isFloat; + } }; #endif //PORYGONLANG_SCRIPTTYPE_HPP