#include #include #include #include #include "Script.hpp" #include "Parser/Lexer.hpp" #include "Parser/Parser.hpp" #include "Binder/Binder.hpp" #include "EvaluateResult.hpp" Porygon::Script* Porygon::Script::Create(const u16string& script, ScriptOptions* options) { return new Script(script, options); } std::u16string To_UTF16(const string &s) { std::wstring_convert, char16_t> conv; return conv.from_bytes(s); } Porygon::Script *Porygon::Script::Create(const string &script, ScriptOptions* options) { return Script::Create(To_UTF16(script), options); } Porygon::Script::Script(const u16string& s, ScriptOptions* options) : Diagnostics(make_shared(s)), _boundScript(nullptr), _scriptVariables(new map()), _scriptTypes(new unordered_map>{}), _scriptOptions(options) { _evaluator = new Evaluator(this -> _scriptVariables, this -> GetScriptOptions()); this -> Parse(s); } EvalValuePointer Porygon::Script::Evaluate() { return _evaluator->Evaluate(_boundScript.get()); } Porygon::Script::~Script() { delete this -> _evaluator; this->_scriptVariables->clear(); delete this->_scriptVariables; this->_scriptTypes->clear(); delete this->_scriptTypes; } void Porygon::Script::Parse(const u16string& script) { auto lexer = Lexer(script, this); auto lexResult = lexer.Lex(); auto parser = Parser::Parser(lexResult, this); auto parseResult = parser.Parse(); for (auto token : lexResult){ delete token; } lexResult.clear(); if (!Diagnostics->HasErrors()){ map scriptScope; unordered_map> variableTypes; auto bindScope = new BoundScope(&scriptScope, &variableTypes); this->_boundScript = shared_ptr(Binder::Binder::Bind(this, parseResult, bindScope)); for (const auto& v : scriptScope){ this->_scriptVariables -> insert({v.first, nullptr}); delete v.second; } for (const auto& v : variableTypes){ this->_scriptTypes -> insert({v.first, nullptr}); } scriptScope.clear(); variableTypes.clear(); } delete parseResult; } const EvalValue* Porygon::Script::GetVariable(const u16string &key) { return _scriptVariables -> at(HashedString::CreateLookup(key)).Clone(); } bool Porygon::Script::HasVariable(const u16string &key) { auto f = _scriptVariables->find(HashedString::CreateLookup(key)); return f != _scriptVariables->end(); } bool Porygon::Script::HasFunction(const u16string &key) { auto f = _scriptVariables->find(HashedString::CreateLookup(key)); return f != _scriptVariables->end() && f.operator->()->second->GetTypeClass() == TypeClass ::Function; } const EvalValue* Porygon::Script::CallFunction(const u16string &key, const vector& variables) { auto var = (GenericFunctionEvalValue*)GetVariable(key); return this->_evaluator->EvaluateFunction(var, variables); } Porygon::Script *Porygon::Script::Clone(const Porygon::Script *script) { auto s = new Script(script->_boundScript, script->Diagnostics); s->_scriptOptions = script ->_scriptOptions; for (const auto& v: *script->_scriptVariables){ s->_scriptVariables->insert({v.first, nullptr}); } for (const auto& v: *script->_scriptTypes){ s->_scriptTypes->insert({v.first, v.second}); } s->_returnType = script->_returnType; return s; } Porygon::Script::Script(shared_ptr boundScript, shared_ptr diagnostics) : _boundScript(std::move(boundScript)), Diagnostics(std::move(diagnostics)), _scriptVariables(new map()), _scriptTypes(new unordered_map>{}), _scriptOptions(nullptr) { _evaluator = new Evaluator(_scriptVariables, this -> GetScriptOptions()); } std::string Porygon::Script::GetTreeString() { if (_treeString.empty()){ std::stringstream stream; _boundScript->GetTreeString(stream, 0); _treeString = stream.str(); } return _treeString; } extern "C" { Porygon::Script* CreateScript(char16_t * s, Porygon::ScriptOptions* options){ return Porygon::Script::Create(s, options); } Porygon::Script* CloneScript(Porygon::Script* p){ return Porygon::Script::Clone(p); } Porygon::EvaluateResult* EvaluateScript(Porygon::Script* script){ try{ auto result = script -> Evaluate(); return new Porygon::EvaluateResult(result.Take()); } catch (const EvaluationException& e){ return new Porygon::EvaluateResult(e.what()); } } bool HasVariable(Porygon::Script* script, const char16_t* key){ return script->HasVariable(key); } const EvalValue* GetVariable(Porygon::Script* script, const char16_t* key){ return script->GetVariable(key); } bool HasFunction(Porygon::Script* script, const char16_t* key){ return script->HasFunction(key); } Porygon::EvaluateResult* CallFunction(Porygon::Script* script, const char16_t* key, EvalValue* parameters[], int parameterCount){ try{ std::vector v(parameters, parameters + parameterCount); auto result = script->CallFunction(key, v); return new Porygon::EvaluateResult(result); } catch (const EvaluationException& e){ return new Porygon::EvaluateResult(e.what()); } } const char * GetResultError(Porygon::EvaluateResult * result){ return result->GetError(); } const size_t GetTreeStringLength(Porygon::Script* script){ return script->GetTreeString().size(); } void GetTreeString(Porygon::Script* script, char* buffer){ auto s = script->GetTreeString(); for (size_t i = 0; i < s.size(); i++){ buffer[i] = s[i]; } } }