如何將lisp/scheme翻譯成llvm IR,並通過llvm生成機器碼?
感覺從lisp到llvm IR的跨度比較大,大家認為過程中可能出現的難點和主要存在的問題是什麼?
http://stackoverflow.com/questions/2143605/why-isnt-there-a-good-scheme-lisp-on-llvm/2143627上面提到似乎難點在GC上?我不是很理解需要GC的語言和LLVM之間有什麼小九九。
涉及到「遞歸」的語義,包括define,letrec,容易搞錯,記得先測試。推薦Dybvig的一篇相關文章:http://www.cs.indiana.edu/~dyb/papers/fixing-letrec.pdf LtU相關討論:doing letrec with lambdas
目前正在被這個坑。。實現一個帶類型系統的lisp,通過類型檢查和幾次desugaring後轉換成一個scheme的子集(跟iswim很像,已經非常接近裸的lambda calculus),結果寫這個scheme子集的解釋器時被坑得死去活來,有個讓遞歸函數跑不起來的跟閉包表示相關的bug,而且還沒調出來( ′_ゝ`) 不管是用Z組合子也好,還是直接實現letrec語義也好都會出這個bug,感覺需要回爐重練閉關寫一年解釋器再出來吹這個牛X。。
所以就說個教訓讓題主噹噹心。
想像一下這學期交付一個有scheme後端的編譯器。。一開始還雄心勃勃要做llvm後端的。。哭瞎
UPDATE:
bug解決了。關於遞歸的問題再說一下:比如我用letrec定義了一個遞歸函數f,f是一個lambda表達式,然後在運行期對f求值應該會生成一個閉包,閉包的環境里有一項是f,指向這個閉包自身,構成了一個環。如果有互遞歸的函數,運行時可能生成相互指向的閉包,構成循環引用。然後,內存管理記得要處理好這種循環引用。Scheme是動態類型的,不可能輕易地像靜態類型語言那樣簡單通過LLVM完全弄成原生代碼加速。
我之前想到的方法還是,優化局部的頻繁的簡單運算(例如大量重複整數運算弄成原生代碼)和整個「框架」(例如調用賦值每個expression的宏觀的「順序」可以用原生代碼),最後捆綁一個帶有gc功能的運行時。最終性能未必好上太多,肯定該有的類型檢查到處都是。
現在覺得,如果強制加一套類型簽名和嚴格檢查,後端省力又高效,順便保障你代碼不寫錯,不然類型檢查都通不過。推薦閱讀:
※linux下編程,定義數組一多就會崩潰,如何解決?
※(截止2014.8.21)windows平台上完成一個編譯器(詞法、語法分析),想使用C++11開發,有啥好的技術推薦嗎?
※這是OS X下g++的bug嗎?
※遞歸下降的語法分析程序如何進行錯誤恢復?
※模板編程如何引入類型是否存在條件???