[Lua]50行代碼的解釋器,用來演示lambda calculus

嗯,來寫寫通過:javascript

 

在知乎上看見用Belleve牛用javascript寫了一個精簡的lisp解釋器  java

  =>git

我也想寫一個,用lua寫,能多簡單呢?  github

  =>bash

寫了一個閹割的scheme解釋器,包含lambda/if兩個special form,以及+-=print幾個過程,60行代碼  less

  =>lua

能再精簡嗎?好比把if給去掉?  spa

  =>code

搜索,嗯,lambda calculus能幫我  orm

  =>

閱讀wiki上lambda calculus的"Encoding datatypes"部分  

  =>

改寫scheme腳本,用Y-combinator幫助實現遞歸,用church numeral表示數字,以及實現church numeral之上的基本邏輯、算數、關係運算,最後用這些基本運算編寫for-each和fib過程  

  =>

從解釋器裏移除關鍵字if,移除過程+-=,改寫print過程使之可以打印church numeral

  =>

進一步把lambda實現爲單參數過程,多參數lambda的聲明和調用變成了語法糖,因而全部過程都是fully curried的了,和haskell同樣

  =>

雖然scheme腳本爲了打印fibonacci數列須要作更多的事情,但解釋器僅僅爲這門閹割scheme提供了一個lambda關鍵字;就結果而言,它演示瞭如何在只支持「匿名過程」這個基本元素的語言中實現強大的計算能力;固然,完成這一切靠的是lambda calculus理論。過程和結果都很是有趣~

 

scheme代碼,只支持lambda這個special form和基本過程print:

 1 ((lambda (zero one add mul pow sub1 true false and or)
 2    ((lambda (sub not zero? two Y)
 3       ((lambda (less-equal? equal? three four)
 4          ;------------------------------
 5          ((lambda (for-each fib)
 6             (for-each (lambda (i) (print (fib zero one zero i))) zero (mul four four))
 7             )
 8           (Y 
 9             (lambda (self)
10               (lambda (f i n)
11                 (f i)
12                 (((equal? i n)
13                   (lambda () i)
14                   (lambda () (self f (add i one) n))))
15                 )
16               ))
17           (Y 
18             (lambda (self)
19               (lambda (a b i n)
20                 (((equal? i n)
21                   (lambda () a)
22                   (lambda () (self b (add a b) (add i one) n))))
23                 )
24               ))
25           )
26          ;------------------------------
27          )
28        (lambda (m n) (zero? (sub m n)))
29        (lambda (m n) (and (zero? (sub m n)) (zero? (sub n m))))
30        (add two one)
31        (add two two)
32        ))
33     (lambda (m n) (n sub1 m))
34     (lambda (a) (a false true))
35     (lambda (n) (n (lambda (x) false) true))
36     (add one one)
37     (lambda (f)
38       ((lambda (g) (g g))
39        (lambda (g) (f (lambda (a) ((g g) a))))))
40     ))
41  (lambda (f x) x)
42  (lambda (f x) (f x))
43  (lambda (m n f x) (m f (n f x)))
44  (lambda (m n f) (m (n f)))
45  (lambda (e b) (e b))
46  (lambda (n f x) 
47    (((n 
48        (lambda (g h) (h (g f)))) 
49      (lambda (u) x)) 
50     (lambda (u) u)))
51  (lambda (a b) a)
52  (lambda (a b) b)
53  (lambda (a b) (a b a))
54  (lambda (a b) (a a b))
55  )

 

lua解釋器代碼:

 1 function S_parse(s)
 2     s = string.gsub(s, ';[^\n]+\n', '')
 3     s = string.gsub(s, '%s+', ',')
 4     s = string.gsub(s, '[%(%)]', {['(']='{',[')']='}'})
 5     s = string.gsub(s, '[^{},%d][^{},]*', '"%1"')
 6     return assert(loadstring(string.format("return {%s}", s)))()[1]
 7 end
 8 function S_lookupVar(vm, env, name)
 9     while env do
10         if env[name] then return env[name] end
11         env = env[vm]
12     end
13 end
14 function S_createLambda(vm, env, argIdx, expArgs, expBody)
15     return function(arg)
16         local newEnv = {[vm]=env, [expArgs[argIdx]]=arg}
17         if argIdx == #expArgs then
18             for i = 3, #expBody - 1 do S_interpret(vm, newEnv, expBody[i]) end
19             return S_interpret(vm, newEnv, expBody[#expBody])
20         else
21             return S_createLambda(vm, newEnv, argIdx + 1, expArgs, expBody)
22         end
23     end
24 end
25 function S_interpret(vm, env, exp)
26     if type(exp) == 'string' then 
27         return S_lookupVar(vm, env, exp) 
28     elseif exp[1] == 'lambda' then
29         return S_createLambda(vm, env, 1, #exp[2] > 0 and exp[2] or {'_'}, exp)
30     else 
31         local p = S_interpret(vm, env, exp[1])
32         for i = 2, math.max(#exp, 2) do 
33             p = p(exp[i] and S_interpret(vm, env, exp[i]) or nil)
34         end
35         return p
36     end
37 end
38 function S_createVM()
39     return {
40         G = {
41             ['print'] = function(n) print(n(function(i) return i + 1 end)(0)) end,
42         },
43     }
44 end
45 function S_eval(vm, s)
46     return S_interpret(vm, vm.G, S_parse(s))
47 end
48 
49 S_eval(S_createVM(), io.read('*a'))

 

驅動:

1 #! /bin/bash
2 cat script.rkt | lua main.lua

 

結果:

0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987

 

源碼放這兒:https://github.com/PublicScan/LambdaCalculus/tree/c4a64b162b7049a6d278c86aaaa4a7c0750d7fa7

相關文章
相關標籤/搜索