Rework of variable scope to reduce load on evaluator
This commit is contained in:
parent
0339c44a89
commit
813ab1e90b
|
@ -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){
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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: ";
|
||||||
|
|
|
@ -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--;
|
|
||||||
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue