World Library  
Flag as Inappropriate
Email this Article

Oberon-2

 

Oberon-2

Oberon-2
Paradigm(s) imperative, structured, modular, object-oriented
Appeared in 1991
Designed by Niklaus Wirth, Hanspeter Mössenböck
Typing discipline strong, static
Influenced by Oberon, Modula-2, Pascal
Influenced Component Pascal

Oberon-2 is an extension of the original Oberon programming language that adds limited reflection and object-oriented programming facilities, open arrays as pointer base types, read-only field export and reintroduces the FOR loop from Modula-2.

It was developed in 1991 at ETH Zurich by Niklaus Wirth and Hanspeter Mössenböck, who is now at Institut für Systemsoftware (SSW) of the University of Linz, Austria. Oberon-2 is a superset of Oberon, and is fully compatible with it. Oberon-2 was a redesign of Object Oberon.

Oberon-2 inherited limited reflection and single inheritance ("type extension") without interfaces or mixins from Oberon, but added efficient virtual methods ("type bound procedures"). Method calls were resolved at run-time using C++-style virtual method tables.

Compared to fully object-oriented programming languages like Smalltalk, in Oberon-2 basic types are not objects, classes are not objects, many operations are not methods, there is no message passing (to a certain extent it can be emulated by reflection and through message extension, as demonstrated in ETH Oberon), and polymorphism is limited to subclasses of a common class (no duck typing like in Python,[1] and it's not possible to define interfaces like in Java). Oberon-2 does not support encapsulation at object/class level, but modules can be used for this purpose.

Reflection in Oberon-2 does not use meta-objects, but simply reads from type descriptors compiled into the executable binaries, and exposed in the modules that define the types and/or procedures. If the format of these structures are exposed at the language level (as is the case for ETH Oberon, for example), reflection could be implemented at the library level. It could therefore be implemented almost entirely at library level, without changing the language code. Indeed, ETH Oberon makes use of language-level and library-level reflection capabilities extensively.

Oberon-2 provides built-in run-time support for garbage collection similar to Java and performs bounds and array index checks, etc. that eliminate the potential stack and array bounds overwriting problems and manual memory management issues inherent in C/C++. Separate compilation using symbol files and name-spaces via the module architecture ensure quick rebuilds since only modules with changed interfaces need to be recompiled.

Example Oberon-2 code

The following Oberon-2 code would implement a very minimal list class:

MODULE Lists;

    (*** declare global constants, types and variables ***)

    TYPE
        List*    = POINTER TO ListNode;
        ListNode = RECORD
            value : Integer;
            next  : List;
        END;

    (*** declare procedures ***)

    PROCEDURE (l : List) Add* (v : Integer);
    BEGIN
        IF l = NIL THEN
            NEW(l);             (* create record instance *)
            l.value := v
        ELSE
            l.next.Add(v)      (* recursive call to .add(n) *)
        END
    END Add;

    PROCEDURE (l : List) Get* () : Integer;
    VAR
        v : Integer;
    BEGIN
        IF l = NIL THEN
            RETURN 0           (* .get() must always return an INTEGER *)
        ELSE
            v := l.value;       (* this line will crash if l is NIL *)
            l := l.next;
            RETURN v
        END
    END Get;

END Lists.

Oberon-2 extensions to Oberon

Type-bound procedures

Procedures can be bound to a record (or pointer) type. They are equivalent to instance methods in object-oriented terminology.

Read-only export

The use of exported variables and record fields can be restricted to read-only access. This is shown with a "-" visibility flag.

Open arrays

Open arrays which previously could only be declared as formal parameter types may now be declared as pointer base types.

FOR statement

The FOR statement of Pascal and Modula-2 was not implemented in Oberon. It is reintroduced in Oberon-2.

Run-time type checking

Oberon-2 provides several mechanisms for checking the dynamic type of an object. For example, where a Bird object might be instantiated to either a Duck or a Cuckoo, Oberon-2 allows the programmer to respond to the actual type of the object at run-time.

The first, most conventional, approach is to rely on the type binding system. The second approach is to use the WITH statement, which allows the dynamic subtype of a variable to be checked directly. In both cases, once the subtype has been identified, the programmer can make use of any type-bound procedures or variables that are appropriate to the subtype. Examples of these approaches are shown below.

Note that the form of WITH statement used in Oberon-2 is unrelated to the Pascal and Modula-2 WITH statement. This method of abbreviating access to record fields is not implemented in Oberon or Oberon-2.

Type binding

MODULE Birds;
    TYPE
        Bird* = RECORD
            sound* : ARRAY 10 OF Char;
        END;
END Birds.

MODULE Ducks;
    IMPORT 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 := "Cuckoo!"
    END SetSound;
END Cuckoos.

WITH statement

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 := "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.

POINTER

MODULE PointerBirds;
    IMPORT Out;

    TYPE
        BirdRec*   = RECORD
            sound* : ARRAY 10 OF Char;
        END;
        DuckRec*   = RECORD (BirdRec) END;
        CuckooRec* = RECORD (BirdRec) END;

        Bird   = POINTER TO BirdRec;
        Cuckoo = POINTER TO CuckooRec;
        Duck   = POINTER TO DuckRec;

   VAR
       pb : Bird;
       pc : Cuckoo;
       pd : Duck;

    PROCEDURE SetDuckSound* (bird : Duck);
    BEGIN
        bird.sound := "Quack!"
    END SetDuckSound;

    PROCEDURE SetCuckooSound* (bird : Cuckoo);
    BEGIN
        bird.sound := "Cuckoo!"
    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;

(* -------------------------------------- *)
(* Pass dynamic type to procedure         *)

    pb := pd;

    SetDuckSound(pb(Duck));
    Out.Ln; Out.String(pb^.sound); Out.Ln;

    pb := pc;

    SetCuckooSound(pb(Cuckoo));
    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;

(* -------------------------------------- *)

    NEW(pb);

    SetSound(pb);
    Out.Ln; Out.String(pb^.sound); Out.Ln
END PointerBirds.

IS operator

A third approach is possible using the IS operator. This is a relation operator with the same precedence as equals (=), greater (>), etc. but which tests dynamic type. Unlike the two other approaches, however, it does not allow the programmer access to the subtype that has been detected.

Syntax

The development of the ALGOL - Pascal - Modula-2 - Oberon - Component Pascal language family is marked by a reduction in the complexity of the language syntax. The entire Oberon-2 language is described (Mössenböck & Wirth, 1993) using only 33 grammatical productions in the extended Backus–Naur form, as shown below.

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 [" * " | "-"].

Implementations

Oberon-2 compilers maintained by ETH include versions for Windows, Linux, Solaris, Mac OS X.

The Keiko Virtual Machine.

There is an Oberon-2 Lex scanner and Yacc parser by Stephen J Bevan of Manchester University, UK, based on the one in the Mössenböck and Wirth reference. It is at version 1.4.

There is a release called Native Oberon which includes an operating system, and can directly boot on PC class hardware.

A .NET implementation of Oberon with the addition of some minor .NET-related extensions has also been developed at ETHZ.

Windows executables. Full source code is provided - the compiler is written in Oberon-2.

The bytecode). Some JOB-specific classes are provided which are Java compatible, but which use a more Oberon-like component hierarchy.

