diff options
author | tomsmeding <hallo@tomsmeding.nl> | 2015-10-14 21:46:42 +0200 |
---|---|---|
committer | tomsmeding <hallo@tomsmeding.nl> | 2015-10-14 21:51:00 +0200 |
commit | 34a4ab54f7f1e58396a636d322c2a674c04e2344 (patch) | |
tree | c179251eea3839ec6b28b3ee18f546f15a3a4d7f /cripp | |
parent | 7a4871a6fbacb6e14fc4a52d8faa6ffeb8e86d7f (diff) |
Add beginnings of cripp
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; +} |