summaryrefslogtreecommitdiff
path: root/tests/bf.toc
blob: 83fb2911289ab8971d054723da6871def9e5cb44 (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
121
122
#include "std/mem.toc";
#include "std/io.toc";

readfile ::= fn(filename: []char) []char {
#C("extern void *fopen(char *name, char const *mode); extern char *fgets(char *buf, size_t sz, void *f);");
#C("
extern void exit(int);
");
	fp : &u8 = #C("(u8 *)fopen(&(((char *)filename.data)[0]), \"r\")");
	if !fp {
		puts("couldn't open file.");
		#C("exit(-1);");
	}
	contents := news(char, 1);
	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 = news(char, contents_sz);
	   	  i := 0;
	   	  while i < contents_len {
	   			contents[i] = old_contents[i];
	   			i = i + 1;
	   	  }
	   	  dels(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
};

runfile ::= fn(filename: []char) {
	 #C("extern int putchar(int c);");
	 code := readfile(filename);
	 tape_sz := 3;
	 tape := news(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 := news(int, 2*tape_sz);
				j := 0;
				while j < tape_sz {
					  newtape[j] = tape[j];
					  j = j + 1;
				}
				tape_sz = tape_sz * 2;
				dels(tape);
				tape = newtape;
			 }
		   } elif code[i] == '<' {
		   	 ptr = ptr - 1;
			 if ptr < 0 {
			 	// extend to the left
			 	newtape := news(int, 2*tape_sz);
				j := 0;
				while j < tape_sz {
					  newtape[j+tape_sz] = tape[j];
					  j = j + 1;
				}
				tape_sz = tape_sz * 2;
				dels(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;
	 }
	 dels(tape);
	 dels(code);
};

main ::= fn() {
	 runfile("bf_hw0\0");
	 runfile("bf_hw1\0");
};