From 2f912afe923e1535a88c31e24c9745b203da3907 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sat, 10 Aug 2019 11:55:45 +0200 Subject: [PATCH] Setup for making script options non global if desired --- src/Evaluator/Evaluator.cpp | 2 +- src/Evaluator/Evaluator.hpp | 7 +++-- src/GlobalScriptOptions.cpp | 18 ------------ src/GlobalScriptOptions.hpp | 31 -------------------- src/Script.cpp | 10 ++++--- src/Script.hpp | 9 ++++++ src/ScriptOptions.cpp | 21 ++++++++++++++ src/ScriptOptions.hpp | 36 ++++++++++++++++++++++++ src/StandardLibraries/BasicLibrary.hpp | 18 ++++++------ src/UserData/UserDataFunction.cpp | 3 +- src/UserData/UserDataFunction.hpp | 15 ++++++---- src/UserData/UserDataTemplates.hpp | 7 +++-- tests/standardLibraries/BasicLibrary.cpp | 4 +-- 13 files changed, 105 insertions(+), 76 deletions(-) delete mode 100644 src/GlobalScriptOptions.cpp delete mode 100644 src/GlobalScriptOptions.hpp create mode 100644 src/ScriptOptions.cpp create mode 100644 src/ScriptOptions.hpp diff --git a/src/Evaluator/Evaluator.cpp b/src/Evaluator/Evaluator.cpp index 9e9dbe3..4a78626 100644 --- a/src/Evaluator/Evaluator.cpp +++ b/src/Evaluator/Evaluator.cpp @@ -325,7 +325,7 @@ namespace Porygon::Evaluation { arr[i] = parameters[i].Get(); } delete function; - return scriptOption -> Call(arr, parameters.size()); + return scriptOption -> Call(this -> _scriptOptions, arr, parameters.size()); } } diff --git a/src/Evaluator/Evaluator.hpp b/src/Evaluator/Evaluator.hpp index 045573d..0ac3392 100644 --- a/src/Evaluator/Evaluator.hpp +++ b/src/Evaluator/Evaluator.hpp @@ -11,6 +11,7 @@ #include "EvalValues/ScriptFunctionEvalValue.hpp" #include "EvaluationScope/EvaluationScope.hpp" #include "EvalValuePointer.hpp" +#include "../ScriptOptions.hpp" using namespace std; @@ -21,7 +22,7 @@ namespace Porygon::Evaluation{ bool _hasReturned; bool _hasBroken; - //Porygon::Script* _scriptData; + const Porygon::ScriptOptions* _scriptOptions; shared_ptr _evaluationScope; void EvaluateStatement(const BoundStatement* statement); @@ -48,9 +49,9 @@ namespace Porygon::Evaluation{ EvalValuePointer GetVariable(const BoundVariableExpression *expression); public: - explicit Evaluator(map* scriptVariables) + explicit Evaluator(map* scriptVariables, const ScriptOptions* options) : _scriptVariables(scriptVariables), _hasReturned(false), _hasBroken(false), _returnValue(nullptr), - _evaluationScope(nullptr){ + _evaluationScope(nullptr), _scriptOptions(options){ } const EvalValue* Evaluate(const BoundScriptStatement* statement); diff --git a/src/GlobalScriptOptions.cpp b/src/GlobalScriptOptions.cpp deleted file mode 100644 index e0934aa..0000000 --- a/src/GlobalScriptOptions.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include "GlobalScriptOptions.hpp" -#include "Utilities/StringUtils.hpp" - -std::streambuf* Porygon::GlobalScriptOptions::_printBuffer = std::cout.rdbuf(); -std::ostream* Porygon::GlobalScriptOptions::_printStream = new std::ostream(Porygon::GlobalScriptOptions::_printBuffer); - -static void DefaultPrint(const char16_t* s){ - Porygon::GlobalScriptOptions::GetPrintStream() << Porygon::Utilities::StringUtils::FromUTF8(s) << std::endl; -} - -void (*Porygon::GlobalScriptOptions::_print)(const char16_t*) = DefaultPrint; - -extern "C"{ - void SetPrintFunc(void (*func)(const char16_t*)){ - Porygon::GlobalScriptOptions::SetPrintFunc(func); - } -} \ No newline at end of file diff --git a/src/GlobalScriptOptions.hpp b/src/GlobalScriptOptions.hpp deleted file mode 100644 index 4857dea..0000000 --- a/src/GlobalScriptOptions.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PORYGONLANG_GLOBALSCRIPTOPTIONS_HPP -#define PORYGONLANG_GLOBALSCRIPTOPTIONS_HPP - -#include - -namespace Porygon{ - class GlobalScriptOptions{ - static void (*_print)(const char16_t* s); - static std::streambuf* _printBuffer; - static std::ostream* _printStream; - public: - inline static void Print(const char16_t* s){ - GlobalScriptOptions::_print(s); - } - - static void SetPrintFunc(void (*print)(const char16_t *)){ - GlobalScriptOptions::_print = print; - } - - static std::ostream& GetPrintStream(){ - return *GlobalScriptOptions::_printStream; - } - - static void SetPrintStream(std::ostream* stream){ - delete GlobalScriptOptions::_printStream; - GlobalScriptOptions::_printStream = stream; - } - }; -} - -#endif //PORYGONLANG_GLOBALSCRIPTOPTIONS_HPP diff --git a/src/Script.cpp b/src/Script.cpp index 0a16d56..c42cba2 100644 --- a/src/Script.cpp +++ b/src/Script.cpp @@ -25,9 +25,10 @@ Porygon::Script *Porygon::Script::Create(const string &script) { Porygon::Script::Script(const u16string& s) : Diagnostics(make_shared(s)), _boundScript(nullptr), - _scriptVariables(new map()) + _scriptVariables(new map()), + _scriptOptions(nullptr) { - _evaluator = new Evaluator(this -> _scriptVariables); + _evaluator = new Evaluator(this -> _scriptVariables, this -> GetScriptOptions()); this -> Parse(s); } @@ -99,9 +100,10 @@ Porygon::Script::Script(shared_ptr boundScript, shared_ptr diagnostics) : _boundScript(std::move(boundScript)), Diagnostics(std::move(diagnostics)), - _scriptVariables(new map()) + _scriptVariables(new map()), + _scriptOptions(nullptr) { - _evaluator = new Evaluator(_scriptVariables); + _evaluator = new Evaluator(_scriptVariables, this -> GetScriptOptions()); } extern "C" { diff --git a/src/Script.hpp b/src/Script.hpp index 04f59a1..7a0eea0 100644 --- a/src/Script.hpp +++ b/src/Script.hpp @@ -10,6 +10,7 @@ #include "Evaluator/Evaluator.hpp" #include "Evaluator/EvalValues/EvalValue.hpp" #include "Utilities/HashedString.hpp" +#include "ScriptOptions.hpp" using namespace std; using namespace Porygon::Evaluation; @@ -20,6 +21,7 @@ namespace Porygon{ map* _scriptVariables; shared_ptr _boundScript; shared_ptr _returnType; + ScriptOptions* _scriptOptions; explicit Script(const u16string&); Script(shared_ptr boundScript, shared_ptr diagnostics); @@ -41,6 +43,13 @@ namespace Porygon{ _returnType = t; } + [[nodiscard]] inline const ScriptOptions* GetScriptOptions() const{ + if (_scriptOptions == nullptr){ + return ScriptOptions::GetDefaultScriptOptions(); + } + return _scriptOptions; + } + EvalValuePointer Evaluate(); const EvalValue* GetVariable(const u16string& key); diff --git a/src/ScriptOptions.cpp b/src/ScriptOptions.cpp new file mode 100644 index 0000000..a8630db --- /dev/null +++ b/src/ScriptOptions.cpp @@ -0,0 +1,21 @@ +#include +#include "ScriptOptions.hpp" +#include "Utilities/StringUtils.hpp" + +Porygon::ScriptOptions Porygon::ScriptOptions::DefaultScriptOptions; + +std::streambuf* Porygon::ScriptOptions::_printBuffer = std::cout.rdbuf(); +std::ostream* Porygon::ScriptOptions::_printStream = new std::ostream(Porygon::ScriptOptions::_printBuffer); + +static void DefaultPrint(const char16_t* s){ + Porygon::ScriptOptions::GetDefaultScriptOptions()->GetPrintStream() << Porygon::Utilities::StringUtils::FromUTF8(s) << std::endl; +} + +void (*Porygon::ScriptOptions::_print)(const char16_t*) = DefaultPrint; + + +extern "C"{ + void SetDefaultPrintFunc(void (*func)(const char16_t*)){ + Porygon::ScriptOptions::GetDefaultScriptOptions()->SetPrintFunc(func); + } +} \ No newline at end of file diff --git a/src/ScriptOptions.hpp b/src/ScriptOptions.hpp new file mode 100644 index 0000000..95e1525 --- /dev/null +++ b/src/ScriptOptions.hpp @@ -0,0 +1,36 @@ +#ifndef PORYGONLANG_SCRIPTOPTIONS_HPP +#define PORYGONLANG_SCRIPTOPTIONS_HPP + +#include + +namespace Porygon{ + class ScriptOptions{ + static Porygon::ScriptOptions DefaultScriptOptions; + static void (*_print)(const char16_t* s); + static std::streambuf* _printBuffer; + static std::ostream* _printStream; + public: + static Porygon::ScriptOptions* GetDefaultScriptOptions(){ + return &DefaultScriptOptions; + } + + inline void Print(const char16_t* s) const{ + ScriptOptions::_print(s); + } + + void SetPrintFunc(void (*print)(const char16_t *)){ + ScriptOptions::_print = print; + } + + std::ostream& GetPrintStream(){ + return *ScriptOptions::_printStream; + } + + void SetPrintStream(std::ostream* stream){ + delete ScriptOptions::_printStream; + ScriptOptions::_printStream = stream; + } + }; +} + +#endif //PORYGONLANG_SCRIPTOPTIONS_HPP diff --git a/src/StandardLibraries/BasicLibrary.hpp b/src/StandardLibraries/BasicLibrary.hpp index 9d84a65..7bbe56d 100644 --- a/src/StandardLibraries/BasicLibrary.hpp +++ b/src/StandardLibraries/BasicLibrary.hpp @@ -8,20 +8,21 @@ #include "../Evaluator/EvalValues/NumericEvalValue.hpp" #include "../Evaluator/EvalValues/NilEvalValue.hpp" #include "../Utilities/StringUtils.hpp" +#include "../Utilities/Random.hpp" #include "../Binder/BoundVariables/BoundVariable.hpp" #include "../UserData/UserDataFunction.hpp" #include "../UserData/UserDataFunctionType.hpp" -#include "../GlobalScriptOptions.hpp" +#include "../ScriptOptions.hpp" namespace Porygon::StandardLibraries{ class BasicLibrary{ - static const Evaluation::EvalValue* _error(void*, const Evaluation::EvalValue* parameters[], int parameterCount){ + static const Evaluation::EvalValue* _error(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ auto message = parameters[0]->EvaluateString(); auto conv = Utilities::StringUtils::FromUTF8(message); throw Evaluation::EvaluationException(conv); } - static const Evaluation::EvalValue* _assert(void*, const Evaluation::EvalValue* parameters[], int parameterCount){ + static const Evaluation::EvalValue* _assert(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ auto assertion = parameters[0]->EvaluateBool(); if (!assertion){ if (parameterCount >= 2){ @@ -34,13 +35,13 @@ namespace Porygon::StandardLibraries{ return new Evaluation::BooleanEvalValue(true); } - static const Evaluation::EvalValue* _print(void*, const Evaluation::EvalValue* parameters[], int parameterCount){ + static const Evaluation::EvalValue* _print(void*, const ScriptOptions* options, const Evaluation::EvalValue* parameters[], int parameterCount){ auto message = parameters[0]->EvaluateString(); - GlobalScriptOptions::Print(message.c_str()); + options->Print(message.c_str()); return new Evaluation::NilEvalValue(); } - static const Evaluation::EvalValue* _toInt(void*, const Evaluation::EvalValue* parameters[], int parameterCount){ + static const Evaluation::EvalValue* _toInt(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ auto parameter = parameters[0]->EvaluateString(); auto parsed = Utilities::StringUtils::ParseInteger(parameter); return new Evaluation::IntegerEvalValue(parsed); @@ -75,9 +76,10 @@ namespace Porygon::StandardLibraries{ static Evaluation::EvalValue* GetFuncEvalValue( - const Evaluation::EvalValue* (*func)(void* obj, const Evaluation::EvalValue* parameters[], int parameterCount), + const Evaluation::EvalValue* (*func)(void* obj, const ScriptOptions*, + const Evaluation::EvalValue* parameters[], int parameterCount), const shared_ptr& type, size_t optionLength){ - auto f = new Evaluation::GenericFunctionEvalValue(type, rand()); + auto f = new Evaluation::GenericFunctionEvalValue(type, Utilities::Random::Get()); for (size_t i = 0; i < optionLength; i++){ auto funcOption = new UserData::UserDataFunction(func, nullptr); f->RegisterOption(funcOption); diff --git a/src/UserData/UserDataFunction.cpp b/src/UserData/UserDataFunction.cpp index fff5406..dc8461e 100644 --- a/src/UserData/UserDataFunction.cpp +++ b/src/UserData/UserDataFunction.cpp @@ -5,7 +5,8 @@ using namespace Porygon::Evaluation; namespace Porygon::UserData{ extern "C" { - const EvalValue * CreateFunctionEvalValue(const Evaluation::EvalValue* (*func)(void* , const EvalValue* [], int ), void* obj) { + const EvalValue * CreateFunctionEvalValue(const Evaluation::EvalValue* (*func)(void*, const ScriptOptions*, + const EvalValue* [], int ), void* obj) { auto opt = new UserDataFunction(func, obj); auto t = new GenericFunctionEvalValue(make_shared(), rand()); t->RegisterOption(opt); diff --git a/src/UserData/UserDataFunction.hpp b/src/UserData/UserDataFunction.hpp index 45b8d9e..ea19e71 100644 --- a/src/UserData/UserDataFunction.hpp +++ b/src/UserData/UserDataFunction.hpp @@ -4,19 +4,23 @@ #include "../Evaluator/EvalValues/ScriptFunctionEvalValue.hpp" #include "UserDataFunctionType.hpp" #include "../ScriptTypes/FunctionScriptType.hpp" +#include "../ScriptOptions.hpp" namespace Porygon::UserData{ class UserDataFunction : public Evaluation::GenericFunctionOption { - const Evaluation::EvalValue* (*_call)(void* obj, const Evaluation::EvalValue* parameters[], int parameterCount); + const Evaluation::EvalValue* (*_call)(void* obj, const ScriptOptions*, const Evaluation::EvalValue* parameters[], + int parameterCount); void *_obj; - UserDataFunction(const Evaluation::EvalValue* (*call)(void* obj, const Evaluation::EvalValue* parameters[], int parameterCount), void* obj, + UserDataFunction(const Evaluation::EvalValue* (*call)(void* obj, const ScriptOptions*, + const Evaluation::EvalValue* parameters[], int parameterCount), void* obj, const shared_ptr& type, size_t hash) : GenericFunctionOption(){ _call = call; _obj = obj; } public: - UserDataFunction(const Evaluation::EvalValue* (*call)(void* obj, const Evaluation::EvalValue* parameters[], int parameterCount), void* obj) : + UserDataFunction(const Evaluation::EvalValue* (*call)(void* obj, const ScriptOptions*, + const Evaluation::EvalValue* parameters[], int parameterCount), void* obj) : GenericFunctionOption(){ _call = call; _obj = obj; @@ -25,8 +29,9 @@ namespace Porygon::UserData{ ~UserDataFunction() final = default; [[nodiscard]] - inline const Evaluation::EvalValue* Call(const Evaluation::EvalValue* parameters[], int parameterCount) const{ - return _call(_obj, parameters, parameterCount); + inline const Evaluation::EvalValue* Call(const ScriptOptions* script, + const Evaluation::EvalValue* parameters[], int parameterCount) const{ + return _call(_obj, script, parameters, parameterCount); } }; } diff --git a/src/UserData/UserDataTemplates.hpp b/src/UserData/UserDataTemplates.hpp index 6b0d887..10adbae 100644 --- a/src/UserData/UserDataTemplates.hpp +++ b/src/UserData/UserDataTemplates.hpp @@ -102,8 +102,8 @@ auto t = new Porygon::Evaluation::GenericFunctionEvalValue(make_shared(), \ Porygon::Utilities::Random::Get()); \ t->RegisterOption(new Porygon::UserData::UserDataFunction( \ - [](void* obj, const Porygon::Evaluation::EvalValue* par[], int parameterCount) \ - -> const Porygon::Evaluation::EvalValue*{return ((const T_USERDATA*)obj)->invoke__##fieldName(obj, par, parameterCount);}, \ + [](void* obj, const ScriptOptions* opts, const Porygon::Evaluation::EvalValue* par[], int parameterCount) \ + -> const Porygon::Evaluation::EvalValue*{return ((const T_USERDATA*)obj)->invoke__##fieldName(obj, opts, par, parameterCount);}, \ obj)); \ return t;}, \ nullptr) \ @@ -123,7 +123,8 @@ \returns An invokable function. */ #define PORYGON_PREPARE_FUNCTION(userDataTypeName, fieldName, returnType, ...) \ - static const Porygon::Evaluation::EvalValue* invoke__##fieldName(void* obj, const Porygon::Evaluation::EvalValue* par[], int parameterCount){ \ + static const Porygon::Evaluation::EvalValue* invoke__##fieldName(void* obj, const ScriptOptions* opts, \ + const Porygon::Evaluation::EvalValue* par[], int parameterCount){ \ return Porygon::Evaluation::EvalValueHelper::Create(((userDataTypeName*)obj)->fieldName( \ __VA_ARGS__ \ ));} diff --git a/tests/standardLibraries/BasicLibrary.cpp b/tests/standardLibraries/BasicLibrary.cpp index 8cb8678..4014670 100644 --- a/tests/standardLibraries/BasicLibrary.cpp +++ b/tests/standardLibraries/BasicLibrary.cpp @@ -1,7 +1,7 @@ #ifdef TESTS_BUILD #include #include "../src/Script.hpp" -#include "../../src/GlobalScriptOptions.hpp" +#include "../../src/ScriptOptions.hpp" #include using namespace Porygon; @@ -56,7 +56,7 @@ TEST_CASE( "Print func works", "[integration]" ) { Script* script = Script::Create(u"print('foobar')"); REQUIRE(!script->Diagnostics -> HasErrors()); auto stream = new std::stringstream(); - GlobalScriptOptions::SetPrintStream(stream); + ScriptOptions::GetDefaultScriptOptions()->SetPrintStream(stream); script->Evaluate(); auto printVal = stream->str(); REQUIRE(printVal == "foobar\n");