Browse code
initial
fiddlerwoaroof authored on 20/07/2014 06:34:23
Showing 3 changed files
Showing 3 changed files
1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,517 @@ |
1 |
+from __future__ import print_function |
|
2 |
+import sys |
|
3 |
+import inspect |
|
4 |
+SPACE = None |
|
5 |
+class _RUN: pass |
|
6 |
+ |
|
7 |
+def read_word(fil): |
|
8 |
+ char = ' ' |
|
9 |
+ buffer = [] |
|
10 |
+ delim = SPACE |
|
11 |
+ spaces = {' ', '\n', '\t'} |
|
12 |
+ while char != '': |
|
13 |
+ char = fil.read(1) |
|
14 |
+ if char == '': |
|
15 |
+ yield ''.join(buffer).strip() |
|
16 |
+ break |
|
17 |
+ buffer.append(char) |
|
18 |
+ if delim != SPACE and buffer[-len(delim):] == delim: |
|
19 |
+ delim = yield ''.join(buffer[:-len(delim)]) |
|
20 |
+ buffer = [] |
|
21 |
+ elif char in spaces: |
|
22 |
+ delim = yield ''.join(buffer[:-1]).strip() |
|
23 |
+ if char == '\n': |
|
24 |
+ yield _RUN |
|
25 |
+ buffer = [] |
|
26 |
+ |
|
27 |
+def skip_run(reader): |
|
28 |
+ skipped = False |
|
29 |
+ r = reader.next() |
|
30 |
+ while r == _RUN: |
|
31 |
+ skipped = skipped or r == _RUN |
|
32 |
+ #print(r, end=':') |
|
33 |
+ r = reader.next() |
|
34 |
+ #print(r, end=' ') |
|
35 |
+ #print('out') |
|
36 |
+ return r, skipped |
|
37 |
+ |
|
38 |
+import collections |
|
39 |
+import traceback |
|
40 |
+class SymbolDict(collections.MutableMapping): |
|
41 |
+ def __init__(self, *args, **kwargs): |
|
42 |
+ self.ctr = 0 |
|
43 |
+ self.items_ = set() |
|
44 |
+ self.dct = dict(*args, **kwargs) |
|
45 |
+ |
|
46 |
+ def __getitem__(self, key): |
|
47 |
+ if self.dct[key] != []: |
|
48 |
+ return self.dct[key][-1][1] |
|
49 |
+ else: |
|
50 |
+ raise KeyError("No such key '%s'" % key) |
|
51 |
+ def __setitem__(self, key, value): |
|
52 |
+ self.ctr += 1 |
|
53 |
+ self.items_.add(key) |
|
54 |
+ self.dct.setdefault(key, []).append((self.ctr, value)) |
|
55 |
+ def __delitem__(self, key): |
|
56 |
+ state = self.dct[key][-1][0] |
|
57 |
+ for a in self.dct.keys(): |
|
58 |
+ while self.dct[a] and self.dct[a][-1][0] >= state: |
|
59 |
+ self.dct[a].pop() |
|
60 |
+ if self.dct[a] == []: self.dct.pop(a) |
|
61 |
+ forget = __delitem__ |
|
62 |
+ def __iter__(self): |
|
63 |
+ return (x for x in self.dct.keys()) |
|
64 |
+ def __len__(self): |
|
65 |
+ return len(self.dct) |
|
66 |
+ |
|
67 |
+import random |
|
68 |
+ |
|
69 |
+class Reader(object): |
|
70 |
+ symbols = SymbolDict() |
|
71 |
+ |
|
72 |
+ def rev_pctr(self, stack, rstack): |
|
73 |
+ num = stack.pop() |
|
74 |
+ self.program_ctr -= num |
|
75 |
+ |
|
76 |
+ def adv_pctr(self, stack, rstack): |
|
77 |
+ num = stack.pop() |
|
78 |
+ self.program_ctr += num |
|
79 |
+ |
|
80 |
+ def adv_pctr0(self, stack, rstack): |
|
81 |
+ #print('adv0 -->', stack, rstack) |
|
82 |
+ num = stack.pop() |
|
83 |
+ cond = stack.pop() |
|
84 |
+ if cond == 0: |
|
85 |
+ stack.append(num) |
|
86 |
+ self.adv_pctr(stack, rstack) |
|
87 |
+ |
|
88 |
+ def save_program_ctr(self): |
|
89 |
+ self.pcs.append(self.program_ctr) |
|
90 |
+ def restore_program_ctr(self): |
|
91 |
+ self.program_ctr = self.pcs.pop() |
|
92 |
+ def rollback_program(self): |
|
93 |
+ self.restore_program_ctr() |
|
94 |
+ del self.program[self.program_ctr:] |
|
95 |
+ def splice_program(self, words): |
|
96 |
+ begin = self.peek_saved_program_ctr() |
|
97 |
+ end = self.program_ctr + 1 |
|
98 |
+ self.program[begin:end] = words |
|
99 |
+ def peek_saved_program_ctr(self): |
|
100 |
+ return self.pcs[-1] |
|
101 |
+ def drop_saved_program_ctr(self): |
|
102 |
+ return self.pcs.pop() |
|
103 |
+ |
|
104 |
+ def if_(self, stack, rstack=None): |
|
105 |
+ def if_reader(gen): |
|
106 |
+ counter = 0 |
|
107 |
+ if_clause = [] |
|
108 |
+ else_clause = [] |
|
109 |
+ cur_clause = if_clause |
|
110 |
+ for word in gen: |
|
111 |
+ if word == 'if': |
|
112 |
+ cur_clause.extend(if_reader(gen)) |
|
113 |
+ continue |
|
114 |
+ elif word == 'else': |
|
115 |
+ cur_clause = else_clause |
|
116 |
+ continue |
|
117 |
+ elif word == 'then': |
|
118 |
+ else_clause.extend(['nop']) |
|
119 |
+ break |
|
120 |
+ cur_clause.extend(self.expand_word(word)) |
|
121 |
+ if_clause.extend(['%d' % len(else_clause), 'adv']) |
|
122 |
+ if_clause.insert(0, '%d' % len(if_clause)) |
|
123 |
+ if_clause.insert(1, 'adv0') |
|
124 |
+ result = if_clause + else_clause |
|
125 |
+ return result |
|
126 |
+ |
|
127 |
+ ## Below we replace the if statement with a call to lower-level primitives |
|
128 |
+ ## i.e. if is implemented as a kind of macro. |
|
129 |
+ self.save_program_ctr() |
|
130 |
+ self.program_ctr += 1 # since the program counter doesn't update until after the yield |
|
131 |
+ gen = self.read_word() |
|
132 |
+ self.splice_program(if_reader(gen)) |
|
133 |
+ self.restore_program_ctr() |
|
134 |
+ self.program_ctr -= 1 # in order to pick up the beginning of the if statement |
|
135 |
+ |
|
136 |
+ def words(self, stack, rstack=None): |
|
137 |
+ words = sorted(self.symbols.keys()) |
|
138 |
+ mlen = max(len(x) for x in words) |
|
139 |
+ c = 80 // (mlen + 2) |
|
140 |
+ while words: |
|
141 |
+ head, words = words[:c], words[c:] |
|
142 |
+ print(' '.join(x.center(mlen) for x in head)) |
|
143 |
+ |
|
144 |
+ def forget(self, stack, rstack=None): |
|
145 |
+ self.program_ctr += 1 # since the program counter doesn't update until after the yield |
|
146 |
+ name, skipped = skip_run(self.read_word()) |
|
147 |
+ self.symbols.forget(name) |
|
148 |
+ if skipped: self.inp.append([_RUN]) |
|
149 |
+ |
|
150 |
+ def colon(self, stack, rstack=None): |
|
151 |
+ self.program_ctr += 1 # since the program counter doesn't update until after the yield |
|
152 |
+ gen = self.read_word() |
|
153 |
+ name = gen.next() |
|
154 |
+ word = ' ' |
|
155 |
+ conts = [] |
|
156 |
+ while word != ';': |
|
157 |
+ word = gen.next() |
|
158 |
+ if word == _RUN: continue |
|
159 |
+ conts.append(word) |
|
160 |
+ conts.pop() # pop off the semicolon |
|
161 |
+ |
|
162 |
+ self.compile(name, filter(None,conts)) |
|
163 |
+ #print(' >name', name, ' >symbols["%s"]' % name, self.symbols[name.lower()]) |
|
164 |
+ |
|
165 |
+ def expand_word(self, word): |
|
166 |
+ if word in self.sym_words: |
|
167 |
+ outp = [self.expand_word(w) for w in self.sym_words[word][:]] |
|
168 |
+ return sum(outp, []) |
|
169 |
+ else: |
|
170 |
+ return [word] |
|
171 |
+ |
|
172 |
+ def compile(self, name, words): |
|
173 |
+ if hasattr(words, 'split'): words = words.split() |
|
174 |
+ self.sym_words[name] = words[:] |
|
175 |
+ @self.add_symbol(name) |
|
176 |
+ def newfun(stack, rstack=None): |
|
177 |
+ self.save_program_ctr() |
|
178 |
+ self.splice_program(words[:]) |
|
179 |
+ self.program_ctr -= 1 |
|
180 |
+ newfun.__name__ = '_forth_%s' % name |
|
181 |
+ def prog_print(self, stack, rstack=None): |
|
182 |
+ print('<%d>' % len(self.program), end=' ') |
|
183 |
+ for n in self.program: |
|
184 |
+ print(n, end=' ') |
|
185 |
+ print() |
|
186 |
+ |
|
187 |
+ def set_pctr(self, v): |
|
188 |
+ self.program_ctr = v |
|
189 |
+ def begin_until(self, stack, rstack): |
|
190 |
+ self.program_ctr += 1 # since the program counter doesn't update until after the yield |
|
191 |
+ mark = self.program_ctr |
|
192 |
+ word = ' ' |
|
193 |
+ loop_count = 0 |
|
194 |
+ words = [] |
|
195 |
+ while True: |
|
196 |
+ word = self.read_word() |
|
197 |
+ if word == 'begin': loop_count += 1 |
|
198 |
+ elif word == 'until': |
|
199 |
+ if loop_count == 0: break |
|
200 |
+ else: loop_count -= 1 |
|
201 |
+ words.append(word) |
|
202 |
+ |
|
203 |
+ def mark_r(self, stack, rstack): |
|
204 |
+ self.jmpr.append(self.program_ctr-1) |
|
205 |
+ #print('markr', self.jmpr) |
|
206 |
+ def jmp_r(self, stack, rstack): |
|
207 |
+ dst = self.jmpr.pop() |
|
208 |
+ self.set_pctr(dst) |
|
209 |
+ #print('jmpr', dst, self.jmpr) |
|
210 |
+ def jmp_clr(self, stack, rstack): |
|
211 |
+ self.jmpr.pop() |
|
212 |
+ #print('clrjmp', self.jmpr) |
|
213 |
+ |
|
214 |
+ def mark(self, stack, rstack): |
|
215 |
+ self.stack.append(self.program_ctr-1) |
|
216 |
+ def jmp(self, stack, rstack): |
|
217 |
+ dst = stack.pop() |
|
218 |
+ self.set_pctr(dst) |
|
219 |
+ |
|
220 |
+ def __init__(self): |
|
221 |
+ self.sym_words = SymbolDict() |
|
222 |
+ self.stack = [] |
|
223 |
+ self.rstack = [] |
|
224 |
+ self.program = [] |
|
225 |
+ self.jmpr = [] |
|
226 |
+ self.pcs = [] |
|
227 |
+ self.mode = 0; # 0 - Normal; 1 - string reading |
|
228 |
+ self.program_ctr = 0 |
|
229 |
+ self.add_symbol('words')(self.words) |
|
230 |
+ self.add_symbol('.p')(self.prog_print) |
|
231 |
+ self.add_symbol(':')(self.colon) |
|
232 |
+ self.add_symbol('forget')(self.forget) |
|
233 |
+ self.add_symbol('if')(self.if_) |
|
234 |
+ self.add_symbol('jmp')(self.jmp) |
|
235 |
+ self.add_symbol('rev')(self.rev_pctr) |
|
236 |
+ self.add_symbol('adv')(self.adv_pctr) |
|
237 |
+ self.add_symbol('adv0')(self.adv_pctr0) |
|
238 |
+ self.add_symbol('mark')(self.mark) |
|
239 |
+ self.add_symbol('markr')(self.mark_r) |
|
240 |
+ self.add_symbol('jmpr')(self.jmp_r) |
|
241 |
+ self.add_symbol('clrjmp')(self.jmp_clr) |
|
242 |
+ |
|
243 |
+ def __getword(self): |
|
244 |
+ while self.inp[-1] == []: self.inp.pop() |
|
245 |
+ if hasattr(self.inp[-1], 'read'): |
|
246 |
+ self.inp[-1] = read_word(self.inp[-1]) |
|
247 |
+ if hasattr(self.inp[-1], 'next'): |
|
248 |
+ result = self.inp[-1].next() |
|
249 |
+ else: |
|
250 |
+ result = self.inp[-1].pop(0) |
|
251 |
+ self.program.append(result) |
|
252 |
+ |
|
253 |
+ def read_word(self): |
|
254 |
+ while True: |
|
255 |
+ while self.program_ctr >= len(self.program): |
|
256 |
+ self.__getword() |
|
257 |
+ yield self.program[self.program_ctr] |
|
258 |
+ self.program_ctr += 1 |
|
259 |
+ |
|
260 |
+ def read(self, inp, silent=False): |
|
261 |
+ self.inp = [inp] |
|
262 |
+ delim = SPACE |
|
263 |
+ if not silent: print(self.program_ctr, end='? ') |
|
264 |
+ for word in self.read_word(): |
|
265 |
+ #print('<%s>' % word, end=' ') |
|
266 |
+ if word == _RUN: |
|
267 |
+ if not silent: |
|
268 |
+ print(' ok') |
|
269 |
+ print(self.program_ctr, end='? ') |
|
270 |
+ continue |
|
271 |
+ elif word == '."': |
|
272 |
+ out = [] |
|
273 |
+ word = self.__getword() |
|
274 |
+ while word != '"': |
|
275 |
+ out.append(self.__getword) |
|
276 |
+ word = self.__getword() |
|
277 |
+ print(' '.join(out)) |
|
278 |
+ continue |
|
279 |
+ elif word == '': continue |
|
280 |
+ self.stack.append(word) |
|
281 |
+ self.lookup() |
|
282 |
+ def lookup(self, sym=None): |
|
283 |
+ if sym is None: |
|
284 |
+ sym = self.stack.pop() |
|
285 |
+ result = None |
|
286 |
+ if sym.lower() in self.symbols: |
|
287 |
+ result = self.symbols[sym.lower()](self.stack, self.rstack) |
|
288 |
+ else: |
|
289 |
+ result = self.numberp(sym) |
|
290 |
+ if result is None: raise ValueError("Symbol %r not found" % sym) |
|
291 |
+ else: |
|
292 |
+ self.stack.append(result) |
|
293 |
+ return result |
|
294 |
+ def numberp(self, sym): |
|
295 |
+ is_valid = -1 # -1 = undecided, 0 = False, 1 = True |
|
296 |
+ typ = int |
|
297 |
+ dot_acceptable = False |
|
298 |
+ if sym == '': is_valid = 0 |
|
299 |
+ elif not (sym.startswith('-') or sym[0].isdigit()): is_valid = 0 |
|
300 |
+ if is_valid == 0: return None |
|
301 |
+ else: |
|
302 |
+ for char in sym[1:]: |
|
303 |
+ if char.isdigit(): dot_acceptable = True |
|
304 |
+ elif dot_acceptable and char == '.': typ = float |
|
305 |
+ elif dot_acceptable and char == 'e': typ = float |
|
306 |
+ else: |
|
307 |
+ return None |
|
308 |
+ else: |
|
309 |
+ return typ(sym) |
|
310 |
+ @classmethod |
|
311 |
+ def add_symbol(cls, name): |
|
312 |
+ def _i1(func): |
|
313 |
+ cls.symbols[name.lower()] = func |
|
314 |
+ return func |
|
315 |
+ return _i1 |
|
316 |
+ |
|
317 |
+@Reader.add_symbol('J') |
|
318 |
+def J(stack, rstack): |
|
319 |
+ stack.append(rstack[-3]) |
|
320 |
+ |
|
321 |
+@Reader.add_symbol('R@') |
|
322 |
+def rAt(stack, rstack): |
|
323 |
+ stack.append(rstack[-1]) |
|
324 |
+ |
|
325 |
+@Reader.add_symbol('I') |
|
326 |
+def I(stack, rstack): |
|
327 |
+ stack.append(rstack[-1]) |
|
328 |
+ |
|
329 |
+@Reader.add_symbol('R>') |
|
330 |
+def movP(stack, rstack): |
|
331 |
+ stack.append(rstack.pop()) |
|
332 |
+ |
|
333 |
+@Reader.add_symbol('>R') |
|
334 |
+def movR(stack, rstack): |
|
335 |
+ rstack.append(stack.pop()) |
|
336 |
+ |
|
337 |
+@Reader.add_symbol('2over') |
|
338 |
+def _2over(stack, rstack=None): |
|
339 |
+ d, c, b, a = [stack.pop() for _ in range(4)] |
|
340 |
+ stack.append(a) |
|
341 |
+ stack.append(b) |
|
342 |
+ stack.append(c) |
|
343 |
+ stack.append(d) |
|
344 |
+ stack.append(a) |
|
345 |
+ stack.append(b) |
|
346 |
+ |
|
347 |
+@Reader.add_symbol('2dup') |
|
348 |
+def _2dup(stack, rstack=None): |
|
349 |
+ b, a = [stack.pop() for _ in range(2)] |
|
350 |
+ stack.append(a) |
|
351 |
+ stack.append(b) |
|
352 |
+ stack.append(a) |
|
353 |
+ stack.append(b) |
|
354 |
+ |
|
355 |
+@Reader.add_symbol('2swap') |
|
356 |
+def _2swap(stack, rstack=None): |
|
357 |
+ d, c, b, a = [stack.pop() for _ in range(4)] |
|
358 |
+ stack.append(c) |
|
359 |
+ stack.append(d) |
|
360 |
+ stack.append(a) |
|
361 |
+ stack.append(b) |
|
362 |
+ |
|
363 |
+@Reader.add_symbol('.r') |
|
364 |
+def stack_print(stack, rstack=None): |
|
365 |
+ print('<%d>' % len(rstack), end=' ') |
|
366 |
+ for n in rstack: |
|
367 |
+ print(n, end=' ') |
|
368 |
+ print() |
|
369 |
+ |
|
370 |
+@Reader.add_symbol('.s') |
|
371 |
+def stack_print(stack, rstack=None): |
|
372 |
+ print('<%d>' % len(stack), end=' ') |
|
373 |
+ for n in stack: |
|
374 |
+ print(n, end=' ') |
|
375 |
+ print() |
|
376 |
+ |
|
377 |
+@Reader.add_symbol('drop') |
|
378 |
+def drop(stack, rstack=None): |
|
379 |
+ stack.pop() |
|
380 |
+ |
|
381 |
+@Reader.add_symbol('rot') |
|
382 |
+def rot(stack, rstack=None): |
|
383 |
+ n1, n2, n3 = stack.pop(), stack.pop(), stack.pop() |
|
384 |
+ #a, b, c |
|
385 |
+ stack.extend([n2, n1, n3]) |
|
386 |
+ |
|
387 |
+@Reader.add_symbol('dup') |
|
388 |
+def dup(stack, rstack=None): |
|
389 |
+ a = stack.pop() |
|
390 |
+ stack.append(a) |
|
391 |
+ stack.append(a) |
|
392 |
+ |
|
393 |
+@Reader.add_symbol('over') |
|
394 |
+def over(stack, rstack=None): |
|
395 |
+ b, a = stack.pop(), stack.pop() |
|
396 |
+ stack.append(a) |
|
397 |
+ stack.append(b) |
|
398 |
+ stack.append(a) |
|
399 |
+ |
|
400 |
+@Reader.add_symbol('swap') |
|
401 |
+def swap(stack, rstack=None): |
|
402 |
+ b, a = stack.pop(), stack.pop() |
|
403 |
+ stack.append(b) |
|
404 |
+ stack.append(a) |
|
405 |
+ |
|
406 |
+@Reader.add_symbol('%') |
|
407 |
+def mod(stack, rstack=None): |
|
408 |
+ b, a = stack.pop(), stack.pop() |
|
409 |
+ stack.append(a % b) |
|
410 |
+ |
|
411 |
+@Reader.add_symbol('/') |
|
412 |
+def div(stack, rstack=None): |
|
413 |
+ b, a = stack.pop(), stack.pop() |
|
414 |
+ stack.append(a / b) |
|
415 |
+ |
|
416 |
+@Reader.add_symbol('*') |
|
417 |
+def mul(stack, rstack=None): |
|
418 |
+ b, a = stack.pop(), stack.pop() |
|
419 |
+ stack.append(a * b) |
|
420 |
+ |
|
421 |
+@Reader.add_symbol('-') |
|
422 |
+def min_(stack, rstack=None): |
|
423 |
+ b, a = stack.pop(), stack.pop() |
|
424 |
+ stack.append(a - b) |
|
425 |
+ |
|
426 |
+@Reader.add_symbol('+') |
|
427 |
+def add(stack, rstack=None): |
|
428 |
+ b, a = stack.pop(), stack.pop() |
|
429 |
+ stack.append(a + b) |
|
430 |
+ |
|
431 |
+@Reader.add_symbol('and') |
|
432 |
+def and_(stack, rstack=None): |
|
433 |
+ b, a = stack.pop(), stack.pop() |
|
434 |
+ stack.append(a and b) |
|
435 |
+ |
|
436 |
+@Reader.add_symbol('or') |
|
437 |
+def or_(stack, rstack=None): |
|
438 |
+ b, a = stack.pop(), stack.pop() |
|
439 |
+ stack.append(a or b) |
|
440 |
+ |
|
441 |
+@Reader.add_symbol('.') |
|
442 |
+def period(stack, rstack=None): |
|
443 |
+ print(stack.pop(), end=' ') |
|
444 |
+ |
|
445 |
+@Reader.add_symbol('emit') |
|
446 |
+def emit(stack, rstack=None): |
|
447 |
+ print(chr(stack.pop()), end='') |
|
448 |
+ |
|
449 |
+@Reader.add_symbol('=') |
|
450 |
+def eql(stack, rstack=None): |
|
451 |
+ b, a = stack.pop(), stack.pop() |
|
452 |
+ stack.append(int(a == b)) |
|
453 |
+ |
|
454 |
+@Reader.add_symbol('<') |
|
455 |
+def lt(stack, rstack=None): |
|
456 |
+ b, a = stack.pop(), stack.pop() |
|
457 |
+ stack.append(int(a < b)) |
|
458 |
+ |
|
459 |
+@Reader.add_symbol('>') |
|
460 |
+def gt(stack, rstack=None): |
|
461 |
+ b, a = stack.pop(), stack.pop() |
|
462 |
+ stack.append(int(a > b)) |
|
463 |
+ |
|
464 |
+@Reader.add_symbol('nop') |
|
465 |
+def nop(*_): |
|
466 |
+ pass |
|
467 |
+ |
|
468 |
+@Reader.add_symbol('clear') |
|
469 |
+def clear(stack, rstack): |
|
470 |
+ del stack[:] |
|
471 |
+ del rstack[:] |
|
472 |
+ |
|
473 |
+if __name__ == '__main__': |
|
474 |
+ import sys |
|
475 |
+ reader = Reader() |
|
476 |
+ reader.compile(*'0= 0 ='.split(None,1)) |
|
477 |
+ reader.compile(*'0> 0 >'.split(None,1)) |
|
478 |
+ reader.compile(*'0< 0 <'.split(None,1)) |
|
479 |
+ reader.compile('cr', ['10', 'emit']) |
|
480 |
+ reader.compile('2drop', ['drop', 'drop']) |
|
481 |
+ reader.compile('false', ['0']) |
|
482 |
+ reader.compile('true', ['-1']) |
|
483 |
+ reader.compile('invert', ['0=', 'if', 'true', 'else', 'false', 'then']) |
|
484 |
+ reader.compile('?dup', 'dup if dup then'.split()) |
|
485 |
+ reader.compile('1+', '1 +'.split()) |
|
486 |
+ reader.compile('1-', '1 -'.split()) |
|
487 |
+ reader.compile('2+', '2 +'.split()) |
|
488 |
+ reader.compile('2-', '2 -'.split()) |
|
489 |
+ reader.compile('2*', '2 *'.split()) |
|
490 |
+ reader.compile('2/', '2 /'.split()) |
|
491 |
+ reader.compile('abs', 'dup 0< if -1 * then'.split()) |
|
492 |
+ reader.compile('negate', '-1 *'.split()) |
|
493 |
+ reader.compile('min', '2dup - 0> if swap then drop') |
|
494 |
+ reader.compile('max', '2dup - 0< if swap then drop') |
|
495 |
+ reader.compile('*/', 'rot rot * swap /') |
|
496 |
+ reader.compile('*/mod', 'rot rot * swap /mod') |
|
497 |
+ reader.compile('/mod1', '2dup % dup 2swap / rot drop') |
|
498 |
+ reader.compile('mark>r', 'mark >r') |
|
499 |
+ reader.compile('arrow', '45 emit 45 emit 62 emit') |
|
500 |
+ reader.compile('loop0', '0= arrow .s if 98 emit cr else 97 emit cr .s r> .s jmp then') |
|
501 |
+ reader.compile(*'spaces 0 do 32 emit loop'.split(None, 1)) |
|
502 |
+ reader.compile(*'do swap >r >r begin'.split(None, 1)) |
|
503 |
+ reader.compile('rdrop', 'r> drop') |
|
504 |
+ reader.compile(*'loop r> 1+ r> 2dup >r >r < invert until rdrop rdrop'.split(None, 1)) |
|
505 |
+ reader.compile('begin', 'markr') |
|
506 |
+ reader.compile('until', 'invert if jmpr else clrjmp then') |
|
507 |
+ |
|
508 |
+ import argparse |
|
509 |
+ parser = argparse.ArgumentParser() |
|
510 |
+ parser.add_argument('file', nargs='?') |
|
511 |
+ args = parser.parse_args() |
|
512 |
+ if args.file == '-' or args.file == None: |
|
513 |
+ fil = sys.stdin |
|
514 |
+ reader.read(sys.stdin) |
|
515 |
+ else: |
|
516 |
+ with open(args.file) as f: |
|
517 |
+ reader.read(f, silent=True) |