1
0
Fork 0
mirror of https://gitlab.com/niansa/pilang3.git synced 2025-03-06 20:49:20 +01:00

Advanced scoping

This commit is contained in:
niansa 2021-02-14 20:57:15 +01:00
parent d185ff9b20
commit ba4f67517c
3 changed files with 36 additions and 10 deletions

View file

@ -61,10 +61,12 @@ namespace Pilang3 {
using Scope = std::unordered_map<std::string, SharedVariable>; using Scope = std::unordered_map<std::string, SharedVariable>;
std::stack<Scope> variableScope; std::stack<Scope> variableScope;
Scope *globalScope;
void *anybuf = nullptr; void *anybuf = nullptr;
Environment() { Environment() {
variableScope.push({}); variableScope.push({});
globalScope = &variableScope.top();
} }
Scope &currScope() { Scope &currScope() {
@ -89,6 +91,7 @@ namespace Pilang3 {
public: public:
std::vector<SharedEvaluation> evalChain; std::vector<SharedEvaluation> evalChain;
std::vector<std::string> argumentNames; std::vector<std::string> argumentNames;
bool new_scope = false;
Variable execute(SharedEnvironment env, Cmdargs& args); Variable execute(SharedEnvironment env, Cmdargs& args);
}; };

View file

@ -18,9 +18,25 @@ public:
} }
static Variable set(SharedEnvironment env, Cmdargs& args) { static Variable set(SharedEnvironment env, Cmdargs& args) {
auto varName = std::get<std::string>(args[0].data);
auto& scope = env->currScope();
auto res = scope.find(varName);
if (res != scope.end()) {
*res->second = args[1];
} else {
scope[varName] = std::make_shared<Variable>(args[1]);
}
return args[1];
}
static Variable local(SharedEnvironment env, Cmdargs& args) {
env->currScope()[std::get<std::string>(args[0].data)] = std::make_shared<Variable>(args[1]); env->currScope()[std::get<std::string>(args[0].data)] = std::make_shared<Variable>(args[1]);
return args[1]; return args[1];
} }
static Variable global(SharedEnvironment env, Cmdargs& args) {
(*env->globalScope)[std::get<std::string>(args[0].data)] = std::make_shared<Variable>(args[1]);
return args[1];
}
static Variable concat(SharedEnvironment, Cmdargs& args) { static Variable concat(SharedEnvironment, Cmdargs& args) {
std::ostringstream fres; std::ostringstream fres;
@ -43,6 +59,8 @@ public:
builtinCmds["exit"] = {exit, {Variable::id_integer}, false}; builtinCmds["exit"] = {exit, {Variable::id_integer}, false};
builtinCmds["return"] = {retval, {Variable::id_any}, false}; builtinCmds["return"] = {retval, {Variable::id_any}, false};
builtinCmds["="] = builtinCmds["set"] = {set, {Variable::id_string, Variable::id_any}, false}; builtinCmds["="] = builtinCmds["set"] = {set, {Variable::id_string, Variable::id_any}, false};
builtinCmds[":="] = builtinCmds["local"] = {local, {Variable::id_string, Variable::id_any}, false};
builtinCmds["!="] = builtinCmds["global"] = {global, {Variable::id_string, Variable::id_any}, false};
builtinCmds["concat"] = {concat, {}, true}; builtinCmds["concat"] = {concat, {}, true};
} }
}; };

View file

@ -151,11 +151,14 @@ namespace Pilang3 {
case Variable::id_function: { case Variable::id_function: {
auto thisfunc = std::make_shared<Function>(); auto thisfunc = std::make_shared<Function>();
if (character == '(') { if (character == '(') {
thisfunc->new_scope = true;
// Parse // Parse
while (++characterit != expression.end()) { while (++characterit != expression.end()) {
if (*characterit == ',' or *characterit == ')') { if (*characterit == ',' or *characterit == ')') {
thisfunc->argumentNames.push_back(cache); if (not cache.empty()) {
cache.clear(); thisfunc->argumentNames.push_back(cache);
cache.clear();
}
if (*characterit == ')') { if (*characterit == ')') {
break; break;
} else { } else {
@ -315,25 +318,27 @@ namespace Pilang3 {
// Go on // Go on
Variable fres; Variable fres;
// Apply arguments to new scope // Apply arguments to new scope
auto scope = env->currScope(); if (new_scope) {
scope.reserve(args.size()); auto scope = env->currScope();
for (auto args_idx = args.size(); args_idx != 0; args_idx--) { scope.reserve(args.size());
scope[argumentNames[args_idx - 1]] = std::make_shared<Variable>(args[args_idx - 1]); for (auto args_idx = args.size(); args_idx != 0; args_idx--) {
scope[argumentNames[args_idx - 1]] = std::make_shared<Variable>(args[args_idx - 1]);
}
env->variableScope.push(std::move(scope)); // Start new scope
} }
env->variableScope.push(scope); // Start new scope
// Copy, derefer and execute all evaluations // Copy, derefer and execute all evaluations
for (auto& evaluation : evalChain) { for (auto& evaluation : evalChain) {
auto thiseval = Evaluation(*evaluation); auto thiseval = Evaluation(*evaluation);
thiseval.derefer(env); thiseval.derefer(env);
fres = thiseval.execute(env); fres = thiseval.execute(env);
// Return on return // Return on return
if (fres.type == Variable::id_retval) { if (fres.type == Variable::id_retval and new_scope) {
auto fresdata = std::get<SharedVariable>(fres.data); auto fresdata = std::get<SharedVariable>(fres.data);
env->variableScope.pop(); // End scope if (new_scope) env->variableScope.pop(); // End scope
return *fresdata; return *fresdata;
} }
} }
env->variableScope.pop(); // End scope if (new_scope) env->variableScope.pop(); // End scope
return Variable({ return Variable({
Variable::id_null, Variable::id_null,
0 0