-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
32 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
## 編譯與直譯 | ||
只要學過計算機概論,大抵都對編譯與直譯有基本的概念。 | ||
|
||
常會有人把程式語言分類爲編譯式語言、直譯式語言兩類,其實這並不嚴謹,編譯與直譯並非形容「語言」,而是形容「語言的執行方式」。 | ||
|
||
舉例來說, C 語言通常被編譯成機器碼執行,但它也可以直譯執行,例如 [c4](https://github.com/rswier/c4) 就是個極簡 C 語言(子集)直譯器,才幾百行而已。 | ||
|
||
再舉個例子, Kotlin 官方就支援多種執行方式,可以編譯到機器碼、 JVM 字節碼、乃至於轉譯成 JavaScript 再交由 JavaScript 引擎執行。硬要將它歸類為編譯式或直譯式都不對,唯有把程式如何執行在機器上給具體描述出來,才有意義。 | ||
|
||
基本上,一個語言能被編譯,那幾乎都能被直譯,因為寫直譯器比編譯器要容易得多。而如 Python/Ruby/JavaScript 等動態語言則很難完全被編譯,即使真要編譯,由於動態語言中一個物件是否擁有某個方法是無法在編譯期判定的,所以在編譯出的執行檔中,勢必得加入厚重的運行時來即時維護物件資料、判定物件類型,但如此一來,還能算是編譯嗎? | ||
|
||
總的來說,編譯跟直譯是很粗略的分類,要知道一份程式是如何執行的,終究得深入其編譯時跟運行時的細節才行。當吾人說某語言是編譯執行,往往代表其運行時相對較小,反之若說某語言是直譯執行,代表其含有沈重的運行時(通常得附帶整個直譯器)。 | ||
|
||
## 什麼語言容易自舉 | ||
|
||
帶有沈重運行時的語言難以自舉。以 Python 為例,它的官方實作是用 C 寫的直譯器 CPython。在這個基礎之上,能透過**純**寫 Python 完成自舉嗎?如果用 Python 寫了個 Python 直譯器,該直譯器仍然得運行在 CPython 上,兩層直譯執行會得到一個很慢的直譯器,而且無法擺脫 CPython。 | ||
|
||
要擺脫 CPython ,就得是用 Python 寫出 Python 編譯器才行,以此編譯器將自身源碼轉為機器碼,就不再依賴 CPython 了。但前一節提到的物件維護運行時怎麼要怎麼加進去呢?有兩種思路: | ||
|
||
1. 手寫真言來實作運行時。 | ||
2. 定義一個不需要運行時的 Python 子集,用這個子集來寫運行時。 | ||
|
||
不管哪一種做法都需要額外的開發成本。 | ||
|
||
除了動態語言的物件/類型維護,垃圾搜集也是需要運行時的語言特性。有些語言如 Bash, JavaScript 還支援 `eval` 這種動態執行程式碼的函數,不把整個直譯器/編譯器包進編譯結果還真支援不了。 | ||
|
||
編譯時期的語法特性如模式匹配、和類型(sum type)以及各種語法糖都是編譯期(語法、語義分析)就處理完的,跟是否容易自舉的關係不大。當然,語言的能力越強,編譯器越複雜,但語言能力越強,編譯器又越好寫,該如何完成特性的迭代開發,這其中的折衷,大概也是自舉的樂趣所在吧! | ||
|
||
TODO: 此節應補圖 | ||
|
||
小記:本章不少內容屬貧道自行推想,有錯請不吝賜教。 |