root/lang/unlambda/impl/in_python/unlambda_lambda.py @ 1759

Revision 1759, 6.4 kB (checked in by nishio, 6 years ago)

lang/unlambda/impl/in_python: replace I with lambda

Line 
1""" unlambda interpreter
2
3# test
4>>> run("`.ai")
5a
6>>> run("``i.ai")
7a
8>>> run("`i`.ai")
9a
10>>> run("`d`.ai")
11>>> run("``d`.aii")
12a
13>>> run("`.b`i`.ai")
14ab
15>>> run("`.b`d`.ai")
16b
17>>> run("``.b`d`.aii")
18ba
19>>> run("``.b`.a`ci.c")
20ababc
21>>> Debug.show_node = True
22>>> run("``v.a.a")
23(apply (apply V (print 'a')) (print 'a'))
24(apply V (print 'a'))
25V
26>>> Debug.show_node = False
27>>> run("````skk.av")
28a
29"""
30# Main loop
31#
32def run(s):
33    task = EvalTask(parse(s), FinalCont)
34    try:
35        while True:
36            task = task()
37    except StopIteration, e:
38        return
39
40# Continuation
41# __call__(Func) returns Task
42def FinalCont(f):
43    return FinalTask
44
45# Task
46#
47
48def FinalTask(X=None):
49    raise StopIteration()
50
51def EvalTask(node, cont):
52    def run():
53        if Debug.show_node: print node
54        return node(cont)
55    return run
56
57def ApplyTask(operator, operand, cont):
58    def run():
59        return operator(operand, cont)
60    return run
61
62# Node
63#
64class Node(object):
65    "parsed element"
66
67I = lambda: lambda c: c(lambda X, c: c(X))
68
69class Dot(Node):
70    "print char: `.aX => print 'a'"
71    def __init__(self, c):
72        self.c = c
73    def __str__(self):
74        return "(print %r)" % self.c
75    def __call__(self, cont):
76        def Dot0(X, cont):
77            import sys
78            sys.stdout.write(self.c)
79            return cont(X)
80        return cont(Dot0)
81   
82class Apply(Node):
83    "apply: `FG = F(G)"
84    def __init__(self, X, Y):
85        "take 2 not-evaluated node"
86        self.nX = X
87        self.nY = Y
88    def __str__(self):
89        return "(apply %s %s)" % (self.nX, self.nY)
90    def __call__(self, cont):
91        nY = self.nY
92        def next(X):
93            def _App1(): # task
94                "evalated X and not-evaluated Y"
95
96                if X.__class__ == D:
97                    def Promise0(Y, cont):
98                        def next(X):
99                            def Promise1(X, cont):
100                                return X(Y, cont)
101                            return cont(Promise1)
102                        return nY(next)
103                    return cont(Promise0)
104
105                def next(Y):
106                    def _App2(): # task
107                        "evaluated X and Y"
108                        return X(Y, cont)
109                    return _App2
110                return nY(next)
111            return _App1
112        return EvalTask(self.nX, next)
113
114class D(Node):
115    "delay (special form)"
116    def __str__(self):
117         return "D"
118    def __call__(self, cont):
119        return cont(self)
120   
121
122class C(Node):
123    "call/cc"
124    def __str__(self):
125        return "C"
126    def __call__(self, cont):
127        def C0(Y, cont):
128            def C1(func, new_cont):
129                return cont(func) # use old cont
130            operator = Y
131            operand = C1
132            def Apply(): # task
133                return operator(operand, cont)
134            return Apply
135        return cont(C0)
136
137class V(Node):
138    """void: v(x) == v
139    equivalent to ` ``s``s`kskk ``s``s`kskk"""
140    def __str__(self):
141        return "V"
142    def __call__(self, cont):
143        def V0(X, cont):
144            return cont(V0)
145        return cont(V0)
146
147class K(Node):
148    "constant: ``kXY = X"
149    def __str__(self):
150        return "K"
151    def __call__(self, cont):
152        def K0(X, cont):
153            def K1(Y, cont):
154                return cont(X)
155            return cont(K1)
156        return cont(K0)
157
158class S(Node):
159    "substitution: ```sXYZ = ``XZ`YZ"
160    def __str__(self):
161        return "S"
162    def __call__(self, cont):
163        def S0(X, cont):
164            def S1(Y, cont):
165                def S2(Z, cont):
166                    return EvalTask(
167                        Apply(
168                            Apply(Func2Node(X), Func2Node(Z)),
169                            Apply(Func2Node(Y), Func2Node(Z))), cont)
170                return cont(S2)
171            return cont(S1)
172        return cont(S0)
173
174class Func2Node(Node):
175    def __str__(self): return "%s" % self.f.func_name
176    def __init__(self, f):
177        self.f = f
178    def __call__(self, cont):
179        return cont(self.f)
180
181class At(Node):
182    def __str__(self): return "At"
183    def __call__(self, cont):
184        def At0(X, cont):
185            import sys
186            try:
187                #At.c = sys.stdin.read(1)
188                At.c = raw_input(">>> ")[0]
189                switch = I()
190            except:
191                switch = V()
192
193            return EvalTask(
194                    Apply(
195                        Func2Node(X),
196                        switch),
197                    cont)
198        return cont(At0)
199           
200class Qu(Node):
201    def __str__(self): return "(? %r)" % self.c
202    def __init__(self, c):
203        self.c = c
204
205    def __call__(self, cont):
206        def Qu0(X, cont):
207            if At.c == self.c:
208                switch = I()
209            else:
210                switch = V()
211
212            return EvalTask(Apply(Func2Node(X), switch), cont)
213        return cont(Qu0)
214
215class Pipe(Node):
216    def __call__(self, cont):
217        def Pipe0(X, cont):
218            if At.c != -1:
219                switch = Dot(At.c)
220            else:
221                switch = V()
222
223            return ApplyTask(X, switch, cont)
224        return Pipe0
225
226class E(Node):
227    def __call__(self, cont):
228        def E0(X, cont):
229            return FinalTask(X)
230        return E0
231   
232def _parse(iter):
233    c = iter.next()
234    result = {
235        "i": lambda: I(),
236        ".": lambda: Dot(iter.next()),
237        "`": lambda: Apply(_parse(iter), _parse(iter)),
238        "r": lambda: Dot("\n"),
239        "d": lambda: D(), # special form
240        "c": lambda: C(),
241        "v": lambda: V(),
242        "s": lambda: S(),
243        "k": lambda: K(),
244        "@": lambda: At(),
245        "?": lambda: Qu(iter.next()),
246        "|": lambda: Pipe(),
247        "e": lambda: E(),
248    }.get(c, lambda: _parse(iter))()
249    return result
250
251def parse(s):
252    return _parse(list(s).__iter__())
253
254class Debug():
255    show_node = False
256
257def _test():
258    import doctest
259    reload(doctest)
260    doctest.testmod()
261
262def fib():
263    "show Fibonacci numbers"
264    run("""
265    ```s``s``sii`ki
266      `k.*``s``s`ks
267     ``s`k`s`ks``s``s`ks``s`k`s`kr``s`k`sikk
268      `k``s`ksk
269      """)
270
271#Debug.show_node = True
272#run("`````@?a.oi.kv")
273
Note: See TracBrowser for help on using the browser.