2019-05-21 16:09:08 +00:00
|
|
|
|
|
|
|
#include "Binder.hpp"
|
|
|
|
|
2019-05-22 10:22:52 +00:00
|
|
|
BoundScriptStatement *Binder::Bind(Script* script, ParsedScriptStatement *s) {
|
2019-05-21 18:59:26 +00:00
|
|
|
auto binder = Binder();
|
2019-05-22 10:22:52 +00:00
|
|
|
binder.ScriptData = script;
|
2019-05-21 18:59:26 +00:00
|
|
|
auto statements = s->GetStatements();
|
|
|
|
vector<BoundStatement*> boundStatements (statements.size());
|
|
|
|
for (int i = 0; i < statements.size(); i++){
|
|
|
|
boundStatements[i] = binder.BindStatement(statements[i]);
|
|
|
|
}
|
|
|
|
return new BoundScriptStatement(boundStatements);
|
2019-05-21 16:09:08 +00:00
|
|
|
}
|
2019-05-21 18:59:26 +00:00
|
|
|
|
|
|
|
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<BoundStatement*> 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());
|
|
|
|
|
2019-05-21 20:15:51 +00:00
|
|
|
case ParsedExpressionKind ::Binary:
|
|
|
|
return this -> BindBinaryOperator((BinaryExpression*)expression);
|
2019-05-22 10:22:52 +00:00
|
|
|
case ParsedExpressionKind ::Unary:
|
|
|
|
return this -> BindUnaryOperator((UnaryExpression*)expression);
|
2019-05-21 20:15:51 +00:00
|
|
|
|
2019-05-21 19:00:56 +00:00
|
|
|
case ParsedExpressionKind ::Parenthesized:
|
|
|
|
return BindExpression(((ParenthesizedExpression*)expression)->GetInnerExpression());
|
|
|
|
|
2019-05-21 18:59:26 +00:00
|
|
|
case ParsedExpressionKind ::Bad:
|
|
|
|
return new BoundBadExpression(expression->GetStartPosition(), expression-> GetLength());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-21 20:15:51 +00:00
|
|
|
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,
|
2019-05-22 10:22:52 +00:00
|
|
|
BoundBinaryOperation::Addition, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()));
|
2019-05-21 20:15:51 +00:00
|
|
|
}
|
|
|
|
else{
|
2019-05-22 10:22:52 +00:00
|
|
|
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Addition, new NumericScriptType(false, false));
|
2019-05-21 20:15:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//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,
|
2019-05-22 10:22:52 +00:00
|
|
|
BoundBinaryOperation::Subtraction, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()));
|
2019-05-21 20:15:51 +00:00
|
|
|
}
|
|
|
|
else{
|
2019-05-22 10:22:52 +00:00
|
|
|
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Subtraction, new NumericScriptType(false, false));
|
2019-05-21 20:15:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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,
|
2019-05-22 10:22:52 +00:00
|
|
|
BoundBinaryOperation::Multiplication, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()));
|
2019-05-21 20:15:51 +00:00
|
|
|
}
|
|
|
|
else{
|
2019-05-22 10:22:52 +00:00
|
|
|
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Multiplication, new NumericScriptType(false, false));
|
2019-05-21 20:15:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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,
|
2019-05-22 10:22:52 +00:00
|
|
|
BoundBinaryOperation::Division, new NumericScriptType(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()));
|
2019-05-21 20:15:51 +00:00
|
|
|
}
|
|
|
|
else{
|
2019-05-22 10:22:52 +00:00
|
|
|
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Division, new NumericScriptType(false, false));
|
2019-05-21 20:15:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case BinaryOperatorKind ::Equality:
|
2019-05-22 10:22:52 +00:00
|
|
|
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Equality, new ScriptType(TypeClass::Bool));
|
2019-05-21 20:15:51 +00:00
|
|
|
case BinaryOperatorKind ::LogicalAnd:
|
|
|
|
if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool)
|
2019-05-22 10:22:52 +00:00
|
|
|
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LogicalAnd, new ScriptType(TypeClass::Bool));
|
2019-05-21 20:15:51 +00:00
|
|
|
break;
|
|
|
|
case BinaryOperatorKind ::LogicalOr:
|
|
|
|
if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool)
|
2019-05-22 10:22:52 +00:00
|
|
|
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LogicalOr, new ScriptType(TypeClass::Bool));
|
2019-05-21 20:15:51 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2019-05-22 10:22:52 +00:00
|
|
|
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());
|
|
|
|
|
2019-05-21 20:15:51 +00:00
|
|
|
}
|