diff options
Diffstat (limited to 'cripp')
| -rw-r--r-- | cripp/Makefile | 2 | ||||
| -rw-r--r-- | cripp/cripp.cpp | 328 | 
2 files changed, 330 insertions, 0 deletions
diff --git a/cripp/Makefile b/cripp/Makefile new file mode 100644 index 0000000..925e6f7 --- /dev/null +++ b/cripp/Makefile @@ -0,0 +1,2 @@ +CXX = g++ +CXXFLAGS = -Wall -Wextra -O2 -std=c++11 -lgmp -lgmpxx
\ No newline at end of file diff --git a/cripp/cripp.cpp b/cripp/cripp.cpp new file mode 100644 index 0000000..0e193b0 --- /dev/null +++ b/cripp/cripp.cpp @@ -0,0 +1,328 @@ +#include <iostream> +#include <fstream> +#include <exception> +#include <cctype> +#include <gmpxx.h> + +#undef RIPMODE +#undef DEBUGMODE + +using namespace std; + +typedef mpz_class ripint; + +template <typename T> +int integral(T v){ +	return (int)v; +} +template <> +int integral<mpz_class>(mpz_class v){ +	return v.get_si(); +} + +template <typename T> +class Llist{ +	struct Node{ +		T value; +		Node *prev,*next; + +		inline Node(void):prev(NULL),next(NULL){} +	}; + +	Node *first,*last; +	int sz; + +public: +	inline Llist(void):first(NULL),last(NULL),sz(0){} +	inline ~Llist(void){ +		Node *n; +		while(first){ +			n=first->next; +			delete first; +			first=n; +		} +	} + +	inline int size(void){return sz;} + +	inline void push_back(T v){ +		Node *n=new Node; +		swap(n->value,v); +		if(last==NULL)first=last=n; +		else { +			last->next=n; +			n->prev=last; +			last=n; +		} +		sz++; +	} +	inline void push_front(T v){ +		Node *n=new Node; +		swap(n->value,v); +		if(first==NULL)first=last=n; +		else { +			first->prev=n; +			n->next=first; +			first=n; +		} +		sz++; +	} +	inline void pop_back(void){ +		if(last==NULL)throw length_error("pop_back on empty Llist"); +		Node *n=last; +		last=last->prev; +		if(last==NULL)first=NULL; +		else last->next=NULL; +		delete n; +		sz--; +	} +	inline void pop_front(void){ +		if(first==NULL)throw length_error("pop_front on empty Llist"); +		Node *n=first; +		first=first->next; +		if(first==NULL)last=NULL; +		else first->prev=NULL; +		delete n; +		sz--; +	} + +	inline T& back(void){ +		if(last==NULL)throw length_error("back on empty Llist"); +		return last->value; +	} +	inline T& front(void){ +		if(first==NULL)throw length_error("front on empty Llist"); +		return first->value; +	} + +	inline void* itemp(int i){ +		if(i>=0){ +			Node *n=first; +			while(i-->0)n=n->next; +			return n; +		} else { +			Node *n=last; +			while(++i<0)n=n->prev; +			return n; +		} +	} + +	inline void* frontp(void){return first;} +	inline void* backp(void){return last;} + +	inline void erase(void *p){ +		Node *n=(Node*)p; +		if(n->prev)n->prev->next=n->next; else first=n->next; +		if(n->next)n->next->prev=n->prev; else last=n->prev; +		sz--; +		delete n; +	} +	inline void insertafter(void *after,T v){ +		Node *aftern=(Node*)after; +		Node *n=new Node; +		swap(n->value,v); +		n->prev=aftern; +		if(aftern->next){ +			n->next=aftern->next; +			aftern->next->prev=n; +			aftern->next=n; +		} else { +			aftern->next=n; +			last=n; +		} +		sz++; +	} + +	static inline void* nextp(void *p){return ((Node*)p)->next;} +	static inline void* prevp(void *p){return ((Node*)p)->prev;} +	static inline T& valueof(void *p){return ((Node*)p)->value;} +}; + +#ifdef RIPMODE +void riperror(string){ +	cerr<<"rip"<<endl; +	exit(1); +} +#else +void riperror(string s){ +	throw runtime_error(s); +} +#endif + +void buildjumpmap(char *code,int len,int *jumpmap){ +	Llist<int> stack; +	int i; +	int iwidx=-1,fidx=-1,lastangleidx=-1; +	for(i=0;i<len;i++){ +		if(isspace(code[i]))continue; +		if(code[i]=='['){ +			stack.push_back(i); +			if(iwidx!=-1)jumpmap[iwidx]=i; +			if(lastangleidx!=-1)jumpmap[lastangleidx]=i; +		} else if(code[i]==']'){ +			if(stack.size()==0)riperror("Unexpected closing ']'"); +			const int start=stack.back(); +			stack.pop_back(); +			jumpmap[start]=i; +			jumpmap[i]=start; +		} else if(code[i]=='<'){ +			if(fidx!=-1)jumpmap[fidx]=i; +			const int start=i; +			for(i++;i<len;i++)if(code[i]=='>')break; +			if(i==len)riperror("Unmatched open '<'"); +			jumpmap[start]=i; +			lastangleidx=i; //the '>' +		} else if(code[i]=='>'){ +			riperror("Unexpected closing '>'"); +		} else if(code[i]=='W'||code[i]=='I'){ +			iwidx=i; +		} else if(code[i]=='F'){ +			fidx=i; +		} +		if(iwidx!=i)iwidx=-1; +		if(fidx!=i)fidx=-1; +		if(lastangleidx!=i)lastangleidx=-1; +	} +} + +void runcode(const char *code,const int *jumpmap,Llist<ripint> &stack,const int startat=0){ +	int i; +	for(i=startat;code[i];i++){ +#ifdef DEBUGMODE +		cout<<'['; +		for(void *p=stack.frontp();p;p=Llist<ripint>::nextp(p)){ +			cout<<Llist<ripint>::valueof(p)<<' '; +		} +		cout<<']'<<endl; +#endif +		if(code[i]>='0'&&code[i]<='9'){ +			stack.push_back(code[i]-'0'); +			continue; +		} +		switch(code[i]){ +			case 'P': +				stack.pop_back(); +				break; +			case 'S':{ +				const ripint b=stack.back(); stack.pop_back(); +				const ripint a=stack.back(); stack.pop_back(); +				stack.push_back(b); +				stack.push_back(a); +				break; +			} +			case 'D': +				stack.push_back(stack.back()); +				break; +			case 'i': +				stack.back()++; +				break; +			case 'd': +				stack.back()--; +				break; +			case 'r':{ +				const int n=integral(stack.back()); stack.pop_back(); +				const ripint value=stack.back(); stack.pop_back(); +				if(n==stack.size()+1)stack.push_front(value); +				else { +					void *const before=stack.itemp(-n); +					stack.insertafter(before,value); +				} +				break; +			} +			case 'R':{ +				const int n=integral(stack.back()); stack.pop_back(); +				void *const p=stack.itemp(-n); +				stack.push_back(Llist<ripint>::valueof(p)); +				stack.erase(p); +				break; +			} +			case 'l': +				stack.push_back(stack.size()); +				break; +			case 'a': case 's': case 'm': case 'q': case 'G': case 'L': case 'E':{ +				const ripint b=stack.back(); stack.pop_back(); +				const ripint a=stack.back(); stack.pop_back(); +				switch(code[i]){ +					case 'a': stack.push_back(a+b); break; +					case 's': stack.push_back(a-b); break; +					case 'm': stack.push_back(a*b); break; +					case 'q': stack.push_back(a/b); break; +					case 'G': stack.push_back(a>b); break; +					case 'L': stack.push_back(a<b); break; +					case 'E': stack.push_back(a==b); break; +				} +				break; +			} +			case 'n': +				stack.back()=!integral(stack.back()); +				break; +			case 'I': { +				if(jumpmap[i]==0)riperror("No code block after 'I'"); +				const int cond=integral(stack.back()); stack.pop_back(); +				if(cond){ +					runcode(code,jumpmap,stack,jumpmap[i]+1); +				} +				i=jumpmap[jumpmap[i]]; +				break; +			} +			case 'W': { +				if(jumpmap[i]==0)riperror("No code block after 'W'"); +				int cond; +				while(true){ +					cond=integral(stack.back()); stack.pop_back(); +					//cerr<<"whiling on "<<string(code+i-2,5)<<"; cond="<<cond<<endl; +					if(!cond)break; +					runcode(code,jumpmap,stack,jumpmap[i]+1); +				} +				i=jumpmap[jumpmap[i]]; +				break; +			} +			case 'o': +				cout<<(char)integral(stack.back()); +				stack.pop_back(); +				break; +			case 'O': +				cout<<stack.back(); +				stack.pop_back(); +				break; +			case 'g':{ +				char c; +				cin>>c; +				stack.push_back((int)c); +				break; +			} +			case '$': +				for(void *p=stack.frontp();p;p=Llist<ripint>::nextp(p)){ +					cout<<Llist<ripint>::valueof(p)<<' '; +				} +				cout<<endl; +				break; +			case ']': +				return; +		} +	} +} + +int main(int argc,char **argv){ +	if(argc!=2){ +		cout<<"Pass a rip file as the command-line argument"<<endl; +		return 1; +	} +	ifstream codef(argv[1]); +	codef.seekg(0,ios::end); +	const size_t len=codef.tellg(); +	codef.seekg(0); +	char *code=new char[len+1]; +	codef.read(code,len); +	code[len]='\0'; +	codef.close(); + +	int *jumpmap=new int[len](); +	buildjumpmap(code,len,jumpmap); + +	Llist<ripint> stack; +	runcode(code,jumpmap,stack); + +	delete[] jumpmap; +	delete[] code; +}  | 
