diff options
-rw-r--r-- | bf.prn | 2 | ||||
-rw-r--r-- | functions.cpp | 30 | ||||
-rw-r--r-- | runtime.cpp | 2 |
3 files changed, 33 insertions, 1 deletions
@@ -80,7 +80,7 @@ dup 0 > while c ">" = if -1 roll end c "<" = if 1 roll end c "]" = if - i "loopend" depth 1 - + store + i "loopend" depth 1 - + gstore len "i" store # == break end c "[" = if 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) diff --git a/runtime.cpp b/runtime.cpp index 63e0b52..3cf607d 100644 --- a/runtime.cpp +++ b/runtime.cpp @@ -129,7 +129,9 @@ void runpasseval(const vector<string> &T, } else { auto it=functions.find(word); if(it!=functions.end()){ + builtins.find("enterscope")->second(S,variables); runpasseval(it->second.first,S,functions,variables,it->second.second); + builtins.find("leavescope")->second(S,variables); } else { if(word=="while"){ if(S.size()<1)throw string("Keyword 'while' needs 1 stack item"); |