1.1 1957 — FORTRAN 與第一個真正的編譯器#
編譯器為何誕生#
1940 年代末,第一部電子計算機 ENIAC(1945 年完成)以插線與開關編程,隨後的 von Neumann 架構機器則以機器碼與組合語言編程。當時工程師普遍認為,唯有親手撰寫組合語言、甚至直接操作位元,才能寫出「夠快」的程式。高階語言被視為浪漫的幻想:機器怎麼可能替人翻譯出效率不輸手工的程式碼?
這個偏見被三個人逐步打破。1940 年代末,Konrad Zuse 為其 Z4 設計了 Plankalkül(但因戰後環境未實作);1952 年,Grace Hopper 在 Remington Rand 完成了 A-0 編譯器,將符號化的副程式描述翻譯為機器碼,並在 1957 年發展出 FLOW-MATIC,為 COBOL 鋪路。但這些系統多半是「組合器+副程式庫」的性質,真正的突破來自 1954 年至 1957 年,由 IBM 的 John Backus 領導的 FORTRAN 專案。
Backus 團隊與 FORTRAN I#
1954 年,Backus 在 IBM 提出「Formula Translation」的提案報告《Preliminary Report: Specifications for the IBM Mathematical FORmula TRANslating System》。當時 IBM 剛推出 704 計算機,軟體成本高漲:寫一個大型科學計算程式往往要耗費數月。Backus 的目標極具野心——產生的程式碼速度必須「接近手工組合語言」,否則沒有人會採用。
團隊核心成員包括 Robert Nelson、Irving Ziller、Harlan Herrick、Sheldon Best、Richard Goldberg、Lois Haibt 等。他們開創了許多延用至今的技術:
- 表達式的樹狀解析:將代數式解析成樹,再依代數恆等式改寫。
- 公共子表示式刪除:
x*y出現多次時只計算一次。 - 簡化強度與迴圈最佳化:把乘法換成加法、將不變量移出迴圈。
- 雜湊符號表:Lois Haibt 以 Monte Carlo 方法分析 FORTRAN 程式的分支行為來安排暫存器使用。
1957 年 4 月,FORTRAN I 編譯器正式交付給第一批 60 個客戶。經過 22,000 行程式碼、六大系統的密集測試後,IBM 對外宣稱編譯出的程式碼效率已達手工碼的一半以上(多數案例更接近),從此高階語言編程被廣為接受。這證明了 Backus 團隊的核心信念:編譯器不只是翻譯器,更是一座最佳化的大山。
為什麼 FORTRAN 的挑戰特別難#
FORTRAN 當時面臨的技術難題至今仍是教科書經典案例:
- FORTRAN 不宣告維度的陣列問題:語法上
DO 5 I=1,3與DO 5 I = 1.3(把 1.3 賦值給變數 DO5I)僅差一個字元,因當時卡片輸入易錯、空白不具意義,這個歧義成為著名的軼事(原委有所誇大,但反映了設計取捨)。 - 別名問題:FORTRAN 允許副程式以相同的實際參數傳入同一陣列,使得「兩個變數是否指向同一記憶體」難以判斷,至今仍是最佳化的核心難題。
- 缺乏暫存器模型:704 只有 38 個索引暫存器與浮點暫存器,必須精確分配。
歷史的延續#
FORTRAN 之後的發展構成一條清晰的譜系:
- 1958:FORTRAN II 加入副程式;同年 LISP 由 John McCarthy 提出,引出遞迴與垃圾回收。
- 1960:ALGOL 60 以 Backus–Naur Form(BNF)正式定義語法,使「語法可以形式化」成為共識,直接催生了本書第 3 章的語法分析理論。
- 1970 年代:Ritchie 與 Thompson 的 C、UNIX 把編譯器變成可移植的系統軟體。
- 1980–2000:RISC 架構(Patterson & Hennessy,1980 年代初)使得最佳化的重要性再度暴增,LLVM(Chris Lattner, 2000 年代初)與 GCC 成為現代生態系主流。
Backus 在 1977 年獲得圖靈獎,其得獎演說《Can Programming Be Liberated from the von Neumann Style?》再次提出高階抽象的願景。編譯器的歷史告訴我們:語言的每一次抽象化升級,都必須由編譯器技術的突破來兌現。
小結#
- 編譯器誕生於 1950 年代對「軟體生產力」與「執行效率」的雙重需求。
- Grace Hopper 的 A-0/FLOW-MATIC 開啟翻譯概念,Backus 團隊的 FORTRAN 證明最佳化可行。
- ALGOL 60 的 BNF 將語法形式化,奠定後續所有編譯理論的基礎。