#include #include "Binder.hpp" #include "../TableScriptType.hpp" #include "BoundExpressions/BoundTableExpression.hpp" #include "../UserData/UserDataScriptType.hpp" #include BoundScriptStatement *Binder::Bind(Script* script, const ParsedScriptStatement *s, BoundScope* scriptScope) { auto binder = Binder(); binder._scriptData = script; binder._scope = scriptScope; auto statements = s->GetStatements(); vector boundStatements (statements->size()); for (int i = 0; i < statements->size(); i++){ boundStatements[i] = binder.BindStatement(statements->at(i)); } return new BoundScriptStatement(boundStatements, scriptScope->GetLocalVariableCount()); } Binder::~Binder() { delete _scope; } BoundStatement* Binder::BindStatement(const 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); case ParsedStatementKind::Assignment: return this -> BindAssignmentStatement(statement); case ParsedStatementKind::IndexAssignment: return this -> BindIndexAssignmentStatement(statement); case ParsedStatementKind ::FunctionDeclaration: return this->BindFunctionDeclarationStatement(statement); case ParsedStatementKind::Return: return this -> BindReturnStatement(statement); case ParsedStatementKind::Conditional: return this -> BindConditionalStatement(statement); case ParsedStatementKind::Bad: return new BoundBadStatement(); } } BoundStatement *Binder::BindBlockStatement(const ParsedStatement *statement) { auto statements = ((ParsedBlockStatement*)statement)->GetStatements(); vector boundStatements (statements->size()); this->_scope->GoInnerScope(); for (int i = 0; i < statements->size(); i++){ boundStatements[i] = this -> BindStatement(statements->at(i)); } this->_scope->GoOuterScope(); return new BoundBlockStatement(boundStatements); } BoundStatement *Binder::BindExpressionStatement(const ParsedStatement *statement) { auto exp = ((ParsedExpressionStatement*)statement)->GetExpression(); return new BoundExpressionStatement(this -> BindExpression(exp)); } BoundStatement* Binder::BindAssignmentStatement(const ParsedStatement *statement){ auto s = (ParsedAssignmentStatement*) statement; auto boundExpression = this->BindExpression(s->GetExpression()); VariableAssignment assignment = s->IsLocal() ? this->_scope->CreateExplicitLocal(s->GetIdentifier().GetHash(), boundExpression->GetType()) : this->_scope->AssignVariable(s->GetIdentifier().GetHash(), boundExpression->GetType()); if (assignment.GetResult() == VariableAssignmentResult::Ok){ auto key = assignment.GetKey(); return new BoundAssignmentStatement(key, boundExpression); } else{ this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::CantAssignVariable, statement->GetStartPosition(), statement->GetLength()); return new BoundBadStatement(); } } BoundStatement *Binder::BindIndexAssignmentStatement(const ParsedStatement *statement) { auto s = (ParsedIndexAssignmentStatement*) statement; auto indexExp = s -> GetIndexExpression(); const BoundExpression* indexable; if (indexExp->GetKind() == ParsedExpressionKind::Indexer){ indexable = this -> BindIndexExpression((IndexExpression*)indexExp, true); } else{ indexable = this -> BindPeriodIndexExpression((PeriodIndexExpression*)indexExp, true); } auto valueExpression = this -> BindExpression(s->GetValueExpression()); auto boundIndexType = indexable -> GetType(); if (boundIndexType ->GetClass() != TypeClass ::Error && boundIndexType->operator!=(valueExpression->GetType().get())){ this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidTableValueType, statement->GetStartPosition(), statement->GetLength()); return new BoundBadStatement(); } return new BoundIndexAssignmentStatement(indexable, valueExpression); } std::shared_ptr ParseTypeIdentifier(HashedString s){ auto hash = s.GetHash(); switch (hash){ case HashedString::ConstHash("number"): return std::make_shared(false, false); case HashedString::ConstHash("bool"): return std::make_shared(TypeClass::Bool); case HashedString::ConstHash("string"): return std::make_shared(false, 0); default: if (!UserDataStorage::HasUserDataType(hash)){ return nullptr; } return std::make_shared(hash); } } BoundStatement *Binder::BindFunctionDeclarationStatement(const ParsedStatement *statement) { auto functionStatement = (ParsedFunctionDeclarationStatement*) statement; auto parameters = functionStatement->GetParameters(); auto parameterTypes = vector>(parameters->size()); auto parameterKeys = vector>(parameters->size()); auto scopeIndex = this->_scope->GetCurrentScope(); this->_scope->GoInnerScope(); for (int i = 0; i < parameters->size(); i++){ auto var = parameters -> at(i); auto parsedType = ParseTypeIdentifier(var->GetType()); if (parsedType == nullptr){ this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidTypeName, statement->GetStartPosition(), statement->GetLength()); return new BoundBadStatement(); } parameterTypes.at(i) = parsedType; auto parameterAssignment = this->_scope->CreateExplicitLocal(var->GetIdentifier().GetHash(), parsedType); if (parameterAssignment.GetResult() == VariableAssignmentResult::Ok){ parameterKeys.at(i) = std::shared_ptr(parameterAssignment.GetKey()); } else{ //TODO: log error continue; } } auto identifier = functionStatement->GetIdentifier(); auto returnType = make_shared(TypeClass::Nil); auto type = make_shared(returnType, parameterTypes, parameterKeys, scopeIndex); this->_currentFunction = type; auto assignment = this->_scope->AssignVariable(identifier.GetHash(), type); if (assignment.GetResult() != VariableAssignmentResult::Ok){ this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::CantAssignVariable, statement->GetStartPosition(), statement->GetLength()); return new BoundBadStatement(); } auto boundBlock = this -> BindBlockStatement(functionStatement->GetBlock()); this->_scope->GoOuterScope(); this->_currentFunction = nullptr; return new BoundFunctionDeclarationStatement(type, assignment.GetKey(), (BoundBlockStatement*)boundBlock); } BoundStatement *Binder::BindReturnStatement(const ParsedStatement* statement){ auto expression = ((ParsedReturnStatement*)statement)->GetExpression(); shared_ptr currentReturnType; if (this->_currentFunction == nullptr){ currentReturnType = this->_scriptData->GetReturnType(); } else{ currentReturnType = this->_currentFunction->GetReturnType(); } if (expression == nullptr && currentReturnType != nullptr){ this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidReturnType, statement->GetStartPosition(), statement->GetLength()); return new BoundBadStatement(); } auto boundExpression = this->BindExpression(expression); auto expresionType = boundExpression->GetType(); if (currentReturnType == nullptr || currentReturnType->GetClass() == TypeClass::Nil){ if (this->_currentFunction == nullptr){ this->_scriptData->SetReturnType(expresionType); } else{ this->_currentFunction->SetReturnType(expresionType); } return new BoundReturnStatement(boundExpression); } if (currentReturnType.get()->operator!=(expresionType.get())){ this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidReturnType, statement->GetStartPosition(), statement->GetLength()); return new BoundBadStatement(); } return new BoundReturnStatement(boundExpression); } BoundStatement *Binder::BindConditionalStatement(const ParsedStatement* statement) { auto conditionalStatement = (ParsedConditionalStatement*)statement; auto boundCondition = this -> BindExpression(conditionalStatement -> GetCondition()); if (boundCondition->GetType() -> GetClass() != TypeClass::Bool){ this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::ConditionNotABool, statement->GetStartPosition(), statement->GetLength()); return new BoundBadStatement(); } auto boundBlock = this -> BindStatement(conditionalStatement->GetBlock()); BoundStatement* elseStatement = nullptr; if (conditionalStatement->GetElseStatement() != nullptr){ elseStatement = this -> BindStatement(conditionalStatement->GetElseStatement()); } return new BoundConditionalStatement(boundCondition, boundBlock, elseStatement); } BoundExpression* Binder::BindExpression(const 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 ::LiteralString: return new BoundLiteralStringExpression(((LiteralStringExpression*)expression)->GetValue(), expression->GetStartPosition(), expression->GetLength()); case ParsedExpressionKind ::LiteralBool: return new BoundLiteralBoolExpression(((LiteralBoolExpression*)expression)->GetValue(), expression->GetStartPosition(), expression->GetLength()); case ParsedExpressionKind ::Variable: return this -> BindVariableExpression((VariableExpression*)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()); case ParsedExpressionKind ::FunctionCall: return this->BindFunctionCall((FunctionCallExpression*)expression); case ParsedExpressionKind ::Indexer: return this->BindIndexExpression((IndexExpression*)expression, false); case ParsedExpressionKind::PeriodIndexer: return this -> BindPeriodIndexExpression((PeriodIndexExpression*)expression, false); case ParsedExpressionKind::NumericalTable: return this -> BindNumericalTableExpression((ParsedNumericalTableExpression*)expression); case ParsedExpressionKind ::Table: return this -> BindTableExpression((ParsedTableExpression*)expression); case ParsedExpressionKind ::Bad: return new BoundBadExpression(expression->GetStartPosition(), expression-> GetLength()); } } BoundExpression* Binder::BindVariableExpression(const VariableExpression* expression){ auto key = expression->GetValue(); auto scope = this->_scope->Exists(key.GetHash()); if (scope == -1){ this -> _scriptData -> Diagnostics->LogError(DiagnosticCode::VariableNotFound, expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); } auto var = this->_scope->GetVariable(scope, key.GetHash()); auto type = var->GetType(); return new BoundVariableExpression(new BoundVariableKey(key.GetHash(), scope, false), type, expression->GetStartPosition(), expression->GetLength()); } BoundExpression* Binder::BindBinaryOperator(const 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 = std::dynamic_pointer_cast(boundLeftType); auto rightNumeric = std::dynamic_pointer_cast(boundRightType); if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Addition, std::make_shared(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()), expression->GetStartPosition(), expression->GetLength()); } else{ return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Addition, std::make_shared(false, false), expression->GetStartPosition(), expression->GetLength()); } } else if (boundLeftType->GetClass() == TypeClass::String){ return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Concatenation, std::make_shared(false, 0), expression->GetStartPosition(), expression->GetLength()); } break; case BinaryOperatorKind ::Subtraction: if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number){ auto leftNumeric = std::dynamic_pointer_cast(boundLeftType); auto rightNumeric = std::dynamic_pointer_cast(boundRightType); if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Subtraction, std::make_shared(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()), expression->GetStartPosition(), expression->GetLength()); } else{ return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Subtraction, std::make_shared(false, false), expression->GetStartPosition(), expression->GetLength()); } } break; case BinaryOperatorKind ::Multiplication: if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number){ auto leftNumeric = std::dynamic_pointer_cast(boundLeftType); auto rightNumeric = std::dynamic_pointer_cast(boundRightType); if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Multiplication, std::make_shared(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()), expression->GetStartPosition(), expression->GetLength()); } else{ return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Multiplication, std::make_shared(false, false), expression->GetStartPosition(), expression->GetLength()); } } break; case BinaryOperatorKind ::Division: if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number){ auto leftNumeric = std::dynamic_pointer_cast(boundLeftType); auto rightNumeric = std::dynamic_pointer_cast(boundRightType); if (leftNumeric->IsAwareOfFloat() && rightNumeric->IsAwareOfFloat()){ return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Division, std::make_shared(true, leftNumeric->IsFloat() || rightNumeric->IsFloat()), expression->GetStartPosition(), expression->GetLength()); } else{ return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Division, std::make_shared(false, false), expression->GetStartPosition(), expression->GetLength()); } } break; case BinaryOperatorKind ::Equality: return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Equality, std::make_shared(TypeClass::Bool), expression->GetStartPosition(), expression->GetLength()); case BinaryOperatorKind ::Inequality: return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Inequality, std::make_shared(TypeClass::Bool), expression->GetStartPosition(), expression->GetLength()); case BinaryOperatorKind ::Less: if (boundLeft->GetType()->GetClass() == TypeClass::Number && boundRight->GetType()->GetClass() == TypeClass::Number){ return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LessThan, std::make_shared(TypeClass::Bool), expression->GetStartPosition(), expression->GetLength()); } case BinaryOperatorKind ::LessOrEquals: if (boundLeft->GetType()->GetClass() == TypeClass::Number && boundRight->GetType()->GetClass() == TypeClass::Number){ return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LessThanEquals, std::make_shared(TypeClass::Bool), expression->GetStartPosition(), expression->GetLength()); } case BinaryOperatorKind ::Greater: if (boundLeft->GetType()->GetClass() == TypeClass::Number && boundRight->GetType()->GetClass() == TypeClass::Number){ return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::GreaterThan, std::make_shared(TypeClass::Bool), expression->GetStartPosition(), expression->GetLength()); } case BinaryOperatorKind ::GreaterOrEquals: if (boundLeft->GetType()->GetClass() == TypeClass::Number && boundRight->GetType()->GetClass() == TypeClass::Number){ return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::GreaterThanEquals, std::make_shared(TypeClass::Bool), expression->GetStartPosition(), expression->GetLength()); } case BinaryOperatorKind ::LogicalAnd: if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool) return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LogicalAnd, std::make_shared(TypeClass::Bool), expression->GetStartPosition(), expression->GetLength()); break; case BinaryOperatorKind ::LogicalOr: if (boundLeftType->GetClass() == TypeClass::Bool && boundRightType->GetClass() == TypeClass::Bool) return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::LogicalOr, std::make_shared(TypeClass::Bool), expression->GetStartPosition(), expression->GetLength()); break; } this -> _scriptData -> Diagnostics->LogError(DiagnosticCode::NoBinaryOperationFound, expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); } BoundExpression* Binder::BindUnaryOperator(const 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 = std::dynamic_pointer_cast(operandType); return new BoundUnaryExpression(operand, BoundUnaryOperation::Negation, std::make_shared(innerType.get()->IsAwareOfFloat(), innerType.get()->IsFloat()), expression->GetStartPosition(), expression->GetLength()); } break; case UnaryOperatorKind ::LogicalNegation: if (operandType->GetClass() == TypeClass::Bool){ return new BoundUnaryExpression(operand, BoundUnaryOperation::LogicalNegation, std::make_shared(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()); } BoundExpression* Binder::BindFunctionCall(const FunctionCallExpression* expression){ auto functionExpression = BindExpression(expression->GetFunction()); auto type = functionExpression->GetType(); if (type->GetClass() != TypeClass::Function){ this->_scriptData->Diagnostics->LogError(DiagnosticCode::ExpressionIsNotAFunction, expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); } auto functionType = std::dynamic_pointer_cast(type); auto parameterTypes = functionType->GetParameterTypes(); auto givenParameters = expression->GetParameters(); if (parameterTypes.size() != givenParameters->size()){ this->_scriptData->Diagnostics->LogError(DiagnosticCode::ParameterCountMismatch, expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); } vector boundParameters = vector(givenParameters->size()); for (int i = 0; i < givenParameters->size(); i++){ auto parameter = givenParameters -> at(i); auto boundParameter = this -> BindExpression(parameter); if (boundParameter->GetType().get()->operator!=(parameterTypes.at(i).get())){ this->_scriptData->Diagnostics->LogError(DiagnosticCode::ParameterTypeMismatch, parameter->GetStartPosition(), parameter->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); } boundParameters[i] = boundParameter; } return new BoundFunctionCallExpression(functionExpression, boundParameters, functionType.get()->GetReturnType(), expression->GetStartPosition(), expression->GetLength()); } BoundExpression *Binder::BindIndexExpression(const IndexExpression *expression, bool setter) { auto indexer = this->BindExpression(expression->GetIndexer()); auto index = this->BindExpression(expression->GetIndex()); auto indexerType = indexer -> GetType(); if (!indexerType->CanBeIndexedWith(index->GetType().get())){ this->_scriptData->Diagnostics->LogError(DiagnosticCode::CantIndex, index->GetStartPosition(), index->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); } if (indexerType -> GetClass() == TypeClass::UserData){ auto stringKey = dynamic_pointer_cast(index -> GetType()); auto field = dynamic_pointer_cast(indexerType) -> GetField(stringKey->GetHashValue()); if (!setter){ if (!field->HasGetter()){ this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoGetter, index->GetStartPosition(), index->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); } } else{ if (!field->HasSetter()){ this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoSetter, index->GetStartPosition(), index->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); } } } auto resultType = indexer->GetType()->GetIndexedType(index->GetType().get()); return new BoundIndexExpression(indexer, index, resultType, expression->GetStartPosition(), expression->GetLength()); } BoundExpression* Binder::BindPeriodIndexExpression(const PeriodIndexExpression* expression, bool setter){ auto indexer = this->BindExpression(expression->GetIndexer()); const auto& identifier = expression->GetIndex(); const auto& indexerType = indexer -> GetType(); if (!indexerType -> CanBeIndexedWithIdentifier(identifier.GetHash())){ this->_scriptData->Diagnostics->LogError(DiagnosticCode::CantIndex, expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); } if (indexerType -> GetClass() == TypeClass::UserData){ auto field = dynamic_pointer_cast(indexerType) -> GetField(identifier . GetHash()); if (!setter){ if (!field->HasGetter()){ this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoGetter, expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); } } else{ if (!field->HasSetter()){ this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoSetter, expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); } } } auto resultType = indexer->GetType()->GetIndexedType(identifier . GetHash()); return new BoundPeriodIndexExpression(indexer, identifier, resultType, expression->GetStartPosition(), expression->GetLength()); } BoundExpression* Binder::BindNumericalTableExpression(const ParsedNumericalTableExpression* expression){ auto expressions = expression->GetExpressions(); auto boundExpressions = vector(expressions-> size()); shared_ptr valueType = nullptr; if (!boundExpressions.empty()){ boundExpressions[0] = this -> BindExpression(expressions -> at(0)); valueType = boundExpressions[0] -> GetType(); for (int i = 1; i < expressions->size(); i++){ boundExpressions[i] = this -> BindExpression(expressions -> at(i)); if (boundExpressions[i] -> GetType().get()->operator!=(valueType.get())){ this->_scriptData->Diagnostics->LogError(DiagnosticCode::InvalidTableValueType, boundExpressions[i]->GetStartPosition(), boundExpressions[i]->GetLength()); } } } if (valueType == nullptr){ valueType = std::make_shared(TypeClass::Nil); } auto tableType = std::make_shared(valueType); return new BoundNumericalTableExpression(boundExpressions, tableType, expression->GetStartPosition(), expression->GetLength()); } BoundExpression *Binder::BindTableExpression(const ParsedTableExpression *expression) { auto tableScope = new unordered_map(); auto innerScope = new BoundScope(tableScope); auto currentScope = this -> _scope; this -> _scope = innerScope; auto block = this -> BindBlockStatement(expression -> GetBlock()); this -> _scope = currentScope; auto tableType = std::make_shared(tableScope, innerScope->GetLocalVariableCount()); delete innerScope; return new BoundTableExpression((BoundBlockStatement*)block, tableType, expression->GetStartPosition(), expression->GetLength()); }