ALGOL 68 ( Algorithmic Language 1968の略)は、ALGOLファミリーに属する命令型プログラミング言語であり、 ALGOL 60言語の後継として構想され、より幅広い応用範囲と、より厳密に定義された構文および意味論を目指して設計されました。
数百ページにも及ぶ非標準的な用語で埋め尽くされた言語定義の複雑さゆえに、コンパイラの実装は困難を極め、「実装もユーザーもいない」と言われていた。しかし、これは部分的にしか真実ではなかった。ALGOL 68は、特に英国でInternational Computers Limited (ICL)のマシンで人気を博したほか、教育現場など、いくつかのニッチな市場で利用されていた。これらの分野以外では、利用は比較的限られていた。
それにもかかわらず、ALGOL 68がコンピュータ科学の分野にもたらした貢献は、深く、広範囲にわたり、永続的なものであった。ただし、これらの貢献の多くは、後に開発されたプログラミング言語に再び登場したときに初めて公に認識された。多くの言語は、ALGOL 68の複雑さに対する認識への対応として開発されたものであり、最も有名なのはPascalである。また、 Adaのように、特定の役割のために再実装されたものもあった。
1970年代の多くのプログラミング言語は、その設計をALGOL 68に明確に遡ることができ、複雑すぎる、あるいは特定の役割には不適切と判断された機能を一部採用し、その他は放棄した。現代のほとんどの言語は、構文の少なくとも一部をC言語またはPascalに由来しており、したがって直接的または間接的にALGOL 68に遡ることができる。
ALGOL 68の機能には、式ベースの構文、ユーザー宣言型および構造体/タグ付き共用体、変数と参照パラメータの参照モデル、文字列、配列、行列のスライス、および並行処理が含まれます。
ALGOL 68は、国際情報処理連盟(IFIP)のアルゴリズム言語および計算に関するワーキンググループ2.1によって設計されました。1968年12月20日、この言語は同グループによって正式に採用され、その後IFIP総会によって出版が承認されました。
ALGOL 68 は、Adriaan van Wijngaardenによって考案された、2 段階の形式文法である形式体系を用いて定義されました。Van Wijngaarden 文法は、文脈自由文法を用いて、特定の ALGOL 68 プログラムを認識する無限の生成規則を生成します。特に、他の多くのプログラミング言語の技術標準では意味論と呼ばれる種類の要件を表現でき、曖昧さを生じやすい自然言語の散文で表現し、形式言語の構文解析器に付随するアドホックコードとしてコンパイラに実装する必要があります。
ALGOL 68 の設計の主な目的と原則は次のとおりです。[ 7 ]
ALGOL 68 は、特に設計委員会のメンバーであるCAR HoareやEdsger Dijkstraから、 ALGOL 60のシンプルさを放棄し、複雑または過度に一般的なアイデアの手段となり、意図的にシンプルに設計された同時代 (および競合) の言語であるC、S-algol 、 Pascalとは対照的に、コンパイラ開発者の作業を容易にするのにほとんど役立たないとして批判されてきた。
1970年、ALGOL 68-RはALGOL 68向けの最初の動作するコンパイラとなった。
1973年の改訂では、手続き、ゴンマ[ 8 ]、形式境界などの特定の機能が省略された[ 9 ] 。改訂前の報告書の記述を参照。r0
欧州の防衛機関(英国では王立信号レーダー研究所(RSRE))は、ALGOL 68がもたらすと期待される安全保障上の利点からその使用を推進したが、NATO同盟の米国側は別のプロジェクトであるAda言語の開発を決定し、米国の防衛契約においてその使用を義務付けた。
ALGOL 68 はソ連にも顕著な影響を与えており、その詳細はアンドレイ・テレホフの 2014 年の論文「ALGOL 68 とそのソ連およびロシアのプログラミングへの影響」 [ 10 ]および「Алгол 68 и его влияние на программирование в」に記載されています。СССР и России」。[ 11 ]
ALGOL 68 改訂委員会のメンバーであったSteve Bourneは、そのアイデアの一部を自身のBourne シェル(そして、Bashなどの派生Unix シェル) やC (そして、C++などの派生言語) に取り入れた。Bourne シェルのソースコードは C で書かれているが、マクロを使用してALGOL に似せている。これは「Bournegol」というニックネームで呼ばれている。[ 12 ]
このプロジェクトの完全な歴史は、CH Lindseyの「ALGOL 68 の歴史」に記載されています。[ 13 ]
この言語の完全な解説については、Sian Mountbatten 博士による「Programming ALGOL 68 Made Easy」 [ 14 ] 、または改訂版レポートを含む Marcel van der Veer による「Learning ALGOL 68 Genie」 [ 15 ]を参照してください。
ALGOL 68 は、その名前が示すように、1960 年に初めて正式に定義されたALGOL言語の後継です。同年、国際情報処理連盟(IFIP) が結成され、ALGOL ワーキンググループ (WG2.1) が発足しました。このグループは、1962 年 4 月にローマで更新された ALGOL 60 仕様を発表しました。1964 年 3 月に行われたフォローアップ会議で、グループは 2 つの後継標準、つまり言語の再定義といくつかの追加、およびLISP言語のスタイルで独自のプログラムを変更できるALGOL Yの開発に着手することが合意されました。[ 16 ]
ALGOL X グループの最初の会合は、 1965 年 5 月にプリンストン大学で開催されました。会合の報告では、強力な型付けの導入と、コレクションを扱うためのオイラーの「ツリー」または「リスト」の概念への関心という、広く支持された 2 つのテーマが挙げられています。 [ 17 ]「既存の困難に対する短期的な解決策」として意図されていましたが、[ 18 ] ALGOL X はコンパイラが作成されるところまで進みました。このコンパイラは、マサチューセッツ工科大学(MIT)のDouglas T. Rossによって、ALGOL Extended for Design とも呼ばれるAutomated Engineering Design (AED-0) システムを使用して作成されました。[ 19 ] [ 20 ]
10月にフランスで開催された第2回会議では、3つの正式な提案が発表された。ニクラウス・ヴィルトのALGOL WとCAR(トニー)ホアによるレコード構造に関するコメント、ゲルハルト・ゼーグミュラーによる類似の言語、そしてアドリアーン・ファン・ワインガルデンによる「形式言語の直交設計と記述」に関する論文である。後者は、ほとんど解読不能な「W文法」で書かれており、言語の進化における決定的な転換点となった。会議は、ファン・ワインガルデンが自身のW文法を用いてヴィルト/ホアの提出物を書き直すという合意で終了した。[ 17 ]
この一見単純な作業は、最終的には予想以上に困難であることが判明し、フォローアップ会議は 6 か月延期せざるを得ませんでした。1966 年 4 月にKootwijkで開催された会議では、van Wijngaarden の草稿は未完成のままで、Wirth と Hoare はより伝統的な記述を使用したバージョンを発表しました。彼らの論文は「間違った形式体系における正しい言語」であるという点で概ね合意されました。[ 21 ]これらのアプローチが検討されるにつれて、パラメータの記述方法に現実世界に影響を与える違いがあることが明らかになり、Wirth と Hoare はこれ以上の遅延は際限がないかもしれないと抗議しましたが、委員会は van Wijngaarden のバージョンを待つことにしました。その後、Wirth は現在の定義を ALGOL W として実装しました。[ 22 ]
1966 年 10 月にワルシャワで開催された次の会議では、[ 23 ]オーク リッジ国立研究所とイリノイ大学で会合を開いた I/O 小委員会からの最初の報告がありましたが、まだあまり進展していませんでした。前回の会議の 2 つの提案が再び検討され、今回はポインタの使用に関する新たな議論が起こりました。ALGOL W ではレコードを参照するためだけにポインタを使用していましたが、van Wijngaarden のバージョンでは任意のオブジェクトを指すことができました。さらに混乱を招いたのは、John McCarthy が演算子オーバーロードとandとor構造を連結する機能に関する新しい提案を提示し、Klaus Samelson が匿名関数を許可したいと考えていたことです。結果として生じた混乱の中で、この取り組み全体を放棄するという議論もありました。[ 22 ]この混乱は、1967 年 5 月にザントフォールトで開催された ALGOL Y 会議まで続きました。[ 17 ]
草稿レポートは最終的に1968年2月に公開された。これは「衝撃、恐怖、そして反対」[ 17 ]で迎えられたが、その主な理由は、何百ページにも及ぶ読みにくい文法と奇妙な用語であった。チャールズ・H・リンジーは「その中に隠された言語」 [ 24 ]を解明しようと試みたが、その過程には6人週の労力を要した。その結果として作成された論文「涙の少ないALGOL 68」[ 25 ]は広く配布された。1968年5月にチューリッヒで開催されたより広範な情報処理会議で、参加者は、この言語が強制されていること、そして会議がほとんど非公開で正式なフィードバックメカニズムがないため、IFIPが「この不合理な状況の真の悪者」であると不満を述べた。ワースとピーター・ナウアーはその時にWG2.1の執筆者としての地位を正式に辞任した。[ 24 ]
次のWG2.1会議は1968年6月にティレニアで開催された。コンパイラのリリースやその他の問題について議論する予定だったが、代わりに言語についての議論に発展した。ファン・ワインガルデンは、報告書のもう1つのバージョンしかリリースしないと述べた(あるいは脅迫した)。この時点で、ナウル、ホア、ワースは取り組みから離脱しており、さらに数人が離脱すると脅迫していた。[ 26 ]その後、1968年8月にノース・バーウィック、12月にミュンヘンでさらに数回の会議が開かれ、1969年1月に公式報告書がリリースされたが、論争の的となる少数意見報告書も作成された。最後に、 1969年9月にアルバータ州バンフで、プロジェクトは概ね完了したとみなされ、議論は主に正誤表と大幅に拡張された報告書の序文に関するものであった。[ 27 ]
この取り組みには5年かかり、コンピュータサイエンス界の多くの著名人が疲弊し、定義とグループ全体の問題の両方で何度か行き詰まりました。ホアはほぼすぐに「ALGOL 68の批判」[ 28 ]を発表し、これは多くの著作で広く参照されています。ワースはALGOL Wの概念をさらに発展させ、1970年にこれをPascalとして発表しました。
1968 年後半の草案レポートに基づくこの標準の最初の実装は、 1970 年 7 月に英国の王立レーダー研究所によってALGOL 68-Rとして導入されました。しかし、これは完全な言語のサブセットであり、レポートの最終編集者であるバリー・マイユーは、「これは道徳の問題です。私たちは聖書を持っていますが、あなた方は罪を犯しています!」と冗談を言いました。[ 29 ]それでもこのバージョンはICLマシンで非常に人気があり、特に英国で軍事コーディングで広く使用される言語になりました。[ 6 ]
68-R の変更点の 1 つは、すべての変数を最初に使用する前に宣言する必要があるという要件でした。これにより、アクティベーション レコード内の変数の領域が使用される前に確保されるため、コンパイラが 1 パスで済むという大きな利点がありました。しかし、この変更には、 PROCを 2 回宣言する必要があるという副作用もありました。1回は型の宣言として、もう 1 回はコード本体として宣言する必要がありました。もう 1 つの変更点は、値を返す式 (他の言語ではステートメントと呼ばれる) であるVOIDモードを暗黙的に使用していたものを削除し、VOID が暗黙的に使用されていた箇所にVOID という単語を追加するように要求したことです。さらに、68-R ではPARに基づく明示的な並列処理コマンドを削除しました。[ 29 ]
この言語の最初の完全な実装は、1974年にCDCオランダによってコントロールデータメインフレームシリーズ向けに導入されました。これは、主にドイツとオランダでの教育など、限られた用途で使用されました。[ 6 ]
68-R に似たバージョンが1976 年にカーネギーメロン大学から68S として発表されました。これもまた、オリジナルのさまざまな簡略化に基づいたワンパスコンパイラで、DEC PDP-11のような小型マシンでの使用を目的としていました。これも主に教育目的で使用されました。[ 6 ]
IBMメインフレーム版は1978年まで利用できず、ケンブリッジ大学からリリースされたものが「ほぼ完成」していた。リンジーは1984年にIBM PCを含む小型マシン向けのバージョンをリリースした。[ 6 ]
3つのオープンソースのAlgol 68実装が知られています。[ 30 ]
「ヴァン・ワインガーデンはかつて、4人の著者をやや冗談っぽく、コスター:変換者、ペック:構文作成者、マイルー:実装者、ヴァン・ワインガーデン:党思想家として特徴付けた。」 – コスター。
1968年: 1968年12月20日、「最終報告書」(MR 101)が作業部会で採択され、その後ユネスコのIFIP総会で出版が承認された。この規格はロシア語、ドイツ語、フランス語、ブルガリア語に翻訳され、その後日本語と中国語にも翻訳された。[ 45 ]また、この規格は点字でも利用可能になった。
1984年:TC97はALGOL 68を「新規作業項目」TC97/N1642として標準化対象として検討した。西ドイツ、ベルギー、オランダ、ソ連、チェコスロバキアは規格策定への参加を希望したが、ソ連とチェコスロバキアは「適切なISO委員会の適切なメンバーではなかった」。そして、アルゴル68のISO標準化は停滞した。
1988年:その後、ALGOL 68はロシアのGOST規格の一つとなった。
標準語には約60の予約語が含まれており、通常は印刷物で太字で表記され、一部には「略記号」に相当するものもある。
モード、操作、優先度、プロシージャ、 フレックス、ヒープ、位置、ロング、参照、ショート、ビット、 ブール、バイト、文字、完全型、整数、実数、セマ、文字列、無効、 チャネル、ファイル、フォーマット、構造体、共用体、 アット"@", r0のいずれか、IS ":=:", ISNT IS NOT r0 ":/=:" ":≠:", OF "→" r0、TRUE、FALSE、EMPTY、NIL "○", SKIP "~", CO "¢", COMMENT "¢", PR、プラグマット、 CASE ~ IN ~ OUSE ~ IN ~ OUT ~ ESAC "( ~ | ~ |: ~ | ~ | ~ )", FOR ~ FROM ~ TO ~ BY ~ WHILE ~ DO ~ OD、 もし~ THEN ~ ELIF ~ THEN ~ ELSE ~ FI "( ~ | ~ |: ~ | ~ | ~ )", PAR BEGIN ~ END "( ~ )", GO TO、GOTO、EXIT "□" r0。
基本的な言語構造はユニットです。ユニットは、式、囲まれた節、ルーチンテキスト、またはいくつかの技術的に必要な構造 (代入、ジャンプ、スキップ、ニヒル) のいずれかになります。技術用語の囲まれた節は、他の現代的な言語でブロック、do ステートメント、switch ステートメントとして知られる、本質的に括弧で囲む構造の一部を統一します。キーワードが使用される場合、一般的に、囲みを終了するために、導入キーワードの逆順の文字シーケンスが使用されます (例: IF ~ THEN ~ ELSE ~ FI、CASE ~ IN ~ OUT ~ ESAC、FOR ~ WHILE ~ DO ~ OD )。このガード付きコマンド構文は、 Stephen Bourneによって一般的なUnixシェル Bourneで再利用されました。式は、付随節によって他の値から構築される複数の値を生成することもできます。この構造は、プロシージャ呼び出しのパラメータパックのように見えます。
基本的なデータ型(modeAlgol 68 の用語では s と呼ばれる)は、、、real(複素数)、、、、およびです。例:intcomplboolcharbitsbytes
INT n = 2; CO n は定数 2 に固定されます。CO INT m := 3; CO m は新しく作成されたローカル変数で、初期値は 3 に設定されます。CO COこれはref の略ですint m = loc int := 3; CO REAL avogadro = 6.0221415⏨23; COアボガドロ数CO long long real long long pi = 3.14159 26535 89793 23846 26433 83279 50288 41971 69399 37510; COMPLマイナス 1 の平方根 = 0 ⊥ 1;
しかし、この宣言REAL x;は単なる構文糖衣です。つまり、は実際には新しく生成されたローカルの実変数への参照の定数識別子です。REFREAL x = LOCREAL;x
さらに、 ALGOL 68 ではfloat、 とdouble、またはintとlongなどを定義する代わりに、修飾子 を提供しています。これにより、現在一般的なは、たとえばLONG REALまたはLONG LONG REALと記述されます。前置定数および は、プログラムをさまざまな実装に適応させるために提供されています。shortdoublemax realmin long int
すべての変数は宣言する必要がありますが、宣言は最初の使用に先行する必要はありません。
プリミティブ宣言子: INT、REAL、COMPL、COMPLEX G、BOOL、CHAR、STRING、BITS、BYTES、FORMAT、FILE、PIPE G、CHANNEL、SEMA
複雑な型は、さまざまな型コンストラクタを使用して、より単純な型から作成できます。
その他の宣言記号には、 FLEX、HEAP、LOC、REF、LONG、SHORT、EVENTSなどがあります。
モード(型)の名前は、 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 );
これは以下のC言語コードと似ています。
const int max = 99 ; typedef struct { double a , b , c ; short i , j , k ; float * r ; } newmode [ 9 + 1 ][ max + 1 ];ALGOL 68 では、等号の左側にNEWMODEモード表示のみが表示され、最も重要な点は、優先順位に関係なく左から右に構築され、読み取ることができることです。また、Algol 68 配列の下限はデフォルトでは 1 ですが、-max intからmax intまでの任意の整数にすることができます。
モード宣言では、型を再帰的に定義できます。つまり、型自体を直接的または間接的に定義できます。ただし、これにはいくつかの制限があります。たとえば、次の宣言は不正です。
モードA = REF AモードA = STRUCT ( A a, B b) モードA = PROC ( A a) A
これらは有効なものですが、
モードA = STRUCT ( REF A a, B b) モードA = PROC ( REF A a) REF A
強制は、強制される側の構文から強制される側の構文へと、以下の3つの基準に従って強制される側の構文を生成します。すなわち、強制が適用される前の強制される側の構文の事前モード、強制後に必要とされる強制される側の構文の事後モード、そして強制される側の構文上の位置または「種類」です。強制は連鎖的に適用される場合があります。
可能な6つの型変換は、 deproceduring、dereferencing、uniting、widening、rowing、voidingと呼ばれます。unitingを除く各型変換は、関連する値に対して対応する動的な効果を規定します。したがって、多くのプリミティブな動作は、型変換によって暗黙的にプログラムできます。
文脈の強さ – 許容される強制:
ALGOL 68には、プログラムの特定の時点で利用可能な型変換の種類を決定するコンテキストの階層構造があります。これらのコンテキストは次のとおりです。
プライマリ、セカンダリ、ターシャリ、クオタリの詳細については、オペレーターの優先順位を参照してください。
プラグマット(「実用的な発言」に由来)はプログラム内の指示であり、通常はコンパイラへのヒントです。新しい言語では、これらは「プラグマ」(tなし)と呼ばれます。例:
PRAGMAT heap=32 PRAGMAT PR heap=32 PR
コメントは様々な方法で挿入できます。
¢ プログラムに意見を述べるためのオリジナルの方法 ¢ コメント「太字」コメントコメントCOスタイル i コメントCO # スタイル ii コメント # £ これは英国キーボード用のハッシュ/ポンドのコメントです £
通常、ALGOL 68ではコメントをネストすることはできません。この制限は、異なるコメント区切り文字を使用することで回避できます(例えば、一時的なコード削除にのみハッシュを使用するなど)。
ALGOL 68は式指向プログラミング言語であるため、代入文によって返される値は、宛先への参照です。したがって、次のコードは有効なALGOL 68コードです。
実数1/2π、1π; 1π := 2 * ( 1/2π := 2 * arctan(1) )
この概念は、 C言語やPerl言語などに見られます。Algol 60やFORTRANなどの以前の言語と同様に、識別子にスペースが使用できるため、単一の識別子として扱われますhalf pi(アンダースコア、キャメルケース、小文字の区別といった問題は回避されます)。
別の例として、i=1からnまでの和という数学的な概念を表現するにはf(i)、次のALGOL 68整数式で十分です。
( INT sum := 0; FOR i TO n DO sum +:= f(i) OD ; sum)
なお、前述のコードブロックは整数式であるため、整数値が使用できるあらゆる状況で使用できます。コードブロックは、最後に評価した式の値を返します。この考え方は、 Lispをはじめとする多くの言語に見られます。
複合文はすべて、それぞれ異なる閉じ括弧で終わります。
IF条件THEN文 [ ELSE文 ] FI 簡略形式: (条件 | 文 | 文 )
IF condition1 THENステートメントELIF condition2 THENステートメント [ ELSEステートメント ] FI "簡略" 形式: ( condition1 | ステートメント |: condition2 | ステートメント | ステートメント )
この方式は、宙ぶらりんのelse文の問題を回避するだけでなく、埋め込みステートメントBEGINシーケンスでandを使用する必要も回避します。END
CASE switch INステートメント、ステートメント、... [ OUTステートメント ] ESAC 「簡略」形式: ( switch | ステートメント、ステートメント、... | ステートメント )
CASE switch1 INステートメント、ステートメント、... OUSE switch2 INステートメント、ステートメント、... [ OUTステートメント ] ESAC CASEステートメント の「簡略」形式: ( switch1 | ステートメント、ステートメント、... |: switch2 | ステートメント、ステートメント、... | ステートメント )
選択条項の例(ブリーフ記号付き):
PROC月の日数 = ( INT年、月) INT : (月| 31、 (年÷×4=0 ∧ 年÷×100≠0 ∨ 年÷×400=0 | 29 | 28 ) 31、30、31、30、31、31、30、31、30、31 );
太字記号を使用した選択条項の例:
PROC月の日数 = ( INT年、月) INT : CASE月IN 31、 もし年を4で割った余りが0で、かつ年を100で割った余りが0でない か、または 年を400で割った余りが0であれば29 、そうでなければ28 FI、 31、30、31、30、31、31、30、31、30、31 ESAC ;
太字記号と簡略記号を組み合わせた選択条項の例:
PROC月の日数 = ( INT年、月) INT : CASE月IN 1月31日 ¢Feb¢ ( 年MOD 4 = 0かつ年MOD 100 ≠ 0 または 年MOD 400 = 0 | 29 | 28 )、 3月31日、30日、31日、30日、31日、30日、31日、30日、31日~12月 ESAC ;
Algol68では、スイッチの型はINTまたは(唯一)UNIONのいずれかにすることが可能でした。後者は、UNION変数に厳密な型付けを強制することを可能にします。例えば、以下のunionを参照してください。
[ FORインデックス ] [ FROM first ] [ BY increment ] [ TO last ] [ WHILE条件 ] DOステートメントOD ループ句の最小形式は次のとおりです。DOステートメントOD
これは「普遍的な」ループと考えられており、完全な構文は次のとおりです。
iを1から-22から-333まで、 i × i ≠ 4444の間、次の処理を繰り返す~ OD
この構造にはいくつかの特異な点がある。
INT sum sq:=0; FOR i WHILE print(("これまでのところ:",i,newline)); 合計 sq≠70↑2 する 合計 sq+:=i↑2 ODその後、標準Algol68への「拡張」により、TO構文要素をUPTOとDOWNTOに置き換えることで、わずかな最適化が実現した。同じコンパイラには、以下の機能も組み込まれていた。
さらなる例は、以下のコード例をご覧ください。
[:]: 構造体、共用体、配列ALGOL 68は任意の次元数の配列をサポートしており、行または列全体、あるいは部分的なスライス処理が可能です。
MODE VECTOR = [1:3] REAL ; # ベクトルMODE宣言 (typedef) # MODE MATRIX = [1:3,1:3] REAL ; # 行列MODE宣言 (typedef) # 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 ⌊a TO ⌈a DO out[i] := a[i]+b[i] OD ; out); MATRIX m := (v1, v2, v1+v2); print ((m[,2:])); # 2列目と3列目のスライス #
行列はどちらの方向にもスライスできます。例:
REF VECTOR row = m[2,]; # 2行目へのREF (ポインタ)を定義 # REF VECTOR col = m[,2]; # 2列目へのREF (ポインタ)を定義 #
ALGOL 68は、複数のフィールド構造(STRUCT)と統合モードをサポートしています。参照変数は、配列スライスや構造体フィールドを含む任意のモードを指すことができます。
これらすべてを例示するために、従来のリンクリストの宣言を以下に示します。
MODE NODE = UNION ( VOID , REAL , INT , COMPL , STRING ); MODE LIST = STRUCT ( NODE val, REF LIST next);
UNION CASE of NODEの使用例:
プロシージャ(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);
の戻り値はproc、プロシージャ内で最後に評価された式の値です。プロシージャへの参照 ( 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では実現不可能だった。
プログラマは新しい演算子を定義することができ、それらの演算子と定義済みの演算子の両方をオーバーロードしたり、優先順位を変更したりできます。次の例では、2 進数と 1 進数の両方のバージョンを持つ演算子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 ; 外)
これらは厳密にはオペレーターではなく、「名前に関連付けられた単位」とみなされます。
具体的な詳細:
union([]int, [,]real, flex[,,,]char)これらは厳密にはオペレーターではなく、「名前に関連付けられた単位」とみなされます。
注: 四元数にはSKIPと ~ という名前が含まれます。
:=:(ISとも表記)2 つのポインタが等しいかどうかをテストします。(ISNTとも表記)それらが等しくないかどうかをテストします。:/=:
:=:か:/=:次のような、整数型へのポインタとして宣言された2つのポインタ値を比較することを考えてみましょう。
REFINT ip, jp 次に、これら2つが同じ場所を指しているかどうか、あるいはどちらか一方がNILを指しているかどうかをどのように判断するかを考えてみましょう。次の式
ip = jp 両方のポインタをINT型の値に逆参照し、それらを比較します。これは、=演算子がINT型に対して定義されていますが、REF INT型に対しては定義されていないためです。REF INT型とINT型のオペランドに対して同時に=を定義することは、暗黙の型変換が適用されるため、呼び出しがあいまいになるという問題が生じるため、合法ではありません。オペランドをREF INT型のままにして、そのバージョンの演算子を呼び出すべきでしょうか?それとも、さらにINT型に逆参照して、そのバージョンを使用すべきでしょうか?したがって、次の式は決して合法にすることはできません。
ip = NILしたがって、オペランドから演算子への通常の型変換規則の対象とならない、別の構造が必要となる。しかし、落とし穴がある。次の式:
ip :=: jp ip :=: NIL合法ではあるものの、おそらく期待通りの動作はしないでしょう。変数とが指すアドレスではなく、変数の実際のアドレスを比較しているため、常にFALSEが返されます。正しい効果を得るには、次のように記述する必要があります。ipjp
ip :=: REFINT(jp) ip :=: REFINT(NIL) 
Algol の特殊文字 (⊂、≡、␣、×、÷、≤、≥、≠、¬、⊃、≡、∨、∧、→、↓、↑、⌊、⌈、⎩、⎧、⊥、⏨、¢、○、□) のほとんどは、APLの「ゴルフボール」プリントヘッドが挿入されたIBM 2741キーボードで使用できます。これらの文字は、ALGOL 68 が草案作成されていた 1960 年代半ばに利用可能になりました。これらの文字はUnicode標準にも含まれており、そのほとんどはいくつかの一般的なフォントで使用できます。
トランスプットとは、ALGOL 68の入出力機能を指す用語です。これには、フォーマットなし、フォーマット済み、バイナリのトランスプットのための定義済み手順が含まれます。ファイルやその他のトランスプットデバイスは、一貫性があり、マシンに依存しない方法で処理されます。次の例は、フォーマットなしの出力を標準出力デバイスに出力するものです。
print ((newpage, "タイトル", newline, "i の値は ", i, "そして x[i] は ", x[i], 改行))
定義済みの手順newpageとnewline引数として渡される内容に注意してください。
転送は、書籍、チャネル、およびファイルに関するものとみなされます。
match。establish, create, open, associate, lock, close, scratch。char number, line number, page number:space、、、。backspacenewlinenewpageget good line, get good page, get good book、 そしてPROC set=(REFFILE f, INT page,line,char)VOID:on logical file end, on physical file end, on page end, on line end, on format end, on value error, on char error:ALGOL 68 のトランスプットにおける「フォーマット済みトランスプット」は、独自の構文とパターン (関数) を持ち、FORMATは 2 つの $ 文字の間に埋め込まれています。[ 48 ]
例:
printf (($2l"合計は:"x, g(0)$, m + n)); ¢ は以下と同じものを出力します: ¢ print ((new line, new line, "合計は:", space, whole (m + n, 0))
ALGOL 68 は並列処理のプログラミングをサポートしています。キーワードPARを使用すると、付随句が並列句に変換され、そこでアクションの同期はセマフォを使用して制御されます。A68G では、ホストオペレーティングシステムでスレッドが利用可能な場合、並列アクションはスレッドにマッピングされます。A68S では、異なる並列処理パラダイムが実装されました (下記参照)。
PROC eat = VOID : ( muffins-:=1; print(("おいしい!",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; 食べる; 口 を上げるOD、 単語が 0より大きい間は口を下げる。 話す; 上口ODエンド ALGOL 68は技術的に複雑なため、何かの存在を否定するためには、実に多様な方法が必要となる。
SKIP、"~" または "?" C – 構文的に常に有効な未定義値、 EMPTY – UNIONでVOID を選択するために必要なVOIDに許容される唯一の値、 VOID – 構文的にはMODEに似ているが、MODE ではない、 NILまたは "○" – 未指定の参照モードの何も示さない名前、 () または具体的には [1:0] INT –真空は空の配列です (ここでは具体的にはMODE [] INT )。 undefined – 標準レポート手順がランタイムシステムで例外を発生させます。ℵ – 特定のタイプの内省を 抑制するために標準レポートで使用される。例:SEMA
用語NIL IS var は、どの変数に対しても常にTRUEと評価されます (ただし、 IS :/=: の正しい使用法については上記を参照してください)。一方、比較x < SKIP が任意の整数xに対してどの値に評価されるかはわかりません。
ALGOL 68では、整数オーバーフローが発生した場合、整数のビット表現、および浮動小数点数の数値精度に関して、意図的に定義されていない。
どちらの公式報告書にも、標準言語には含まれていない高度な機能がいくつか含まれていました。これらはℵで示され、事実上非公開とみなされていました。例としては、テンプレート用の「≮」と「≯」、 簡易的なダックタイピングのためのOUTTYPE / INTYPE、ネストされた配列や構造体を「整列」するためのSTRAIGHTOUTおよびSTRAIGHTIN演算子などがあります。
このサンプルプログラムは、エラトステネスの篩を実装して、 100 未満のすべての素数を見つけます。NILは、他の言語のヌルポインタに相当する ALGOL 68 のものです。表記x OF yは、 STRUCT yのメンバxにアクセスします。
BEGIN # Algol-68 素数篩、関数型スタイル # PROC error = ( STRING s) VOID : (print(( newline, " error: ", s, newline)); GOTO stop); PROC one to = ( INT n) LIST : ( PROC f = ( INT m,n) LIST : (m>n | NIL | cons(m, f(m+1,n))); f(1,n)); MODE LIST = REF NODE ; MODE NODE = STRUCT ( INT h, LIST t); PROC cons = ( INT n, LIST l) LIST : HEAP NODE := (n,l); 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))); PROC filter = ( PROC ( INT ) BOOL p, LIST l) LIST : IF l IS NIL THEN NIL ELIF p(hd(l)) THEN cons(hd(l), 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) ~= 0; cons(hd(l), sieve( filter( not multiple, tl(l) ))) FI ; PROC primes = ( INT n) LIST : sieve( tl( one to(n) )); show( primes(100) ) 終わり
注: ソ連時代のコンピュータЭльбрус-1 (Elbrus-1)と Эльбрус-2 は、従来のアセンブリ言語ではなく、高級言語 Эль-76 (AL-76) を使用して作成されました。Эль-76 は Algol-68 に似ていますが、主な違いは Эль-76 ではハードウェア レベルで動的なバインディング タイプがサポートされていることです。Эль-76 は、アプリケーション、ジョブ制御、システム プログラミングに使用されます。[ 52 ]
ALGOL 68CとALGOL 68-RはどちらもALGOL 68で記述されているため、ALGOL 68自体がアプリケーションと言える。その他のアプリケーションには以下のようなものがある。
ALGOL 68の特徴の一つは、 ALGOLの伝統を受け継ぎ、様々な表現方法を採用している点です。厳密な言語(レポートで厳密に定義されています)で記述されたプログラムは、文法記号のシーケンスの形で生成木を表し、様々な目的に合わせて用意された多くの表現言語を用いて表現する必要があります。
改訂版報告書では参照言語が定義されており、人間が読むことを目的とした表現言語は、記号が「さらなる説明なしに」区別できるほど参照言語に十分近いものであることが推奨されている。これらの表現言語は、参照言語の実装と呼ばれる。
例えば、厳密な言語の太字開始記号は、出版言語ではbegin 、プログラミング言語ではBEGIN、ハードウェア言語ではバイト 0xC000 と表現できます。同様に、厳密な言語では、記号は≠ または /= と表現できます。
ALGOL 68 の予約語は、識別子とは実質的に異なる名前空間にあり、ほとんどのストロッピング レジームでは識別子にスペースが使用できるため、次の断片は有効です。
INT実数 int = 3 ;
実行可能コードを作成するプログラマーは、ハードウェアや文化的な問題によって、コード内で太字や下線を使用するオプションを常に利用できるとは限りません。これらの識別子を示すためのさまざまな方法が考案されています。これはストロッピング方式と呼ばれます。たとえば、以下のすべてまたは一部がプログラミング表現として利用可能です。
'INT'A REAL INT = 3; # 引用 ストロッピング スタイル # .INT A REAL INT = 3; # ポイント ストロッピング スタイル # INT a real int = 3; # 上部研磨スタイル # int a_real_int = 3; # RES ストロッピングスタイル、受け入れられる予約語は 61 個あります #
すべての実装は、PRAGMAT セクション内で少なくとも POINT、UPPER、RES を認識する必要があります。これらのうち、POINT と UPPER のストロッピングは非常に一般的です。QUOTE (シングル アポストロフィによる引用) が当初の推奨事項でした。
Algol 68には予約語がないため、RESストロッピングは仕様と矛盾しているように見えるかもしれません。しかし、そうではありません。RESストロッピングでは、太字の単語(またはキーワード)beginの表現はbegin_であり、識別子beginの表現はbegin_です。アンダースコア文字は単なる表現上のアーティファクトであり、表現される識別子の一部ではないことに注意してください。これに対し、C言語など予約語を持つ非ストロッピング言語では、表現if_は識別子if_を表し、 ifを表すわけではないため、識別子ifを表すことはできません。
以下の文字は移植性を考慮して推奨され、Algol 68 の標準ハードウェア表現に関する報告書 では「優れた文字」と呼ばれています。
これは1960年代に一部のハードウェアが小文字やその他の非ASCII文字をサポートしていなかったという問題を反映したものであり、実際、1973年の報告書には「“|”、“_”、“"[”、“]”という4つの重要な文字は、名目上同じ文字セットを使用しているシステムであっても、しばしば異なるコードで表記される」と記されている。
ALGOL 68では、あらゆる自然言語が独自のキーワードセットであるALGOL-68を定義できます。その結果、プログラマーは母国語のキーワードを使ってプログラムを作成できます。以下は、「翌日」を計算する簡単なプロシージャの例です。コードは英語とドイツ語の2つの言語で記述されています。
# 翌日の日付 - 英語形式 # MODE DATE = STRUCT ( INT day, STRING month, INT year); PROC the day following = ( DATE x) DATE : IF day OF x < length of month (month OF x, year OF x) THEN (day OF x + 1, month OF x, year OF x) ELIF month OF x = "December" THEN (1, "January", year OF x + 1) ELSE (1, successor of month (month OF x), year OF x) FI ;
# Nachfolgetag - Deutsche Variante # MENGE DATUM = TUPEL ( GANZタグ、WORT monat、GANZ jahr); FUNKTION naechster tag nach = ( DATUM x) DATUM : WENN tag VON x < monatslaenge(monat VON x, jahr VON x) DANN (tag VON x + 1, monat VON x, jahr VON x) WENNABER monat VON x = "Dezember" DANN (1, "Januar", jahr VON x + 1) ANSONSTEN (1, nachfolgemonat(monat VON x), jahr VON x) エンデウェン;
ロシア語/ソ連の例: 英語では Algol68 の case ステートメントはCASE ~ IN ~ OUT ~ ESACと読みますが、キリル文字ではвыб ~ в ~ либо ~ бывと読みます。
上付き文字で明記されている場合を除き、上記の説明文は「改訂版報告書(r1)」のものです。
元の言語(「最終報告書」r0によると)は、モードキャストの構文が異なり、プロシージャル化、つまり項の値をその項を評価するプロシージャに強制変換する機能を持っていました。プロシージャル化は、評価を遅延評価にすることを目的としていました。最も有用なアプリケーションは、ブール演算子の短絡評価だった可能性があります。
OP ANDF = ( BOOL a, PROC BOOL b) BOOL :(a | b | FALSE ); OP ORF = ( BOOL a, PROC BOOL b) BOOL :(a | TRUE | b);
bは、 aが真の場合にのみ評価される。
ALGOL 68で定義されているように、期待どおりに動作しませんでした。例えば、以下のコードでは次のようになります。
IF FALSE ANDF CO proc bool: CO ( print ("実行すべきではありません"); TRUE ) THEN ...プログラマーの素朴な予想に反して、 ANDFの後に続く詳細化された囲み句の値のみが処理されるため、print が実行されます。コメントアウトされたPROC BOOL : をテキストとして挿入すると、動作します。
一部の実装では、言語を拡張することで、この特殊なケースにおける期待される動作をエミュレートしています。
改訂前は、プログラマーはセミコロンをカンマ( gomma s)の代わりに使用することで、プロシージャの引数を付随的にではなく逐次的に評価するように決定することができました。
例えば、次のような場合:
PROC test = ( REAL a; REAL b) :... ... テスト(xプラス1、x)
テスト対象となる最初の引数は、2番目の引数よりも先に評価されることが保証されていますが、通常の方法では、次のようになります。
PROC test = ( REAL a, b) :... ... テスト(xプラス1、x)
そうすれば、コンパイラは引数を好きな順序で評価できる。
報告書の改訂後、適用範囲を広げるために、文言にいくつかの追加が提案された。
ENVIRONのandUSING句に似ています。[ 56 ]これまでのところ、部分的なパラメータ化はAlgol 68 Genieに実装されており、モジュールおよび分離コンパイル機能の一部はGCCに実装されている。
ICL VMEオペレーティングシステムやICL 2900シリーズの他の多くのシステムソフトウェアの記述に使用されたS3言語は、ALGOL 68の直接的な派生言語でした。しかし、より複雑な機能の多くは省略され、基本モードは2900シリーズのハードウェアアーキテクチャに直接対応する一連のデータ型に置き換えられました。
RRE社のALGOL 68Rは、 ICL 1900上で動作する、ALGOL 68サブセットの最初の実装でした。オリジナルの言語をベースに、サブセットの主な制約は使用前に定義が必要で、並列処理はできないという点でした。このコンパイラは1970年代の英国の大学で人気があり、多くのコンピュータサイエンス専攻の学生が最初のプログラミング言語としてALGOL 68を学びました。また、このコンパイラは優れたエラーメッセージで知られていました。
RSREのALGOL 68RS (RS)は、ALGOL 68RからブートストラップされたALGOL 68RSで記述された移植性の高いコンパイラシステムで、ICL 2900 / Series 39、Multics、DEC VAX/VMSなど、さまざまなシステムに実装されました。この言語は改訂版レポートに基づいていましたが、ALGOL 68Rと同様のサブセット制限がありました。このコンパイラは、Algol68からCへのコンパイラとして現存しています。
カーネギーメロン大学のALGOL 68S (S)では、イベント処理という直交拡張機能を追加することで並列処理能力が向上しました。キーワードEVENTを含む変数宣言は、その変数への代入を並列評価の対象としました。つまり、右辺はプロシージャに変換され、C.mmpマルチプロセッサシステムのプロセッサのいずれかに移動されました。このような変数へのアクセスは、代入処理の終了後に遅延されました。
Cambridge ALGOL 68C (C)は、ALGOL 68 のサブセットを実装した移植可能なコンパイラであり、演算子定義を制限し、ガベージコレクション、フレキシブル行、フォーマット済み転送を省略していました。
マルセル・ファン・デル・フェールによるAlgol 68 Genie (G)は、現代のコンピュータおよびオペレーティングシステム向けに実装されたALGOL 68です。このインタプリタは、1976年に発表されたチャールズ・リンゼイの部分パラメータ化提案という拡張機能を実装しており、命令型言語であるAlgol 68に関数型サブ言語を与えています。
GNUコンパイラコレクションのGNU Algol 68は、この言語に対するいくつかのGNU拡張機能を実装しており、[ 68 ] [ 69 ]改訂報告書で明示的に許可されているように、ALGOL 68の厳密なスーパー言語を提供している。[ 1 ] : 51
「善意であっても、プログラマーは意図せずローカル拡張を使用することで移植性を損なう可能性があります。これを防ぐために、各実装はPORTCHECKプラグマットオプションを提供する必要があります。このオプションが有効になっている間、コンパイラは移植性制約に違反していると認識した各構成要素に対してメッセージを出力します。」[ 70 ]
から私が捉えた中心的な概念は、配列、ポインタ (参照)、および関数 (手続き) に構成される原子型 (構造体を含む) に基づく型構造でした。Algol 68 の共用体とキャストの概念も、後になって現れる影響がありました。
特に、共用体型 (C に後から追加されたもの) は、詳細ではなく、そのような型を持つというアイデア自体において A68 に負っている。より深くは、型構造全般、そして奇妙なことに宣言構文 (型コンストラクタ部分) さえも、A68 に触発されている。そしてもちろん、「long」も。