#include "BoundScope.hpp" BoundScope::BoundScope(unordered_map *scriptScope) { _scriptScope = scriptScope; _currentScope = 1; _deepestScope = 1; auto localUpmostScope = new unordered_map(); _localScope.push_back(localUpmostScope); } BoundScope::~BoundScope() { for (auto scope : _localScope){ for (auto v : *scope){ delete v.second; } delete scope; } } void BoundScope::GoInnerScope() { _currentScope++; if (_localScope.size() < _currentScope){ auto innerScope = new unordered_map(); _localScope.push_back(innerScope); } if (_deepestScope < _currentScope){ _deepestScope = _currentScope; } } void BoundScope::GoOuterScope() { _localScope[_currentScope - 1]->clear(); _currentScope--; } int BoundScope::Exists(int key) { auto found = this -> _scriptScope -> find(key); if (found != _scriptScope -> end()){ return 0; } for (int i = _currentScope - 1; i >= 0; i--){ auto scope = _localScope.at(i); found = scope -> find(key); if (found != scope -> end()){ return i + 1; } } return -1; } BoundVariable *BoundScope::GetVariable(int scope, int identifier) { if (scope == 0){ auto find = this -> _scriptScope->find(identifier); if (find != _scriptScope->end()){ return find -> second; } return nullptr; } else{ auto s = this->_localScope.at(scope); auto find = s -> find(identifier); if (find != s -> end()){ return find -> second; } return nullptr; } } VariableAssignment BoundScope::CreateExplicitLocal(int identifier, const ScriptType& type) { auto scope = this->_localScope.at(this->_currentScope); if (scope -> find(identifier) != scope -> end()){ return VariableAssignment(VariableAssignmentResult::ExplicitLocalVariableExists, nullptr); } scope -> insert({identifier, new BoundVariable(type)}); return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, this->_currentScope, true)); } VariableAssignment BoundScope::AssignVariable(int identifier, const ScriptType& type) { int exists = this->Exists(identifier); if (exists == -1){ // Creation _scriptScope->insert({identifier, new BoundVariable(type)}); return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, 0, true)); } else{ // Assigning auto var = this->GetVariable(exists, identifier); if (var->GetType() != type){ return VariableAssignment(VariableAssignmentResult::VariableDefinedWithDifferentType, nullptr); } return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, exists, false)); } }