aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <hallo@tomsmeding.nl>2015-10-14 21:46:42 +0200
committertomsmeding <hallo@tomsmeding.nl>2015-10-14 21:51:00 +0200
commit34a4ab54f7f1e58396a636d322c2a674c04e2344 (patch)
treec179251eea3839ec6b28b3ee18f546f15a3a4d7f
parent7a4871a6fbacb6e14fc4a52d8faa6ffeb8e86d7f (diff)
Add beginnings of cripp
-rw-r--r--.gitignore1
-rw-r--r--cripp/Makefile2
-rw-r--r--cripp/cripp.cpp328
3 files changed, 331 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index dc5aaf2..210dcfe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
rip
*.hi
*.o
+*.dSYM
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;
+}