Oberon-2

Last updated

Oberon-2
Oberon programming language logo.svg
Paradigms Imperative, structured, modular, object-oriented
Family Wirth Oberon
Designed by Niklaus Wirth
Hanspeter Mössenböck
Developer ETH Zurich
First appeared1991;33 years ago (1991)
Typing discipline Strong, hybrid (static and dynamic)
Scope Lexical
Platform Ceres (NS32032), IA-32, x86-64
OS Windows, Linux, Solaris, macOS
Website www.ethoberon.ethz.ch
Influenced by
Oberon, Modula-2, Object Oberon
Influenced
Oberon-07, Zonnon, Active Oberon, Component Pascal, Go, Nim

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.

Contents

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, is fully compatible with it, and was a redesign of Object Oberon.

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

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

Reflection in Oberon-2 does not use metaobjects, 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 thus be implemented almost entirely at library level, without changing the language code. Indeed, ETH Oberon makes use of language-level and library-level reflection abilities extensively.

Oberon-2 provides built-in runtime 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 and C++. Separate compiling using symbol files and namespaces via the module architecture ensure fast rebuilds since only modules with changed interfaces need to be recompiled.

The language Component Pascal [2] is a refinement (a superset) of Oberon-2.

Example code

The following Oberon-2 code implements a simple binary tree:

