Implements binding unary expressions

This commit is contained in:
Deukhoofd 2019-05-22 12:22:52 +02:00
parent 62e938e039
commit 2cdb9abdb6
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
5 changed files with 83 additions and 20 deletions

View File

@ -1,8 +1,9 @@
#include "Binder.hpp" #include "Binder.hpp"
BoundScriptStatement *Binder::Bind(ParsedScriptStatement *s) { BoundScriptStatement *Binder::Bind(Script* script, ParsedScriptStatement *s) {
auto binder = Binder(); auto binder = Binder();
binder.ScriptData = script;
auto statements = s->GetStatements(); auto statements = s->GetStatements();
vector<BoundStatement*> boundStatements (statements.size()); vector<BoundStatement*> boundStatements (statements.size());
for (int i = 0; i < statements.size(); i++){ for (int i = 0; i < statements.size(); i++){
@ -44,6 +45,8 @@ BoundExpression* Binder::BindExpression(ParsedExpression* expression){
case ParsedExpressionKind ::Binary: case ParsedExpressionKind ::Binary:
return this -> BindBinaryOperator((BinaryExpression*)expression); return this -> BindBinaryOperator((BinaryExpression*)expression);
case ParsedExpressionKind ::Unary:
return this -> BindUnaryOperator((UnaryExpression*)expression);
case ParsedExpressionKind ::Parenthesized: case ParsedExpressionKind ::Parenthesized:
return BindExpression(((ParenthesizedExpression*)expression)->GetInnerExpression()); return BindExpression(((ParenthesizedExpression*)expression)->GetInnerExpression());
@ -67,10 +70,10 @@ BoundExpression* Binder::BindBinaryOperator(BinaryExpression* expression){
auto rightNumeric = (NumericScriptType*)boundRightType; auto rightNumeric = (NumericScriptType*)boundRightType;
if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){
return new BoundBinaryExpression(boundLeft, boundRight, return new BoundBinaryExpression(boundLeft, boundRight,
BoundBinaryOperator::Addition, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat())); BoundBinaryOperation::Addition, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()));
} }
else{ 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 //TODO: String Concatenation
@ -81,10 +84,10 @@ BoundExpression* Binder::BindBinaryOperator(BinaryExpression* expression){
auto rightNumeric = (NumericScriptType*)boundRightType; auto rightNumeric = (NumericScriptType*)boundRightType;
if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){
return new BoundBinaryExpression(boundLeft, boundRight, return new BoundBinaryExpression(boundLeft, boundRight,
BoundBinaryOperator::Subtraction, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat())); BoundBinaryOperation::Subtraction, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()));
} }
else{ else{
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperator::Subtraction, new NumericScriptType(false, false)); return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Subtraction, new NumericScriptType(false, false));
} }
} }
break; break;
@ -94,10 +97,10 @@ BoundExpression* Binder::BindBinaryOperator(BinaryExpression* expression){
auto rightNumeric = (NumericScriptType*)boundRightType; auto rightNumeric = (NumericScriptType*)boundRightType;
if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){
return new BoundBinaryExpression(boundLeft, boundRight, return new BoundBinaryExpression(boundLeft, boundRight,
BoundBinaryOperator::Multiplication, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat())); BoundBinaryOperation::Multiplication, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()));
} }
else{ else{
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperator::Multiplication, new NumericScriptType(false, false)); return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Multiplication, new NumericScriptType(false, false));
} }
} }
break; break;
@ -107,26 +110,57 @@ BoundExpression* Binder::BindBinaryOperator(BinaryExpression* expression){
auto rightNumeric = (NumericScriptType*)boundRightType; auto rightNumeric = (NumericScriptType*)boundRightType;
if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){
return new BoundBinaryExpression(boundLeft, boundRight, return new BoundBinaryExpression(boundLeft, boundRight,
BoundBinaryOperator::Division, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat())); BoundBinaryOperation::Division, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()));
} }
else{ else{
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperator::Division, new NumericScriptType(false, false)); return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Division, new NumericScriptType(false, false));
} }
} }
break; break;
case BinaryOperatorKind ::Equality: 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: case BinaryOperatorKind ::LogicalAnd:
if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool) 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; break;
case BinaryOperatorKind ::LogicalOr: case BinaryOperatorKind ::LogicalOr:
if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool) 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; break;
default: default:
break; break;
} }
//TODO: Log error this -> ScriptData -> Diagnostics->LogError(DiagnosticCode::NoBinaryOperationFound, expression->GetStartPosition(), expression->GetLength());
return new BoundBadExpression(boundLeft->GetStartPosition(), boundRight->GetEndPosition() - boundLeft->GetStartPosition()); 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());
} }

