Rework of variable scope to reduce load on evaluator

This commit is contained in:
Deukhoofd 2019-06-13 15:16:41 +02:00
parent 0339c44a89
commit 813ab1e90b
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
9 changed files with 65 additions and 91 deletions

View File

@ -202,7 +202,7 @@ BoundExpression* Binder::BindVariableExpression(VariableExpression* expression){
} }
auto var = this->_scope->GetVariable(scope, key.GetHash()); auto var = this->_scope->GetVariable(scope, key.GetHash());
auto type = var->GetType(); auto type = var->GetType();
return new BoundVariableExpression(scope, key.GetHash(), type, expression->GetStartPosition(), expression->GetLength()); return new BoundVariableExpression(new BoundVariableKey(key.GetHash(), scope, false), type, expression->GetStartPosition(), expression->GetLength());
} }
BoundExpression* Binder::BindBinaryOperator(BinaryExpression* expression){ BoundExpression* Binder::BindBinaryOperator(BinaryExpression* expression){

View File

@ -134,13 +134,11 @@ public:
}; };
class BoundVariableExpression : public BoundExpression{ class BoundVariableExpression : public BoundExpression{
int _scope; BoundVariableKey* _key;
int _id;
public: public:
BoundVariableExpression(int scope, int id, shared_ptr<ScriptType> type, unsigned int start, unsigned int length) BoundVariableExpression(BoundVariableKey* key, shared_ptr<ScriptType> type, unsigned int start, unsigned int length)
: BoundExpression(start, length, std::move(type)){ : BoundExpression(start, length, std::move(type)){
_scope = scope; _key = key;
_id = id;
} }
~BoundVariableExpression() override = default; ~BoundVariableExpression() override = default;
@ -149,12 +147,8 @@ public:
return BoundExpressionKind ::Variable; return BoundExpressionKind ::Variable;
} }
int GetScope(){ BoundVariableKey* GetKey(){
return _scope; return _key;
}
int GetId(){
return _id;
} }
}; };

View File

