summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <hallo@tomsmeding.nl>2015-09-06 22:18:30 +0200
committertomsmeding <hallo@tomsmeding.nl>2015-09-06 22:18:30 +0200
commitb50d606bdd0fbda3451e9fcb07e8096fa5bee55b (patch)
treeb323b11157acdd52c6a7ba61b3036e82b0a57381
parent61dc84ab5ae95b3fa6bbbdcadf880f8ec64a925f (diff)
Add scopes!
-rw-r--r--bf.prn2
-rw-r--r--functions.cpp30
-rw-r--r--runtime.cpp2
3 files changed, 33 insertions, 1 deletions
diff --git a/bf.prn b/bf.prn
index acaa6c1..19d1368 100644
--- a/bf.prn
+++ b/bf.prn
@@ -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");