2019-06-05 16:44:23 +00:00
|
|
|
#include <utility>
|
2019-06-07 11:51:49 +00:00
|
|
|
#include <vector>
|
2019-06-15 15:20:27 +00:00
|
|
|
#include <locale>
|
|
|
|
#include <codecvt>
|
2019-05-21 10:59:15 +00:00
|
|
|
#include "Script.hpp"
|
2019-05-21 11:56:08 +00:00
|
|
|
#include "Parser/Lexer.hpp"
|
|
|
|
#include "Parser/Parser.hpp"
|
2019-05-21 18:59:26 +00:00
|
|
|
#include "Binder/Binder.hpp"
|
2019-07-27 17:45:15 +00:00
|
|
|
#include "EvaluateResult.hpp"
|
2019-05-21 10:59:15 +00:00
|
|
|
|
2019-07-04 17:31:52 +00:00
|
|
|
Porygon::Script* Porygon::Script::Create(const u16string& script) {
|
2019-06-18 15:14:18 +00:00
|
|
|
return new Script(script);
|
2019-05-21 10:59:15 +00:00
|
|
|
}
|
|
|
|
|
2019-06-15 15:20:27 +00:00
|
|
|
std::u16string To_UTF16(const string &s)
|
|
|
|
{
|
|
|
|
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> conv;
|
|
|
|
return conv.from_bytes(s);
|
|
|
|
}
|
2019-07-04 17:18:03 +00:00
|
|
|
Porygon::Script *Porygon::Script::Create(const string &script) {
|
2019-06-15 15:20:27 +00:00
|
|
|
return Script::Create(To_UTF16(script));
|
|
|
|
}
|
|
|
|
|
2019-07-04 16:24:49 +00:00
|
|
|
Porygon::Script::Script(const u16string& s)
|
|
|
|
: Diagnostics(make_shared<Diagnostics::DiagnosticsHolder>(s)),
|
|
|
|
_boundScript(nullptr),
|
2019-08-10 09:55:45 +00:00
|
|
|
_scriptVariables(new map<Utilities::HashedString, EvalValuePointer>()),
|
2019-08-11 10:32:18 +00:00
|
|
|
_scriptTypes(new unordered_map<Utilities::HashedString, shared_ptr<ScriptType>>{}),
|
2019-08-10 09:55:45 +00:00
|
|
|
_scriptOptions(nullptr)
|
2019-07-04 16:24:49 +00:00
|
|
|
{
|
2019-08-10 09:55:45 +00:00
|
|
|
_evaluator = new Evaluator(this -> _scriptVariables, this -> GetScriptOptions());
|
2019-06-18 15:14:18 +00:00
|
|
|
this -> Parse(s);
|
2019-05-23 16:50:09 +00:00
|
|
|
}
|
|
|
|
|
2019-07-27 15:59:42 +00:00
|
|
|
EvalValuePointer Porygon::Script::Evaluate() {
|
2019-06-24 13:33:29 +00:00
|
|
|
return _evaluator->Evaluate(_boundScript.get());
|
2019-05-23 16:50:09 +00:00
|
|
|
}
|
|
|
|
|
2019-06-17 16:35:12 +00:00
|
|
|
Porygon::Script::~Script() {
|
2019-05-24 17:14:30 +00:00
|
|
|
delete this -> _evaluator;
|
2019-05-29 12:55:03 +00:00
|
|
|
this->_scriptVariables->clear();
|
|
|
|
delete this->_scriptVariables;
|
2019-08-11 10:32:18 +00:00
|
|
|
this->_scriptTypes->clear();
|
|
|
|
delete this->_scriptTypes;
|
2019-05-21 12:15:39 +00:00
|
|
|
}
|
|
|
|
|
2019-06-17 16:35:12 +00:00
|
|
|
void Porygon::Script::Parse(const u16string& script) {
|
2019-06-13 15:37:23 +00:00
|
|
|
auto lexer = Lexer(script, this);
|
2019-05-21 10:59:15 +00:00
|
|
|
auto lexResult = lexer.Lex();
|
2019-06-17 16:35:12 +00:00
|
|
|
auto parser = Parser::Parser(lexResult, this);
|
2019-05-21 10:59:15 +00:00
|
|
|
auto parseResult = parser.Parse();
|
|
|
|
for (auto token : lexResult){
|
|
|
|
delete token;
|
|
|
|
}
|
|
|
|
lexResult.clear();
|
2019-05-21 18:59:26 +00:00
|
|
|
if (!Diagnostics->HasErrors()){
|
2019-06-23 13:58:14 +00:00
|
|
|
map<Utilities::HashedString, BoundVariable*> scriptScope;
|
2019-08-11 10:32:18 +00:00
|
|
|
unordered_map<Utilities::HashedString, shared_ptr<const ScriptType>> variableTypes;
|
|
|
|
auto bindScope = new BoundScope(&scriptScope, &variableTypes);
|
2019-06-24 13:33:29 +00:00
|
|
|
this->_boundScript = shared_ptr<BoundScriptStatement>(Binder::Binder::Bind(this, parseResult, bindScope));
|
2019-05-28 15:49:03 +00:00
|
|
|
for (const auto& v : scriptScope){
|
2019-05-29 12:55:03 +00:00
|
|
|
this->_scriptVariables -> insert({v.first, nullptr});
|
2019-05-28 15:49:03 +00:00
|
|
|
delete v.second;
|
|
|
|
}
|
2019-08-11 10:32:18 +00:00
|
|
|
for (const auto& v : variableTypes){
|
|
|
|
this->_scriptTypes -> insert({v.first, nullptr});
|
|
|
|
}
|
2019-05-28 15:49:03 +00:00
|
|
|
scriptScope.clear();
|
2019-08-11 10:32:18 +00:00
|
|
|
variableTypes.clear();
|
2019-05-21 18:59:26 +00:00
|
|
|
}
|
|
|
|
delete parseResult;
|
2019-05-21 10:59:15 +00:00
|
|
|
}
|
2019-05-21 12:15:39 +00:00
|
|
|
|
2019-07-27 15:59:42 +00:00
|
|
|
const EvalValue* Porygon::Script::GetVariable(const u16string &key) {
|
|
|
|
return _scriptVariables -> at(HashedString::CreateLookup(key)).Clone();
|
2019-05-29 13:10:16 +00:00
|
|
|
}
|
|
|
|
|
2019-06-17 16:35:12 +00:00
|
|
|
bool Porygon::Script::HasVariable(const u16string &key) {
|
2019-06-25 13:18:36 +00:00
|
|
|
auto f = _scriptVariables->find(HashedString::CreateLookup(key));
|
2019-05-29 13:10:16 +00:00
|
|
|
return f != _scriptVariables->end();
|
|
|
|
}
|
|
|
|
|
2019-06-17 16:35:12 +00:00
|
|
|
bool Porygon::Script::HasFunction(const u16string &key) {
|
2019-06-25 13:18:36 +00:00
|
|
|
auto f = _scriptVariables->find(HashedString::CreateLookup(key));
|
2019-06-13 14:26:10 +00:00
|
|
|
return f != _scriptVariables->end() && f.operator->()->second->GetTypeClass() == TypeClass ::Function;
|
2019-06-05 16:44:23 +00:00
|
|
|
}
|
|
|
|
|
2019-07-27 15:59:42 +00:00
|
|
|
const EvalValue* Porygon::Script::CallFunction(const u16string &key, const vector<EvalValue *>& variables) {
|
2019-06-29 17:59:42 +00:00
|
|
|
auto var = (GenericFunctionEvalValue*)GetVariable(key);
|
2019-06-14 20:21:33 +00:00
|
|
|
return this->_evaluator->EvaluateFunction(var, variables);
|
2019-06-05 16:44:23 +00:00
|
|
|
}
|
|
|
|
|
2019-06-24 13:33:29 +00:00
|
|
|
Porygon::Script *Porygon::Script::Clone(const Porygon::Script *script) {
|
|
|
|
auto s = new Script(script->_boundScript, script->Diagnostics);
|
2019-08-11 10:32:18 +00:00
|
|
|
for (const auto& v: *script->_scriptVariables){
|
2019-06-24 13:33:29 +00:00
|
|
|
s->_scriptVariables->insert({v.first, nullptr});
|
|
|
|
}
|
2019-08-11 10:32:18 +00:00
|
|
|
for (const auto& v: *script->_scriptTypes){
|
|
|
|
s->_scriptTypes->insert({v.first, v.second});
|
|
|
|
}
|
|
|
|
|
2019-06-24 13:33:29 +00:00
|
|
|
s->_returnType = script->_returnType;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
Porygon::Script::Script(shared_ptr<BoundScriptStatement> boundScript,
|
2019-07-04 16:24:49 +00:00
|
|
|
shared_ptr<Porygon::Diagnostics::DiagnosticsHolder> diagnostics)
|
|
|
|
: _boundScript(std::move(boundScript)),
|
|
|
|
Diagnostics(std::move(diagnostics)),
|
2019-08-10 09:55:45 +00:00
|
|
|
_scriptVariables(new map<Utilities::HashedString, EvalValuePointer>()),
|
2019-08-11 10:32:18 +00:00
|
|
|
_scriptTypes(new unordered_map<Utilities::HashedString, shared_ptr<ScriptType>>{}),
|
2019-08-10 09:55:45 +00:00
|
|
|
_scriptOptions(nullptr)
|
2019-07-04 16:24:49 +00:00
|
|
|
{
|
2019-08-10 09:55:45 +00:00
|
|
|
_evaluator = new Evaluator(_scriptVariables, this -> GetScriptOptions());
|
2019-06-24 13:33:29 +00:00
|
|
|
}
|
|
|
|
|
2019-06-05 15:46:46 +00:00
|
|
|
extern "C" {
|
2019-06-17 16:35:12 +00:00
|
|
|
Porygon::Script* CreateScript(char16_t * s){
|
|
|
|
return Porygon::Script::Create(s);
|
2019-06-05 15:46:46 +00:00
|
|
|
}
|
|
|
|
|
2019-07-27 17:45:15 +00:00
|
|
|
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());
|
|
|
|
}
|
2019-06-05 15:46:46 +00:00
|
|
|
}
|
|
|
|
|
2019-06-17 16:35:12 +00:00
|
|
|
bool HasVariable(Porygon::Script* script, const char16_t* key){
|
2019-06-05 15:46:46 +00:00
|
|
|
return script->HasVariable(key);
|
|
|
|
}
|
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
const EvalValue* GetVariable(Porygon::Script* script, const char16_t* key){
|
2019-06-05 15:46:46 +00:00
|
|
|
return script->GetVariable(key);
|
|
|
|
}
|
2019-06-07 11:51:49 +00:00
|
|
|
|
2019-06-17 16:35:12 +00:00
|
|
|
bool HasFunction(Porygon::Script* script, const char16_t* key){
|
2019-06-07 11:51:49 +00:00
|
|
|
return script->HasFunction(key);
|
|
|
|
}
|
|
|
|
|
2019-07-27 17:45:15 +00:00
|
|
|
Porygon::EvaluateResult* CallFunction(Porygon::Script* script, const char16_t* key, EvalValue* parameters[], int parameterCount){
|
|
|
|
try{
|
|
|
|
std::vector<EvalValue*> 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();
|
2019-06-07 11:51:49 +00:00
|
|
|
}
|
2019-06-17 16:35:12 +00:00
|
|
|
}
|