summaryrefslogtreecommitdiff
path: root/tests/bf.toc
blob: e1f8781745365207cf2a8351735c0fcf6e080793 (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
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");
};