diff options
-rw-r--r-- | arrays.prn | 13 | ||||
-rw-r--r-- | functions.cpp | 197 | ||||
-rw-r--r-- | postrun.cpp | 6 | ||||
-rw-r--r-- | runtime.cpp | 68 | ||||
-rw-r--r-- | runtime.h | 24 |
5 files changed, 231 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..dacd194 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,78 @@ 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>())); + }}, + //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]); + }}, + {"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 +433,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; @@ -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); |