view interps/axo/axopp.0.1.0.cc @ 9554:23f43464694e

<Zarutian> le/rn Frams\xc3\xb3knarflokkurinn/A, now defunct, political party in Iceland. Like its sister party Sj\xc3\xa1lfst\xc3\xa6\xc3\xb0isflokkurinn it is named by the antonym of what it is. (The name means the Progressive Party but they have nearly always been highly regressive). Think dumb Hill-Billies in ill fitting suits and you get their constiuents.
author HackBot
date Sun, 30 Oct 2016 14:33:24 +0000
parents 859f9b4339e6
children
line wrap: on
line source

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>



using namespace std;

typedef int stack_item;


#ifndef __APPLE__
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
void sranddev()
{
    int rf;
    struct timeval tv;
    unsigned int newseed;
    
    gettimeofday(&tv, NULL);
    srand(tv.tv_usec);
    
    if (access("/dev/urandom", R_OK)) {
        rf = open("/dev/urandom", O_RDONLY);
        if (rf == -1) return;
        
        if (read(rf, &newseed, sizeof(unsigned int)) > 0) {
            srand(newseed);
        }
    }
}
#endif


class Axo2Interpreter {
	vector<string> m_program;
	istream *m_input;
	ostream *m_output;
	int m_x,m_y,m_dx,m_dy;
	int m_width,m_height;
	deque<stack_item> m_stack;
	enum {mode_command,mode_string,mode_raw} m_mode;
	stack_item m_mem[2048];
	bool m_running;
	
	stack_item m_reg_a,m_reg_b;
	
	stack_item peak() {
		if(m_stack.empty())
			return 0;
		return m_stack.back();
	}
	
	stack_item pop() {
		if(m_stack.empty())
			return 0;
		stack_item rv = m_stack.back();
		m_stack.pop_back();
		return rv;
	}
	
	stack_item dequeue() {
		if(m_stack.empty())
			return 0;
		stack_item rv = m_stack.front();
		m_stack.pop_front();
		return rv;
	}
	
	void push(stack_item a) {
		m_stack.push_back(a);
	}
	
	void enqueue(stack_item a) {
		m_stack.push_front(a);
	}
	
	void clear_stack() {
		m_stack.clear();
	}
	
	bool outside() {
		return m_x < 0 || m_x >= m_width || m_y < 0 || m_y >= m_height;
	}
	
	char current_command() {
		return m_program[m_y][m_x];
	}
	
	void set_direction(int num) {
		switch(num&3) {
		case 0:
			m_dx= 0;m_dy=-1;
			return;
		case 1:
			m_dx=-1;m_dy= 0;
			return;
		case 2:
			m_dx= 1;m_dy= 0;
			return;
		case 3:
			m_dx= 0;m_dy= 1;
			return;
		}
	}
	
	void move() {
		m_x+=m_dx;
		m_y+=m_dy;
	}
	
	
	inline void execute_command(char command);
public:
	Axo2Interpreter(istream &, istream &, ostream &);
	void set_input(istream &input) {m_input = &input;}
	void set_output(ostream &output) {m_output = &output;}
	bool is_running() {return m_running;}
	
	void step() {
		if(!outside()) {
			execute_command(current_command());
			move();
			//cerr << "x: " << m_x << " y: " << m_y << endl; 
		}
	}
	
	void run() {
		while(m_running) 
			step();
	}
};

Axo2Interpreter::Axo2Interpreter(istream &program_file, istream &input = cin, ostream &output = cout) {
	string rline;
	m_input = &input;
	m_output = &output;
	m_x = m_y = 0;
	m_dx = 1;
	m_dy = 0;
	m_height = 0;
	m_width = 0;
	m_mode = mode_command;
	m_reg_a = m_reg_b = 0;
	m_running = true;
	while(getline(program_file,rline,'\n') && rline != "__END__") {
		m_height++;
		m_program.push_back(rline);
		if(rline.size()>m_width)
			m_width = rline.size();
	}
	for(vector<string>::iterator cline = m_program.begin(); cline!=m_program.end();++cline) {
		(*cline).append(m_width-cline->size(),' ');
	}
	sranddev();
}

