summaryrefslogtreecommitdiff
path: root/functions.cpp
diff options
context:
space:
mode:
authortomsmeding <hallo@tomsmeding.nl>2015-09-08 19:14:27 +0200
committertomsmeding <hallo@tomsmeding.nl>2015-09-08 19:36:44 +0200
commit03deaf70dde4181373c2c3c44e8bbb0ba6718b41 (patch)
treeb76dca62c332de266da236139eb0f91ff6b5b349 /functions.cpp
parentb50d606bdd0fbda3451e9fcb07e8096fa5bee55b (diff)
make scopes ACTUALLY WORK nicely
Diffstat (limited to 'functions.cpp')
-rw-r--r--functions.cpp40
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: ";