summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <hallo@tomsmeding.nl>2015-09-10 15:51:19 +0200
committertomsmeding <hallo@tomsmeding.nl>2015-09-10 15:51:19 +0200
commit38921ae6d41c8e50676aa8b01eaf701939d64573 (patch)
tree35367b78f9b3266caae57d50b92f5551e1040145
parent22b84da031e21041a15584a8982c4c4c7b7f68ff (diff)
parent74151599d4107055c6d8ecef05ad9cbd6b2045bb (diff)
Merge branch 'master' into tetris
merge array stuff into tetris
-rw-r--r--arrays.prn13
-rw-r--r--functions.cpp233
-rw-r--r--postrun.cpp6
-rw-r--r--runtime.cpp68
-rw-r--r--runtime.h24
5 files changed, 267 insertions, 77 deletions
diff --git a/arrays.prn b/arrays.prn
new file mode 100644
index 0000000..2dc7d43
--- /dev/null
+++ b/arrays.prn
@@ -0,0 +1,13 @@
+mkarray
+1 "i" store
+i 11 < while
+ i +
+ i 1 + "i" store
+i 11 < end
+stackdump
+0 "i" store
+i 10 < while
+ "Array index " i + ": " + print
+ i arridx print lf
+ i 1 + "i" store
+i 10 < end
diff --git a/functions.cpp b/functions.cpp
index 7a6ce36..261405e 100644
--- a/functions.cpp
+++ b/functions.cpp
@@ -7,6 +7,7 @@
#include <string>
#include <functional>
#include <cmath>
+#include <cassert>
#include <unistd.h>
#include <fcntl.h>
@@ -30,81 +31,107 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack
BUILTIN_GUARD_STACKSIZE("+",2)
Stackitem b=move(S.back()); S.pop_back();
Stackitem a=move(S.back()); S.pop_back();
- if(!a.isstr&&!b.isstr){
+ if(a.type==SIT_INT&&b.type==SIT_INT){
S.emplace_back(a.intval+b.intval);
return;
}
- if(!a.isstr){
- a.strval=to_string(a.intval);
- a.isstr=true;
+ if(a.type==SIT_ARR||b.type==SIT_ARR){
+ if(a.type!=SIT_ARR){
+ b.arrval.insert(b.arrval.begin(),move(a));
+ S.push_back(move(b));
+ } else if(b.type!=SIT_ARR){
+ a.arrval.push_back(move(b));
+ S.push_back(move(a));
+ } else {
+ const auto bsz=b.arrval.size();
+ a.arrval.reserve(a.arrval.size()+b.arrval.size());
+ for(unsigned int i=0;i<bsz;i++)a.arrval.push_back(move(b.arrval[i]));
+ S.push_back(move(a));
+ }
+ return;
}
- if(!b.isstr){
- b.strval=to_string(b.intval);
- b.isstr=true;
+ //none is array, and one is not int -> at least one is string and other is int
+ if(a.type!=SIT_STR){
+ S.emplace_back(to_string(a.intval)+b.strval);
+ } else if(b.type!=SIT_STR){
+ S.emplace_back(a.strval+to_string(b.intval));
+ } else {
+ S.emplace_back(a.strval+b.strval);
}
- S.emplace_back(a.strval+b.strval);
}},
{"-",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("-",2)
Stackitem b=move(S.back()); S.pop_back();
Stackitem a=move(S.back()); S.pop_back();
- if(a.isstr||b.isstr)throw string("Builtin '-' cannot accept a string argument");
+ if(a.type!=SIT_INT||b.type!=SIT_INT)
+ throw string("Builtin '-' expects two number arguments");
S.emplace_back(a.intval-b.intval);
}},
{"*",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("*",2)
Stackitem b=move(S.back()); S.pop_back();
Stackitem a=move(S.back()); S.pop_back();
- if(a.isstr||b.isstr)throw string("Builtin '*' cannot accept a string argument");
+ if(a.type!=SIT_INT||b.type!=SIT_INT)
+ throw string("Builtin '*' expects two number arguments");
S.emplace_back(a.intval*b.intval);
}},
{"/",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("/",2)
Stackitem b=move(S.back()); S.pop_back();
Stackitem a=move(S.back()); S.pop_back();
- if(a.isstr||b.isstr)throw string("Builtin '/' cannot accept a string argument");
+ if(a.type!=SIT_INT||b.type!=SIT_INT)
+ throw string("Builtin '/' expects two number arguments");
S.emplace_back(a.intval/b.intval);
}},
{"%",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("%",2)
Stackitem b=move(S.back()); S.pop_back();
Stackitem a=move(S.back()); S.pop_back();
- if(a.isstr||b.isstr)throw string("Builtin '%' cannot accept a string argument");
+ if(a.type!=SIT_INT||b.type!=SIT_INT)
+ throw string("Builtin '%' expects two number arguments");
S.emplace_back(a.intval%b.intval);
}},
{"&",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("&",2)
Stackitem b=move(S.back()); S.pop_back();
Stackitem a=move(S.back()); S.pop_back();
- if(a.isstr||b.isstr)throw string("Builtin '&' cannot accept a string argument");
+ if(a.type!=SIT_INT||b.type!=SIT_INT)
+ throw string("Builtin '&' expects two number arguments");
S.emplace_back(a.intval&b.intval);
}},
{"|",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("|",2)
Stackitem b=move(S.back()); S.pop_back();
Stackitem a=move(S.back()); S.pop_back();
- if(a.isstr||b.isstr)throw string("Builtin '|' cannot accept a string argument");
+ if(a.type!=SIT_INT||b.type!=SIT_INT)
+ throw string("Builtin '|' expects two number arguments");
S.emplace_back(a.intval|b.intval);
}},
{"~",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("~",1)
Stackitem &back=S.back();
- if(back.isstr)throw string("Builtin '~' cannot accept a string argument");
+ if(back.type!=SIT_INT)throw string("Builtin '~' expects a number argument");
else back.intval=~back.intval;
}},
{"^",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("^",2)
Stackitem b=move(S.back()); S.pop_back();
Stackitem a=move(S.back()); S.pop_back();
- if(a.isstr||b.isstr)throw string("Builtin '^' cannot accept a string argument");
+ if(a.type!=SIT_INT||b.type!=SIT_INT)
+ throw string("Builtin '^' expects two number arguments");
S.emplace_back((int)pow(a.intval,b.intval));
}},
{"!",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("!",1)
Stackitem &back=S.back();
- if(back.isstr){
- back.isstr=false;
+ if(back.type==SIT_ARR){
+ back.type=SIT_INT;
+ back.intval=!back.arrval.size();
+ back.arrval.clear();
+ } else if(back.type==SIT_STR){
+ back.type=SIT_INT;
back.intval=!back.strval.size();
+ back.strval.clear();
} else back.intval=!back.intval;
}},
{"=",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
@@ -117,25 +144,30 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack
BUILTIN_GUARD_STACKSIZE("<",2)
Stackitem b=move(S.back()); S.pop_back();
Stackitem a=move(S.back()); S.pop_back();
- if(a.isstr&&b.isstr)S.emplace_back(a.strval<b.strval);
- else if(!a.isstr&&!b.isstr)S.emplace_back(a.intval<b.intval);
- else if(a.isstr)S.emplace_back(a.strval<to_string(b.intval));
+ if(a.type==SIT_ARR&&b.type==SIT_ARR)S.emplace_back(a.arrval.size()<b.arrval.size());
+ else if(a.type==SIT_ARR||b.type==SIT_ARR){
+ throw string("Builtin '<' cannot accept an array and a non-array argument");
+ } else if(a.type==SIT_STR&&b.type==SIT_STR)S.emplace_back(a.strval<b.strval);
+ else if(a.type==SIT_INT&&b.type==SIT_INT)S.emplace_back(a.intval<b.intval);
+ else if(a.type==SIT_STR)S.emplace_back(a.strval<to_string(b.intval));
else S.emplace_back(to_string(a.intval)<b.strval);
}},
{">",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE(">",2)
Stackitem b=move(S.back()); S.pop_back();
Stackitem a=move(S.back()); S.pop_back();
- if(a.isstr&&b.isstr)S.emplace_back(a.strval>b.strval);
- else if(!a.isstr&&!b.isstr)S.emplace_back(a.intval>b.intval);
- else if(a.isstr)S.emplace_back(a.strval>to_string(b.intval));
+ if(a.type==SIT_ARR&&b.type==SIT_ARR)S.emplace_back(a.arrval.size()>b.arrval.size());
+ else if(a.type==SIT_ARR||b.type==SIT_ARR){
+ throw string("Builtin '>' cannot accept an array and a non-array argument");
+ } else if(a.type==SIT_STR&&b.type==SIT_STR)S.emplace_back(a.strval>b.strval);
+ else if(a.type==SIT_INT&&b.type==SIT_INT)S.emplace_back(a.intval>b.intval);
+ else if(a.type==SIT_STR)S.emplace_back(a.strval>to_string(b.intval));
else S.emplace_back(to_string(a.intval)>b.strval);
}},
{"print",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("print",1)
- Stackitem v=move(S.back()); S.pop_back();
- if(v.isstr)cout<<v.strval<<flush;
- else cout<<v.intval<<flush;
+ cout<<to_string(S.back())<<flush;
+ S.pop_back();
}},
{"lf",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("lf",0)
@@ -146,7 +178,7 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack
string line;
getline(cin,line);
if(!cin)S.emplace_back(-1);
- else S.emplace_back(line);
+ else S.emplace_back(move(line));
}},
{"getc",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("getc",0)
@@ -158,23 +190,23 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack
BUILTIN_GUARD_STACKSIZE("fprint",2)
Stackitem file=move(S.back()); S.pop_back();
Stackitem v=move(S.back()); S.pop_back();
- if(file.isstr)throw string("Second argument to 'fprint' not a number");
- if(v.isstr)write(file.intval,v.strval.data(),v.strval.size());
+ if(file.type!=SIT_INT)throw string("Second argument to 'fprint' not a number");
+ if(v.type==SIT_STR)write(file.intval,v.strval.data(),v.strval.size());
else {
- string s=to_string(v.intval);
+ string s=to_string(v);
write(file.intval,s.data(),s.size());
}
}},
{"flf",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("flf",1)
Stackitem file=move(S.back()); S.pop_back();
- if(file.isstr)throw string("Argument to 'flf' not a number");
+ if(file.type!=SIT_INT)throw string("Argument to 'flf' not a number");
write(file.intval,"\n",1);
}},
{"fgetc",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("fgetc",1)
Stackitem file=move(S.back()); S.pop_back();
- if(file.isstr)throw string("Argument to 'fgetc' not a number");
+ if(file.type!=SIT_INT)throw string("Argument to 'fgetc' not a number");
char c;
int ret=read(file.intval,&c,1);
if(ret==-1)perror("read");
@@ -185,8 +217,8 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack
BUILTIN_GUARD_STACKSIZE("fopen",2)
Stackitem mode=move(S.back()); S.pop_back();
Stackitem fname=move(S.back()); S.pop_back();
- if(!fname.isstr)throw string("First argument to 'fopen' not a string");
- if(!mode.isstr)throw string("Second argument to 'fopen' not a string");
+ if(fname.type!=SIT_STR)throw string("First argument to 'fopen' not a string");
+ if(mode.type!=SIT_STR)throw string("Second argument to 'fopen' not a string");
int oflag=0;
if(mode.strval.find('r')!=string::npos)oflag|=O_RDONLY;
if(mode.strval.find('w')!=string::npos){
@@ -207,7 +239,7 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack
{"argvget",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("argvget",1)
Stackitem idx=move(S.back()); S.pop_back();
- if(idx.isstr)throw string("Argument to 'argvget' not a number");
+ if(idx.type!=SIT_INT)throw string("Argument to 'argvget' not a number");
if(idx.intval<0||idx.intval>=g_argc)throw string("Argument to 'argvget' out of bounds");
S.emplace_back(g_argv[idx.intval]);
}},
@@ -223,13 +255,13 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack
BUILTIN_GUARD_STACKSIZE("swap",2)
Stackitem b=move(S.back()); S.pop_back();
Stackitem a=move(S.back()); S.pop_back();
- S.push_back(b);
- S.push_back(a);
+ S.push_back(move(b));
+ S.push_back(move(a));
}},
{"store",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
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");
+ if(name.type!=SIT_STR)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()){
@@ -247,23 +279,31 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack
{"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");
+ if(name.type!=SIT_STR)throw string("Second argument to 'store' not a string");
variables[name.strval]=move(S.back());
S.pop_back();
}},
{"get",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("get",1)
Stackitem name=move(S.back()); S.pop_back();
- if(!name.isstr)throw string("Argument to 'get' not a string");
+ if(name.type!=SIT_STR)throw string("Argument to 'get' not a string");
S.push_back(variables[name.strval]);
}},
//leaves variable with value 0
{"swapoutvar",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("swapoutvar",1)
Stackitem name=move(S.back()); S.pop_back();
- if(!name.isstr)throw string("Second argument to 'swapoutvar' not a string");
- S.push_back(move(variables[name.strval]));
- variables[name.strval].intval=0;
+ if(name.type!=SIT_STR)throw string("Second argument to 'swapoutvar' not a string");
+ auto it=variables.find(name.strval);
+ if(it==variables.end()){
+ variables.emplace(piecewise_construct,
+ forward_as_tuple(name.strval),
+ forward_as_tuple());
+ it=variables.find(name.strval);
+ }
+ S.push_back(move(it->second));
+ it->second.intval=0;
+ it->second.type=SIT_INT;
}},
{"enterscope",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("enterscope",0)
@@ -285,7 +325,7 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack
{"roll",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("roll",1)
Stackitem ns=move(S.back()); S.pop_back();
- if(ns.isstr)throw string("Argument to 'roll' not a number");
+ if(ns.type!=SIT_INT)throw string("Argument to 'roll' not a number");
int n=ns.intval;
if(S.size()<2)return;
bool negative=n<0;
@@ -314,45 +354,114 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack
BUILTIN_GUARD_STACKSIZE("stridx",2)
Stackitem idx=move(S.back()); S.pop_back();
const Stackitem &str=S.back();
- if(!str.isstr)throw string("First argument to 'stridx' not a string");
- if(idx.isstr)throw string("Second argument to 'stridx' not a number");
- if(idx.intval<0||idx.intval>=(int)str.strval.size())throw string("Index argument to 'stridx' out of range");
+ if(str.type!=SIT_STR)throw string("Top of stack is not a string in builtin 'stridx'");
+ if(idx.type!=SIT_INT)throw string("Argument to 'stridx' not a number");
+ if(idx.intval<0||idx.intval>=(int)str.strval.size())throw string("Argument to 'stridx' out of range");
S.emplace_back(string(1,str.strval[idx.intval]));
}},
//leaves the string on the stack
{"strlen",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("strlen",1)
const Stackitem &str=S.back();
- if(!str.isstr)throw string("Argument to 'strlen' not a string");
+ if(str.type!=SIT_STR)throw string("Argument to 'strlen' not a string");
S.emplace_back(str.strval.size());
}},
- //leaves the string on the stack
+ //leaves the string on the stack; `to` is exclusive
{"substr",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("substr",3)
const Stackitem to=move(S.back()); S.pop_back();
const Stackitem from=move(S.back()); S.pop_back();
const Stackitem &str=S.back();
- if(!str.isstr)throw string("First argument to 'substr' not a string");
- if(from.isstr)throw string("Second argument to 'substr' not a number");
- if(to.isstr)throw string("Third argument to 'substr' not a number");
+ if(str.type!=SIT_STR)throw string("Top of stack is not a string in builtin 'substr'");
+ if(from.type!=SIT_INT)throw string("First argument to 'substr' not a number");
+ if(to.type!=SIT_INT)throw string("Second argument to 'substr' not a number");
S.emplace_back(str.strval.substr(from.intval,to.intval-from.intval));
}},
{"chr",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("chr",1)
- Stackitem ascii=move(S.back()); S.pop_back();
- if(ascii.isstr)throw string("Argument to 'chr' not a number");
- S.emplace_back(string(1,ascii.intval));
+ if(S.back().type!=SIT_INT)throw string("Argument to 'chr' not a number");
+ S.back().type=SIT_STR;
+ S.back().strval=string(1,S.back().intval);
}},
{"ord",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
BUILTIN_GUARD_STACKSIZE("ord",1)
- if(!S.back().isstr)throw string("Argument to 'ord' not a string");
- S.back().isstr=false;
+ if(S.back().type!=SIT_STR)throw string("Argument to 'ord' not a string");
+ S.back().type=SIT_INT;
S.back().intval=(int)S.back().strval[0];
- S.back().strval="";
+ S.back().strval.clear();
+ }},
+ {"mkarray",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("mkarray",0)
+ S.emplace_back(Stackitem(vector<Stackitem>()));
+ }},
+ //mkarray prefill
+ {"mkarrayp",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("mkarrayp",1)
+ const Stackitem nitems=move(S.back()); S.pop_back();
+ if(nitems.type!=SIT_INT)throw string("Argument to 'mkarrayp' not a number");
+ if(nitems.intval<0)throw string("Negative argument to 'mkarrayp'");
+ BUILTIN_GUARD_STACKSIZE("mkarrayp: prefill",nitems.intval);
+ Stackitem res((vector<Stackitem>()));
+ res.arrval.reserve(nitems.intval);
+ const int sz=S.size();
+ for(int i=sz-nitems.intval;i<sz;i++)res.arrval.push_back(move(S[i]));
+ S.erase(S.end()-nitems.intval,S.end());
+ S.push_back(move(res));
+ }},
+ //leaves the array on the stack
+ {"arridx",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("arridx",2)
+ const Stackitem idx=move(S.back()); S.pop_back();
+ if(idx.type!=SIT_INT)
+ throw string("Argument to 'arridx' not a number");
+ if(S.back().type!=SIT_ARR)
+ throw string("Top of stack is not an array in builtin 'arridx'");
+ if(idx.intval<0||idx.intval>=S.back().arrval.size())
+ throw string("Argument to 'arridx' out of range");
+ S.push_back(S.back().arrval[idx.intval]);
+ }},
+ //leaves the array on the stack
+ {"arrlen",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("arrlen",1)
+ if(S.back().type!=SIT_ARR)
+ throw string("Top of stack is not an array in builtin 'arrlen'");
+ S.emplace_back(S.back().arrval.size());
+ }},
+ //leaves the array on the stack, obviously
+ {"push",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("push",2)
+ if(S[S.size()-2].type!=SIT_ARR)
+ throw string("Top of stack is not an array in builtin 'push'");
+ S[S.size()-2].arrval.push_back(move(S.back()));
+ S.pop_back();
+ }},
+ //leaves the array on the stack, obviously
+ {"pop",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("pop",1)
+ if(S.back().type!=SIT_ARR)
+ throw string("Top of stack is not an array in builtin 'pop'");
+ S.back().arrval.pop_back();
+ }},
+ {"rand",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("rand",0)
+ assert(RAND_MAX==0x7fffffff);
+ S.emplace_back(rand());
+ }},
+ //`to` exclusive
+ {"randr",[](vector<Stackitem> &S,unordered_map<string,Stackitem> &variables){
+ BUILTIN_GUARD_STACKSIZE("rand",2)
+ assert(RAND_MAX==0x7fffffff);
+ const Stackitem from=move(S.back()); S.pop_back();
+ const Stackitem to=move(S.back()); S.pop_back();
+ if(from.type!=SIT_INT)throw string("First argument to 'randr' not a number");
+ if(to.type!=SIT_INT)throw string("Second argument to 'randr' not a number");
+ if(to.intval<=from.intval)throw string("Arguments to 'randr' form an empty range");
+ const int rval=rand();
+ S.emplace_back(rval%(to.intval-from.intval)+from.intval);
}},
{"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");
+ if(S.back().type!=SIT_INT)throw string("Argument to 'sleep' not a number");
usleep(S.back().intval);
S.pop_back();
}},
@@ -360,8 +469,8 @@ unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stack
BUILTIN_GUARD_STACKSIZE("stackdump",0)
cerr<<"STACKDUMP: ";
for(const Stackitem &si : S){
- if(si.isstr)cerr<<'"'<<si.strval<<"\" ";
- else cerr<<si.intval<<' ';
+ if(si.type==SIT_STR)cerr<<'"'<<si.strval<<"\" ";
+ else cerr<<to_string(si)<<' ';
}
cerr<<endl;
}},
diff --git a/postrun.cpp b/postrun.cpp
index eda3714..2c3c97f 100644
--- a/postrun.cpp
+++ b/postrun.cpp
@@ -2,6 +2,7 @@
#include <fstream>
#include <vector>
#include <string>
+#include <sys/time.h>
#include "runtime.h"
@@ -32,6 +33,11 @@ int main(int argc,char **argv){
cerr<<"Could not open file '"<<argv[1]<<"'"<<endl;
return 1;
}
+
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ srand(tv.tv_sec*1000000+tv.tv_usec);
+
//string source=readfile(srcf);
try {
const vector<string> tokens=tokenise(srcf);
diff --git a/runtime.cpp b/runtime.cpp
index 98ae245..19108cd 100644
--- a/runtime.cpp
+++ b/runtime.cpp
@@ -1,10 +1,12 @@
#include <iostream>
+#include <sstream>
#include <vector>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <functional>
#include <cstring>
+#include <cassert>
#include "runtime.h"
@@ -15,23 +17,67 @@ inline bool isextword(char c){return isword(c)||isdigit(c);}
inline bool isoperator(char c){return (bool)strchr("+-*/%&|~^!=><{}",c);}
-Stackitem::Stackitem(void):isstr(false),intval(0){}
-Stackitem::Stackitem(int _i):isstr(false),intval(_i){}
-Stackitem::Stackitem(const string &_s):isstr(true),strval(_s),intval(0){}
-Stackitem::Stackitem(const Stackitem&)=default;
-Stackitem::Stackitem(Stackitem &&other):isstr(other.isstr),strval(move(other.strval)),intval(other.intval){
- other.isstr=false;
+Stackitem::Stackitem(void){}
+
+Stackitem::Stackitem(int _i):type(SIT_INT),intval(_i){}
+Stackitem::Stackitem(const string &_s):type(SIT_STR),strval(_s){}
+Stackitem::Stackitem(const vector<Stackitem> &_a):type(SIT_ARR),arrval(_a){}
+
+Stackitem::Stackitem(const Stackitem &other)=default;
+Stackitem::Stackitem(Stackitem &&other):type(other.type),strval(move(other.strval)),intval(other.intval),arrval(move(other.arrval)){
+ other.type=SIT_INT;
+}
+
+Stackitem& Stackitem::operator=(const Stackitem &other){
+ type=other.type;
+ strval=other.strval;
+ intval=other.intval;
+ arrval=other.arrval;
+ return *this;
}
-Stackitem& Stackitem::operator=(const Stackitem&)=default;
Stackitem& Stackitem::operator=(Stackitem &&other){
- isstr=other.isstr;
+ type=other.type;
strval=move(other.strval);
intval=other.intval;
- other.isstr=false;
+ arrval=move(other.arrval);
+ other.type=SIT_INT;
return *this;
}
-Stackitem::operator bool(void) const{return (isstr&&strval.size())||(!isstr&&intval);}
-bool Stackitem::operator==(const Stackitem &other) const{return isstr==other.isstr&&(isstr?strval==other.strval:intval==other.intval);}
+
+Stackitem::operator bool(void) const{
+ return (type==SIT_INT&&intval)||
+ (type==SIT_STR&&strval.size())||
+ (type==SIT_ARR&&arrval.size());
+}
+
+bool Stackitem::operator==(const Stackitem &other) const{
+ if(type!=other.type)return false;
+ if(type==SIT_INT)return intval==other.intval;
+ if(type==SIT_STR)return strval==other.strval;
+ assert(type==SIT_ARR);
+ auto sz=arrval.size();
+ if(sz!=other.arrval.size())return false;
+ for(int i=0;i<sz;i++)if(arrval[i]!=other.arrval[i])return false;
+ return true;
+}
+bool Stackitem::operator!=(const Stackitem &other) const{
+ return !(*this==other);
+}
+
+string to_string(const Stackitem &si){
+ if(si.type==SIT_ARR){
+ stringstream ss;
+ ss<<'[';
+ const auto sz=si.arrval.size();
+ for(unsigned int i=0;i<sz;i++){
+ if(i!=0)ss<<',';
+ ss<<to_string(si.arrval[i]);
+ }
+ ss<<']';
+ return ss.str();
+ } else if(si.type==SIT_STR)return si.strval;
+ else return to_string(si.intval);
+}
extern const unordered_map<string,function<void(vector<Stackitem>&,unordered_map<string,Stackitem>&)>> builtins;
diff --git a/runtime.h b/runtime.h
index 1a49300..1b20329 100644
--- a/runtime.h
+++ b/runtime.h
@@ -6,21 +6,37 @@
using namespace std;
+enum Stackitemtype{
+ SIT_INT,
+ SIT_STR,
+ SIT_ARR
+};
+
struct Stackitem{
- bool isstr;
+ Stackitemtype type=SIT_INT;
string strval;
- int intval;
+ int intval=0;
+ vector<Stackitem> arrval;
Stackitem(void);
- Stackitem(int _i);
- Stackitem(const string &_s);
+
+ Stackitem(int _i); //int init
+ Stackitem(const string&); //string init
+ Stackitem(const vector<Stackitem>&); //array init
+
Stackitem(const Stackitem&);
Stackitem(Stackitem &&other);
+
Stackitem& operator=(const Stackitem&);
Stackitem& operator=(Stackitem &&other);
+
explicit operator bool(void) const;
+
bool operator==(const Stackitem &other) const;
+ bool operator!=(const Stackitem &other) const;
};
+string to_string(const Stackitem&);
+
vector<string> tokenise(istream &stream);
void run(vector<string> T);