可擴充套件程式設計（Extensible programming）是電腦科學的詞語，是指程式設計的風格會著重在可以擴充套件程式語言、編譯器、執行時系統的相關機制。可延伸程式語言（Extensible programming languages）是可以支援這種程式設計方式的程式語言，在 1960 年代曾是熱門研究主題，而此運動在 1970 年代就已邊緣化 Standish Thomas A Extensibility in Programming Language Design SIGPLAN Notices 10 no 7 July 1975 pp 1821，在 21 世紀時此一主題又受到關注 Gregory V Wilson Extensible Programming for the 21st Century ACM Queue 2 no 9 DecJan 20042005。 以往的發展 第一篇和可擴充套件程式設計運動有關的論文 Sammet Jean E Programming Languages History and Fundamentals PrenticeHall 1969 section III72 是道格拉斯麥克羅伊在 1960 撰寫，有關高階程式語言巨集的論文 McIlroy MD Macro Instruction Extensions of Compiler Languages Communications of the ACM 3 no 4 April 1960 pp 214220。另一個早期對可擴充套件原則的說明，出現在 Brooker 和 Morris 所著，有關編譯器編譯程式（compilercompiler）的論文 Brooker RA and Morris D A General Translation Program for Phrase Structure Languages Journal of the ACM 9 no 1 January 1962 pp 110 The paper was received in 1960。此運動中有二個具代表性，分別在 1969 年及 1971 年舉行的學術座談會，是此運動發展最熱的時期 Christensen C and Shaw CJ eds Proceedings of the Extensible Languages Symposium SIGPLAN Notices 4 no 8 August 1969Schuman SA ed Proceedings of the International Symposium on Extensible Languages SIGPLAN Notices 6 no 12 December 1971。Thomas A Standish 在 1975 年發表對此運動的調查文章，在本質上屬於事後的剖析。Forth 算是此一運動的例外，不過也沒有被人注意到。 特點 可延伸程式語言會包括提供基礎計算功能的基礎語言（base language），以及可以修改基礎語言的元語言。程式會包括元語言所進行的修改，以及以修改後基礎語言所撰寫的程式碼。 在此波潮流中，最著名的語言擴充套件技術就是巨集定義。語法修改也和可擴充套件程式設計運動有密切的關係，最終發展成形式主義。Lisp 程式語言的群體仍和可擴充套件程式語言群體分開，其原因顯然如下： 任何程式語言，只要程式碼和資料在本質上可以互換，就可以視為是可延伸程式語言 由 Lisp 已長久當作可延伸程式語言來使用，就可以輕易的看出此一事實。Harrison MC in Panel on the Concept of Extensibility pp 5354 of the 1969 symposium 在 1969 的研討會中，認為 Simula 是可延伸程式語言。 Standish 描述了三類不同的語言延伸，稱為 paraphrase、orthophrase 和 metaphrase。（paraphrase 和 metaphrase 原來是翻譯上的術語）。 paraphrase（改寫）會說明新功能如何用以前定義（或是將要定義）的事物來表示，以此定義新的功能。Standish 的舉例提到了巨集定義、一般程式定義、語法延伸、資料定義、運運算元定義以及控制結構的延伸。 Orthophrase 在語言中加入一些基礎語言無法達成的功能，例如在沒有輸出入指令的基礎語言中加入輸入及輸出功能。因為此功能無法用此基礎語言表示，因此一定要用其他的語言來定義。這些擴充套件功能對原語言來說就是 Orthophrase。這對應現代的外掛。 Metaphrase 會修改詮釋表示式時所用的規則。這對應現代的反射式程式設計。 以往發展的終止 Standish 認為當時可擴充套件程式設計的失敗是因為若程式有數層的擴充套件，在撰寫時會格外困難。程式設計師可以在基礎語言上加上第一層的巨集。若要在此語言上加上第二層的擴充套件，後續的程式設計者需要熟悉基礎語言，以及第一層的擴充套件。若要加上第三層的擴充套件，程式設計者需要熟悉基礎語言、第一層擴充套件以及第二層擴充套件。取代可擴充套件程式設計運動的抽象化，其本意就是讓程式設計者 不用接觸低階的細節。 Standish 雖然在 1975 年時將 Simula 歸類為可擴充套件程式語言，但其研究似乎沒有將比較新的，以抽象化為基礎技術算在可擴充套件程式語言內（只是其中對可擴充套件的定義，使用了非常寬的定義，抽象化在技術上是在該定義範圍內）。1978 年有一份文獻提到程式抽象化的歷史，說明從電腦發明以來的相關演進，其中沒有提到巨集，也沒有提及可擴充套件程式設計運動 Guarino LR The Evolution of Abstraction in Programming Languages CMUCS78120 Department of Computer Science CarnegieMellon University Pennsylvania 22 May 1978。一直到 1980 年代末期，才試驗性的將巨集列在抽象化運動中（可能是因為衛生巨集的出現），其名稱為「句法抽象化」（syntactic abstraction）Gabriel Richard P ed Draft Report on Requirements for a Common Prototyping System SIGPLAN Notices 24 no 3 March 1989 pp 93ff。 現代的發展 現代支援可擴充套件程式設計的系統需要提供以下的所有功能。 可延伸的語法 這是指所編輯的來源程式語言不能是封閉、固定、靜態不能變化的。要支援在來源程式語言加入新關鍵字、新概念或是結構的功能。有些程式語言可以用使用者定義語法加入組成元素，例如 Coq、Racket、、OpenC、Zingaro Daniel Modern Extensible Languages SQRL Report 47 McMaster University October 2007 page 16、 、Rebol 及 Felix。可延伸的語法可以接受一些基礎以及固有的程式語言特性是不變的，但系統不可能只依賴這些程式語言的功能，需可以加入新的程式語言功能。 可延伸的編譯器 在可延伸程式設計中的編譯器，不是一個將程式原始碼轉換為二進位制可執行輸出的單層系統。編譯器本身也要是可延伸的，編譯器在實質上是許多外掛的組合，這些外掛可以將原始程式語言的輸入轉換為任何想要的輸出。例如，可延伸的編譯器可以支援產生目的碼、程式檔案、重新調整格式的原始碼，或是其他想要的輸出。編譯器的架構需允許使用者進入其編譯流程內，在編譯流程的各步驟可以提供其他的處理任務。 若考慮將原始程碼翻譯成電腦可以執行檔案的這個任務，可延伸編譯器需要有： 在其功能的絕大部份層面，使用外掛或是元件架構。 確認要編譯的語言（或是語言變體），配置適當的外掛來的辨認及確認其語言。 依各來源語言的型式語言規範，在句法及結構上確認。 呼叫適當的確認外掛，以協助來源語言的語意確認 允許使用者者在不同種類的程式碼產生器中選擇，可以依處理器、作業系統、虛擬機器及其他作業環境的不同，生成適合的執行檔。 提供錯誤訊息產生的功能，以及相關的延伸。 可以在抽象語法樹（AST）中加入新的節點種類。 抽象語法樹的節點中允許有新的值。 允許其他種類，連線節點的邊。 允許輸入抽象語法樹的轉換，可以部份或全部來自外部的程式。 允許輸入抽象語法樹的翻譯，可以部份或全部交由外部的程式。 協助內部和外部程式之間的資訊流，因為他們都會將抽象語法樹轉換或是翻譯為其他的抽象語法樹，或是其他表現方式。 可延伸的執行時環境 可延伸程式系統在執行時的環境要允許程式語言增加可處理的運算。例如，某個使用位元組碼直譯器的系統，需要允許定義新的位元組碼。在可延伸語法下，可以接受少數基礎運算或是固有運算是不能變的，不過這些固有運算要可以過載或是擴充，以便支援新增的行為。 內容和形式分離 可延伸程式系統需將程式視為要處理的資料。程式中需要完全沒有格式化相關的資訊。要給使用者的程式 視覺顯示以及編輯都應該是可延伸編譯器所支援的翻譯函式，將程式資料轉換成適合顯示或是編輯的格式。此翻譯會是雙向的翻譯。雙向翻譯的特性很重要，因為需要可以用許多不同的方式，輕鬆的處理可延伸程式。若只能用來源語言來編輯及檢視，然後就翻譯成機械碼，無法再翻譯成其他的格式，這是無法接受的。透過將來源輸入和其處理（格式、儲存、顯示及編輯）的格式分離，可以對程式進行各種不同的處理。 支援用原始語言除錯 可延伸程式系統需要可以用原始來源語言來進行除錯，即使是程式在變成可執行檔的過程有進行轉換或是延伸也是一樣。最為人知的是：不可以假設執行時資料只能用結構或是陣列的方式顯示。除錯器（更準確的說法是「程式檢查器」）需要讓執行時資料以適合其來源語言的形式來呈現。例如，若程式語言支援業務過程或是工作流的資料結構，需要將資料結構用外掛表示為流程圖或是其他適合的型式。 相關的軟體或程式語言 Felix Nemerle Rebol Ruby（超程式設計） OpenC XML Forth Lisp Racket Scheme Lua PLI Smalltalk 相關條目 面向語言的程式設計 同像性 參考資料 Category 程式設計典範