Oberon-2

Oberon-2 とは、プログラミング言語 Oberon を拡張し、オブジェクト指向的なコンセプトを取り入れた言語である。
1991年、チューリッヒ工科大学のニクラウス・ヴィルトと （現システムソフトウェア研究所）が開発した。Oberon-2 は Oberon の上位互換である。Oberon-2 は Object Oberon（Oberon にオブジェクト指向のコンセプトを導入した最初の試み）の再設計でもあった。
Oberon-2 は Oberon から限定されたリフレクションとインタフェースなどを持たない単一継承（型拡張）を受け継いでいるが、効果的な仮想メソッド（型束縛プロシージャ）を追加している。メソッド呼び出しは、C++のような仮想メソッドテーブルを使って実行時に確定する。
Smalltalk などの完全なオブジェクト指向言語に比べると、Oberon-2 の基本データ型はオブジェクトになっておらず、クラスもオブジェクトではなく、多くの操作がメソッドではないし、メッセージパッシングの概念もなく、ポリモーフィズムも限定的である（SmalltalkやRubyのようなダックタイピングがなく、Javaのようなインタフェースも定義できない）。オブジェクト/クラスレベルでのカプセル化もサポートしていないが、モジュールをその目的で使用することができる。
Oberon-2 のリフレクションはを使わず、実行ファイル内に含まれる型記述子を単に読み、それが型やプロシージャを定義しているモジュールに渡される。その構造体の形式が言語レベルで渡されるなら（例えば Oberon System 3 がそうである）、ライブラリレベルでのリフレクションの実装が可能である。従って、言語コードを全く変えずにライブラリレベルでほとんど全てを実行することも可能である。実際、Oberon System 3 は言語レベルとライブラリレベルのリフレクションを多用している。
コード例.
以下の Oberon-2 のコードは、単純なリストクラスを実装したものである。
MODULE ListClass;
 TYPE List* = POINTER TO ListNode;
 ListNode = RECORD
 value : INTEGER;
 next : List;
 END;
 PROCEDURE ( l : List ) Add* ( v : INTEGER );
 BEGIN
 END Add;
 PROCEDURE ( l : List ) AddLast*( v : INTEGER );
 BEGIN
 END AddLast;
 PROCEDURE ( l : List ) AddAt* ( i : INTEGER; v : INTEGER );
 BEGIN
 END AddAt;
 PROCEDURE ( l : List ) Remove*;
 BEGIN
 END Remove;
 PROCEDURE ( l : List ) RemoveLast*;
 BEGIN
 END RemoveLast;
 PROCEDURE ( l : List ) RemoveAt* ( i : INTEGER );
 BEGIN
 END RemoveAt;
END ListClass.
Oberon からの拡張.
実行時型チェック.
Oberon-2 はオブジェクトの型について、動的なチェックを行う機構がいくつか用意されている。例えば、Bird オブジェクトのインスタンスとして Duck や Cuckoo があったとき、Oberon-2 では実行時にオブジェクトの実際の型に応じた処理が可能である。
従来的な方法としては、「型束縛システム」を使った方法がある。第二の方法として、codice_1 文を使った方法がある。これは、変数の動的な派生型を直接チェックするものである。どちらの場合も、派生型を特定したら、プログラマはその派生型に適切な型束縛プロシージャや型束縛変数を使うことができる。以下に具体例を示す。
なお、Oberon-2 の codice_1 文と Pascal や Modula-2 の WITH 文は無関係である。以下のメソッドではレコードのフィールドへのアクセスを略記しているが、Oberon や Oberon-2 では実際にはこのような記法は使わない。
型束縛
MODULE Birds;
 TYPE Bird* = RECORD
 sound* : ARRAY 10 OF CHAR;
 END;
END Birds.
MODULE Ducks;
 IMPORT Birds;
 TYPE Duck* = RECORD(Birds.Bird) END;
 PROCEDURE makeSound*( VAR bird: Duck );
 BEGIN COPY("Quack!", bird.sound); END makeSound;
END Ducks.
MODULE Cuckoos;
 IMPORT Birds;
 TYPE Cuckoo* = RECORD(Birds.Bird) END;
 PROCEDURE makeSound*( VAR bird: Cuckoo );
 BEGIN COPY("Cuckoo!", bird.sound); END makeSound;
END Cuckoos.
codice_1 文
MODULE Test;
 IMPORT Out, Birds, Cuckooo, Ducks;
 TYPE SomeBird* = RECORD ( Birds.Bird ) END;
 VAR sb : SomeBird;
 VAR c : Cuckoos.Cuckoo;
 VAR d : Ducks.Duck;
 PROCEDURE setSound*( VAR bird : Birds.Bird );
 BEGIN
 WITH bird : Cuckoos.Cuckoo DO
 bird.sound := "Cuckoo!";
 | bird : Ducks.Duck DO
 bird.sound := "Quack!";
 ELSE
 bird.sound := "Tweet!";
 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.
codice_4
MODULE PointerBirds;
 IMPORT Out;
 TYPE BirdRec* = RECORD sound* : ARRAY 10 OF CHAR; END;
 DuckRec* = RECORD(BirdRec) END;
 CuckooRec* = RECORD(BirdRec) END;
 TYPE Bird = POINTER TO BirdRec;
 Cuckoo = POINTER TO CuckooRec;
 Duck = POINTER TO DuckRec;
 VAR pb : Bird;
 pc : Cuckoo;
 pd : Duck;
 PROCEDURE makeDuckSound*( bird : Duck );
 BEGIN COPY("Quack!", bird.sound) END makeDuckSound;
 PROCEDURE makeCuckooSound*( bird : Cuckoo );
 BEGIN COPY("Cuckoo!", bird.sound) END makeCuckooSound;
 PROCEDURE makeSound*( bird : Bird );
 BEGIN
 WITH bird : Cuckoo DO makeCuckooSound(bird);
 | bird : Duck DO makeDuckSound(bird)
 ELSE
 COPY("Tweet!", bird.sound);
 END;
 END makeSound;
BEGIN
 NEW(pc);
 NEW(pd);
 makeCuckooSound( pc );
 makeDuckSound( pd );
 Out.Ln;Out.String( pc^.sound );Out.Ln;
 Out.Ln;Out.String( pd^.sound );Out.Ln;
 makeSound( pc );
 makeSound( pd );
 Out.Ln;Out.String( pc^.sound );Out.Ln;
 Out.Ln;Out.String( pd^.sound );Out.Ln;
 pb := pd;
 makeDuckSound( pb(Duck) );
 Out.Ln;Out.String( pb^.sound );Out.Ln;
 pb := pc;
 makeCuckooSound( pb(Cuckoo) );
 Out.Ln;Out.String( pb^.sound );Out.Ln;
 makeSound(pb);
 Out.Ln;Out.String( pb^.sound );Out.Ln;
 pb := pd;
 makeSound(pb);
 Out.Ln;Out.String( pb^.sound );Out.Ln;
 NEW(pb);
 makeSound(pb);
 Out.Ln;Out.String( pb^.sound );Out.Ln;
END PointerBirds.
第三の方法として、codice_5 演算子を使った方法もある。これは、等号（codice_6）や不等号（codice_7）などと同じ優先順位の関係演算子であるが、動的な型の検査を行う。しかし、上述の2つの方法とは異なり、検出した派生型によって処理を振り分けることはできない。
文法.
ALGOL - Pascal - Modula-2 - Oberon - Component Pascal の系列の言語は文法を単純化させてきたと言える。Oberon-2 はEBNFを使って下記のように33の構文生成規則で表せる（"Mössenböck & Wirth, 1993"）。
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}.
Factor = Designator ["(" [ExprList] ")"] | number | character | string | NIL | Set | "(" 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 [" * " | "-"].