View File

@ -3,18 +3,21 @@
#define PORYGONLANG_BINDER_HPP #define PORYGONLANG_BINDER_HPP
#include "../Parser/ParsedStatements/ParsedStatement.hpp" #include "../Parser/ParsedStatements/ParsedStatement.hpp"
#include "BoundStatements/BoundStatement.hpp" #include "BoundStatements/BoundStatement.hpp"
#include "../Script.hpp"
class Binder { class Binder {
Script* ScriptData;
BoundStatement *BindStatement(ParsedStatement *statement); BoundStatement *BindStatement(ParsedStatement *statement);
BoundStatement *BindBlockStatement(ParsedStatement *statement); BoundStatement *BindBlockStatement(ParsedStatement *statement);
BoundStatement *BindExpressionStatement(ParsedStatement *statement); BoundStatement *BindExpressionStatement(ParsedStatement *statement);
BoundExpression *BindExpression(ParsedExpression *expression); BoundExpression *BindExpression(ParsedExpression *expression);
BoundExpression *BindBinaryOperator(BinaryExpression *expression); BoundExpression *BindBinaryOperator(BinaryExpression *expression);
BoundExpression *BindUnaryOperator(UnaryExpression *expression);
public: public:
static BoundScriptStatement* Bind(ParsedScriptStatement* s); static BoundScriptStatement* Bind(Script* script, ParsedScriptStatement* s);
}; };

View File

@ -133,13 +133,13 @@ public:
class BoundBinaryExpression : public BoundExpression { class BoundBinaryExpression : public BoundExpression {
BoundExpression* _left; BoundExpression* _left;
BoundExpression* _right; BoundExpression* _right;
BoundBinaryOperator _operator; BoundBinaryOperation _operation;
public: 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){ : BoundExpression(left->GetStartPosition(), right->GetEndPosition() - left->GetStartPosition(), result){
_left = left; _left = left;
_right = right; _right = right;
_operator = op; _operation = op;
} }
~BoundBinaryExpression() final{ ~BoundBinaryExpression() final{
delete _left; 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;
}
};

View File

@ -2,7 +2,7 @@
#ifndef PORYGONLANG_BOUNDOPERATORS_HPP #ifndef PORYGONLANG_BOUNDOPERATORS_HPP
#define PORYGONLANG_BOUNDOPERATORS_HPP #define PORYGONLANG_BOUNDOPERATORS_HPP
enum class BoundBinaryOperator{ enum class BoundBinaryOperation{
Addition, Addition,
Subtraction, Subtraction,
Multiplication, Multiplication,
@ -13,4 +13,10 @@ enum class BoundBinaryOperator{
Concatenation Concatenation
}; };
enum class BoundUnaryOperation{
Identity,
Negation,
LogicalNegation,
};
#endif //PORYGONLANG_BOUNDOPERATORS_HPP #endif //PORYGONLANG_BOUNDOPERATORS_HPP

View File

@ -5,6 +5,9 @@
enum class DiagnosticCode{ enum class DiagnosticCode{
UnexpectedCharacter, UnexpectedCharacter,
UnexpectedToken, UnexpectedToken,
NoBinaryOperationFound,
NoUnaryOperationFound,
}; };
#endif //PORYGONLANG_DIAGNOSTICCODE_HPP #endif //PORYGONLANG_DIAGNOSTICCODE_HPP