ALGOL 68(源自英語:ALGOrithmic Language 1968的縮寫),一種指令式程式語言,為ALGOL家族的成員,是官方上的ALGOL 60後繼者。它設計的目標,是提供更廣泛的應用,以及更嚴格的語法定義。

Quick Facts 編程範型, 設計者 ...
ALGOL 68
編程範型多范型指令式過程式結構化並發
設計者阿德里安·范·韋恩加登, B.J. Mailloux英語Barry J. Mailloux, J.E.L. Peck英語John E. L. Peck, C.H.A. Koster英語Cornelis H.A. Koster等人
釋出時間最終報告: 1968年,​56年前​(1968
型態系統靜態強類型安全結構式英語Structural type system
網站Revised Report on the Algorithmic Language ALGOL 68
主要實作產品
ALGOL 68C英語ALGOL 68C, ALGOL 68 Genie(新近[1]), ALGOL 68-R英語ALGOL 68-R, ALGOL 68RS英語ALGOL 68RS, ALGOL 68S英語ALGOL 68S, FLACC英語FLACC, 列寧格勒ALGOL 68, Odra英語Odra (computer) ALGOL 68
衍生副語言
ALGOL 68r0 (最終報告:1968年),
ALGOL 68r1 (修訂報告:1973年)
啟發語言
ALGOL 60, ALGOL Y英語ALGOL Y
影響語言
C[2]C++[3]Bourne shellKornShellBashSteelman英語Steelman language requirementsAdaPython[4]Seed7英語Seed7Mary英語Mary (programming language)S3英語S3 (programming language)
Close

ALGOL 68的特徵包括基於表達式英語Expression-oriented programming language的語法,用戶聲明的類型結構/標記聯合,變量和引用參數的引用模型,字符串、數組和矩陣的分片英語array slicing,以及並發

概論

ALGOL 68由IFIP工作組2.1英語IFIP Working Group 2.1負責設計。1968年12月20日,IFIP工作組2.1通過了這個語法規範,並提交IFIP大會通過且出版。

ALGOL 68的定義使用了阿德里安·范·韋恩加登發明的一種數學形式主義的兩級形式文法Van Wijngaarden文法英語Van Wijngaarden grammar使用分別稱為「超規則」和「元產生式規則」的兩組上下文無關文法規則,生成形成一個可能無限的產生式集合,而這些常規的產生式將識別特定的ALGOL 68程序;值得注意的是,它們能夠表達在很多其他程式語言的技術標準中被標記為「語義」的那種要求,其他語言的語義必須用易致歧義的自然語言敘述來表達,並接着在編譯器中實現為附加到形式語言解析器的「特設」代碼。

ALGOL 68設計的主要目標和原則為:

  1. 描述的完備性和清晰性[5]
  2. 設計的正交性[6]
  3. 安全性[5]
  4. 高效性[5]

ALGOL 68曾受到批評,最突出的是來自其設計委員會的一些成員比如C. A. R. Hoare[7],還有ALGOL 60編譯器作者比如Edsger Dijkstra[8],它拋棄了ALGOL 60的簡單性,成為了複雜或過於籠統的想法的載體,不能使編譯器作者的任務變得更輕易些,與刻意保持簡單的同時代(競爭)者如CS-algol英語S-algolPascal形成了鮮明對比。

在1970年,ALGOL 68-R英語ALGOL 68-R成為了第一個投入工作的ALGOL 68編譯器。

在1973年9月確定的修訂版本中,省略了特定特徵比如過程化、gomma和形式邊界[5]

Stephen R. Bourne是ALGOL 68修訂委員會成員,他選取了它的一些想法到他的Bourne shell之中。

ALGOL 68的語言定義出版後的文本長達兩百多頁並充斥着非標準術語,這種複雜性使得編譯器實現變得困難,故而它曾被稱為「沒有實現也沒有用戶」。這麼說只是部份真實的,ALGOL 68曾應用於一些小眾市場,特別是流行於英國國際計算機有限公司英語International Computers Limited(ICL)的機器之上,還有在教學角色之上。在這些領域之外,其使用相對有限。

儘管如此,ALGOL 68對計算機科學領域的貢獻是深刻、廣泛而持久的,雖然這些貢獻大多只是在它們於後來開發的程式語言中重現之時才被公開認可。很多語言是為了應對這門語言的複雜性而專門開發的,其中最著名的是Niklaus WirthALGOL WPascal[9],或者是針對特定角色而重新實現的,比如有些人認為Ada可以看作ALGOL 68的後繼者[10]

1970年代的很多語言可以追溯其設計至ALGOL 68,選取一些特徵,並放棄被認為太複雜或超出給定角色範圍的其他特徵。其中就有C語言,它受到ALGOL 68的直接影響,特別是它的強類型和結構。多數現代語言都至少可以追溯其部份語法至要麼C語言要麼Pascal,因而很多語言可直接或間接的經由C語言而追溯至ALGOL 68。

規定和實現時間線

More information 名稱, 年 ...
名稱 國家 描述 目標CPU/平台 屬主/許可證 實現語言
廣義ALGOL 1962  荷蘭 廣義文法的ALGOL[11]
ALGOL 68DR 1968 Does not appear IFIP WG 2.1草案報告[12] Does not appear
ALGOL 68r0 1968 Does not appear IFIP WG 2.1最終報告[13] Does not appear
ALGOL 68-R英語ALGOL 68-R 1970  英國 GEORGE 3英語GEORGE (operating system)之下的ALGOL 68 ICL 1900英語ICT 1900 series 皇家雷達研究所英語Royal Radar Establishment ALGOL 60
DTSS ALGOL 68 1970  美國 Dartmouth分時系統英語Dartmouth Time Sharing System的ALGOL 68[14] GE-635英語GE-600 series 達特茅斯學院
Mini ALGOL 68 1973  荷蘭 針對簡單ALGOL 68程序的解釋器[15] 可移植解釋器 荷蘭數學中心 ALGOL 60
OREGANO 1973  美國 實踐「實現模型的重要性。」[16] 加州大學洛杉磯分校
ALGOL 68C英語ALGOL 68C 1975  英國 劍橋ALGOL 68 ICL英語International Computers LimitedIBM System/360PDP-10UnixTelefunken TR440/TR445,Tesla 200和Z80(1980年)[17] 劍橋大學 ALGOL 68C
ALGOL 68r1 1975 Does not appear IFIP WG 2.1修訂報告[18] Does not appear
ALGOL 68 H 1975  荷蘭 加拿大 ALGOL 68編譯器[19] 阿爾伯塔大學荷蘭數學中心 ALGOL W
CDC ALGOL 68 1975  美國 完全實現的ALGOL 68[20] CDC 6000系列英語CDC 6000 seriesCDC Cyber 控制數據公司
Odra英語Odra (computer) ALGOL 68 1976  蘇聯 波蘭 Odra 1204/IL ALGOL 60
俄克拉何馬ALGOL 68 1976  美國 俄克拉何馬州立大學實現[21] IBM 1130System/370 Model 158英語IBM System/370 俄克拉何馬州立大學 ANSI Fortran 66
柏林ALGOL 68 1977  德國 柏林ALGOL 68實現[22] 抽象ALGOL 68機器 – 機器無關編譯器 柏林工業大學 CDL 2英語Compiler Description Language
FLACC英語FLACC 1977  加拿大 具有調試特徵的修訂報告完整實現 System/370 租用,Chion公司 匯編
ALGOL 68RS英語ALGOL 68RS 1977  英國 可移植編譯器 ICL 2900系列英語ICL 2900 SeriesMulticsVMSC生成器(1993年) 皇家信號與雷達研究所英語Royal Signals and Radar Establishment ALGOL 68RS
ALGOL 68-RT英語ALGOL 68-RT 1979  英國 並行ALGOL 68-R
ALGOL 68+ 1980  荷蘭 提議的ALGOL 68的超語言[23]
M-220英語M-220 ALGOL 68  蘇聯 M-220 EPSILON英語EPSILON (programming language)
列寧格勒ALGOL 68 1980  蘇聯 完全語言 + 模塊 IBM,DEC,CAMCOH,PS 1001和PC
交互式ALGOL 68英語Interactive ALGOL 68 1983  英國 增量編譯 PC 非商業共享軟件
ALGOL 68S英語ALGOL 68S 1985  英國 美國 ALGOL 68的子集語言[24] Sun-3英語Sun-3,Sun SPARC(在SunOS 4.1和Solaris 2下),Atari ST(在GEMDOS下),Acorn Archimedes英語Acorn Archimedes(在RISC OS下),VAX-11英語VAX-11(在Ultrix-32英語Ultrix下) 利物浦大學卡內基·梅隆大學曼徹斯特大學 BLISS英語BLISS
MK2 交互式ALGOL 68英語Interactive ALGOL 68 1992  英國 增量編譯 PC 非商業共享軟件[25]
Algol68toC 1993  英國 基於源自1985年ELLA英語ELLA (programming language) ALGOL 68RS英語ALGOL 68RS的ctrans[26][27] 可移植C生成器 國防研究局英語Defence Research Agency皇冠版權開源軟件 ALGOL 68RS
ALGOL 68 Genie 2001  荷蘭 完全語言包括標準的並立子句 可移植解釋器 GNU GPL C
ALGOL 68 Genie版本2 2010  荷蘭 完全語言包括標準的並立子句 可移植解釋器;可選的選定單元的編譯 GNU GPL C
Close

樣例代碼

下面的樣例代碼實現了埃拉托斯特尼篩法來找到小於等於100的所有素數。ALGOL 68中NIL類似於其他語言中的空指針x OF y表示訪問STRUCT y的成員x

BEGIN # ALGOL68的素数筛法,基于链表实现 #
    MODE
        LIST = REF NODE,
        NODE = STRUCT (INT h, LIST t);
    OP  CONS = (INT n, LIST l) LIST: HEAP NODE := NODE (n, l);
    PRIO CONS = 9;
    PROC one to = (INT n) LIST:
        (PROC f = (INT m) LIST: (m > n | NIL | m CONS f(m + 1));
         f(1));
    PROC error = (STRING s) VOID:
        (print((newline, " error: ", s, newline)); stop);
    PROC hd = (LIST l) INT:
        (l IS NIL | error("hd NIL"); SKIP | h OF l);
    PROC tl = (LIST l) LIST:
        (l IS NIL | error("tl NIL"); SKIP | t OF l);
    PROC show = (LIST l) VOID:
        (l ISNT NIL | print((" ", whole(hd(l), 0))); show(tl(l)) 
         | print(newline));
    PROC filter = (PROC (INT) BOOL p, LIST l) LIST:
        IF l IS NIL THEN NIL
        ELIF p(hd(l)) THEN hd(l) CONS filter(p, tl(l))
        ELSE filter(p, tl(l))
        FI;
    PROC sieve = (LIST l) LIST:
        IF l IS NIL THEN NIL
        ELSE
            PROC not multiple = (INT n) BOOL: n MOD hd(l) NE 0;
            hd(l) CONS sieve(filter(not multiple, tl(l)))
        FI;
    PROC primes = (INT n) LIST: sieve(tl(one to(n)));
    show(primes(100))
END

將上述代碼保存入文本文件primes.a68中,然後使用ALGOL 68 Genie執行它:

$ a68g primes.a68
 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

顯著的語言元素

符號和保留字

標準語言包含六十一個保留字,典型的用粗體字打印,並且其中一些還具有「簡短」符號等價者:

MODEOPPRIOPROCFLEXHEAPLOCLONGREFSHORTBITSBOOLBYTESCHARCOMPLINTREALSEMASTRINGVOIDCHANNELFILEFORMATSTRUCTUNIONAT @,IS :=:, ISNT :/=:,OFr0TRUEFALSEEMPTYNIL ○,SKIP ~,
COMMENT  CO # ¢,PRAGMAT  PRCASE ~ IN ~ OUSE ~ IN ~ OUT ~ ESAC ( ~ | ~ |: ~ | ~ | ~ ),
FOR ~ FROM ~ TO ~ BY ~ WHILE ~ DO ~ ODIF ~ THEN ~ ELIF ~ THEN ~ ELSE ~ FI ( ~ | ~ |: ~ | ~ | ~ ),
PARBEGIN ~ END ( ~ ),GO TO  GOTOEXITr0

GO TO被當作兩個保留字,未修訂報告的語言還有保留字EITHERIS NOT結合。

符號表示

Thumb
1963年版的ASCII,在後來版本中,被替代為^被替代為_

「臻選字符」(worthy character)是1977年出版的ALGOL 68標準硬件表示報告出於可移植性而推薦的字符集中的字符[28]:

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9   " # $ % ' ( ) * + , - . / : ; < = > @ [ ] _ |

這反映了當年一些硬件不支持在ANSIASCIIIBMEBCDIC之外其他字符的事實。

傳輸表示採用「臻選字符」時,「加上乘以」符號替代為I,「乘以的冪」符號\替代為E

Thumb
配備APL打字球與鍵帽後的IBM 2741英語IBM 2741終端的鍵盤,它不再支持小寫字母。

ALGOL的「特殊」字符:

× ÷ ≤ ≥ ≠ ≡ ¬ ∧ ∨ ⊃ ↑ ⏨ ␣ ↓ → ⊥ ○ □ ⌊ ⌈ ⎩ ⎧ ¢

多數都可以在1965年出現的配備APL打字球與鍵帽後的IBM 2741英語IBM 2741終端的鍵盤上找到。這些字符也是Unicode標準的一部份,並且在一些流行的字體中可獲得到。

單元

基本語言構造是「單元」(unit)。單元可以是「公式」、「封閉子句」、「例程正文」和某個技術上需要的那些構造(賦值、跳轉、越過、空無)。技術術語「封閉子句」(enclosed clause)統一了某些固有的加括號的構造,在其他當代語言中被稱為「」、「do語句」、「switch語句英語Switch statement」。在使用關鍵字的時候,通常使用介入關鍵字的反轉字符序列來終結這個包圍,比如:IF ~ THEN ~ ELSE ~ FICASE ~ IN ~ OUT ~ ESACFOR ~ WHILE ~ DO ~ OD。這種守衛命令語法被Stephen Bourne重新使用在常用的Unix Bourne shell之中。一個表達式還可以產生「多個值」,它是通過「並立子句」(collateral clause)從其他一些值構造出來的。這種構造看起來就像過程調用的參數包(pack)。

模態

基本數據類型在ALGOL 68用語中叫做「模態」(mode),其原始聲明符為:INTREALCOMPL複數)、BOOLCHARBITSBYTES。ALGOL 68不再定義longshortdouble這樣的類型,而是提供了修飾符(modifier)LONGSHORT

  • BITSBOOL值的包裝向量(packed vector)。
  • BYTESCHAR值的包裝向量。
  • LONG – 聲明INTREALCOMPL的大小為LONG
  • SHORT – 聲明INTREALCOMPL的大小為SHORT

ALGOL 68提供了預置常量(prelude constant)如max reallong max real等來將程序適配到不同實現之中。

所有變量都必須被聲明,但是聲明不必須先於第一次使用。例如:

INT n = 2;  # n被固定为常量2 #
INT m := 3; # m是新建的局部变量,它的值被初始化为3 #
# 这是REF INT m = LOC INT := 3;的简写 #
REAL avogadro = 6.02214076E23; # 阿伏伽德罗常数 #
LONG LONG REAL long long pi = 3.14159 26535 89793 23846 26433 83279 50288 41971 69399 37510;
COMPL square root of minus one = 0 I 1; # 复数0 + 1i #

原始聲明符還包括:COMPLEXGSTRINGFORMATFILEPIPEGCHANNELSEMA

  • STRINGCHAR值的FLEX(靈活)數組。
  • SEMA – 可以通過OP LEVEL初始化的信號量

複雜類型可以使用類型構造子REFSTRUCTUNIONPROC來創建自更簡單的類型:

  • REF mode – 到類型mode的值的引用,類似於C/C++中和Pascal中的指針
  • STRUCT – 用來建造結構,類似於C/C++中的struct和Pascal中的recode
  • UNION – 用來建造聯合,類似於C/C++和Pascal中的union
  • PROC – 用來指定過程,類似於C/C++中的函數和Pascal中的過程/函數。

具體例子可參見ALGOL 68與C++的比較英語Comparison of ALGOL 68 and C++

其他聲明符號包括:FLEXHEAPLOCEVENTS

  • FLEX – 聲明這個數組是靈活的,就是說它的長度可以按需要增長。
  • HEAP – 為變量從全局堆中分配一些空閒空間。
  • LOC – 為變量分配這個局部棧的一些空閒空間。

聲明REAL x;只是REF REAL x = LOC REAL;語法糖。就是說,x實際上是「常量標識符」,它「引用到」一個新創建的局部REAL變量。

聲明模態(類型)的名字可以使用MODE聲明,它類似於C/C+中的typedef和Pascal中的type

 INT max = 99;
 MODE NEWMODE = [0:9][0:max]STRUCT (
     LONG REAL a, b, c, SHORT INT i, j, k, REF REAL r
 );

這類似於如下C99代碼:

 const int max=99;
 typedef struct {
     double a, b, c; short i, j, k; float *r;
 } newmode[9+1][max+1];

對於ALGOL 68,只有模態標示(indicant)NEWMODE出現在等號的左側,最值得注意的是,構造的製造和讀取,是從左至右而不顧及優先級的。還有ALGOL 68數組的下界(lower bound)缺省的是1,但也可以是從-max intmax int的任何整數。

模態聲明允許類型是遞歸的:直接或間接的依據自身來進行定義。這要服從一些限制,例如下列聲明是非法的:

 MODE A = REF A
 MODE A = STRUCT (A a, B b)
 MODE A = PROC (A a) A

而下列聲明是有效的:

 MODE A = STRUCT (REF A a, B b)
 MODE A = PROC (REF A a) REF A

註釋和編譯指導

註釋可以按各種方式插入:

¢ 最初方式是在程序中增加两个美分符号 ¢
COMMENT "粗体"注释 COMMENT
CO 风格i注释 CO
# 风格ii注释 #
£ 针对英国键盘的横杠/英镑注释 £

一般而言,註釋在ALGOL 68中不能嵌套。這個限制可以使用不同的註釋分界符來繞過,比如只對臨時代碼刪除使用井號。

語用指定(pragmat)是在程序中的編譯指導,典型的提示給編譯器;在新近的語言中叫做「pragma」。例如:

PRAGMAT heap=32 PRAGMAT
PR heap=32 PR

表達式和複合語句

ALGOL 68成為了面向表達式程式語言英語Expression-oriented programming language賦值語句所返回的值是到目的地的引用。因此下列代碼在ALGOL 68中是有效的:

 REAL half pi, one pi; one pi := 2*(half pi := 2*arc tan(1))

這種表示法也出現在C語言和Perl以及其他一些語言之中。注意在早期語言比如ALGOL 60FORTRAN中,在標識符中的空格是允許的,所以half pi是一個單一的標識符,因而無需採用蛇形命名法駝峰式大小寫

另一個例子,要表達數學中f(i)i=1n的總和,下列ALGOL 68整數表達式就可勝任:

 (INT sum := 0; FOR i TO n DO sum +:= f(i) OD; sum)

注意,作為整數表達式,上述的代碼塊可以用在「整數值可以使用的任何上下」之中。代碼塊在ALGOL 68稱為「系列子句」(serial clause),它返回其中被求值的最後一個表達式的值;這個概念也出現在LISP以及其他一些語言之上。系列子句加上封閉它的一對圓括號或BEGINEND叫做閉合子句(closed-clause)。

複合語句都終止於獨特的閉括號:

  • IF選擇子句:
 IF 条件 THEN 诸语句 [ ELSE 诸语句 ] FI
 “简短”形式:  ( 条件 | 诸语句 | 诸语句 )
 IF 条件1 THEN 诸语句 ELIF 条件2 THEN 诸语句 [ ELSE 诸语句 ] FI
 “简短”形式: ( 条件1 | 诸语句 |: 条件2 | 诸语句 | 诸语句 )

這種方案不僅避免了懸擺else英語dangling else問題,還避免了必須對嵌入的語句序列使用BEGINEND

  • CASE選擇子句:
 CASE 开关 IN 诸语句, 诸语句, ... [ OUT 诸语句 ] ESAC
 “简短”形式:  ( 开关 | 诸语句, 诸语句, ... | 诸语句 )
 CASE 开关1 IN 诸语句, 诸语句, ... OUSE 开关2 IN 诸语句, 诸语句, ... [ OUT 诸语句 ] ESAC
 “简短”形式: ( 开关1 | 诸语句, 诸语句, ... |: 开关2 | 诸语句, 诸语句, ... | 诸语句 )

採用"簡短"符號的選擇子句的例子:

PROC days in month = (INT year, month) INT:
    (month|
     31,
     (year%*4 = 0 AND year%*100 /= 0 OR year%*400 = 0 | 29 | 28),
     31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    );

採用「粗體」符號的選擇子句的例子:

PROC days in month = (INT year, month) INT:
    CASE month IN
        31,
        IF year MOD 4 EQ 0 AND year MOD 100 NE 0 OR year MOD 400 EQ 0 THEN 29 ELSE 28 FI,
        31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    ESAC;

混合了「粗體」和「簡短」符號的選擇子句的例子:

PROC days in month = (INT year, month) INT:
    CASE month IN
    #一月# 31,
    #二月# (year MOD 4 = 0 AND year MOD 100 /= 0 OR year MOD 400 = 0 | 29 | 28),
    #三月# 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 # 直到十二月 #
    ESAC;

Algol68允許開關具有類型要麼INT要麼(獨有的)UNION。後者允許在UNION變量上施加強類型,參見後面的聯合例子。

  • DO循環子句:
 [ FOR 索引 ] [ FROM 第一个 ] [ BY 增量 ] [ TO 最后一个 ] [ WHILE 条件  ] DO 诸语句 OD
 循环语句的极小化形式是DO 诸语句 OD

下面是這種「通用」循循的完整例子:

FOR i FROM 1 BY -22 TO -333 WHILE i*i /= 4444 DO ~ OD

這個構造有一些不尋常的方面:

  • 只有DO ~ OD部份是強制性的,在這種情況下循環將無限迭代。
  • 因此子句 TO 100 DO ~ OD,將只迭代100次。
  • WHILE「語法元素」允許編程者更早的從FOR循環中破出,例如:
INT sum sq := 0;
FOR i
WHILE
    print(("So far:", i, newline));
    sum sq /= 70**2
DO
    sum sq +:= i**2
OD

後續的對標準Algol68的擴展允許TO語法元素被替代為UPTODOWNTO來達成小優化。這些編譯器還結合了:

  • UNTIL(C) – 用於更晚的循環終止。
  • FOREACH(S) – 用於並行的運算於數組之上。

進一步的例子可以在下面的代碼例子中找到。

數組

ALGOL 68支持據於任意數目維度的數組,並且允許整體或部份橫行或縱列的分片英語array slicing

 MODE VECTOR = [1:3]    REAL;   # 向量MODE声明 #
 MODE MATRIX = [1:3,1:3]REAL;   # 矩阵MODE声明 #
 VECTOR v1  := (1,2,3);         # 数组变量初始化为 (1,2,3)  #
 []REAL v2   = (4,5,6);         # 常量数组,类型等价于VECTOR,边界是隐含的 #
 OP + = (VECTOR a, b) VECTOR:   # 二元OP即运算符定义 #
     (VECTOR out; FOR i FROM LWB a TO UPB a DO out[i] := a[i]+b[i] OD; out);
 MATRIX m := (v1, v2, v1+v2);
 print ((m[,2:]));              # 第二和第三纵列的切片 #

矩陣可以用任何一種方式定義,例如:

 REF VECTOR row = m[2,];  # 定义一个REF至第二横行 #
 REF VECTOR col = m[,2];  # 定义一个REF至第二纵列 #

結構與聯合

ALGOL 68支持多字段結構STRUCT標籤聯合UNION。引用變量可以指向任何MODE,包括數組切片和結構字段。

作為遞歸模態的例子,下面是傳統的鍊表的聲明:

 MODE
     NODE = UNION (VOID, REAL, INT, COMPL, STRING),
     LIST = STRUCT (NODE val, REF LIST next);

對上述NODEUNION使用CASE的例子:

More information ALGOL68r0遵循1968年最終報告, ALGOL68r1遵循1973年修訂報告 ...
ALGOL68r0遵循1968年最終報告 ALGOL68r1遵循1973年修訂報告
 NODE n := "1234";
 REAL r; INT i; COMPL c; STRING s
 CASE r,i,c,s CTAB n IN
     print(("real:", r)),
     print(("int:", i)),
     print(("compl:", c)),
     print(("string:", s))
 OUT print(("?:", n))
 ESAC
 NODE n := "1234";  # 或者 n := EMPTY; #
 CASE n IN
     (VOID):     print(("void:", "EMPTY")),
     (REAL r):   print(("real:", r)),
     (INT i):    print(("int:", i)),
     (COMPL c):  print(("compl:", c)),
     (STRING s): print(("string:", s))
     OUT         print(("?:", n))
 ESAC
Close

過程

過程(procedure)的PROC聲明對參數和結果二者要求類型指定,如果沒有則為VOID

 PROC max of real = (REAL a, b) REAL:
     IF a > b THEN a ELSE b FI;

或者使用條件語句的「簡短」形式:

 PROC max of real = (REAL a, b) REAL: (a > b | a | b);

過程的返回值是在過程中求值的最後一個的表達式的值 。到過程的引用REF PROC也是允許的。提供了傳引用調用參數來在形式參數列表中指定引用,比如REF REAL。下列例子定義一個過程,它將(作為參數而指定的)一個函數應用於一個數組的每個元素:

 PROC apply = (REF [] REAL a, PROC (REAL) REAL f):
     FOR i FROM LWB a TO UPB a DO a[i] := f(a[i]) OD

這種代碼的簡單性是在ALGOL 68的前身ALGOL 60中不能達成的。

運算符與關聯名字的單元

過程和運算符(operator)合稱例程(routine),編程者可以定義新的運算符,並且這些自定義的和預定義的運算符二者都可以重載,並且它們的優先級可以由編碼者變更。下列例子定義的運算符MAX具有二元和一元形式二者,一元形式在一個數組的元素之上進行掃描。

 PRIO MAX = 9;
  
 OP MAX = (INT a, b) INT: (a > b | a | b);
 OP MAX = (REAL a, b) REAL: (a > b | a | b);
 OP MAX = (COMPL a, b) COMPL: (ABS a > ABS b | a | b);
  
 OP MAX = ([]REAL a) REAL:
     (REAL out := a[LWB a];
      FOR i FROM LWB a + 1 TO UPB a DO (a[i] > out | out := a[i]) OD;
      out)

初等和二等單元

初等單元(primary)涵蓋封閉子句,此類屬自身包括:所應用的標識符、調用、鑄型、除了例程指示之外的指示和分片。

指示(denotation)比如3.14"abc",是其所產生與任何行動都無關的構造,在其他語言中,它們有時叫做「文字英語Literal (computer programming)」(literal)或「常值」(constant)。

鑄型(cast)構成自一個模態標示(indicant)和隨後的通常為閉合子句的封閉子句。鑄型可被用來提供強位置,在強上下文中能獲得所有的強制。例如在REF REAL (xx) := 1中的REF REAL (xx)

調用(call)引起(invoke)一個過程,調用在ALGOL 68 Genie中可以被部份參數化英語Partial application(partial parameterisation):就是說增加實際參數到一個過程的語境(locale)中,當這個語境完全之時調用這個過程,否則發生柯里化

More information PRIO, ALGOL68r1「臻選字符」 ...
PRIO ALGOL68r1「臻選字符」 ALGOL68G
相當於12 加下標[~],分片[~:~]AT @ DIAGTRNSPROWCOL
Close

二等單元(secondary)包括生成器(generator)和選取(selection)。

More information PRIO, ALGOL68r1「臻選字符」 ...
PRIO ALGOL68r1「臻選字符」 ALGOL68r0−r1 ALGOL68G
相當於11 OFLOCHEAP NEW
Close

有關的符號在技術上不是運算符,它們轉而被當作「關聯名字的單元」[29]

三等單元

三等單元(tertiary)包括公式和NIL(可替代為)。公式構成自運算符運算元

一元運算符
More information PRIO, ALGOL68r1「臻選字符」 ...
PRIO ALGOL68r1「臻選字符」 ALGOL68r1替代符號 ALGOL68C,G ALGOL68r0-r1
相當於10 NOT,-,UPDOWNLWBUPBABSARGBINENTIERLENGLEVELODDREPRROUNDSHORTEN ¬ ~,↑,↓,⌊,⌈ NORMTRACETDETINV LWS ⎩,UPS ⎧,BTBCTB
Close
二元運算符及其關聯的優先級
More information PRIO, ALGOL68r1「臻選字符」 ...
PRIO ALGOL68r1「臻選字符」 ALGOL68r1替代符號 ALGOL68r0−r1
9 I +* ⊥ +× !
8 UP **,DOWNLWBUPBSHLSHR ↑,↓,⌊,⌈ ^ ××,LWS ⎩,UPS
7 *,/,OVER %,MOD %*,ELEM ×,÷,÷× ÷* %×,□ ÷:
6 -,+
5 LT <,LE <=,GE >=,GT > ≤,≥
4 EQ =,NE /= ≠ ¬= ~=
3 AND ∧ & /\
2 OR \/
1 MINUSAB -:=,PLUSAB +:=,TIMESAB *:=,DIVAB /:=,OVERAB %:=,MODAB %*:=,PLUSTO +=: ×:=,÷:=,÷×:=,÷*:=,%×:= MINUSPLUSTIMESDIVOVERBMODB ÷::=,PRUS
Close

特殊細節:

  • LWS:在ALGOL 68r0中,運算符LWS(可替代為),在一個數組的這個維度的「下界狀態」為固定的(fixed)的情況下返回TRUE
  • UPS(可替代為)運算符針對「上界狀態」。
  • LWBUPB運算符自動的可獲得在一個數組的不同階次(和MODE)的UNION之上,例如:UNION([]INT, [,]REAL, FLEX[,,,]CHAR)UPB

四等單元

四等單元(quaternary)包括:賦值、恆等(identity)關係、例程指示(也稱作例程正文)和SKIP(可替代為~)。四等單元並非語言報告中的術語,它是給從單元這個類屬中除去封閉子句、初等單元、二等單元和三等單元所餘下的只稱為「單元」的類屬的別名。

More information PRIO, ALGOL68r1「臻選字符」 ...
PRIO ALGOL68r1「臻選字符」 ALGOL68r1替代符號 ALGOL68C,R ALGOL68r0−r1
相當於0 :=,IS :=:,ISNT :/=: :≠: :¬=: :~=: :=:=C,=:=R ..= .=,IS NOTCT ::,CTAB ::=
Close

恆等關係包括:IS(可替代為:=:)測試兩個引用是否相等;ISNT(可替代為:/=:)測試兩個引用是否不相等。恆等關係的一側是可以解引用來匹配另一側的強側,而另一側則為軟側,不允許兩側都解引用。

強制

強制(coercion)依據三個要件,從被強制者(coercend)產生已強制者(coercee):在應用任何強制之前作為被強制者的一個先驗模態,在這些強制之後作為已經強制者的一個後驗模態,已強制者的的語法位置(position)或類屬(sort)。強制是可以級聯的(cascaded)。

有六種可能的強制,其術語為解過程化(deproceduring),解引用(dereferencing),聯合化(uniting),擴大(widening)、成行(rowing)和棄置(voiding)。除了聯合化之外,每種強制都在所關聯的值之上,規制(prescribe)一個相應的動態效果。因此,可以使用強制來編程很多原始行動。

上下文強度 – 允許的強制:

  • 軟(soft)– 解過程化。
  • 弱(weak) – 解引用或解過程化,產生一個名字。
  • 柔(meek)– 解引用或解過程化。
  • 硬(firm)– 柔強制,隨後聯合化。
  • 強(strong)– 硬強制,隨後擴大、成行或棄置。

強制層級及例子

ALGOL 68有着上下文層級,它確定在程序中特定點之上可獲得的強制的種類。這種上下文分為五個層次:

More information 上下文, 上下文位置 ...
上下文 上下文位置 可獲得的強制 在此上下文中強制例子
如下情況中的右手側:
  • 恆等(identity)聲明,如~之於REAL …… = ~
  • 初始化的名字聲明,如~之於REAL …… := ~
  • 賦值,如~之於 …… := ~