inline void Axo2Interpreter::execute_command(char command) {
	stack_item a,b;
	int tmpd;
	if(m_mode != mode_raw) {
		switch(command) {
		case '^':
			m_dx= 0;m_dy=-1;
			return;
		case '<':
			m_dx=-1;m_dy= 0;
			return;
		case '>':
			m_dx= 1;m_dy= 0;
			return;
		case '%':
			m_dx= 0;m_dy= 1;
			return;
		case '+':
			push(pop()+pop());
			return;
		case '-':
			a=pop();
			push(pop()-a);
			return;
		case '*':
			push(pop()*pop());
			return;
		case '/':
			a=pop();
			b=pop();
			push(b/a);
			push(b%a);
			return;
		case '\\':
			m_running = false;
			return;
		}
	}
	if(m_mode == mode_command) {
		switch(command) {
		case '&':
			enqueue(pop());
			return;
		case '|':
			push(dequeue());
			return;
		case '$':
			set_direction(pop());
			return;
		case '#':
			if(!pop())
				move();
			return;
		case '[':
			push(peak());
			return;
		case ']':
			pop();
			return;
		case '(':
		  
			m_output->put((char)(pop()&0xFF));
			m_output->flush();
			return;
		case ')':
			char inchar;
			m_input->get(inchar);
			if(m_input->eof())
				push(-1);
			else
				push(((stack_item)inchar)&0xFF);
			return;
		case '{':
			(*m_output) << pop();
			return;
		case '}':
			char ic;
			stack_item cnum;
			bool neg;
			cnum = 0;
			
			do m_input->get(ic);
			while(ic < '0' || ic > '9' && ic != '-');
			
			neg = false;
			if(ic == '-') {
				neg = true;
				m_input->get(ic);
			}
			
			while(ic >= '0' && ic <= '9') {
				cnum = cnum * 10 + ic-'0';
				m_input->get(ic);
			}
			
			while(ic != '\n')
				m_input->get(ic);
			
			if(neg)
				cnum = -cnum;
			
			push(cnum);

			return;
		case '"':
			m_mode = mode_string;
			return;
		case '\'':
			m_mode = mode_raw;
			return;
		case ':':
			m_reg_a = pop();
			return;
		case ';':
			push(m_reg_a);
			return;
		case '.':
			m_reg_b = pop();
			return;
		case ',':
			push(m_reg_b);
			return;
		case '?':
			set_direction(random());
			return;
		case '_':
			m_x = -1;
			m_y = 0;
			m_dx = 1;
			m_dy = 0;
			return;
		case '@':
			clear_stack();
			return;
		case '!':
			tmpd = m_dx;
			m_dx=-m_dy;
			m_dy=tmpd;
			return;
		case '=':
			a = pop();
			b = pop();
			push(m_mem[a&2047]);
			m_mem[a&2047]=b;
			return;
		case '~':
			cerr << "\n[ ";
			bool first;
			first = true;
			for(deque<stack_item>::const_iterator i = m_stack.begin();i != m_stack.end();i++){
				if(!first)
					cerr << " | ";
				cerr << *i;
				first = false;
			}
			cerr << " ] a:" << m_reg_a << " b:" << m_reg_b << " x:" << m_x << " y:" << m_y << endl;
			
			return;
		default:
			if(command >= '0' and command <= '9'){
				push(command-'0');
				return;
			}
		}
	}
	if(m_mode == mode_string) {
		if(command == '"')
			m_mode = mode_command;
		else if(command == '$')
			push(10);
		else
			push(((stack_item)command)&0xFF);
	}
	else if(m_mode == mode_raw) {
		if(command == '\'')
			m_mode = mode_command;
		else
			push(((stack_item)command)&0xFF);
	}
}

// quick and dirty cli 

void usage() {
	cerr << "Usage: axopp <sourcefile>" << endl;
	exit(1);
}

int main(int argc, char * const argv[]) {
	if(argc != 2)
		usage();


	if(argv[1][0] == '-' && argv[1][1] == 0) {
		Axo2Interpreter i(cin);
		i.run();
	}
	else {
		ifstream inf;
		inf.open(argv[1],ios::in);
		if(!inf.is_open()) {
			cerr << "Couldn't open sourcefile." << endl;
			return 1;
		}
		Axo2Interpreter i(inf);
		i.run();
		inf.close();
	}
	

	
  return 0;
}