home *** CD-ROM | disk | FTP | other *** search
/ Global Amiga Experience / globalamigaexperience.iso / compressed / development / clusterdemo.dms / clusterdemo.adf / Sprachreport.lha / Cluster_1.4_Sprachreport next >
Text File  |  1993-03-08  |  59KB  |  1,771 lines

  1.  
  2.  Sprachreport für Cluster V1.4
  3. -------------------------------
  4.  
  5. [redigierte deutsche Version vom 25. 11. 91]
  6.  
  7.  
  8. C.1     Grundlegende Sprachelemente
  9.  
  10. Die Sprache Cluster basiert auf dem ASCII Zeichenstandard. Verwendet werden
  11. die großen und kleinen Buchstaben des Standardalphabets, sowie die üblichen
  12. Sonderzeichen. Cluster ist case-sensitive, das heißt, es wird zwischen
  13. großen und kleinen Buchstaben unterschieden. In der Tradition von Algol,
  14. Pascal, C und Modula ist Cluster formatfrei, d.h. zwischen zwei Symbolen
  15. der Sprache dürfen beliebig viele Leerzeichen und Zeilenvorschübe enthalten
  16. sein.
  17.  
  18. Cluster ist eine Sprache, die für einen Singlepasscompiler zugeschnitten
  19. ist. Dies hat zur Folge, daß mit Ausnahme von Pointerzielen alle Bezeichner
  20. vor ihrer Verwendung definiert werden müssen.
  21.  
  22. Die Sprachdefinition wird in EBNF angegeben.
  23.  
  24. $$ letter       ::=     a|b|c|...X|Y|Z
  25. $$ digit        ::=     0|1|2|3|4|5|6|7|8|9
  26. $$ hexdigit     ::=     digit|A|B|C|D|E|F
  27.  
  28.  
  29. C.1.1   Bezeichner
  30.  
  31. Bezeichner bestehen in Cluster aus großen und kleinen Buchstaben, Zahlen
  32. und dem Unterstrich "_". Sie müssen immer mit einem Buchstaben beginnen.
  33.  
  34. $$ ident        ::=     letter{letter|digit|"_"}
  35.  
  36. Beispiele für richtige Bezeichner:
  37.  
  38. Cluster, Text2, Text_2, aus, Ein_Text
  39.  
  40. Falsch wären:
  41.  
  42. 2Pi, _LVO, Ein Text
  43.  
  44. Großschreibungen im Wort und der Unterstrich können dazu dienen, die
  45. Bezeichner lesbarer zu gestalten.
  46.  
  47. Manche Bezeichner müssen noch qualifiziert werden:
  48.  
  49. $$ qualident    ::=     {ident.}ident
  50.  
  51. Folgende Bezeichner sind vorbelegt:
  52.  
  53. SHORTCARD       CARDINAL        LONGCARD        SHORTINT
  54. INTEGER         LONGINT         FFP             REAL
  55. LONGREAL        BOOLEAN         CHAR            ANYTYPE
  56. ANYPTR          STRING          SAMEPTR
  57.  
  58. TRUE            FALSE           NIL
  59.  
  60. INC     DEC     INCL    EXCL    FLIP    CAST    ABS     CAP
  61. ODD     ACOS    ASIN    ATAN    COS     COSH    EXP     LN
  62. LOG     SIN     SINH    SQRT    TAN     TANH    CEIL    FLOOR
  63. SETREG  REG     SHL     SHR     LMUL    LDIV    EVEN    ROL
  64. ROR     UNI     SEC     HALT    HALT2   PUSH    POP     SUCC
  65. PRED    ASSERT  ASSERT2 RAISE   RAISE2  ALLOC_RESULT
  66.  
  67.  
  68. C.1.2   Einfache Konstanten
  69.  
  70. Ganzzahlkonstanten können binär, dezimal, hexadezimal oder zu einer
  71. beliebigen Basis angegeben werden. Beginnt eine Konstante mit einer Zahl,
  72. wird sie als dezimal interpretiert. Ein Dollarzeichen "$" leitet eine
  73. Hexzahl, ein Prozentzeichen "%" eine Binärzahl ein. Zahlen zu einer
  74. beliebigen Basis haben die Form "Basis:Wert"
  75.  
  76. $$ intconst     ::=     (digit{digit})|("$"{hexdigit})|("%"{bindigit})|
  77.             (digit{digit}:hexdigit{hexdigit})
  78.  
  79. Folgende Konstanten haben zum Beispiel den selben Wert:
  80.  
  81. 107, $6B, %1101011, 16:6B 4:1223
  82.  
  83. Realkonstanten enthalten einen Punkt und bei Bedarf eine Exponentenangabe.
  84. Diese wird durch ein "E" in der Zahl begonnen. Danach kann bei Bedarf ein
  85. "-" folgen.
  86.  
  87. $$ realconst    ::=     digit{digit}"."{digit}["E"["-"]digit{digit}]
  88.  
  89. Folgende Konstanten haben z.B. den selben Wert:
  90.  
  91. 127.64, 1.2764E2, 12764.E-2
  92.  
  93. Zeichenkonstanten werden durch ein kaufmännisches Und "&", mit
  94. nachfolgendem ASCII-Wert in Dezimalschreibweise angegeben. Alternativ kann
  95. auch das Zeichen in Anführungstrichen gegeben sein.
  96.  
  97. $$ charconst    ::=     ("&"digit{digit})|("char")
  98.  
  99. Beispiele:
  100.  
  101. "A", "0", &13, &10
  102.  
  103.  
  104. C.1.3   Zeichenkettenkonstanten
  105.  
  106. Zeichenketten werden als Folge von ASCII-Zeichen in Anführungsstrichen
  107. angegeben. Dabei ist eine Konkatenation erlaubt, um im Text Sonderzeichen
  108. verwenden zu können, oder eine Konstante über mehrere Zeilen erstrecken zu
  109. lassen.
  110.  
  111. $$ strconst     ::=     ("{char}")|charconst
  112. $$ stringconst  ::=     strconst{"+"strconst}
  113.  
  114. Beispiele:
  115.  
  116. "Haus", "Dies ist ein Text", "X", "Return"+&10+"neue Zeile"+&10
  117.  
  118. Der Typ einer Zeichenkettenkonstante ist der Typ STRING. Zur kompatibilität
  119. mit Sprachen ohne expliziten Stringtyp, wird einer Zeichenkettenkonstante
  120. ein unsichtbares ASCII-NULL (&0) angehängt.
  121.  
  122.  
  123. C.1.4   Geschützte Bezeichner und Symbole
  124.  
  125. In Cluster sind viele Sprachsymbole durch Bezeichner gegeben. Diese
  126. Bezeichner bestehen nur aus großen Buchstaben, und werden durch den Editor
  127. zusätzlich Fett hervorgehoben.
  128.  
  129. Folgende Symbole werden in Cluster verwendet:
  130.  
  131. "       #       $       %       &    (       )       (*      *)      +
  132. +^      ,       -       -^      .       ..      /       :       ;       <
  133. <=      =       >       >=      [       ]       ^       {       }
  134.  
  135. AND     AND_IF  AND_WHILE       ARRAY   AS      BCPLPTR BEGIN   BY
  136. CLASSPTR        CLOSE   CONST   DEFINITION      DIV     DO
  137. ELSE    ELSIF   END     EXCEPT  EXIT    FOR     FORGET  FORWARD
  138. FROM    GROUP   HIDDEN  IF      IMPLEMENTATION  IMPORT  IN      KEY
  139. LIBRARY LOOP    MOD     MODULE  NOT     OF      OR      OR_IF
  140. OR_WHILE        POINTER PROCEDURE       RECORD  REF     REPEAT  RETURN
  141. SET     SHL     SHR     STATIC  TAGS    THEN    TO      TRACK   TRY
  142. TYPE    UNTIL   VAR     WHILE   WITH
  143.  
  144.  
  145. C.1.5   Kommentare
  146.  
  147. Kommentare können als (* <Kommentartext> *) angegeben werden. Sie können
  148. geschachtelt werden, und zwischen zwei beliebigen Symbolen liegen. Durch
  149. einen snkrechten Strich "|" kann eine Zeile bzw. der Rest der Zeile nach
  150. dem Strich zum Kommentar erklärt werden.
  151.  
  152.  
  153. C.2     Typen
  154.  
  155. Cluster ist eine streng und statisch getypte Sprache, das heißt, bei allen
  156. Operationen werden die Typen beachtet. Die Typüberprüfung findet soweit
  157. möglich während der Compilierung statt.
  158.  
  159. Eine Typausdruck hat folgendes Format:
  160.  
  161. $$ simpletype   ::=     qualident|("["expression[".."expression]"]")|
  162.                 ("("ident[:=expression]{,ident[:=expression]}")")
  163. $$ varlist      ::=     ident{,ident}":"typeexpress
  164. $$ elements     ::=     expression[".."expression]
  165. $$ elemlist     ::=     elements{","elements}
  166. $$ recordtype   ::=     varlist|
  167.                 (IF KEY [ident]":"simpletype
  168.                 {OF elemlist THEN {varlist}} END)
  169. $$ tagtype      ::=     ident [:= expression] : typeexpress
  170. $$ paradeclar   ::=     [VAR|REF] ident [IN expression]
  171.                 {,ident [IN expression]}:qualident
  172. $$ formalparams ::=     ["("[paradeclar{;paradeclar}]")"[":"qualident]
  173. $$ typeexpress  ::=     ident|simpletype|
  174.                 (ARRAY [simpletype{,simpletype}] OF typeexpress)|
  175.                 (RECORD [OF qualident] recordtype{;recordtype})|
  176.                 (SET OF simpletype)|
  177.                 (POINTER|CLASSPTR|BCPLPTR TO typeexpress)|
  178.                 (ident"("expression")")|
  179.                 (PROCEDURE formalparams)|
  180.                 (TAG [OF qualident] tagtype{;tagtype})
  181.  
  182. Eine Typdefiniton hat folgendes Format:
  183.  
  184. $$ typedef      ::=     TYPE {ident"="typeexpress}
  185.  
  186. Dabei wird einem Bezeichner ein Typ zugeordnet, der dann über diesen
  187. Bezeichner weiter verwendet werden kann.
  188.  
  189. C.2.1   Einfache Typen
  190.  
  191. C.2.1.1 Zählbare Typen
  192.  
  193. SHORTINT        -128..127
  194. INTEGER         -32768..32767
  195. LONGINT         -2147483648..2147483648
  196.  
  197. SHORTCARD       0..255
  198. CARDINAL        0..65535
  199. LONGCARD        0..4294967296
  200.  
  201. CHAR            &0..&255 Zeichen
  202.  
  203. BOOLEAN         TRUE , FALSE
  204.  
  205. Aufzählungstypen sind Typen, die eine feste Anzahl von Werten
  206. repräsentieren. Diese sind durch Konstanten gegeben, die von Null an aufwärts
  207. numeriert sind. Ein Aufzählungstyp wird durch eine Aufzählung der Elemente
  208. in runden Klammern definiert.
  209.  
  210. Beispiel:
  211. Obst=(Apfel,Banane,Kirsche) oder Farben=(rot,gruen,blau)
  212.  
  213. Die Numerierung der Elemente eines Aufzählungstyps kann unterbrochen und
  214. mit einem neuen Wert fortgesetzt werden:
  215.  
  216. FileAccess=(readWrite=1004,readOnly=1005,newFile=1006);
  217.  
  218. oder auch:
  219.  
  220. FileAccess=(readWrite=1004,readOnly,newFile);
  221.  
  222. Verschiedene Aufzählungstypen dürfen die selben Bezeichner für ihre
  223. Elemente benutzen z.B.:
  224.  
  225. Hardware:
  226.  
  227. TYPE IntFlags = (tbe,dskblk,softint,ports,copper ... );
  228.  
  229. Exec:
  230.  
  231. TYPE
  232.   NodeType = (unknown,task,interrupt,device,msgport,message,
  233.           freeMsg,replyMsg,resource,library,memory,
  234.           softint,font ... );
  235.  
  236. TYPE
  237.   MsgPortAction = (signal,softint,ignore);
  238.  
  239. In allen drei Typen ist ein Element namens "softint" enthalten. Der
  240. Compiler versucht so weit ihm dies möglich ist, das richtige Element zu
  241. finden, ist ihm dies nicht eindeutig möglich, meldet er einen Fehler. Das
  242. Element muß dann über seinen Typen qualifiziert werden:
  243.  
  244.   NodeType.softint
  245.  
  246. Unterbereichstypen repräsentieren eine Untermenge der Elemente eines
  247. einfachen Typs. Die Grenzen werden in eckigen Klammern getrennt durch ".."
  248. gegeben. Wird nur ein Wert angegeben, bedeutet dies einen Unterbereich von
  249. null an mit sovielen Elementen.
  250.  
  251. Beispiel:
  252.  
  253. [1..10], [-200..200], ["A".."Z"], [10], [gruen..blau]
  254.  
  255.  
  256. C.2.1.2 Überabzählbare Typen
  257.  
  258. Cluster bietet drei Typen, die die Menge der Reellen Zahlen repräsentieren.
  259. Diese Typen sind unvollständig, da der Speicherplatz eines Rechners
  260. beschränkt ist.
  261.  
  262. FFP, REAL        7 geltende Stellen, Exponent bis +/- 19
  263. LONGREAL        16 geltende Stellen, Exponent bis +/- 304
  264.  
  265. REAL-Zahlen sind IEEE-single-precision Zahlen. Da diese erst ab 2.0 bzw.
  266. mit einem mathematischen Coprozessor verfügbar sind, können sie auf einem
  267. normalen Rechner unter 1.3 nicht genutzt werden.
  268. Auf einem Amiga ohne FPU sind FFP-Zahlen schneller als REAL-Zahlen;
  269. besitzt man jedoch eine FPU, sind REAL-Zahlen schneller.
  270.  
  271.  
  272. C.2.1.3 Mengentypen
  273.  
  274. Mengentypen sind Typen von Mengen über einer vorgegebenen Grundmenge. Diese
  275. muß sich aus Elementen eines zählbaren Typs zusammensetzen. Die Maximale
  276. Anzahl der Elemente der Grundmenge ist 32. Ein Mengentyp wird definiert
  277. durch "SET OF".
  278.  
  279. Beispiel:
  280.  
  281. BITSET=SET OF [0..15], Farbset=SET OF Farben
  282.  
  283.  
  284. C.2.2   Komplexe Typen
  285.  
  286. Komplexe Typen sind in Cluster Arrays, Records, Tags und Strings.
  287.  
  288.  
  289. C.2.2.1 Arrays
  290.  
  291. Ein Array ist eine Zusammenfassung mehrerer Elemente eines Typs zu einem
  292. neuen, wobei jedes Element eindeutig über einen Index (oder mehrere
  293. Indices) bezeichnet wird. Ein Array besitzt einen Unterbereichstypen als
  294. Indextyp und einen Basistyp.
  295.  
  296. Beispiel:
  297.  
  298. Farbwerte = ARRAY Farben OF [0..15];
  299.  
  300. Mehrdimensionale Arrays sind Arrays von Arrays:
  301.  
  302. ARRAY T1 OF ARRAY T2 OF ARRAY T3 .. OF T
  303.  
  304. ist gleichbedeutend mit
  305.  
  306. ARRAY T1,T2,T3... OF T
  307.  
  308. Matrix = ARRAY [1..3],[1..3] OF REAL;
  309.  
  310. Es ist auch möglich Arrays über einen Typen zu definieren, dessen
  311. Obergrenze nicht bekannt ist. Diese offenen Arrays haben immer INTEGER als
  312. Indextyp.
  313.  
  314. TYPE
  315.   Vector = ARRAY OF REAL;
  316.  
  317. Sie können nur auf vier Arten verwendet werden, als Ziel eines Pointers,
  318. als Parameter einer Prozedur, als Typ einer Konstanten oder bei der
  319. Definition eines geschlossenen Typen. Wird ein offenes Array als
  320. Pointerziel verwendet, sollte dafür ein CLASSPTR verwendet werden, da nur
  321. so eine Bereichsüberprüfung möglich ist. Die Grenzen eines existierenden
  322. offenen Arrays können über Attribute ermittelt werden.
  323.  
  324. TYPE
  325.   Vector3 = Vector(3);
  326.   VecPtr  = CLASSPTR TO Vector;
  327.  
  328. CONST
  329.   IntArray = ARRAY OF INTEGER:(1,2,3,4);
  330.  
  331. Will man ein solches offenes Array allozieren, trägt man zuerst den RANGE
  332. des Arrays ein, und ruft dann New auf:
  333.  
  334. VAR
  335.   UserVec  : VecPtr;
  336.  
  337. BEGIN
  338.   UserVec'RANGE:=6;
  339.   New(UserVec);
  340.  
  341.  
  342. C.2.2.2 Records
  343.  
  344. Ein Record ist eine Zusammenfassung mehrerer Elemente verschiedener Typen
  345. zu einem neuen, wobei jedes Element über einen zusätzlichen Namen
  346. angesprochen wird.
  347.  
  348. TYPE
  349.   Adresse = RECORD
  350.           namen,
  351.           vornamen : STRING(20);
  352.           alter    : INTEGER;
  353.         END;
  354.  
  355. Werden in einem Record nicht alle Felder gleichzeitig benötigt, können
  356. diese übereinandergelegt werden. Dies spart Speicherplatz. Man spricht in
  357. diesem Fall von einem varianten Record.
  358.  
  359. TYPE
  360.   Geschlecht = (maennlich,weiblich);
  361.   Person     = RECORD
  362.          namen,
  363.          vornamen : STRING(20);
  364.          IF KEY geschl : Geschlecht
  365.            OF maennlich THEN dienstgrad   : STRING(20);
  366.            OF weiblich  THEN maedchenname : STRING(20);
  367.          END;
  368.            END;
  369.  
  370. (Entschuldigen Sie dieses chauvinistische Beispiel, aber es ist nicht von
  371. mir.)
  372.  
  373. Records lassen sich um weitere Elemente erweitern, dabei bleiben alle
  374. vorherigen Felder erhalten. Ein Record, der sich auf einen bereits
  375. bestehenden gründet, wird durch RECORD OF eingeleitet.
  376.  
  377. Ein Beispiel aus Exec:
  378.  
  379. MinNodePtr = POINTER TO MinNode;
  380. MinNode    = RECORD
  381.            succ,pred : MinNodePtr;
  382.          END;
  383.  
  384. Node       = RECORD OF MinNode
  385.            type : NodeTypes;
  386.            pri  : SHORTINT;
  387.            name : SysSTringPtr;
  388.          END;
  389.  
  390. Message    = RECORD OF Node
  391.            replyPort : MsgPortPtr;
  392.            length    : CARDINAL;
  393.          END;
  394.  
  395. IORequest  = RECORD OF Message
  396.            device  : DevicePtr;
  397.            unit    : UnitPtr;
  398.            command : CARDINAL;
  399.            flags   : IOFlagSet;
  400.            error   : SHORTCARD;
  401.          END;
  402.  
  403. So lassen sich Hierarchien von Typen aufbauen, die nach unten
  404. zuweisungskompatibel sind.
  405.  
  406.  
  407. C.2.2.3 Strings
  408.  
  409. Ein String in Cluster hat folgendes Format:
  410.  
  411. STRING = RECORD
  412.        len  : INTEGER;
  413.        data : ARRAY OF CHAR;
  414.      END;
  415.  
  416. Es gibt wie bei Arrays offene und feste Strings. Für Variablen dürfen nur
  417. Stringtypen mit fester Maximallänge verwendet werden.
  418.  
  419. String30 = STRING(30);
  420.  
  421. Offene Strings unterliegen den selben Beschränkungen wie offene Arrays.
  422.  
  423. Jeder String hat zwei Endkenzeichen: die in len gegebene Länge und ein
  424. Nullbyte nach dem letzten Zeichen. Dieses Nullbyte geht nich in len ein,
  425. wohl aber in die maximale Länge des Strings.
  426.  
  427.  
  428. C.2.2.4 Tag-Typen
  429.  
  430. Ein Tag Element besteht immer aus zwei Elementen. Das erste Element enthält
  431. einen TAG-Wert, der aussagt, welchen Typ das zweite Element hat. Dieses
  432. zweite Feld ist maximal vier Bytes groß. Hierbei ist ein Erben von bereits
  433. bestehenden Tag-Typen möglich.
  434.  
  435. Beispiel:
  436.  
  437.   ScreenTags = TAGS OF StdTags
  438.          width  = $80000020 : INTEGER;
  439.          height             : INTEGER;
  440.          depth              : INTEGER;
  441.          name               : POINTER TO STRING;
  442.          flags              : ScreenFlagSet
  443.            END;
  444.  
  445. Tags werden durch das Amiga-OS 2.0 häufig verwendet und zwar in der Form
  446. von TAG-Listen, das sind (nach Bedarf auch verkettete) Arrays von Tag-
  447. Typen.
  448.  
  449. Beispiel:
  450.  
  451.   ScreenTagList = ARRAY OF ScreenTags;
  452.  
  453. Um nun einen Screen zu öffnen, muß eine Tag-Liste angegeben werden, in der
  454. die Elemente aufgeführt sind, die sich von den Werten eines Standardscreens
  455. unterscheiden.
  456.  
  457.   OpenScreenTagList(ScreenTagList:(width  : 320,
  458.                    height : 256,
  459.                    name   : "Name"'PTR));
  460.  
  461. Die Verwendung von Tags beschränkt sich momentan noch auf derartige
  462. Konstanten.
  463.  
  464.  
  465. C.2.3   Zeigertypen
  466.  
  467. Es gibt in Cluster drei Zeigertypen: normale Zeiger (POINTER), Zeiger für
  468. offene Typen (CLASSPTR) und Zeiger, die zu BCPL kompatibel sind (BCPLPTR).
  469.  
  470. Beispiel:
  471.  
  472. TYPE
  473.   NodePtr = POINTER TO Node;
  474.  
  475.   Node    = RECORD
  476.           prev,
  477.           next  : NodePtr;
  478.           key   : INTEGER;
  479.         END;
  480.  
  481. Es existiert ein Pointertyp, der zu allen Pointertypen und zu LONGINT
  482. kompatibel ist: ANYPTR. Dieser Pointer hat kein eigentliches Ziel. Zu
  483. diesem Typ gibt es die Konstante NIL, die eine nicht vorhandene Adresse
  484. bedeutet.
  485.  
  486. Neben diesen allgemeineren Pointertypen exisitiert noch ein Typ, der
  487. speziell zum Gebrauch bei der Vererbung von Records eingeführt wurde,
  488. der SAMEPTR. Ein SAMEPTR kann nur als Element eines Records verwendet
  489. werden, er stellt einen Zeiger auf den Typen dar, den der aktuelle Record
  490. bildet.
  491.  
  492. Beispiel:
  493.  
  494. TYPE
  495.   Node    = RECORD
  496.           prev,
  497.           next  : SAMEPTR;
  498.         END;
  499.   Node2   = RECORD OF Node
  500.           data  : INTEGER
  501.         END;
  502.  
  503. Die Felder prev und next haben in Records des Typs Node den Typ POINTER TO
  504. Node, in Records des Typs Node2 aber den Typen POINTER TO Node2. Der Record
  505. bleibt trotzdem nach unten kompatibel, da ja ein POINTER TO Node2 auch ein
  506. Nachfahre von POINTER TO Node darstellt.
  507. Der Vorteil ist aber, daß Ausdrücke der Form Node2^.next^.data möglich
  508. sind, was bei der Verwendung des Typs POINTER TO Node anstatt eines
  509. SAMPETRs nicht möglich wäre.
  510.  
  511.  
  512. C.2.4   Opake-Typen
  513.  
  514. Opake Typen sind Typen, die in einem Definitions-Modul angegeben, aber erst
  515. im Implementations-Modul definiert werden. Dies ermöglicht das
  516. Geheimnissprinzip. Ein opaker Typ darf nur stellvertretend für einen
  517. Pointer stehen.
  518.  
  519. DEFINITION MODULE <name>
  520.  
  521. TYPE
  522.   List  = HIDDEN;
  523.  
  524. END <name>.
  525.  
  526. IMPLEMENTATION MODULE <name>
  527.  
  528. TYPE
  529.   List  = POINTER TO
  530.         RECORD
  531.           first,
  532.           prev   : NodePtr;
  533.         END;
  534.  
  535. END <name>.
  536.  
  537.  
  538. C.2.5   Prozedurtypen
  539.  
  540. Prozeduren haben in Cluster ebenfalls einen Typ. Dieser ist durch die
  541. Übergabeparameter gegeben (siehe Prozedurdeklaration).
  542.  
  543.  
  544. C.3     Variablendeklaration
  545.  
  546. Alle Variablen, die in Cluster benutzt werden, haben einen festen Typ, und
  547. müssen vor ihrer Benutzung deklariert werden.
  548.  
  549. $$ vardeclar      ::= ident [(IN expression)|STATIC]
  550.                     {,ident [(IN expression)|STATIC]}
  551.                     (([:typeexpress] := expression)|(:typeexpress))
  552. $$ vardeclaration ::=VAR [vardeclar{;vardeclar}]
  553.  
  554. Das Schlüsselwort IN gibt an, daß die Variable in ein Register zu legen
  555. ist. Dies gilt nur für den unmittelbaren Sichtbarkeitsbereich der
  556. Variablen, nicht jedoch für weiter innen liegende.
  557.  
  558. Beispiel:
  559.  
  560. VAR i,j     : INTEGER;
  561.     c       : CHAR;
  562.     k IN D2 : INTEGER;
  563.     l       : INTEGER := 2;
  564.     n       := NewScreen:(width=...);
  565.  
  566. Die Registernamen D0 bis A7 sind im Modul SYSTEM als Aufzählungstyp 'Regs'
  567. definiert.
  568.  
  569. Durch die Initialisierung ":=" kann der Variable bei ihrer Deklaration ein
  570. Startwert zugewiesen werden. Lokale Variablen werden am Prozeduranfang,
  571. globale Variablen dagegen werden am Programmanfang initialisiert. Alle
  572. globalen Variablen, die nicht mit einer Konstante vorbelegt werden, werden
  573. am Programmanfang mit Nullen initialisiert.
  574.  
  575. Das Schlüsselwort STATIC kann nur bei Variablendeklarationen innerhalb von
  576. Prozeduren verwendet werden. Diese Variablen überleben ihre Prozedur, und
  577. haben beim nächsten Aufruf noch den selben Wert wie beim Verlassen. Werden
  578. sie vorinitialisiert, so geschieht dies nur einmal am Programmanfang.
  579.  
  580.  
  581. C.4     Konstanten
  582.  
  583. C.4.1   Einfache Konstanten
  584.  
  585. Einfache Konstanten sind Konstanten der einfachen Typen.
  586.  
  587. Beispiel:
  588.  
  589.   123.43, "C", 12, $1234
  590.  
  591. Der Typ einer derartigen Konstante ergibt sich aus ihrer Darstellung, so
  592. ist "C" vom Typ CHAR.
  593.  
  594.  
  595. C.4.2   Komplexe Konstanten
  596.  
  597. In Cluster ist es auch möglich, Konstanten komplexer Typen zu bilden.
  598. Stringkonstanten werden einfach in Hochkomma eingeschlossen:
  599.  
  600. "Dies ist ein Text"
  601.  
  602. Andere komplexe Konstanten werden durch einen Typbezeichner mit
  603. nachfolgendem Doppelpunkt eingeleitet:
  604.  
  605. $$ comconst     ::=     expression|
  606.                         ("("[comconst{,comconst}]")")|
  607.                         ("("[ident=comconst{,ident=comconst}]")")|
  608.                         ("{"elemlist"}")|
  609.                         (ident : comconst)
  610.  
  611. $$ complexconst ::=     ((ident|(ARRAY OF))":"comconst)|
  612.                         ("{"elemlist"}")
  613.  
  614. Beispiel:
  615.  
  616.   ARRAY OF Vector3:((1,0,0),(0,1,0),(0,0,1));
  617.  
  618.   FarbSet:{gruen,blau};
  619.  
  620.   ARRAY OF Adresse:((name   ="Sigmund",
  621.              vorname="Ulrich",
  622.              alter  =23),
  623.             (name   ="Pfrengle",
  624.              vorname="Thomas",
  625.              alter  =21));
  626.  
  627. Ein Zeiger auf eine derartige komplexe Konstante ist ebenfalls eine
  628. Konstante. Dieser Zeiger kann durch das Attribut PTR gewonnen werden.
  629.  
  630. Bei Mengen, deren Typ dem Compiler sicher bekannt ist (bei Zuweisungen,
  631. innerhalb komplexer Konstanten etc.) kann auf den Typbezeichner verzichtet
  632. werden.
  633.  
  634. Bei Recordkonstanten kann auf die Bezeichner verzichtet werden (sollte nur
  635. in Ausnahmefällen geschehen, da die Lesbarkeit des Programms meist
  636. vermindert wird), und die Elemente können in ihrer Reihenfolge durch Kommata
  637. getrennt aufgezählt werden. Diese Technik ist zu empfehlen bei großen
  638. Arrays aus kleinen Records.
  639.  
  640. Bei Konstanten, die aus offenen Arrays gebildet werden, wird die wirkliche
  641. Größe aus der Anzahl der angegebenen Elemente gebildet.
  642.  
  643.  
  644. C.4.2   Konstantendefinition
  645.  
  646. Konstanten können mit einem Namen belegt werden, und so mehrfach verwendet
  647. werden. Dabei ist für komplexe Konstanten auch eine Vorwärtsdeklaration
  648. möglich, indem nur der Typ der Konstanten angegeben wird. Dies ist
  649. besonders in Defintionsmodulen oder für konstante verkette Listen sinnvoll.
  650.  
  651. $$ constdef        ::= ident "=" (ident|expression)
  652. $$ constdefinition ::= CONST [constdef{;constdef}]
  653.  
  654. CONST
  655.   pi    = 3.1415;
  656.   Basis = ARRAY OF Vector3:((1,0,0),
  657.                 (0,1,0),
  658.                 (0,0,1));
  659.  
  660.  
  661. C.4.3   Ausnahmedeklaration
  662.  
  663. Ausnahmen sind Zustände, die eintreten, wenn nicht planmäßige Ereignisse
  664. auftreten, wie zu wenig Speicher, eine Division durch Null oder der Versuch,
  665. aus einer leeren Datenstruktur ein Element zu lesen.
  666.  
  667. Es gibt drei Arten von Ausnahmen: solche, die durch den Prozessor
  668. hervorgerufen werden (wie Division durch Null, Bereichsfehler etc.); solche,
  669. die durch die Standard/Schnittstellenmodule ausgelöst werden (wie zu wenig
  670. Speicher) und benutzerdefinierte Ausnahmen.
  671.  
  672. $$ exceptdefs   ::= ident : (stringconst|intconst)
  673. $$ exceptdef    ::= EXCEPTION exceptdef{;exceptdef}
  674.  
  675. Beispiele:
  676.  
  677. EXCEPTION
  678.   NotEnoughMemory : "Nicht genug Systemspeicher verfügbar";
  679.   DivisionByZero  : 8;
  680.  
  681.  
  682. C.4.4   Gruppendeklaration
  683.  
  684. Objekte und Deklarationen in einem Definitionsmodul können zu einer Gruppe
  685. zusammengefasst werden, durch deren Importierung alle darin enthaltenen
  686. Objekte importiert werden.
  687.  
  688. $$ groupdef     ::=     GROUP {ident = ident{,ident};}
  689.  
  690. In einer solchen Gruppe können auch andere Gruppen enthalten sein. Stammen
  691. diese aus einem anderen Modul, müssen sie qualifiziert angegeben werden.
  692.  
  693.  
  694. C.5     Ausdrücke
  695.  
  696. Ein Ausdruck besteht aus Variablen, Konstanten, Attributen, Funktionen und
  697. Operatoren.
  698.  
  699. $$ relop        ::=     "="|"#"|"<="|">="|"<"|">"
  700. $$ operator     ::=     "+"|"-"|"*"|"/"|"^"|DIV|MOD|SHL|SHR|AND|OR
  701. $$ paralist     ::=     [expression{,expression}]
  702. $$ term         ::=     {-}|{NOT}(qualident|complexconst|intconst|realconst|
  703.                 charconst|stringconst|("("expression")"))|
  704.                 relop|"+"
  705. $$ expression   ::=     term{(operator term)|("^"|"+^"|"-^")|
  706.                         ("." ident)|("'" ident)|(IN expression)|
  707.                            (OF elemlist)|("("paralist")")|
  708.                         ("["expression{,expression}"]")
  709.  
  710. Die Operatoren haben bei verschiedenen Typen verschiedene Bedeutungen:
  711.  
  712.         Zahlen:         Mengen:         Zeiger:         Boolean:
  713. ----------------------------------------------------------------------
  714. +    |  Summe           Vereinigung     --              --
  715. -    |  Differenz       Differenz       --              --
  716. *    |  Produkt         Schnitt         --              --
  717. /    |  Division        Sym.Differenz   --              --
  718. ^    |  Potenz          --              Dereferenz      --
  719. DIV  |  Ganzzahldiv.    --              --              --
  720. MOD  |  Rest der Div.   --              --              --
  721. SHL  |  Linksshiften    --              --              --
  722. SHR  |  Rechtsshiften   --              --              --
  723. +^   |  --              --              Postinc.Deref.  --
  724. -^   |  --              --              Predec.Deref.   --
  725. =    |  gleich          gleich          gleich          Äquivalenz
  726. #    |  ungleich        ungleich        ungleich        Exklusiv-Oder
  727. <    |  kleiner         --              kleiner         --
  728. <=   |  kleiner/gleich  Teilmenge von   hleiner/gleich  --
  729. >    |  größer          --              größer          --
  730. >=   |  größer/kleich   Obermenge von   größer/gleich   --
  731. AND  |  --              --              --              Und
  732. OR   |  --              --              --              Oder
  733. IN   |  --              Element aus     --              --
  734. OF   |  Element aus     --              --              --
  735.  
  736. Wird ein relationaler Operator als parameterlose Funktion benutzt, liefert
  737. er den Zustand des korrespondierenden Prozessorflags.
  738.  
  739. Folgende Regeln gelten für die Rechnungskompatibilität der Typen t1 und t2:
  740.  
  741. t1 ist gleich t2
  742. t1 und t2 sind SHORTINT, INTEGER, LONGINT oder ANYPTR
  743. t1 und t2 sind SHORTCARD, CARDINAL oder LONGCARD
  744. t1 und t2 sind FFP, REAL oder LONGREAL
  745. t1 und t2 sind Unterbereiche zweier rechnungskompatibler Typen
  746.  
  747. Das Zeichen "." dient dazu, ein Element eines Records zu qualifizieren. Mit
  748. den Klammern [] wird ein Element eines Arrays bestimmt. Dies kann bei
  749. mehrdimensionalen Arrays auf zwei verschiedene Arten geschehen:
  750.  
  751. A[i1][i2].. oder A[i1,i2,..]
  752.  
  753. Das Zeichen "^" dient zur Dereferenzierung eines Zeigers, d.h. aus dem
  754. Zeiger wird das Objekt gebildet, auf das der Zeiger zeigt. Bei Zeigern auf
  755. Records und Arrays kann auf die explizite Dereferenzierung verzichtet
  756. werden, wenn diese unmittelbar darauf qualifiziert oder indiziert werden.
  757.  
  758. Bei der Auswertung eines Ausdrucks gelten folgende Prioritäten:
  759.  
  760. 1.      Funktionsauswertung, Dereferenzierung, Indizierung, Qualifizierung,
  761.         Attributbildung
  762. 2.      Unäres Minus, Negation
  763. 3.      Potenzierung
  764. 4.      Multiplikation, Division, Shifts, logisches Und
  765. 5.      Addition, Subtraktion, logisches Oder
  766. 6.      relationale Operatoren
  767.  
  768. Attribute liefern Informationen über Objekte und deren Typen. Sie werden
  769. durch ein Hochkomma "'" und einen Attributsbezeichner ermittelt. Folgende
  770. Attribute sind vorgegeben:
  771.  
  772. PTR     : Zeiger auf das Objekt
  773. ADR     : Adresse des Objekts
  774. MIN     : kleinster Wert, oder untere Indexgrenze
  775. MAX     : größter Wert, oder obere Indexgrenze
  776. RANGE   : Anzahl der Elemente eines Arrays/Strings
  777. SIZE    : Größe in Bytes
  778.  
  779. Neben selbstdefinierbaren Funktionen existiert auch eine Anzahl
  780. vordefinierter Funktionen. Diese werden meist nicht aufgerufen, sondern
  781. direkt in den erzeugten Code eingebaut.
  782.  
  783. ODD(x:INTEGER):BOOLEAN  liefert TRUE, falls x ungerade ist.
  784. CAST(Typ,x):Typ         Wandelt den Typ des Objekts x in Typ
  785. LMUL(x,y):LONG..        Multiplikation von 16x16Bit auf 32Bit
  786. LDIV(x,y):...           Division von 32x16Bit auf 16Bit
  787. REG(x):LONGINT          Inhalt des Prozessorregisters x
  788. PRED(x):...             Liefert den Wert von x um eins vermindert zurück,
  789.                         auch für Aufzählungstypen
  790. SUCC(x):...             Liefert den Wert von x, um eins erhöht zurück.
  791. CEIL(real):...          Liefert die nächste ganze Zahl, die größer oder
  792.                         gleich real ist.
  793. FLOOR(real):...         Liefert die nächste ganze Zahl, die kleiner oder
  794.                         gleich real ist.
  795.  
  796. Die Standardfunktionen SUCC und PRED liefern bei Integers etc. den Wert
  797. +/-1, bei Zeigern auf Strukturen einen Zeiger des selben Typs, dessen
  798. Zieladresse um die Größe eines Zielelements erhöht ist.
  799.  
  800. Beispiel:
  801.  
  802.   SUCC(3)   = 4
  803.   PRED("B") = "A"
  804.  
  805. TYPE
  806.   Elem  = RECORD
  807.         x,y,z : INTEGER;
  808.         c,h   : CHAR;
  809.       END;
  810.  
  811. VAR
  812.   Array : ARRAY [100] OF Elem;
  813.   p     : POINTER TO Elem;
  814.   i     : INTEGER;
  815.  
  816. BEGIN
  817.   p:=Array[0]'PTR;
  818.   FOR i:=Array'MAX TO 0 BY -1 DO
  819.     p.x:=10;...;p.h:="C";
  820.     p:=SUCC(p)
  821.   END;
  822. END...
  823.  
  824. Oder auch extrem:
  825.  
  826.   SUCC(SUCC(p))^.x:=4;
  827.  
  828. Neben diesen allgemeinen Funktionen verfügt Cluster noch über eine große
  829. Anzahl mathematischer Funktionen für REALs und LONGREALs:
  830.  
  831. SIN, ASIN, SINH, COS, ACOS, COSH, TAN, ATAN, TANH, LN, LOG, EXP, SQRT, ABS
  832.  
  833. Der Typ eines Ausdrucks kann sicher in einen anderen überführt werden,
  834. indem der Typbezeichner als Funktion verwendet wird.
  835.  
  836.  
  837. C.6     Anweisungen und Strukturen
  838.  
  839. Eine Anweisungsfolge ist eine Folge von Anweisungen, die durch Semikoli
  840. getrennt sind.
  841.  
  842. $$ statementsequence ::= statement{;statement}
  843. $$ statement         ::= |assignment|repeatstatement|whilestatement|
  844.                          ifstatement|loopstatement|forstatement|
  845.                          withstatement|exitstatement|returnstatement|
  846.                          trystatement|forgetstatement|procedurecall
  847.  
  848. Auch die leere Anweisung ist eine Anweisung.
  849.  
  850.  
  851. C.6.1   Zuweisungen
  852.  
  853. Die wichtigste Anweisung ist die Zuweisung. Dabei wird einem Ausdruck auf
  854. der linken Seite der Wert des Ausdrucks der rechten Seite zugewiesen. Der
  855. Ausdruck der linken Seite muß eine Variable bzw. eine durch einen Pointer
  856. bezeichnete Speicherstelle sein.
  857.  
  858. $$ assignment   ::= expression ":=" expression
  859.  
  860. Folgende Regeln gelten für Zuweisungskompatibilität von t1 und t2:
  861.  
  862. t1 ist gleich t2
  863. t1 und t2 sind Pointer auf den selben Typen
  864. t1 und t2 sind SHORTINT, INTEGER, LONGINT, SHORTCARD, CARDINAL, LONGCARD
  865.                oder ANYPTR
  866. t1 und t2 sind REAL oder LONGREAL
  867. t1 und t2 sind Unterbereiche eines zuweisungskompatiblen Typen
  868. t1 und t2 sind Arrays gleichen Basistyps mit gleichviel Elementen
  869. t1 und t2 sind Strings beliebiger Länge
  870. t1 und t2 sind direkte Nachfolger bei offenen Records
  871.  
  872.  
  873. C.6.2   REPEAT..UNTIL..
  874.  
  875. $$ repeatstatement      ::= REPEAT statementsequence UNTIL expression
  876.  
  877. Die Anweisungsfolge zwischen REPEAT und UNTIL wird solange ausgeführt, bis
  878. der Ausdruck an ihrem Ende wahr wird.
  879.  
  880. i:=0;
  881. REPEAT WriteInt(i,0);INC(i) UNTIL i=10
  882.  
  883. liefert
  884. 0 1 2 3 4 5 6 7 8 9
  885.  
  886.  
  887. C.6.3   IF-Struktur
  888.  
  889. Die IF-Struktur ist extrem mächtig, sie enthält auch die von Modula
  890. bekannte CASE-Anweisung.
  891.  
  892. $$ ifcase       ::= (expression (THEN statementsequence)|
  893.             (AND_IF ifcase))|(KEY expression
  894.             {OF elemlist (THEN statementsequence END)|
  895.                     (AND_IF ifcase)})
  896.                     [OR_IF|ELSIF ifcase]|([ELSE statementsequence] END)
  897. $$ ifstatement  ::= IF ifcase
  898.  
  899. Die Grundstruktur ist:
  900.  
  901. IF b1 THEN
  902.   S1
  903. OR_IF b2 THEN
  904.   S2
  905. ...
  906. ELSE
  907.   SN
  908. END;
  909.  
  910. Der zu dem ersten Boolausdruck bi, der TRUE ist, gehörende Programmteil Si
  911. wird ausgeführt, und das Programm hinter END fortgesetzt. Ist kein Ausdruck
  912. wahr, wird SN ausgeführt.
  913.  
  914. Jeder IF-Fall kann durch Einführen einer AND_IF-Klausel eingeschränkt
  915. werden, die selbst wieder OR_IF und/oder ELSE-Klauseln besitzt. Ist keiner
  916. dieser Fälle wahr, und kein ELSE-Teil vorhanden, wird der Vergleich mit dem
  917. nächsten tieferliegenden OR_IF oder ELSE weitergeführt.
  918.  
  919. ...
  920. OR_IF bx
  921.   AND_IF bx1 THEN
  922.     ...
  923.   OR_IF bx2 THEN
  924.     ...
  925.   ELSE
  926.   ...
  927.   END
  928. OR_IF by
  929. ...
  930.  
  931. Sollen anhand eines Schlüsselwertes verschiedene Möglichkeiten geprüft
  932. werden, kann "KEY" benutzt werden.
  933.  
  934. OR_IF KEY a1
  935.   OF ... THEN ... END
  936.   OF ... AND_IF bx THEN
  937.        ...
  938.      OR_IF KEY a11
  939.        OF ... THEN
  940.        ...
  941.      END
  942.   OF ... THEN ... END
  943. OR_IF ...
  944.  
  945. C.6.4   WHILE-Struktur
  946.  
  947. Die WHILE-Struktur ist völlig symmetrisch zur IF-Struktur. Der Unterschied
  948. ist, daß nachdem ein Programmteil zu einem DO ausgeführt wurde, wieder
  949. zurück zum Anfang der WHILE-Struktur gesprungen wird.
  950.  
  951. $$ whilecase      ::= (expression (DO statementsequence)|
  952.               (AND_WHILE  whilecase))|(KEY expression
  953.               {OF elemlist (DO statementsequence END)|
  954.               (AND_WHILE whilecase)})
  955.               [OR_WHILE whilecase]|([ELSE statementsequence] END)
  956. $$ whilestatement ::= WHILE whilecase
  957.  
  958.  
  959. C.6.5   LOOP..END, EXIT
  960.  
  961. Die LOOP-Struktur ist eine Schleife ohne dedizierte Terminationsbedingung.
  962. Die Schleife wird durch das Schlüsselwort EXIT terminiert, das beliebig
  963. innerhalb der Schleife stehen darf.
  964.  
  965. $$ loopstatement        ::= LOOP statementsequence END
  966. $$ exitstatement        ::= EXIT
  967.  
  968.  
  969. C.6.6   FOR..DO..END
  970.  
  971. Die FOR-Struktur ist eine Schleifenstruktur, deren Termination durch einen
  972. Zähler gegeben ist. Dieser läuft von einem angegebenen Startwert zu einem
  973. Endwert, wobei der Schleifenindex jedesmal um eine vorgegebene konstante
  974. Schrittweite erhöht wird. Als Schleifenzähler sind alle zählbaren Typen
  975. zugelassen.
  976.  
  977. $$ forstatement ::= FOR assignment TO expression [BY expression] DO
  978.             statementsequence END
  979.  
  980. FOR i:=start TO end BY step DO statement END;
  981.  
  982. entspricht für positives step:
  983.  
  984. i:=start;WHILE i<=end DO statement;INC(i,step) END;
  985.  
  986. bei negativem step:
  987.  
  988. i:=start;WHILE i>=end DO statement;INC(i,step) END;
  989.  
  990. Wird kein Schrittwert angegeben, wird eins verwendet.
  991.  
  992.  
  993. C.6.7   WITH..DO..END
  994.  
  995. Die WITH-Struktur erzeugt temporäre Variablen, oder gibt bestehenden einen
  996. neuen Namen.
  997.  
  998. $$ withstatement    ::= WITH expression [AS ident]{,expression AS ident} DO
  999.                 statementsequence END
  1000.  
  1001. Wird als Ausdruck ein Typ angegeben, wird eine neue Variable erzeugt.
  1002.  
  1003. VAR source,dest : POINTER TO
  1004.             ARRAY [0..3] OF
  1005.               POINTER TO
  1006.             ARRAY [0..9] OF INTEGER;
  1007.     i           : INTEGER;
  1008.  
  1009. FOR i:=0 TO 9 DO
  1010.   dest^[2]^[i]:=source^[3]^[9-i]
  1011. END;
  1012.  
  1013. Kann durch WITH vereinfacht werden:
  1014.  
  1015. WITH dest^[2]^ AS d,source^[3]^ AS s DO
  1016.   FOR i:=0 TO 9 DO
  1017.     d^[i]:=s^[9-i]
  1018.   END;
  1019. END;
  1020.  
  1021. Dies ermöglicht dem Compiler auch Optimierungen, da er die Adressausdrücke
  1022. nur einmal errechnen muß.
  1023.  
  1024. Wird kein neuer Namen durch AS angegeben, wird der Name der Basisvariablen
  1025. beibehalten.
  1026.  
  1027.  
  1028. C.6.8   RETURN
  1029.  
  1030. RETURN beendet die Ausführung einer Prozedur. Handelt es sich dabei um eine
  1031. Funktion mit einem einfachen Rückgabetypen, muß dahinter ein Ausdruck
  1032. angegeben werden, der den Rückgabewert darstellt. Bei Funktionen mit
  1033. komplexem Rückgabewert wird dieser durch die Variable RESULT zurückgegeben.
  1034.  
  1035. $$ returnstatement      ::= RETURN [expression]
  1036.  
  1037.  
  1038. C.6.9   Prozeduraufruf
  1039.  
  1040. Eine Prozedure wird aufgerufen, wenn ein Ausdruck einen Prozedurtypen
  1041. liefert (eine normale Prozedur ist eine Konstante ihres eigenen
  1042. Prozedurtyps).
  1043.  
  1044. $$ procedurecall        ::= expression "("paralist")"
  1045.  
  1046. Cluster verfügt über eine Reihe von Compilerprozeduren, die nicht
  1047. aufgerufen werden, sondern direkt in den erzeugten Code eingebaut werden.
  1048.  
  1049. INC(x)          erhöht x um 1, nur zählbare Typen und Zeiger
  1050. INC(x,m)        erhöht x um m
  1051. DEC(x)          erniedrigt x um 1
  1052. DEC(x,m)        erniedrigt x um m
  1053. EVEN(x)         rundet x auf die nächste gerade Zahl ab
  1054. SHL(x,n)        shiftet x um n Bits links
  1055. SHR(x,n)        shiftet x um n Bits rechts
  1056. ROL(x)          rotiert x um ein Bit nach links
  1057. ROR(x)          rotiert x um ein Bit nach rechts
  1058.  
  1059. INCL(s,e)       fügt das Element e in die Menge s ein
  1060. EXCL(s,e)       entfernt das Element e aus der Menge s
  1061. FLIP(s,e)       wechselt die Anwesenheit von e in der Menge s
  1062. UNI(d,s)        verinigt die Menge d mit der Menge s
  1063. SEC(d,s)        schneidet die Menge d mit der Menge s
  1064.  
  1065. SETREG(r,v)     schreibt den Wert von v in Register r
  1066. INLINE(x,..)    schreibt eine Anzahl von Datenwörter in das erzeugte
  1067.                 Programm
  1068.  
  1069. HALT(x)         beendet das Programm mit Fehlernummer x
  1070. HALT2(x)        beendet das Programm mit Fehlernummer x an der Stelle, an
  1071.                 der die aktuelle Prozedur aufgerufen wurde
  1072.  
  1073. RAISE(x)        löst die Ausnahme x aus
  1074. RAISE2(x)       löst die Ausnahme x aus, wobei als Ereignisspunkt der Punkt
  1075.                 des Prozeduraufrufs angegeben wird
  1076.  
  1077. ASSERT(b,x)     stellt sicher, daß die Bedingung b erfüllt ist, andernfalls
  1078.                 wird die Ausnamhe x ausgelöst
  1079. ASSERT2(b,x)    wie ASSERT, nur wird als Ereignisspunkt der Punkt des
  1080.                 Prozeduraufrufs angegeben.
  1081.  
  1082. PUSH(set)       Sichert die im set angegebenen Register auf den Stapel, z.B.
  1083.                 für Interrupts etc.
  1084. POP(set)        Nimmt mit PUSH gesicherte Register wieder vom Stapel
  1085.                 herunter.
  1086.  
  1087.  
  1088. C.6.9.1 Der Inline-Assembler
  1089.  
  1090. Der Assembler ist als Standardfunktion implementiert: ASSEMBLE(...). Er
  1091. kann an einer beliebigen Stelle im Programm benutzt werden, der erzeugte
  1092. Code wird an genau dieser Stelle ins Programm eingefügt.
  1093.  
  1094. Bsp.:
  1095.  
  1096.   BEGIN
  1097.   ...
  1098.     ASSEMBLE(
  1099.          MOVE.L D0,A0
  1100.          ...
  1101.          BNE    loop
  1102.         );
  1103.   ...
  1104.   END ...;
  1105.  
  1106. Es ist möglich auf alle lokalen und globalen Variablen über ihren Namen
  1107. zuzugreifen, der Assembler wählt automatisch die richtige Adressierungsart.
  1108. Auch auf Variablen innerhalb einer Prozedur kann zugegriffen werden, der
  1109. Assembler übersetzt den Zugriff in eine SP-relative Adressierung. Dies
  1110. wirft allerdings ein Problem auf, wenn der Stackpointer verändert wird, da
  1111. dies den Compiler schwer durcheinander bringt.
  1112.  
  1113. Bsp.:
  1114.  
  1115. VAR i : ARRAY [0..5] OF INTEGER;
  1116.  
  1117. PROCEDURE IncI(at,um : INTEGER);
  1118. BEGIN
  1119.   ASSEMBLE(
  1120.        MOVE um,D0
  1121.        MOVE at,D1
  1122.        ASL  #1,D1
  1123.        LEA  i,A0
  1124.        ADD  D0,(A0,D1)
  1125.       )
  1126. END IncI;
  1127.  
  1128. oder auch:
  1129.  
  1130. PROCEDURE IncI(at,um : INTEGER);
  1131. BEGIN
  1132.   ASSEMBLE(USE  D0
  1133.        MOVE um,D0
  1134.        ADD  um,i[at]
  1135.       )
  1136. END IncI;
  1137.  
  1138. Der Assembler überführt diesen Code automatisch in die entsprechenden
  1139. Anweisungen. Da der Compiler dazu freie Register benötigt, diese dem
  1140. Programm aber nicht einfach stehlen kann, ist es sinnvoll, die Register, die
  1141. man innerhalb des Programmes benutzen möchte, mit USE anzugeben. Der
  1142. Assembler betrachtet die nicht belegten Register als sein Eigentum, und
  1143. nutzt diese für erweiterte Adressierungen.
  1144.  
  1145. Es können auch Registervariablen verwendet werden:
  1146.  
  1147. PROCEDURE IncI(at IN D0,um IN D1 : INTEGER);
  1148. BEGIN
  1149.   ASSEMBLE(USE  A0
  1150.        LEA  i,A0
  1151.        ASL  #1,at
  1152.        ADD  um,(A0,at)
  1153.       )
  1154. END IncI;
  1155.  
  1156. Der Assembler versucht so gut wie möglich, dem Stack-Pointer zu folgen; so
  1157. werden Veränderungen des SP durch ADD #,A7, SUB #,A7, LINK sowie -(A7) und
  1158. (A7)+ erkannt, und richtig in die Berechnung der Prozedur-lokalen Variablen
  1159. einbezogen. Was der Assembler nicht berücksichtigen kann sind Veränderungen
  1160. des SP durch MOVE ...,A7 o.ä, Veränderungen durch variable Werte wie in
  1161. ADD D0,A7, und Unterprogramme.
  1162.  
  1163. Bsp.:
  1164.  
  1165. PROCEDURE ReturnSame(i : INTEGER):INTEGER;
  1166. VAR j : INTEGER;
  1167. BEGIN
  1168.   ASSEMBLE(SUB.W  #100,A7
  1169.        MOVE   i,j
  1170.        ADD.W  #100,A7
  1171.   RETURN j;
  1172. END ReturnSame;
  1173.  
  1174. Dies ist völlig legal und wird auch richtig übersetzt.
  1175.  
  1176. Der Compiler verlangt, daß am Ende eines Assemblerteiles der Stackpointer
  1177. wieder den selben Wert hat wie beim Eintritt, da er sonst beim Mitzählen
  1178. aus dem Ruder geraten würde.
  1179.  
  1180. Labels können an einer beliebigen Stelle im Assemblerteil verwendet, oder
  1181. definiert werden (dies natürlich nicht mitten in einem Befehl). Bei der
  1182. Definition eines Labels muß dieses von einem Doppelpunkt gefolgt werden. Es
  1183. gibt keine feste Form, wie Assembleranweisungen im Text formatiert werden
  1184. müssen, es muß lediglich zwischen Label, Mnemonic und Operanden mindestens
  1185. ein Space stehen, auch dürfen beliebig viele Anweisungen in einer Zeile
  1186. stehen.
  1187.  
  1188. Bsp.:
  1189.  
  1190. PROCEDURE Copy(from IN A0,to IN A1,size IN D2 : LONGINT);
  1191. BEGIN
  1192.   ASSEMBLE(USE     D1
  1193.        MOVE    size,D1  | .L wird erkannt, da "size" ein LONGINT
  1194.        SHR     #2,size
  1195.        SUB     #1,size
  1196.   loop:    MOVE.L  (from)+,(to)+ DBRA size,loop
  1197.        BTST    #1,D1 BEQ not2 MOVE.W (from)+,(to)+
  1198.   not2:    BTST    #0,D1 BEQ not1 MOVE.B (from)+,(to)+
  1199.   not1:    )
  1200. END Copy;
  1201.  
  1202. Dies steigert zwar nicht die Lesbarkeit, ist aber möglich. Nicht möglich
  1203. ist es mit, Labels zu rechnen, da dies den Shortbranch-Optimierer aus dem
  1204. Ruder bringen würden (Vorerst sind noch fast alle Optimierungen, die der
  1205. Compiler normalerweise ausführt, auch im Assemblerteil vorhanden, also
  1206. keinen Code patchen !!!).
  1207.  
  1208. Es gibt keine Anweisungen wie ADDA oder ADDI, diese werden durch den
  1209. Assembler bei Bedarf erzeugt.
  1210.  
  1211.  
  1212. C.6.10  FORGET
  1213.  
  1214. Viele Funktionen (gerade solche des Betriebssystems) sind eigentlich keine
  1215. Funktionen, sondern Prozeduren, da ihre eigentliche Aufgabe nicht in der
  1216. Rückgabe eines Wertes, sondern in der Ausführung einer Tätigkeit besteht
  1217. (z.B. WritePixel). Diese Funktionen liefern mehr als Nebeneffekt auch noch
  1218. einen Wert zurück, der in den meisten Fällen problemlos ignoriert werden
  1219. kann. Da es aber sehr gefährlich ist, eine Verwendung von Funktionen als
  1220. Prozeduren zuzulassen, es andererseits aber sehr störend ist, das
  1221. Funktionsergebnis jedesmal einer Dummy-Variablen zuzuweisen, kann mit
  1222. FORGET ein Ausdruck ausgewertet werden, dessen Ergebniss danach einfach
  1223. vergessen wird.
  1224.  
  1225. $$ forgetstatement      ::= FORGET
  1226.  
  1227. Beispiel:
  1228.  
  1229. FORGET WritePixel(rast,x,y);
  1230.  
  1231.  
  1232. C.6.11  TRY..EXCEPT
  1233.  
  1234. Ausnahmesituationen (Exceptions) können durch Programm- bzw. Datenfehler,
  1235. systembedingte Probleme wie Speichermangel oder durch beutzerdefinierte
  1236. Ausnahmen entstehen.
  1237.  
  1238. Ist kein Exceptionhandler installiert, kann das Programm nur durch einen
  1239. Abbruch reagieren.
  1240.  
  1241. $$ trystatement ::= TRY statementsequence EXCEPT
  1242.             {OF ident{,ident} THEN statementsequence END}
  1243.             [ELSE statementsequence] END
  1244.  
  1245. Die Anweisungssequenz zwischen TRY und EXCEPT wird ausgeführt; tritt dabei
  1246. eine Ausnahme auf, wird das Programm mit dem passenden Exceptionhandler des
  1247. EXCEPT Teils fortgesetzt. Ist kein passender Exceptionhandler vorhanden,
  1248. wird der eventuell vorhandene ELSE Teil ausgeführt, und die Ausnahme an den
  1249. nächsten übergeordneten Exceptionhandler weitergereicht.
  1250.  
  1251. Somit werden alle Ausnahmen von dem nächsten passenden Exceptionhandler
  1252. bearbeitet. Ist überhaupt kein Exceptionhandler vorhanden, wird das Programm
  1253. mit einem Laufzeitfehler abgebrochen. Ein für die Exception angegebener Text
  1254. wird als Fehlermeldung verwendet.
  1255.  
  1256. Beispiel: Auswertung einer math. Funktion
  1257.  
  1258. PROCEDURE F(x : INTEGER):INTEGER;
  1259. BEGIN
  1260.   RETURN 100 DIV x
  1261. END F;
  1262.  
  1263. Diese Prozedur löst für x=0 eine "DivisionByZero" Exception aus, die durch
  1264. den Funktionsplotter abgefangen werden muß:
  1265.  
  1266. PROCEDURE WriteF(l,r : INTEGER);
  1267. VAR i : INTEGER;
  1268. BEGIN
  1269.   FOR i:=l TO r DO
  1270.     TRY
  1271.       WriteInt(F(i),10);
  1272.     EXCEPT
  1273.       OF DivisionByZero THEN WriteString("Division durch Null") END
  1274.     END
  1275.     WriteLn
  1276.   END;
  1277. END WriteF;
  1278.  
  1279. Durch dieses TRY-Statement wird wird nur eine Division durch Null, nicht
  1280. aber andere Ausnahmen, wie Ctrl-C o.ä. abgefangen. Diese Ausnahmen werden
  1281. ohne Änderung weitergereicht.
  1282.  
  1283. Ausnahmen sollten so weit zurückgereicht werden, bis eine sichere
  1284. Bearbeitung möglich ist.
  1285.  
  1286. Der ELSE-Teil der TRY Anweisung dient als Close-Teil, so daß bereits
  1287. allozierte Strukturen noch freigegeben bzw. geschlossen werden können.
  1288.  
  1289.  
  1290. C.6.12  TRACK..END
  1291.  
  1292. Im Zuge des Resourcetrackings (Verfolgen der Systemresourcen durch das
  1293. Laufzeitsystem, siehe auch "Resources.def") wurde TRACK..END eingeführt.
  1294.  
  1295. Durch TRACK wird eine neuer Kontext erzeugt und zum ActContext erklärt.
  1296. Dieser Kontext wird bei Verlassen der Struktur (Normal, Exception oder
  1297. RETURN wieder entfernt).
  1298.  
  1299.  
  1300. C.7     Prozedurdeklaration
  1301.  
  1302. Eine Prozedurdeklaration besteht aus einem Prozedurkopf, in dem ihre
  1303. Schnittstelle definiert wird, und einem Prozedurkörper, in dem der
  1304. eigentliche Inhalt der Prozedur definiert wird. Eine Funktionsprozedur
  1305. hat zusätzlich zu den normalen Parametern noch einen Rückgabetypen, der
  1306. hinter einem Doppelpunkt definiert wird.
  1307.  
  1308. Innerhalb einer Prozedur können Typen, Variablen, Konstanten und weitere
  1309. Prozeduren deklariert werden. Objekte, die innerhalb einer Prozedur
  1310. deklariert sind, existieren nur, solange die Prozedur läuft. Sie sind auch
  1311. nur innerhalb dieser sichtbar. Alle außen bekannten Bezeichner sind auch
  1312. innerhalb bekannt, solange sie nicht durch neue Deklarationen überdeckt
  1313. werden.
  1314.  
  1315. $$ paradeclar      ::= [VAR|REF] ident [IN expression]
  1316.                {,ident [IN expression]}:
  1317.                (qualident[:= expression])|(:=expression)
  1318. $$ formalparams    ::= ["("[paradeclar{;paradeclar}]")"[":"qualident]
  1319. $$ procedureheader ::= PROCEDURE ident formalparams ";"
  1320. $$ proceduredeclar ::= ([FORWARD] procedureheader)|(procedureheader
  1321.                {import|typedef|vardeclaration|constdef|proceduredeclar}
  1322.                BEGIN statementsequence END ident) ";"
  1323.  
  1324. Soll eine Prozedur verwendet werden, bevor ihr Prozedurrumpf implementiert
  1325. werden kann, wenn sich also z.B. zwei Prozeduren gegenseitig benötigen, muß
  1326. sie mit dem Schlüsselwort FORWARD vorwärts deklariert werden.
  1327.  
  1328. Parameter können mit einem Vorgabewert vorbelegt werden. Parameter mit
  1329. Vorgabewert brauchen beim Prozeduraufruf nicht mit angegeben werden, statt
  1330. dessen wird der Defaultwert vorgegeben:
  1331.  
  1332. Beisp:
  1333.  
  1334. PROCEDURE WriteInt(val : LONGINT;width : INTEGER := 0);
  1335.  
  1336. kann aufgerufen werden mit:
  1337.  
  1338. WriteInt(10,4) oder aber auch WriteInt(41)
  1339.  
  1340. Hat eine Prozedur viele Parameter, kann nicht immer davon ausgegangen
  1341. werden, daß die zu überspringenden Parameter am Ende liegen. In diesem Fall
  1342. muß die Zuweisung durch Schlüsselwörter (die Namen der Parameter)
  1343. vorgenommen werden:
  1344.  
  1345. PROCEDURE New(VAR p       : ANYPTR;
  1346.           chip,
  1347.           clear   : BOOLEAN    := FALSE;
  1348.           context : ContextPtr := NIL);
  1349.  
  1350. New(p);
  1351. New(p,TRUE,FALSE,MyContext);
  1352. New(p,clear:=TRUE);
  1353. New(p,clear:=TRUE,context:=MyContext);
  1354. ...
  1355.  
  1356. Die Reihenfolge der Parameter muß eingehalten werden, auch dürfen nach
  1357. Parametern mit Bezeichnern keine Positionalen mehr folgen.
  1358.  
  1359. Parameter können auf drei Arten übergeben werden, die bestimmen, wie
  1360. innerhalb der Prozedur auf dieses zugegriffen werden kann, welche Objekte
  1361. übergeben werden können und ob der Parameter nach der Prozedur verändert
  1362. sein kann.
  1363.  
  1364.  
  1365. C.7.1 Übergabe durch Wert (Call by value)
  1366.  
  1367. Als aktueller Parameter kann ein beliebiger Ausdruck angegeben werden. Das
  1368. Ergebnis der Auswertung wird als Kopie an die Prozedur übergeben.
  1369. Änderungen dieses Parameters innherhalb der Prozedur bleiben außen ohne
  1370. Wirkung, da die Prozedur ja lediglich über eine Kopie verfügt.
  1371.  
  1372. Nachteilig bei diesem Verfahren ist, daß das Kopieren bei komplexen Typen
  1373. relativ viel Zeit und Speicherplatz benötigt.
  1374.  
  1375. PROCEDURE WriteInt(i : INTEGER);
  1376.  
  1377.  
  1378. C.7.2 Übergabe durch Referenz (Call by reference)
  1379.  
  1380. Als aktueller Parameter kann ein adressierbares Objekt angegeben werden
  1381. (Variablen, Konstanten, Parameter oder Zeigerziele). Die Prozedur bekommt
  1382. die Adresse des Parameters übergeben, es wird im Gegensatz zu oben nicht
  1383. kopiert. Der Parameter kann innerhalb der Prozedur nicht verändert werden,
  1384. da ja sonst das Original verändert würde. Der aktuelle Parameter wird also
  1385. mit Sicherheit nicht verändert.
  1386.  
  1387. Diese Übergabe lohnt sich für größere Typen (Arrays oder Records) auf
  1388. keinen Fall aber für einfache Typen wie Zeiger oder Zahlen.
  1389.  
  1390. PROCEDURE WriteString(REF s : STRING);
  1391.  
  1392.  
  1393. C.7.3 Übergabe durch 'wirkliche' Referenz (mit Schreibzugriff)
  1394.  
  1395. Als aktueller Parameter kann eine Variable, ein Parameter  oder ein
  1396. Pointerziel angegeben werden. Die Prozedur erhält die Adresse dieses
  1397. Objekts, und darf dieses auch verändern. Die Änderungen bleiben
  1398. nach dem Prozeduraufruf erhalten, sind also 'richtige' Änderungen am Objekt.
  1399.  
  1400. PROCEDURE ReadString(VAR s : STRING);
  1401.  
  1402.  
  1403. C.7.4  Methoden
  1404.  
  1405. Hat man mehre Prozeduren, die die gleiche Funktion für verschiedene Typen
  1406. erfüllen, ist es unangenehm, jeder Prozedur einen anderen Namen geben zu
  1407. müssen. Daher besteht die Möglichkeit, beliebig viele Methoden mit dem
  1408. gleichen Namen zu definieren, wenn Sie einen RECORD oder einen Zeiger auf
  1409. einen RECORD als ersten Parameter erwarten.
  1410.  
  1411. Hier einige Beispiele aus dem Modul DosSupport:
  1412.  
  1413. METHOD Get(VAR data       : FileData;
  1414.        REF path       : STRING)
  1415.  
  1416. METHOD Get(VAR list       : DirList;
  1417.        REF path       : STRING;
  1418.        REF pattern    : STRING:="#?";
  1419.            type       := DirSelectType:{selectDirs,selectFiles};
  1420.            context    : ContextPtr := NIL);
  1421.  
  1422. Diese Methoden kann man nicht direkt importieren und aufrufen, sondern
  1423. werden qualifiziert über eine Variable des Typs des ersten Parameters
  1424. aufgerufen z.B.:
  1425.  
  1426. VAR
  1427.   Dir      : DirList;
  1428.   FileInfo : FileData;
  1429.  
  1430. BEGIN
  1431.   FileInfo.Get("s:startup-sequence");
  1432.   Dir.Get("DH0:");
  1433.  
  1434.  
  1435. C7.5 Funktions-Prozeduren
  1436.  
  1437. Hat eine Prozedur oder Methode einen Rückgabewert, bezeichnet man sie als
  1438. Funktion. Am Ende der Prozedur wird dieser mit RETURN zurückgegeben (siehe
  1439. 6.8). Handelt es sich bei dem Wert, der zurückgegeben werden soll, um einen
  1440. komplexen Typen (Array/Record), so weist man diesen der Variablen RESULT
  1441. zu, und verläßt die Funktion durch RETURN, ohne danach den Wert anzugeben.
  1442.  
  1443. Handelt es sich bei dem Rückgabetypen um einen offenen Typen
  1444. (String/Offenes Array), so muß man vor der Prozedurdeklaration den Schalter
  1445. $$OwnHeap:=TRUE setzen (bei Prozeduren, die exportiert werden, genügt es,
  1446. dies im Definitionsteil zu machen.). Außerdem muß man dafür sorgen, daß im
  1447. Falle, daß das Ergebnis an einen VAR/REF-Parameter übergeben wird,
  1448. außreichend Platz auf dem Stack alloziert wird, um das Ergebnis dort
  1449. zwischenzulagern. Hierzu dient die Standartprozedur
  1450.  
  1451. ALLOC_RESULT(range : LONGINT);
  1452.  
  1453. Der Parameter range gibt dabei den Bereich des Arrays/Strings an, für das
  1454. Platz alloziert werden soll. Denken Sie dabei daran, daß Sie bei Strings
  1455. range = Maximallänge+1 wählen, um Platz für das 0-Byte zu haben.
  1456. Die zwei Bytes für die Länge bei einem String alloziert ALLOC_RESULT
  1457. selbstständig, wenn es sich bei dem Rückgabetypen um einen String handelt.
  1458.  
  1459.  
  1460. C.8     Moduldeklaration
  1461.  
  1462. Es gibt drei Arten von Modulen: Programmodule, Definitionsmodule und
  1463. Implementationsmodule. Immer ein Definitionsmodul gehöhrt zu einem
  1464. Implementationsmodul, in ihm werden die Schnittstellen zu anderen Modulen
  1465. definiert.
  1466.  
  1467. $$ import       ::= (FROM qualident[AS ident] IMPORT ident{","ident}";")|
  1468.             (IMPORT qualident[AS ident]{","qualident AS ident}";")
  1469. $$ modulebody   ::= {import|typedef|vardeclaration|constdef|proceduredeclar|
  1470.             defmodule|implementmod}
  1471.                     [BEGIN statementsequence]
  1472.             [CLOSE statementsequence]
  1473. $$ implementmod ::= IMPLEMENTATION MODULE ident ";"
  1474.             modulebody END ident
  1475. $$ mainmodule   ::= MODULE ident ";" modulebody END ident
  1476. $$ defmodule    ::= DEFINITION MODULE ident
  1477.             [("("ident : typedef")")|
  1478.             ("=" qualident "(" typedef ")")]
  1479.             {import|typedef|vardeclaration|constdef|procedureheader|
  1480.             defmodule} END ident
  1481. $$ module       ::= mainmodule|implementmod|defmodule "."
  1482.  
  1483.  
  1484. Durch die Importklausel, können Elemente anderer Module im eigenen Modul
  1485. verwendet werden. Es ist sowohl ein Qualifizierender als auch
  1486. Unqualifizerender Import Möglich.
  1487.  
  1488. Beispiel:
  1489.  
  1490. Durch den Import
  1491.  
  1492. FROM InOut IMPORT WriteInt,Read;
  1493.  
  1494. werden dem Programm die Bezeichner "WriteInt" und "Read" direkt zur
  1495. Verfügung gestellt, aber auch der Bezeichner "InOut", so daß auch über
  1496. "InOut.xxx" auf andere Bezeichner des Objektes zugegriffen werden kann.
  1497.  
  1498.  
  1499. C.8.1   Generische Module
  1500.  
  1501. Viele Datenstrukturen und dazugehörige Algorithmen werden häufig in
  1502. verschiedenen Kontexten und in Verbindung mit anderen Datenstrukturen
  1503. benötigt (z.B. Listen, AVLBäume, Stacks etc.).
  1504.  
  1505. In einer streng und vor allem statisch getypten Sprache tritt das Problem
  1506. auf, daß diese Strukturen jedesmal neu definiert und implementiert werden
  1507. müssen. Diesem Problem wird durch Generizität abgeholfen.
  1508.  
  1509. Ein generisches Modul besitzt einen generischen Parameter. Dieser Parameter
  1510. ist ein Zeigertyp, über den das Modul auch bereits Annahmen machen kann.
  1511.  
  1512. Ein derartiges Modul muß vor seiner Verwendung durch ein anderes Modul
  1513. durch einen aktuellen Parameter ausgeprägt werden. Dieser Typ muß zum
  1514. formalen Parametertyp passen.
  1515.  
  1516. Beispiel:
  1517.  
  1518.   DEFINITION MODULE BiList(NodePtr : POINTER TO Node);
  1519.  
  1520.     TYPE
  1521.       Node  = RECORD
  1522.         pred,
  1523.         succ   : NodePtr
  1524.           END;
  1525.  
  1526.       List  = RECORD
  1527.         first,
  1528.         last   : NodePtr
  1529.           END;
  1530.  
  1531.       ApplyProc = PROCEDURE(n : NodePtr);
  1532.  
  1533.     PROCEDURE Init(VAR l : List);
  1534.  
  1535.     PROCEDURE InsertTop(VAR l : List;n : NodePtr)
  1536.  
  1537.     PROCEDURE Apply(VAR l : List;apply : ApplyProc);
  1538.  
  1539.   END BiList;
  1540.  
  1541.  
  1542.   IMPLEMENTATION MODULE BiList;
  1543.  
  1544.     PROCEDURE Init(VAR l : List);
  1545.     BEGIN
  1546.       l.first:=NIL;
  1547.       l.last :=NIL
  1548.     END Init;
  1549.  
  1550.     PROCEDURE InsertTop(VAR l : List;n : NodePtr);
  1551.     BEGIN
  1552.       n.pred:=NIL;
  1553.       n.succ:=l.first;
  1554.       IF l.first=NIL THEN
  1555.     l.last:=n
  1556.       ELSE
  1557.     l.first.pred:=n
  1558.       END;
  1559.       l.first:=n
  1560.     END InsertTop
  1561.  
  1562.     PROCEDURE Apply(VAR l : List;apply : ApplyProc);
  1563.     VAR n : NodePtr;
  1564.     BEGIN
  1565.       n:=l.first;
  1566.       WHILE n#NIL DO
  1567.     apply(n);n:=n.next
  1568.       END;
  1569.     END Apply;
  1570.  
  1571.   END BiList;
  1572.  
  1573. Das Implementations-Modul kann über die bekannten Elemente des Knotentyps
  1574. (pred,succ) verfügen, da durch die Definition des generischen Parameters
  1575. sichergestellt wird, daß nur ein Zeiger auf einen Nachfolger von Node in
  1576. Frage kommt.
  1577.  
  1578. TYPE
  1579.   NamePtr  = POINTER TO NameNode;
  1580.  
  1581.   DEFINITION MODULE NameList = BiList(NamePtr);
  1582.  
  1583. TYPE
  1584.   NameNode = RECORD OF NameList.Node
  1585.            name,
  1586.            vorname : STRING(100);
  1587.            alter   : INTEGER;
  1588.          END;
  1589.  
  1590. Das Modul NameList verwaltet nun eine Liste derartiger NameNodes. Die
  1591. Typsicherheit ist voll gegeben, da keine anderen Knotentypen zugelassen
  1592. sind.
  1593.  
  1594. VAR
  1595.   MyNames  : NameList.List;
  1596.   name     : NameNode;
  1597.  
  1598. Die Prozeduren des Modules NameList können wie üblich importiert und
  1599. benutzt werden. Werden jedoch mehrere Ausprägungen des selben generischen
  1600. Moduls verwendet, treten Namenskonflikte auf. Diese könnten durch ständiges
  1601. qualifizieren umgangen werden, was jedoch sehr aufwendig und fehleranfällig
  1602. ist.
  1603.  
  1604.   NameList.Init(MyNames);
  1605.   New(name);
  1606.   NameList.InsertTop(MyNames,name);
  1607.  
  1608. Um dies zu umgehen kann eine Prozedur aus einem generischen Modul auch auf
  1609. eine andere Art aufgerufen werden:
  1610.  
  1611.   MyNames.Init;
  1612.   New(name);
  1613.   MyNames.InsertTop(name);
  1614.  
  1615. Für alle Ausprägungen eines generischen Moduls wird in einem Programm der
  1616. selbe Code benutzt, es wird also kein Code vervielfältigt. Aus diesem
  1617. Grund können auch nur Zeiger als generische Parameter dienen.
  1618.  
  1619. Werden für eine Implementation einer Datenstruktur gewisse Fähigkeiten des
  1620. generischen Parameters (wie eine Ordnungsrelation) benötigt, so kann dies
  1621. über Prozedurvariablen erreicht werden.
  1622.  
  1623. Es ist möglich, lokale Prozeduren als Parameter zu verwenden; es ist
  1624. allerdings nicht möglich, einer Prozedurvariablen eine lokale Prozedur
  1625. zuzuweisen.
  1626.  
  1627.  
  1628.   PROCEDURE LasseAltern(VAR l : NameList.List;um : INTEGER);
  1629.  
  1630.     PROCEDURE altere(n : NodePtr);
  1631.     BEGIN
  1632.       INC(n.alter,um)
  1633.     END altere;
  1634.  
  1635.   BEGIN
  1636.     l.Parse(altere);
  1637.   END LasseAltern;
  1638.  
  1639.  
  1640. C.9     Compilerswitches
  1641.  
  1642. Compiler-Switches (Schalter) können verwendet werden, um Teile eines Moduls
  1643. bedingt zu compilieren. Ein Compilerswitch wird durch $$ eingeleitet:
  1644.  
  1645. $$xxx:=yyy
  1646.  
  1647. Setzt den Switch xxx auf den Ausdruck yyy
  1648.  
  1649. Bsp:
  1650.  
  1651. $$RangeChk:=FALSE
  1652.  
  1653. Die Zustände der stapelbaren Schalter können durch
  1654.  
  1655. $$xxx:=OLD
  1656.  
  1657. wieder in ihren vorherigen Zustand zurückgesetzt werden, die maximale
  1658. Schachtelungstiefe jedes Schalters ist 16.
  1659.  
  1660. Zu jedem Projekt können bis zu 24 Schalter selbstdefiniert werden, dies
  1661. gschieht im Project-Requester (nicht das Verzeichnis Cluster:Projects
  1662. vergessen). Die Schalter können global, im Info Requester oder im Quelltext
  1663. gesetzt/gelöscht werden. Sie können zur bedingten Compilierung eingesetzt
  1664. werden.
  1665.  
  1666. Bsp: ein benutzerdefinierter Schalter 'Turbo' für eine 020/881 Version:
  1667.  
  1668. $$IF Turbo THEN
  1669.   $$MC68020:=TRUE
  1670.   $$MC68881:=TRUE
  1671. $$END
  1672.  
  1673. MODULE ...;
  1674.  
  1675. $$IF Turbo THEN
  1676.   TYPE  Float = REAL;
  1677.   IMPORT VectorReal AS Vectors;
  1678. $$ELSE
  1679.   TYPE  Float = FFP
  1680.   IMPORT VectorFFP AS Vectors;
  1681. $$END
  1682. ...
  1683.  
  1684. Je nach dem, ob 'Turbo' gesetzt ist, wird ein anderes Programm compiliert.
  1685.  
  1686. Folgende Swicthes sind vordefiniert:
  1687.  
  1688.     Name:       Kurz:   Geltung:   Init:   Bedeutung:
  1689. ----------------------------------------------------------------------------
  1690.   OverflowChk    V      Bereich    Info    Überlauf bei Rechenoperationen
  1691.   RangeChk       R        "         "      Bereichsprüfung bei Zuweisungen
  1692.                                            und Indizierungen
  1693.   StackChk       S        "         "      Stacküberprüfung an
  1694.                                            (bei Prozedur/Modulanfang)
  1695.   StrZeroChk     Z        "         "      Test bei Stringzuweisungen, ob
  1696.                                            Str.data[Str.len]=&0
  1697.   NilChk         N        "         "      Test bei Dereferenzierungen, ob
  1698.                                            der Zeiger NIL enthält
  1699.   ReturnChk               "         "      Test, ob eine Funktion einen Wert
  1700.                                            mit RETURN zurückliefert
  1701.   LocalChk       L        "         "      Test, ob eine Prozedur, die an
  1702.                                            eine Variable zugewiesen wird,
  1703.                                            eine globale Prozedur ist
  1704.   ConstChk                "        TRUE    Der Compiler verhindert, daß
  1705.                                            Konstanten oder REF-Parameter
  1706.                                            verändert werden. Dieser Switch hat
  1707.                                            nur Auswirkungen wärend der
  1708.                                            Compilierung, er hat keine
  1709.                                            Auswirkung auf den erzeugten Code.
  1710.   RelaxPtr                "       FALSE    Erlaubt bei Konstantendefinitionen
  1711.                                            die 'PTR wegzulassen, wenn ein
  1712.                                            Zeiger statt der Struktur erwartet
  1713.                                            wird.
  1714.   ChipMem        C      Modul      Info    Das Modul wird ins ChipMem gelegt
  1715.   LongAlign      A        "         "      Variablen und Elemente von
  1716.                                            Strukturen, die länger als 3 Bytes
  1717.                                            sind, werden auf Langwortgrenzen
  1718.                                            gelegt
  1719.   Library               Modul       "      Das Modul soll in einer Library
  1720.                                            verwendet werden
  1721.   Debug                   "         "      Das Modul wird mit Debug-Info
  1722.                                            compiliert.
  1723.   WithArea       W      Struktur   TRUE    Bei einer WITH Anweisung, lokalen
  1724.                                            Variablen oder Parametern einer
  1725.                                            Prozedur wird ein Sicherungsbereich
  1726.                                            eingerichtet. Dieser ist nötig,
  1727.                                            falls innerhalb der Struktur eine
  1728.                                            Prozedur aufgerufen wird. Wird
  1729.                                            innerhalb der Anweisung keine
  1730.                                            Prozedur benützt, sollte (* $W- *)
  1731.                                            davor gesetzt werde. Der Compiler
  1732.                                            meldet einen Fehler, wenn doch
  1733.                                            eine Prozedur aufgerufen wird.
  1734.   WithModify     M        "         "      Nach einer WITH Anweisung wird der
  1735.                                            Wert des Registers (falls  er
  1736.                                            verändert wurde) wieder in die
  1737.                                            Variable gesichert, (* $M- *)
  1738.                                            unterbindet dies, falls das
  1739.                                            Ergebnis nicht mehr benötigt wird.
  1740.   OwnHeap        O      Prozedur  FALSE    Funktionen, die einen offenen
  1741.                                            Rückgabetyp haben, müssen sich in
  1742.                                            einigen Situationen selbst um die
  1743.                                            Allozierung des Rückgabe-Stacks
  1744.                                            kümmern (siehe "Strings"). Dieser
  1745.                                            Schalter zeigt an, daß die Prozedur
  1746.                                            sich darum kümmert, und auch in
  1747.                                            diesen Situationen benutzt werden
  1748.                                            kann.
  1749.   PushRegs       P        "         "      Sichert alle Register am
  1750.                                            Prozeduranfang. Diese Prozedur
  1751.                                            kann dann auch innerhalb einer
  1752.                                            WITH Struktur benutzt werden, ohne
  1753.                                            daß die Registervariablen gesichert
  1754.                                            werden müssten.
  1755.   EntryCode      E        "        TRUE    Die Prozedur hat keinen Eingangs-
  1756.                                            code. Darf nur verwendet werden,
  1757.                                            wenn keine lokalen Parameter auf
  1758.                                            dem Stack benötigt werden (hat
  1759.                                            dann aber auch wenig Sinn ???)
  1760.   ModulaII              Bereich    Info    Es gelten die Syntaxregeln von
  1761.                                            Modula II
  1762.   MC68020                 "         "      Es wird Code für den 68020++
  1763.                                            erzeugt
  1764.   MC68881                 "         "      Es wird Code für den 68881++
  1765.                                            erzeugt
  1766.   AssTypeChk              "       FALSE    Der Assembler führt einen Typecheck
  1767.                                            durch
  1768.   ComplexAss              "        TRUE    Der Assembler erlaubt auch
  1769.                                            komplexere Adressierungsarten
  1770.  
  1771.