view interps/axo/axopp.0.1.0.cc @ 3418:d0d4a6a6ad9b

<boily> learn ph\xe1\xbb\x9f l\xc3\xa0 m\xe1\xbb\x99t m\xc3\xb3n \xc4\x83n truy\xe1\xbb\x81n th\xe1\xbb\x91ng c\xe1\xbb\xa7a Vi\xe1\xbb\x87t Nam, c\xc5\xa9ng c\xc3\xb3 th\xe1\xbb\x83 xem l\xc3\xa0 m\xe1\xbb\x99t trong nh\xe1\xbb\xafng m\xc3\xb3n \xc4\x83n \xc4\x91\xe1\xba\xb7c tr\xc6\xb0ng nh\xe1\xba\xa5t cho \xe1\xba\xa9m th\xe1\xbb\xb1c Vi\xe1\xbb\x87t Nam.
author HackBot
date Thu, 15 Aug 2013 19:52:26 +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;
}