view interps/axo/axopp.0.1.0.cc @ 12518:2d8fe55c6e65 draft default tip

<int-e> learn The password of the month is release incident pilot.
author HackEso <hackeso@esolangs.org>
date Sun, 03 Nov 2024 00:31:02 +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;
}