| 1 | """ unlambda interpreter
|
|---|
| 2 |
|
|---|
| 3 | # test
|
|---|
| 4 | >>> run("`.ai")
|
|---|
| 5 | a
|
|---|
| 6 | >>> run("``i.ai")
|
|---|
| 7 | a
|
|---|
| 8 | >>> run("`i`.ai")
|
|---|
| 9 | a
|
|---|
| 10 | >>> run("`d`.ai")
|
|---|
| 11 | >>> run("``d`.aii")
|
|---|
| 12 | a
|
|---|
| 13 | >>> run("`.b`i`.ai")
|
|---|
| 14 | ab
|
|---|
| 15 | >>> run("`.b`d`.ai")
|
|---|
| 16 | b
|
|---|
| 17 | >>> run("``.b`d`.aii")
|
|---|
| 18 | ba
|
|---|
| 19 | >>> run("``.b`.a`ci.c")
|
|---|
| 20 | ababc
|
|---|
| 21 | >>> Debug.show_node = True
|
|---|
| 22 | >>> run("``v.a.a")
|
|---|
| 23 | (apply (apply V (print 'a')) (print 'a'))
|
|---|
| 24 | (apply V (print 'a'))
|
|---|
| 25 | V
|
|---|
| 26 | >>> Debug.show_node = False
|
|---|
| 27 | >>> run("````skk.av")
|
|---|
| 28 | a
|
|---|
| 29 | """
|
|---|
| 30 | # Main loop
|
|---|
| 31 | #
|
|---|
| 32 | def 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
|
|---|
| 42 | def FinalCont(f):
|
|---|
| 43 | return FinalTask
|
|---|
| 44 |
|
|---|
| 45 | # Task
|
|---|
| 46 | #
|
|---|
| 47 |
|
|---|
| 48 | def FinalTask(X=None):
|
|---|
| 49 | raise StopIteration()
|
|---|
| 50 |
|
|---|
| 51 | def EvalTask(node, cont):
|
|---|
| 52 | def run():
|
|---|
| 53 | if Debug.show_node: print node
|
|---|
| 54 | return node(cont)
|
|---|
| 55 | return run
|
|---|
| 56 |
|
|---|
| 57 | def ApplyTask(operator, operand, cont):
|
|---|
| 58 | def run():
|
|---|
| 59 | return operator(operand, cont)
|
|---|
| 60 | return run
|
|---|
| 61 |
|
|---|
| 62 | # Node
|
|---|
| 63 | #
|
|---|
| 64 | class Node(object):
|
|---|
| 65 | "parsed element"
|
|---|
| 66 |
|
|---|
| 67 | I = lambda: lambda c: c(lambda X, c: c(X))
|
|---|
| 68 |
|
|---|
| 69 | class 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 |
|
|---|
| 82 | class 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 |
|
|---|
| 114 | class D(Node):
|
|---|
| 115 | "delay (special form)"
|
|---|
| 116 | def __str__(self):
|
|---|
| 117 | return "D"
|
|---|
| 118 | def __call__(self, cont):
|
|---|
| 119 | return cont(self)
|
|---|
| 120 |
|
|---|
| 121 |
|
|---|
| 122 | class 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 |
|
|---|
| 137 | class 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 |
|
|---|
| 147 | class 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 |
|
|---|
| 158 | class 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 |
|
|---|
| 174 | class 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 |
|
|---|
| 181 | class 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 |
|
|---|
| 200 | class 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 |
|
|---|
| 215 | class 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 |
|
|---|
| 226 | class E(Node):
|
|---|
| 227 | def __call__(self, cont):
|
|---|
| 228 | def E0(X, cont):
|
|---|
| 229 | return FinalTask(X)
|
|---|
| 230 | return E0
|
|---|
| 231 |
|
|---|
| 232 | def _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 |
|
|---|
| 251 | def parse(s):
|
|---|
| 252 | return _parse(list(s).__iter__())
|
|---|
| 253 |
|
|---|
| 254 | class Debug():
|
|---|
| 255 | show_node = False
|
|---|
| 256 |
|
|---|
| 257 | def _test():
|
|---|
| 258 | import doctest
|
|---|
| 259 | reload(doctest)
|
|---|
| 260 | doctest.testmod()
|
|---|
| 261 |
|
|---|
| 262 | def 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 |
|
|---|