Pascal (程式語言)

歷史

Pascal基於ALGOL程式語言，為紀念法國數學家和哲學家布萊茲·帕斯卡而命名。維爾特後來開發了類似Pascal的Modula-2和Oberon。在開發Pascal之前，維爾特開發了語言Euler，然後開發了Algol-W。
最初，Pascal在很大程度上但不是完全地為了教授學生結構化編程。很多代學生已使用Pascal作為本科課程的入門語言。Pascal的變種也逐漸地用於從研究專案到PC遊戲和嵌入式系統的所有領域。更新的Pascal編譯器存在於廣泛使用它的領域。
GCC，Gnu C編譯器，最初是用Pascal的一種方言Pastel編寫的（見GCC#概觀）。Pascal是Apple Lisa和早期Mac開發使用的高階語言；最初Macintosh作業系統的部分是從Pascal原始碼手工翻譯成Motorola 68000組合語言的。流行的排版系統TeX是由高德納使用基於DEC PDP-10 Pascal的最初文學編程系統WEB編寫的，而像Total Commander的應用是使用Delphi（即Object Pascal）編寫的。
Object Pascal仍然廣泛用於開發像Skype這樣的Windows應用。

簡要描述

維爾特的意圖是，基於結構化編程，建立一個高效（無論是編譯速度還是生成程式碼）的執行速度。Pascal植根於Algol 60語言，但是也引進了一些概念和機制，使程式設計師（在Algol的純量和陣列之上）能定義他們自己的複雜（結構化）資料類型，也使建立諸如lists、trees和graphs這樣的動態和遞迴資料結構更容易。這些重要的特性包括記錄、列舉、子範圍、使用關聯指標去動態分配變數和集合。為了使這些有可能和有意義，Pascal在所有物件上有一個強型別，意味著如果不使用顯式轉換，一種資料類型不能轉換或解釋成另外一種。類似的機制是今天許多程式語言的標準。影響Pascal開發的其它語言是COBOL、Simula 67和維爾特自己的Algol-W。
Pascal，像今天的許多程式語言一樣（但是不像C家族的絕大多數語言），允許任意層次的巢狀過程定義，也允許過程和函式內部的絕大多數種類的定義和聲明。這使得一個非常簡單和一致的語法，能讓一個完整的program與一個單獨的procedure或function語法上近似相同（當然除了關鍵字本身外）。

實現