還有:

  • 調用的實際參數,如~之於 ……(~)
  • 鑄型(cast)的閉合子句,如~之於REAL(~)
  • 例程指示的單元
  • 產生VOID的單元
  • 平衡(balanced)子句的除第一部份之外的所有部份
  • 恆等關係的一側,它可能需要解引用來適配於另一側,
    xx之於xx := x; xx IS x
解過程化 都軟強制再解引用或解過程化產生一個名字 都弱強制再解引用或解過程化 都柔強制再聯合化 都硬強制再擴大或成行或棄置

擴大出現在沒有精度損失的情況下。例如:

  • LONG INTINT
  • REALINT
  • LONG REALREAL
  • COMPLREAL
  • 得 []BOOLBITS
  • STRINGBYTES

變量可以成行為長度為1的數組。例如:

  • 得 [1]INTINT
  • 得 [1]REALREAL
  • 公式的運算元,如~之於~ + ~
  • 傳輸調用的實際參數
例子:

UNION(INT, REAL) var := 1

  • 剪標(trimscript):修剪器(trimmer)中的下標和邊界產生INT
  • 質詢(enquiry)子句,如~之於
    IF ~ THEN …… FIFROM ~ BY ~ TO ~ WHILE ~ DO …… OD
  • 調用的初等單元,如~之於~(……)
例子:
  • BOOLREF REF BOOL
  • INTREF REF REF INT
  • 分片的初等單元,如~之於~[……]
  • 選取的二等單元,如~之於…… OF ~
例子:
  • REF INTREF REF INT
  • REF REALREF REF REF REAL
  • REF STRUCTREF REF REF REF STRUCT
  • 賦值的左手側,如~之於~ := ……
  • 恆等關係的另一側,它被其中一側可能需要解引用來匹配,
    x之於xx := x; xx IS x
例子:
  • PROC REAL random的解過程化:random
Close

傳輸

傳輸(transput)是ALGOL 68用來稱謂輸入和輸出設施的術語。它包括針對非格式化、格式化和二進制傳輸的預定義的過程。文件和其他傳輸設備以機器無關的方式來處理。下面的例子打印出一些非格式化的輸出到「標準輸出」設備:

 print ((newpage, "Title", newline, "Value of i is ",
     i, "and x[i] is ", x[i], newline))

注意預定義的過程newpagenewline作為實際參數而傳送。

在ALGOL 68中「格式化傳輸」擁有自己的語法和模式(函數),具有嵌入在兩個$字符之間的FORMAT。例如:

 printf (($2l"The sum is:"x, g(0)$, m + n)); # 其打印相同于下列: #
 print ((new line, new line, "The sum is:", space, whole(m + n, 0))

並行處理

ALGOL 68支持並行處理編程。使用關鍵字PAR,可以將「並立子句」轉換成「並行子句」,這裏的行動的同步使用信號量來控制。並行行動在ALOGL 68 Genie中被映射到線程上,如果它們在宿主作業系統上能獲得到的話。例如:

PROC
    eat = VOID: (muffins -:= 1; print(("Yum!", new line))),
    speak = VOID: (words -:= 1; print(("Yak...", new line)));
 
INT muffins := 4, words := 8;
SEMA mouth = LEVEL 1;
 
PAR BEGIN
    WHILE muffins > 0 DO
        DOWN mouth;
        eat;
        UP mouth
    OD,
    WHILE words > 0 DO
        DOWN mouth;
        speak;
        UP mouth
    OD
END

未修訂報告的語言

原本依據1968年最終報告的語言在「模態鑄型」 的語法上有所不同,並且它擁有過程化(proceduring)這個特徵,就是說,將一個項目的值強制成求值這個項目的一個過程。過程化意圖進行惰性求值。最有用的應用是布爾運算符的短路求值:

OP ANDF = (BOOL a, PROC BOOL b) BOOL: (a | b | FALSE);
OP ORF = (BOOL a, PROC BOOL b) BOOL: (a | TRUE | b);

ANDF中,b只在aTRUE的情況下才求值。例如:

IF FALSE ANDF (print("Should not be executed"); TRUE) THEN ……

語言修訂之後與編程者的預期相反,打印仍會執行,需要如下這樣使打印不執行:

IF FALSE ANDF PROC BOOL: (print("Should not be executed"); TRUE) THEN ……

在語言修訂之前,編程者可以通過使用叫做「gomma」的分號替代逗號(comma),從而決定一個過程的參數串行而非並立的求值。例如:

PROC test = (REAL a; REAL b): ……
test (x +:= 1, x);

這裏保證第一個實際參數求值在第二個實際參數之前,但是在平常情況:

PROC test = (REAL a, b): ……
test (x +:= 1, x);

這時編譯器可以按它喜好的次序來求值實際參數。

參見

註釋

外部連結

Wikiwand in your browser!

Seamless Wikipedia browsing. On steroids.

Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.

Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.