Super Prev Next

XDS Oberon-2

This chapter includes the details of the Oberon-2 language which are specific for this implementation. In the standard mode /When the options O2EXTENSIONS and O2NUMEXT are OFF./ XDS Oberon-2 is fully compatible with ETH compilers (See The Oberon-2 Report). The last changes to the language are described in Last changes to the language.

To provide a smooth path from Modula-2 to Oberon-2 XDS allows all Modula-2 data types to be used in Oberon-2 modules (See Using Modula-2 features).

Several language extensions are implemented in the language according to The Oakwood Guidelines for the Oberon-2 Compiler Developers /These guidelines have been produced by a group of Oberon-2 compiler developers, including ETH developers, after a meeting at the Oakwood Hotel in Croydon, UK in June 1993./ (See Oakwood numeric extensions). Other language extensions are described in Language extensions. As XDS is a truly multi-lingual system, special features were introduced to provide interfacing to foreign languages (See Chapter Multilanguage programming).


Super Prev Next

The Oberon environment

The Oberon-2 language was originally designed for use in an environment that provides command activation, garbage collection, and dynamic loading of the modules. Not being a part of the language, these features still contribute to the power of Oberon-2.

The garbage collector and command activation are implemented in the Oberon Run-Time Support and can be used in any program. The dynamic loader is not provided in the current release. See The oberonRTS module for further information.


Super Prev Next

Program structure

In an Oberon-2 environment, any declared parameterless procedure can be considered as a main procedure and can be called by its name (a qualified identifier of the form ModuleName.ProcName).

Due to the nature of XDS, and its freedom from the Oberon system, a different approach had to be found to declare the ‘top level’ or program modules.

The module which contains the top level of your program must be compiled it with the MAIN option set. This will generate an entry point to your program. Only one module per program shall be compiled with the option set. It is recommended to set it in the module header:

    <*+ MAIN *>
    MODULE hello;

    IMPORT InOut;

    BEGIN
      InOut.WriteString ("Hello World!");
      InOut.WriteLn;
    END hello.


Super Prev Next

Creating a definition

XDS provides two different ways to create a definition for an Oberon-2 module:

