Die Programmiersprache Oberon (Revidierte Fassung)                      N.Wirth

Make it as simple as possible, but not simpler.
A. Einstein.


1. Einfhrung

Oberon ist eine aus Modula-2 hervorgegangene universelle Programmiersprache,
deren wesentliche Neuerung das Konzept der Typerweiterung darstellt, welches
die Konstruktion neuer Datentypen auf der Basis bereits existierender
und die Inbezugsetzung dieser Typen untereinander ermglicht.Dieser Report ist
nicht als Programmierkurs gedacht. Er ist bewut knapp gehalten und soll als
Referenz fr Programmierer, Implementoren und Autoren von Handbchern dienen.

Fehlende Spezifikationen sind meistens beabsichtigt, da sich der betreffende
Sachverhalt entweder aus den gegebenen Sprachregeln ableiten lt, oder aber
an solchen Stellen bewut offen gelassen wird, an denen eine endgltige
Festlegung unklug erscheint.


2. Syntax

Eine Sprache besteht aus einer unendlichen Menge von Stzen, welche sich gem
ihrer Syntax herleiten lassen. Die Stze der Sprache Oberon nennen wir
Compilationseinheiten (Compilation Units); sie bestehen jeweils aus einer
endlichen Folge vom Symbolen eines endlichen Vokabulars. Das Vokabular der
Sprache Oberon besteht aus Namen (Identifiers), Zahlen (Numbers), Zeichenketten
(Strings), Operatoren (Operators), Begrenzern (Delimiters) und Kommentaren.

Die Elemente dieses Vokabulars werden lexikalische Symbole genannt und bestehen
aus Zeichenfolgen. (Man beachte die Unterscheidung zwischen Symbolen und
Zeichen.) Zur Beschreibung der Syntax wird ein erweiterter Backus Naur-
Formalismus (EBNF) verwendet. Eckige Klammern [ und ] bedeuten hierin, da die
umschlossenen Konstrukte optional sind, und geschweifte Klammern { und }, da
der dazwischenstehende Satzteil (mglicherweise auch nullmalig) wiederholt
werden darf. Syntaktische Einheiten (Nichtterminalsymbole) werden mit
englischen Begriffen bezeichnet, welche intuitiv die Bedeutung ausdrcken.
Symbole des Sprachvokabulars (Terminalsymbole) werden durch in
Anfhrungszeichen eingeschlossene Zeichenketten bezeichnet, oder durch Worte in
Grobuchstaben, sogenannte reservierte Worte. Die Syntaktischen Regeln
(Produktionen) sind mit einem Dollarzeichen ($) am linken Zeilenrand markiert.


3. Vokabular und Darstellung

Die Darstellung von Symbolen durch Zeichen ist mittels des ASCII-Zeichensatzes
definiert. Symbole sind Namen, Zahlen, Zeichenketten, Operatoren, Begrenzer
und Kommentare. Die folgenden lexikalischen Regeln sind einzuhalten:
Leerzeichen und Zeilenbrche drfen nicht innerhalb von Symbolen auftreten
(ausgenommen innerhalb von Kommentaren und Leerzeichen in Strings); sie werden
ignoriert, es sei denn, sie wren absolut notwendig, um zwei
aufeinanderfolgende Symbole zu trennen. Gro- und Kleinbuchstaben werden
unterschieden.

1. Namen sind Folgen von Buchstaben und Ziffern. Das erste Zeichen mu ein
Buchstabe sein.

$       ident  =  letter {letter | digit}.

Beispiele:

  x scan   Oberon   GetSymbol   firstLetter

2. Zahlen sind vorzeichenlose Integerzahlen oder reelle Zahlen. Integerzahlen
sind Folgen von Ziffern und knnen von einem Buchstaben gefolgt werden. Der
Typ einer Zahl ist der Minimaltyp (siehe 6.1), zu dem die Zahl gehrt. Folgt
der Ziffernfolge kein Buchstabe, so handelt es sich um eine Zahl in dezimaler
Darstellung. Der nachgestellte Buchstabe H bezeichnet die hexadezimale
Darstellung. Eine reelle Zahl enthlt immer einen Dezimalpunkt. Wahlweise
kann auch ein dezimaler Skalierungsfaktor enthalten sein:  Der Buchstabe E
(oder D) wird gesprochen als "mal zehn hoch". Eine reelle Zahl ist vom Typ
REAL, es sei denn, der Skalierungsfaktor wre D; dann ist die Zahl vom Typ
LONGREAL.

$       number =  integer | real.
$       integer  =  digit {digit} | digit {hexDigit} "H" .
$       real  =  digit {digit} "." {digit} [ScaleFactor].
$       ScaleFactor  =  ("E" | "D") ["+" | "-"] digit {digit}.
$       hexDigit  =  digit | "A" | "B" | "C" | "D" | "E" | "F".
$       digit  =  "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9".

Beispiele:

  1987
  100H    = 256
  12.3
  4.567E8 = 456700000
  0.57712566D-6   = 0.000000577125663.

Zeichenkonstanten werden entweder durch ein einzelnes Zeichen in
Anfhrungszeichen, oder durch die Ordinalzahl des Zeichens in hexadezimaler
Darstellung, gefolgt von dem Buchstaben X, gekennzeichnet.

$    CharConstant = """ character """ | digit {hexDigit} "X".

