Rework function evaluation scope to handle tables
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
c022c91777
commit
3477ddd18c
|
@ -1,5 +1,7 @@
|
|||
#include <utility>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#ifndef PORYGONLANG_SCRIPTFUNCTIONEVALVALUE_HPP
|
||||
#define PORYGONLANG_SCRIPTFUNCTIONEVALVALUE_HPP
|
||||
|
||||
|
@ -9,24 +11,30 @@
|
|||
#include "EvalValue.hpp"
|
||||
#include "../../Binder/BoundStatements/BoundStatement.hpp"
|
||||
#include "../Evaluator.hpp"
|
||||
#include "../EvaluationScope/EvaluationScope.hpp"
|
||||
|
||||
|
||||
class ScriptFunctionEvalValue : public EvalValue{
|
||||
std::shared_ptr<BoundBlockStatement> _innerBlock;
|
||||
std::shared_ptr<FunctionScriptType> _type;
|
||||
std::shared_ptr<EvaluationScope> _scope;
|
||||
std::size_t _hash;
|
||||
explicit ScriptFunctionEvalValue(std::shared_ptr<BoundBlockStatement> innerBlock, std::shared_ptr<FunctionScriptType> type, size_t hash)
|
||||
explicit ScriptFunctionEvalValue(std::shared_ptr<BoundBlockStatement> innerBlock, std::shared_ptr<EvaluationScope> scope,
|
||||
std::shared_ptr<FunctionScriptType> type, size_t hash)
|
||||
: _type(std::move(type))
|
||||
{
|
||||
_innerBlock = std::move(innerBlock);
|
||||
_scope = std::move(scope);
|
||||
_hash = hash;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit ScriptFunctionEvalValue(std::shared_ptr<BoundBlockStatement> innerBlock, std::shared_ptr<FunctionScriptType> type)
|
||||
explicit ScriptFunctionEvalValue(std::shared_ptr<BoundBlockStatement> innerBlock, std::shared_ptr<EvaluationScope> scope,
|
||||
std::shared_ptr<FunctionScriptType> type)
|
||||
: _type(std::move(type))
|
||||
{
|
||||
_innerBlock = std::move(innerBlock);
|
||||
_scope = std::move(scope);
|
||||
_hash = rand();
|
||||
}
|
||||
|
||||
|
@ -35,7 +43,7 @@ public:
|
|||
}
|
||||
|
||||
shared_ptr<EvalValue> Clone() final{
|
||||
return shared_ptr<ScriptFunctionEvalValue>(new ScriptFunctionEvalValue(_innerBlock, _type, _hash));
|
||||
return shared_ptr<ScriptFunctionEvalValue>(new ScriptFunctionEvalValue(_innerBlock, _scope, _type, _hash));
|
||||
}
|
||||
|
||||
|
||||
|
@ -49,11 +57,13 @@ public:
|
|||
return _innerBlock;
|
||||
}
|
||||
|
||||
std::size_t GetHashCode(){
|
||||
std::size_t GetHashCode() final{
|
||||
return _hash;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<EvaluationScope> GetScope(){
|
||||
return _scope;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -37,12 +37,15 @@ shared_ptr<EvalValue> EvaluationScope::GetVariable(int scope, int id) {
|
|||
return _localScope[scope - 1]->at(id);
|
||||
}
|
||||
|
||||
EvaluationScope* EvaluationScope::CreateBranchingScope(int index){
|
||||
EvaluationScope* EvaluationScope::CreateBranchingScope(int scopeIndex){
|
||||
auto scope = new EvaluationScope(this -> _scriptScope, this -> _localScope.size());
|
||||
for (int i = 0; i < index; i++){
|
||||
for (int i = 0; i <= scopeIndex; i++){
|
||||
scope->_localScope[i] = this->_localScope[i];
|
||||
}
|
||||
scope->_currentScope = index;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ public:
|
|||
void InnerScope(bool clearScope = true);
|
||||
shared_ptr<EvalValue> GetVariable(int scope, int id);
|
||||
|
||||
EvaluationScope* CreateBranchingScope(int index);
|
||||
EvaluationScope* CreateBranchingScope(int scopeIndex);
|
||||
|
||||
int GetCurrentScope(){
|
||||
return _currentScope;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
using namespace std;
|
||||
|
||||
void Evaluator::Evaluate(BoundScriptStatement *statement) {
|
||||
this->_evaluationScope = new EvaluationScope(this->_scriptData->_scriptVariables, statement->GetDeepestScope());
|
||||
this->_evaluationScope = make_shared<EvaluationScope>(this->_scriptData->_scriptVariables, statement->GetDeepestScope());
|
||||
EvaluateBlockStatement(statement, false);
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,8 @@ void Evaluator::EvaluateFunctionDeclarationStatement(BoundFunctionDeclarationSta
|
|||
auto type = statement->GetType();
|
||||
auto key = statement->GetKey();
|
||||
auto block = statement->GetBlock();
|
||||
auto value = make_shared<ScriptFunctionEvalValue>(block, type);
|
||||
auto evaluator = shared_ptr<EvaluationScope>(this->_evaluationScope->CreateBranchingScope(this->_evaluationScope->GetCurrentScope() + 1));
|
||||
auto value = make_shared<ScriptFunctionEvalValue>(block, evaluator, type);
|
||||
if (key->IsCreation()){
|
||||
this->_evaluationScope->CreateVariable(key->GetScopeId(), key->GetIdentifier(), value);
|
||||
} else{
|
||||
|
@ -174,6 +175,7 @@ shared_ptr<StringEvalValue> Evaluator::EvaluateStringExpression(BoundExpression
|
|||
shared_ptr<EvalValue> Evaluator::EvaluateFunctionExpression(BoundExpression * expression){
|
||||
switch (expression->GetKind()){
|
||||
case BoundExpressionKind ::Variable: return this->GetVariable((BoundVariableExpression*)expression);
|
||||
case BoundExpressionKind ::Index: return this->EvaluateIndexExpression(expression);
|
||||
default: throw;
|
||||
}
|
||||
}
|
||||
|
@ -216,8 +218,7 @@ shared_ptr<EvalValue> Evaluator::EvaluateFunctionCallExpression(BoundExpression*
|
|||
auto parameterKeys = type->GetParameterKeys();
|
||||
auto scope = type -> GetScopeIndex();
|
||||
auto originalScope = this->_evaluationScope;
|
||||
auto functionScope = this->_evaluationScope->CreateBranchingScope(scope);
|
||||
this->_evaluationScope = functionScope;
|
||||
this->_evaluationScope = shared_ptr<EvaluationScope>(function -> GetScope() -> CreateBranchingScope(scope));
|
||||
|
||||
for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++){
|
||||
auto parameter = parameters[i];
|
||||
|
@ -230,7 +231,6 @@ shared_ptr<EvalValue> Evaluator::EvaluateFunctionCallExpression(BoundExpression*
|
|||
}
|
||||
this->EvaluateBlockStatement(function->GetInnerBlock().get(), true);
|
||||
|
||||
delete this->_evaluationScope;
|
||||
this->_evaluationScope = originalScope;
|
||||
this->_hasReturned = false;
|
||||
auto r = this -> _returnValue;
|
||||
|
@ -245,8 +245,7 @@ shared_ptr<EvalValue> Evaluator::EvaluateFunction(ScriptFunctionEvalValue *funct
|
|||
|
||||
auto scope = type -> GetScopeIndex();
|
||||
auto originalScope = this->_evaluationScope;
|
||||
auto functionScope = this->_evaluationScope->CreateBranchingScope(scope);
|
||||
this->_evaluationScope = functionScope;
|
||||
this->_evaluationScope = shared_ptr<EvaluationScope>(function -> GetScope() -> CreateBranchingScope(scope));
|
||||
|
||||
for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++){
|
||||
auto parameter = parameters[i];
|
||||
|
@ -258,7 +257,6 @@ shared_ptr<EvalValue> Evaluator::EvaluateFunction(ScriptFunctionEvalValue *funct
|
|||
this->_evaluationScope->CreateVariable(key->GetScopeId(), key->GetIdentifier(), parameter->Clone());
|
||||
}
|
||||
this->EvaluateBlockStatement(function->GetInnerBlock().get(), true);
|
||||
delete this->_evaluationScope;
|
||||
this->_evaluationScope = originalScope;
|
||||
this->_hasReturned = false;
|
||||
auto r = this -> _returnValue;
|
||||
|
@ -293,7 +291,7 @@ shared_ptr<EvalValue> Evaluator::EvaluateComplexTableExpression(BoundExpression
|
|||
for (auto i : *declaredVars){
|
||||
variables->insert({i.first, nullptr});
|
||||
}
|
||||
auto evaluator = new EvaluationScope(variables.get(), type -> GetDeepestScope());
|
||||
auto evaluator = make_shared<EvaluationScope>(variables.get(), type -> GetDeepestScope());
|
||||
auto currentEvaluator = this -> _evaluationScope;
|
||||
this -> _evaluationScope = evaluator;
|
||||
this -> EvaluateBlockStatement(tableExpression->GetBlock(), false);
|
||||
|
|
|
@ -20,7 +20,7 @@ class Evaluator {
|
|||
shared_ptr<EvalValue> _lastValue;
|
||||
|
||||
Script* _scriptData;
|
||||
EvaluationScope* _evaluationScope;
|
||||
shared_ptr<EvaluationScope> _evaluationScope;
|
||||
|
||||
void EvaluateStatement(BoundStatement* statement);
|
||||
void EvaluateBlockStatement(BoundBlockStatement* statement, bool clearScope);
|
||||
|
@ -57,10 +57,6 @@ public:
|
|||
_evaluationScope = nullptr;
|
||||
}
|
||||
|
||||
~Evaluator(){
|
||||
delete _evaluationScope;
|
||||
}
|
||||
|
||||
void Evaluate(BoundScriptStatement* statement);
|
||||
shared_ptr<EvalValue> EvaluateFunction(ScriptFunctionEvalValue* func, vector<EvalValue*> parameters);
|
||||
|
||||
|
|
|
@ -86,13 +86,15 @@ TEST_CASE( "Define script function and return", "[integration]" ) {
|
|||
|
||||
TEST_CASE( "Functions can call themselves", "[integration]" ) {
|
||||
Script* script = Script::Create(
|
||||
"val = 0\n"
|
||||
"function add() \n"
|
||||
"if val < 5 then\n"
|
||||
"val = val + 1\n"
|
||||
"add()\n"
|
||||
"end\n"
|
||||
"end");
|
||||
R"(
|
||||
val = 0
|
||||
function add()
|
||||
if val < 5 then
|
||||
val = val + 1
|
||||
add()
|
||||
end
|
||||
end
|
||||
)");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
script->CallFunction("add", {});
|
||||
|
|
|
@ -62,6 +62,24 @@ table = {
|
|||
delete script;
|
||||
}
|
||||
|
||||
TEST_CASE( "Complex table with function", "[integration]" ) {
|
||||
Script* script = Script::Create(
|
||||
R"(
|
||||
table = {
|
||||
local foo = 'test'
|
||||
function getFoo()
|
||||
return foo
|
||||
end
|
||||
}
|
||||
result = table["getFoo"]()
|
||||
)");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto variable = script->GetVariable("result");
|
||||
REQUIRE(variable != nullptr);
|
||||
delete script;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue