Implements assignment binding
This commit is contained in:
88
src/Binder/BoundVariables/BoundScope.hpp
Normal file
88
src/Binder/BoundVariables/BoundScope.hpp
Normal file
@@ -0,0 +1,88 @@
|
||||
|
||||
#ifndef PORYGONLANG_BOUNDSCOPE_HPP
|
||||
#define PORYGONLANG_BOUNDSCOPE_HPP
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "BoundVariable.hpp"
|
||||
#include "BoundVariableKey.hpp"
|
||||
#include "VariableAssigmentResult.hpp"
|
||||
#include "../../Utilities/HashedString.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class BoundScope {
|
||||
unordered_map<int, BoundVariable*>* _scriptScope;
|
||||
vector<unordered_map<int, BoundVariable*>> _localScope;
|
||||
int _currentScope;
|
||||
public:
|
||||
explicit BoundScope(unordered_map<int, BoundVariable*> *scriptScope){
|
||||
_scriptScope = scriptScope;
|
||||
_currentScope = 1;
|
||||
_localScope = vector<unordered_map<int, BoundVariable*>>(1);
|
||||
}
|
||||
~BoundScope(){
|
||||
_localScope.clear();
|
||||
}
|
||||
|
||||
int 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* 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 CreateExplicitLocal(HashedString& identifier, ScriptType* type){
|
||||
auto scope = this->_localScope.at(this->_currentScope);
|
||||
if (scope.find(identifier.GetHash()) != scope.end()){
|
||||
return VariableAssignment(VariableAssignmentResult::ExplicitLocalVariableExists, nullptr);
|
||||
}
|
||||
scope.insert({identifier.GetHash(), new BoundVariable(type)});
|
||||
return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier.GetHash(), this->_currentScope, true));
|
||||
}
|
||||
|
||||
VariableAssignment AssignVariable(int identifier, 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));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif //PORYGONLANG_BOUNDSCOPE_HPP
|
||||
Reference in New Issue
Block a user