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>;
|
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);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
25
pilang.cpp
25
pilang.cpp
|
@ -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
|
||||||
|
|
Loading…
Add table
Reference in a new issue