mirror of
https://gitlab.com/niansa/pilang3.git
synced 2025-03-06 20:49:20 +01:00
Advanced scoping
This commit is contained in:
parent
d185ff9b20
commit
ba4f67517c
3 changed files with 36 additions and 10 deletions
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
};
|
||||
|
|
25
pilang.cpp
25
pilang.cpp
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue