Pascal 語言

Pascal 是一個指令式程式設計和麵向過程程式語言，由尼克勞斯・維爾特在 1968 年 9 月設計，在 1970 年發行，作為一個小型的和高效的語言，意圖鼓勵使用結構化程式設計和資料結構進行良好的程式設計實踐。

稱作 Object 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 的建議繼承或獲得靈感。

4.1 Hello world

Pascal 程式開始於外部檔案描述符作為引數的 program 關鍵字；然後跟著 begin 和 end 關鍵字封裝的主要塊。分號分割語句，句點終結整個程式（或單元）。Pascal 原始碼不區分大小寫。

這裡是一個非常簡單的 “Hello world” 程式示例的原始碼：

（注：在實際程式設計中，通常可以省略第一行的 output 甚至 program 行）

Program HelloWorld (output);

begin

writeln ('Hello, world!')

{程式塊的最後一條語句後不需要 ";" -

如果新增一個 ";" 會在程式中增加一個 “空語句”}

end.

4.2 資料型別

Pascal 和幾種其它流行程式語言的型別以定義變數能儲存的值的範圍的方式定義一個變數，也定義了一個允許在該類變數上執行的運算子集。預定義型別是：

每種型別（除了 boolean）允許的值的範圍是定義實現的。為一些資料轉換提供了函式。為了將 real 轉換成 integer，下面的捨入函式可用：使用四捨五入取整的 round 和 roundto（非標準）；分別向上和向下捨入的 ceil 和 floor；向零舍入的 trunc。注意在 str 和 floattostr 函式（非標準）中轉換成十進位制的輸出，和 write 命令不使用銀行家捨入。

程式設計師可以使用 Pascal 型別宣告工具以預定義型別，自由地定義其它常用資料型別（例如，byte，string 等等。)。

例如：

type

byte = 0..255;

signedbyte = -128..127;

string = packed array 1..255 of char;

（注：實際上，常用的資料型別如 byte，string 等在很多實現中已經定義過）

4.3 標量型別

Pascal 的標量型別是 real、integer、character、boolean 和引進 Pascal 的新型別列舉：

var

r: Real;

i: Integer;

c: Char;

b: Boolean;

e: (apple, pear, banana, orange, lemon);

4.4 子範圍型別

可以構造任意有序型別（除了 real 的簡單型別）的子範圍：

var

x: 1..10;

y: 'a'..'z';

z: pear..orange;

4.5 集合型別

不同於同時期的其它程式語言，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

同時，非連續值的集合可能有利於效能和可讀性：

if i in 0..3, 7, 9, 12..15 then

...

對於像這些涉及小域上集合的例子，效能的提高通常是編譯器將集合變數看作位掩碼實現的。集合運算子然後可以作為按位機器碼運算有效實現。

然而，對於值範圍顯著大於本地字長的例子，集合表示式比使用關係運算符的同等表示式可能導致更糟的效能和更多的記憶體使用。

4.6 型別宣告

使用型別宣告，可以從其它型別定義新型別：

type

x = Integer;

y = x;

...

更進一步，複雜的型別可以從簡單的型別構建：

type

a = Array 1..10 of Integer;

b = record

x: Integer;

y: Char

end;

c = File of a;

4.7 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 裡，字串用封裝的字元陣列表示；因此有固定長度和通常是空間填充。有些方言有一個自定義字串型別。

4.8 指標型別

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^ do

begin

a := 10;

b := 'A';

c := nil

end;

...

在 with 語句範圍內，a 和 b 指記錄指標 pointertob 的子域，而不是記錄 b 或指標型別 a。

透過在記錄裡包含一個指標型別域（c，參見 nil 和 null），可以建立連結串列、棧和佇列。

與許多以指標為特性的語言不同，Pascal 只允許指標引用匿名的動態建立的變數，不允許引用標準的靜態或本地變數。另外，指標是型別繫結的，即字元指標與整數指標是型別不相容的。該淨效果是 Pascal 指標是 “安全的”，遠離其它指標實現固有的型別安全問題。

4.9 控制結構

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 + 1

until a = 10;

case i of

0: write ('zero');

1: write ('one');

2: write ('two')

end;

4.10 過程和函式

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

過程和函式可以巢狀任意深度，“program” 構造是邏輯上最外層的塊。

每個過程或函式可以有自己的正確順序的 goto 標籤、常量、型別、變數和其它過程和函式宣告。

此順序要求最初的本意是允許高效的單通編譯。然而，在一些方言裡宣告節嚴格的順序要求是不必要的。

4.11 分號作為語句分割符

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 的方言。

6.1 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 系統。

6.2 相關標準清單

ISO 8651-2:1988 資訊處理系統 —— 計算機影像 —— 影像核心系統（GKS）語言邦定 —— 第二部分：Pascal

評論

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

7.1 批評

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