@ -7,6 +7,7 @@ BoundScope::BoundScope(unordered_map<int, BoundVariable *> *tableScope) {
_tableScope = tableScope; _tableScope = tableScope;
_currentScope = 1; _currentScope = 1;
_deepestScope = 1; _deepestScope = 1;
_lastCreatedScope = 1;
auto localUpmostScope = new unordered_map<int, BoundVariable*>(); auto localUpmostScope = new unordered_map<int, BoundVariable*>();
_localScope.push_back(localUpmostScope); _localScope.push_back(localUpmostScope);
} }
@ -21,14 +22,16 @@ BoundScope::~BoundScope() {
} }
void BoundScope::GoInnerScope() { void BoundScope::GoInnerScope() {
_currentScope++; _lastCreatedScope++;
_currentScope = _lastCreatedScope;
if (_localScope.size() < _currentScope){ if (_localScope.size() < _currentScope){
auto innerScope = new unordered_map<int, BoundVariable*>(); auto innerScope = new unordered_map<int, BoundVariable*>();
_localScope.push_back(innerScope); _localScope.push_back(innerScope);
} }
/*
if (_deepestScope < _currentScope){ if (_deepestScope < _currentScope){
_deepestScope = _currentScope; _deepestScope = _currentScope;
} }*/
} }
void BoundScope::GoOuterScope() { void BoundScope::GoOuterScope() {

View File

@ -17,6 +17,7 @@ class BoundScope {
unordered_map<int, BoundVariable*>* _tableScope; unordered_map<int, BoundVariable*>* _tableScope;
vector<unordered_map<int, BoundVariable*>*> _localScope; vector<unordered_map<int, BoundVariable*>*> _localScope;
int _currentScope; int _currentScope;
int _lastCreatedScope;
int _deepestScope; int _deepestScope;
public: public:
explicit BoundScope(unordered_map<int, BoundVariable*> *tableScope); explicit BoundScope(unordered_map<int, BoundVariable*> *tableScope);

View File

@ -10,13 +10,23 @@ class BoundVariableKey{
int _identifier; int _identifier;
unsigned int _scopeId; unsigned int _scopeId;
bool _isCreation; bool _isCreation;
u_int64_t _hash;
static u_int64_t KnuthsHash(int i1, int i2)
{
u_int64_t ret = i1;
ret *= 2654435761U;
return ret ^ i2;
}
public: public:
BoundVariableKey(int id, unsigned int scope, bool creation){ BoundVariableKey(int id, unsigned int scope, bool creation){
_identifier = std::move(id); _identifier = id;
_scopeId = scope; _scopeId = scope;
_hash = KnuthsHash(scope, id);
_isCreation = creation; _isCreation = creation;
} }
int GetIdentifier(){ int GetIdentifier(){
return _identifier; return _identifier;
} }
@ -28,6 +38,10 @@ public:
bool IsCreation(){ bool IsCreation(){
return _isCreation; return _isCreation;
} }
u_int64_t GetHash(){
return _hash;
}
}; };
#endif //PORYGONLANG_BOUNDVARIABLEKEY_HPP #endif //PORYGONLANG_BOUNDVARIABLEKEY_HPP

View File

@ -1,15 +1,17 @@
#ifndef PORYGONLANG_EVALUATIONEXCEPTION_HPP #ifndef PORYGONLANG_EVALUATIONEXCEPTION_HPP
#define PORYGONLANG_EVALUATIONEXCEPTION_HPP #define PORYGONLANG_EVALUATIONEXCEPTION_HPP
#include <utility>
#include <exception> #include <exception>
#include <string> #include <string>
using namespace std; using namespace std;
class EvaluationException : std::exception { class EvaluationException : public std::exception {
string _message; string _message;
public: public:
explicit EvaluationException(string message){ explicit EvaluationException(string message){
_message = message; _message = std::move(message);
} }
const string defaultErrorText = "An evaluation exception occurred: "; const string defaultErrorText = "An evaluation exception occurred: ";

View File

@ -4,60 +4,32 @@
EvaluationScope::EvaluationScope(unordered_map<size_t, shared_ptr<EvalValue>> *scriptVariables, int deepestScope) { EvaluationScope::EvaluationScope(unordered_map<size_t, shared_ptr<EvalValue>> *scriptVariables, int deepestScope) {
_scriptScope = scriptVariables; _scriptScope = scriptVariables;
_localScope = vector<shared_ptr<unordered_map<int, shared_ptr<EvalValue>>>>(deepestScope); _localScope = unordered_map<u_int64_t, shared_ptr<EvalValue>>(deepestScope);
for (int i = 0; i < deepestScope; i++){
_localScope[i] = make_shared<unordered_map<int, shared_ptr<EvalValue>>>();
}
_currentScope = -1;
} }
void EvaluationScope::CreateVariable(int scope, int id, const shared_ptr<EvalValue>& value) { void EvaluationScope::CreateVariable(BoundVariableKey* key, const shared_ptr<EvalValue> &value) {
if (scope == 0){ if (key->GetScopeId() == 0){
_scriptScope->at(id) = value; _scriptScope -> at(key->GetIdentifier()) = value;
} else{ } else{
auto insert = _localScope[scope - 1]->insert({id, value}); auto insert = _localScope.insert({key->GetHash(), value});
if (!insert.second){ if (!insert.second){
_localScope[scope - 1]->at(id) = value; _localScope[key->GetHash()] = value;
} }
} }
} }
void EvaluationScope::SetVariable(int scope, int id, const shared_ptr<EvalValue>& value) { void EvaluationScope::SetVariable(BoundVariableKey* key, const shared_ptr<EvalValue> &value) {
if (scope == 0){ if (key->GetScopeId() == 0){
_scriptScope->at(id) = value; _scriptScope -> at(key->GetIdentifier()) = value;
} else{ } else{
_localScope[scope - 1]->at(id) = value; _localScope[key->GetHash()] = value;
} }
} }
shared_ptr<EvalValue> EvaluationScope::GetVariable(int scope, int id) { shared_ptr<EvalValue> EvaluationScope::GetVariable(BoundVariableKey* key) {
if (scope == 0){ if (key->GetScopeId() == 0){
return _scriptScope->at(id); return _scriptScope -> at(key->GetIdentifier());
} else{
return _localScope[key->GetHash()];
} }
return _localScope[scope - 1]->at(id); }
}
EvaluationScope* EvaluationScope::CreateBranchingScope(int scopeIndex){
auto scope = new EvaluationScope(this -> _scriptScope, this -> _localScope.size());
for (int i = 0; i <= scopeIndex; i++){
scope->_localScope[i] = this->_localScope[i];
}
for (int i = scopeIndex + 1; i < _localScope.size(); i++){
scope->_localScope[i] = make_shared<unordered_map<int, shared_ptr<EvalValue>>>();
}
scope->_currentScope = this -> _currentScope;
return scope;
}
void EvaluationScope::OuterScope() {
_currentScope++;
}
void EvaluationScope::InnerScope(bool clearScope) {
if (clearScope){
auto scope = this->_localScope[_currentScope];
scope->clear();
}
_currentScope--;
}

View File

@ -8,24 +8,14 @@
class EvaluationScope { class EvaluationScope {
unordered_map<size_t, shared_ptr<EvalValue>>* _scriptScope; unordered_map<size_t, shared_ptr<EvalValue>>* _scriptScope;
vector<shared_ptr<unordered_map<int, shared_ptr<EvalValue>>>> _localScope; unordered_map<u_int64_t, shared_ptr<EvalValue>> _localScope;
int _currentScope;
public: public:
explicit EvaluationScope(unordered_map<size_t, shared_ptr<EvalValue>>* scriptVariables, int deepestScope); explicit EvaluationScope(unordered_map<size_t, shared_ptr<EvalValue>>* scriptVariables, int deepestScope);
~EvaluationScope() = default; ~EvaluationScope() = default;
void CreateVariable(int scope, int id, const shared_ptr<EvalValue>& value); void CreateVariable(BoundVariableKey* key, const shared_ptr<EvalValue>& value);
void SetVariable(int scope, int id, const shared_ptr<EvalValue>& value); void SetVariable(BoundVariableKey* key, const shared_ptr<EvalValue>& value);
void OuterScope(); shared_ptr<EvalValue> GetVariable(BoundVariableKey* key);
void InnerScope(bool clearScope = true);
shared_ptr<EvalValue> GetVariable(int scope, int id);
EvaluationScope* CreateBranchingScope(int scopeIndex);
int GetCurrentScope(){
return _currentScope;
}
}; };

View File

@ -35,13 +35,11 @@ void Evaluator::EvaluateStatement(BoundStatement *statement) {
} }
void Evaluator::EvaluateBlockStatement(BoundBlockStatement* statement, bool clearScope) { void Evaluator::EvaluateBlockStatement(BoundBlockStatement* statement, bool clearScope) {
this->_evaluationScope->OuterScope();
for (auto s: statement->GetStatements()){ for (auto s: statement->GetStatements()){
this -> EvaluateStatement(s); this -> EvaluateStatement(s);
if (this->_hasReturned) if (this->_hasReturned)
break; break;
} }
this->_evaluationScope->InnerScope(clearScope);
} }
void Evaluator::EvaluateExpressionStatement(BoundExpressionStatement *statement) { void Evaluator::EvaluateExpressionStatement(BoundExpressionStatement *statement) {
@ -53,9 +51,9 @@ void Evaluator::EvaluateAssignmentStatement(BoundAssignmentStatement *statement)
auto value = this -> EvaluateExpression(statement->GetExpression()); auto value = this -> EvaluateExpression(statement->GetExpression());
auto key = statement->GetKey(); auto key = statement->GetKey();
if (key->IsCreation()){ if (key->IsCreation()){
this->_evaluationScope->CreateVariable(key->GetScopeId(), key->GetIdentifier(), value); this->_evaluationScope->CreateVariable(key, value);
} else{ } else{
this->_evaluationScope->SetVariable(key->GetScopeId(), key->GetIdentifier(), value); this->_evaluationScope->SetVariable(key, value);
} }
} }
@ -63,12 +61,11 @@ void Evaluator::EvaluateFunctionDeclarationStatement(BoundFunctionDeclarationSta
auto type = statement->GetType(); auto type = statement->GetType();
auto key = statement->GetKey(); auto key = statement->GetKey();
auto block = statement->GetBlock(); auto block = statement->GetBlock();
auto evaluator = shared_ptr<EvaluationScope>(this->_evaluationScope->CreateBranchingScope(this->_evaluationScope->GetCurrentScope() + 1)); auto value = make_shared<ScriptFunctionEvalValue>(block, this->_evaluationScope, type);
auto value = make_shared<ScriptFunctionEvalValue>(block, evaluator, type);
if (key->IsCreation()){ if (key->IsCreation()){
this->_evaluationScope->CreateVariable(key->GetScopeId(), key->GetIdentifier(), value); this->_evaluationScope->CreateVariable(key, value);
} else{ } else{
this->_evaluationScope->SetVariable(key->GetScopeId(), key->GetIdentifier(), value); this->_evaluationScope->SetVariable(key, value);
} }
} }
@ -109,7 +106,10 @@ shared_ptr<EvalValue> Evaluator::EvaluateExpression(BoundExpression *expression)
} }
shared_ptr<EvalValue> Evaluator::GetVariable(BoundVariableExpression* expression){ shared_ptr<EvalValue> Evaluator::GetVariable(BoundVariableExpression* expression){
auto variable = this->_evaluationScope->GetVariable(expression->GetScope(), expression->GetId()); auto variable = this->_evaluationScope->GetVariable(expression->GetKey());
if (variable == nullptr){
throw EvaluationException("Variable not found");
}
return variable->Clone(); return variable->Clone();
} }
@ -218,9 +218,8 @@ shared_ptr<EvalValue> Evaluator::EvaluateFunctionCallExpression(BoundExpression*
auto type = std::dynamic_pointer_cast<FunctionScriptType>(function->GetType()); auto type = std::dynamic_pointer_cast<FunctionScriptType>(function->GetType());
auto parameterTypes = type->GetParameterTypes(); auto parameterTypes = type->GetParameterTypes();
auto parameterKeys = type->GetParameterKeys(); auto parameterKeys = type->GetParameterKeys();
auto scope = type -> GetScopeIndex();
auto originalScope = this->_evaluationScope; auto originalScope = this->_evaluationScope;
this->_evaluationScope = shared_ptr<EvaluationScope>(function -> GetScope() -> CreateBranchingScope(scope)); this->_evaluationScope = function->GetScope();
for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++){ for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++){
auto parameter = parameters[i]; auto parameter = parameters[i];
@ -229,11 +228,11 @@ shared_ptr<EvalValue> Evaluator::EvaluateFunctionCallExpression(BoundExpression*
throw EvaluationException("Passed wrong type to function."); throw EvaluationException("Passed wrong type to function.");
} }
auto key = parameterKeys.at(i); auto key = parameterKeys.at(i);
this->_evaluationScope->CreateVariable(key->GetScopeId(), key->GetIdentifier(), parameter->Clone()); this->_evaluationScope->CreateVariable(key.get(), parameter->Clone());
} }
this->EvaluateBlockStatement(function->GetInnerBlock().get(), true); this->EvaluateBlockStatement(function->GetInnerBlock().get(), true);
this->_evaluationScope = originalScope; this->_evaluationScope = originalScope;
this->_hasReturned = false; this->_hasReturned = false;
auto r = this -> _returnValue; auto r = this -> _returnValue;
this -> _returnValue = nullptr; this -> _returnValue = nullptr;
@ -245,9 +244,8 @@ shared_ptr<EvalValue> Evaluator::EvaluateFunction(ScriptFunctionEvalValue *funct
auto parameterTypes = type->GetParameterTypes(); auto parameterTypes = type->GetParameterTypes();
auto parameterKeys = type->GetParameterKeys(); auto parameterKeys = type->GetParameterKeys();
auto scope = type -> GetScopeIndex();
auto originalScope = this->_evaluationScope; auto originalScope = this->_evaluationScope;
this->_evaluationScope = shared_ptr<EvaluationScope>(function -> GetScope() -> CreateBranchingScope(scope)); this->_evaluationScope = function->GetScope();
for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++){ for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++){
auto parameter = parameters[i]; auto parameter = parameters[i];
@ -256,7 +254,7 @@ shared_ptr<EvalValue> Evaluator::EvaluateFunction(ScriptFunctionEvalValue *funct
throw EvaluationException("Passed wrong type to function."); throw EvaluationException("Passed wrong type to function.");
} }
auto key = parameterKeys.at(i); auto key = parameterKeys.at(i);
this->_evaluationScope->CreateVariable(key->GetScopeId(), key->GetIdentifier(), parameter->Clone()); this->_evaluationScope->CreateVariable(key.get(), parameter->Clone());
} }
this->EvaluateBlockStatement(function->GetInnerBlock().get(), true); this->EvaluateBlockStatement(function->GetInnerBlock().get(), true);
this->_evaluationScope = originalScope; this->_evaluationScope = originalScope;