1
0
www.mikescher.com/www/data/programs/desc/BefunUtils/03_Examples/07_Befunge-93 interpreter.markdown

3.8 KiB

###Befunge-93 interpreter

An Befunge-93 interpreter

program BefInterpreter : display[60, 30]
	const
		int STACKSIZE := 16;
	global
		int[4] DELTA_IDX_X;
		int[4] DELTA_IDX_Y;
		
		bool running;
	
		int PC_X;
		int PC_Y;
		
		int D_X;
		int D_Y;
		
		bool stringmode;
		
		int[16] stack;
		int stackHead;
	begin
		Init();
		
		while (running) do
			execute();
			move();
		end
		
		quit;
	end
	
	void Init()
	begin
		DELTA_IDX_X[0] =  1;
		DELTA_IDX_X[1] =  0;
		DELTA_IDX_X[2] = -1;
		DELTA_IDX_X[3] =  0;
		
		DELTA_IDX_Y[0] =  0;
		DELTA_IDX_Y[1] = -1;
		DELTA_IDX_Y[2] =  0;
		DELTA_IDX_Y[3] =  1;
	
		stackHead = 0;
	
		PC_X = 0;
		PC_Y = 0;
		
		D_X = 1;
		D_Y = 0;
		
		stringmode = false;
		
		running = true;
	end
	
	void execute()
	var
		char c;
	
		int tmp, tmp2, tmp3;
	begin
		c = display[PC_X, PC_Y];

		if (stringmode && c != '"') then
			push((int)c);
			return;
		end

		switch(c)
		begin
			case ' ':
				// NOP
			end 
			case '0':
				push(0);
			end
			case '1':
				push(1);
			end
			case '2':
				push(2);
			end
			case '3':
				push(3);
			end
			case '4':
				push(4);
			end
			case '5':
				push(5);
			end
			case '6':
				push(6);
			end
			case '7':
				push(7);
			end
			case '8':
				push(8);
			end
			case '9':
				push(9);
			end
		end
		
		switch(c)
		begin
			case '+':
				push(pop() + pop());
			end
			case '-':
				tmp = pop();
				push(pop() - tmp);
			end
			case '*':
				push(pop() * pop());
			end
			case '/':
				tmp = pop();
				push(pop() / tmp);
			end
			case '%':
				tmp = pop();
				push(pop() % tmp);
			end
			case '!':
				push((int)(!popBool()));
			end
			case '`':
				tmp = pop();
				push((int)(pop() > tmp));
			end
			case '>':
				D_X = 1;
				D_Y = 0;
			end
			case '<':
				D_X = -1;
				D_Y = 0;
			end
			case '^':
				D_X = 0;
				D_Y = -1;
			end
			case 'v':
				D_X = 0;
				D_Y = 1;
			end
			case '?':
				tmp = RAND[1];
				D_X = DELTA_IDX_X[tmp];
				D_Y = DELTA_IDX_Y[tmp];
			end
		end
		
		switch(c)
		begin
			case '_':
				if (popBool()) then
					D_X = DELTA_IDX_X[2];
					D_Y = DELTA_IDX_Y[2];
				else
					D_X = DELTA_IDX_X[0];
					D_Y = DELTA_IDX_Y[0];
				end
			end
			case '|':
				if (popBool()) then
					D_X = DELTA_IDX_X[1];
					D_Y = DELTA_IDX_Y[1];
				else
					D_X = DELTA_IDX_X[3];
					D_Y = DELTA_IDX_Y[3];
				end
			end
			case '"':
				stringmode = !stringmode;
			end
			case ':':
				push(peek());
			end
			case '\\':
				tmp = pop();
				tmp2 = pop();
				push(tmp);
				push(tmp2);
			end
			case '$':
				pop();
			end
			case '.':
				out pop();
			end
			case ',':
				out popChar();
			end
			case '#':
				move();
			end
			case 'g':
				tmp = pop();
				tmp2 = pop();
				if (tmp >= 0 && tmp2 >= 0 && tmp2 < DISPLAY_WIDTH && tmp < DISPLAY_HEIGHT) then
					push((int)display[tmp2, tmp]);
				else
					push(0);
				end
			end
			case 'p':
				tmp = pop();
				tmp2 = pop();
				if (tmp >= 0 && tmp2 >= 0 && tmp2 < DISPLAY_WIDTH && tmp < DISPLAY_HEIGHT) then
					display[tmp2, tmp] = popChar();
				else
					pop();
				end
			end
			case '&':
				in tmp;
				push(tmp);
			end
			case '~':
				in tmp3;
				push((int)tmp3);
			end
			case '@':
				out "\r\n\r\n >> FINISHED";
				running = false;
			end
			default:
				// NOP
			end
		end
	end
	
	void move()
	begin
		PC_X += D_X + DISPLAY_WIDTH;
		PC_Y += D_Y + DISPLAY_HEIGHT;
		
		PC_X %= DISPLAY_WIDTH;
		PC_Y %= DISPLAY_HEIGHT;
	end
	
	void push(int v)
	begin
		stack[stackhead++] = v;
	end
	
	int pop()
	begin
		if (stackhead == 0) then
			return 0;
		end
		
		return stack[--stackhead];
	end
	
	char popChar()
	begin
		return (char)pop();
	end
	
	bool popBool()
	begin
		return (bool)pop();
	end
	
	int peek()
	begin
		if (stackhead == 0) then
			return 0;
		end
		
		return stack[stackhead - 1];
	end
end

Note: This and other examples are included in the BefunGen download