MODULETrees;TYPETree*=POINTERTONode;Node*=RECORDname-:POINTERTOARRAYOFCHAR;left,right:TreeEND;PROCEDURE(t:Tree)Insert*(name:ARRAYOFCHAR);VARp,father:Tree;BEGINp:=t;REPEATfather:=p;IFname=p.name^THENRETURNEND;IFname<p.name^THENp:=p.leftELSEp:=p.rightENDUNTILp=NIL;NEW(p);p.left:=NIL;p.right:=NIL;NEW(p.name,LEN(name)+1);COPY(name,p.name^);IFname<father.name^THENfather.left:=pELSEfather.right:=pENDENDInsert;PROCEDURE(t:Tree)Search*(name:ARRAYOFCHAR):Tree;VARp:Tree;BEGINp:=t;WHILE(p#NIL)&(name#p.name^)DOIFname<p.name^THENp:=p.leftELSEp:=p.rightENDEND;RETURNpENDSearch;PROCEDURENewTree*():Tree;VARt:Tree;BEGINNEW(t);NEW(t.name,1);t.name[0]:=0X;t.left:=NIL;t.right:=NIL;RETURNtENDNewTree;ENDTrees.

Oberon-2 extensions to Oberon [3]

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 formerly 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.

Runtime 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 runtime.

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

MODULEBirds;TYPEBird*=RECORDsound*:ARRAY10OFCHAR;END;ENDBirds.MODULEDucks;IMPORTBirds;TYPEDuck*=RECORD(Birds.Bird)END;PROCEDURESetSound*(VARbird:Duck);BEGINbird.sound:="Quack!"ENDSetSound;ENDDucks.MODULECuckoos;IMPORTBirds;TYPECuckoo*=RECORD(Birds.Bird)END;PROCEDURESetSound*(VARbird:Cuckoo);BEGINbird.sound:="Cuckoo!"ENDSetSound;ENDCuckoos.

WITH statement

MODULETest;IMPORTOut,Birds,Cuckoos,Ducks;TYPESomeBird*=RECORD(Birds.Bird)END;VARsb:SomeBird;c:Cuckoos.Cuckoo;d:Ducks.Duck;PROCEDURESetSound*(VARbird:Birds.Bird);BEGINWITHbird:Cuckoos.CuckooDObird.sound:="Cuckoo!"|bird:Ducks.DuckDObird.sound:="Quack!"ELSEbird.sound:="Tweet!"ENDENDSetSound;PROCEDUREMakeSound*(VARb:Birds.Bird);BEGINOut.Ln;Out.String(b.sound);Out.LnENDMakeSound;BEGINSetSound(c);SetSound(d);SetSound(sb);MakeSound(c);MakeSound(d);MakeSound(sb)ENDTest.

POINTER

MODULEPointerBirds;IMPORTOut;TYPEBirdRec*=RECORDsound*:ARRAY10OFCHAR;END;DuckRec*=RECORD(BirdRec)END;CuckooRec*=RECORD(BirdRec)END;Bird=POINTERTOBirdRec;Cuckoo=POINTERTOCuckooRec;Duck=POINTERTODuckRec;VARpb:Bird;pc:Cuckoo;pd:Duck;PROCEDURESetDuckSound*(bird:Duck);BEGINbird.sound:="Quack!"ENDSetDuckSound;PROCEDURESetCuckooSound*(bird:Cuckoo);BEGINbird.sound:="Cuckoo!"ENDSetCuckooSound;PROCEDURESetSound*(bird:Bird);BEGINWITHbird:CuckooDOSetCuckooSound(bird)|bird:DuckDOSetDuckSound(bird)ELSEbird.sound:="Tweet!"ENDENDSetSound;BEGINNEW(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.LnENDPointerBirds.

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 ALGOLPascalModula-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, March 1995) 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, macOS.

The Oxford Oberon-2 compiler compiles to native machine code and can use a JIT on Windows, Linux, and macOS. It is created and maintained by Mike Spivey and uses the Keiko Virtual Machine. [4] [5]

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 named 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 been developed at ETHZ.

Programmer's Open Workbench (POW!) [6] is a very simple integrated development environment, which is provided with editor, linker, and Oberon-2 compiler. This compiles to Windows executables. Full source code is provided; the compiler is written in Oberon-2.

The Java to Oberon Compiler (JOB) was written at the University of Vologda in Russia. It produces object code in the form of Java class files (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 GNU Compiler Collection (GCC) toolchain for program generation.

Oberon Script is a compiler that translates the full Oberon language into JavaScript. The compiler is written in JavaScript and can thus be called from Web pages to process scripts 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 software development. Available for Windows and Linux. The compiler is written in Oberon-2 and compiles itself.

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

XOberon is a real-time operating system for PowerPC, written in Oberon-2.

The Portable Oberon-2 Compiler (OP2) was developed to port the Oberon System onto commercially available platforms. [7]

Keiko bytecode

Oberon-2 can target the Keiko Virtual machine. [8] [9] For example, like some other language compilers (see O-code, p-code, etc.), the Oxford Oberon-2 compiler first compiles to an intermediate bytecode (Keiko bytecode) which can be interpreted with a byte-code interpreter or use just-in-time compilation.

See also

Related Research Articles

Mesa is a programming language developed in the mid 1970s at the Xerox Palo Alto Research Center in Palo Alto, California, United States. The language name was a pun based upon the programming language catchphrases of the time, because Mesa is a "high level" programming language.

<span class="mw-page-title-main">Oberon (programming language)</span> General-purpose programming language

Oberon is a general-purpose programming language first published in 1987 by Niklaus Wirth and the latest member of the Wirthian family of ALGOL-like languages. Oberon was the result of a concentrated effort to increase the power of Modula-2, the direct successor of Pascal, and simultaneously to reduce its complexity. Its principal new feature is the concept of type extension of record types. It permits constructing new data types on the basis of existing ones and to relate them, deviating from the dogma of strictly static typing of data. Type extension is Wirth's way of inheritance reflecting the viewpoint of the parent site. Oberon was developed as part of the implementation of an operating system, also named Oberon at ETH Zurich in Switzerland. The name was inspired both by the Voyager space probe's pictures of the moon of the planet Uranus, named Oberon, and because Oberon is famous as the king of the elfs.

Pascal is an imperative and procedural programming language, designed by Niklaus Wirth as a small, efficient language intended to encourage good programming practices using structured programming and data structuring. It is named after French mathematician, philosopher and physicist Blaise Pascal.

In computer programming, a p-code machine is a virtual machine designed to execute p-code. This term is applied both generically to all such machines, and to specific implementations, the most famous being the p-Machine of the Pascal-P system, particularly the UCSD Pascal implementation, among whose developers, the p in p-code was construed to mean pseudo more often than portable, thus pseudo-code meaning instructions for a pseudo-machine.

In computer science, a recursive descent parser is a kind of top-down parser built from a set of mutually recursive procedures where each such procedure implements one of the nonterminals of the grammar. Thus the structure of the resulting program closely mirrors that of the grammar it recognizes.

In computer science, imperative programming is a programming paradigm of software that uses statements that change a program's state. In much the same way that the imperative mood in natural languages expresses commands, an imperative program consists of commands for the computer to perform. Imperative programming focuses on describing how a program operates step by step, rather than on high-level descriptions of its expected results.

Component Pascal is a programming language in the tradition of Niklaus Wirth's Pascal, Modula-2, Oberon and Oberon-2. It bears the name of the language Pascal and preserves its heritage, but is incompatible with Pascal. Instead, it is a minor variant and refinement of Oberon-2 with a more expressive type system and built-in string support. Component Pascal was originally named Oberon/L, and was designed and supported by a small ETH Zürich spin-off company named Oberon microsystems. They developed an integrated development environment (IDE) named BlackBox Component Builder. Since 2014, development and support has been taken over by a small group of volunteers. The first version of the IDE was released in 1994, as Oberon/F. At the time, it presented a novel approach to graphical user interface (GUI) construction based on editable forms, where fields and command buttons are linked to exported variables and executable procedures. This approach bears some similarity to the code-behind way used in Microsoft's .NET 3.0 to access code in Extensible Application Markup Language (XAML), which was released in 2008.

PL/0 is a programming language, intended as an educational programming language, that is similar to but much simpler than Pascal, a general-purpose programming language. It serves as an example of how to construct a compiler. It was originally introduced in the book, Algorithms + Data Structures = Programs, by Niklaus Wirth in 1976. It features quite limited language constructs: there are no real numbers, very few basic arithmetic operations and no control-flow constructs other than "if" and "while" blocks. While these limitations make writing real applications in this language impractical, it helps the compiler remain compact and simple.

In computer science, type safety and type soundness are the extent to which a programming language discourages or prevents type errors. Type safety is sometimes alternatively considered to be a property of facilities of a computer language; that is, some facilities are type-safe and their usage will not result in type errors, while other facilities in the same language may be type-unsafe and a program using them may encounter type errors. The behaviors classified as type errors by a given programming language are usually those that result from attempts to perform operations on values that are not of the appropriate data type, e.g., adding a string to an integer when there's no definition on how to handle this case. This classification is partly based on opinion.

Object Pascal is an extension to the programming language Pascal that provides object-oriented programming (OOP) features such as classes and methods.

The computer programming languages C and Pascal have similar times of origin, influences, and purposes. Both were used to design their own compilers early in their lifetimes. The original Pascal definition appeared in 1969 and a first compiler in 1970. The first version of C appeared in 1972.

IP Pascal is an implementation of the Pascal programming language using the IP portability platform, a multiple machine, operating system and language implementation system. It implements the language "Pascaline", and has passed the Pascal Validation Suite.

In computer programming, an opaque pointer is a special case of an opaque data type, a data type declared to be a pointer to a record or data structure of some unspecified type.

Lola is designed to be a simple hardware description language for describing synchronous, digital circuits. Niklaus Wirth developed the language to teach digital design on field-programmable gate arrays (FPGAs) to computer science students while a professor at ETH Zurich.

A property, in some object-oriented programming languages, is a special sort of class member, intermediate in functionality between a field and a method. The syntax for reading and writing of properties is like for fields, but property reads and writes are (usually) translated to 'getter' and 'setter' method calls. The field-like syntax is easier to read and write than many method calls, yet the interposition of method calls "under the hood" allows for data validation, active updating, or implementation of what may be called "read-only fields".

Protel stands for "Procedure Oriented Type Enforcing Language". It is a programming language created by Nortel Networks and used on telecommunications switching systems such as the DMS-100. Protel-2 is the object-oriented version of Protel.

Modula-2 is a structured, procedural programming language developed between 1977 and 1985/8 by Niklaus Wirth at ETH Zurich. It was created as the language for the operating system and application software of the Lilith personal workstation. It was later used for programming outside the context of the Lilith.

OpenHMPP - programming standard for heterogeneous computing. Based on a set of compiler directives, standard is a programming model designed to handle hardware accelerators without the complexity associated with GPU programming. This approach based on directives has been implemented because they enable a loose relationship between an application code and the use of a hardware accelerator (HWA).

<span class="mw-page-title-main">Nim (programming language)</span> Programming language

Nim is a general-purpose, multi-paradigm, statically typed, compiled high-level systems programming language, designed and developed by a team around Andreas Rumpf. Nim is designed to be "efficient, expressive, and elegant", supporting metaprogramming, functional, message passing, procedural, and object-oriented programming styles by providing several features such as compile time code generation, algebraic data types, a foreign function interface (FFI) with C, C++, Objective-C, and JavaScript, and supporting compiling to those same languages as intermediate representations.

<span class="mw-page-title-main">Zig (programming language)</span> A general-purpose programming language, toolchain to build Zig/C/C++ code

Zig is an imperative, general-purpose, statically typed, compiled system programming language designed by Andrew Kelley. It is intended to be a successor to the C programming language, with the goals of being even smaller and simpler to program in while also offering modern features, new optimizations and a variety of safety mechanisms while not as demanding of runtime safety as seen in other languages. It is distinct from languages like Go, Rust and Carbon, which have similar goals but also target the C++ space.

References

  1. "Related Reading". Dr. Dobb's.
  2. Pfister, Cuno (2001). "What's New in Component Pascal (changes from Oberon-2 to CP)" (PDF). Oberon microsystems. Archived from the original (PDF) on 15 May 2011. Retrieved 10 January 2007.
  3. Differences between Oberon and Oberon-2, Mössenböck and Wirth (1993)
  4. Spivey, Michael (2014). Specification of Keiko. Spivey's Corner (Report). Oriel College, University of Oxford. Archived from the original on 4 March 2016. Retrieved 9 July 2023.
  5. Spivey, Michael (30 September 2020). Design overview for OBC: The Keiko Abstract Machine. Spivey's Corner (Report). Oriel College, University of Oxford. Retrieved 9 July 2023. The Oxford Oberon-2 compiler translates source programs into code for a stack-based abstract machine. ... the Keiko machine.
  6. Collingbourne, H. (February 2000). "What Pascal's inventor did next". PC Plus . No. 160.
  7. Crelier, Régis (1994). Separate Compilation and Module Extension (PhD). ETH Zurich. doi:10.3929/ethz-a-000945227. hdl:20.500.11850/141604 . Retrieved 18 November 2018.
  8. Dr. Michael Spivey. "Specification of Keiko".
  9. Dr. Michael Spivey. "Design overview for OBC: The Keiko Abstract Machine". quote: "The Oxford Oberon--2 compiler translates source programs into code for a stack-based abstract machine... the Keiko machine"

Further reading