Skip to content

Commit

Permalink
離塵第一步
Browse files Browse the repository at this point in the history
  • Loading branch information
MROS committed Sep 17, 2024
1 parent 57dd858 commit 3c8f4d1
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 4 deletions.
6 changes: 5 additions & 1 deletion book/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ export default defineConfig({
sidebar: [
{
text: "緣起",
items: [{ text: "大品天仙訣之臆想", link: "/大品天仙訣之臆想" }],
items: [
{ text: "大品天仙訣之臆想", link: "/大品天仙訣之臆想" },
{ text: "序・去往新世界", link: "/序・去往新世界" },
{ text: "離塵第一步:自舉", link: "/離塵第一步:自舉" },
],
},
],

Expand Down
4 changes: 1 addition & 3 deletions book/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@ hero:
link: /大品天仙訣之臆想

features:
- title: 天語
details: 本書定義以天語為關鍵字的「杞人咒」,書中將涵蓋天語的詞法分析。
- title: 自舉
details: 欲離塵,結真丹。
- title: 元嬰
details: 杞人咒」乃系統級程式語言,將可用於撰寫作業系統。
details: 音界」乃系統級程式語言,將可用於撰寫作業系統。
---

7 changes: 7 additions & 0 deletions book/序・去往新世界.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
「離塵指引」啟發自大品天仙訣,但並不嚴格遵循仙訣。「離塵指引」並不是企圖囊括計算機科學系統部分的教材,而是有著更大的野心,它要指引的,是一條重塑計算機系統之路。

軟體界經歷幾十年的發展,已經沉澱下數以億計的程式碼,這些程式碼盤根錯節,彼此之間互相緊密依賴。舉例來說,寫一個網站,必須跑在瀏覽器上,瀏覽器又跑在作業系統之上,主流作業系統又都是由 C/C++ 編譯器編譯出來,依賴可以追溯很多很多層。甚至這些依賴不是樹狀的,彼此會成環,例如編譯器通常也需要作業系統作為執行環境,而作業系統又是由編譯器編譯生成的。

將現代軟體當做一個世界,從學會寫程式的第一天開始,絕大多數的人就永遠也脫離不了它。本作企圖指引人們如何離開原世界(下稱塵界),再造一個新世界(洞天、仙界、天界)。

在這個新世界,不必為了理解一段彆扭的程式碼去考古三十年前的郵件往返,不必再與費解的歷史遺留問題做鬥爭,人不該活在前人定義好的世界裡反覆修補。來吧!道友,去創造一個新世界,即使要設計世界的法則會讓你絞盡腦汁;即使維持世界的運轉會令人精疲力竭...
42 changes: 42 additions & 0 deletions book/離塵第一步:自舉.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
書接上回,塵界程式碼彼此依賴,如樹、如網。要想脫出這張樹網,自成一個世界,固然可以一切用組合語言(下稱真言)寫就,但常人負荷不了如此巨大的工作量,借鑑塵界軟體的發展史,先造出一門高階語言,再以此撰寫程式,能大幅加快構造世界的速度。

## 自舉高階語言編譯器

X 語言的編譯器,未必就要用 X 語言來寫就,但如果能夠 X 語言來寫自己的編譯器,就象徵了 X 語言已經成熟到一定程度,其自成一格,不需要依賴另一種語言。

但若欲「離塵」,就需要去除掉塵界的所有依賴,就斷不可用塵界的語言來寫新世界語言的編譯器了。自舉不再是可選項,而是唯一的方法。

然而,還沒有可執行的 X 語言編譯器時,就算把 X 語言編譯器源碼寫好了,要怎麼編譯出可執行的 X 語言編譯器呢?這是一個雞生蛋蛋生雞的問題,在不同條件下各有做法。

### 洪荒年代

在還沒有高階語言的年代(195X 之前),要創造高階語言就只能由真言寫起了。流程如下:

1. 以真言寫出 X 語言零號編譯器 X0。
2. 以 X 語言寫出 X 語言初號編譯器 X1 源碼。
3. 用 X0 編譯 X1 源碼,得到 X1。

或者也可以選擇:

1. 用 X 語言來寫 X 語言的編譯器 X1 。(此時還沒有可執行的 X 語言編譯器)。
2. 人肉將編譯器 X1 的源碼翻譯成真言,得到可執行的 X 語言編譯器 X1-0。
3. 用 X1-0 編譯自身原始碼,得到非人肉翻譯的編譯器 X1-1。

這兩種流程其實大同小異,終究都是用人肉寫出第一版編譯器,不過第二種流程在生成第一版編譯器時,是根據 X 語言的源碼爲藍本逐句生成的,較有所憑依,算是流程上的一點優化。

### 近現代

軟體發展至今,早已有幾十種甚至數百種成熟可靠的語言可用,自舉之初,不必像洪荒年代直接手寫真言,而可以採用現成語言來寫零號編譯器。假設我們採用成熟的 C 語言來輔助自舉,流程如下:

1. 用 A 語言來寫 X 語言的零號編譯器 X0 。
2. 以 X 語言寫出 X 語言初號編譯器 X1 源碼。
3. 用 X0 編譯 X1 源碼,得到 X1。

舉個實際例子, Rust 一開始用 Ocaml 來寫前幾版 Rust 編譯器,待 Rust 編譯器成熟後,再以 Rust 語言重寫一份 Rust 編譯器。此時 X = Rust , A = Ocaml

## 迭代
寫出完整的 X 語言未必是一蹴而就,畢竟,設計新語言需要反覆實驗,幾乎不可能在零號或初號編譯器就定完 X 語言而毫無問題,很有可能在自舉的過程中才會發現設計缺失。所以初號編譯器所能編譯的語言已經與零號編譯器有所不同了,在語言特性尚未穩定之前,每一版的編譯器都可能不相互兼容。

在洪荒年代,更有可能的狀況是,手寫真言實在太累了。因此零號編譯器只有十分簡單的功能,它僅能編譯 X 語言的子集 X--,例如,僅支援迴圈、分支、函數這幾個最簡單的語言特性。得到了 X-- 編譯器之後,用 X-- 寫一個 X- 編譯器(X- 是能力介於 X-- 與 X 之間的語言),再將 X-- 寫就的 X- 編譯器擴展為用 X- 寫就的 X 編譯器,如此反覆迭代,才最終得到原先定義好的 X 於言編譯器。


5 changes: 5 additions & 0 deletions book/T字圖.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# T字圖
在描述字句過程時,我們常常要加上許多定語,才能分辨:
- 以 Y 語言寫成的 X 語言編譯器的執行檔
- 以 Y 語言寫成的 X 語言編譯器的源碼
-

0 comments on commit 3c8f4d1

Please sign in to comment.