第一個Pascal編譯器是在Zurich為CDC 6000系列大型電腦家族設計的。維爾特報導，在1969年第一次使用Fortran實現的嘗試沒有成功，由於Fortran不足以表達複雜的資料結構。第二次嘗試以Pascal語言本身來制定，並在1970年代中期實施。由於許多Pascal編譯器已類似地自代管，即編譯器本身是以Pascal編寫的，因此在新特性加入語言或編譯器移植到一個新環境時編譯器通常能重編譯其本身。用C編寫的GNU Pascal編譯器是一個顯著的例外。
1972年，Welsh和Quinn在貝爾法斯特女王大學，第一次將CDC Pascal編譯器成功地移植到另外一個主機。目標主機是ICL1900系列。這個編譯器反過來說是ICS Multum微電腦Pascal編譯器的父母。以一個使用Pascal作為系統程式語言的視角，Glasgow University電腦科學系的Findlay，Cupples，Cavouras和Davis開發了Multum介面。完成於1973年夏季的Multum Pascal被認為是第一個16位元實現。
一個全新的編譯器由QUB的Welsh et al.在1977年完成。它提供了一個由Glasgow University的Findlay和Watt實現的源語言診斷特性（結合分析，跟蹤和類型辨識格式化事後轉儲）。該實現在1980年由南安普敦大學和Glasgow University的一個小組移植到ICL 2900系列。標準Pascal模式實現也基於該編譯器，曼徹斯特大學的Welsh和Hay在1984年已將其改編，以嚴格檢查與BSI 6192/ISO 7185標準的一致性，以及為可移植抽象機生成程式碼。
在北美洲為PDP-11編寫的第一個Pascal編譯器在Donald B. Gillies的伊利諾伊大學厄巴納-香檳分校構造，並生成了本地機器碼。Pascal在整個1970年代和1980年代大受歡迎。
為了迅速地傳播該語言，一個編譯器「移植工具包」在Zurich產生，包括一個為「虛擬」堆疊機（即啟動本身合理有效解釋的程式碼）生成程式碼的編譯器，一個解釋這些程式碼的直譯器——Pascal-P系統。雖然SC（堆疊電腦）程式碼的主要意圖是在至少一個系統上編譯成真實的機器碼，著名的UCSD實現使用它建立了解釋性UCSD p-System。P-系統編譯器被稱作P1-P4，P1是來自於Zurich的第一個版本，P4是最後一個。
P4編譯器/直譯器仍然可以在相容最初Pascal的系統上執行和編譯。然而，它本身只是Pascal語言的一個子集。接受全部Pascal語言和包含ISO 7185相容性的一個P4版本建立了，稱作P5編譯器，它在源形式上可用。
一個為IBM System/370大型電腦產生本地二機制程式碼的P4編譯器版本由澳大利亞原子能委員會發布；縮寫該委員會的名稱後，它被稱作「AAEC Pascal編譯器」。從1975年6月起，一個包含編譯器原始碼和二機制程式碼，以及PDP-10主機執行時庫檔案的P4版本可以從這裡下載。
在1980年代早期，也是為IBM System 370開發的Watcom Pascal開發了。
IP Pascal是一個使用Micropolis DOS的Pascal程式語言的實現，但是被迅速地移植到執行於Z80上的CP/M。在1994年它被移植動80386類型機器上，今天作為Windows/XP和Linux實現存在。在2008年，該系統達到一個新層次，該結果語言稱作「Pascaline」（Pascal的計算機之後）。它包括物件，命名空間控制，動態陣列和許多其它擴充，以及與C有相同功能和類型保護的通用特性。它僅是也相容最初Pascal實現（作為ISO 7185的標準）的這樣一個實現。
在1980年代早期，UCSD Pascal移植到Apple II和Apple III電腦，以提供一個隨著機器而來的BASIC直譯器的結構化替代品。
Apple Computer在1982年為Lisa Workshop建立了自己的Lisa Pascal，在1985年將該編譯器移植到Apple Macintosh和MPW。在1985年，經諮詢維爾特，Larry Tesler定義了Object Pascal，這些擴充合併進Lisa Pascal和Mac Pascal編譯器。
在1980年代，Anders Hejlsberg為Nascom-2編寫了Blue Label Pascal編譯器。為IBM PC編寫的該編譯器的重實現在Borland收購之前以Compas Pascal和PolyPascal的名稱銷售。重新命名為Turbo Pascal後，它變得廣受歡迎，一方面由於一個積極的定價策略，一方面由於是第一個全螢幕整合式開發環境之一，以及快速的周轉時間（只需要數秒編譯，連結和執行）。另外，它用組合語言編寫，並整體高度最佳化，使它比許多競爭對手更小和更快。1986年Anders將Turbo Pascal移植到Macintosh，並將Apple的Object Pascal擴充合併進Turbo Pascal。這些擴充然後加回到Turbo Pascal v5.5的PC版本中。與此同時Microsoft也實現了Object Pascal編譯器。 Turbo Pascal 5.5給在1980年代後期開始主要關注於IBM PC的Pascal社群帶來巨大影響力。許多研究BASIC結構化替代品的PC愛好者使用該產品。它也開始被專業開發人員接受。幾乎同時，為了讓Pascal程式設計師直接使用Microsoft Windows的基於C的API，許多概念從C語言引入。這些擴充包括空終止字串，指標算術運算，函式指標，address-of運算子和非安全類型轉換。
然而，Borland後來決定需要更多精細的物件導向特性，並在Delphi里使用Apple提議的Object Pascal草圖示准作為基礎重新開始。（該Apple草圖仍然不是一個正式的標準。）Delphi程式語言的第一版相應地命名為Object Pascal。與老的OOP擴充相比較，主要的增加是基於參考物件模型，虛擬構建器和解構器，以及屬性。幾個其它編譯器也實現了該方言。
Turbo Pascal，和其它有單元或模組概念的衍生物是模組化語言。然而，它不提供一個巢狀模組概念或合格的匯入和匯出指定符號。
Super Pascal是一個增加了非數字標籤，作為類型名稱的返回語句和表達式的變異。
Zurich、Karlsruhe和Wuppertal大學已開發了一個EXtension for Scientific Computing（Pascal XSC），為有控制精度的數字計算編程提供了一個自由的解決方案。

語言結構

最初形式的Pascal是一個純粹的程序化語言，包括有諸如if，then，else，while，for等等保留字的類Algol控制結構的傳統陣列。然而，Pascal也有許多最初Algol60不包括的資料結構工具和其它抽象概念，像類型定義、記錄、指標、列舉和集合。這些結構部分從Simula67、Algol68、尼克勞斯·維爾特自己的Algol-W和C. A. R. Hoare的建議繼承或獲得靈感。

Hello world

Pascal程式開始於外部檔案描述符作為參數的program關鍵字；然後跟著begin和end關鍵字封裝的主要塊。分號分割語句，句點終結整個程式（或單元）。Pascal原始碼不區分大小寫。
這裡是一個非常簡單的「Hello world」程式範例的原始碼：
（註：在實際編程中，通常可以省略第一行的output甚至program行）
Program HelloWorld(output);begin
  writeln('Hello, world!')
 {程序块的最后一条语句后不需要";" -    如果添加一个";"会在程序中增加一个“空语句”}end.

純量類型

Pascal的純量類型是real、integer、character、boolean和引進Pascal的新類型列舉：
var
  r: Real;
  i: Integer;
  c: Char;
  b: Boolean;
  e: (apple, pear, banana, orange, lemon);

子範圍類型

可以構造任意有序類型（除了real的簡單類型）的子範圍：
var
  x: 1..10;
  y: 'a'..'z';
  z: pear..orange;

集合類型

與該時代的其它程式語言相反，Pascal支援集合類型：
var
  set1: set of 1..10;
  set2: set of 'a'..'z';
  set3: set of pear..orange;
集合是現代數學的基礎概念，可能在很多演算法中使用。這樣一個特性是非常有用的，可能比不支援集合的語言的同等結構更快。例如，對於許多Pascal編譯器：
if i in [5..10] then...
比下面程式碼執行更快：
if (i>4) and (i<11) then...
從效能和可讀性來說，非連續值的集合可能特別有用：
if i in [0..3, 7, 9, 12..15] then...
對於像這些涉及小域上集合的例子，效能的提高通常是編譯器將集合變數看作位遮罩實現的。集合運算子然後可以作為按位元機器碼運算有效實現。
然而，對於值範圍顯著大於本地字長的例子，集合表達式比使用關係運算子的同等表達式可能導致更糟的效能和更多的記憶體使用。

類型聲明

使用類型聲明，可以從其它類型定義新類型：
type
  x = Integer;
  y = x;...
更進一步，複雜的類型可以從簡單的類型構建：
type
  a = Array [1..10] of Integer;
  b = record
        x: Integer;
        y: Char
      end;
  c = File of a;

File類型

正如上面的例子所示，Pascal的檔案是元件序列。每個檔案有一個用f^表示的緩衝變數。過程get（讀）和put（寫）移動到緩衝變數的下一個元素。引進了讀，使得read(f, x)與x:=f^; get(f);相同。引進了寫，使得write(f, x)與f^ := x; put(f);相同。列印的文字作為字元檔案預定義了。當緩衝變數能用於檢查下一個字元可用（讀一個整數前檢查一個數字）時，這個概念導致了早期實現的互動程式的嚴重問題，但是後來用「lazy I/O」概念解決了。
在Jensen & Wirth的Pascal裡，字串用封裝的字元陣列表示；因此有固定長度和通常是空間填充。有些方言有一個自訂字串類型。

指標類型

Pascal支援指標的使用：
type
  a = ^b;
  b = record
        a: Integer;
        b: Char;
        c: a
      end;var
  pointertob: a;
這裡變數pointertob是資料類型記錄b的一個指標。指標在聲明之前可用。這是前向聲明，一個使用之前必須聲明的規則的例外。建立一個新記錄，將值10和字元A分配給記錄的域a和b，將指標c初始化為nil，命令是這樣的：
new(pointertob);
pointertob^.a := 10;pointertob^.b := 'A';pointertob^.c := nil;...
也可以如下面這樣使用with語句來做：
new(pointertob);with pointertob^ dobegin
  a := 10;
  b := 'A';
  c := nilend;...
在with語句範圍內，a和b指記錄指標pointertob的子域，而不是記錄b或指標類型a。
通過在記錄里包含一個指標類型域（c，參見nil和null），可以建立連結串列、棧和佇列。
與許多以指標為特性的語言不同，Pascal只允許指標參照匿名的動態建立的變數，不允許參照標準的靜態或本地變數。另外，指標是類型繫結的，即字元指標與整數指標是類型不相容的。該淨效果是Pascal指標是「安全的」，遠離其它指標實現原生的類型安全問題。

控制結構

Pascal是結構化編程語言，意味著控制流被結構化成標準語句，理想地沒有「go to」命令。
while a <> b do writeln('Waiting');if a > b then writeln('Condition met')else writeln('Condition not met');for i := 1 to 10 do writeln('Iteration: ', i:1);repeat
  a := a + 1until a = 10;case i of
  0: write('zero');
  1: write('one');
  2: write('two')end;

過程和函式

Pascal將程式結構化成過程和函式。
program mine(output);var i : integer;procedure print(var j: integer);

  function next(k: integer): integer;
  begin
    next := k + 1
  end;begin
  writeln('The total is: ', j);
  j := next(j)end;begin
  i := 1;
  while i <= 10 do print(i)end.
過程和函式可以巢狀任意深度，「program」構造是邏輯上最外層的塊。
每個過程或函式可以有自己的正確順序的goto標籤、常數、類型、變數和其它過程和函式聲明。
此順序要求最初的本意是允許高效的單通編譯。然而，在一些方言裡聲明節嚴格的順序要求是不必要的。

分號作為語句分割符

Pascal從ALGOL語言裡吸納了許多語言語法特性，包括使用分號作為語句分割符。這與其它諸如PL/I、C等的語言是不同的。它們使用分號作為語句終止符。正如上述例子演示的，記錄類型聲明、塊或case語句的end關鍵字之前，repeat語句的until關鍵字之前，if語句的else關鍵字之前，不需要分號。
在Pascal的早期版本裡，不允許存在額外的分號。然而，1973年的修訂報告，後來成為ISO 7185:1983里的額外的類ALGOL空語句現在允許這些情況的絕大多數可選地使用分號。例外是仍然不允許分號立即出現在if語句的else關鍵字之前。
在一些情況下，真正需要空語句：
(* skip blanks *)while GetChar() = ' ' do ;
然而，濫用可能會產生問題。雖然下面語句是語法正確的，但是結果不大可能是想要的：
if alarm then;begin;
  SendMayday;
  EjectPilot;end;

標準

1983年，該語言標準化為國際標準IEC/ISO 7185，以及一些當地國家的具體標準，包括美國ANSI/IEEE770X3.97-1983和ISO 7185:1983。這2個標準的區別僅在於ISO標準包含一個conformant陣列的「級別1」擴充，而ANSI不允許對原始（維爾特版本）語言擴充。1989年，對ISO 7185進行了修正（ISO 7185:1990），糾正了原始文件中找到的各種錯誤和模糊。
1990年，一個擴充的Pascal標準作為ISO/IEC 10206建立。1993年，ANSI組織用ISO 7185:1990標準代替了ANSI標準，有效地終結了作為一個不同標準的狀態。
ISO 7185被說成是對《用戶手冊和報告（Jensen和維爾特）》詳述的維爾特的1974年語言的澄清，但是引人注意的是增加了作為標準級別1的「Conformant Array Parameters」，級別0是沒有Conformant Array的陣列。該增加是在C. A. R. Hoare的請求下，得到了維爾特贊同。該變動的原因是Hoare想建立數學演算法庫（NAG）的一個Pascal版本，該庫最初用FORTRAN編寫，發現如果沒有允許變長陣列參數的擴充就無法實現該庫。出於同樣的考慮，ISO 7185包含了指定過程和函式參數的參數類型的工具。
注意維爾特自己將1974年的語言當作「標準」，以將其與CDC 6000編譯器的機器特定特徵相區別。該語言記錄在「Pascal用戶手冊和報告」的第二部分報告」。
在Pascal起源的大型電腦（主機和微電腦）上，這些標準普遍遵循。在IBM-PC上，這些標準不被遵循。在IBM-PC上，Borland標準Turbo Pascal和Delphi有最大量的用戶。因此，了解一個特別的實現符合原始Pascal語言還是Borland方言非常重要。
該語言的IBM-PC版本開始區別於UCSD Pascal，以對該語言的幾個擴充以及幾個遺漏和變化為特性的解釋型實現。許多UCSD語言特性今天仍然存在，包含於Borland的方言。

Divisions

Pascal的維爾特的Zurich版本在ETH之外以2個基本形式發布，CDC 6000編譯器源和一個稱作Pascal-P系統的移植工具。Pascal-P編譯器遺漏了完全語言的幾個特性。例如，作為參數使用的過程和函式，無區別變體記錄，包裝，處理，過程間的goto方法和完全編譯器的其它特性被忽略。
Kenneth Bowles教授的UCSD Pascal是基於Pascal-P2套件的，因此有幾個共同的Pascal-P語言限制。UCSD Pascal後來作為Apple Pascal被接納了，並持續有幾個版本。雖然UCSD Pascal實際上擴充了Pascal-P2套件的Pascal子集，通過添加回標準Pascal結構，它仍然不是一個完整的Pascal標準安裝。
Borland的Turbo Pascal由Anders Hejlsberg用組合語言獨立於UCSD或Zurich編譯器編寫。然而，它與UCSD編譯器一樣接納了許多相同子集和擴充。這可能是因為UCSD系統是適於在當時可用的資源限制的微處理器上開發應用的最常見Pascal系統。

評論

Pascal在計算社群產生了廣泛的回應，包括批評和讚美。

批評

儘管非常流行（尤其在八十到九十年代），依據維爾特的對這種語言的定義來構建Pascal，使它不適合非教學的使用，這遭到了廣泛的批評。 推廣了C語言的布萊恩·柯林漢（Brian Kernighan）早在1981年就在他的論文Why Pascal Is Not My Favorite Programming Language對Pascal提出了嚴厲的抨擊。