comparison bin/gs2.py @ 9075:c989a1669243

<fizzie> revert 58b9ee8f97a7
author HackBot
date Sun, 25 Sep 2016 20:31:46 +0000
parents
children
comparison
equal deleted inserted replaced
9074:560a73f4f0a4 9075:c989a1669243
1 # gs2 interpreter (version 0.2)
2 # (c) nooodl 2014
3
4 import copy
5 import inspect
6 import itertools as it
7 import math
8 import operator
9 import os
10 import random
11 import re
12 import string
13 import struct
14 import sys
15 import traceback
16
17 from collections import namedtuple
18 from fractions import gcd
19
20 Block = namedtuple('Block', 'code')
21 STRING_ENDS = '\x05\x06' + ''.join(map(chr, range(0x9b, 0xa0)))
22
23 DEBUG = False
24
25 def log(x):
26 if not DEBUG: return
27 line, name = inspect.stack()[1][2:4]
28 sys.stderr.write('\x1b[36m%s:%d\x1b[34m: %r\x1b[0m\n' % (name, line, x))
29
30 def lcm(a, b):
31 if (a, b) == (0, 0): return 0
32 return abs(a * b) // gcd(a, b)
33
34 def product(xs):
35 p = 1
36 for x in xs:
37 p *= x
38 return p
39
40 def split(a, b, clean=False):
41 res = [[]]
42 lb = len(b)
43
44 i = 0
45 while i < len(a):
46 if a[i:i + lb] == b:
47 res.append([])
48 i += lb
49 else:
50 res[-1].append(a[i])
51 i += 1
52
53 return filter(None, res) if clean else res
54
55 def join(a, b):
56 res = []
57 for i, x in enumerate(a):
58 if i > 0:
59 res.extend(b)
60 res.extend(x if is_list(x) else [x])
61 return res
62
63 def set_diff(a, b):
64 res = []
65 for i in a:
66 if i not in b:
67 res.append(i)
68 return res
69
70 def set_and(a, b):
71 res = []
72 for i in a:
73 if i in b:
74 res.append(i)
75 return res
76
77 def set_or(a, b):
78 return a + set_diff(b, a)
79
80 def set_xor(a, b):
81 return set_diff(a, b) + set_diff(b, a)
82
83 # prime number functions
84 prime_list = []
85 sieved = 2
86 composite = set([1])
87
88 def sieve(limit):
89 global prime_list
90 global sieved
91 global composite
92 if limit <= sieved: return
93
94 prime_list = []
95 for i in range(2, limit):
96 if i in composite: continue
97 for j in range(i*i, limit, i):
98 composite.add(j)
99 prime_list.append(i)
100 sieved = limit
101
102 sieve(1000)
103
104 def is_prime(n):
105 global prime_list
106 sieve(n+1)
107 return n not in composite
108
109 def nth_prime(n):
110 global prime_list
111 sieve(int(math.log(n) * n) + 100)
112 return prime_list[n-1]
113
114 def n_primes(n):
115 global prime_list
116 sieve(int(math.log(n) * n) + 100)
117 return prime_list[:n]
118
119 def primes_below(n):
120 global prime_list
121 sieve(n+1)
122 return list(it.takewhile(lambda x: x < n, prime_list))
123
124 def next_prime(n):
125 n += 1
126 while not is_prime(n): n += 1
127 return n
128
129 def totient(n):
130 count = 0
131 for i in xrange(1, n+1):
132 if gcd(n, i) == 1: count += 1
133 return count
134
135 def factor(n, exps=False):
136 if is_num(n):
137 p = 2
138 res = []
139 while n > 1:
140 while n % p == 0:
141 res.append(p)
142 n //= p
143 p = next_prime(p)
144 if exps:
145 res = [[k, len(list(g))] for k, g in it.groupby(res)]
146 return res
147 elif is_list(n):
148 if n and is_num(n[0]):
149 n = zip(n[0::2], n[1::2])
150 p = 1
151 for b, e in n: p *= b ** e
152 return p
153 else:
154 raise TypeError('factor')
155
156 def chunks(x, y):
157 # chunks(range(12), 3) ==> [[0, 1, 2], [3, 4, 5], ...]
158 while x:
159 yield x[:y]
160 x = x[y:]
161
162 def tokenize(prog):
163 # string hack
164 cs = STRING_ENDS
165 if re.match('^[^\x04]*[%s]' % cs, prog):
166 prog = '\x04' + prog
167
168 mode = None
169 if prog[0] in '\x30\x31\x32': # set mode
170 mode = prog[0]
171 prog = prog[1:]
172
173 token_re = [
174 '\x04[^%s]*[%s]' % (cs, cs), # string (array)
175 '\x01.', # unsigned byte
176 '\x02..', # signed short
177 '\x03....', # signed long
178 '\x07.', # 1 char string
179 '.', # regular token
180 ]
181
182 tokens = re.findall('|'.join(token_re), prog, re.DOTALL)
183
184 final = []
185 blocks = [Block([])]
186 i = 0
187 while i < len(tokens):
188 t = tokens[i]
189 log(tokens[i:])
190 if t == '\x08': #= {
191 blocks.append(Block([]))
192 final.append('\x00')
193 elif t == '\x09': #= }
194 blocks[-2].code.append(blocks.pop())
195 blocks[-1].code.append(final.pop())
196 elif '\xe0' <= t <= '\xff' and ord(t) & 7 < 6:
197 # quick block
198 # 0b111XXYYY -- Y+1 is number of tokens, X is end token:
199 # 0 = nop (0x00) 2 = filter (0x35)
200 # 1 = map (0x34) 3 = both (0x38)
201 # but 0xfe and 0xff are special (see below.)
202 num = (ord(t) & 7) + 1
203 ts = blocks[-1].code[-num:]
204 del blocks[-1].code[-num:]
205 blocks[-1].code.append(Block(ts))
206 blocks[-1].code.append('\x00\x34\x35\x38'[(ord(t) >> 3) & 3])
207 elif t in '\xee\xef': #= z1 zipwith1, z2 zipwith2
208 # zipwith (1/2 tokens)
209 num = (ord(t) & 1) + 1
210 ts = blocks[-1].code[-num:]
211 del blocks[-1].code[-num:]
212 blocks[-1].code.append(Block(ts))
213 blocks[-1].code.append('\xb1')
214 elif t in '\xf6\xf7': #= dm1 dump-map1, df1 dump-filter1
215 # like m1/f1 with dump prepended to block
216 # useful with transpose, pairwise, cartesian-product, etc.
217 f = {'\xf6': '\x34', '\xf7': '\x35'}[t]
218 x = blocks[-1].code.pop()
219 blocks[-1].code.extend([Block(['\x0e', x]), f])
220 elif t == '\xfe': #= m:
221 blocks.append(Block([]))
222 final.append('\x34')
223 elif t == '\xff': #= f:
224 blocks.append(Block([]))
225 final.append('\x35')
226 else:
227 blocks[-1].code.append(t)
228 i += 1
229
230 while final:
231 blocks[-2].code.append(blocks.pop())
232 blocks[-1].code.append(final.pop())
233
234 assert len(blocks) == 1
235 main = blocks[0]
236
237 if mode == '\x30': #= line-mode
238 main = Block(['\x2a', main, '\x34', '\x54'])
239 elif mode == '\x31': #= word-mode
240 main = Block(['\x2c', main, '\x34', '\x55'])
241 elif mode == '\x32': #= line-mode-skip-first
242 main = Block(['\x2a', '\x22', main, '\x34', '\x54'])
243
244 main.code.extend(final)
245 return main
246
247 is_num = lambda v: isinstance(v, (int, long))
248 is_list = lambda v: isinstance(v, list)
249 is_block = lambda v: isinstance(v, Block)
250
251 def to_gs(ps): return map(ord, ps)
252
253 def to_ps(gs):
254 if is_list(gs): return ''.join(map(chr, gs))
255 else: return chr(gs)
256
257 def regex_count(pattern):
258 c = 0
259 if pattern[0] == ']':
260 c = 1
261 pattern = pattern[1:]
262 elif pattern[0] == '}':
263 c = ord(pattern[1])
264 pattern = pattern[2:]
265 return (c, pattern)
266
267 def show(value, nest=False):
268 if is_list(value):
269 return ''.join(show(x, nest=True) for x in value)
270 elif nest and is_num(value):
271 return chr(value)
272 else:
273 return str(value)
274
275 class Stack(list):
276 def __init__(self, *args):
277 list.__init__(self, *args)
278 self.junk = []
279 def pop(self, i=-1, junk=True):
280 x = list.pop(self, i)
281 if junk: self.junk.append(x)
282 return x
283
284 class GS2(object):
285 def __init__(self, code, stdin=''):
286 self.code = code
287 self.stdin = to_gs(stdin)
288 self.stack = Stack([self.stdin])
289 self.regs = {
290 0: to_gs(stdin), # A
291 1: len(stdin), # B
292 2: to_gs(code), # C
293 3: random.randint(0, 2), # D
294 }
295 self.counter = 1
296
297 def run(self):
298 try:
299 self.evaluate(tokenize(self.code))
300 sys.stdout.write(''.join(map(show, self.stack)))
301 except Exception:
302 # If the code fails, print something meaningful to stderr,
303 # but quine on stdout: this allows GS2 to good at simple
304 # "print this string" programs -- just upload a plaintext
305 # file, it's unlikely to be valid GS2 code.
306 traceback.print_exc()
307 if not DEBUG: sys.stdout.write(self.code)
308
309 def evaluate(self, block):
310 log(block)
311 for t in block.code:
312 if is_block(t):
313 self.stack.append(t)
314 elif t[0] == '\x00': #= nop
315 pass
316 elif t[0] == '\x01': # push unsigned byte
317 self.stack.append(struct.unpack('<B', t[1:])[0])
318 elif t[0] == '\x02': # push signed short
319 self.stack.append(struct.unpack('<h', t[1:])[0])
320 elif t[0] == '\x03': # push signed long
321 self.stack.append(struct.unpack('<l', t[1:])[0])
322
323 elif t[0] == '\x04': # string
324 assert len(t) >= 2
325 assert t[-1] in STRING_ENDS
326 strings = t[1:-1].split('\x07')
327 strings = map(to_gs, strings)
328 if t[-1] == '\x05': # regular
329 self.stack += strings
330 elif t[-1] == '\x06': # array
331 self.stack.append(strings)
332 elif t[-1] == '\x9b': # printf
333 f = to_ps(strings.pop())
334 n = f.count('%') - f.count('%%') * 2
335 x = tuple(map(to_ps, self.stack[-n:]))
336 del self.stack[-n:]
337 self.stack.append(to_gs(f % x))
338 elif t[-1] == '\x9c': # regex match
339 pattern = to_ps(strings.pop())
340 c, pattern = regex_count(pattern)
341 s = to_ps(self.stack.pop())
342 f = re.match if c else re.search
343 self.stack.append(1 if f(pattern, s) else 0)
344 elif t[-1] == '\x9d': # regex sub
345 repl = to_ps(strings.pop())
346 pattern = to_ps(strings.pop())
347 c, pattern = regex_count(pattern)
348 s = to_ps(self.stack.pop())
349 m = re.sub(pattern, repl, s, count=c)
350 self.stack.append(to_gs(m))
351 elif t[-1] == '\x9e': # regex find
352 pattern = to_ps(strings.pop())
353 c, pattern = regex_count(pattern)
354 s = to_ps(self.stack.pop())
355 ms = re.findall(pattern, s)
356 if c > 0: ms = ms[0] if ms else []
357 self.stack.append(map(to_gs, ms))
358 elif t[-1] == '\x9f': # regex split
359 pattern = to_ps(strings.pop())
360 c, pattern = regex_count(pattern)
361 s = to_ps(self.stack.pop())
362 m = re.split(pattern, s, maxsplit=c)
363 self.stack.append(map(to_gs, m))
364
365 elif t[0] == '\x07': # single char string
366 self.stack.append([ord(t[1])])
367
368 # \x08 and \x09 are block syntax
369 elif t == '\x0a': #= new-line
370 self.stack.append([ord('\n')])
371 elif t == '\x0b': #= empty-list
372 self.stack.append([])
373 elif t == '\x0c': #= empty-block
374 self.stack.append(Block([]))
375 elif t == '\x0d': #= space
376 self.stack.append([ord(' ')])
377 elif t == '\x0e': #= make-array extract-array dump
378 x = self.stack.pop()
379 if is_num(x):
380 self.stack[-x:] = [self.stack[-x:]]
381 elif is_list(x):
382 for i in x:
383 self.stack.append(i)
384 else:
385 raise TypeError('make-array / extract-array')
386
387 elif t == '\x0f': #= exit
388 break
389
390 elif 0x10 <= ord(t[0]) <= 0x1a: # push small number
391 self.stack.append(ord(t[0]) - 0x10)
392 elif t == '\x1b': self.stack.append(100)
393 elif t == '\x1c': self.stack.append(1000)
394 elif t == '\x1d': self.stack.append(16)
395 elif t == '\x1e': self.stack.append(64)
396 elif t == '\x1f': self.stack.append(256)
397
398 elif t == '\x20': #= negate reverse eval
399 x = self.stack.pop()
400 if is_num(x):
401 self.stack.append(-x)
402 elif is_list(x):
403 self.stack.append(x[::-1])
404 elif is_block(x):
405 self.evaluate(x)
406 else:
407 raise TypeError('negate / reverse')
408
409 elif t == '\x21': #= bnot head
410 x = self.stack.pop()
411 if is_num(x):
412 self.stack.append(~x)
413 elif is_list(x):
414 self.stack.append(x[0])
415 else:
416 raise TypeError('bitwise not / head')
417
418 elif t == '\x22': #= not tail
419 x = self.stack.pop()
420 if is_num(x):
421 self.stack.append(0 if x else 1)
422 elif is_list(x):
423 self.stack.append(x[1:])
424 else:
425 raise TypeError('not / tail')
426
427 elif t == '\x23': #= abs init
428 x = self.stack.pop()
429 if is_num(x):
430 self.stack.append(abs(x))
431 elif is_list(x):
432 self.stack.append(x[:-1])
433 else:
434 raise TypeError('abs / init')
435
436 elif t == '\x24': #= digits last
437 x = self.stack.pop()
438 if is_num(x):
439 self.stack.append(map(int, str(abs(x))))
440 elif is_list(x):
441 self.stack.append(x[-1])
442 else:
443 raise ValueError('digits / last')
444
445 elif t == '\x25': #= random
446 x = self.stack.pop()
447 if is_num(x):
448 self.stack.append(random.randrange(x))
449 elif is_list(x):
450 self.stack.append(random.choice(x))
451 else:
452 raise TypeError('random')
453
454 elif t == '\x26': #= dec left-uncons
455 x = self.stack.pop()
456 if is_num(x):
457 self.stack.append(x - 1)
458 elif is_list(x):
459 self.stack.append(x[1:])
460 self.stack.append(x[0])
461 else:
462 raise TypeError('deincrement / left uncons')
463
464 elif t == '\x27': #= inc right-uncons
465 x = self.stack.pop()
466 if is_num(x):
467 self.stack.append(x + 1)
468 elif is_list(x):
469 self.stack.append(x[:-1])
470 self.stack.append(x[-1])
471 else:
472 raise TypeError('increment / right uncons')
473
474 elif t == '\x28': #= sign min
475 x = self.stack.pop()
476 if is_num(x):
477 self.stack.append(cmp(x, 0))
478 elif is_list(x):
479 self.stack.append(min(x))
480 else:
481 raise TypeError('sign / min')
482
483 elif t == '\x29': #= thousand max
484 x = self.stack.pop()
485 if is_num(x):
486 self.stack.append(x * 1000)
487 elif is_list(x):
488 self.stack.append(max(x))
489 else:
490 raise TypeError('thousand / max')
491
492 elif t == '\x2a': #= double lines
493 x = self.stack.pop()
494 if is_num(x):
495 self.stack.append(x * 2)
496 elif is_list(x):
497 if x and x[-1] == ord('\n'):
498 x.pop()
499 self.stack.append(split(x, to_gs('\n')))
500 else:
501 raise TypeError('double / line')
502
503 elif t == '\x2b': #= half unlines
504 x = self.stack.pop()
505 if is_num(x):
506 self.stack.append(x // 2)
507 elif is_list(x):
508 x = [to_gs(show(i)) for i in x]
509 self.stack.append(join(x, to_gs('\n')))
510 else:
511 raise TypeError('half / unlines')
512
513 elif t == '\x2c': #= square words
514 x = self.stack.pop()
515 if is_num(x):
516 self.stack.append(x * x)
517 elif is_list(x):
518 self.stack.append(map(to_gs, to_ps(x).split()))
519 else:
520 raise TypeError('square / words')
521
522 elif t == '\x2d': #= sqrt unwords
523 x = self.stack.pop()
524 if is_num(x):
525 self.stack.append(int(math.sqrt(x)))
526 elif is_list(x):
527 x = [to_gs(show(i)) for i in x]
528 self.stack.append(join(x, to_gs(' ')))
529 else:
530 raise TypeError('sqrt / unwords')
531
532 elif t == '\x2e': #= range length
533 x = self.stack.pop()
534 if is_num(x):
535 self.stack.append(range(x))
536 elif is_list(x):
537 self.stack.append(len(x))
538 else:
539 raise TypeError('range / length')
540
541 elif t == '\x2f': #= range1 sort
542 x = self.stack.pop()
543 if is_num(x):
544 self.stack.append(range(1, x + 1))
545 elif is_list(x):
546 self.stack.append(list(sorted(x)))
547 elif is_block(x):
548 l = self.stack.pop()
549 def f(z):
550 self.stack.append(z)
551 self.evaluate(x)
552 return self.stack.pop(junk=False)
553 self.stack.append(list(sorted(l, key=f)))
554 else:
555 raise TypeError('range1 / sort')
556
557 elif t == '\x30': #= + add catenate
558 y = self.stack.pop()
559 x = self.stack.pop()
560 if is_num(x) and is_num(y):
561 self.stack.append(x + y)
562 elif is_list(x) and is_list(y):
563 self.stack.append(x + y)
564 elif is_block(x) and is_block(y):
565 self.stack.append(Block(x.code + y.code))
566 elif is_list(x) and not is_list(y):
567 self.stack.append(x + [y])
568 elif not is_list(x) and is_list(y):
569 self.stack.append([x] + y)
570 else:
571 raise TypeError('add / catenate')
572
573 elif t == '\x31': #= - sub diff
574 y = self.stack.pop()
575 x = self.stack.pop()
576 if is_num(x) and is_num(y):
577 self.stack.append(x - y)
578 elif is_list(x) and is_list(y):
579 self.stack.append(set_diff(x, y))
580 elif is_list(x) and not is_list(y):
581 self.stack.append(set_diff(x, [y]))
582 elif not is_list(x) and is_list(y):
583 self.stack.append(set_diff(y, [x]))
584 else:
585 raise TypeError('subtract / set diff')
586
587 elif t == '\x32': #= * mul join times fold
588 y = self.stack.pop()
589 x = self.stack.pop()
590 if is_num(x) and (is_block(y) or is_list(y)):
591 x, y = y, x
592 if is_block(x) and is_list(y):
593 x, y = y, x
594
595 if is_num(x) and is_num(y):
596 self.stack.append(x * y)
597 elif is_list(x) and is_list(y):
598 self.stack.append(join(x, y))
599 elif is_list(x) and is_num(y):
600 self.stack.append(x * y)
601 elif is_block(x) and is_num(y):
602 for i in xrange(y):
603 self.evaluate(x)
604 elif is_list(x) and is_block(y):
605 self.stack.append(x[0])
606 for i in x[1:]:
607 self.stack.append(i)
608 self.evaluate(y)
609 else:
610 raise TypeError('multiply / join / times / fold')
611
612 elif t == '\x33': #= / div chunks split each
613 y = self.stack.pop()
614 x = self.stack.pop()
615
616 if not is_list(x) and is_list(y):
617 x, y = y, x
618
619 if is_num(x) and is_num(y):
620 self.stack.append(x // y)
621 elif is_list(x) and is_num(y):
622 self.stack.append(list(chunks(x, y)))
623 elif is_list(x) and is_list(y):
624 self.stack.append(split(x, y))
625 elif is_list(x) and is_block(y):
626 for i in x:
627 self.stack.append(i)
628 self.evaluate(y)
629 else:
630 raise TypeError('divide / chunks / split / each')
631
632 elif t == '\x34': #= % mod step clean-split map
633 y = self.stack.pop()
634 x = self.stack.pop()
635
636 if not is_list(x) and is_list(y):
637 x, y = y, x
638
639 if is_num(x) and is_num(y):
640 self.stack.append(x % y)
641 elif is_list(x) and is_num(y):
642 self.stack.append(x[::y])
643 elif is_list(x) and is_list(y):
644 self.stack.append(split(x, y, clean=True))
645 elif is_list(x) and is_block(y):
646 self.eval_map(y, x)
647 else:
648 raise TypeError('modulo / step / split\' / map')
649
650 elif t == '\x35': #= & and get when filter
651 y = self.stack.pop()
652 x = self.stack.pop()
653
654 if is_block(x) and is_num(y):
655 x, y = y, x
656 if is_num(x) and is_list(y):
657 x, y = y, x
658 if is_block(x) and is_list(y):
659 x, y = y, x
660
661 if is_num(x) and is_num(y):
662 self.stack.append(x & y)
663 elif is_list(x) and is_list(y):
664 self.stack.append(set_and(x, y))
665 elif is_list(x) and is_num(y):
666 self.stack.append(x[y])
667 elif is_num(x) and is_block(y):
668 if x: self.evaluate(y)
669 elif is_list(x) and is_block(y):
670 self.eval_filter(y, x)
671 else:
672 raise TypeError('and / get / when / filter')
673
674 elif t == '\x36': #= | or unless
675 y = self.stack.pop()
676 x = self.stack.pop()
677
678 if is_block(x) and is_num(y):
679 x, y = y, x
680
681 if is_num(x) and is_num(y):
682 self.stack.append(x | y)
683 elif is_list(x) and is_list(y):
684 self.stack.append(set_or(x, y))
685 elif is_num(x) and is_block(y):
686 if not x: self.evaluate(y)
687 else:
688 raise TypeError('bor / unless')
689
690 elif t == '\x37': #= ^ xor concatmap
691 y = self.stack.pop()
692 x = self.stack.pop()
693
694 if is_block(x) and is_list(y):
695 x, y = y, x
696
697 if is_num(x) and is_num(y):
698 self.stack.append(x ^ y)
699 elif is_list(x) and is_list(y):
700 self.stack.append(set_xor(x, y))
701 elif is_list(x) and is_block(y):
702 res = []
703 for i in x:
704 self.stack.append(i)
705 self.evaluate(y)
706 res.extend(self.stack.pop(junk=False))
707 self.stack.append(res)
708 else:
709 raise TypeError('xor / concatmap')
710
711 elif t == '\x38': #= smallest both
712 y = self.stack.pop()
713 if is_block(y):
714 x = self.stack.pop()
715 self.evaluate(y)
716 self.stack.append(x)
717 self.evaluate(y)
718 else:
719 x = self.stack.pop()
720 self.stack.append(min(x, y))
721
722 elif t == '\x39': #= biggest
723 y = self.stack.pop()
724 x = self.stack.pop()
725 self.stack.append(max(x, y))
726
727 elif t == '\x3a': #= clamp
728 z = self.stack.pop()
729 y = self.stack.pop()
730 x = self.stack.pop()
731 self.stack.append(min(max(x, y), z))
732
733 elif t == '\x3c': #= gcd take
734 y = self.stack.pop()
735 x = self.stack.pop()
736
737 if is_num(x) and is_list(y):
738 x, y = y, x
739
740 if is_num(x) and is_num(y):
741 self.stack.append(gcd(x, y))
742 elif is_list(x) and is_num(y):
743 self.stack.append(x[:y])
744 else:
745 raise TypeError('gcd / take')
746
747 elif t == '\x3d': #= lcm drop
748 y = self.stack.pop()
749 x = self.stack.pop()
750
751 if is_num(x) and is_list(y):
752 x, y = y, x
753
754 if is_num(x) and is_num(y):
755 self.stack.append(lcm(x, y))
756 elif is_list(x) and is_num(y):
757 self.stack.append(x[y:])
758 else:
759 raise TypeError('lcm / drop')
760
761 elif t == '\x3e': #= pow index
762 y = self.stack.pop()
763 x = self.stack.pop()
764
765 if is_num(x) and is_list(y):
766 x, y = y, x
767
768 if is_num(x) and is_num(y):
769 self.stack.append(x ** y)
770 elif is_list(x) and is_num(y):
771 self.stack.append(x.index(y) if y in x else -1)
772 else:
773 raise TypeError('power / index')
774
775 elif t == '\x3f': #= log member
776 y = self.stack.pop()
777 x = self.stack.pop()
778
779 if is_list(y):
780 x, y = y, x
781
782 if is_num(x) and is_num(y):
783 self.stack.append(int(math.log(x, y)))
784 elif is_list(x):
785 self.stack.append(1 if y in x else 0)
786 else:
787 raise TypeError('log / member')
788
789 elif t == '\x40': #= dup
790 self.stack.append(self.stack[-1])
791 elif t == '\x41': #= dup2
792 self.stack.append(self.stack[-1])
793 self.stack.append(self.stack[-1])
794 elif t == '\x42': #= swap
795 self.stack.append(self.stack.pop(-2))
796 elif t == '\x43': #= rot
797 self.stack.append(self.stack.pop(-3))
798 elif t == '\x44': #= rrot
799 self.stack.append(self.stack.pop(-3))
800 self.stack.append(self.stack.pop(-3))
801 elif t == '\x45': #= over
802 self.stack.append(self.stack[-2])
803 elif t == '\x46': #= nip
804 self.stack.pop(-2)
805 elif t == '\x47': #= tuck
806 self.stack.insert(-2, self.stack[-1])
807 elif t == '\x48': #= 2dup
808 self.stack.append(self.stack[-2])
809 self.stack.append(self.stack[-2])
810 elif t == '\x49': #= pick
811 n = self.stack.pop()
812 self.stack.append(self.stack[-n])
813 elif t == '\x4a': #= roll
814 n = self.stack.pop()
815 self.stack.append(self.stack.pop(-n))
816 elif t == '\x4b': #= wrap-stack
817 self.stack = [copy.deepcopy(self.stack)]
818 elif t == '\x4c': #= leave-top
819 del self.stack[:-1]
820 elif t == '\x4d': #= itemize
821 self.stack.append([self.stack.pop()])
822 elif t == '\x4e': #= rrange
823 x = self.stack.pop()
824 self.stack.append(range(x)[::-1])
825 elif t == '\x4f': #= crange
826 y = self.stack.pop()
827 x = self.stack.pop()
828 if x > y: x, y = y, x
829 self.stack.append(range(x, y))
830 elif t == '\x50': #= pop
831 self.stack.pop()
832 elif t == '\x51': #= pop2
833 self.stack.pop()
834 self.stack.pop()
835 elif t == '\x52': #= show
836 x = self.stack.pop()
837 self.stack.append(to_gs(show(x)))
838 elif t == '\x53': #= map-show
839 x = self.stack.pop()
840 self.stack.append(map(to_gs, map(show, x)))
841 elif t == '\x54': #= show-lines
842 x = self.stack.pop()
843 self.stack.append(to_gs('\n'.join(map(show, x))))
844 elif t == '\x55': #= show-words
845 x = self.stack.pop()
846 self.stack.append(to_gs(' '.join(map(show, x))))
847 elif t in '\x56\x57': #= read-num, read-nums
848 x = to_ps(self.stack.pop())
849 nums = map(int, re.findall(r'-?\d+', x))
850 self.stack.append(nums[0] if t == '\x56' else nums)
851 elif t == '\x58': #= show-line
852 x = self.stack.pop()
853 self.stack.append(to_gs(show(x) + '\n'))
854 elif t == '\x59': #= show-space
855 x = self.stack.pop()
856 self.stack.append(to_gs(show(x) + ' '))
857 elif t == '\x5a': #= show-comma
858 x = self.stack.pop()
859 self.stack.append(to_gs(', '.join(map(show, x))))
860 elif t == '\x5b': #= show-python
861 x = self.stack.pop()
862 self.stack.append(to_gs(', '.join(map(show, x)).join('[]')))
863 elif t in '\x5c\x5d\x5e': #= ljust, center, rjust
864 fill = ' '
865 if is_num(self.stack[-2]):
866 fill = chr(self.stack.pop())
867 width = self.stack.pop()
868 s = self.stack.pop()
869 if t == '\x5c': g = show(s).ljust(width, fill)
870 if t == '\x5d': g = show(s).center(width, fill)
871 if t == '\x5e': g = show(s).rjust(width, fill)
872 self.stack.append(to_gs(g))
873 elif t == '\x5f': #= inspect
874 self.stack.append(to_gs(repr(self.stack.pop())))
875 elif t == '\x60': #= logical-and
876 y = self.stack.pop()
877 x = self.stack.pop()
878 self.stack.append(x and y)
879 elif t == '\x61': #= logical-or
880 y = self.stack.pop()
881 x = self.stack.pop()
882 self.stack.append(x or y)
883 elif t == '\x62': #= divides left-cons
884 y = self.stack.pop()
885 x = self.stack.pop()
886 if is_num(x):
887 self.stack.append(0 if x % y else 1)
888 elif is_list(x):
889 self.stack.append([y] + x)
890 else:
891 raise TypeError('divides / left-cons')
892 elif t == '\x63': #= divmod group
893 y = self.stack.pop()
894 if is_num(y):
895 x = self.stack.pop()
896 self.stack.append(x // y)
897 self.stack.append(x % y)
898 elif is_list(y):
899 gb = [list(g) for k, g in it.groupby(y)]
900 self.stack.append(list(gb))
901 else:
902 raise TypeError('divmod / group')
903 elif t == '\x64': #= sum even
904 x = self.stack.pop()
905 if is_num(x):
906 self.stack.append(1 if x % 2 == 0 else 0)
907 elif is_list(x):
908 self.stack.append(sum(x))
909 elif t == '\x65': #= product odd
910 x = self.stack.pop()
911 if is_num(x):
912 self.stack.append(1 if x % 2 == 1 else 0)
913 elif is_list(x):
914 self.stack.append(product(x))
915 elif t == '\x66': #= fizzbuzz
916 fizzbuzz = []
917 for i in range(1, 101):
918 s = ("Fizz" if i % 3 == 0 else "") + \
919 ("Buzz" if i % 5 == 0 else "")
920 fizzbuzz.append(s or str(i))
921 self.stack.append(to_gs('\n'.join(fizzbuzz)))
922 elif t == '\x67': #= popcnt right-cons
923 x = self.stack.pop()
924 if is_num(x):
925 x = abs(x)
926 p = 0
927 while x:
928 p += (x & 1)
929 x >>= 1
930 self.stack.append(p)
931 elif is_list(x):
932 y = self.stack.pop()
933 self.stack.append(x + [y])
934 elif t == '\x68': #= hello
935 x = 0
936 if len(self.stack) >= 1 and is_num(self.stack[-1]):
937 x = self.stack.pop()
938 x = (range(0, 11) + [100, 1000, 16, 64, 256]).index(x)
939 s1 = 'h' if x & 1 else 'H'
940 s2 = 'W' if x & 2 else 'w'
941 s3 = ['!', '', '.', '...'][((x & 4) >> 2) | ((x & 16) >> 3)]
942 s4 = '' if x & 8 else ','
943 f = '%sello%s %sorld%s' % (s1, s4, s2, s3)
944 self.stack.append(to_gs(f))
945 elif t in '\x69\x6a': #= base, binary
946 b = 2 if t == '\x6a' else self.stack.pop()
947 x = self.stack.pop()
948 if is_num(x):
949 x = abs(x)
950 res = []
951 while x:
952 res.append(x % b)
953 x //= b
954 self.stack.append(res[::-1])
955 elif is_list(x):
956 res = 0
957 for i in x:
958 res = res * b + i
959 self.stack.append(res)
960 else:
961 raise TypeError('base / binary')
962 elif t == '\x6b': #= is-prime
963 x = self.stack.pop()
964 if is_num(x):
965 self.stack.append(1 if is_prime(x) else 0)
966 elif is_list(x):
967 self.stack.append(filter(is_prime, x))
968 else:
969 raise TypeError('is-prime')
970 elif t == '\x6c': #= primes
971 op = self.stack.pop()
972 x = self.stack.pop()
973 if op == 0: self.stack.append(n_primes(x))
974 elif op == 1: self.stack.append(primes_below(x))
975 elif op == 2: self.stack.append(next_prime(x))
976 elif op == 3: self.stack.append(totient(x))
977 elif op == 4: self.stack.append(factor(x, exps=False))
978 elif op == 5: self.stack.append(factor(x, exps=True))
979 elif t == '\x6d': #= scan
980 f = self.stack.pop()
981 def call_f(x, y):
982 self.stack.append(x)
983 self.stack.append(y)
984 self.evaluate(f)
985 return self.stack.pop()
986 xs = self.stack.pop()
987 res = [xs.pop(0)]
988 while xs:
989 res.append(call_f(res[-1], xs.pop(0)))
990 self.stack.append(res)
991 elif t in '\x70\x71\x72\x73\x74\x75': #= lt <, eq =, gt >, ge >=, ne !=, le <=
992 y = self.stack.pop()
993 x = self.stack.pop()
994 ops = {
995 '\x70': operator.lt,
996 '\x71': operator.eq,
997 '\x72': operator.gt,
998 '\x73': operator.ge,
999 '\x74': operator.ne,
1000 '\x75': operator.le,
1001 }
1002 self.stack.append(1 if ops[t](x, y) else 0)
1003 elif t == '\x76': #= cmp
1004 y = self.stack.pop()
1005 x = self.stack.pop()
1006 self.stack.append(cmp(x, y))
1007 elif t == '\x77': #= is-sorted
1008 x = self.stack.pop()
1009 if is_list(x):
1010 self.stack.append(1 if x == list(sorted(x)) else 0)
1011 elif is_block(x):
1012 l = self.stack.pop()
1013 def f(z):
1014 self.stack.append(z)
1015 self.evaluate(x)
1016 return self.stack.pop()
1017 sorted_l = list(sorted(l, key=f))
1018 self.stack.append(1 if l == sorted_l else 0)
1019 else:
1020 raise TypeError('sorted')
1021 elif t == '\x78': #= shift-left inits
1022 y = self.stack.pop()
1023 if is_list(y):
1024 inits = []
1025 for i in xrange(len(y) + 1):
1026 inits.append(y[:i])
1027 self.stack.append(inits)
1028 else:
1029 x = self.stack.pop()
1030 self.stack.append(x << y)
1031 elif t == '\x79': #= shift-right tails
1032 y = self.stack.pop()
1033 if is_list(y):
1034 tails = []
1035 for i in xrange(len(y) + 1):
1036 tails.append(y[len(y)-i:])
1037 self.stack.append(tails)
1038 else:
1039 x = self.stack.pop()
1040 self.stack.append(x >> y)
1041 elif t == '\x7a': #= digit-left enumerate
1042 y = self.stack.pop()
1043 if is_list(y):
1044 self.stack.append(list(map(list, enumerate(y))))
1045 else:
1046 x = self.stack.pop()
1047 self.stack.append(x * (10 ** y))
1048 elif t == '\x7b': #= digit-right
1049 y = self.stack.pop()
1050 x = self.stack.pop()
1051 self.stack.append(x // (10 ** y))
1052 elif t == '\x7c': #= power-of-2
1053 self.stack.append(2 ** self.stack.pop())
1054 elif t == '\x7d': #= power-of-10
1055 self.stack.append(10 ** self.stack.pop())
1056 elif t == '\x7e': #= sub-power-of-2
1057 self.stack.append(2 ** self.stack.pop() - 1)
1058 elif t == '\x7f': #= sub-power-of-10
1059 self.stack.append(10 ** self.stack.pop() - 1)
1060
1061 elif t == '\x80': #= pair
1062 y = self.stack.pop()
1063 x = self.stack.pop()
1064 self.stack.append([x, y])
1065 elif t == '\x81': #= copies
1066 n = self.stack.pop()
1067 x = self.stack.pop()
1068 self.stack.append([x for _ in xrange(n)])
1069 elif t == '\x82': #= take-end
1070 y = self.stack.pop()
1071 x = self.stack.pop()
1072 if is_num(x) and is_list(y):
1073 x, y = y, x
1074 self.stack.append(x[-y:])
1075 elif t == '\x83': #= cartesian-product
1076 y = self.stack.pop()
1077 x = self.stack.pop()
1078 p = it.product(x, y)
1079 self.stack.append(list(map(list, p)))
1080 elif t == '\x84': #= uppercase-alphabet
1081 self.stack.append(range(ord('A'), ord('Z') + 1))
1082 elif t == '\x85': #= lowercase-alphabet
1083 self.stack.append(range(ord('a'), ord('z') + 1))
1084 elif t == '\x86': #= ascii-digits
1085 self.stack.append(range(ord('0'), ord('9') + 1))
1086 elif t == '\x87': #= printable-ascii
1087 self.stack.append(range(32, 127))
1088 elif t in '\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f': #= is-alnum, is-alpha, is-digit, is-lower, is-space, is-upper, is-printable, is-hexdigit
1089 m = [str.isalnum, str.isalpha, str.isdigit,
1090 str.islower, str.isspace, str.isupper,
1091 lambda x: all(32 <= ord(c) <= 126 for c in x),
1092 lambda x: x in '0123456789abcdefABCDEF']
1093 p = m[ord(t) - 0x88]
1094 x = to_ps(self.stack.pop())
1095 self.stack.append(1 if p(x) else 0)
1096 elif t == '\x90': #= uniq nub
1097 xs = self.stack.pop()
1098 uniq = []
1099 for x in xs:
1100 if x not in uniq:
1101 uniq.append(x)
1102 self.stack.append(uniq)
1103 elif t == '\x91': #= compress
1104 ns = self.stack.pop()
1105 xs = self.stack.pop()
1106 new = []
1107 for n, x in zip(ns, xs):
1108 new += [x for _ in xrange(n)]
1109 self.stack.append(new)
1110 elif t == '\x92': #= select
1111 xs = self.stack.pop()
1112 iis = self.stack.pop()
1113 new = []
1114 for i in iis:
1115 new.append(xs[i])
1116 self.stack.append(new)
1117 elif t == '\x93': #= permutations
1118 xs = self.stack.pop()
1119 if is_num(xs):
1120 n = xs
1121 xs = self.stack.pop()
1122 else:
1123 n = None
1124 ps = list(map(list, it.permutations(xs, n)))
1125 self.stack.append(ps)
1126 elif t == '\x94': #= fold-product
1127 xss = self.stack.pop()
1128 ys = list(map(list, it.product(*xss)))
1129 self.stack.append(ys)
1130 elif t == '\x95': #= repeat-product
1131 n = self.stack.pop()
1132 xs = self.stack.pop()
1133 ys = list(map(list, it.product(xs, repeat=n)))
1134 self.stack.append(ys)
1135 elif t == '\x96': #= combinations
1136 n = self.stack.pop()
1137 xs = self.stack.pop()
1138 ys = list(map(list, it.combinations(xs, n)))
1139 self.stack.append(ys)
1140 elif t == '\x97': #= combinations-with-replacement
1141 n = self.stack.pop()
1142 xs = self.stack.pop()
1143 ys = list(map(list, it.combinations_with_replacement(xs, n)))
1144 self.stack.append(ys)
1145 elif t == '\x98': #= pairwise
1146 xs = self.stack.pop()
1147 ys = map(list, zip(xs, xs[1:]))
1148 self.stack.append(ys)
1149 elif t == '\x99': #= flatten
1150 def flatten(xs):
1151 acc = []
1152 for x in xs:
1153 if is_list(x):
1154 acc += flatten(x)
1155 else:
1156 acc.append(x)
1157 return acc
1158 xs = self.stack.pop()
1159 self.stack.append(flatten(xs))
1160 elif t == '\x9a': #= transpose
1161 xs = self.stack.pop()
1162 self.stack.append(map(list, zip(*xs)))
1163 elif '\xa0' <= t <= '\xaf': # junk (recently popped items)
1164 self.stack.append(self.stack.junk[-1 - (ord(t) & 15)])
1165 elif t == '\xb0': #= zip
1166 ys = self.stack.pop()
1167 xs = self.stack.pop()
1168 self.stack.append(map(list, zip(xs, ys)))
1169 elif t == '\xb1': #= zipwith
1170 f = self.stack.pop()
1171 ys = self.stack.pop()
1172 xs = self.stack.pop()
1173 l0 = len(self.stack)
1174 for x, y in zip(xs, ys):
1175 self.stack.append(x)
1176 self.stack.append(y)
1177 self.evaluate(f)
1178 self.stack[l0:] = [self.stack[l0:]]
1179 elif t == '\xb2': #= counter
1180 self.stack.append(self.counter)
1181 self.counter += 1
1182 elif '\xc8' <= t <= '\xcb': # save
1183 self.regs[ord(t) & 3] = self.stack[-1]
1184 elif '\xcc' <= t <= '\xcf': # put
1185 self.regs[ord(t) & 3] = self.stack.pop()
1186 elif '\xd0' <= t <= '\xd3': # get
1187 self.stack.append(self.regs[ord(t) & 3])
1188 elif '\xd4' <= t <= '\xd7': # nip
1189 self.regs[ord(t) & 3] = self.stack.pop(-2)
1190 elif '\xd8' <= t <= '\xdb': # tuck
1191 self.stack.insert(-1, self.regs[ord(t) & 3])
1192 elif '\xdc' <= t <= '\xdf': # show
1193 self.stack.append(to_gs(show(self.regs[ord(t) & 3])))
1194 else:
1195 raise ValueError('invalid token %r' % t)
1196
1197 def eval_map(self, f, x):
1198 l0 = len(self.stack)
1199 for i in x:
1200 self.stack.append(i)
1201 self.evaluate(f)
1202 self.stack[l0:] = [self.stack[l0:]]
1203
1204 def eval_filter(self, f, x):
1205 l0 = len(self.stack)
1206 for i in x:
1207 self.stack.append(i)
1208 self.evaluate(f)
1209 if self.stack.pop():
1210 self.stack.append(i)
1211 self.stack[l0:] = [self.stack[l0:]]
1212
1213 if __name__ == '__main__':
1214 if len(sys.argv) <= 1:
1215 print >> sys.stderr, 'usage: python %s [-d] <code file>' % sys.argv[0]
1216 sys.exit(1)
1217
1218 if sys.argv[1] == '-d':
1219 DEBUG = True
1220 sys.argv.pop(1)
1221
1222 code = open(sys.argv[1], 'rb').read()
1223 stdin = '' if sys.stdin.isatty() else sys.stdin.read()
1224 GS2(code, stdin).run()