#include "Binder.hpp" BoundScriptStatement *Binder::Bind(ParsedScriptStatement *s) { 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 ::Binary: return this -> BindBinaryOperator((BinaryExpression*)expression); case ParsedExpressionKind ::Parenthesized: return BindExpression(((ParenthesizedExpression*)expression)->GetInnerExpression()); case ParsedExpressionKind ::Bad: return new BoundBadExpression(expression->GetStartPosition(), expression-> GetLength()); } } 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()); }