summaryrefslogtreecommitdiff
path: root/samples/brainfuck.golem
blob: 56aef26c723ddd6cfac7d4b7a2e3d35f5c4b568f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
define EOF = 0xffff;
define BUF_SIZE = 0x4000;
define MEM_SIZE = 0x8000; // has to be 2^x
define MEM_MAX_PTR = MEM_SIZE - 1;

global buf[BUF_SIZE] = 0;
global pc = 0;

global mem[MEM_SIZE] = 0;
global mem_ptr = 0;

main() {
	if drain() |> ensure_match
		return error("[] don't match");
	loop {
		if ([buf + pc] == 0)
			return;
		getop() |> exec;
	}
}

drain() {
	local p = buf;
	loop {
		red p;
		if ([p] == EOF | [p] == '\n') {
			[p] = 0;
			return buf;
		}
		p++;
	}
}

ensure_match(p) {
	local matching = 0;
	loop {
		if ([p] == 0)
			return matching;
		if ([p] == ']' & matching == 0)
			return 1;
		matching = matching + ([p] == '[') - ([p] == ']');
		p++;
	}
}

error(msg) {
	loop {
		if ([msg] == 0) {
			wrt '\n';
			return;
		}
		wrt [msg++];
	}
}

getop() => [buf + pc++];

exec(op)
	     if (op == '<') mem_ptr = (mem_ptr - 1) & MEM_MAX_PTR;
	else if (op == '>') mem_ptr = (mem_ptr + 1) & MEM_MAX_PTR;
	else if (op == '+') [mem + mem_ptr] = ([mem + mem_ptr] + 1) & 0xff;
	else if (op == '-') [mem + mem_ptr] = ([mem + mem_ptr] - 1) & 0xff;
	else if (op == '.') wrt [mem + mem_ptr];
	else if (op == ',') red mem + mem_ptr;
	else if (op == '[') => zjmpfwd();
	else if (op == ']') => nzjmpbckwd();

zjmpfwd() {
	local matching = 1;
	if ([mem + mem_ptr] == 0) loop {
		matching = matching + ([buf + pc] == '[') - ([buf + pc] == ']');
		pc++;
		if (matching == 0)
			return;
	}
}

nzjmpbckwd() {
	local matching = 0;
	if ([mem + mem_ptr] != 0) loop {
		pc--;
		matching = matching + ([buf + pc] == ']') - ([buf + pc] == '[');
		if (matching == 0)
			return pc++;
	}
}