diff options
author | tomsmeding <hallo@tomsmeding.nl> | 2015-09-08 19:14:27 +0200 |
---|---|---|
committer | tomsmeding <hallo@tomsmeding.nl> | 2015-09-08 19:36:44 +0200 |
commit | 03deaf70dde4181373c2c3c44e8bbb0ba6718b41 (patch) | |
tree | b76dca62c332de266da236139eb0f91ff6b5b349 /functions.cpp | |
parent | b50d606bdd0fbda3451e9fcb07e8096fa5bee55b (diff) |
make scopes ACTUALLY WORK nicely
Diffstat (limited to 'functions.cpp')
-rw-r--r-- | functions.cpp | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/functions.cpp b/functions.cpp index 9655e5a..8bd4053 100644 --- a/functions.cpp +++ b/functions.cpp @@ -1,11 +1,12 @@ #include <iostream> #include <fstream> #include <unordered_map> -#include <unordered_set> +// #include <unordered_set> #include <vector> #include <stack> #include <string> #include <functional> +#include <cmath> #include <unistd.h> #include <fcntl.h> @@ -18,7 +19,10 @@ 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; +stack<unordered_map<string,pair<Stackitem,bool>>> scopestack; +//Each stack frame contains the variables local to the stack frame. The bool is +//whether it was already present in the previous frame, and the Stackitem +//is the value held by the previous frame, if any. //please extern this shit with const! unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stackitem>&)>> builtins={ @@ -213,11 +217,17 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack if(!name.isstr)throw string("Second argument to 'store' not a string"); auto it=variables.find(name.strval); bool exists=it!=variables.end(); + if(scopestack.size()&&scopestack.top().find(name.strval)==scopestack.top().end()){ + if(exists) + scopestack.top()[name.strval]={move(variables[name.strval]),true}; + else + scopestack.top()[name.strval]={Stackitem(),false}; + } //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()); + /*if(exists)variables.insert_or_assign(it,make_pair(name.strval,move(S.back()))); + else variables[name.strval]=move(S.back());*/ + 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) @@ -241,17 +251,19 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack variables[name.strval].intval=0; }}, {"enterscope",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){ - //cerr<<"scope enter"<<endl; + BUILTIN_GUARD_STACKSIZE("enterscope",0) scopestack.emplace(); }}, {"leavescope",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){ + BUILTIN_GUARD_STACKSIZE("leavescope",0) 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<<' '; + for(const pair<string,pair<Stackitem,bool>> &var : scopestack.top()){ + if(var.second.second){ + variables[var.first]=move(var.second.first); + } else { + variables.erase(var.first); + } } - //cerr<<endl; scopestack.pop(); }}, //positive n: roll OFF top to bottom; negative n: roll off bottom ONTO top @@ -323,6 +335,12 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack S.back().intval=(int)S.back().strval[0]; S.back().strval=""; }}, + {"sleep",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){ + BUILTIN_GUARD_STACKSIZE("sleep",1) + if(S.back().isstr)throw string("Argument to 'sleep' not a number"); + usleep(S.back().intval); + S.pop_back(); + }}, {"stackdump",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){ BUILTIN_GUARD_STACKSIZE("stackdump",0) cerr<<"STACKDUMP: "; |