From 813ab1e90b511e9ce3016aef96bec8e6d5c0b89f Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Thu, 13 Jun 2019 15:16:41 +0200 Subject: [PATCH] Rework of variable scope to reduce load on evaluator --- src/Binder/Binder.cpp | 2 +- .../BoundExpressions/BoundExpression.hpp | 16 ++--- src/Binder/BoundVariables/BoundScope.cpp | 7 ++- src/Binder/BoundVariables/BoundScope.hpp | 1 + .../BoundVariables/BoundVariableKey.hpp | 16 ++++- src/Evaluator/EvaluationException.hpp | 6 +- .../EvaluationScope/EvaluationScope.cpp | 60 +++++-------------- .../EvaluationScope/EvaluationScope.hpp | 18 ++---- src/Evaluator/Evaluator.cpp | 30 +++++----- 9 files changed, 65 insertions(+), 91 deletions(-) diff --git a/src/Binder/Binder.cpp b/src/Binder/Binder.cpp index 29ee625..7c72eea 100644 --- a/src/Binder/Binder.cpp +++ b/src/Binder/Binder.cpp @@ -202,7 +202,7 @@ BoundExpression* Binder::BindVariableExpression(VariableExpression* expression){ } auto var = this->_scope->GetVariable(scope, key.GetHash()); 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){ diff --git a/src/Binder/BoundExpressions/BoundExpression.hpp b/src/Binder/BoundExpressions/BoundExpression.hpp index 81ab63c..60967d9 100644 --- a/src/Binder/BoundExpressions/BoundExpression.hpp +++ b/src/Binder/BoundExpressions/BoundExpression.hpp @@ -134,13 +134,11 @@ public: }; class BoundVariableExpression : public BoundExpression{ - int _scope; - int _id; + BoundVariableKey* _key; public: - BoundVariableExpression(int scope, int id, shared_ptr type, unsigned int start, unsigned int length) + BoundVariableExpression(BoundVariableKey* key, shared_ptr type, unsigned int start, unsigned int length) : BoundExpression(start, length, std::move(type)){ - _scope = scope; - _id = id; + _key = key; } ~BoundVariableExpression() override = default; @@ -149,12 +147,8 @@ public: return BoundExpressionKind ::Variable; } - int GetScope(){ - return _scope; - } - - int GetId(){ - return _id; + BoundVariableKey* GetKey(){ + return _key; } }; diff --git a/src/Binder/BoundVariables/BoundScope.cpp b/src/Binder/BoundVariables/BoundScope.cpp index 311d6cf..155a632 100644 --- a/src/Binder/BoundVariables/BoundScope.cpp +++ b/src/Binder/BoundVariables/BoundScope.cpp @@ -7,6 +7,7 @@ BoundScope::BoundScope(unordered_map *tableScope) { _tableScope = tableScope; _currentScope = 1; _deepestScope = 1; + _lastCreatedScope = 1; auto localUpmostScope = new unordered_map(); _localScope.push_back(localUpmostScope); } @@ -21,14 +22,16 @@ BoundScope::~BoundScope() { } void BoundScope::GoInnerScope() { - _currentScope++; + _lastCreatedScope++; + _currentScope = _lastCreatedScope; if (_localScope.size() < _currentScope){ auto innerScope = new unordered_map(); _localScope.push_back(innerScope); } + /* if (_deepestScope < _currentScope){ _deepestScope = _currentScope; - } + }*/ } void BoundScope::GoOuterScope() { diff --git a/src/Binder/BoundVariables/BoundScope.hpp b/src/Binder/BoundVariables/BoundScope.hpp index bad447e..2388c19 100644 --- a/src/Binder/BoundVariables/BoundScope.hpp +++ b/src/Binder/BoundVariables/BoundScope.hpp @@ -17,6 +17,7 @@ class BoundScope { unordered_map* _tableScope; vector*> _localScope; int _currentScope; + int _lastCreatedScope; int _deepestScope; public: explicit BoundScope(unordered_map *tableScope); diff --git a/src/Binder/BoundVariables/BoundVariableKey.hpp b/src/Binder/BoundVariables/BoundVariableKey.hpp index 220476f..67edc2b 100644 --- a/src/Binder/BoundVariables/BoundVariableKey.hpp +++ b/src/Binder/BoundVariables/BoundVariableKey.hpp @@ -10,13 +10,23 @@ class BoundVariableKey{ int _identifier; unsigned int _scopeId; 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: BoundVariableKey(int id, unsigned int scope, bool creation){ - _identifier = std::move(id); + _identifier = id; _scopeId = scope; + _hash = KnuthsHash(scope, id); _isCreation = creation; } + int GetIdentifier(){ return _identifier; } @@ -28,6 +38,10 @@ public: bool IsCreation(){ return _isCreation; } + + u_int64_t GetHash(){ + return _hash; + } }; #endif //PORYGONLANG_BOUNDVARIABLEKEY_HPP diff --git a/src/Evaluator/EvaluationException.hpp b/src/Evaluator/EvaluationException.hpp index bf62a48..f301049 100644 --- a/src/Evaluator/EvaluationException.hpp +++ b/src/Evaluator/EvaluationException.hpp @@ -1,15 +1,17 @@ + #ifndef PORYGONLANG_EVALUATIONEXCEPTION_HPP #define PORYGONLANG_EVALUATIONEXCEPTION_HPP +#include #include #include using namespace std; -class EvaluationException : std::exception { +class EvaluationException : public std::exception { string _message; public: explicit EvaluationException(string message){ - _message = message; + _message = std::move(message); } const string defaultErrorText = "An evaluation exception occurred: "; diff --git a/src/Evaluator/EvaluationScope/EvaluationScope.cpp b/src/Evaluator/EvaluationScope/EvaluationScope.cpp index 483345f..f74d492 100644 --- a/src/Evaluator/EvaluationScope/EvaluationScope.cpp +++ b/src/Evaluator/EvaluationScope/EvaluationScope.cpp @@ -4,60 +4,32 @@ EvaluationScope::EvaluationScope(unordered_map> *scriptVariables, int deepestScope) { _scriptScope = scriptVariables; - _localScope = vector>>>(deepestScope); - for (int i = 0; i < deepestScope; i++){ - _localScope[i] = make_shared>>(); - } - _currentScope = -1; + _localScope = unordered_map>(deepestScope); } -void EvaluationScope::CreateVariable(int scope, int id, const shared_ptr& value) { - if (scope == 0){ - _scriptScope->at(id) = value; +void EvaluationScope::CreateVariable(BoundVariableKey* key, const shared_ptr &value) { + if (key->GetScopeId() == 0){ + _scriptScope -> at(key->GetIdentifier()) = value; } else{ - auto insert = _localScope[scope - 1]->insert({id, value}); + auto insert = _localScope.insert({key->GetHash(), value}); if (!insert.second){ - _localScope[scope - 1]->at(id) = value; + _localScope[key->GetHash()] = value; } } } -void EvaluationScope::SetVariable(int scope, int id, const shared_ptr& value) { - if (scope == 0){ - _scriptScope->at(id) = value; +void EvaluationScope::SetVariable(BoundVariableKey* key, const shared_ptr &value) { + if (key->GetScopeId() == 0){ + _scriptScope -> at(key->GetIdentifier()) = value; } else{ - _localScope[scope - 1]->at(id) = value; + _localScope[key->GetHash()] = value; } } -shared_ptr EvaluationScope::GetVariable(int scope, int id) { - if (scope == 0){ - return _scriptScope->at(id); +shared_ptr EvaluationScope::GetVariable(BoundVariableKey* key) { + if (key->GetScopeId() == 0){ + 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>>(); - } - 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--; - -} +} \ No newline at end of file diff --git a/src/Evaluator/EvaluationScope/EvaluationScope.hpp b/src/Evaluator/EvaluationScope/EvaluationScope.hpp index d05d891..0d3ad64 100644 --- a/src/Evaluator/EvaluationScope/EvaluationScope.hpp +++ b/src/Evaluator/EvaluationScope/EvaluationScope.hpp @@ -8,24 +8,14 @@ class EvaluationScope { unordered_map>* _scriptScope; - vector>>> _localScope; - int _currentScope; + unordered_map> _localScope; public: explicit EvaluationScope(unordered_map>* scriptVariables, int deepestScope); ~EvaluationScope() = default; - void CreateVariable(int scope, int id, const shared_ptr& value); - void SetVariable(int scope, int id, const shared_ptr& value); - void OuterScope(); - void InnerScope(bool clearScope = true); - shared_ptr GetVariable(int scope, int id); - - EvaluationScope* CreateBranchingScope(int scopeIndex); - - int GetCurrentScope(){ - return _currentScope; - } - + void CreateVariable(BoundVariableKey* key, const shared_ptr& value); + void SetVariable(BoundVariableKey* key, const shared_ptr& value); + shared_ptr GetVariable(BoundVariableKey* key); }; diff --git a/src/Evaluator/Evaluator.cpp b/src/Evaluator/Evaluator.cpp index 4ee2261..872ea58 100644 --- a/src/Evaluator/Evaluator.cpp +++ b/src/Evaluator/Evaluator.cpp @@ -35,13 +35,11 @@ void Evaluator::EvaluateStatement(BoundStatement *statement) { } void Evaluator::EvaluateBlockStatement(BoundBlockStatement* statement, bool clearScope) { - this->_evaluationScope->OuterScope(); for (auto s: statement->GetStatements()){ this -> EvaluateStatement(s); if (this->_hasReturned) break; } - this->_evaluationScope->InnerScope(clearScope); } void Evaluator::EvaluateExpressionStatement(BoundExpressionStatement *statement) { @@ -53,9 +51,9 @@ void Evaluator::EvaluateAssignmentStatement(BoundAssignmentStatement *statement) auto value = this -> EvaluateExpression(statement->GetExpression()); auto key = statement->GetKey(); if (key->IsCreation()){ - this->_evaluationScope->CreateVariable(key->GetScopeId(), key->GetIdentifier(), value); + this->_evaluationScope->CreateVariable(key, value); } 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 key = statement->GetKey(); auto block = statement->GetBlock(); - auto evaluator = shared_ptr(this->_evaluationScope->CreateBranchingScope(this->_evaluationScope->GetCurrentScope() + 1)); - auto value = make_shared(block, evaluator, type); + auto value = make_shared(block, this->_evaluationScope, type); if (key->IsCreation()){ - this->_evaluationScope->CreateVariable(key->GetScopeId(), key->GetIdentifier(), value); + this->_evaluationScope->CreateVariable(key, value); } else{ - this->_evaluationScope->SetVariable(key->GetScopeId(), key->GetIdentifier(), value); + this->_evaluationScope->SetVariable(key, value); } } @@ -109,7 +106,10 @@ shared_ptr Evaluator::EvaluateExpression(BoundExpression *expression) } shared_ptr 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(); } @@ -218,9 +218,8 @@ shared_ptr Evaluator::EvaluateFunctionCallExpression(BoundExpression* auto type = std::dynamic_pointer_cast(function->GetType()); auto parameterTypes = type->GetParameterTypes(); auto parameterKeys = type->GetParameterKeys(); - auto scope = type -> GetScopeIndex(); auto originalScope = this->_evaluationScope; - this->_evaluationScope = shared_ptr(function -> GetScope() -> CreateBranchingScope(scope)); + this->_evaluationScope = function->GetScope(); for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++){ auto parameter = parameters[i]; @@ -229,11 +228,11 @@ shared_ptr Evaluator::EvaluateFunctionCallExpression(BoundExpression* throw EvaluationException("Passed wrong type to function."); } 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->_evaluationScope = originalScope; + this->_hasReturned = false; auto r = this -> _returnValue; this -> _returnValue = nullptr; @@ -245,9 +244,8 @@ shared_ptr Evaluator::EvaluateFunction(ScriptFunctionEvalValue *funct auto parameterTypes = type->GetParameterTypes(); auto parameterKeys = type->GetParameterKeys(); - auto scope = type -> GetScopeIndex(); auto originalScope = this->_evaluationScope; - this->_evaluationScope = shared_ptr(function -> GetScope() -> CreateBranchingScope(scope)); + this->_evaluationScope = function->GetScope(); for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++){ auto parameter = parameters[i]; @@ -256,7 +254,7 @@ shared_ptr Evaluator::EvaluateFunction(ScriptFunctionEvalValue *funct throw EvaluationException("Passed wrong type to function."); } 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->_evaluationScope = originalScope;