為什麼總有人追求 one-pass compiler?

One-pass compiler 代碼非常晦澀,效率也沒高到哪去。


One-pass 用在 C 這樣的靜態語言里已經過時了,因為今天的計算機性能很高,不在乎那點編譯時間。但是像 Lua 這樣的語言有可能被用作數據描述語言,就是說有可能好幾百兆的文件會被經常編譯,one-pass 就是有用的。一切都要看場景。


其實用lazy語言寫multi-pass compiler的話,就有可能獲得類似one-pass的效果:不在內存中顯式構建出多個pass的中間AST。


大概是炫技,因為要跟多pass的編譯器達到同樣的結果,非常難寫。


懶得聲明語法樹各個節點


對於相對簡單的解釋器,解釋體量比較小的、原子化代碼塊(比如類似Lisp、Haskell和Python的非OO風格),使用One pass構造解釋器避免顯式構造語法樹,確實有一箭雙鵰的愉悅感——但也僅限於此了。我自己寫過簡單的解釋器,One pass的代碼的可讀性和可維護性都是比較糟糕的。尤其是同時需要解釋代碼和進行類型推斷的時候(相比之下,預先顯式構造的語法樹的Two pass方法會簡單很多)。

對於複雜的大規模OO代碼,比如C++和Java這樣的,開發環境要附帶實時靜態分析這類功能,適應頻繁的局部修改代碼的需要,處理大量的局部聲明,那麼One pass顯然是不可行的。

我認為一個理想的編譯器會在打開任意規模的項目時先生成一個語法樹,局部的代碼修改相當於對語法樹某個結點的修改,儘可能避免重複性的全局編譯,然後寫代碼的過程就成為了實時拓展語法樹的過程。既然需要生成語法樹,那就至少是Two pass。有了語法樹就可以附加很豐富的分析功能和優化功能,這種拓展性是One pass所達不到的。

至於One pass是不是一種「追求極致」的表現,我持保留態度。這種「極致」僅限於有限的需求下的某種效率,但現實的尤其是人性化的需求會複雜很多,滿足這些需求則是另一種「極致」。

既然理論上的背景都是一樣的,那麼One pass和More pass並沒有實質區別,能根據實際需求分析兩者的利弊才是最重要的。

-


觀念落後了。pass多少並不一定和效率相關。


推薦閱讀:

c++為什麼需要虛函數表?
現在編譯器處理那種「用換行代替分號」的語句邏輯是怎麼做的?
程序如何根據變數名在內存中找到存放這個變數的地址?
如何減小GacLib生成的可執行文件大小?

TAG:編譯器 | 編譯器優化 |