diff --git a/include/pilang.hpp b/include/pilang.hpp index f4a4bf0..b66a44a 100644 --- a/include/pilang.hpp +++ b/include/pilang.hpp @@ -61,10 +61,12 @@ namespace Pilang3 { using Scope = std::unordered_map; std::stack variableScope; + Scope *globalScope; void *anybuf = nullptr; Environment() { variableScope.push({}); + globalScope = &variableScope.top(); } Scope &currScope() { @@ -89,6 +91,7 @@ namespace Pilang3 { public: std::vector evalChain; std::vector argumentNames; + bool new_scope = false; Variable execute(SharedEnvironment env, Cmdargs& args); }; diff --git a/modules/std.cpp b/modules/std.cpp index f14b6e0..1bfce77 100644 --- a/modules/std.cpp +++ b/modules/std.cpp @@ -18,9 +18,25 @@ public: } static Variable set(SharedEnvironment env, Cmdargs& args) { + auto varName = std::get(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(args[1]); + } + return args[1]; + } + static Variable local(SharedEnvironment env, Cmdargs& args) { env->currScope()[std::get(args[0].data)] = std::make_shared(args[1]); return args[1]; } + static Variable global(SharedEnvironment env, Cmdargs& args) { + (*env->globalScope)[std::get(args[0].data)] = std::make_shared(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}; } }; diff --git a/pilang.cpp b/pilang.cpp index 4919cd3..42c1e2a 100644 --- a/pilang.cpp +++ b/pilang.cpp @@ -151,11 +151,14 @@ namespace Pilang3 { case Variable::id_function: { auto thisfunc = std::make_shared(); 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(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(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(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