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
119
120
|
readfile ::= fn(filename: []char) []char {
#C("extern void *fopen(char *name, char const *mode); extern char *fgets(char *buf, size_t sz, void *f);");
fp : &u8 = #C("fopen(&(((char *)filename.data)[0]), \"r\")");
contents : []char;
contents_sz : int;
contents_len : int;
buffer : [1024]char;
while #C("fgets(buffer, 1024, fp)") {
buffer_len : int;
while buffer[buffer_len] {
buffer_len = buffer_len + 1;
}
if contents_sz < contents_len + buffer_len {
old_contents := contents;
contents_sz = 2*contents_sz + 1024;
contents = new(char, contents_sz);
i := 0;
while i < contents_len {
contents[i] = old_contents[i];
i = i + 1;
}
del(old_contents);
}
i := 0;
while i < buffer_len {
contents[contents_len] = buffer[i];
contents_len = contents_len + 1;
i = i + 1;
}
}
contents[contents_len] = 0 as char;
contents
};
puti ::= fn(x: int) {
#C("#ifndef __TINYC__
extern int printf(const char *fmt, ...);
#endif
");
#C("printf(\"%ld\\n\", x);");
};
runfile ::= fn(filename: []char) {
#C("extern int putchar(int c);");
code := readfile(filename);
tape_sz := 3;
tape := new(int, tape_sz);
ptr := tape_sz / 2;
i := 0;
while code[i] {
// puti(ptr);
// puti(tape_sz);
if code[i] == '+' {
tape[ptr] = tape[ptr]+1;
} elif code[i] == '-' {
tape[ptr] = tape[ptr]-1;
} elif code[i] == '>' {
ptr = ptr + 1;
if ptr >= tape_sz {
// extend to the right
newtape := new(int, 2*tape_sz);
j := 0;
while j < tape_sz {
newtape[j] = tape[j];
j = j + 1;
}
tape_sz = tape_sz * 2;
del(tape);
tape = newtape;
}
} elif code[i] == '<' {
ptr = ptr - 1;
if ptr < 0 {
// extend to the left
newtape := new(int, 2*tape_sz);
j := 0;
while j < tape_sz {
newtape[j+tape_sz] = tape[j];
j = j + 1;
}
tape_sz = tape_sz * 2;
del(tape);
tape = newtape;
ptr = ptr + tape_sz;
}
} elif code[i] == '[' {
if !tape[ptr] {
// jump to matching ]
level := 0;
while level >= 0 {
i = i + 1;
level = level + (if code[i] == '[' { 1 } elif code[i] == ']' { -1 } else {0});
}
}
} elif code[i] == ']' {
if tape[ptr] {
// jump to matching [
level := 0;
while level <= 0 {
i = i - 1;
level = level + (if code[i] == '[' { 1 } elif code[i] == ']' { -1 } else {0});
}
}
} elif code[i] == '.' {
c := tape[ptr] as char;
#C("putchar(c);");
} elif code[i] == ',' {
// Input doesn't really work, because you
// need to send an EOF to end the program.
}
i = i + 1;
}
del(tape);
del(code);
};
main ::= fn() {
runfile("bf_hw0");
runfile("bf_hw1");
};
|