Rework of evaluation variable handling, to account for functions having branching variable states
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
4d452b33e0
commit
471632c6e4
|
@ -4,7 +4,10 @@
|
|||
|
||||
EvaluationScope::EvaluationScope(unordered_map<int, shared_ptr<EvalValue>> *scriptVariables, int deepestScope) {
|
||||
_scriptScope = scriptVariables;
|
||||
_localScope = vector<unordered_map<int, shared_ptr<EvalValue>>>(deepestScope);
|
||||
_localScope = vector<shared_ptr<unordered_map<int, shared_ptr<EvalValue>>>>(deepestScope);
|
||||
for (int i = 0; i < deepestScope; i++){
|
||||
_localScope[i] = make_shared<unordered_map<int, shared_ptr<EvalValue>>>();
|
||||
}
|
||||
_currentScope = -1;
|
||||
}
|
||||
|
||||
|
@ -12,7 +15,10 @@ void EvaluationScope::CreateVariable(int scope, int id, const shared_ptr<EvalVal
|
|||
if (scope == 0){
|
||||
_scriptScope->at(id) = value;
|
||||
} else{
|
||||
_localScope[scope - 1][id] = value;
|
||||
auto insert = _localScope[scope - 1]->insert({id, value});
|
||||
if (!insert.second){
|
||||
_localScope[scope - 1]->at(id) = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +26,7 @@ void EvaluationScope::SetVariable(int scope, int id, const shared_ptr<EvalValue>
|
|||
if (scope == 0){
|
||||
_scriptScope->at(id) = value;
|
||||
} else{
|
||||
_localScope[scope - 1][id] = value;
|
||||
_localScope[scope - 1]->at(id) = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,11 +34,15 @@ shared_ptr<EvalValue> EvaluationScope::GetVariable(int scope, int id) {
|
|||
if (scope == 0){
|
||||
return _scriptScope->at(id);
|
||||
}
|
||||
return _localScope[scope - 1][id];
|
||||
return _localScope[scope - 1]->at(id);
|
||||
}
|
||||
|
||||
void EvaluationScope::JumpToScope(int index){
|
||||
_currentScope = index;
|
||||
EvaluationScope* EvaluationScope::CreateBranchingScope(int index){
|
||||
auto scope = new EvaluationScope(this -> _scriptScope, this -> _localScope.size());
|
||||
for (int i = 0; i < index; i++){
|
||||
scope->_localScope[i] = this->_localScope[i];
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
|
||||
void EvaluationScope::OuterScope() {
|
||||
|
@ -41,7 +51,7 @@ void EvaluationScope::OuterScope() {
|
|||
|
||||
void EvaluationScope::InnerScope() {
|
||||
auto scope = this->_localScope[_currentScope];
|
||||
scope.clear();
|
||||
scope->clear();
|
||||
_currentScope--;
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
class EvaluationScope {
|
||||
unordered_map<int, shared_ptr<EvalValue>>* _scriptScope;
|
||||
vector<unordered_map<int, shared_ptr<EvalValue>>> _localScope;
|
||||
vector<shared_ptr<unordered_map<int, shared_ptr<EvalValue>>>> _localScope;
|
||||
int _currentScope;
|
||||
public:
|
||||
explicit EvaluationScope(unordered_map<int, shared_ptr<EvalValue>>* scriptVariables, int deepestScope);
|
||||
|
@ -20,11 +20,12 @@ public:
|
|||
void InnerScope();
|
||||
shared_ptr<EvalValue> GetVariable(int scope, int id);
|
||||
|
||||
void JumpToScope(int index);
|
||||
EvaluationScope* CreateBranchingScope(int index);
|
||||
|
||||
int GetCurrentScope(){
|
||||
return _currentScope;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -102,7 +102,8 @@ shared_ptr<EvalValue> Evaluator::EvaluateExpression(BoundExpression *expression)
|
|||
}
|
||||
|
||||
shared_ptr<EvalValue> Evaluator::GetVariable(BoundVariableExpression* expression){
|
||||
return this->_evaluationScope->GetVariable(expression->GetScope(), expression->GetId())->Clone();
|
||||
auto variable = this->_evaluationScope->GetVariable(expression->GetScope(), expression->GetId());
|
||||
return variable->Clone();
|
||||
}
|
||||
|
||||
shared_ptr<NumericEvalValue> Evaluator::EvaluateIntegerExpression(BoundExpression *expression) {
|
||||
|
@ -179,6 +180,7 @@ shared_ptr<EvalValue> Evaluator::EvaluateNilExpression(BoundExpression * express
|
|||
shared_ptr<EvalValue> Evaluator::EvaluateFunctionCallExpression(BoundExpression* expression){
|
||||
auto functionCall = (BoundFunctionCallExpression*)expression;
|
||||
auto function = dynamic_pointer_cast<ScriptFunctionEvalValue>(this->EvaluateExpression(functionCall->GetFunctionExpression()));
|
||||
|
||||
auto boundParameters = functionCall->GetParameters();
|
||||
auto parameters = vector<shared_ptr<EvalValue>>(boundParameters.size());
|
||||
for (int i = 0; i < boundParameters.size(); i++){
|
||||
|
@ -189,8 +191,9 @@ shared_ptr<EvalValue> Evaluator::EvaluateFunctionCallExpression(BoundExpression*
|
|||
auto parameterTypes = type->GetParameterTypes();
|
||||
auto parameterKeys = type->GetParameterKeys();
|
||||
auto scope = type -> GetScopeIndex();
|
||||
auto originalScope = this->_evaluationScope->GetCurrentScope();
|
||||
this->_evaluationScope->JumpToScope(scope);
|
||||
auto originalScope = this->_evaluationScope;
|
||||
auto functionScope = this->_evaluationScope->CreateBranchingScope(scope);
|
||||
this->_evaluationScope = functionScope;
|
||||
|
||||
for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++){
|
||||
auto parameter = parameters[i];
|
||||
|
@ -201,8 +204,9 @@ shared_ptr<EvalValue> Evaluator::EvaluateFunctionCallExpression(BoundExpression*
|
|||
auto key = parameterKeys.at(i);
|
||||
this->_evaluationScope->CreateVariable(key->GetScopeId(), key->GetIdentifier(), parameter->Clone());
|
||||
}
|
||||
this->_evaluationScope->OuterScope();
|
||||
this->EvaluateBlockStatement(function->GetInnerBlock().get());
|
||||
this->_evaluationScope->JumpToScope(originalScope);
|
||||
this->_evaluationScope = originalScope;
|
||||
this->_hasReturned = false;
|
||||
auto r = this -> _returnValue;
|
||||
this -> _returnValue = nullptr;
|
||||
|
|
|
@ -104,4 +104,33 @@ TEST_CASE( "Functions can call themselves", "[integration]" ) {
|
|||
delete script;
|
||||
}
|
||||
|
||||
TEST_CASE( "Functions respect scope", "[integration]" ) {
|
||||
Script* script = Script::Create(
|
||||
R"(
|
||||
function test()
|
||||
function foo()
|
||||
local a = 10
|
||||
end
|
||||
if true then
|
||||
if true then
|
||||
local a = 50
|
||||
foo()
|
||||
result = a
|
||||
end
|
||||
end
|
||||
end
|
||||
test()
|
||||
)"
|
||||
);
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
|
||||
auto variable = script->GetVariable("result");
|
||||
REQUIRE(variable->GetType()->GetClass() == TypeClass::Number);
|
||||
REQUIRE(variable->EvaluateInteger() == 50);
|
||||
|
||||
delete script;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue