996
|
1 #include <iostream>
|
|
2 #include <fstream>
|
|
3 #include <string>
|
|
4 #include <vector>
|
|
5 #include <deque>
|
|
6
|
|
7
|
|
8
|
|
9 using namespace std;
|
|
10
|
|
11 typedef int stack_item;
|
|
12
|
|
13
|
|
14 #ifndef __APPLE__
|
|
15 #include <fcntl.h>
|
|
16 #include <stdlib.h>
|
|
17 #include <sys/stat.h>
|
|
18 #include <sys/time.h>
|
|
19 #include <sys/types.h>
|
|
20 #include <unistd.h>
|
|
21 void sranddev()
|
|
22 {
|
|
23 int rf;
|
|
24 struct timeval tv;
|
|
25 unsigned int newseed;
|
|
26
|
|
27 gettimeofday(&tv, NULL);
|
|
28 srand(tv.tv_usec);
|
|
29
|
|
30 if (access("/dev/urandom", R_OK)) {
|
|
31 rf = open("/dev/urandom", O_RDONLY);
|
|
32 if (rf == -1) return;
|
|
33
|
|
34 if (read(rf, &newseed, sizeof(unsigned int)) > 0) {
|
|
35 srand(newseed);
|
|
36 }
|
|
37 }
|
|
38 }
|
|
39 #endif
|
|
40
|
|
41
|
|
42 class Axo2Interpreter {
|
|
43 vector<string> m_program;
|
|
44 istream *m_input;
|
|
45 ostream *m_output;
|
|
46 int m_x,m_y,m_dx,m_dy;
|
|
47 int m_width,m_height;
|
|
48 deque<stack_item> m_stack;
|
|
49 enum {mode_command,mode_string,mode_raw} m_mode;
|
|
50 stack_item m_mem[2048];
|
|
51 bool m_running;
|
|
52
|
|
53 stack_item m_reg_a,m_reg_b;
|
|
54
|
|
55 stack_item peak() {
|
|
56 if(m_stack.empty())
|
|
57 return 0;
|
|
58 return m_stack.back();
|
|
59 }
|
|
60
|
|
61 stack_item pop() {
|
|
62 if(m_stack.empty())
|
|
63 return 0;
|
|
64 stack_item rv = m_stack.back();
|
|
65 m_stack.pop_back();
|
|
66 return rv;
|
|
67 }
|
|
68
|
|
69 stack_item dequeue() {
|
|
70 if(m_stack.empty())
|
|
71 return 0;
|
|
72 stack_item rv = m_stack.front();
|
|
73 m_stack.pop_front();
|
|
74 return rv;
|
|
75 }
|
|
76
|
|
77 void push(stack_item a) {
|
|
78 m_stack.push_back(a);
|
|
79 }
|
|
80
|
|
81 void enqueue(stack_item a) {
|
|
82 m_stack.push_front(a);
|
|
83 }
|
|
84
|
|
85 void clear_stack() {
|
|
86 m_stack.clear();
|
|
87 }
|
|
88
|
|
89 bool outside() {
|
|
90 return m_x < 0 || m_x >= m_width || m_y < 0 || m_y >= m_height;
|
|
91 }
|
|
92
|
|
93 char current_command() {
|
|
94 return m_program[m_y][m_x];
|
|
95 }
|
|
96
|
|
97 void set_direction(int num) {
|
|
98 switch(num&3) {
|
|
99 case 0:
|
|
100 m_dx= 0;m_dy=-1;
|
|
101 return;
|
|
102 case 1:
|
|
103 m_dx=-1;m_dy= 0;
|
|
104 return;
|
|
105 case 2:
|
|
106 m_dx= 1;m_dy= 0;
|
|
107 return;
|
|
108 case 3:
|
|
109 m_dx= 0;m_dy= 1;
|
|
110 return;
|
|
111 }
|
|
112 }
|
|
113
|
|
114 void move() {
|
|
115 m_x+=m_dx;
|
|
116 m_y+=m_dy;
|
|
117 }
|
|
118
|
|
119
|
|
120 inline void execute_command(char command);
|
|
121 public:
|
|
122 Axo2Interpreter(istream &, istream &, ostream &);
|
|
123 void set_input(istream &input) {m_input = &input;}
|
|
124 void set_output(ostream &output) {m_output = &output;}
|
|
125 bool is_running() {return m_running;}
|
|
126
|
|
127 void step() {
|
|
128 if(!outside()) {
|
|
129 execute_command(current_command());
|
|
130 move();
|
|
131 //cerr << "x: " << m_x << " y: " << m_y << endl;
|
|
132 }
|
|
133 }
|
|
134
|
|
135 void run() {
|
|
136 while(m_running)
|
|
137 step();
|
|
138 }
|
|
139 };
|
|
140
|
|
141 Axo2Interpreter::Axo2Interpreter(istream &program_file, istream &input = cin, ostream &output = cout) {
|
|
142 string rline;
|
|
143 m_input = &input;
|
|
144 m_output = &output;
|
|
145 m_x = m_y = 0;
|
|
146 m_dx = 1;
|
|
147 m_dy = 0;
|
|
148 m_height = 0;
|
|
149 m_width = 0;
|
|
150 m_mode = mode_command;
|
|
151 m_reg_a = m_reg_b = 0;
|
|
152 m_running = true;
|
|
153 while(getline(program_file,rline,'\n') && rline != "__END__") {
|
|
154 m_height++;
|
|
155 m_program.push_back(rline);
|
|
156 if(rline.size()>m_width)
|
|
157 m_width = rline.size();
|
|
158 }
|
|
159 for(vector<string>::iterator cline = m_program.begin(); cline!=m_program.end();++cline) {
|
|
160 (*cline).append(m_width-cline->size(),' ');
|
|
161 }
|
|
162 sranddev();
|
|
163 }
|
|
164
|
|
165 inline void Axo2Interpreter::execute_command(char command) {
|
|
166 stack_item a,b;
|
|
167 int tmpd;
|
|
168 if(m_mode != mode_raw) {
|
|
169 switch(command) {
|
|
170 case '^':
|
|
171 m_dx= 0;m_dy=-1;
|
|
172 return;
|
|
173 case '<':
|
|
174 m_dx=-1;m_dy= 0;
|
|
175 return;
|
|
176 case '>':
|
|
177 m_dx= 1;m_dy= 0;
|
|
178 return;
|
|
179 case '%':
|
|
180 m_dx= 0;m_dy= 1;
|
|
181 return;
|
|
182 case '+':
|
|
183 push(pop()+pop());
|
|
184 return;
|
|
185 case '-':
|
|
186 a=pop();
|
|
187 push(pop()-a);
|
|
188 return;
|
|
189 case '*':
|
|
190 push(pop()*pop());
|
|
191 return;
|
|
192 case '/':
|
|
193 a=pop();
|
|
194 b=pop();
|
|
195 push(b/a);
|
|
196 push(b%a);
|
|
197 return;
|
|
198 case '\\':
|
|
199 m_running = false;
|
|
200 return;
|
|
201 }
|
|
202 }
|
|
203 if(m_mode == mode_command) {
|
|
204 switch(command) {
|
|
205 case '&':
|
|
206 enqueue(pop());
|
|
207 return;
|
|
208 case '|':
|
|
209 push(dequeue());
|
|
210 return;
|
|
211 case '$':
|
|
212 set_direction(pop());
|
|
213 return;
|
|
214 case '#':
|
|
215 if(!pop())
|
|
216 move();
|
|
217 return;
|
|
218 case '[':
|
|
219 push(peak());
|
|
220 return;
|
|
221 case ']':
|
|
222 pop();
|
|
223 return;
|
|
224 case '(':
|
|
225
|
|
226 m_output->put((char)(pop()&0xFF));
|
|
227 m_output->flush();
|
|
228 return;
|
|
229 case ')':
|
|
230 char inchar;
|
|
231 m_input->get(inchar);
|
|
232 if(m_input->eof())
|
|
233 push(-1);
|
|
234 else
|
|
235 push(((stack_item)inchar)&0xFF);
|
|
236 return;
|
|
237 case '{':
|
|
238 (*m_output) << pop();
|
|
239 return;
|
|
240 case '}':
|
|
241 char ic;
|
|
242 stack_item cnum;
|
|
243 bool neg;
|
|
244 cnum = 0;
|
|
245
|
|
246 do m_input->get(ic);
|
|
247 while(ic < '0' || ic > '9' && ic != '-');
|
|
248
|
|
249 neg = false;
|
|
250 if(ic == '-') {
|
|
251 neg = true;
|
|
252 m_input->get(ic);
|
|
253 }
|
|
254
|
|
255 while(ic >= '0' && ic <= '9') {
|
|
256 cnum = cnum * 10 + ic-'0';
|
|
257 m_input->get(ic);
|
|
258 }
|
|
259
|
|
260 while(ic != '\n')
|
|
261 m_input->get(ic);
|
|
262
|
|
263 if(neg)
|
|
264 cnum = -cnum;
|
|
265
|
|
266 push(cnum);
|
|
267
|
|
268 return;
|
|
269 case '"':
|
|
270 m_mode = mode_string;
|
|
271 return;
|
|
272 case '\'':
|
|
273 m_mode = mode_raw;
|
|
274 return;
|
|
275 case ':':
|
|
276 m_reg_a = pop();
|
|
277 return;
|
|
278 case ';':
|
|
279 push(m_reg_a);
|
|
280 return;
|
|
281 case '.':
|
|
282 m_reg_b = pop();
|
|
283 return;
|
|
284 case ',':
|
|
285 push(m_reg_b);
|
|
286 return;
|
|
287 case '?':
|
|
288 set_direction(random());
|
|
289 return;
|
|
290 case '_':
|
|
291 m_x = -1;
|
|
292 m_y = 0;
|
|
293 m_dx = 1;
|
|
294 m_dy = 0;
|
|
295 return;
|
|
296 case '@':
|
|
297 clear_stack();
|
|
298 return;
|
|
299 case '!':
|
|
300 tmpd = m_dx;
|
|
301 m_dx=-m_dy;
|
|
302 m_dy=tmpd;
|
|
303 return;
|
|
304 case '=':
|
|
305 a = pop();
|
|
306 b = pop();
|
|
307 push(m_mem[a&2047]);
|
|
308 m_mem[a&2047]=b;
|
|
309 return;
|
|
310 case '~':
|
|
311 cerr << "\n[ ";
|
|
312 bool first;
|
|
313 first = true;
|
|
314 for(deque<stack_item>::const_iterator i = m_stack.begin();i != m_stack.end();i++){
|
|
315 if(!first)
|
|
316 cerr << " | ";
|
|
317 cerr << *i;
|
|
318 first = false;
|
|
319 }
|
|
320 cerr << " ] a:" << m_reg_a << " b:" << m_reg_b << " x:" << m_x << " y:" << m_y << endl;
|
|
321
|
|
322 return;
|
|
323 default:
|
|
324 if(command >= '0' and command <= '9'){
|
|
325 push(command-'0');
|
|
326 return;
|
|
327 }
|
|
328 }
|
|
329 }
|
|
330 if(m_mode == mode_string) {
|
|
331 if(command == '"')
|
|
332 m_mode = mode_command;
|
|
333 else if(command == '$')
|
|
334 push(10);
|
|
335 else
|
|
336 push(((stack_item)command)&0xFF);
|
|
337 }
|
|
338 else if(m_mode == mode_raw) {
|
|
339 if(command == '\'')
|
|
340 m_mode = mode_command;
|
|
341 else
|
|
342 push(((stack_item)command)&0xFF);
|
|
343 }
|
|
344 }
|
|
345
|
|
346 // quick and dirty cli
|
|
347
|
|
348 void usage() {
|
|
349 cerr << "Usage: axopp <sourcefile>" << endl;
|
|
350 exit(1);
|
|
351 }
|
|
352
|
|
353 int main(int argc, char * const argv[]) {
|
|
354 if(argc != 2)
|
|
355 usage();
|
|
356
|
|
357
|
|
358 if(argv[1][0] == '-' && argv[1][1] == 0) {
|
|
359 Axo2Interpreter i(cin);
|
|
360 i.run();
|
|
361 }
|
|
362 else {
|
|
363 ifstream inf;
|
|
364 inf.open(argv[1],ios::in);
|
|
365 if(!inf.is_open()) {
|
|
366 cerr << "Couldn't open sourcefile." << endl;
|
|
367 return 1;
|
|
368 }
|
|
369 Axo2Interpreter i(inf);
|
|
370 i.run();
|
|
371 inf.close();
|
|
372 }
|
|
373
|
|
374
|
|
375
|
|
376 return 0;
|
|
377 }
|
|
378
|