Allow non-local script functions to be called from outside the script

This commit is contained in:
Deukhoofd 2019-06-05 18:44:23 +02:00
parent 43dede9ae2
commit bda26b0ddf
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
6 changed files with 50 additions and 4 deletions

View File

@ -175,3 +175,19 @@ shared_ptr<EvalValue> Evaluator::EvaluateFunctionCallExpression(BoundExpression*
} }
EvalValue* Evaluator::EvaluateFunction(ScriptFunctionEvalValue *function, vector<EvalValue *> parameters) {
auto type = std::dynamic_pointer_cast<FunctionScriptType>(function->GetType());
auto parameterTypes = type->GetParameterTypes();
auto parameterKeys = type->GetParameterKeys();
for (int i = 0; i < parameterTypes->size() && i < parameterKeys->size() && i < parameters.size(); i++){
auto parameter = parameters[i];
auto requiredType = parameterTypes->at(i);
if (*parameter->GetType() != requiredType.get()){
throw EvaluationException("Passed wrong type to function.");
}
auto key = parameterKeys->at(i);
this->_evaluationScope->CreateVariable(key->GetScopeId(), key->GetIdentifier(), parameter->Clone());
}
this->EvaluateBlockStatement(function->GetInnerBlock().get());
return nullptr;
}

View File

@ -9,6 +9,7 @@
#include "EvalValues/NumericEvalValue.hpp" #include "EvalValues/NumericEvalValue.hpp"
#include "EvalValues/StringEvalValue.hpp" #include "EvalValues/StringEvalValue.hpp"
#include "EvalValues/StringEvalValue.hpp" #include "EvalValues/StringEvalValue.hpp"
#include "EvalValues/ScriptFunctionEvalValue.hpp"
#include "EvaluationScope/EvaluationScope.hpp" #include "EvaluationScope/EvaluationScope.hpp"
using namespace std; using namespace std;
@ -21,6 +22,7 @@ class Evaluator {
EvaluationScope* _evaluationScope; EvaluationScope* _evaluationScope;
void EvaluateStatement(BoundStatement* statement); void EvaluateStatement(BoundStatement* statement);
void EvaluateBlockStatement(BoundBlockStatement* statement);
void EvaluateExpressionStatement(BoundExpressionStatement* statement); void EvaluateExpressionStatement(BoundExpressionStatement* statement);
void EvaluateAssignmentStatement(BoundAssignmentStatement* statement); void EvaluateAssignmentStatement(BoundAssignmentStatement* statement);
void EvaluateFunctionDeclarationStatement(BoundFunctionDeclarationStatement *statement); void EvaluateFunctionDeclarationStatement(BoundFunctionDeclarationStatement *statement);
@ -52,7 +54,7 @@ public:
} }
void Evaluate(BoundScriptStatement* statement); void Evaluate(BoundScriptStatement* statement);
void EvaluateBlockStatement(BoundBlockStatement* statement); EvalValue* EvaluateFunction(ScriptFunctionEvalValue* func, vector<EvalValue*> parameters);
EvaluationScope* GetScope(){ EvaluationScope* GetScope(){
return _evaluationScope; return _evaluationScope;

View File

@ -1,3 +1,5 @@
#include <utility>
#include <utility> #include <utility>
#include <unordered_map> #include <unordered_map>
#include "Script.hpp" #include "Script.hpp"
@ -65,6 +67,16 @@ EvalValue *Script::GetLastValue() {
return _evaluator->GetLastValue(); return _evaluator->GetLastValue();
} }
bool Script::HasFunction(const string &key) {
auto f = _scriptVariables->find(HashedString(key).GetHash());
return f != _scriptVariables->end() && f.operator->()->second->GetType()->GetClass() == TypeClass ::Function;
}
EvalValue *Script::CallFunction(const string &key, vector<EvalValue *> variables) {
auto var = (ScriptFunctionEvalValue*)GetVariable(key);
return this->_evaluator->EvaluateFunction(var, std::move(variables));
}
extern "C" { extern "C" {
Script* CreateScript(char * s){ Script* CreateScript(char * s){
return Script::Create(s); return Script::Create(s);

View File

@ -36,6 +36,9 @@ public:
EvalValue* GetVariable(const string& key); EvalValue* GetVariable(const string& key);
bool HasVariable(const string& key); bool HasVariable(const string& key);
EvalValue* CallFunction(const string& key, vector<EvalValue*> variables);
bool HasFunction(const string& key);
}; };

View File

@ -1,3 +0,0 @@

View File

@ -38,4 +38,20 @@ TEST_CASE( "Define script function and call multiple times", "[integration]" ) {
delete script; delete script;
} }
TEST_CASE( "Define script function and call from extern", "[integration]" ) {
Script* script = Script::Create("result = 0 function add(number a) result = result + a end");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
REQUIRE(script->HasFunction("add"));
script->CallFunction("add", {new IntegerEvalValue(5)});
script->CallFunction("add", {new IntegerEvalValue(6)});
auto result = script->GetVariable("result");
REQUIRE(result->GetType()->GetClass() == TypeClass::Number);
REQUIRE(result->EvaluateInteger() == 11);
delete script;
}
#endif #endif