-
Notifications
You must be signed in to change notification settings - Fork 259
Expand file tree
/
Copy pathbf.vala
More file actions
executable file
·118 lines (104 loc) · 3.32 KB
/
bf.vala
File metadata and controls
executable file
·118 lines (104 loc) · 3.32 KB
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!/usr/bin/vala
void notify(string message) {
try {
var address = new InetAddress.from_string ("127.0.0.1");
var client = new SocketClient ();
var conn = client.connect (new InetSocketAddress (address, 9001));
conn.output_stream.write (message.data);
} catch (Error e) {
// Standalone usage
}
}
void start() {
var msg = "Vala ";
#if GCC_TEST
msg += "GCC";
#elif CLANG_TEST
msg += "Clang";
#else
// The preprocessor directive for the test should be specified
Process.exit(-1);
#endif
msg += @"\t $((uint16)Posix.getpid())";
notify(msg);
}
enum OpT {INC, MOVE, PRINT, LOOP}
namespace Test {
struct Op {
public OpT op;
public int v;
public Op[] loop;
public Op(OpT _op, int _v) { op = _op; v = _v; loop = null; }
public Op.vnull(OpT _op, Op[] _l) { op = _op; loop = _l; v = 0; }
}
public class Tape {
public int pos;
public int[] tape;
public Tape() {
pos = 0;
tape = new int[1];
}
public int Get() { return tape[pos]; }
public void Inc(int x) { tape[pos] += x; }
public void Move(int x) { pos += x; while (pos >= tape.length) tape.resize(tape.length*2);}
}
class Program {
public string code;
public int pos;
public Op[] ops;
Program(string text) {
code = text;
pos = 0;
ops = parse();
}
private Op[] parse() {
Op[] res = {};
while (pos < code.length) {
char c = code[pos];
pos++;
switch (c) {
case '+': res += (Op(OpT.INC, 1)); break;
case '-': res += (Op(OpT.INC, -1)); break;
case '>': res += (Op(OpT.MOVE, 1)); break;
case '<': res += (Op(OpT.MOVE, -1)); break;
case '.': res += (Op(OpT.PRINT, 0)); break;
case '[': res += (Op.vnull(OpT.LOOP, parse())); break;
case ']': return res;
}
}
return res;
}
public void run() {
_run(ops, new Tape());
}
private void _run(Op[] program, Tape tape) {
for (int i=0;i<program.length;i++) {
switch (program[i].op) {
case OpT.INC: tape.Inc(program[i].v); break;
case OpT.MOVE: tape.Move(program[i].v); break;
case OpT.LOOP: while (tape.Get() > 0) _run(program[i].loop, tape); break;
case OpT.PRINT: stdout.printf("%c", (char)tape.Get()); stdout.flush(); break;
}
}
}
static void main(string[] args) {
string text;
try {
FileUtils.get_contents(args[1], out text);
} catch (FileError e) {
stdout.printf("Error: %s\n", e.message);
}
if (text.length == 0) {
Process.exit(-1);
}
start();
message("run");
Timer timer = new Timer ();
var p = new Program(text);
p.run();
timer.stop();
message("time: " + timer.elapsed().to_string() + " s");
notify("stop");
}
}
}