Support for loading variables from module with require
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
This commit is contained in:
parent
c39f3a0884
commit
641b6784c7
|
@ -630,12 +630,12 @@ namespace Porygon::Binder {
|
||||||
exp->GetLength());
|
exp->GetLength());
|
||||||
return new BoundBadExpression(exp->GetStartPosition(), exp ->GetLength());
|
return new BoundBadExpression(exp->GetStartPosition(), exp ->GetLength());
|
||||||
}
|
}
|
||||||
auto module = opt->ResolveModule(transformedKey);
|
auto module = Script::Clone(opt->ResolveModule(transformedKey));
|
||||||
if (module -> GetReturnType() == nullptr){
|
if (module -> GetReturnType() == nullptr){
|
||||||
for (const auto& v: *module->GetScriptVariables()){
|
for (const auto& v: *module->GetScriptVariables()){
|
||||||
//TODO: Currently a hack, will always make all variables nil
|
auto type = module->GetVariableType(v.first);
|
||||||
auto type = make_shared<const ScriptType>(TypeClass::Nil);
|
auto result = this -> _scope -> AssignVariable(v.first, type);
|
||||||
this -> _scope -> AssignVariable(v.first, type);
|
delete result.GetKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -737,7 +737,7 @@ namespace Porygon::Binder {
|
||||||
|
|
||||||
BoundExpression *Binder::BindTableExpression(const ParsedTableExpression *expression) {
|
BoundExpression *Binder::BindTableExpression(const ParsedTableExpression *expression) {
|
||||||
auto tableScope = new map<Utilities::HashedString, BoundVariable *>();
|
auto tableScope = new map<Utilities::HashedString, BoundVariable *>();
|
||||||
auto innerScope = new BoundScope(tableScope);
|
auto innerScope = new BoundScope(tableScope, nullptr);
|
||||||
auto currentScope = this->_scope;
|
auto currentScope = this->_scope;
|
||||||
this->_scope = innerScope;
|
this->_scope = innerScope;
|
||||||
auto block = dynamic_cast<BoundBlockStatement*>(this->BindBlockStatement(expression->GetBlock()));
|
auto block = dynamic_cast<BoundBlockStatement*>(this->BindBlockStatement(expression->GetBlock()));
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
#include "../../StandardLibraries/StaticScope.hpp"
|
#include "../../StandardLibraries/StaticScope.hpp"
|
||||||
|
|
||||||
namespace Porygon::Binder {
|
namespace Porygon::Binder {
|
||||||
BoundScope::BoundScope(map<Utilities::HashedString, BoundVariable *> *tableScope) {
|
BoundScope::BoundScope(map<Utilities::HashedString, BoundVariable *> *tableScope,
|
||||||
|
unordered_map<Utilities::HashedString, shared_ptr<const ScriptType>>* tableVariableTypes) {
|
||||||
_tableScope = tableScope;
|
_tableScope = tableScope;
|
||||||
|
_tableVariableTypes = tableVariableTypes;
|
||||||
_currentScope = 1;
|
_currentScope = 1;
|
||||||
_lastCreatedScope = 1;
|
_lastCreatedScope = 1;
|
||||||
auto localUpmostScope = new map<Utilities::HashedString, BoundVariable *>();
|
auto localUpmostScope = new map<Utilities::HashedString, BoundVariable *>();
|
||||||
|
@ -92,6 +94,9 @@ namespace Porygon::Binder {
|
||||||
if (exists < 0) {
|
if (exists < 0) {
|
||||||
// Creation
|
// Creation
|
||||||
_tableScope->insert({identifier, new BoundVariable(type)});
|
_tableScope->insert({identifier, new BoundVariable(type)});
|
||||||
|
if (_tableVariableTypes != nullptr){
|
||||||
|
_tableVariableTypes->insert({identifier, type});
|
||||||
|
}
|
||||||
return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, 0, true));
|
return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, 0, true));
|
||||||
} else {
|
} else {
|
||||||
// Assigning
|
// Assigning
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "BoundVariable.hpp"
|
#include "BoundVariable.hpp"
|
||||||
|
@ -16,11 +17,13 @@ using namespace std;
|
||||||
namespace Porygon::Binder {
|
namespace Porygon::Binder {
|
||||||
class BoundScope {
|
class BoundScope {
|
||||||
map<Utilities::HashedString, BoundVariable *> *_tableScope;
|
map<Utilities::HashedString, BoundVariable *> *_tableScope;
|
||||||
|
unordered_map<Utilities::HashedString, shared_ptr<const ScriptType>> * _tableVariableTypes;
|
||||||
vector<map<Utilities::HashedString, BoundVariable *> *> _localScope;
|
vector<map<Utilities::HashedString, BoundVariable *> *> _localScope;
|
||||||
int _currentScope;
|
int _currentScope;
|
||||||
int _lastCreatedScope;
|
int _lastCreatedScope;
|
||||||
public:
|
public:
|
||||||
explicit BoundScope(map<Utilities::HashedString, BoundVariable *> *tableScope);
|
explicit BoundScope(map<Utilities::HashedString, BoundVariable *> *tableScope,
|
||||||
|
unordered_map<Utilities::HashedString, shared_ptr<const ScriptType>>* tableVariableTypes);
|
||||||
|
|
||||||
~BoundScope();
|
~BoundScope();
|
||||||
|
|
||||||
|
|
|
@ -402,13 +402,14 @@ namespace Porygon::Evaluation {
|
||||||
|
|
||||||
EvalValuePointer Evaluator::EvaluateRequireExpression(const BoundExpression* expression) {
|
EvalValuePointer Evaluator::EvaluateRequireExpression(const BoundExpression* expression) {
|
||||||
auto module = dynamic_cast<const BoundRequireExpression*>(expression)->GetModule();
|
auto module = dynamic_cast<const BoundRequireExpression*>(expression)->GetModule();
|
||||||
|
auto result = module->Evaluate();
|
||||||
if (module ->GetReturnType() == nullptr){
|
if (module ->GetReturnType() == nullptr){
|
||||||
for (const auto& v: *module->GetScriptVariables()){
|
for (const auto& v: *module->GetScriptVariables()){
|
||||||
this->_scriptVariables->insert({v.first, v.second.Clone()});
|
this->_scriptVariables->at(v.first) = v.second.Clone();
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else{
|
} else{
|
||||||
return module -> Evaluate().Take();
|
return result.Take();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iterator>
|
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
#include "Script.hpp"
|
#include "Script.hpp"
|
||||||
|
@ -26,6 +25,7 @@ Porygon::Script::Script(const u16string& s)
|
||||||
: Diagnostics(make_shared<Diagnostics::DiagnosticsHolder>(s)),
|
: Diagnostics(make_shared<Diagnostics::DiagnosticsHolder>(s)),
|
||||||
_boundScript(nullptr),
|
_boundScript(nullptr),
|
||||||
_scriptVariables(new map<Utilities::HashedString, EvalValuePointer>()),
|
_scriptVariables(new map<Utilities::HashedString, EvalValuePointer>()),
|
||||||
|
_scriptTypes(new unordered_map<Utilities::HashedString, shared_ptr<ScriptType>>{}),
|
||||||
_scriptOptions(nullptr)
|
_scriptOptions(nullptr)
|
||||||
{
|
{
|
||||||
_evaluator = new Evaluator(this -> _scriptVariables, this -> GetScriptOptions());
|
_evaluator = new Evaluator(this -> _scriptVariables, this -> GetScriptOptions());
|
||||||
|
@ -40,6 +40,8 @@ Porygon::Script::~Script() {
|
||||||
delete this -> _evaluator;
|
delete this -> _evaluator;
|
||||||
this->_scriptVariables->clear();
|
this->_scriptVariables->clear();
|
||||||
delete this->_scriptVariables;
|
delete this->_scriptVariables;
|
||||||
|
this->_scriptTypes->clear();
|
||||||
|
delete this->_scriptTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Porygon::Script::Parse(const u16string& script) {
|
void Porygon::Script::Parse(const u16string& script) {
|
||||||
|
@ -53,13 +55,18 @@ void Porygon::Script::Parse(const u16string& script) {
|
||||||
lexResult.clear();
|
lexResult.clear();
|
||||||
if (!Diagnostics->HasErrors()){
|
if (!Diagnostics->HasErrors()){
|
||||||
map<Utilities::HashedString, BoundVariable*> scriptScope;
|
map<Utilities::HashedString, BoundVariable*> scriptScope;
|
||||||
auto bindScope = new BoundScope(&scriptScope);
|
unordered_map<Utilities::HashedString, shared_ptr<const ScriptType>> variableTypes;
|
||||||
|
auto bindScope = new BoundScope(&scriptScope, &variableTypes);
|
||||||
this->_boundScript = shared_ptr<BoundScriptStatement>(Binder::Binder::Bind(this, parseResult, bindScope));
|
this->_boundScript = shared_ptr<BoundScriptStatement>(Binder::Binder::Bind(this, parseResult, bindScope));
|
||||||
for (const auto& v : scriptScope){
|
for (const auto& v : scriptScope){
|
||||||
this->_scriptVariables -> insert({v.first, nullptr});
|
this->_scriptVariables -> insert({v.first, nullptr});
|
||||||
delete v.second;
|
delete v.second;
|
||||||
}
|
}
|
||||||
|
for (const auto& v : variableTypes){
|
||||||
|
this->_scriptTypes -> insert({v.first, nullptr});
|
||||||
|
}
|
||||||
scriptScope.clear();
|
scriptScope.clear();
|
||||||
|
variableTypes.clear();
|
||||||
}
|
}
|
||||||
delete parseResult;
|
delete parseResult;
|
||||||
}
|
}
|
||||||
|
@ -73,10 +80,6 @@ bool Porygon::Script::HasVariable(const u16string &key) {
|
||||||
return f != _scriptVariables->end();
|
return f != _scriptVariables->end();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*const EvalValue *Porygon::Script::GetLastValue() {
|
|
||||||
return _evaluator->GetLastValue();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
bool Porygon::Script::HasFunction(const u16string &key) {
|
bool Porygon::Script::HasFunction(const u16string &key) {
|
||||||
auto f = _scriptVariables->find(HashedString::CreateLookup(key));
|
auto f = _scriptVariables->find(HashedString::CreateLookup(key));
|
||||||
return f != _scriptVariables->end() && f.operator->()->second->GetTypeClass() == TypeClass ::Function;
|
return f != _scriptVariables->end() && f.operator->()->second->GetTypeClass() == TypeClass ::Function;
|
||||||
|
@ -89,9 +92,13 @@ const EvalValue* Porygon::Script::CallFunction(const u16string &key, const vecto
|
||||||
|
|
||||||
Porygon::Script *Porygon::Script::Clone(const Porygon::Script *script) {
|
Porygon::Script *Porygon::Script::Clone(const Porygon::Script *script) {
|
||||||
auto s = new Script(script->_boundScript, script->Diagnostics);
|
auto s = new Script(script->_boundScript, script->Diagnostics);
|
||||||
for (auto v: *script->_scriptVariables){
|
for (const auto& v: *script->_scriptVariables){
|
||||||
s->_scriptVariables->insert({v.first, nullptr});
|
s->_scriptVariables->insert({v.first, nullptr});
|
||||||
}
|
}
|
||||||
|
for (const auto& v: *script->_scriptTypes){
|
||||||
|
s->_scriptTypes->insert({v.first, v.second});
|
||||||
|
}
|
||||||
|
|
||||||
s->_returnType = script->_returnType;
|
s->_returnType = script->_returnType;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
@ -101,6 +108,7 @@ Porygon::Script::Script(shared_ptr<BoundScriptStatement> boundScript,
|
||||||
: _boundScript(std::move(boundScript)),
|
: _boundScript(std::move(boundScript)),
|
||||||
Diagnostics(std::move(diagnostics)),
|
Diagnostics(std::move(diagnostics)),
|
||||||
_scriptVariables(new map<Utilities::HashedString, EvalValuePointer>()),
|
_scriptVariables(new map<Utilities::HashedString, EvalValuePointer>()),
|
||||||
|
_scriptTypes(new unordered_map<Utilities::HashedString, shared_ptr<ScriptType>>{}),
|
||||||
_scriptOptions(nullptr)
|
_scriptOptions(nullptr)
|
||||||
{
|
{
|
||||||
_evaluator = new Evaluator(_scriptVariables, this -> GetScriptOptions());
|
_evaluator = new Evaluator(_scriptVariables, this -> GetScriptOptions());
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace Porygon{
|
||||||
class Script {
|
class Script {
|
||||||
Evaluator* _evaluator;
|
Evaluator* _evaluator;
|
||||||
map<Utilities::HashedString, EvalValuePointer>* _scriptVariables;
|
map<Utilities::HashedString, EvalValuePointer>* _scriptVariables;
|
||||||
|
unordered_map<Utilities::HashedString, shared_ptr<ScriptType>>* _scriptTypes;
|
||||||
shared_ptr<Binder::BoundScriptStatement> _boundScript;
|
shared_ptr<Binder::BoundScriptStatement> _boundScript;
|
||||||
shared_ptr<const ScriptType> _returnType = nullptr;
|
shared_ptr<const ScriptType> _returnType = nullptr;
|
||||||
ScriptOptions* _scriptOptions;
|
ScriptOptions* _scriptOptions;
|
||||||
|
@ -54,6 +55,9 @@ namespace Porygon{
|
||||||
|
|
||||||
const EvalValue* GetVariable(const u16string& key);
|
const EvalValue* GetVariable(const u16string& key);
|
||||||
bool HasVariable(const u16string& key);
|
bool HasVariable(const u16string& key);
|
||||||
|
shared_ptr<const ScriptType> GetVariableType(const Utilities::HashedString& key){
|
||||||
|
return _scriptTypes->at(key);
|
||||||
|
}
|
||||||
|
|
||||||
const EvalValue* CallFunction(const u16string& key, const vector<EvalValue*>& variables);
|
const EvalValue* CallFunction(const u16string& key, const vector<EvalValue*>& variables);
|
||||||
bool HasFunction(const u16string& key);
|
bool HasFunction(const u16string& key);
|
||||||
|
|
|
@ -63,9 +63,20 @@ namespace Porygon::Utilities{
|
||||||
inline bool operator>(const HashedString& b) const{
|
inline bool operator>(const HashedString& b) const{
|
||||||
return _hash > b._hash;
|
return _hash > b._hash;
|
||||||
}
|
}
|
||||||
|
std::size_t operator()(const HashedString& k) const {
|
||||||
|
return _hash;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template <>
|
||||||
|
struct hash<Porygon::Utilities::HashedString> {
|
||||||
|
std::size_t operator()(const Porygon::Utilities::HashedString& k) const{
|
||||||
|
return k.GetHash();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif //PORYGONLANG_HASHEDSTRING_HPP
|
#endif //PORYGONLANG_HASHEDSTRING_HPP
|
||||||
|
|
|
@ -4,20 +4,32 @@
|
||||||
using namespace Porygon;
|
using namespace Porygon;
|
||||||
|
|
||||||
class ModuleHandler{
|
class ModuleHandler{
|
||||||
static unordered_map<string, Script*> MODULES;
|
class Internal{
|
||||||
|
public:
|
||||||
|
unordered_map<string, Script*> MODULES;
|
||||||
|
|
||||||
~ModuleHandler(){
|
Internal(){
|
||||||
for (auto v: MODULES){
|
MODULES = {
|
||||||
|
{"simple_return", Script::Create(u"return 500")},
|
||||||
|
{"simple_variables", Script::Create(u"foo = 50\nbar = \'test\'")}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
~Internal(){
|
||||||
|
for (const auto& v: MODULES){
|
||||||
delete v.second;
|
delete v.second;
|
||||||
}
|
}
|
||||||
|
MODULES.clear();
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
static Internal _internal;
|
||||||
|
|
||||||
inline static bool DoesModuleExist(const string& moduleName){
|
inline static bool DoesModuleExist(const string& moduleName){
|
||||||
return MODULES.find(moduleName) != MODULES.end();
|
return _internal.MODULES.find(moduleName) != _internal.MODULES.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static Script* ResolveModule(const string& moduleName){
|
inline static Script* ResolveModule(const string& moduleName){
|
||||||
return MODULES[moduleName];
|
return _internal.MODULES[moduleName];
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -27,9 +39,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
unordered_map<string, Script*> ModuleHandler::MODULES = unordered_map<string, Script*>{
|
ModuleHandler::Internal ModuleHandler::_internal;
|
||||||
{"simple_return", Script::Create(u"return 500")}
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_CASE( "Require simple return script", "[integration]" ) {
|
TEST_CASE( "Require simple return script", "[integration]" ) {
|
||||||
ModuleHandler::Initialize();
|
ModuleHandler::Initialize();
|
||||||
|
@ -42,4 +52,23 @@ return require("simple_return")
|
||||||
delete script;
|
delete script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "Require simple variables script", "[integration]" ) {
|
||||||
|
ModuleHandler::Initialize();
|
||||||
|
auto script = Script::Create(uR"(
|
||||||
|
require("simple_variables")
|
||||||
|
)");
|
||||||
|
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||||
|
script->Evaluate();
|
||||||
|
REQUIRE(script->HasVariable(u"foo"));
|
||||||
|
REQUIRE(script->HasVariable(u"bar"));
|
||||||
|
auto foo = script->GetVariable(u"foo");
|
||||||
|
auto bar = script->GetVariable(u"bar");
|
||||||
|
CHECK(foo->EvaluateInteger() == 50);
|
||||||
|
CHECK(bar->EvaluateString() == u"test");
|
||||||
|
|
||||||
|
delete foo;
|
||||||
|
delete bar;
|
||||||
|
delete script;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue