|
Revision 1749, 2.2 kB
(checked in by nishio, 6 years ago)
|
|
lang/unlambda/impl/in_python: brandnew version to support call/cc[c], currently supports [`.xi]
|
| Line | |
|---|
| 1 | """ unlambda interpreter
|
|---|
| 2 |
|
|---|
| 3 | # test
|
|---|
| 4 | >>> run("`.ai")
|
|---|
| 5 | a
|
|---|
| 6 |
|
|---|
| 7 | """
|
|---|
| 8 | globals().clear()
|
|---|
| 9 | # Main loop
|
|---|
| 10 | #
|
|---|
| 11 | def run(s):
|
|---|
| 12 | task = EvalTask(parse(s), FinalCont)
|
|---|
| 13 | try:
|
|---|
| 14 | while True:
|
|---|
| 15 | task = task()
|
|---|
| 16 | except StopIteration, e:
|
|---|
| 17 | return
|
|---|
| 18 |
|
|---|
| 19 | # Continuation
|
|---|
| 20 | # __call__(Func) returns Task
|
|---|
| 21 | def FinalCont(f):
|
|---|
| 22 | def FinalTask():
|
|---|
| 23 | raise StopIteration
|
|---|
| 24 | return FinalTask
|
|---|
| 25 |
|
|---|
| 26 | # Task
|
|---|
| 27 | #
|
|---|
| 28 | class Task(object): pass
|
|---|
| 29 |
|
|---|
| 30 | def EvalTask(node, cont):
|
|---|
| 31 | def run():
|
|---|
| 32 | return node.eval(cont)
|
|---|
| 33 | return run
|
|---|
| 34 |
|
|---|
| 35 | # Node
|
|---|
| 36 | #
|
|---|
| 37 | class Node(object):
|
|---|
| 38 | "parsed element"
|
|---|
| 39 |
|
|---|
| 40 | class I(Node):
|
|---|
| 41 | "identity"
|
|---|
| 42 | def eval(self, cont):
|
|---|
| 43 | def I0(X, cont):
|
|---|
| 44 | return cont.invoke(X)
|
|---|
| 45 | return cont(I0)
|
|---|
| 46 |
|
|---|
| 47 | class Dot(Node):
|
|---|
| 48 | "print char: `.aX => print 'a'"
|
|---|
| 49 | def __init__(self, c):
|
|---|
| 50 | self.c = c
|
|---|
| 51 | def eval(self, cont):
|
|---|
| 52 | def Dot0(X, cont):
|
|---|
| 53 | import sys
|
|---|
| 54 | sys.stdout.write(self.c)
|
|---|
| 55 | return cont(X)
|
|---|
| 56 | return cont(Dot0)
|
|---|
| 57 |
|
|---|
| 58 | class Apply(Node):
|
|---|
| 59 | "apply: `FG = F(G)"
|
|---|
| 60 | def __init__(self, X, Y):
|
|---|
| 61 | "take 2 not-evaluated node"
|
|---|
| 62 | self.nX = X
|
|---|
| 63 | self.nY = Y
|
|---|
| 64 | def eval(self, cont):
|
|---|
| 65 | nY = self.nY
|
|---|
| 66 | def next(X):
|
|---|
| 67 | def _App1(): # task
|
|---|
| 68 | "evalated X and not-evaluated Y"
|
|---|
| 69 |
|
|---|
| 70 | # if X.isDelay:
|
|---|
| 71 | # return self.cont.invoke(D1Function(self.nY))
|
|---|
| 72 |
|
|---|
| 73 | def next(Y):
|
|---|
| 74 | def _App2(): # task
|
|---|
| 75 | return X(Y, cont)
|
|---|
| 76 | return _App2
|
|---|
| 77 | return nY.eval(next)
|
|---|
| 78 | return _App1
|
|---|
| 79 | return EvalTask(self.nX, next)
|
|---|
| 80 |
|
|---|
| 81 | def _parse(iter):
|
|---|
| 82 | c = iter.next()
|
|---|
| 83 | result = {
|
|---|
| 84 | "i": lambda: I(),
|
|---|
| 85 | ".": lambda: Dot(iter.next()),
|
|---|
| 86 | "`": lambda: (lambda f=_parse(iter): Apply(f, _parse(iter)))(),
|
|---|
| 87 |
|
|---|
| 88 | "r": lambda: R(),
|
|---|
| 89 | "v": lambda: V(),
|
|---|
| 90 | "d": lambda: "(delay)", # special form
|
|---|
| 91 | "c": lambda: C(),
|
|---|
| 92 | "s": lambda: S(),
|
|---|
| 93 | "k": lambda: K(),
|
|---|
| 94 | }.get(c, lambda: _parse(iter))()
|
|---|
| 95 | return result
|
|---|
| 96 |
|
|---|
| 97 | def parse(s):
|
|---|
| 98 | return _parse(list(s).__iter__())
|
|---|
| 99 |
|
|---|
| 100 | def _test():
|
|---|
| 101 | import doctest
|
|---|
| 102 | reload(doctest)
|
|---|
| 103 | doctest.testmod()
|
|---|
| 104 |
|
|---|
| 105 | run("`.ai")
|
|---|