summaryrefslogtreecommitdiff
path: root/functions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'functions.cpp')
-rw-r--r--functions.cpp30
1 files changed, 30 insertions, 0 deletions
diff --git a/functions.cpp b/functions.cpp
index 4795c93..9655e5a 100644
--- a/functions.cpp
+++ b/functions.cpp
@@ -1,7 +1,9 @@
#include <iostream>
#include <fstream>
#include <unordered_map>
+#include <unordered_set>
#include <vector>
+#include <stack>
#include <string>
#include <functional>
#include <unistd.h>
@@ -16,6 +18,8 @@ extern char **g_argv;
#define BUILTIN_GUARD_STACKSIZE(nm,sz) {if(S.size()<(sz))throw string("Builtin '" nm "' needs " #sz " stack item")+(sz==1?"":"s");}
+stack<unordered_set<string>> scopestack;
+
//please extern this shit with const!
unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stackitem>&)>> builtins={
{"+",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
@@ -207,6 +211,18 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack
BUILTIN_GUARD_STACKSIZE("store",2)
Stackitem name=move(S.back()); S.pop_back();
if(!name.isstr)throw string("Second argument to 'store' not a string");
+ auto it=variables.find(name.strval);
+ bool exists=it!=variables.end();
+ //insert_or_assign is C++17 sadly
+ /*if(exists)variables.insert(it,make_pair(name.strval,move(S.back())));
+ else*/ variables[name.strval]=move(S.back());
+ S.pop_back();
+ if(scopestack.size()&&!exists)scopestack.top().insert(name.strval);
+ }},
+ {"gstore",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("gstore",2)
+ Stackitem name=move(S.back()); S.pop_back();
+ if(!name.isstr)throw string("Second argument to 'store' not a string");
variables[name.strval]=move(S.back());
S.pop_back();
}},
@@ -224,6 +240,20 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack
S.push_back(move(variables[name.strval]));
variables[name.strval].intval=0;
}},
+ {"enterscope",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ //cerr<<"scope enter"<<endl;
+ scopestack.emplace();
+ }},
+ {"leavescope",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ if(scopestack.size()<1)throw string("Scope stack empty while requesting scope leave");
+ //cerr<<"scope leave: ";
+ for(const string &varname : scopestack.top()){
+ variables.erase(varname);
+ //cerr<<varname<<' ';
+ }
+ //cerr<<endl;
+ scopestack.pop();
+ }},
//positive n: roll OFF top to bottom; negative n: roll off bottom ONTO top
{"roll",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("roll",1)