The MAKEDEF option provides additional services: the compiler will preserve the so-called exported comments (i.e. comments which start with ‘(**’) if the XCOMMENTS option is ON.

The generated pseudo-definition module contains all exported declarations in the order of their appearance in the source text. All exported comments are placed at the appropriate positions.

A definition can be generated in three styles.The BSTYLE equation can be used to choose one of the styles: DEF (default), DOC or MOD.

The DEF style

This produces an ETH-style definition module. All type-bound procedures (methods) and relative comments are shown as parts of the corresponding record types.

This is the only style for which the BSREDEFINE and BSCLOSURE options are applicable.

The DOC style

This produces a pseudo-definition module in which methods are shown as parts of the appropriate record types (ignoring comments) and at the positions at which they occur in the source text.

The MOD style

This attempts to produce a file which can be compiled as an Oberon-2 module after slight modification (i.e. the file will contain "END procname", etc.)


Super Prev Next

Last changes to the language


Super Prev Next

ASSERT

The procedure ASSERT checks its boolean parameter and terminates the program if it is not TRUE. The second optional parameter denotes a task termination code. If omitted, a standard value is assumed.

    PROCEDURE ASSERT(cond: BOOLEAN [; code: INTEGER]);

A call ASSERT(expr,code) is equivalent to

    IF NOT expr THEN HALT(code) END;


Super Prev Next

Underscores in identifiers

According to the Oakwood Guidelines an underscore ("_") may be used in identifiers (as a letter).

    ident = ( letter | "_" ) { letter | digit | "_" }

We recommend to use underscores with care, as it may cause problems with software portability to other compilers. This feature may be important for interfacing to foreign languages (See Chapter Multilanguage programming).


Super Prev Next

Source code directives

Source code directives (or pragmas) are used to set compilation options in the source text and to select specific pieces of the source text to be compiled (conditional compilation). According to the Oakwood Guidelines all directives are contained in ISO Modula-2 style pseudo comments using angled brackets <* ... *>.

The additional language constructs should not be considered to be part of the Oberon-2 language. They define a separate compiler control language that coexist with Oberon-2. The option O2ISOPRAGMA allows pragmas to be used.

The syntax of the directives is the same for Modula-2 and Oberon-2. See Source code directives for further details.


Super Prev Next

Oakwood numeric extensions

XDS Oberon-2 supports two extensions which are of importance for scientific programming, namely

The O2NUMEXT option should be set to use these extensions.


Super Prev Next

Complex numbers

NOTE: Only valid when option O2NUMEXT is set.

Two additional types are included in the type hierarchy if the O2NUMEXT option is set:

COMPLEX defined as (REAL,REAL)
LONGCOMPLEX defined as (LONGREAL,LONGREAL)

All numeric types form a (partial) hierarchy whole types ⊂REAL ⊆l COMPLEX
LONGREAL
⊆LONGCOMPLEX A common mathematical notation is used for complex number literals:

    number = integer | real | complex
    complex = real "i"

A literal of the form 5.0i denotes a complex number with real part equal to zero and an imaginary part equal to 5.0. Complex constants with a non-zero real part can be described using arithmetic operators.

    CONST
      i = 1.i;
      x = 1. + 1.i;

For the declarations

    VAR
      c: COMPLEX;
      l: LONGCOMPLEX;
      r: REAL;
      x: INTEGER;

the following statements are valid:

      c:=i+r;
      l:=c;
      l:=c*r;
      l:=l*c;

New conversion functions RE and IM can be used to obtain a real or imaginary part of a value of a complex type. Both functions have one parameter. If the parameter is of the COMPLEX type, both functions return a REAL value; if the parameter is of the LONGCOMPLEX type, functions return a LONGREAL value; otherwise the parameter should be a complex constant and functions return a real constant.

A complex value can be formed by applying the standard function CMPLX to two reals. If both CMPLX arguments are real constants, the result is a complex constant.

    CONST i = CMPLX(0.0,1.0);

If both expressions are of the REAL type, the function returns a COMPLEX value, otherwise it returns a LONGCOMPLEX value.


Super Prev Next

In-line exponentiation

NOTE: Only valid when option O2NUMEXT is set.

The exponentiation operator ** provides a convenient notation for arithmetic expressions, which does not involve function calls. It is an arithmetic operator which has a higher precedence than multiplication operators.

    Term     =  Exponent { MulOp Exponent }.
    Exponent =  Factor { "**" Factor }.

Note: the operator is right-associated: a**b**c is evaluated as a**(b**c)

The left operand of the exponentiation (a**b) should be any numeric value (including complex), while the right operand should be of a real or integer type. The result type does not depend of the type of right operand and is defined by the table:

Left operand type Result type
an integer type REAL
REAL REAL
LONGREAL LONGREAL
COMPLEX COMPLEX
LONGCOMPLEX LONGCOMPLEX


Super Prev Next

Using Modula-2 features

All Modula-2 types and corresponding operations can be used in Oberon-2, including enumeration types, range types, records with variant parts, sets, etc.

Super Prev Next

Important Notes:

Super Prev Next

Example

    (*MODULA-2*) DEFINITION MODULE UsefulTypes;

    TYPE
      TranslationTable = ARRAY CHAR OF CHAR;
      Color  = (red,green,blue);
      Colors = SET OF Color;

    END UsefulTypes.

    (*OBERON-2*) MODULE UsingM2;

    IMPORT UsefulTypes;

    TYPE
      TranslationTable* = UsefulTypes.TranslationTable;

    VAR colors*: UsefulTypes.Color;

    BEGIN
      colors:=UsefulTypes.Colors{UsefulTypes.red};
    END UsingM2.


Super Prev Next

Language extensions

Warning: Using extensions may cause problems with the software portability to other compilers.

In the standard mode, the XDS Oberon-2 compiler is fully compatible with ETH compilers (See also Last changes to the language). The O2EXTENSIONS option enables some language extensions. The main purposes of language extensions are

See also


Super Prev Next

Comments

NOTE: Only valid when option O2EXTENSIONS is set.

As well as "(**)", there is another valid format for comments in source texts. The portion of a line from "--" to the end of line is considered a comment.

    VAR j: INTEGER; -- this is a comment


Super Prev Next

String concatenation

NOTE: Only valid when option O2EXTENSIONS is set.

The symbol "+" can be used for constant string and characters concatenation. See Strings for more details.


Super Prev Next

VAL function

NOTE: Only valid when option O2EXTENSIONS is set.

The function VAL can be used to obtain a value of the specified scalar type from an expression of a scalar type. See Type conversions for more details.

    PROCEDURE VAL(Type; expr: ScalarType): Type;

The function can be applied to any scalar types, including system fixed size types (See Whole system types).


Super Prev Next

Read-only parameters

NOTE: Only valid when option O2EXTENSIONS is set.

In a formal parameter section, the symbol "-" may appear after a name of a value parameter. That parameter is called read-only; its value can not be changed in the procedure’s body. Read-only parameters need not to be copied before the procedure activation; this enables procedures with structured parameters to be more effective. Read-only parameters can not be used in a procedure type declaration.

We recommend to use read-only parameters with care. The compiler does not check that the read-only parameter is not modified via another parameter or a global variable.

Super Prev Next

Example

    PROCEDURE Foo(VAR dest: ARRAY OF CHAR;
                   source-: ARRAY OF CHAR);
    BEGIN
      dest[0]:='a';
      dest[1]:=source[0];
    END Foo;

The call Foo(x,x) would produce a wrong result, because the first statement changes the value of source[0] (source is not copied and points to the same location as dest).


Super Prev Next

Variable number of parameters

NOTE: Only valid when option O2EXTENSIONS is set.

Everything contained in the section Variable number of parameters is applicable to Oberon-2.


Super Prev Next

Value constructors

NOTE: Only valid when option O2EXTENSIONS is set.

Everything contained in the section Value constructors is applicable to Oberon-2.


Super Prev Next

The Oberon-2 module SYSTEM

Low-level facilities are provided by the module SYSTEM. This module does not exist in the same sense as other library modules; it is hard-coded into the compiler itself. However, to use the provided facilities, it must be imported in the usual way.

Some procedures in the module SYSTEM are generic procedures that cannot be explicitly declared, i.e. they apply to classes of operand types.

XDS Oberon-2 compiler implements all system features described in The Oberon-2 Report (except GETREG, PUTREG, and CC) and allows one to access all features, described in the Modula-2 International Standard Modula-2 (See The Modula-2 module SYSTEM). In this section we describe only features specific for this implementation.


Super Prev Next

Compatibility with BYTE

Expressions of types CHAR, BOOLEAN, SHORTINT and SYSTEM.CARD8 can be assigned to variables of type BYTE or passed as actual parameters to formal parameters of type BYTE.

If a formal procedure parameter has type ARRAY OF BYTE, then the corresponding actual parameter may be of any type, except numeric literals.


Super Prev Next

Whole system types

Module SYSTEM contains the signed types INT8, INT16, INT32, and unsigned types CARD8, CARD16, CARD32, which are guaranteed to contain exactly 8, 16, or 32 bits respectively. These types were introduced to simplify consstructing the interfaces to foreign libraries (See Chapter Multilanguage programming). The basic types SHORTINT, INTEGER, LONGINT are synonyms of INT8, INT16, and INT32 respectively.

The unsigned types form a hierarchy whereby larger types include (the values of) smaller types. SYSTEM.CARD32SYSTEM.CARD16SYSTEM.CARD8 The whole hierarchy of numeric types (See also Complex numbers): LONGREALREAL ⊇{ l signed types
unsigned types
.


Super Prev Next

NEW and DISPOSE

The procedure SYSTEM.NEW can be used to allocate the system memory, i.e. memory which is not the subject of garbage collection. SYSTEM.NEW is a generic procedure, which is applied to pointer types and can be used in several ways, depending on pointer’s base type.

    PROCEDURE NEW(VAR p: AnyPointer [; x0,..xn: integer]);

Let type P be defined as POINTER TO T and p is of type P.

NEW(p) T is a record or fixed length array type. The procedure allocates a storage block of SIZE(T) bytes and assigns its address to p.
NEW(p,n) T is a record or fixed length array type. The procedure allocates a storage block of n bytes and assigns its address to p.
NEW(p,x0,..xn-1) T is an n-dimensional open array. The procedure allocates an open array of lengths given by the expressions x0,..xn-1

The procedure SYSTEM.DISPOSE can be used to free a block previously allocated by a call to SYSTEM.NEW. It does not immediately deallocate the block, but marks it as a free block. The block will be deallocated by the next call of the garbage collector.

    PROCEDURE DISPOSE(VAR p: AnyPointer; [size: integer]);

DISPOSE(p) T is a record or array type. The procedure deallocates the storage block p points to.
DISPOSE(p,n) T is a record or fixed length array type. The procedure deallocates the storage block of n bytes p points to.


Super Prev Next

M2ADR

In Oberon-2, the SYSTEM.ADR procedure returns LONGINT, which is not always very convenient. The SYSTEM.M2ADR procedure behaves as Modula-2 SYSTEM.ADR, returning SYSTEM.ADDRESS:

    PROCEDURE M2ADR(VAR x: any type): ADDRESS;