可扩展编程

可扩展编程（Extensible programming）是計算機科學的詞語，是指程式設計的風格會著重在可以擴展程式語言、編譯器、运行时系统的相關機制。可延伸程式語言（Extensible programming languages）是可以支援這種程式設計方式的程式語言，在1960年代曾是熱門研究主題，而此運動在1970年代就已邊緣化Standish, Thomas A., "Extensibility in Programming Language Design", SIGPLAN Notices 10 no. 7 (July 1975), pp. 18–21.，在21世紀時此一主題又受到關注Gregory V. Wilson, "Extensible Programming for the 21st Century ", ACM Queue 2 no. 9 (Dec/Jan 2004–2005).。
 以往的發展 
第一篇和可扩展编程運動有關的論文Sammet, Jean E., Programming Languages: History and Fundamentals, Prentice-Hall, 1969, section III.7.2是道格拉斯·麥克羅伊在1960撰寫，有關高階程式語言巨集的論文McIlroy, M.D., "Macro Instruction Extensions of Compiler Languages", Communications of the ACM 3 no. 4 (April 1960), pp. 214–220.。另一個早期對可擴展原則的說明，出現在Brooker和Morris所著，有關編譯器編譯程式（compiler-compiler）的論文Brooker, R.A. and Morris, D., "A General Translation Program for Phrase Structure Languages", Journal of the ACM 9 no. 1 (January 1962), pp. 1–10. The paper was received in 1960.。此運動中有二個具代表性，分別在1969年及1971年舉行的學術座談會，是此運動發展最熱的時期Christensen, C. and Shaw, C.J., eds., Proceedings of the Extensible Languages Symposium, SIGPLAN Notices 4 no. 8 (August 1969).Schuman, S.A., 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, M.C., in "Panel on the Concept of Extensibility", pp. 53–54 of the 1969 symposium.

在1969的研討會中，認為Simula是可延伸程式語言。

Standish描述了三類不同的語言延伸，稱為paraphrase、orthophrase和metaphrase。（paraphrase和metaphrase原來是翻譯上的術語）。

 paraphrase（改寫）會說明新功能如何用以前定義（或是將要定義）的事物來表示，以此定義新的功能。Standish的舉例提到了巨集定義、一般程序定義、語法延伸、資料定義、運算子定義以及控制結構的延伸。
 Orthophrase在語言中加入一些基礎語言無法達成的功能，例如在沒有輸出入指令的基礎語言中加入輸入及輸出功能。因為此功能無法用此基礎語言表示，因此一定要用其他的語言來定義。這些擴展功能對原語言來說就是Orthophrase。這對應現代的插件。
 Metaphrase會修改詮釋表示式時所用的規則。這對應現代的反射式编程。

  以往發展的終止 
Standish認為當時可扩展编程的失敗是因為若程式有數層的扩展，在撰寫時會格外困難。程式設計師可以在基礎語言上加上第一層的巨集。若要在此語言上加上第二層的扩展，後續的程式設計者需要熟悉基礎語言，以及第一層的扩展。若要加上第三層的扩展，程式設計者需要熟悉基礎語言、第一層扩展以及第二層扩展。取代可扩展编程運動的抽象化，其本意就是讓程式設計者
不用接觸低階的細節。

Standish雖然在1975年時將Simula歸類為可扩展程式語言，但其研究似乎沒有將比較新的，以抽象化為基礎技術算在可扩展程式語言內（只是其中對可扩展的定義，使用了非常寬的定義，抽象化在技術上是在該定義範圍內）。1978年有一份文獻提到程式抽象化的歷史，說明從電腦發明以來的相關演進，其中沒有提到巨集，也沒有提及可扩展编程運動Guarino, L.R., "The Evolution of Abstraction in Programming Languages", CMU-CS-78-120, Department of Computer Science, Carnegie-Mellon 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
 PL/I
 Smalltalk

相關條目

面向语言的程序设计
同像性

參考資料

Category:编程范式