diff options
| -rw-r--r-- | arrays.prn | 13 | ||||
| -rw-r--r-- | functions.cpp | 233 | ||||
| -rw-r--r-- | postrun.cpp | 6 | ||||
| -rw-r--r-- | runtime.cpp | 68 | ||||
| -rw-r--r-- | runtime.h | 24 | 
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; @@ -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);  | 