The Optimizing Oberon-2 Compiler compiles to C, using the gcc toolchain for program generation.

HTML script sections written in Oberon.

XDS Modula2/Oberon2 is a development system by Excelsior LLC, Novosibirsk, Russia. It contains an optimizing compiler for Intel Pentium, or "via-C" translator for cross-platform development. Available for Windows and Linux. The compiler is written on Oberon-2 and compiles itself.

Oberon Revival is a project to bring Oberon 2 and Component Pascal (blackbox) to Linux and Win32. The Linux port of blackbox was not available before and it originally ran only on Microsoft Windows.

References

Evolution of Oberon and Oberon-2

  • "ETHZ
  • "Second International Modula-2 Conference", September 1991.

Detailed papers

Books

  • Various including electronic online versions
  • [1] as PDF with the friendly permission of Springer-Verlag)
  • Design Patterns in Oberon-2 and Component Pascal
  • Project Oberon. The design of an Operating System and Compiler Niklaus Wirth & Jürg Gutknecht (2005)

External links

  • ETH Oberon Home Page
  • Oberon Reference page at ETH-Zürich
  • Oberon at SSW, Linz
  • Language Report
  • Pow Course - by Dan Popa (Romanian version)
  • ftp://ftp.inf.ethz.ch/pub/Oberon/.
  • The Oberon-2 Reflection Model and its Applicationsbe-x-old:Oberon

cs:Oberon (programovací jazyk) de:Oberon (Programmiersprache) es:Lenguaje de programación Oberon fr:Oberon (langage) it:Oberon (linguaggio) nl:Oberon (programmeertaal) ja:Oberon-2 pl:Oberon (język programowania) tg:Оберон (забони барноманависӣ)

This article was sourced from Creative Commons Attribution-ShareAlike License; additional terms may apply. World Heritage Encyclopedia content is assembled from numerous content providers, Open Access Publishing, and in compliance with The Fair Access to Science and Technology Research Act (FASTR), Wikimedia Foundation, Inc., Public Library of Science, The Encyclopedia of Life, Open Book Publishers (OBP), PubMed, U.S. National Library of Medicine, National Center for Biotechnology Information, U.S. National Library of Medicine, National Institutes of Health (NIH), U.S. Department of Health & Human Services, and USA.gov, which sources content from all federal, state, local, tribal, and territorial government publication portals (.gov, .mil, .edu). Funding for USA.gov and content contributors is made possible from the U.S. Congress, E-Government Act of 2002.
 
Crowd sourced content that is contributed to World Heritage Encyclopedia is peer reviewed and edited by our editorial staff to ensure quality scholarly research articles.
 
By using this site, you agree to the Terms of Use and Privacy Policy. World Heritage Encyclopedia™ is a registered trademark of the World Public Library Association, a non-profit organization.
 


Copyright © World Library Foundation. All rights reserved. eBooks from Project Gutenberg are sponsored by the World Library Foundation,
a 501c(4) Member's Support Non-Profit Organization, and is NOT affiliated with any governmental agency or department.