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

View file

@ -18,9 +18,25 @@ public:
}
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]);
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) {
std::ostringstream fres;
@ -43,6 +59,8 @@ public:
builtinCmds["exit"] = {exit, {Variable::id_integer}, false};
builtinCmds["return"] = {retval, {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};
}
};

View file

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