4. Strings sind in Anfhrungszeichen (") eingeschlossene Zeichenfolgen. Ein
String darf selbst keine Anfhrungszeichen enthalten. Die Anzahl der Zeichen
eines Strings wird als seine Lnge bezeichnet. Strings knnen Zeichenarrays
zugewiesen werden und mit ihnen verglichen werden (siehe 9.1 und 8.2.4).

$ string  =  """ {character} """ .

Beispiele:

  "OBERON"
  "Don't worry!"

5. Operatoren und Begrenzer sind die nachfolgend aufgefhrten speziellen
Zeichen, Zeichenpaare und reservierten Worte. Reservierte Worte bestehen
ausschlielich aus Grobuchstaben und knnen nicht in der Rolle von Namen
verwendet werden.

  +       :=      ARRAY   IS      TO
  -       ^       BEGIN   LOOP    TYPE
  *       =       CASE    MOD     UNTIL
  /       #       CONST   MODULE  VAR
  ~       <       DIV     NIL     WHILE
  &       >       DO      OF      WITH
  .       <=      ELSE    OR
  ,       >=      ELSIF   POINTER
  ;       ..      END     PROCEDURE
  |       :       EXIT    RECORD
  (       )       IF      REPEAT
  [       ]       IMPORT  RETURN
  {       }       IN      THEN

6. Kommentare sind beliebige mit der Klammer (* beginnende und mit *) endende
Zeichenfolgen, welche berall im Programm zwischen zwei Symbolen eingefgt
werden drfen. Kommentare haben keinen Einflu auf die Bedeutung eines
Programms.


4. Deklarationen und Sichtbarkeitsregeln

Jeder Name in einem Programm mu mittels einer Deklaration eingefhrt werden,
es sei denn, es handle sich um einen vordefinierten Namen. Deklarationen
dienen auch dazu, bestimmte bleibende Eigenschaften eines Objekts festzulegen,
so z.B., ob es sich um eine Konstante, einen Typ, eine Variable oder eine
Prozedur handelt.Der Name wird verwendet, um sich auf das damit verbundene
Objekt zu beziehen. Dies ist nur innerhalb desjenigen Programmteils mglich,
der im Gltigkeitsbereich der entsprechenden Deklaration liegt. Kein Name darf
sich innerhalb eines einzelnen Gltigkeitsbereichs auf mehr als ein Objekt
beziehen. Ein Gltigkeitsbereich erstreckt sich textuell vom Ort der Deklaration
bis zum Ende des Blocks (Prozedur oder Modul), zu dem die Deklaration gehrt;
das Objekt ist somit lokal zu diesem Block. Folgende Zustze gelten zu dieser
Regel:

1. Wird ein Typ T definiert als POINTER TO T1 (siehe 6.4), dann darf der Name
T1 im Text folgend der Deklaration von T vereinbart werden, aber nur im
gleichen Gltigkeitsbereich.

2. Feldnamen einer Recorddeklaration (siehe 6.3) sind nur innerhalb von Feld-
Bezeichnern gltig. Ein Name mit globalem Gltigkeitsbereich darf bei seiner
Deklaration von einer Exportmarkierung (*) gefolgt sein, die anzeigt, da er
von seinem Modul exportiert wird. In diesem Falle darf der Name in anderen
Modulen verwendet werden, sofern diese dessen Modul importieren. Dem Namen wird
dann als Prfix der Name, der sein Modul bezeichnet, vorangestellt (siehe
Kap. 11). Prfix und Name werden durch einen Punkt getrennt und gemeinsam
qualifizierter Name genannt.

$       qualident = [ident "."] ident.
$       identdef = ident ["*"].

Die folgenden Namen sind vordefiniert, ihre Bedeutung wird in den angegebenen
Abschnitten erklrt:

  ABS             (10.2)     LEN             (10.2)
  ASH             (10.2)     LONG            (10.2)
  BOOLEAN         (6.1)      LONGINT         (6.1)
  BYTE            (6.1)      LONGREAL        (6.1)
  CAP             (10.2)     MAX             (10.2)
  CHAR            (6.1)      MIN             (10.2)
  CHR             (10.2)     NEW             (6.4)
  DEC             (10.2)     ODD             (10.2)
  ENTIER          (10.2)     ORD             (10.2)
  EXCL            (10.2)     REAL            (6.1)
  FALSE           (6.1)      SET             (6.1)
  HALT            (10.2)     SHORT           (10.2)
  INC             (10.2)     SHORTINT        (6.1)
  INCL            (10.2)     SIZE            (10.2)
  INTEGER         (6.1)      TRUE            (6.1)


5. Konstantendeklarationen

Eine Konstantendeklaration verbindet einen Namen mit einem konstanten Wert.

$       ConstantDeclaration  =  identdef "=" ConstExpression.
$       ConstExpression  =  expression.

Ein konstanter Ausdruck kann whrend des Lesens des Quelltextes berechnet
werden, ohne da das Programm tatschlich ausgefhrt werden mu. Seine
Operanden sind Konstanten (siehe Kap. 8). Beispiele fr Konstanten-
deklarationen sind

  N       =       100
  limit   =       2*N -1
  all     =       {0 .. WordSize-1}


6. Typdeklarationen


Ein Datentyp bestimmt die Menge der Werte, welche Variablen dieses Typs
annehmen knnen, und die anwendbaren Operatoren. Eine Typdeklaration verbindet
einen Namen mit einem Typ; solche Assoziationen knnen mit Grundtypen (Basic
Types), oder mit strukturierten Typen geschehen. Im letzteren Fall wird
hierdurch auch die Struktur aller Variablen dieses Typs festgelegt und,
implizit, auch die Operatoren, die auf Komponenten solcher Variablen anwendbar
sind. Es gibt zwei Arten von strukturierten Datentypen, nmlich Arrays
(Vektoren, Matrizen) und Records (Verbundtypen), die sich in der Art des
Zugriffs auf die Komponenten unterscheiden.

$       TypeDeclaration  =  identdef "=" type.
$       type  =  qualident | ArrayType | RecordType | PointerType | ProcedureType.

Beispiele:

  Table        =       ARRAY N OF REAL

  Tree         =       POINTER TO Node

  Node         =       RECORD key: INTEGER;
                        left, right: Tree
                       END

  CenterNode   =       RECORD (Node)
                         name: ARRAY 32 OF CHAR;
                         subnode: Tree
                       END

  Function*    =       PROCEDURE (x: INTEGER): INTEGER

6.1. Grundtypen

Die folgenden Grundtypen sind durch vordefinierte Namen gekennzeichnet. Die
anwendbaren Operatoren werden in Kap. 8.2 beschrieben und die zugehrigen
vordefinierten Funktionen in Kap. 10.2. Die Wertebereiche der Grundtypen sind
wie folgt:

  1.    BOOLEAN         die Wahrheitswerte TRUE und FALSE.
  2.    CHAR            die Menge der ASCII-Werte (0X ... 0FFX).
  3.    SHORTINT        die Integerzahlen von MIN(SHORTINT) bis MAX(SHORTINT).
  4.    INTEGER         die Integerzahlen von MIN(INTEGER) bis MAX(INTEGER).
  5.    LONGINT         die Integerzahlen von MIN(LONGINT) bis MAX(LONGINT).
  6.    REAL            die reellen Zahlen von MIN(REAL) bis MAX(REAL).
  7.    LONGREAL        die reellen Zahlen von MIN(LONGREAL) bis MAX(LONGREAL).
  8.    SET             die Menge der Integerzahlen von 0 bis MAX(SET).
  9.    BYTE            (siehe 9.1 und 10.1)

Die Typen 3 bis 5 sind Integertypen und 6 und 7 sind reelle Typen. Zusammen
bezeichnen wir sie als numerische Typen. Sie bilden eine Hierarchie; der
mchtigere Typ schliet hierbei jeweils den (Wertebereich des) kleineren
Typ(s) ein.

  LONGREAL  J  REAL  J  LONGINT  J  INTEGER  J  SHORTINT

6.2. Arraytypen

Ein Array ist eine Datenstruktur, die aus einer festen Anzahl von Elementen des
gleichen Typs, genannt Elementtyp, besteht. Als Lnge des Arrays wird die
Anzahl seiner Elemente bezeichnet. Die Elemente eines Arrays werden durch
Indizes ausgewhlt. Dies sind Integerzahlen im Wertebereich zwischen 0 und
(Lnge minus 1).

$       ArrayType  =  ARRAY length {"," length} OF type.
$       length  =  ConstExpression.

Eine Deklaration der Form

  ARRAY N0, N1, ... , Nk OF T

wird betrachtet als Abkrzung der Deklaration

  ARRAY N0 OF
    ARRAY N1 OF
      ...
           ARRAY Nk OF T


Beispiele fr Arraytypen:

  ARRAY N OF INTEGER
  ARRAY 10, 20 OF REAL

6.3. Recordtypen

Ein Record ist eine Datenstruktur, die eine feste Anzahl von Elementen,
mglicherweise unterschiedlicher Typen, beinhaltet. Bei der Deklaration eines
Recordtyps wird fr jedes Element, genannt Feld, sein Typ und der Name, der das
Feld auswhlt, festgelegt. Der Gltigkeitsbereich dieser Feldnamen ist die
Recorddefinition; sie sind aber auch innerhalb von Feld-Bezeichnern (siehe 8.1)
sichtbar, die sich auf Elemente von Recordvariablen beziehen.

$       RecordType  =  RECORD ["(" BaseType ")"] FieldListSequence END.
$       BaseType  =  qualident.
$       FieldListSequence  =  FieldList {";" FieldList}.
$       FieldList  =  [IdentList ":" type].
$       IdentList  =  identdef {"," identdef}.

Soll ein Recordtyp exportiert werden, so mssen diejenigen Feldnamen, die
auerhalb des definierenden Moduls sichtbar sein sollen, markiert werden.
Solcherart markierte Felder werden public genannt, nicht markierte hingegen
private. Recordtypen sind erweiterbar, d.h. ein Recordtyp lt sich als
Erweiterung eines anderen Recordtyps vereinbaren. In den obigen Beispielen ist
CenterNode eine (direkte) Erweiterung von Node, welches wiederum ein (direkter)
Basistyp (Base Type) von CenterNode ist. Genauer gesagt, erweitert CenterNode
den Typ Node um die Felder name und subnode.

Definition: Ein Typ T0 erweitert einen Typ T, wenn er gleich T ist, oder wenn
er die direkte Erweiterung einer Erweiterung von T darstellt. Umgekehrt ist
ein Typ T ein Basistyp von T0, falls er gleich T0 ist, oder falls er der
direkte Basistyp eines Basistyps von T0 ist.

Beispiele fr Recordtypen:

  RECORD
    day, month, year: INTEGER
  END

  RECORD
    name, firstname: ARRAY 32 OF CHAR;
    age: INTEGER;
    salary: REAL
  END

6.4. Pointertypen

Variablen eines Pointertyps (Zeigertyps) P nehmen als Werte Referenzen auf
Variablen eines Typs T an. Man sagt, der Pointertyp P ist an den Typ T
gebunden, und T ist der Pointer-Basistyp von P. T mu ein Record- oder
Arraytyp sein. Pointertypen erben die Erweiterungsbeziehungen ihrer Basistypen.
Wenn ein Typ T0 eine Erweiterung von T ist, und P0 ein an T0 gebundener
Pointertyp, dann ist P0 auch eine Erweiterung von P.

$       PointerType  =  POINTER TO type.

Ist p eine Variable vom Typ P = POINTER TO T, dann hat der Aufruf der
vordefinierten Prozedur NEW(p) die folgende Wirkung (siehe 10.2):  Im freien
Speicherbereich wird eine Variable vom Typ T alloziert und eine Referenz auf
diese Variable wird der Pointervariablen p zugewiesen. Die Pointervariable p
ist vom Typ P; die referenzierte Variable p^ ist vom Typ T. Kann kein Speicher
reserviert werden, so wird der Pointervariablen p der Wert NIL zugewiesen.
Jeder Pointervariablen darf der Wert NIL zugewiesen werden, welcher auf keine
Variable verweist.

6.5. Prozedurtypen

Variablen eines Prozedurtyps T haben als Wert eine Prozedur. Wird
eine Prozedur einer Prozedurvariablen vom Typ T zugewiesen, so mssen die
(Typen der) formalen Parameter von P die gleichen sein, wie die der Parameter
von T. Gleiches gilt fr den Typ des Ergebnisses im Fall einer
Funktionsprozedur (siehe 10.1). P darf nicht lokal zu einer anderen Prozedur
vereinbart sein und darf auch keine vordefinierte Prozedur sein. Jeder
Prozedurvariablen darf der Wert NIL zugewiesen werden, welcher auf keine
Prozedur verweist.

$       ProcedureType = PROCEDURE [FormalParameters].


7. Variablendeklarationen

Variablendeklarationen dienen dazu, Variablen einzufhren und sie mit einem
Namen zu verbinden, der im gegebenen Gltigkeitsbereich eindeutig sein mu.
Variablendeklarationen dienen auch dazu, einen Datentyp mit der Variablen zu
assoziieren.

$       VariableDeclaration =  IdentList ":" type.

Variablen, deren Name in der selben Liste auftreten, haben alle den gleichen
Typ.

Beispiele fr Variablendeklarationen (siehe Beispiele in Kap. 6):

  i, j, k:     INTEGER
  x, y:        REAL
  p, q:        BOOLEAN
  s:           SET
  f:           Function
  a:           ARRAY 100 OF REAL
  w:           ARRAY 16 OF
                  RECORD ch: CHAR;
                     count: INTEGER
                  END
  t:           Tree


8. Ausdrcke

Ausdrcke (Expressions) beschreiben die Rechenregeln, nach denen die Werte von
Konstanten und die aktuellen Werte von Variablen kombiniert werden, um durch
die Anwendung von Operatoren und Funktionsprozeduren neue Werte zu erhalten.
Ausdrcke bestehen aus Operanden und Operatoren. Spezielle Assoziationen von
Operatoren und Operanden lassen sich durch Klammerung ausdrcken.


8.1. Operanden

Mit Ausnahme von Mengen und Literalen, d.h. Zahlen und Zeichenketten, werden
Operanden durch Bezeichner (Designators) dargestellt. Ein Bezeichner besteht
aus einem Namen, der sich auf eine zu bezeichnende Konstante, Variable oder
Prozedur bezieht. Dieser Name kann durch einen Modulnamen qualifiziert werden
(siehe Kap. 4 und 11), und von einem Selektor gefolgt werden, falls das
bezeichnete Objekt Element einer Struktur ist.Falls A einen Array bezeichnet,
dann bezieht sich A[E] auf dasjenige Element von A, dessen Index den aktuellen
Wert des Ausdrucks E darstellt. Der Typ von E mu ein Integertyp sein. Ein
Bezeichner der Form A[E1,E2, ... ,En] steht fr A[E1][E2]...[En]. Falls p eine
Pointervariable bezeichnet, dann bezieht sich p^ auf diejenige Variable, die
von p referenziert wird. Bezeichnet r einen Record, dann bezieht sich r.f
auf das Feld f des Records r. Falls p einen Pointer bezeichnet, dann bezieht
sich p.f auf das Feld f des Records p^, d.h. der Punkt impliziert die
Dereferenzierung und der Bezeichner steht fr p^.f; sinngem bezeichnet p[E]
das Element von p^ mit dem Index E.Der Type Guard v(T0), stellt sicher, da v
vom Typ T0 ist (siehe Kap. 6), d.h. das Programm wird abgebrochen, falls v
nicht vom Typ T0 ist. Ein Type Guard ist anwendbar, falls 1. T0 eine
Erweiterung des deklarierten Typs T von v ist, und falls 2. v ein
Variablenparameter (s.u.) eines Recordtyps ist, oder v eine Pointervariable
darstellt.

$       designator  =  qualident {"." ident | "[" ExpList "]" |
$                      "(" qualident ")" | "^" }.
$       ExpList  =  expression {"," expression}.

Ist das bezeichnete Objekt eine Variable, so bezieht sich der Bezeichner auf
den aktuellen Wert der Variablen. Ist das Objekt eine Prozedur, dann bezieht
sich ein Bezeichner ohne Parameterliste auf diese Prozedur. Wird er von einer
(mglicherweise leeren) Parameterliste gefolgt, dann impliziert der Bezeichner
eine Aktivierung der Prozedur und steht fr den Wert, der aus ihrer Ausfhrung
resultiert. Die (Typen der) aktuellen Parameter mssen denen der formalen
Parameter entsprechen, so wie sie bei der Definition der Prozedur spezifiziert
wurden (siehe Kap. 10).

Beispiele fr Bezeichner (siehe Beispiele in Kap. 7):

  i                       (INTEGER)
  a[i]                    (REAL)
  w[3].ch                 (CHAR)
  t.key                   (INTEGER)
  t.left.right            (Tree)
  t(CenterNode).subnode   (Tree)

8.2. Operatoren

Die Syntax von Ausdrcken unterscheidet zwischen vier Klassen von Operatoren
mit verschiedenen Przedenzen (Bindungtrken). Der Operator ~ hat die hchste
Przedenz, gefolgt von den Multiplikationsoperatoren, Additionsoperatoren und
Relationen. Operatoren der gleichen Przedenzstufe binden von links nach
rechts.

Beispiel:

  x-y-z steht fr (x-y)-z.

$       expression =  SimpleExpression [relation SimpleExpression].
$       relation  =  "=" | "#" | "<" | "<=" | ">" | ">=" | IN | IS.
$       SimpleExpression  =  ["+"|"-"] term {AddOperator term}.
$       AddOperator  =  "+" | "-" | OR .
$       term  =  factor {MulOperator factor}.
$       MulOperator  =  "*" | "/" | DIV | MOD | "&" .
$       factor  =  number | CharConstant | string | NIL | set |
$               designator [ActualParameters] | "(" expression ")" | "~" factor.
$       set  =  "{" [element {"," element}] "}".
$       element  =  expression [".." expression].
$       ActualParameters  =  "(" [ExpList] ")" .

Die in Oberon verfgbaren Operatoren sind in den folgenden Tabellen aufgefhrt.
Manchmal werden verschiedene Operationen durch das gleiche Operatorsymbol
gekennzeichnet; in diesen Fllen wird die tatschliche Operation durch den Typ
der Operanden bestimmt.

8.2.1. Logische Operatoren

Symbol Ergebnis

 OR     logische Disjunktion
  &     logische Konjunktion
  ~     Negation

Diese Operatoren sind auf BOOLEAN-Operanden anwendbar und liefern
ein Ergebnis vom Typ BOOLEAN.

  p OR q     steht fr       "wenn p, dann TRUE, sonst q"
  p & q      steht fr       "wenn p, dann q, sonst FALSE"
  ~ p        steht fr       "nicht p"

8.2.2. Arithmetische Operatoren

Symbol  Ergebnis

  +     Summe
  -     Differenz
  *     Produkt
  /     Quotient
 DIV    ganzzahliger Quotient
 MOD    Modulus

Die Operatoren +, -, * und / beziehen sich auf Operanden numerischer Typen.
Der Typ des Ergebnisses ist derjenige Operandentyp, der den Typ des anderen
Operanden einschliet, auer bei der Division (/), bei der das Ergebnis
derjenige Realtyp ist, welcher beide Operandentypen einschliet. Als
monadische Operatoren bezeichnen - die Vorzeichenumkehr und + die Identitt.
Die Operatoren DIV und MOD sind nur auf ganzzahlige Operanden anwendbar. Sie
sind durch die folgenden Beziehungen zwischen beliebigem x und y>0 definiert:

  x  =  (x DIV y) * y  +  (x MOD y)
  0 <=  (x MOD y) < y

8.2.3. Mengenoperatoren

Symbol        Ergebnis

  +     Vereinigungsmenge
  -     Differenzmenge
  *     Schnittmenge
  /     symmetrische Mengendifferenz

Das monadische Minuszeichen bezeichnet das Mengenkomplement von x, d.h. -x
bezeichnet die Menge der Integerzahlen zwischen 0 und MAX(SET), die nicht
Elemente von x sind.

  x - y     =  x * (-y)
  x / y     =  (x-y) + (y-x)

8.2.4.  Relationen

Symbol Relation

  =     gleich
  #     ungleich
  <     kleiner
  <=    kleiner oder gleich
  >     grer
  >=    grer oder gleich
  IN    Mengenzugehrigkeit
  IS    Typtest

Relationen liefern Ergebnisse vom Typ BOOLEAN. Die Ordnungsrelationen <, <=, >
und >= sind anwendbar auf numerische Typen, CHAR und Zeichenarrays (Strings).
Die Relationen = und # sind auch auf BOOLEAN, Mengen-, Pointer- und
Prozedurtypen anwendbar. x IN s steht fr "x ist Element von s". x mu dabei
ein Integertyp sein und s vom Typ SET. v IS T steht fr "v ist vom Typ T" und
wird Typtest genannt. Er ist anwendbar, falls 1. T eine Erweiterung des
deklarierten Typs T0 von v ist, und falls 2. v ein Variablenparameter eines
Recordtyps ist, oder v eine Pointervariable ist. Nehmen wir z.B. an, da T
eine Erweiterung von T0 darstellt und da v ein als vom Typ T0 deklarierter
Bezeichner ist, dann bestimmt das Ergebnis des Tests "v IS T", ob die aktuell
bezeichnete Variable (nicht nur vom Typ T0, sondern auch) vom Typ T ist. Der
Wert von "NIL IS T" ist nicht definiert.

Beispiele fr Ausdrcke (siehe Beispiele in Kap. 7):

  1987                    (INTEGER)
  i DIV 3                 (INTEGER)
  ~p OR q                 (BOOLEAN)
  (i+j) * (i-j)           (INTEGER)
  s - {8, 9, 13}          (SET)
  i + x                   (REAL)
  a[i+j] * a[i-j]         (REAL)
  (0<=i) & (i<100)        (BOOLEAN)
  t.key = 0               (BOOLEAN)
  k IN {i .. j-1}         (BOOLEAN)
  t IS CenterNode         (BOOLEAN)

9. Anweisungen

Anweisungen (Statements) bezeichnen Aktionen. Wir unterscheiden zwischen
elementaren und strukturierten Anweisungen. Elementare Anweisungen bestehen
nicht selber wieder aus Anweisungen. Es sind dies Wertzuweisungen,
Prozeduraufrufe, und die RETURN- und EXIT-Anweisungen. Strukturierte
Anweisungen beinhalten selbst wieder Anweisungen. Sie werden verwendet, um
Anweisungsfolgen (Statement Sequences), Bedingungen, selektive und wiederholte
Anweisungen zum Ausdruck zu bringen. Ein Anweisung kann auch leer sein; in
diesem Fall bezeichnet sie keine Aktion. Die leere Anweisung dient dem Zweck,
die Interpunktionsregeln in Anweisungsfolgen zu vereinfachen.

$       statement  =  [assignment | ProcedureCall |
$             IfStatement | CaseStatement | WhileStatement | RepeatStatement |
$             LoopStatement | WithStatement | EXIT | RETURN [expression] ].

9.1. Wertzuweisungen

Eine Wertzuweisung (Assignment) wird verwendet, um den aktuellen Wert einer
Variablen durch einen neuen Wert zu ersetzen, welcher durch einen Ausdruck
angegeben wird. Der Zuweisungsoperator wird geschrieben als ":=" und gesprochen
als "wird zu".

$       assignment =  designator ":=" expression.

Der Typ des Ausdrucks mu im Typ der Variablen eingeschlossen sein, oder er
mu den Typ der Variablen erweitern. Dabei gelten die folgenden Ausnahmen:

1. Die Konstante NIL darf Variablen eines beliebigen Pointer- oder
   Prozedurtyps zugewiesen werden.

2. Strings knnen jeder Variablen eines Zeichenarray-Typs zugewiesen werden,
   vorausgesetzt die Lnge des Strings ist kleiner als die Lnge des Arrays.

   Wird ein String s der Lnge n einem Array a zugewiesen, dann ist das
   Ergebnis a[i] = s[i] fr i = 0..n-1 und a[n] = 0X.

3. Werte vom Typ CHAR und SHORTINT drfen Variablen vom Typ BYTE zugewiesen
   werden.

Beispiele fr Wertzuweisungen (siehe auch Beispiele in Kap. 7):

  i := 0
  p := i = j
  x := i + 1
  k := log2(i+j)
  F := log2
  s := {2, 3, 5, 7, 11, 13}
  a[i] := (x+y) * (x-y)
  t.key := i
  w[i+1].ch := "A"

9.2. Prozeduraufrufe

Ein Prozeduraufruf dient dazu, eine Prozedur zu aktivieren. Der Prozeduraufruf
kann eine Liste von Parametern enthalten, welche anstelle der
korrespondierenden formalen Parameter eingesetzt werden, die bei der Definition
der Prozedur angegeben wurden (siehe Kap. 10). Der Zusammenhang zwischen
aktuellen und formalen Parametern wird durch die Position in der jeweiligen
Liste hergestellt. Es existieren zwei Arten von Parametern:
Variablenparameter und Wertparameter.Im Fall des Variablenparameter mu der
aktuelle Parameter ein Bezeichner sein, der eine Variable reprsentiert.
Bezeichnet er ein Element einer strukturierten Variablen, so wird der Selektor
ausgewertet, wenn die Substitution formaler/aktueller Parameter stattfindet,
d.h. vor der Ausfhrung der Prozedur. Ist der Parameter ein Wertparameter, dann
mu der korrespondierende aktuelle Parameter ein Ausdruck sein. Dieser
Ausdruck wird vor der Aktivierung der Prozedur evaluiert und das Ergebnis dem
formalen Parameter zugewiesen, der nun eine lokale Variable darstellt (siehe
auch 10.1).

$       ProcedureCall  =  designator [ActualParameters].

Beispiele fr Prozeduraufrufe:

  ReadInt(i)  (siehe Kap. 10)
  WriteInt(j*2+1, 6)
  INC(w[k].count)

9.3. Anweisungsfolgen

Anweisungsfolgen bezeichnen Sequenzen von Aktionen und werden durch die
entsprechenden Einzelanweisungen, getrennt durch Strichpunkte, spezifiziert.

$       StatementSequence  =  statement {";" statement}.

9.4. If-Anweisungen

$       IfStatement  =  IF expression THEN StatementSequence
$               {ELSIF expression THEN StatementSequence}
$               [ELSE StatementSequence]
$               END.

If-Anweisungen bezeichnen die bedingte Ausfhrung von Anweisungen. Der
boolesche Ausdruck vor einer bedingten Anweisung wird Guard genannt. Die
einzelnen Guards werden nacheinander in der Reihenfolge ihres Auftretens
ausgewertet, bis die Auswertung eines dieser Guards den Wert TRUE ergibt; dann
wird die damit verbundene Anweisungsfolge ausgefhrt. Ist keiner der Guards
erfllt, dann wird die nach dem Symbol ELSE stehende Anweisungsfolge ausgefhrt,
sofern eine vorhanden ist.

Beispiel:

  IF    (ch >= "A") & (ch <= "Z") THEN ReadIdentifier
  ELSIF (ch >= "0") & (ch <= "9") THEN ReadNumber
  ELSIF ch = 22X THEN ReadString
  ELSE SpecialCharacter
  END

9.5. Case-Anweisungen

Case-Anweisungen bezeichnen die Auswahl und Ausfhrung von Anweisungsfolgen
entsprechend dem Wert eines Ausdrucks. Zuerst wird der Ausdruck berechnet,
dann wird diejenige Anweisungsfolge ausgefhrt, deren Liste von Case-Labels
den berechneten Wert enthlt. Der Case-Ausdruck und alle Case-Labels mssen
vom gleichen Typ sein, der ein Integertyp oder CHAR sein mu. Case-Labels sind
Konstanten, und kein Wert darf mehr als einmal auftreten. Falls der Wert des
Ausdrucks nicht als Case-Label auftritt, so wird die Anweisungsfolge nach dem
Symbol ELSE ausgefhrt, sofern vorhanden; andernfalls liegt ein Laufzeitfehler
vor.

$       CaseStatement  =  CASE expression OF case {"|" case}
$                         [ELSE StatementSequence] END.
$       case  = [CaseLabelList ":" StatementSequence].
$       CaseLabelList  =        CaseLabels {"," CaseLabels}.
$       CaseLabels  =   ConstExpression [".." ConstExpression].

Beispiel:

  CASE ch OF
      "A" .. "Z": ReadIdentifier
    | "0" .. "9": ReadNumber
    | 22X :       ReadString
  ELSE    SpecialCharacter
  END

9.6. While-Anweisungen

While-Anweisungen bezeichnen Wiederholungen. Falls der boolesche Ausdruck
(Guard) den Wert TRUE ergibt, so wird die Anweisungsfolge ausgefhrt. Die
Berechnung des Ausdrucks und die Ausfhrung der Anweisungsfolge werden so lange
wiederholt, wie der boolesche Ausdruck das Ergebnis TRUE liefert.

$       WhileStatement  =  WHILE expression DO StatementSequence END.

Beispiele:

  WHILE j > 0 DO
    j := j DIV 2; i := i+1
  END

  WHILE (t # NIL) & (t.key # i) DO
    t := t.left
  END

9.7. Repeat-Anweisungen

Eine Repeat-Anweisung bezeichnet die wiederholte Ausfhrung einer
Anweisungsfolge, solange bis eine Bedingung erfllt ist. Die Anweisungsfolge
wird mindestens einmal ausgefhrt.

$       RepeatStatement  =  REPEAT StatementSequence UNTIL expression.

9.8. Loop-Anweisungen

Eine Loop-Anweisung bezeichnet die wiederholte Ausfhrung einer
Anweisungsfolge. Dies wird durch die Ausfhrung einer beliebigen Exit-Anweisung
innerhalb der Anweisungsfolge beendet (siehe auch 9.9).

$       LoopStatement  =  LOOP StatementSequence END.

Beispiel:

  LOOP
    IF t1 = NIL THEN EXIT END ;
    IF k < t1.key THEN t2 := t1.left; p := TRUE
    ELSIF k > t1.key THEN t2 := t1.right; p := FALSE
    ELSE EXIT
    END ;
    t1 := t2
  END

Obwohl While- und Repeat-Anweisungen durch eine LOOP-Anweisung mit einer
einzelnen Exit-Anweisung ausgedrckt werden knnen, wird die Verwendung von
While- und Repeat-Anweisungen in den sehr hufig auftretenden Situation
empfohlen, in denen der Abbruch von einer einzigen Bedingung am Anfang oder
Ende der wiederholten Anweisungsfolge abhngt. Die Loop-Anweisung ist
ntzlich, um Flle mit mehreren Abbruchbedingungen und -punkten auszudrcken.

9.9. Return- und Exit-Anweisungen

Eine Return-Anweisung besteht aus dem Symbol RETURN, mglicherweise gefolgt von
einem Ausdruck. Sie zeigt die Beendigung einer Prozedur an, bei
Funktionsprozeduren bestimmt der auf das RETURN folgende Ausdruck das Resultat.
In diesem Fall mu der Typ des Ausdrucks gleich dem Ergebnistyp sein, wie er
im Prozedurkopf angegeben wurde (siehe Kap.10).Funktionsprozeduren verlangen
die Anwesenheit einer Return-Anweisung, welche den Resultatwert angibt. Mehrere
Return-Anweisungen sind erlaubt, obwohl nur eine davon ausgefhrt wird. Bei
reinen Prozeduren impliziert das Ende des Prozedurkrpers ein Return-Anweisung.
Eine ausdrckliche Return-Anweisung erscheint daher als zustzlicher
(mglicherweise auerordentlicher) Abschlupunkt der Prozedur. Eine
Exit-Anweisung besteht aus dem Symbol EXIT. Sie bestimmt die Beendigung der
umschlieenden Loop-Anweisung. Das Programm wird mit derjenigen Anweisung
fortgesetzt, die auf die Loop-Anweisung folgt. Exit-Anweisungen sind textuell,
aber nicht syntaktisch, an diejenige Loop-Anweisung gebunden, in der sie
enthalten sind.

9.10. With-Anweisungen

Eine Pointervariable oder ein Variablenparameter mit Recordstruktur vom Typ T0
darf im Kopf einer With-Anweisung mit einem Typ T angegeben werden, der eine
Erweiterung des Typs T0 darstellt. Dann wird diese Variable innerhalb der
With-Anweisung so behandelt, als ob sie vom Typ T vereinbart wre. Die
With-Anweisung bernimmt eine Rolle hnlich dem Type Guard, nur da sie diesen
Guard ber eine Anweisungsfolge ausdehnt. Sie kann deshalb als ein regionaler
Type Guard betrachtet werden.

$       WithStatement  =  WITH qualident ":" qualident DO StatementSequence END.

Beispiel:

  WITH t: CenterNode DO name := t.name; L := t.subnode END


10. Prozedurdeklarationen

Prozedurdeklarationen bestehen aus einem Prozedurkopf (Procedure Heading) und
einem Prozedurkrper (Procedure Body). Der Prozedurkopf bestimmt den
Prozedurnamen, die formalen Parameter und den Typ des Ergebnisses (sofern
vorhanden). Der Prozedurkrper beinhaltet Deklarationen und Anweisungen. Der
Prozedurname wird am Ende der Prozedurdeklaration wiederholt.Es gibt zwei Arten
von Prozeduren, reine Prozeduren und Funktionsprozeduren. Letztere werden
durch Funktionsbezeichner als Bestandteile von Ausdrcken aktiviert und liefern
Ergebnisse, welche als Operanden in diese Ausdrcke einflieen. Reine
Prozeduren werden durch Prozeduraufrufe aktiviert. Funktionsprozeduren werden
bei der Deklaration durch die Angabe eines Ergebnistyps nach der Parameterliste
unterschieden; ihr Prozedurkrper mu eine RETURN-Anweisung enthalten, welche
das Ergebnis bestimmt.Alle Konstanten, Variablen, Typen und Prozeduren, die
innerhalb des Prozedurkrpers vereinbart werden, sind lokal zu dieser Prozedur.
Die Werte lokaler Variablen sind bei Eintritt in die Prozedur unbestimmt. Da
auch Prozeduren als lokale Objekte vereinbart werden drfen, kann man
Prozedurdeklarationen ineinander verschachteln.Zustzlich zu den formalen
Parametern und lokal vereinbarten Objekten sind auch die in der Umgebung der
Prozedur vereinbarten Objekte innerhalb der Prozedur sichtbar (mit Ausnahme
derjenigen Objekte, die den gleichen Namen tragen, wie lokale Objekte). Die
Verwendung des Prozedurnamens als Aufruf innerhalb ihrer Deklaration impliziert
eine rekursive Aktivierung der Prozedur.

$       ProcedureDeclaration  =  ProcedureHeading ";" ProcedureBody ident.
$       ProcedureHeading  =  PROCEDURE ["*"] identdef [FormalParameters].
$       ProcedureBody  =  DeclarationSequence [BEGIN StatementSequence] END.
$       ForwardDeclaration  =  PROCEDURE "^" identdef [FormalParameters].
$       DeclarationSequence  =  {CONST {ConstantDeclaration ";"} |
$           TYPE {TypeDeclaration ";"} | VAR {VariableDeclaration ";"}}
$           {ProcedureDeclaration ";" | ForwardDeclaration ";"}.

Eine Vorausdeklaration erlaubt es, sich auf eine Prozedur zu beziehen, die erst
spter im Text vollstndig vereinbart wird. Die tatschliche Deklaration, die
den Prozedurkrper bestimmt, mu die gleichen Parameter und den gleichen
Ergebnistyp (sofern vorhanden) wie die Vorausdeklaration besitzen, und mu im
gleichen Gltigkeitsbereich liegen. Ein dem PROCEDURE-Symbol folgender Stern
ist ein Hinweis an den Compiler, der anzeigt, da die Prozedur als Parameter
verwendbar ist und Variablen kompatibler Prozedurtypen zugewiesen werden kann.

10.1. Formale Parameter

Formale Parameter sind Namen, welche die aktuellen Parameter einer Prozedur
reprsentieren. Der Zusammenhang zwischen aktuellen und formalen Parametern
wird beim Aufruf der Prozedur hergestellt. Es gibt zwei Arten von Parametern,
Wertparameter (Value Parameters) und Variablenparameter (Variable Parameters).
Die jeweilige Art wird in der formalen Parameterliste angegeben. Wertparameter
stehen fr lokale Variablen, denen das Ergebnis der Auswertung des
korrespondierenden aktuellen Parameter als Anfangswert zugewiesen wird.
Variablenparameter entsprechen aktuellen Parametern, welche Variablen sind, und
reprsentieren diese. Variablenparameter werden durch das Symbol VAR
gekennzeichnet, Wertparameter durch dessen Abwesenheit. Funktionsprozeduren
ohne Parameter mssen eine leere Parameterliste besitzen und mssen mit einem
Funktionsbezeichner aufgerufen werden, dessen aktuelle Parameterliste ebenfalls
leer ist. Formale Parameter sind lokal zur Prozedur, d.h. ihr
Gltigkeitsbereich ist der Text der Prozedurdeklaration.

$       FormalParameters =  "(" [FPSection {";" FPSection}] ")" [":" qualident].
$       FPSection  =  [VAR] ident  {"," ident} ":" FormalType.
$       FormalType  =  {ARRAY OF} qualident.

Der Typ jedes formalen Parameters wird in der Parameterliste angegeben. Bei
Variablenparametern mu er identisch dem Typ des entsprechenden aktuellen
Parameters sein, auer im Fall eines Records; hier mu er ein Basistyp des
Typs des entsprechenden aktuellen Parameters sein. Bei Wertparametern gelten
die Regeln der Zuweisungskompatibilitt (siehe 9.1). Wird ein Parametertyp
angegeben als ARRAY OF Tdann nennt man den Parameter einen Open Array Parameter
und der entsprechende aktuelle Parameter darf irgend ein Array vom Elementtyp T
sein.Im Falle eines Parameters vom formalen Typ BYTE darf der entsprechende
aktuelle Parameter auch vom Typ CHAR oder SHORTINT sein. Ist der Typ des
formalen Variablenparameters ein ARRAY OF BYTE, dann sind aktuelle Parameter
jeden beliebigen Typs zugelassen. Spezifiziert der formale Parameter einen
Prozedurtyp, dann mu der korrespondierende aktuelle Parameter entweder eine
auf der Stufe 0 vereinbarte Prozedur sein, oder eine Variable (oder ein
Parameter) von diesem Prozedurtyp sein. Eine vordefinierte Prozedur ist an
dieser Stelle nicht erlaubt. Das Ergebnis einer Prozedur darf weder ein Record
noch ein Array sein.

Beispiele fr Prozedurdeklarationen:

  PROCEDURE ReadInt(VAR x: INTEGER);
    VAR i : INTEGER; ch: CHAR;
  BEGIN i := 0; Read(ch);
     WHILE ("0" <= ch) & (ch <= "9") DO
         i := 10*i + (ORD(ch)-ORD("0")); Read(ch)
     END ;
     x := i
  END ReadInt

  PROCEDURE WriteInt(x: INTEGER);  (* 0 <= x < 10^5 *)
    VAR i: INTEGER;
        buf: ARRAY 5 OF INTEGER;
  BEGIN i := 0;
     REPEAT buf[i] := x MOD 10;  x := x DIV 10;  INC(i) UNTIL x = 0;
     REPEAT DEC(i); Write(CHR(buf[i] + ORD("0"))) UNTIL i = 0
  END WriteInt

  PROCEDURE log2(x: INTEGER): INTEGER;
    VAR y: INTEGER;  (*assume x>0*)
  BEGIN y := 0;
     WHILE x > 1 DO x := x DIV 2; INC(y) END ;
     RETURN y
  END log2

10.2. Vordefinierte Prozeduren

Die folgende Tabelle zeigt die vordefinierten Prozeduren auf. Einige davon
sind generische Prozeduren, d.h. sie sind auf mehrere Operandentypen anwendbar.
v steht fr eine Variable, x und n stehen fr Ausdrcke und T fr irgendeinen
Typ.

Funktionsprozeduren:

Name         Argumenttyp       Ergebnistyp   Funktion

ABS(x)       numerischer Typ   Typ von x     Absolutwert
ODD(x)       Integertyp        BOOLEAN       x MOD 2 = 1
CAP(x)       CHAR              CHAR          entsprechender Grobuchstabe
ASH(x, n)    x, n: Integertyp  LONGINT       x * 2n, arithmetischer Shift
LEN(v, n)    v: Array          LONGINT       Lnge von v in Dimension n
             n: Integertyp                   LEN(v) ist quivalent zu
                                             LEN(v, 0)
SIZE(T)      beliebiger Typ    Integertyp    Anzahl der von T beanspruchten Bytes
MAX(T)       T = Grundtyp      T             Maximalwert des Typs T
             T = SET           INTEGER       grtes Element der Menge
MIN(T)       T = Grundtyp      T             Minimalwert des Typs T
             T = SET           INTEGER       0

Prozeduren zur Typkonversion:

Name         Argumenttyp       Ergebnistyp   Funktion

ORD(x)       CHAR, BYTE        INTEGER       Ordinalzahl von x
CHR(x)       Integertyp, BYTE  CHAR          Zeichen mit dem Ordinalzahl x
SHORT(x)     LONGINT           INTEGER       Identitt
             INTEGER           SHORTINT
             LONGRAL           REAL          (Beschneidung des Wertes mglich)
LONG(x)      SHORTINT          INTEGER       Identitt
             INTEGER           LONGINT
             REAL              LONGREAL
ENTIER(x)    reeller Typ       LONGINT       grte Integerzahl <= x
                                             Anmerkung: ENTIER(i/j) = i DIV j

Reine Prozeduren:

Name         Argumenttyp                     Funktion

INC(v)       Integertyp                      v := v+1
INC(v, x)    Integertyp                      v := v+x
DEC(v)       Integertyp                      v := v-1
DEC(v, x)    Integertyp                      v := v-x
INCL(v, x)   v: SET; x: Integertyp           v := v + {x}
EXCL(v, x)   v: SET; x: Integertyp           v := v - {x}
COPY(x, v)   x: Zeichenarray, String         v := x
             v: Zeichenarray
NEW(v)       Pointertyp                      Speicher fr v^ reservieren
HALT(x)      Integerkonstante                Programmlauf beenden

Der zweite Parameter von INC und DEC kann entfallen, dann wird jeweils der Wert
1 verwendet. Die Interpretation des Parameters x in HALT(x) wird der
jeweiligen Systemimplementation berlassen.


11. Module

Ein Modul besteht aus einer Sammlung von Konstanten-, Typen-, Variablen- und
Prozedurdeklarationen und aus einer Folge von Anweisungen zur Initialisierung
von Variablen. Ein Modul besteht typischerweise aus einem Text, der als
Einheit kompilerbar ist.

$       module  = MODULE ident ";"  [ImportList] DeclarationSequence
$           [BEGIN StatementSequence] END ident "." .
$       ImportList  =  IMPORT import {"," import} ";" .
$       import  =  ident [":=" ident].

Die Importliste gibt diejenigen Module an, deren Klient das aktuelle Modul ist.
Wird ein Name x von einem Modul M exportiert, und wird M in der Importliste
eines anderen Moduls aufgefhrt, dann wird x dort als M.x referenziert. Falls
in der Importliste die Form "M := M1" verwendet wird, so wird auf ein im Modul
M1 deklariertes Objekt x als M.x zugegriffen.Namen, die in einem Klientenmodul
sichtbar sein sollen, also auerhalb des vereinbarenden Moduls, mssen bei
ihrer Deklaration mit einer Exportmarke versehen werden. Die Anweisungsfolge
nach dem Symbol BEGIN wird ausgefhrt, wenn das Modul geladen wird. Einzelne
(parameterlose) Prozeduren knnen anschlieend vom System aktiviert werden,
sie dienen als Kommandos (Commands).

Beispiel:

        MODULE Out;
        (*exported procedures: Write, WriteInt, WriteLn*)
        IMPORT Texts, Oberon;

        VAR W: Texts.Writer;

        PROCEDURE Write*(ch: CHAR);
        BEGIN
          Texts.Write(W, ch)
        END;

        PROCEDURE WriteInt*(x, n: LONGINT);
        VAR
          i: INTEGER;
          a: ARRAY 16 OF CHAR;
        BEGIN
          i := 0;
          IF x < 0 THEN Texts.Write(W, "-"); x := -x END ;
          REPEAT a[i] := CHR(x MOD 10 + ORD("0")); x := x DIV 10; INC(i) UNTIL x = 0;
          REPEAT Texts.Write(W, " "); DEC(n) UNTIL n <= i;
          REPEAT DEC(i); Texts.Write(W, a[i]) UNTIL i = 0
        END WriteInt;

        PROCEDURE WriteLn*;
        BEGIN
          Texts.WriteLn(W);
          Texts.Append(Oberon.Log, W.buf)
        END WriteLn;

        BEGIN
          Texts.OpenWriter(W)
        END Out.


Anhang: Das Modul SYSTEM

Das Modul SYSTEM enthlt bestimmte Prozeduren, welche notwendig sind, um
"low-level"-Operationen zu programmieren, die sich direkt auf Objekte beziehen,
die fr einen bestimmten Computer oder ein spezielles Betriebssystem spezifisch
sind. Dies beinhaltet beispielsweise Mglichkeiten zum Zugriff auf
Peripheriegerte, die direkt von diesem Computer kontrolliert werden und
Mglichkeiten, die Typkompatibilittsregeln zu durchbrechen, die sonst aufgrund
der Sprachdefinition aufgezwungen werden. Es wird empfohlen, die Verwendung
des Moduls SYSTEM auf spezielle Module (sogenannte Low-Level-Module) zu
beschrnken. Derartige Module sind naturgem nicht portabel, aber leicht am
Namen SYSTEM in der Importliste erkennbar. Die folgenden Spezifikationen
gelten fr die ETH-Implementation fr den NS32000-Prozessor. Die im Modul
SYSTEM enthaltenen Prozeduren sind in den folgenden Tabellen aufgefhrt.
Sie entsprechen einzelnen Prozessorinstruktionen, die als Inline-Code
kompiliert werden. Fr weitere Details wird der Leser auf das
Prozessorhandbuch verwiesen. v steht fr eine Variable, x, y, a und n stehen
fr Ausdrcke und T steht fr einen Typ.

Funktionsprozeduren:

Name      Argumenttyp             Ergebnistyp     Funktion

ADR(v)    beliebig                LONGINT         Adresse der Variablen v
BIT(a, n) a: LONGINT              BOOLEAN         Mem[a][n]
          n: Integertyp
CC(n)     n: Integerkonstante     BOOLEAN         Condition Code n (0 <= n < 16)
LSH(x,

LSH(x,n)  x, n: Integertyp        LONGINT         logischer Shift
ROT(x,n)  x, n: Integertyp        LONGINT         Rotation
VAL(T,x)  T, x: beliebiger Typ    T               x interpretiert als vom Typ T


Reine Prozeduren:

Name            Argumenttyp               Funktion

GET(a, v)       a: LONGINT;               v := Mem[a]
                v: beliebiger Grundtyp
PUT(a, x)       a: LONGINT;               Mem[a] := x
                x: beliebiger Grundtyp
MOVE(a0, a1, n) a0, a1, n: Integertyp     Mem[a1+i] := Mem[a0+i], i = 0..n-1
NEW(v, n)       v: beliebiger Pointertyp  reserviert einen Speicherblock von n
                n: Integertyp             Bytes und bergibt seine Adresse an v


bersetzung aus dem Englischen: Michael Franz

