-
Notifications
You must be signed in to change notification settings - Fork 2
/
bf.rbcvm
82 lines (71 loc) · 1.99 KB
/
bf.rbcvm
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
import array;
import arraylist;
import fs;
import iter;
import string;
struct Tape { get, inc, move }
function tape_new() {
let pos = 0;
let data = arraylist.from_array(1, [0]);
return Tape {
get = function() {
return arraylist.get(data, pos);
},
inc = function(n) {
arraylist.set(data, pos, arraylist.get(data, pos) + n);
},
move = function(n) {
pos = pos + n;
if (pos >= arraylist.length(data)) {
arraylist.push(data, 0);
}
},
};
}
struct Op { type, value }
function parse(it) {
let ops = arraylist.new();
let c;
while ((c = it()) != iter.STOP) {
if (c == '+') {
arraylist.push(ops, Op{type="inc", value=1});
} else if (c == '-') {
arraylist.push(ops, Op{type="inc", value=-1});
} else if (c == '>') {
arraylist.push(ops, Op{type="move", value=1});
} else if (c == '<') {
arraylist.push(ops, Op{type="move", value=-1});
} else if (c == '.') {
arraylist.push(ops, Op{type="print"});
} else if (c == '[') {
arraylist.push(ops, Op{type="loop", value=parse(it)});
} else if (c == ']') {
break;
}
}
return arraylist.to_array(ops);
}
function run(tape, ops) {
let len = array.length(ops);
for (let i = 0; i < len; i = i + 1) {
let op = ops[i];
if (op:type == "inc") {
tape:inc(op:value);
} else if (op:type == "move") {
tape:move(op:value);
} else if (op:type == "print") {
print(chr(tape:get()));
} else if (op:type == "loop") {
while (tape:get() != 0) {
run(tape, op:value);
}
}
}
}
let args = argv();
if (array.length(args) != 1) {
println("Usage: ./cbcvm bf3.rbcvm <program>");
} else {
let it = array.iter(string.chars(fs.read_file(args[0])));
run(tape_new(), parse(it));
}