Oberon-2は、オリジナルのOberonプログラミング言語の拡張版であり、限定的なリフレクション プログラミング(リフレクション) およびオブジェクト指向プログラミング機能、ポインタの基本型としてのオープン配列、読み取り専用フィールドのエクスポートを追加し、Modula-2FORのループを再導入しています。
Oberon-2は、1991年にチューリッヒ工科大学(ETH Zurich)でニクラウス・ヴィルトとハンスペーター・メッセンベックによって開発されました。メッセンベックは現在、オーストリアのリンツ大学システムソフトウェア研究所(SSW)に所属しています。Oberon-2はOberonの上位互換であり、Oberonと完全に互換性があり、 Object Oberonの再設計版です。
Oberon-2は、Oberonからインターフェースやミックスインを継承することなく、限定的なリフレクションと単一継承(「型拡張」)を継承しましたが、効率的な仮想メソッド(「型バインドプロシージャ」)を追加しました。メソッド呼び出しは、 C++スタイルの仮想メソッドテーブルを使用して実行時に解決されました。
Smalltalkのような完全なオブジェクト指向言語と比較すると、Oberon-2 では、基本データ型とクラスはオブジェクトではなく、多くの操作はメソッドではなく、メッセージパッシングはなく(ETH Oberon で実証されているように、リフレクションとメッセージ拡張によってある程度エミュレートできます)、ポリモーフィズムは共通クラスのサブクラスに限定されています ( Pythonのようなダックタイピングはなく、Javaのようなインターフェースを定義することもできません) 。Oberon-2はオブジェクトまたはクラスレベルでのカプセル化をサポートしていませんが、この目的のためにモジュールを使用できます。
Oberon-2 のリフレクションはメタオブジェクトを使用せず、実行可能バイナリにコンパイルされ、型やプロシージャを定義するモジュールで公開されている型記述子から読み取ります。これらの構造のフォーマットが言語レベルで公開されている場合 (たとえば ETH Oberon の場合)、リフレクションはライブラリレベルで実装できます。つまり、言語コードを変更することなく、ほぼ完全にライブラリレベルで実装できます。実際、ETH Oberon は言語レベルとライブラリレベルのリフレクション機能を幅広く活用しています。
Oberon-2は、Javaと同様のガベージコレクションをランタイム時に組み込みでサポートし、境界チェックや配列インデックスチェックなどを実行することで、 CやC++に内在するスタックや配列境界の上書き問題、手動メモリ管理の問題を解消します。モジュールアーキテクチャによるシンボルファイルと名前空間を用いた分離コンパイルにより、インターフェースが変更されたモジュールのみを再コンパイルすれば済むため、高速な再構築が可能です。
言語コンポーネントPascal [ 2 ]はOberon-2の改良版(上位互換)である。
以下のOberon-2コードは、単純な二分木を実装したものです。
モジュールツリー;TYPE Tree * = POINTER TO Node ; Node * = RECORD name - : POINTER TO ARRAY OF CHAR ; left , right : Tree END ;PROCEDURE ( t : Tree ) Insert * ( name : ARRAY OF CHAR ); VAR p , father : Tree ; BEGIN p := t ; REPEAT father := p ; IF name = p . name ^ THEN RETURN END ; IF name < p . name ^ THEN p := p . left ELSE p := p . right END UNTIL p = NIL ; NEW ( p ); p . left := NIL ; p . right := NIL ; NEW ( p . name , LEN ( name ) + 1 ); COPY ( name , p . name ^ ); IF name < father . name ^ THEN father . left := p ELSE father . right := p END END Insert ;PROCEDURE ( t : Tree ) Search * ( name : ARRAY OF CHAR ): Tree ; VAR p : Tree ; BEGIN p := t ; WHILE ( p # NIL ) & ( name # p . name ^ ) DO IF name < p . name ^ THEN p := p . left ELSE p := p . right END END ; RETURN p END Search ;PROCEDURE NewTree * (): Tree ; VAR t : Tree ; BEGIN NEW ( t ); NEW ( t . name , 1 ); t . name [ 0 ] := 0 X ; t . left := NIL ; t . right := NIL ; RETURN t END NewTree ;ENDツリー。出典:[ 3 ]
プロシージャはレコード型(またはポインタ型)にバインドできます。オブジェクト指向の用語でいうインスタンスメソッドに相当します。
エクスポートされた変数とレコードフィールドの使用は、読み取り専用アクセスに制限できます。これは、可視性フラグ「-」で示されます。
以前は仮引数型としてのみ宣言できたオープン配列を、ポインタ基底型として宣言できるようになりました。
FOROberonではPascalとModula-2の記述は実装されていませんでしたが、Oberon-2で再導入されました。
Oberon-2は、オブジェクトの動的な型をチェックするためのいくつかのメカニズムを提供します。例えば、BirdオブジェクトがDuckまたはCuckooのどちらかにインスタンス化される可能性がある場合、Oberon-2ではプログラマが実行時にオブジェクトの実際の型に応じて対応することができます。
最初の、最も一般的な方法は、型バインディングシステムを利用することです。2番目の方法は、変数の動的サブタイプを直接チェックできるWITHステートメントを使用することです。どちらの場合も、サブタイプが特定されれば、プログラマーはそのサブタイプに適した型バインドされたプロシージャや変数を使用できます。これらの方法の例を以下に示します。
Oberon-2で使用されるステートメントの形式は、WITHPascalおよびModula-2のWITHステートメントとは無関係であることに注意してください。レコードフィールドへのアクセスを省略するこの方法は、OberonおよびOberon-2には実装されていません。
MODULE Birds ; TYPE Bird * = RECORD sound * : ARRAY 10 OF CHAR ; END ; END Birds .モジュールアヒル;鳥類のインポート;TYPE Duck * = RECORD ( Birds . Bird ) END ;PROCEDURE SetSound * ( VAR bird : Duck ); BEGIN bird . sound : = "Quack!" END SetSound ; END Ducks .MODULE Cuckoos ; IMPORT Birds ;TYPE Cuckoo * = RECORD ( Birds . Bird ) END ;PROCEDURE SetSound * ( VAR bird : Cuckoo ); BEGIN bird . sound : = "カッコウ!" END SetSound ; END Cuckoos .WITH声明MODULE Test ; IMPORT Out , Birds , Cuckoos , Ducks ;TYPE SomeBird * = RECORD ( Birds . Bird ) END ;VAR sb : SomeBird ; c : Cuckoos . Cuckoo ; d : Ducks . Duck ;PROCEDURE SetSound * ( VAR bird : Birds . Bird ); BEGIN WITH bird : Cuckoos . Cuckoo DO bird . sound : = "カッコウ!" | bird : Ducks . Duck DO bird . sound : = "クワック!" ELSE bird . sound : = "チュンチュン!" END END SetSound ;PROCEDURE MakeSound * ( VAR b : Birds . Bird ); BEGIN Out . Ln ; Out . String ( b . sound ); Out . Ln END MakeSound ;BEGIN SetSound ( c ); SetSound ( d ); SetSound ( sb );MakeSound ( c ); MakeSound ( d ); MakeSound ( sb ) END Test .POINTERMODULE PointerBirds ; IMPORT Out ;TYPE BirdRec * = RECORD sound * : ARRAY 10 OF CHAR ; END ; DuckRec * = RECORD ( BirdRec ) END ; CuckooRec * = RECORD ( BirdRec ) END ;Bird = BirdRecへのポインタ; Cuckoo = CuckooRecへのポインタ; Duck = DuckRecへのポインタ;VAR pb :鳥; pc :カッコウ; pd :アヒル;PROCEDURE SetDuckSound * ( bird : Duck ); BEGIN bird . sound : = "Quack!" END SetDuckSound ;PROCEDURE SetCuckooSound * ( bird : Cuckoo ); BEGIN bird . sound : = "カッコウ!" END SetCuckooSound ;PROCEDURE SetSound * ( bird : Bird ); BEGIN WITH bird : Cuckoo DO SetCuckooSound ( bird ) | bird : Duck DO SetDuckSound ( bird ) ELSE bird . sound : = "Tweet!" END END SetSound ;BEGIN NEW ( pc ); NEW ( pd );SetCuckooSound ( pc ); SetDuckSound ( pd );Out.Ln ; Out.String ( pc ^ .sound ) ; Out.Ln ; Out.Ln ; Out.String ( pd ^ .sound ) ; Out.Ln ;SetSound ( pc ); SetSound ( pd );Out.Ln ; Out.String ( pc ^ .sound ) ; Out.Ln ; Out.Ln ; Out.String ( pd ^ .sound ) ; Out.Ln ;(* -------------------------------------- *) (* プロシージャに動的型を渡す *)pb : = pd ;SetDuckSound ( pb ( Duck ) ) ; Out.Ln ; Out.String ( pb ^ .sound ) ; Out.Ln ;pb : = pc ;SetCuckooSound ( pb ( "カッコウ" ) ) ; Out.Ln ; Out.String ( pb ^ .sound ) ; Out.Ln ;(* -------------------------------------- *)SetSound ( pb ) ; Out.Ln ; Out.String ( pb ^ .sound ) ; Out.Ln ;pb : = pd ;SetSound ( pb ) ; Out.Ln ; Out.String ( pb ^ .sound ) ; Out.Ln ;(* -------------------------------------- *)新規( pb )SetSound ( pb ); Out . Ln ; Out . String ( pb ^ . sound ); Out . Ln END PointerBirds .ISオペレーター3つ目のアプローチとして、IS演算子=を使用する方法があります。これは、等号 ( )、大なり ( ) などと同じ優先順位を持つ関係演算子です>が、動的型をテストします。ただし、他の2つのアプローチとは異なり、検出されたサブタイプにプログラマーがアクセスすることはできません。
ALGOL → Pascal → Modula-2 → Oberon → Component Pascal言語ファミリーの開発は、言語構文の複雑さの軽減によって特徴づけられます。Oberon-2 言語全体は、以下に示すように、拡張バッカス・ナウア記法の 33 個の文法規則のみを使用して記述されています ( Mössenböck & Wirth、1995 年 3 月) 。
Module = MODULE ident ";" [ ImportList ] DeclSeq [ BEGIN StatementSeq ] END ident "." . ImportList = IMPORT [ ident ":=" ] ident { "," [ ident ":=" ] ident } ";" . DeclSeq = { CONST { ConstDecl ";" } | TYPE { TypeDecl ";" } | VAR { VarDecl ";" }} { ProcDecl ";" | ForwardDecl ";" }. ConstDecl = IdentDef "=" ConstExpr . TypeDecl = IdentDef "=" Type . VarDecl = IdentList ":" Type . ProcDecl = PROCEDURE [ Receiver ] IdentDef [ FormalPars ] ";" DeclSeq [ BEGIN StatementSeq ] END ident . ForwardDecl = PROCEDURE "^" [ Receiver ] IdentDef [ FormalPars ]. FormalPars = "(" [ FPSection { ";" FPSection }] ")" [ ":" Qualident ]. FPSection = [ VAR ] ident { "," ident } ":" Type . Receiver = "(" [ VAR ] ident ":" ident ")" . Type = Qualident | ARRAY [ ConstExpr { "," ConstExpr }] OF Type | RECORD [ "(" Qualident ")" ] FieldList { ";" FieldList } END |POINTER TO Type | PROCEDURE [ FormalPars ]. FieldList = [ IdentList ":" Type ]. StatementSeq = Statement { ";" Statement }. Statement = [ Designator ":=" Expr | Designator [ "(" [ ExprList ] ")" ] | IF Expr THEN StatementSeq { ELSIF Expr THEN StatementSeq } [ ELSE StatementSeq ] END | CASE Expr OF Case { "|" Case } [ ELSE StatementSeq ] END | WHILE Expr DO StatementSeq END | REPEAT StatementSeq UNTIL Expr | FOR ident ":=" Expr TO Expr [ BY ConstExpr ] DO StatementSeq END | LOOP StatementSeq END | WITH Guard DO StatementSeq { "|" Guard DO StatementSeq } [ ELSE StatementSeq ] END | EXIT | RETURN [ Expr ] ]. Case = [ CaseLabels { "," CaseLabels } ":" StatementSeq ]. CaseLabels = ConstExpr [ ".." ConstExpr ]. Guard = Qualident ":" Qualident . ConstExpr = Expr . Expr = SimpleExpr [ Relation SimpleExpr ]. SimpleExpr = [ "+" | "-" ] Term { AddOp Term }. Term = Factor { MulOp Factor }.因子 =指定子[ "(" [ ExprList ] ")" ] |数値|文字|文字列| NIL |セット| "("Expr ")" | "~" Factor . Set = "{" [ Element { "," Element }] "}" . Element = Expr [ ".." Expr ]. Relation = "=" | "#" | "<" | "<=" | ">" | ">=" | IN | IS . AddOp = "+" | "-" | OR . MulOp = "*" | "/" | DIV | MOD | "&" . Designator = Qualident { "." ident | "[" ExprList "]" | "^" | "(" Qualident ")" }. ExprList = Expr { "," Expr }. IdentList = IdentDef { "," IdentDef }. Qualident = [ ident "." ] ident . IdentDef = ident [ "*" | "-" ].ETHが保守しているOberon-2コンパイラには、Windows、Linux、Solaris、macOS用のバージョンがあります。
Oxford Oberon-2 コンパイラはネイティブマシンコードにコンパイルし、Windows、Linux、macOS 上で JIT を使用できます。これはMike Spiveyによって作成および保守されており、Keiko 仮想マシンを使用しています。[ 4 ] [ 5 ]
英国マンチェスター大学のStephen J. Bevan氏が、MössenböckとWirthの文献にあるものを基に開発したOberon-2 LexスキャナおよびYaccパーサーが存在する。バージョンは1.4である。
Native Oberonというリリース版があり、これにはオペレーティングシステムが含まれており、PCクラスのハードウェア上で直接起動できます。
ETHZでは、Oberonの.NET実装に、いくつかのマイナーな.NET関連の拡張機能を追加したものが開発されました。
Programmer's Open Workbench (POW!) [ 6 ]は、エディタ、リンカ、Oberon-2 コンパイラを備えた非常にシンプルな統合開発環境です。これはWindows実行可能ファイルにコンパイルされます。ソースコードはすべて提供されており、コンパイラは Oberon-2 で記述されています。
Java to Oberon Compiler (JOB) は、ロシアのヴォログダ大学で開発されました。Javaクラスファイル(バイトコード)形式のオブジェクトコードを生成します。Java互換でありながら、Oberonに似たコンポーネント階層構造を採用した、JOB固有のクラスもいくつか提供されています。
最適化Oberon-2コンパイラは、GNUコンパイラコレクション(GCC)ツールチェーンを使用してプログラム生成を行い、C言語にコンパイルします。
Oberon Scriptは、Oberon言語全体をJavaScriptに変換するコンパイラです。このコンパイラはJavaScriptで記述されているため、Webページから呼び出してOberonで書かれたスクリプトを処理することができます。
XDS Modula2/Oberon2は、ロシアのノボシビルスクにあるExcelsior LLCが開発した開発システムです。Intel Pentium向けの最適化コンパイラ、またはクロスプラットフォームソフトウェア開発のための「C言語経由」トランスレータを搭載しています。WindowsとLinuxに対応しています。コンパイラはOberon-2で記述されており、自己コンパイルが可能です。
Oberon Revivalは、Oberon 2とComponent Pascal(BlackBox Component Builder )をLinuxとWin32に対応させるためのプロジェクトです。BlackBoxのLinux版はこれまで存在せず、元々はMicrosoft Windowsでのみ動作していました。
XOberonは、Oberon-2で記述されたPowerPC向けのリアルタイムオペレーティングシステムです。
ポータブル Oberon-2 コンパイラ (OP2) は、Oberon システムを市販のプラットフォームに移植するために開発されました。[ 7 ]
Oberon-2 は Keiko 仮想マシンをターゲットにすることができます。[ 8 ] [ 9 ] 例えば、他の言語コンパイラ ( O コード、p コードなどを参照) と同様に、Oxford Oberon-2 コンパイラはまず中間バイトコード (Keiko バイトコード) にコンパイルし、それをバイトコード インタプリタで解釈するか、ジャストインタイム コンパイルを使用します。
オックスフォード・オベロン2コンパイラは、ソースプログラムをスタックベースの抽象マシンのコードに変換します。…ケイコマシン。