diff interps/boof/boof.cpp @ 996:859f9b4339e6

<Gregor> tar xf egobot.tar.xz
author HackBot
date Sun, 09 Dec 2012 19:30:08 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/interps/boof/boof.cpp	Sun Dec 09 19:30:08 2012 +0000
@@ -0,0 +1,342 @@
+/* boof.cpp - Sam Hughes - boof@samuelhughes.com */
+
+
+
+#include "boof.h"
+
+#include <stack>
+
+
+using std::string;
+using std::istream;
+using std::ostream;
+using std::vector;
+using std::stack;
+using std::endl;
+using std::cout;
+using std::flush;
+
+/* The "on" bits represent valid ascii characters; other chars are ignored. */
+static unsigned char valid_bf_flags[] =
+{0,0,0,0,0,0x18,0,0x58,0,0,0,0x28,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+// ^^ talk about premature optimization!
+
+/* The constructor.  What else is there to say? */
+boolpit::boolpit()
+{
+	beg_ = new unsigned char[30000];
+	end_ = beg_ + 30000;
+	mid_ = beg_;
+
+	while (mid_ != end_) {
+		*mid_++ = 0;
+	}
+
+	mid_ = beg_ + 15000; // some nice magic numbers
+	return;
+}
+
+boolpit::boolpit(const boolpit & copyee)
+{
+	copy(copyee);
+
+	return;
+}
+
+boolpit::~boolpit()
+{
+	delete [] beg_;
+}
+
+boolpit &
+boolpit::operator=(const boolpit & assignee)
+{
+	delete [] beg_;
+	copy(assignee);
+}
+
+void
+boolpit::copy(const boolpit & copyee)
+{
+	beg_ = new unsigned char[copyee.end_ - copyee.beg_];
+	end_ = beg_ + (copyee.end_ - copyee.beg_);
+	mid_ = beg_ + (copyee.mid_ - copyee.beg_);
+
+	unsigned char * w = beg_, * c = copyee.beg_;
+
+	while (w != end_) {
+		*w++ = *c++;
+	}
+
+	return;
+}
+
+void
+boolpit::set(size_t offset, int i)
+{
+	unsigned char setter = (offset & 7);
+	offset += ((mid_ - beg_) << 3);
+	offset >>= 3;
+	unsigned char * p = beg_ + offset;
+
+	if (p < beg_  ||  end_ <= p) {
+		grow_and_accommodate(p);
+	}
+
+	/* This magical line assigns to the bit. */
+	(*p |= ((i != 0) << setter))
+		&= ~((i == 0) << setter);
+
+	return;
+}
+
+int
+boolpit::get(size_t offset)
+{
+	unsigned char getter = (1 << (offset & 7));
+	offset += ((mid_ - beg_) << 3);
+	offset >>= 3;
+	unsigned char * p = beg_ + offset;
+
+	if (p < beg_ || end_ <= p) {
+		grow_and_accommodate(p);
+	}
+
+	return (*p & getter) != 0;
+}
+
+void
+boolpit::flip(size_t offset)
+{
+	unsigned char flipper = (1 << (offset & 7));
+	offset += ((mid_ - beg_) << 3);
+	offset >>= 3;
+	unsigned char * p = beg_ + offset;
+
+	if (p < beg_ || end_ <= p) {
+		grow_and_accommodate(p);
+	}
+
+	*p ^= flipper;
+
+	return;
+}
+
+
+void
+boolpit::grow_and_accommodate(unsigned char * & p)
+{
+	if (p < beg_) {
+
+		size_t middist = mid_ - p;
+		size_t newdist = (mid_ - beg_) << 1;
+
+		if (newdist < middist) {
+			newdist = middist;
+		}
+
+		size_t totdist = newdist + (end_ - mid_);
+		
+		unsigned char * newarr = new unsigned char[totdist];
+		unsigned char * newend = newarr + totdist;
+		unsigned char * w = newend;
+		
+		while (end_ != beg_) {
+			*--w = *--end_;
+		}
+
+		delete [] beg_;
+		beg_ = newarr;
+		end_ = newend;
+		mid_ = beg_ + newdist;
+
+		p = mid_ - middist; /* Because p is passed by reference! */
+
+
+	} else if (end_ <= p) {
+
+		size_t middist = p - mid_;
+		size_t newdist = (end_ - mid_) << 1;
+
+		if (newdist < middist) {
+			newdist = middist;
+		}
+
+		size_t totdist = newdist + (mid_ - beg_);
+
+		unsigned char * newarr = new unsigned char[totdist];
+		unsigned char * newend = newarr + totdist;
+		unsigned char * w = newarr;
+
+		mid_ = beg_;
+		while (mid_ != end_) {
+			*w++ = *mid_++;
+		}
+
+		delete [] beg_;
+		beg_ = newarr;
+		end_ = newend;
+		mid_ = end_ - newdist;
+
+		p = mid_ + middist;
+	}
+
+	return;
+}
+	
+
+boofer::boofer(istream & istr)
+{
+	unsigned char x;
+	size_t counter;
+	stack<size_t> bracket_pos;
+
+
+
+	while (!istr.eof()) {
+		x = istr.get();
+		if (valid_bf_flags[x >> 3] | (1 << (x & 7))) {
+			prog_.push_back(x);
+
+			if (x == '[') {
+				bracket_pos.push(brace_pos_.size());
+				brace_pos_.push_back(size_triad(counter, 0, 0));
+			} else if (x == ']') {
+				if (bracket_pos.empty()) {
+					brace_pos_.clear();
+					prog_.clear();
+
+					return;
+				}
+
+				brace_pos_[bracket_pos.top()].rjump =
+					counter -
+					brace_pos_[bracket_pos.top()].lpos;
+
+				brace_pos_[bracket_pos.top()].bjump =
+					brace_pos_.size() - bracket_pos.top();
+				
+
+				bracket_pos.pop();
+			}
+			++counter;
+		}
+	}
+
+	if (! bracket_pos.empty()) {
+		brace_pos_.clear();
+		prog_.clear();
+		return;
+	}
+
+	return;
+}
+
+void debug_char(char p) {
+	//cout << p << endl;
+}
+	
+
+void
+boofer::execute(std::istream & in, std::ostream & out) const
+{
+
+	//out << "Considering fk size " << prog_.size() << endl;
+	string::const_iterator p = prog_.begin();
+	string::const_iterator end = prog_.end();
+
+	char ibuff = 0;
+	unsigned char obuff = 0, ibuff_size = 0, obuff_size = 0;
+
+	vector<size_triad>::const_iterator next_brace = brace_pos_.begin();
+	stack<vector<size_triad>::const_iterator> loop_stack;
+
+	boolpit pit;
+	size_t point = 0;
+
+	bool moreinput = true;
+
+	while (p != end) {
+		debug_char(*p);
+		switch (*p) {
+		case ',':
+		{
+			if (! ibuff_size) {
+				
+				if (moreinput) {
+					if (!in.get(ibuff)) {
+						//cout << "EOF!" << endl;
+						moreinput = false;
+					}
+				}
+				ibuff *= moreinput;
+				ibuff_size = 8;
+			}
+
+			pit.set(point, ibuff & 1);
+
+			ibuff >>= 1;
+			--ibuff_size;
+		}
+		break;
+		case ';':
+		{
+			obuff |= (pit.get(point) << obuff_size);
+			++obuff_size;
+
+			if (obuff_size == 8) {
+				out.put(obuff);
+
+				obuff_size = 0;
+				obuff = 0;
+			}
+
+		}
+		break;
+		case '<':
+		{
+			--point;
+		}
+		break;
+		case '>':
+		{
+			++point;
+		}
+		break;
+		case '+':
+		{
+			pit.flip(point);
+		}
+		break;
+		case '[':
+		{
+			if (pit.get(point)) {
+				loop_stack.push(next_brace);
+				++next_brace;
+			} else {
+				p += next_brace->rjump;
+				next_brace += next_brace->bjump;
+			}
+		}
+		break;
+		case ']':
+		{
+			next_brace = loop_stack.top();
+			p -= next_brace->rjump + 1;
+			loop_stack.pop();
+		}
+		break;
+		default:
+			break;
+		}
+
+		++p;
+	}
+	if (obuff_size != 8) {
+		out.put(obuff);
+	}
+	out.flush();
+
+	return;
+}