home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mod201j.zip / modula2.exe / os2doc / mod-us.inf (.txt) < prev    next >
OS/2 Help File  |  1996-03-29  |  177KB  |  5,825 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Release notes ΓòÉΓòÉΓòÉ
  3.  
  4. Welcome to beta version 2.01J. This compiler is a beta-ware. It is not 
  5. shareware nor is it freeware! 
  6.  
  7. Please read the following sections before using this compiler: 
  8.  
  9.  - Licence agreement
  10.  - How to contact the author
  11.  - To-do-list
  12.  
  13.  
  14. ΓòÉΓòÉΓòÉ 1.1. Licence agreement ΓòÉΓòÉΓòÉ
  15.  
  16. IF YOU DOWNLOAD OR USE THIS PROGRAM YOU AGREE TO THESE TERMS. 
  17.  
  18. The author grants you a licence to use the program "Canterbury-MODULA-2 BETA 
  19. 2.01J for OS/2" as a Beta tester. This package contains programs, source files, 
  20. and .INF documents. They are called "the programs" in the following sentences. 
  21.  
  22. The programs are demo- or beta-test versions. Hence their functionality is 
  23. still limited. The GA version may be different from this demo version. 
  24.  
  25. The programs are copyrighted. You obtain no rights on the programs other than 
  26. those granted you under this licence. If you do not agree to the terms listed 
  27. below you are not allowed to use the programs. 
  28.  
  29.     Under this licence, you may: 
  30.  
  31.         1. use the programs on one or more machines at a time 
  32.  
  33.         2. make copies of the programs for use or backup purposes. 
  34.  
  35.         3. make copies of the original file you downloaded and distribute it, 
  36.         provided that you transfer a copy of this licence to the other party. 
  37.         The other party agrees to these terms by its first use of the program. 
  38.  
  39.     You must reproduce the original copyright notice on each copy or partial 
  40.     copy of the programs. 
  41.  
  42.     You may NOT: 
  43.  
  44.         1. sublicence, rent, lease, or assign the programs 
  45.  
  46.         2. reverse assemble, reverse compile, or otherwise translate the 
  47.         programs. 
  48.  
  49.         3. use the programs for military purposes. 
  50.  
  51.     Under no circumstances is the author liable for any of the following: 
  52.  
  53.         1. third-party claims against you for losses or damages 
  54.  
  55.         2. loss of, or damage to, your records or data or 
  56.  
  57.         3. any economic damages even if the author is informed of their 
  58.         possibility. 
  59.  
  60.     Some jurisdictions do not allow these limitations or exclusions, so they 
  61.     may not apply to you. 
  62.  
  63.     The author does not warrant uninterrupted or error free operation of the 
  64.     programs. 
  65.  
  66.     IF YOU DOWNLOAD OR USE THIS PROGRAM YOU AGREE TO THESE TERMS. 
  67.  
  68.     THERE ARE NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING THE IMPLIED 
  69.     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 
  70.  
  71.     You may terminate this licence at any time. The author may terminate this 
  72.     licence if you fail to comply with any of its terms or if the GA version of 
  73.     these programs is available. In either event, you must destroy all your 
  74.     copies of the programs. 
  75.  
  76.     You may not sell, transfer, assign, or subcontract any of your rights or 
  77.     obligations under this licence. Any attempt to do so is void. 
  78.  
  79.     This licence is governed by the laws of the country in which you acquired 
  80.     the programs. 
  81.  
  82.  
  83. ΓòÉΓòÉΓòÉ 1.2. How to contact the author ΓòÉΓòÉΓòÉ
  84.  
  85. Please feel free to send any bug reports, comments, or proposals to the author 
  86. Juergen Neuhoff. You can do this via CompuServe e-mail (the prefered way): 
  87.  
  88.  CompuServe 76721,303 
  89.  
  90. This compiler will be marketed soon by: 
  91.  
  92.  Mill Hill & Canterbury Group, Ltd. 
  93.  P.O. BOX 1277 
  94.  Peralta NM 87042 
  95.  U.S.A. 
  96.  CompuServe 73261,1622 
  97.  
  98. If you downloaded this software from a CompuServe forum library, you can also 
  99. send public messages to that forum. This way other beta users may benefit from 
  100. your information, too. 
  101.  
  102.  
  103. ΓòÉΓòÉΓòÉ 1.3. To-do-list ΓòÉΓòÉΓòÉ
  104.  
  105. This compiler is still an early beta release. There are still many things to be 
  106. done. Future versions may include: 
  107.  
  108.   - Symbolic debugger support for IPMD or SD386:
  109.   This compiler genererates full HLL3-compatible debug-infos.
  110.   These should be supported by both IPMD and SD386, according
  111.   to IBM's statements. Unfortunately, both IBM debuggers are
  112.   still too buggy. This compiler version supports source-line
  113.   level debugging as well as some limited symbol support for SD386.
  114.  - Bug fixes
  115.  - "Direct-to-SOM" feature
  116.  - Modula-2 to IDL generation
  117.  - Class libraries
  118.  - IDE and/or closer integration into WPS
  119.   An IDE is currently being developed.
  120.  - Modula-style resource editors
  121.   A visual interface designer will be adapted to M2.
  122.  - COMPLEX type
  123.  - Range checking during runtime
  124.  - 32-to-16 bit thunking to foreign libraries
  125.   with different names/linkage
  126.  - Assembler-listing
  127.  
  128.  
  129. ΓòÉΓòÉΓòÉ 2. Introduction ΓòÉΓòÉΓòÉ
  130.  
  131. Modula-2 is a general-purpose programming language that evolved from Pascal. As 
  132. the name 'Modula' suggests, the module concept is an important feature of this 
  133. programming language. From Pascal it inherited a revised and systematic syntax. 
  134. This includes in particular the data structures such as arrays, records, 
  135. variant records, sets and pointers. Structured statements include the familiar 
  136. if, case, repeat, while, for, and with statements. 
  137.  
  138. This compiler is an OS/2 2.x or 3.0 implementation of Modula-2. It is based 
  139. upon the descriptions of the book 'Programming in Modula-2' by N.Wirth, fourth 
  140. edition. This documentation is not intended as a programmer's tutorial. It is 
  141. intentionally kept concise because its function is to serve as a reference for 
  142. programmers who wish to write efficient software running under the OS/2 2.x or 
  143. 3.0 operating system. 
  144.  
  145.  
  146. ΓòÉΓòÉΓòÉ 2.1. A first example ΓòÉΓòÉΓòÉ
  147.  
  148. This compiler is an OS/2 text-mode application. It is started from a command 
  149. prompt of an OS/2 full screen or window screen. It can neither run under DOS 
  150. nor as a Presentation Manager application. The compiler is called by typing in 
  151. the command 'MOD'. 
  152.  
  153. Let us take as an example a simple program doing nothing else than simply 
  154. displaying a 'Hello World' message on the screen. The OS/2 2.x or 3.0 
  155. System-Editor can be used to create such a Modula-2 source file. The contents 
  156. of the source file might look like this: 
  157.  
  158.  
  159.   MODULE HELLO;
  160.   IMPORT InOut;
  161.   BEGIN
  162.     InOut.WriteString( "Hello World" );
  163.     InOut.WriteLn();
  164.   END HELLO.
  165.  
  166. Type in the following commands to create, compile, link and run this sample 
  167. program from a OS/2 fullscreen or windowed screen: 
  168.  
  169.   E HELLO.MOD         <enter>
  170.   MOD HELLO -o -m -p  <enter>
  171.   LINK386 @HELLO.RSP  <enter>
  172.   HELLO               <enter>
  173.  
  174. The output from the sample program looks like this: 
  175.  
  176.   Hello World
  177.  
  178. The necessary linker response file HELLO.RSP is created automatically by the 
  179. Modula-2 compiler because of the '-m' switch. The compiler creates object files 
  180. in a format suitable for the OS/2 2.x or 3.0 linker program LINK386.EXE, which 
  181. produces the final HELLO.EXE executable file. The command switch '-p' causes a 
  182. verbose screen output of all the sources including possible error prompts. The 
  183. optimization switch '-o' tells the compiler to produce an all-optimized code. 
  184.  
  185.  
  186. ΓòÉΓòÉΓòÉ 2.2. Features of compiler version 2.01 ΓòÉΓòÉΓòÉ
  187.  
  188. This compiler provides the following major features: 
  189.  
  190.   - target operating system:
  191.    - 32-bit OS/2 2.x or 3.0
  192.    - 16-bit OS/2 1.x
  193.    - 16-bit MS-Windows 3.x
  194.    - 16-bit DOS
  195.    Note: Modula-libraries are currently only available
  196.    for 32-bit OS/2 2.x or 3.0. Future releases will support the other
  197.    target systems.
  198.  
  199.   - compiler output:
  200.    - 16 or 32-bit object files suitable for
  201.     LINK.EXE or LINK386.EXE.
  202.    - linker response file(s)
  203.    - linker definition file(s)
  204.  
  205.   - integrated Make or Build facility:
  206.    - 'Make' recompiles dependent updated modules.
  207.    - 'Build' recompiles all dependent modules.
  208.  
  209.   - Baisc standard types and functions with different sizes:
  210.    - 1-, 2- and 4-bytes cardinal and integer types.
  211.    - 4- and 8-bytes real types
  212.  
  213.   - Set types with up to 256 elements:
  214.    - e.g. TYPE CharSet = SET OF CHAR;
  215.  
  216.   - Powerful language extensions:
  217.    - Allow underscore '_' for identifier names
  218.     (as in OS/2 APIs)
  219.    - Bitwise operators 'AND' 'OR' 'XOR' 'SHL' 'SHR' 'NOT'
  220.    - New logical operator 'XOR'
  221.    - Object orientation similar to Oberon language
  222.    - System Object Model support under OS/2
  223.    - Initialized variables expressed as typed constants
  224.    - Multidimensional open arrays
  225.    - Symbolic INLINE assembler
  226.    - NEAR or FAR keywords for INTEL 80x86 segmentation
  227.    - Extended imports
  228.  
  229.   - Dynamic link library development for OS/2 2.x or 3.0
  230.  
  231.   - Definition modules for external .OBJ .DLL .LIB files
  232.    - OS/2 2.x or 3.0 Control Program interface
  233.    - OS/2 2.x or 3.0 Graphics Program interface
  234.    - OS/2 2.x or 3.0 Presentation Manager interface
  235.    - OS/2 2.x or 3.0 Workplace Shell interface
  236.    - OS/2 2.x or 3.0 Keyboard interface
  237.    - OS/2 2.x or 3.0 Video interface
  238.    - OS/2 2.x or 3.0 Mouse interface
  239.  
  240.  
  241. ΓòÉΓòÉΓòÉ 3. Syntax ΓòÉΓòÉΓòÉ
  242.  
  243. A language is an infinite set of sentences, namely the sentences well formed 
  244. according to its syntax.In Modula-2, these sentences are called compilation 
  245. units. Each compilation unit is a program or definition module stored in a 
  246. source file. Each unit is a finite sequence of symbols from a finite 
  247. vocabulary. The vocabulary of Modula-2 consists of identifiers, numbers, 
  248. strings, operators, delimiters and comments. They are called lexical symbols 
  249. and are composed of character sequences. 
  250.  
  251. To describe the syntax, a formalism similar to that of Backus-Naur is used. 
  252. Angular brackets '[' and ']' denote an optional syntactic entity, and braces 
  253. '{' and '}' denote its repetition (zero or more times). A '|' character means a 
  254. choice between two entities. Syntactic entities are formed from the Modula-2 
  255. set of lexical symbols. They are called non-terminal symbols and are denoted by 
  256. English words expressing their intuitive meaning. Symbols of the language 
  257. vocabulary, the terminal symbols, are denoted by strings enclosed in quote 
  258. marks or words written in capital letters, so-called reserved words. 
  259. Non-terminals are formed from terminals and non-terminals using productions 
  260. with fixed syntactic rules. Productions are denoted by the '=' sign. 
  261.  
  262. Example 1: 
  263.  
  264.   Decl = VAR { VarDecl ";" }
  265.  
  266. A declaration is started by the reserved keyword VAR followed by an possibly 
  267. empty list of variable declarations seperated by semicolons. 
  268.  
  269. Example 2: 
  270.  
  271.   Stmt = RETURN [ Expr ] | EXIT
  272.  
  273. A statement can be a RETURN statement possibly followed by an expression. Or it 
  274. can be an EXIT. 
  275.  
  276.  
  277. ΓòÉΓòÉΓòÉ 4. Vocabulary and representation ΓòÉΓòÉΓòÉ
  278.  
  279. The representation of symbols in term of characters is defined using the ASCII 
  280. set. Symbols are identifiers, numbers, strings, character constants, operators 
  281. and delimiters, and comments. Blanks and line breaks must not occur within 
  282. symbols ( except in comments, and, in the case of blanks, in strings ). They 
  283. are ignored unless they are needed to separate two consecutive symbols. Capital 
  284. and lower letters are considered as being distinct. 
  285.  
  286.  
  287. ΓòÉΓòÉΓòÉ 4.1. Identifiers ΓòÉΓòÉΓòÉ
  288.  
  289. ΓûÉ Ident       = FirstLetter { "_" | Letter | Digit }
  290. ΓûÉ FirstLetter = "_" | Letter
  291.  
  292. Identifiers are sequences of letters and digits. The first character however 
  293. must not be a digit. If the language-extensions are enabled, then the 
  294. underscore character '_' is also allowed for identifiers. This is needed for 
  295. identifiers from OS/2 2.x or 3.0 APIs. Otherwise the programmer should refrain 
  296. from freely using underscores for his own identifiers. 
  297.  
  298. Examples include : 
  299.  
  300.   x scan Modula GetSymbol
  301.  
  302. Examples with underscore '_' enabled : 
  303.  
  304.   FILE_READONLY  OPEN_SHARE_DENYWRITE  vector_graphics
  305.  
  306.  
  307. ΓòÉΓòÉΓòÉ 4.2. Numbers ΓòÉΓòÉΓòÉ
  308.  
  309. ΓûÉ Number      = Integer | Real
  310. ΓûÉ Integer     = Digit { Digit } | OctalDigit { OctalDigit } "B" |
  311. ΓûÉ               Digit { HexDigit } "H"
  312. ΓûÉ Real        = Digit { Digit } "." { Digit } [ ScaleFactor ]
  313. ΓûÉ ScaleFactor = "E" [ "+" | "-" ] Digit { Digit }
  314. ΓûÉ HexDigit    = Digit | "A" | "B" | "C" | "D" | "E" | "F"
  315. ΓûÉ Digit       = "0"  | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
  316. ΓûÉ OctalDigit  = "0"  | "1" | "2" | "3" | "4" | "5" | "6" | "7"
  317.  
  318. Numbers are unsigned integers or real numbers. Integers are sequences of 
  319. digits. If the number is followed by the letter 'B', it is taken as an octal 
  320. number; if it is followed by the letter 'H', it is taken as a hexadecimal 
  321. number. 
  322.  
  323. The default type for an integer number i is assigned according to the following 
  324. value ranges: 
  325.  
  326.   SHORTINT          0 ............ 127
  327.   INTEGER         128 ......... 32 767
  328.   LONGINT      32 768 .. 2 147 483 647
  329.  
  330.   SHORTCARD         0 ............ 255
  331.   CARDINAL        255 ......... 65 535
  332.   LONGCARD     65 536 .. 4 294 967 296
  333.  
  334. This means, that a given value can have 1 or 2 types. The value 128 for 
  335. instance is both of type INTEGER and SHORTCARD. This looks more complicated 
  336. than it actually is, since SHORTINT and INTEGER and LONGINT are compatible with 
  337. each other, and SHORTCARD and CARDINAL and LONGCARD are compatible with each 
  338. other as well. 
  339.  
  340. A real number is a sequence of decimal digits with a decimal point. It is 
  341. optinally followed by a decimal scale factor. The scale factor is introduced by 
  342. the letter 'E' and an optional '+' or '-' sign, to be followed by the digits of 
  343. the scale factor itself. The introducing letter 'E' is understood to be a 'ten 
  344. to the power of'. A real number is internally stored as a LONGREAL. The decimal 
  345. range and precision are guarantied for up to 15 significand digits and a power 
  346. of 10 range from -307 to +308. If there only up to 6 siginificand digits and a 
  347. power of 10 range from -37 to 38 than a real value can also be treated as a 
  348. SHORTREAL. 
  349.  
  350. Integer number examples: 
  351.  
  352.   1980 3764B 7BCH 0FFFFFFFFH
  353.  
  354. Real number examples: 
  355.  
  356.   123456789012.345E-307  12345.   12.3
  357.  
  358.  
  359. ΓòÉΓòÉΓòÉ 4.3. Strings ΓòÉΓòÉΓòÉ
  360.  
  361. ΓûÉ String      = "'" { Character } "'" | """ { Character } """
  362.  
  363. Strings are sequences of characters enclosed in quote marks. Both double quotes 
  364. and single quotes (apostrophes) may be used as quote marks. However, the 
  365. opening and closing marks must match each other, and they cannot appear within 
  366. the string. A string must not extend over the end of a line. This compiler 
  367. always appends a terminating zero to the internal storage of a string, though 
  368. this not explicitly stated in Wirth's standard. A string s can be assigned to 
  369. an array a of characters if the length of s is strictly less to the number of 
  370. elements of a. This ensures that the internal terminating zero can always be 
  371. appended to the resulting a. The purpose is to simplify possible tests for the 
  372. end of a string. 
  373.  
  374. String examples: 
  375.  
  376.   "MODULA"  "Don't worry"  'codeword "Barbarossa"'
  377.  
  378.  
  379. ΓòÉΓòÉΓòÉ 4.4. Characters ΓòÉΓòÉΓòÉ
  380.  
  381. ΓûÉ CharConst   = "'" Character "'" |
  382. ΓûÉ               OctalDigit { OctalDigit } "C" |
  383. ΓûÉ               Digit { HexDigit } "X"
  384.  
  385. A character constant represents an ASCII character. They are either denoted by 
  386. a single character enclosed in single quote marks or by the ordinal number of 
  387. the character in octal notation followed by the letter 'C'. This compiler, with 
  388. language-extensions enabled, also allows a hexadecimal notation followed by the 
  389. letter 'X' for the ordinal value of the character. The actual appearance and 
  390. meaning of the characters depends on the active OS/2 2.x or 3.0 code page and 
  391. font. 
  392.  
  393.  
  394. ΓòÉΓòÉΓòÉ 4.5. Operators and delimiters ΓòÉΓòÉΓòÉ
  395.  
  396. Operators and delimiters are the special characters, character-pairs and 
  397. reserved words. The reserved words consist exclusively of capital letters and 
  398. must not be used in the role of identifiers. The symbols '#' and '<>' are 
  399. synonyms, so are '&' and 'AND', as well as '~' and 'NOT'. 
  400.  
  401.  
  402. ΓòÉΓòÉΓòÉ 4.5.1. Special characters ΓòÉΓòÉΓòÉ
  403.  
  404.   +   -   *   /   &   |   ~
  405.  
  406.   .   ,   ;   ^   ..  :   :=
  407.  
  408.   =   #   <   >   <>  <=  >=
  409.  
  410.   (   )   [   ]   {   }
  411.  
  412.   "   '
  413.  
  414.  
  415. ΓòÉΓòÉΓòÉ 4.5.2. Reserved words ΓòÉΓòÉΓòÉ
  416.  
  417. The following identifiers are treated as reserved words. They cannot be taken 
  418. for user names. 
  419.  
  420.  AND            DO             IF             OF             SET
  421.  ARRAY          ELSE           IMPLEMENTATION OR             THEN
  422.  BEGIN          ELSIF          IMPORT         POINTER        TO
  423.  BY             END            IN             PROCEDURE      TYPE
  424.  CASE           EXIT           LOOP           QUALIFIED      UNTIL
  425.  CONST          EXPORT         MOD            RECORD         VAR
  426.  DEFINITION     FOR            MODULE         REPEAT         WHILE
  427.  DIV            FROM           NOT            RETURN         WITH
  428.  
  429. This compiler also regards few more identifiers as extended reserved words for 
  430. an extended Modula-2 langauge. 
  431.  
  432.  
  433. ΓòÉΓòÉΓòÉ 4.5.3. Extended reserved words ΓòÉΓòÉΓòÉ
  434.  
  435. If the language-extensions are enabled, then the following identifiers are 
  436. treated as reserved words as well. They cannot be taken then for user 
  437. identifiers. 
  438.  
  439.    FAR
  440.    IS
  441.    NEAR
  442.    SHL
  443.    SHR
  444.    XOR
  445.  
  446.  
  447. ΓòÉΓòÉΓòÉ 4.6. Comments ΓòÉΓòÉΓòÉ
  448.  
  449. Comments may be inserted between any two symbols in a program. A comment is any 
  450. sequence of characters enclosed in the brackets "(*" and "*)". Comments may be 
  451. nested, and they do not affect the meaning of a program. Comments may also 
  452. contain compiler-directives. 
  453.  
  454. Comments are skipped by the compiler and serve as additional information to the 
  455. human reader. The INLINE-assembler also treats a ';' as the start of a comment 
  456. up to the end of a line. 
  457.  
  458.  
  459. ΓòÉΓòÉΓòÉ 5. Scope rules for declarations ΓòÉΓòÉΓòÉ
  460.  
  461. Every identifier occuring in a program must be introduced by a declaration, 
  462. unless it is a standard-identifier. The latter is considered to be predeclared. 
  463. This compiler keeps the predeclarations in a pseudo definition module called 
  464. SYSTEM. These standard identifiers are valid in all parts of a program. They 
  465. are somewhat pervasive. 
  466.  
  467. Declarations also serve to specify certain permanent properties of an item, 
  468. such as whether it is a constant, a type, a variable, a procedure or a module. 
  469. The identifier is then used to refer to the associated item. Such a reference 
  470. is possible in those parts of a program only which are within the so-called 
  471. scope of the declaration. No identifier may denote more than one item within a 
  472. given scope. The scope extends textually from the point of the declaration to 
  473. the end of the block of the procedure or module to which the declaration 
  474. belongs and hence to which the item is local. The scope rule has the following 
  475. amendments: 
  476.  
  477.           (1) If a type P is defined as a pointer-type, e.g. P = POINTER TO T, 
  478.           then the identifier T can be declared textually following the 
  479.           declaration of P, but it must lie within the same scope. 
  480.  
  481.           (2) Field identifiers of a record-type are valid only in field 
  482.           designators and in with-statements refering to a variable of that 
  483.           record type. 
  484.  
  485.           (3) If an identifier defined in module M1 is exported, the scope 
  486.           expands to the end of the block which contains M1. If M1 is a 
  487.           compilation-unit it extends to all those units which import M1. 
  488.  
  489.  
  490. ΓòÉΓòÉΓòÉ 5.1. Qualification of identifiers ΓòÉΓòÉΓòÉ
  491.  
  492. ΓûÉ Qualident        = { Qualifier "." } Ident
  493. ΓûÉ Qualifier        = Ident
  494.  
  495. An identifier may be qualified. In this case it is prefixed by another 
  496. identifier which designates the module of a local module-declaration or of a 
  497. global compilation-unit in which the qualified identifier is defined and 
  498. exported. The prefix and the identifier are separated by a period. 
  499. Standard-identifiers are all rooted in the SYSTEM module for this compiler 
  500. implementation and are somewhat pervasive, hence there is no need for 
  501. qualifying them. 
  502.  
  503.  
  504. ΓòÉΓòÉΓòÉ 5.2. Standard identifiers ΓòÉΓòÉΓòÉ
  505.  
  506. Some of the standard identifiers from this compiler might not be present with 
  507. other implementations. They are marked with an asterisk. They include NEW, 
  508. DISPOSE, LONG... and SHORT... and are treated like standard identifiers in this 
  509. compiler because of different basic type sizes and dynamic memory support. 
  510.  
  511.   ABS           FLOAT         LONGREAL     *SHORTCARD
  512.   BITSET        HALT         *LONGTRUNC    *SHORTFLOAT
  513.   BOOLEAN       HIGH          MAX          *SHORTINT
  514.   CAP           INC           MIN          *SHORTNIL
  515.   CARDINAL      INCL         *NEW          *SHORTREAL
  516.   CHAR          INTEGER       NIL          *SHORTTRUNC
  517.   CHR          *LONG          ODD           SIZE
  518.   DEC          *LONGCARD      ORD           TRUE
  519.  *DISPOSE      *LONGFLOAT     PROC          TRUNC
  520.   EXCL          LONGINT       REAL          VAL
  521.   FALSE        *LONGNIL      *SHORT
  522.  
  523.  
  524. ΓòÉΓòÉΓòÉ 6. Declarations ΓòÉΓòÉΓòÉ
  525.  
  526. ΓûÉ Decl          = CONST { ConstDecl ";" } | TYPE { TypeDecl ";" } |
  527. ΓûÉ                 VAR { VarDecl ";" } | ProcedureDecl | ModuleDecl
  528.  
  529. Every item occuring in a program such as types, variables or procedures must be 
  530. introduced by a declaration. A declaration serves to specify certain permanent 
  531. properties of an object. The following kinds of objects can be declared for 
  532. user identifiers: 
  533.  
  534.  - constant
  535.  - types
  536.  - variables
  537.  - procedures
  538.  - modules
  539.  
  540.  
  541. ΓòÉΓòÉΓòÉ 6.1. Constant declarations ΓòÉΓòÉΓòÉ
  542.  
  543. ΓûÉ ConstDecl     = ConstDef | ConstVarDecl "=" TypedConst
  544. ΓûÉ ConstVarDecl  = Ident ":" FormalType
  545. ΓûÉ ConstDef      = Ident "=" ConstExpr
  546. ΓûÉ ConstExpr     = Expr
  547.  
  548. A constant declaration associates an identifier with a constant value. A 
  549. constant expression is an expression which can be evaluated by a mere textual 
  550. scan without actually executing the program. Its operands are constants. 
  551.  
  552. Examples of constant declarations: 
  553.  
  554.   CONST
  555.     N     = 100;
  556.     limit = 2*N - 1;
  557.     all   = {0..WordSize-1};
  558.     bound = MAX(INTEGER) - N;
  559.  
  560. This compiler also supports the declaration of initialized variables using 
  561. typed-constants. This feature is only available if the language-extensions are 
  562. enabled. 
  563.  
  564.  
  565. ΓòÉΓòÉΓòÉ 6.2. Type declarations ΓòÉΓòÉΓòÉ
  566.  
  567. ΓûÉ TypeDecl      = Ident = Type
  568. ΓûÉ Type          = SimpleType | ArrayType | RecordType | SetType |
  569. ΓûÉ                 PointerType | ProcedureType
  570. ΓûÉ SimpleType    = Qualident | Enumeration | SubrangeType
  571.  
  572. A data type determines the set of values that variables of that type may 
  573. assume, and the operators that are applicable. A type declaration is used to 
  574. associate an identifier with the type. Such association may be with 
  575. unstructured types, such as: 
  576.  
  577.  - basic types
  578.  - enumerations
  579.  - subranges
  580.  - pointer-types
  581.  - procedure-types
  582.  
  583. Or the association may be with structured types, in which case it defines the 
  584. structures of variables of this type and, by implication, the operators that 
  585. are applicable to the components. There are three different structures, namely: 
  586.  
  587.  - records
  588.  - arrays
  589.  - sets
  590.  
  591. Examples of type declarations: 
  592.  
  593.   TYPE
  594.     Color      = (red, green, blue);
  595.     Index      = [1..80];
  596.     Card       = ARRAY Index OF CHAR;
  597.     Node       = RECORD
  598.       key        : CARDINAL;
  599.       left,right : TreePtr;
  600.                  END;
  601.     Tint       = SET OF Color;
  602.     TrrePtr    = POINTER TO Node;
  603.     Function   = PROCEDURE( CARDINAL ) : CARDINAL;
  604.  
  605.  
  606. ΓòÉΓòÉΓòÉ 6.2.1. Basic types ΓòÉΓòÉΓòÉ
  607.  
  608. The following basic types are denoted by predeclared standard identifiers. The 
  609. values of a given basic type and the bytes occupied in memory are as follows: 
  610.  
  611.   SHORTINT               -128 ...           127      1 byte
  612.   INTEGER             -32 768 ...        32 767      2 bytes
  613.   LONGINT      -2 147 483 648 ... 2 147 483 647      4 bytes
  614.  
  615.   SHORTCARD                 0 ...           255      1 byte
  616.   CARDINAL                  0 ...        65 535      2 bytes
  617.   LONGCARD                  0 ... 4 294 967 296      4 bytes
  618.  
  619.   BOOLEAN      FALSE and TRUE                        1 byte
  620.  
  621.   CHAR         the characters of the extended        1 byte
  622.                ASCII set (0X ... 0FFX).
  623.  
  624.   SHORTREAL    [+|-] 1.17E-38  ... 3.37E+38          4 bytes
  625.   LONGREAL     [+|-] 2.23E-308 ... 1.67E+308         8 bytes
  626.  
  627.   REAL         same as LONGREAL by default, or if    8 bytes
  628.                compiler switch '-R8' or
  629.                compiler directive (*$R8*).
  630.  
  631.                same as SHORTREAL if                  4 bytes
  632.                compiler switch '-R4' or
  633.                compiler directive (*$R4*).
  634.  
  635.  
  636. ΓòÉΓòÉΓòÉ 6.2.2. Enumerations ΓòÉΓòÉΓòÉ
  637.  
  638. ΓûÉ Enumeration    = "(" IdentList ")"
  639. ΓûÉ IdentList       = Ident { "," Ident }
  640.  
  641. An enumeration is a list of identifiers that denote the values which constitute 
  642. a data type. These identifiers are used as constants in the program. They, and 
  643. no other values, belong to this type. The values are ordered, and the ordering 
  644. relation is defined by their sequence in the enumeration. The ordinal number of 
  645. the first value is 0. An enumeration with up to 256 values occupies only 1 byte 
  646. in memory, else 2 bytes. 
  647.  
  648. Examples of enumerations: 
  649.  
  650.   (red, green, blue)
  651.   (club, diamond, heart, spade)
  652.   (Monday, Tueday, Wednesday, Thursday, Friday, Saturday, Sunday)
  653.  
  654.  
  655. ΓòÉΓòÉΓòÉ 6.2.3. Subrange types ΓòÉΓòÉΓòÉ
  656.  
  657. ΓûÉ SubrangeType   = [ BaseType ] "[" ConstExpr ".." ConstExpr "]"
  658. ΓûÉ BaseType       = Qualident
  659.  
  660. A type T may be defined as a subrange of another, basic or enumeration type T1 
  661. (except reals) by specification of the least and the highest value in the 
  662. subrange. The first constant specifies the lower bound, and must not be greater 
  663. than the upper bound. The type T1 of the bounds is called the base type of T, 
  664. and all operators applicable to operands of type T1 are also applicable to 
  665. operands of type T. However, a value to be assigned to a variable of a subrange 
  666. type must lie within the specified interval. The base type can be specified by 
  667. an identifier (possibly qualified in this compiler) preceding the bounds. If it 
  668. is omitted, and if the lower bound is a non-negative number, the base type is 
  669. taken to be a cardinal (in this compiler LONGCARD for 32-bit models like OS/2 
  670. 2.x or 3.0, or CARDINAL for 16-bit models); if it is a negative number, it is 
  671. an integer (in this compiler LONGINT for 32-bit models like OS/2 2.x or 3.0, or 
  672. INTEGER for 16-bit models). 
  673.  
  674. A type T1 is said to be compatible with a type T0, if it is declared either as 
  675. T1 = T0 or as a subrange of T0, or if T0 is a subrange of T1, or if T0 and T1 
  676. are both subranges of the same base type. 
  677.  
  678. Examples of subrange types: 
  679.  
  680.   [ 0 .. N-1 ]
  681.   Color [red .. green]
  682.   [ 'A' .. 'Z' ]
  683.   [ Monday .. Friday ]
  684.  
  685.  
  686. ΓòÉΓòÉΓòÉ 6.2.4. Array types ΓòÉΓòÉΓòÉ
  687.  
  688. ΓûÉ ArrayType      = ARRAY IndexType { "," IndexType } OF Type
  689. ΓûÉ IndexType      = SimpleType
  690.  
  691. An array is a structure consisting of a fixed number of elements that are all 
  692. of the same type, called the component type. The elements of the array are 
  693. designated by indices, values belonging to the index type. The array type 
  694. declaration specifies the component type as well as the index type. The latter 
  695. must be an enumeration, a subrange type, or one of the basic types BOOLEAN or 
  696. CHAR. 
  697.  
  698. A declaration of the form 
  699.  
  700.   ARRAY T1, T2, ... , Tn OF T
  701.  
  702. with index types T1 ... Tn must be understood as an abbreviation for the 
  703. declaration 
  704.  
  705.   ARRAY T1 OF
  706.     ARRAY T2 OF
  707.       ...
  708.       ARRAY Tn OF T
  709.  
  710. Examples of array types: 
  711.  
  712.   ARRAY [0..N-1] OF CARDINAL
  713.   ARRAY [1..10], [1..20] OF [0..99]
  714.   ARRAY [-10..+10] OF BOOLEAN
  715.   ARRAY WeedDay OF Color
  716.   ARRAY Color OF WeekDay
  717.  
  718.  
  719. ΓòÉΓòÉΓòÉ 6.2.5. Record types ΓòÉΓòÉΓòÉ
  720.  
  721. ΓûÉ RecordType     = RECORD [ "(" RecordBase ")" ] FieldListSeq END
  722. ΓûÉ RecordBase     = Qualident
  723. ΓûÉ FieldListSeq   = FieldList { ";" FieldList }
  724. ΓûÉ FieldList      = [ IdentList ":" Type | Variants ]
  725. ΓûÉ Variants       = CASE [ Ident ":" ] Qualident
  726. ΓûÉ                  OF VariantList ElseVariant END
  727. ΓûÉ VariantList    = Variant { "|" Variant }
  728. ΓûÉ ElseVariant    = ELSE FieldListSeq
  729. ΓûÉ Variant        = CaseLabelList ":" FieldListSeq
  730. ΓûÉ CaseLabelList  = CaseLabels { "," CaseLabels }
  731. ΓûÉ CaseLabels     = ConstExpr [ ".." ConstExpr ]
  732.  
  733. A record type is a structure consisting of a fixed number of elements of 
  734. possibly different types. The record type declaration specifies for each 
  735. element, called a field or member, its type and an identifier that denotes the 
  736. field. The scope of these fields is the record definition itself, but they are 
  737. also visible within field designators refering to elements of record variables, 
  738. and within with statements. 
  739.  
  740. A record type may have several variant sections each of them occupying the same 
  741. memory. A value of a tag type indicates which variant is assumed by the 
  742. section. There may also be a tag field, which, if declared with an tag 
  743. identifier, stores the tag value during runtime. Individual variant structures 
  744. are identified by case labels. These labels are constants of the tag type, 
  745. possibly indicated by the tag field. 
  746.  
  747. This compiler also provides object oriented features in connection with record 
  748. types, similar to the new OBERON language. For further details, refer to the 
  749. documentation sections: 
  750.  
  751.   - object oriented features
  752.   - extending record types
  753.   - dynamic type tests for records
  754.   - type guard selectors
  755.   - regional type guards
  756.   - Type bound procedures
  757.   - System Object Model
  758.  
  759. These object oriented features are available only if the language-extensions is 
  760. enabled. 
  761.  
  762.  
  763. ΓòÉΓòÉΓòÉ 6.2.6. Set types ΓòÉΓòÉΓòÉ
  764.  
  765. ΓûÉ SetType        = SET OF SimpleType
  766. ΓûÉ SimpleType     = Qualident | Enumeration | SubrangeType
  767.  
  768. A set type is defined as a SET OF T. It comprises all sets of values of its 
  769. base type T. The base type must be a a subrange of the integers between 0 and 
  770. N-1, or a subrange of an enumeration type with at most N values, where N is the 
  771. maximum number of elements. This compiler accepts sets with up to 256 elements, 
  772. e.g. the common SET OF CHAR is allowed. 
  773.  
  774. The predeclared type BITSET = SET OF [0..15] is valid in all parts of the 
  775. program, because it is one of the standard-identifiers and as such is 
  776. automatically exported from the SYSTEM-module. 
  777.  
  778.  
  779. ΓòÉΓòÉΓòÉ 6.2.7. Pointer types ΓòÉΓòÉΓòÉ
  780.  
  781. ΓûÉ PointerType    = [ NEAR | FAR ] POINTER TO Type
  782.  
  783. Variables of pointer type P assume as values pointers to variables of some type 
  784. T. The pointer type P is said to be bound to T, and T is the pointer base type 
  785. of P. If p is a variable of type P = POINTER TO T then its value is generated 
  786. by a call to an allocation procedure in a storage management module. The 
  787. standard procedure call NEW(p) is translated into an ALLOCATE(p,SIZE(T)) and is 
  788. the prefered way to generate a pointer value for allocating dynamic memory. The 
  789. standard procedure call DISPOSE(p) is translated into a DEALLOCATE(p) and is 
  790. the prefered way to release a pointer value by freeing up allocated dynamic 
  791. memory. 
  792.  
  793. If the language-extensions are enabled the default size of a pointer type 
  794. declaration can be overwritten by the NEAR or FAR keywords. This is useful for 
  795. accessing far memory segments outside the near DGROUP memory segment. The 
  796. default pointer size (NEAR or FAR) depends on the memory-model and is NEAR for 
  797. the 32-bit OS/2 2.x or 3.0 flat memory model. 
  798.  
  799. Besides above mentioned pointer values, a pointer variable may assume the value 
  800. NIL, which can be thought as pointing to no variable at all. If the 
  801. language-extensions are enabled, then LONGNIL or SHORTNIL can be used instead 
  802. of NIL for pointers with explicit FAR or NEAR specifications. 
  803.  
  804.  
  805. ΓòÉΓòÉΓòÉ 6.2.8. Procedure types ΓòÉΓòÉΓòÉ
  806.  
  807. ΓûÉ ProcedureType  = [ NEAR | FAR ] PROCEDURE [ FormalTypeList ]
  808. ΓûÉ FormalTypeList = "(" FTSectionList ")" [ ":" Qualident ]
  809. ΓûÉ FTSectionList  = [ FTSection { "," FTSection } ]
  810. ΓûÉ FTSection      = [ [ NEAR | FAR ] VAR ] FormalType
  811. ΓûÉ FormalType       = { ARRAY OF } Qualident
  812.  
  813. Variables of a procedure type T may assume as their value a pointer to a 
  814. procedure P. The types of the formal parameters of P must be the same as those 
  815. indicated in the formal type list list of T. The same holds for the result type 
  816. in the case of a function procedure. P must not be declared local to another 
  817. procedure, and neither can it be a generic standard procedure. 
  818.  
  819. If the language-extensions are enabled, the NEAR or FAR attributes can be used. 
  820. FAR indicates that the procedure pointer may assume procedures declared in 
  821. another code segment, or that a formal parameter is passed as a reference to a 
  822. variable of another data segment, e.g. outside DGROUP. This is useful for 
  823. memory-models with many code or data segments. 
  824.  
  825.  
  826. ΓòÉΓòÉΓòÉ 6.3. Variable declarations ΓòÉΓòÉΓòÉ
  827.  
  828. ΓûÉ VarDecl          = VarIdent { "," VarIdent } ":" Type
  829. ΓûÉ VarIdent         = Ident [ FarPointerConst ]
  830. ΓûÉ FarPointerConst  = "[" ConstExpr ":" ConstExpr "]"
  831.  
  832. Variable declarations serve to introduce variables and associate them with 
  833. identifiers that must be unique within the given scope. They also serve to 
  834. associate fixed data-types with the variables. Variables whose identifiers 
  835. appear in the same list are all of the same type. 
  836.  
  837. Examples of variable declarations (refer to the examples in the section about 
  838. type-declarations): 
  839.  
  840.   i,j,k : INTEGER;
  841.   x,y   : REAL;
  842.   p,q   : BOOLEAN;
  843.   s     : BITSET;
  844.   FUNC  : PROCEDURE( VAR INTEGER, LONGINT ) : BOOLEAN;
  845.   f     : FUNC;
  846.   a     : ARRAY Index OF CARDINAL;
  847.   w     : ARRAY [0..7] OF RECORD
  848.             ch    : CHAR;
  849.             count : CARDINAL;
  850.           END;
  851.   t     : TreePtr;
  852.  
  853. If the language-extensions are enabled then variables of a a pointer-type  to 
  854. T0 and VAR-parameters of a record-type T0 may assume values whose type T1 is an 
  855. record-extension of their declared type T0. 
  856.  
  857.  
  858. ΓòÉΓòÉΓòÉ 6.4. Procedure declarations ΓòÉΓòÉΓòÉ
  859.  
  860. ΓûÉ ProcedureDecl    = ProcedureHeading ";" Block Ident |
  861. ΓûÉ                    ProcedureHeading ";" FORWARD
  862. ΓûÉ ProcedureHeading = [ NEAR | FAR ] PROCEDURE
  863. ΓûÉ                    [ Receiver ] Ident [ FormalParameters ]
  864. ΓûÉ Receiver         = "(" [ [ NEAR | FAR ] VAR ] Ident : Ident ")"
  865. ΓûÉ Block            = { Decl } [ BEGIN StmtSeq ] END
  866. ΓûÉ Decl             = CONST { ConstDecl ";" } | TYPE { TypeDecl ";" } |
  867. ΓûÉ                    VAR { VarDecl ";" } | ProcedureDecl | ModuleDecl
  868.  
  869. Procedure declarations consist of a procedure heading and a block which is said 
  870. to be the procedure body. The heading specifies the procedure identifier, the 
  871. formal-parameters and the result type (if any). The body contains declarations 
  872. and statements. The procedure identifier is repeated at the end of the 
  873. procedure declaration. If the language-extensions are enabled, then an optional 
  874. receiver may be specified. The receiver is a leading formal parameter for the 
  875. target object on which to apply the procedure. It is needed for type-bound 
  876. procedures only. It closely resembles the concepts of the new Oberon-2 language 
  877. for classes and methods. 
  878.  
  879. There are two kinds of procedures, namely proper procedures and function 
  880. procedures. The latter are activated by a function designator in an expression, 
  881. yielding a result that serves as an operand in the expression. Proper 
  882. procedures are activated by a procedure-call. The function procedure is 
  883. distinguished in the declaration by indication of the return type of its result 
  884. following the parameter list. Its body must contain a RETURN-statement which 
  885. defines the result of the function procedure. 
  886.  
  887. The procedure body can also be declared FORWARD. This makes it possible for 
  888. procedures to mutually call each other recursively. A forward declared 
  889. procedure must be fully declared later within the same lexical scope, fully 
  890. repeating the procedure heading, with a full procedure block. 
  891.  
  892. If the language-extensions are enabled, then the FAR or NEAR modifiers can be 
  893. used to indicate, whether the procedure resides in a far or near code segment. 
  894. This may be needed for 16-bit APIs like the one of MS-Windows 3.x. Under OS/2 
  895. 2.x or 3.0 however there is no need for explicitly overriding the default NEAR 
  896. attribute because of the 32-bit flat memory-model. 
  897.  
  898. All the constants, variables, types, modules and procedures declared within the 
  899. block that constitutes the procedure body are lexically local to the procedure. 
  900. The values of local variables, including those of local modules, are undefined 
  901. upon entry to the procedure, because local variables reside on the stack. Each 
  902. time a procedure is called a new local stack frame is activated for the local 
  903. vriables and remains alive for the runtime of the procedure. Since procedures 
  904. may be declared as local items too, procedure declarations may be nested. Every 
  905. item is said to be declared at a certain level of nesting. If e.g. it is 
  906. declared local to a procedure at level k, it itself has level k+1. Items 
  907. declared in the module that constitutes a compilation unit are defined to be at 
  908. level 0. 
  909.  
  910. In addition to its formal parameters and locally declared items, the items 
  911. declared in the environment of the procedure so far (at scope levels outside 
  912. the procedure) are also visible to the procedure, unless some of those items 
  913. have the same name as an item declared locally. 
  914.  
  915. The use of the procedure identifier in a call within its declaration implies 
  916. recursive activation of the procedure including the creation of another local 
  917. stack frame for the local variables. 
  918.  
  919.  
  920. ΓòÉΓòÉΓòÉ 6.4.1. Formal parameters ΓòÉΓòÉΓòÉ
  921.  
  922. ΓûÉ FormalParameters = "(" FPSectionList ")" [ ":" Qualident ]
  923. ΓûÉ FPSectionList    = [ FPSection { ";" FPSection } ]
  924. ΓûÉ FPSection        = [ [ NEAR | FAR ] VAR ] IdentList ":" FormalType
  925. ΓûÉ FormalType       = { ARRAY OF } Qualident
  926.  
  927. Formal parameters are identifiers which denote actual parameters specified in 
  928. the procedure-call. The correspondence between formal and actual parameters is 
  929. established when the procedure is called. There are two kind s of parameters, 
  930. namely value and variable parameters. The kind is indicated in the formal 
  931. parameter list. Value parameters stand for local variables to which the result 
  932. of the evaluation of the corresponding actual parameter is assigned as initial 
  933. value. Variables parameters correspond to actual parameters that are variables, 
  934. and they stand for these variables. They are passed by reference, not by value, 
  935. using the addresses. While variable parameters are indicated by the symbol VAR, 
  936. value parameters are introduced without that symbol. 
  937.  
  938. If the language-extensions are enabled, the variable parameters can be declared 
  939. as NEAR or FAR. This serves as a hint for the procedure to reference the actual 
  940. corresponding variables in a near DGROUP data segment or far segment. 
  941.  
  942. Formal parameters are local to the procedure; that is, their scope is the 
  943. program text that constitutes the procedure declaration. 
  944.  
  945. The type of each formal parameter is specified in the parameter list. For 
  946. variable parameters, it must be identical to the corresponding actual 
  947. parameter's type, except in the case of a record-type, with language-extensions 
  948. enabled, where it must be a base type of the corresponding actual parameter's 
  949. type. For value parameters, the rules of assignment hold. 
  950.  
  951. If the formal parameter's type is specified as ARRAY OF T, the parameter is 
  952. said to be an open array parameter, and the corresponding actual parameter may 
  953. be any array with element type T. If the language-extensions are enabled, a 
  954. formal parameter's type can even be a multidimensional open array. An open 
  955. array parameter can only be accessed elementwise, with an index range from 0 to 
  956. N-1, where N is the actual number of elements. The formal array may also wholy 
  957. occur as an actual parameter whose formal parameter is an open array itself. 
  958.  
  959. A function procedure without parameters has an empty parameter list. It must be 
  960. called by a function designator whose actual parameter list is emtpy, too, but 
  961. with enclosing brackets. If a formal parameter specifies a procedure type then 
  962. the corresponding actual parameter must be either a procedure declared globally 
  963. at zero scope level, or it must be a variable or parameter of that procedure 
  964. type. It cannot be a generic standard-procedure. 
  965.  
  966. This compiler also permits structured return types. 
  967.  
  968.  
  969. ΓòÉΓòÉΓòÉ 6.4.2. Standard procedures ΓòÉΓòÉΓòÉ
  970.  
  971. Standard procedures are predefined (in this compiler, they reside in the SYSTEM 
  972. module). Some are generic procedures that cannot be explicitly declared, i.e. 
  973. they apply to classes of operand types or have several possible parameter list 
  974. forms. 
  975.  
  976. The following standard function procedures are available with this compiler: 
  977.  
  978.  Procedure name           Description 
  979.  
  980.  ABS( x )                 absolute value; result type = argument type 
  981.  
  982.  CAP( x )                 if ch is a lower case letter, the corresponding 
  983.                           capital letter, else the the same letter 
  984.  
  985.  CHR( x )                 the character with ordinal number x; 
  986.                           CHR(x)=VAL(CHAR,x) 
  987.  
  988.  FLOAT( x )               x of type SHORTINT, INTEGER, LONGINT, SHORTCARD, 
  989.                           CARDINAL, or LONGCARD, represented as a value of type 
  990.                           REAL 
  991.  
  992.  LONGFLOAT( x )           x of type SHORTINT, INTEGER, LONGINT, SHORTCARD, 
  993.                           CARDINAL, or LONGCARD, represented as a value of type 
  994.                           LONGREAL 
  995.  
  996.  SHORTFLOAT( x )          x of type SHORTINT, INTEGER, LONGINT, SHORTCARD, 
  997.                           CARDINAL, or LONGCARD, represented as a value of type 
  998.                           SHORTREAL 
  999.  
  1000.  HIGH( a )                high index bound of array a 
  1001.  
  1002.  MAX( T )                 the maximum value of type T, where T is a basic type 
  1003.                           (except reals), an enumeration or a subrange type. 
  1004.  
  1005.  MIN( T )                 the minimum value of type T, where T is a basic type 
  1006.                           (except reals), an enumeration or a subrange type. 
  1007.  
  1008.  ODD( x )                 x MOD 2 <> 0 
  1009.  
  1010.  ORD( x )                 ordinal number (of a cardinal type with same size 
  1011.                           than that of x) in the set of values defined by type 
  1012.                           T of x. T is any enumeration type, CHAR, SHORTINT, 
  1013.                           INTEGER, LONGINT, SHORTCARD, CARDINAL, or LONGCARD. 
  1014.  
  1015.  SIZE( T )                the number of bytes of a specified type T. 
  1016.  
  1017.  SIZE( x )                the number of bytes required by a variable for its 
  1018.                           type. 
  1019.  
  1020.  TRUNC( x )               real number x (of type REAL, SHORTREAL or LONGREAL) 
  1021.                           truncated to its integral part of type INTEGER. 
  1022.  
  1023.  LONGTRUNC( x )           real number x (of type REAL, SHORTREAL or LONGREAL) 
  1024.                           truncated to its integral part of type LONGINT. 
  1025.  
  1026.  SHORTTRUNC( x )          real number x (of type REAL, SHORTREAL or LONGREAL) 
  1027.                           truncated to its integral part of type SHORTINT. 
  1028.  
  1029.  LONG( x )                size extended value of x, where x is an integer, 
  1030.                           cardinal or real expression, according to the 
  1031.                           follwing rules: 
  1032.                           SHORTINT->INTEGER, 
  1033.                           INTEGER->LONGINT, 
  1034.                           LONGINT->LONGINT, 
  1035.                           SHORTCARD->CARDINAL, 
  1036.                           CARDINAL->LONGCARD, 
  1037.                           LONGCARD->LONGCARD, 
  1038.                           SHORTREAL->LONGREAL, 
  1039.                           LONGREAL->LONGREAL, 
  1040.                           REAL->LONGREAL 
  1041.  
  1042.  SHORT( x )               size truncated value of x, where x is an integer, 
  1043.                           cardinal or real expression, according to the 
  1044.                           following rules: 
  1045.                           LONGINT->INTEGER, 
  1046.                           INTEGER->SHORTINT, 
  1047.                           SHORTINT->SHORTINT, 
  1048.                           LONGCARD->CARDINAL, 
  1049.                           CARDINAL->SHORTCARD, 
  1050.                           SHORTCARD->SHORTCARD, 
  1051.                           LONGREAL->SHORTREAL, 
  1052.                           SHORTREAL->SHORTREAL, 
  1053.                           REAL->SHORTREAL 
  1054.  
  1055.  VAL( T, x )              the value with ordinal number x and with type T. T is 
  1056.                           any enumeration type, CHAR, SHORTINT, INTEGER, 
  1057.                           LONGINT, SHORTCARD, CARDINAL or LONGCARD. 
  1058.                           VAL(T,ORD(x))=x, if x of type T. 
  1059.  
  1060.  The following standard proper procedures are available with this compiler: 
  1061.  
  1062.  Procedure name           Description 
  1063.  
  1064.  DEC( x )                 x := x - 1, where x is a variable with type SHORTINT, 
  1065.                           INTEGER, LONGINT, SHORTCARD, CARDINAL, LONGCARD, 
  1066.                           CHAR, enumeration or subrange. 
  1067.  
  1068.  DEC( x, n )              x := x - n, where x is a variable with type SHORTINT, 
  1069.                           INTEGER, LONGINT, SHORTCARD, CARDINAL, LONGCARD, 
  1070.                           CHAR, enumeration or subrange. n is any cardinal 
  1071.                           expression. 
  1072.  
  1073.  EXCL( s, i )             s := s - { i } 
  1074.  
  1075.  HALT                     terminate program execution 
  1076.  
  1077.  INC( x )                 x := x + 1, where x is a variable with type SHORTINT, 
  1078.                           INTEGER, LONGINT, SHORTCARD, CARDINAL, LONGCARD, 
  1079.                           CHAR, enumeration or subrange. 
  1080.  
  1081.  INC( x, n )              x := x + n, where x is a variable with type SHORTINT, 
  1082.                           INTEGER, LONGINT, SHORTCARD, CARDINAL, LONGCARD, 
  1083.                           CHAR, enumeration or subrange. n is any cardinal 
  1084.                           expression. 
  1085.  
  1086.  INCL( s, i )             s := s - { i } 
  1087.  
  1088.  NEW( p )                 ALLOCATE(p,SIZE(T)); Allocate dynamic memory and 
  1089.                           assign its address to a pointer p. 
  1090.  
  1091.  DISPOSE( p )             DEALLOCATE(p,SIZE(T)); Deallocate dynamic memory and 
  1092.                           set p to NIL. 
  1093.  
  1094.  
  1095. ΓòÉΓòÉΓòÉ 6.5. Modules ΓòÉΓòÉΓòÉ
  1096.  
  1097. ΓûÉ ModuleDecl    = MODULE Ident [ Priority ] { Import } [ Export ]
  1098. ΓûÉ                 Block Ident
  1099. ΓûÉ Priority      = [ "[" ConstExpr "]" ]
  1100. ΓûÉ Import        = [ FROM Ident ] IMPORT IdentList ";"
  1101. ΓûÉ Export        = EXPORT [ QUALIFIED ] IdentList ";"
  1102. ΓûÉ IdentList     = Ident { "," Ident }
  1103.  
  1104. A module is a collection of declarations of constants, types, variables, 
  1105. modules and procedures, and a sequence of statements. They are enclosed in 
  1106. brackets MODULE and END. The module heading contains the module identfier, and 
  1107. possibly a number of import lists and an export list. An import list specifies 
  1108. all identifiers of items that are declared outside but used within the module 
  1109. and therefore have to be imported. The export list specifies all identifiers of 
  1110. items declared within the module and used outside. Hence, a module constitutes 
  1111. a visibility wall around its local items whose transparancy is strictly under 
  1112. control of the programmer. 
  1113.  
  1114. Items local to a module are said to be at the same scope level as the module. 
  1115. They can be considered as being local to the procedure enclosing the module but 
  1116. residing within a more restricted scope. The module identifier is repeated at 
  1117. the end of the declaration. 
  1118.  
  1119.  
  1120. ΓòÉΓòÉΓòÉ 6.5.1. Purpose of local modules ΓòÉΓòÉΓòÉ
  1121.  
  1122. The statement sequence which constitutes the module body is executed when the 
  1123. procedure or compilation unit to which the module is local is called. If 
  1124. several modules are declared, then these bodies are executed in the sequence in 
  1125. which the modules occur. These bodies serve to intialize local variables and 
  1126. must be considered as prefixes to the enclosing procedure's or compilation 
  1127. unit's statement part. 
  1128.  
  1129. If an indentifier occurs in the import (export) list, then the denoted item may 
  1130. be used inside (outside) the module as if the module brackets did not exist. 
  1131. If, however, the symbol EXPORT is followed by the symbol QUALIFIED, then the 
  1132. listed identifiers must be prefixed with the module's identifier when used 
  1133. outside the module. Such a qualified export serves to avoid clashes of 
  1134. identical identifiers exported from different modules and presumably denoting 
  1135. different items. 
  1136.  
  1137. A module may feature several import lists which may be prefixed with the symbol 
  1138. FROM and a module identifier. The FROM clause has the effect of unqualifying 
  1139. the imported identifiers. Hence they may be used within the module as if they 
  1140. had been exported in a normal, non-qualified mode. 
  1141.  
  1142. If a record-type is exported, all its field identifiers are exported too. The 
  1143. same is true for the constant identifiers in the case of an enumeration-type. 
  1144.  
  1145.  
  1146. ΓòÉΓòÉΓòÉ 6.5.2. Module priority ΓòÉΓòÉΓòÉ
  1147.  
  1148. A classical problem of multitasking is that of exchanging data among various 
  1149. processes, e.g. as part of a comunication between them. Common variables are 
  1150. used to transfer data among processes, and raise the problem of harmonious 
  1151. cooperation. No process should meddle with common variables while another is 
  1152. performing a critical action upon them. A reasonable solution to this problem 
  1153. is to encapsulate shared variables in a module which guarantees mutual 
  1154. exclusion of processes. Such a module is also called a monitor. Access to its 
  1155. local data is, because they are hidden, restricted to statements of the 
  1156. monitor's procedures. These procedures might be exported. A module is 
  1157. designated to be a monitor by specifiying a priority in its heading. The 
  1158. priority value is a cardinal number. 
  1159.  
  1160. Under OS/2 2.x or 3.0 there up to 32 different priority levels from 0 to 31. 
  1161. Each priority value has its own OS/2 mutex semaphore. This way the procedures 
  1162. inside the priority module are protected against other threads. The compiler 
  1163. implements Modula's processes as OS/2 threads, the basic time-sliced task 
  1164. units. 
  1165.  
  1166.  
  1167. ΓòÉΓòÉΓòÉ 7. Expressions ΓòÉΓòÉΓòÉ
  1168.  
  1169. ΓûÉ Expr            = SimpleExpr [ Relation SimpleExpr ]
  1170. ΓûÉ SimpleExpr      = [ "+" | "-" ] Term { AddOperator Term }
  1171. ΓûÉ Term            = Factor { MulOperator Factor }
  1172. ΓûÉ Factor          = CharConst | Number | String | Set |
  1173. ΓûÉ                   Designator [ ActualParams ] | "(" Expr ")" |
  1174. ΓûÉ                   Not Factor
  1175. ΓûÉ Set             = Qualident "{" [ ElemList ] "}"
  1176. ΓûÉ ElemList        = Elem { "," Elem }
  1177. ΓûÉ Elem            = Expr { ".." Elem }
  1178. ΓûÉ ActualParams    = "(" [ Expr { "," Expr } ] ")"
  1179.  
  1180. Expressions are constructs denoting rules of computation whereby constants and 
  1181. current values of variables are combined to derive other values by the 
  1182. application of operators and function procedures. Expressions consist of 
  1183. operands and operators. Parentheses may be used to express specific 
  1184. associations of operators and operands. 
  1185.  
  1186. Examples of expressions (refer to the examples in the section about 
  1187. variable-declarations): 
  1188.  
  1189.   expression:          denoted type:
  1190.     1980                 CARDINAL
  1191.     k DIV 3              INTEGER
  1192.     NOT p OR q           BOOLEAN
  1193.     (i+j) * (i-j)        CARDINAL
  1194.     s - {8,9,13}         BITSET
  1195.     a[i] + a[j]          CARDINAL
  1196.     a[i+j] * a[i-j]      CARDINAL
  1197.     (0<=k) & (k<100)     BOOLEAN
  1198.     t^.key = 0           BOOLEAN
  1199.     {13..15} <= s        BOOLEAN
  1200.     i IN {0,5..8,15}     BOOLEAN
  1201.  
  1202.  
  1203. ΓòÉΓòÉΓòÉ 7.1. Operands ΓòÉΓòÉΓòÉ
  1204.  
  1205. ΓûÉ Designator  = Qualident { Selector }
  1206. ΓûÉ Selector    = "." Ident | "[" IndexList "]" | "^" | TypeGuard
  1207. ΓûÉ IndexList   = Expr { "," Expr }
  1208. ΓûÉ TypeGuard   = "(" Qualident ")"
  1209.  
  1210. With the exception of literal constants, that is numbers, strings, characters 
  1211. and sets, operands are denoted by designators. A designator consists of an 
  1212. identifier referring to the constant, variable, or procedure to be designated. 
  1213. Such an identifier may possibly be qualified by module identifiers, and it may 
  1214. be followed by selectors, if the designated item is an element of a structure. 
  1215.  
  1216. If the structure is an array A, then the designator A[E] denotes that component 
  1217. of A whose index is the current value of the expression E. The index type of A 
  1218. must be assignment-compatible with the type of E. A designator of the form 
  1219. A[E1,E2,...,En] stands for A[E1][E2]...[En]. 
  1220.  
  1221. If P designates a pointer, P^ denotes the variable, that is referenced by P. 
  1222.  
  1223. If R is a structured variable of a record-type then the designator R.f denotes 
  1224. the record field f of R. If the language-extensions are enabled and a procedure 
  1225. m has been declared with a formal receiver type for record R, then R.m denotes 
  1226. the type-bound procedure. Again, if the language-extensions are enabled, the 
  1227. typeguard v(T0) asserts that v is of type T0; that is, program execution is 
  1228. aborted (in this compiler with a return value 3), if it is not of type T0. The 
  1229. guard is applicable if 
  1230.      (1) T is an extension of the declared type T0 of v, and 
  1231.      (2) v is a variable parameter of record type or v is a record pointer. 
  1232.  
  1233.  If the designated item is a variable, then the designator refers to the 
  1234.  variable's current value. If the item is a function procedure, a designator 
  1235.  without parameter list refers to that procedure. If it is followed by a 
  1236.  (possibly empty) parameter list, the designator implies an activation of the 
  1237.  procedure and stands for the value resulting from its execution, that is the 
  1238.  returned value. The types of these actual parameters must correspond to the 
  1239.  formal-parameters as specified in the procedure-declaration. 
  1240.  
  1241.  Examples of designators (see examples in the section about 
  1242.  variable-declarations): 
  1243.  
  1244.     Designator:     Denoted type:
  1245.       k               INTEGER
  1246.       a[i]            CARDINAL
  1247.       w[3].ch         CHAR
  1248.       t^.key          CARDINAL
  1249.       t^.left^.right  TreePtr
  1250.  
  1251.  
  1252. ΓòÉΓòÉΓòÉ 7.2. Operators ΓòÉΓòÉΓòÉ
  1253.  
  1254. ΓûÉ Relation        = "=" | "<>" | "#" | "<" | "<=" | ">" | ">=" | IN | IS
  1255. ΓûÉ AddOperator     = "+" | "-" | OR | XOR
  1256. ΓûÉ MulOperator     = "*" | "/" | DIV | MOD | AND | "&" | SHL | SHR
  1257. ΓûÉ Not             = NOT | "~"
  1258.  
  1259. The syntax of expressions distinguishes between four classes of operators with 
  1260. different precedences or binding strengths. The operators '~' and NOT have the 
  1261. highest precedence, followed by multiplication operators, addition operators 
  1262. and relations. Operators of the same precedence associate from left to right. 
  1263. For example, x-y-z stands for (x-y)-z. 
  1264.  
  1265.  
  1266. ΓòÉΓòÉΓòÉ 7.2.1. Arithmetic operators ΓòÉΓòÉΓòÉ
  1267.  
  1268. The following operators are defined in standard Modula-2 language: 
  1269.  
  1270.      +         binary addition or unary identity 
  1271.      -         binary subtraction or unary sign inversion 
  1272.      *         multiplication 
  1273.      /         real division 
  1274.      DIV       integer division 
  1275.      MOD       modulus 
  1276.  
  1277.  The arithmetic operators (except /) apply to operands of type SHORTINT, 
  1278.  INTEGER, LONGINT, SHORTCARD, CARDINAL, or LONGCARD, or subranges thereof. Both 
  1279.  operands must be either of a cardinal, or they must be both of an integer 
  1280.  type. The resulting type is LONGINT, INTEGER or SHORTINT if both operands are 
  1281.  of integer types, depending on the longest operand type. The resulting type is 
  1282.  LONGCARD, CARDINAL or SHORTCARD if both operands are of cardinal types. 
  1283.  
  1284.  The operators '+', '-', and '*' also apply to real operands. In this case, 
  1285.  both operands must be of a real type, and the result is a LONGREAL or 
  1286.  SHORTREAL depending on the longest operand type. The division operator '/' 
  1287.  applies to real operands only. The '+' and '-' operators can also be used as 
  1288.  unary operators, with a single operand only. In such a cases '-' denotes sign 
  1289.  inversion and '+' denotes the identitiy operation. Sign inversion can be 
  1290.  applied to integer or real operands. The operations DIV and MOD are defined by 
  1291.  the following rules: 
  1292.  
  1293.    x DIV y is equal to the truncated quotient of x / y
  1294.    x MOD y is equal to the remainder of x DIV y
  1295.    x = (x DIV y) * y + (x MOD y), 0 <= (x MOD y) < y
  1296.  
  1297.  If the language-extensions are enabled, then the following bitwise operators 
  1298.  can be used for cardinal or integer operands: 
  1299.  
  1300.      OR        bitwise or 
  1301.      XOR       bitwise exclusive or 
  1302.      AND       bitwise and 
  1303.      &         bitwise and, same as AND 
  1304.      SHL       bitwise shift left 
  1305.      SHR       bitwise shift right 
  1306.      NOT       unary bitwise negation 
  1307.      ~         unary bitwise negation 
  1308.  
  1309.  
  1310. ΓòÉΓòÉΓòÉ 7.2.2. Logical operators ΓòÉΓòÉΓòÉ
  1311.  
  1312. The following logical operators are available with standard Modula-2. They 
  1313. apply to boolean operands and yield a boolean result. 
  1314.  
  1315.      OR        logical conjunction 
  1316.                p OR q means "if p then TRUE, otherwise q" 
  1317.      AND       logical disjunction 
  1318.                p AND q means "if p then q, otherwise FALSE" 
  1319.      &         logical disjunction, same as AND 
  1320.                p & q means "if p then q, otherwise FALSE" 
  1321.      NOT       unary logical negation 
  1322.  
  1323.  If the language-extensions are enabled, then the following, additional logical 
  1324.  operator is available for boolean operands: 
  1325.  
  1326.      XOR       logical exclusive conjunction 
  1327.                p XOR q means "if p then NOT q, otherwise q" 
  1328.  
  1329.  
  1330. ΓòÉΓòÉΓòÉ 7.2.3. Set operators ΓòÉΓòÉΓòÉ
  1331.  
  1332. The following operators apply to operands of any set type and yield a result in 
  1333. the same type. 
  1334.  
  1335.      +         set union 
  1336.                x IN (s1 + s2) means "(x IN s1) OR (x IN s2)" 
  1337.      -         set difference 
  1338.                x IN (s1 - s2) means "(x IN s1) AND NOT (x IN s2)" 
  1339.      *         set intersection 
  1340.                x IN (s1 * s2) means "(x IN s1) AND (x IN s2)" 
  1341.      /         symmetric set difference 
  1342.                x IN (s1 / s2) means "(x IN s1) XOR (x IN s2)" 
  1343.  
  1344.  
  1345. ΓòÉΓòÉΓòÉ 7.2.4. Relations ΓòÉΓòÉΓòÉ
  1346.  
  1347. Relations yield a boolean result. The ordering relations apply to the 
  1348. basic-types SHORTINT, INTEGER, LONGINT, SHORTCARD, CARDINAL, LONGCARD, BOOLEAN, 
  1349. CHAR, SHORTREAL, LONGREAL, REAL, to enumerations and to subrange-types. 
  1350.  
  1351.      =         equal 
  1352.      #         unequal 
  1353.      <>        unequal, same as # 
  1354.      <         less than 
  1355.      <=        less than or equal 
  1356.                set inclusion 
  1357.      >         greater than 
  1358.      >=        greater than or equal 
  1359.                set inclusion 
  1360.      IN        element contained in a set 
  1361.      IS        type test 
  1362.  
  1363.  The relations '=' and '#' also apply to sets and pointers. If the relational 
  1364.  operators '<=' and '>=' are applied to sets, they denote (improper) inclusion. 
  1365.  The relation IN denotes set membership. In an expression of the form x IN s, 
  1366.  the expression s must be of type SET OF T, where T is the type of x, or where 
  1367.  T is compatible with the type of x. 
  1368.  
  1369.  The IS relation is only available when the language-extensions are enabled. v 
  1370.  IS T stands for 'v is of type T' and is called a type-test. It is applicable 
  1371.  if 
  1372.      (1) T is an extension of the declared type T0 of v, and 
  1373.      (2) v is a variable parameter of record type or v is a record pointer. 
  1374.  Assuming, for instance, that T is an extension of T0 and that v is a 
  1375.  designator declared of type T0, then the test 'v IS T' determines whether the 
  1376.  actually designated variable is (not only a T0, but also) a T. The value of 
  1377.  'NIL IS T' is undefined. 
  1378.  
  1379.  
  1380. ΓòÉΓòÉΓòÉ 8. Statements ΓòÉΓòÉΓòÉ
  1381.  
  1382. ΓûÉ Stmt           = [ Assignment | ProcedureCall | IfStmt | CaseStmt |
  1383. ΓûÉ                  WhileStmt | RepeatStmt | LoopStmt | ForStmt |
  1384. ΓûÉ                  WithStmt | EXIT | ReturnStmt ]
  1385.  
  1386. Statements denote execution of the program. There are elementary and structured 
  1387. statements. Elementary statements are not composed of any parts that are 
  1388. themselves statements, as is the case with structured statements. Structured 
  1389. statements are used to express sequencing, and conditional, selective, and 
  1390. repetitive execution. 
  1391.  
  1392. The elementary statements are the assignment, the procedure-call, the 
  1393. return-statement and the exit-statement. A structured statement can be an 
  1394. if-statement, a case-statement, a while-statement, a repeat-statement, a 
  1395. loop-statement, a for-statement or a with-statement. Except for the latter one, 
  1396. they control the flow of program execution. 
  1397.  
  1398. A statement may also be empty, in which case it denotes no action. The empty 
  1399. statement is included included in order to relax punctuation rules in 
  1400. statement-sequences. 
  1401.  
  1402.  
  1403. ΓòÉΓòÉΓòÉ 8.1. Assignments ΓòÉΓòÉΓòÉ
  1404.  
  1405. ΓûÉ Assignment     = Designator ":=" Expr
  1406.  
  1407. An assignment serves to replace the current value of a variable by a new value 
  1408. specified by an expression. The assignment operator is written as ':=' and 
  1409. pronounced as 'becomes'. The designator to the left of the assignment operator 
  1410. denotes a variable. After an assignment is executed, the variable has the value 
  1411. obtained by evaluating the expression. The old value is lost. It is 
  1412. overwritten. 
  1413.  
  1414. The type of the result variable must be assignment-compatible with the type of 
  1415. the expression to the right of the operator. Operand types are said to be 
  1416. assignment-compatible, if either they are compatible or both are integers 
  1417. (SHORTINT, INTEGER, LONGINT) or cardinals (SHORTCARD, CARDINAL, LONGCARD) or 
  1418. subranges with integer or cardinal base types. If, however, truncation occurs 
  1419. as a result of an assignment then the operands are not regarded as 
  1420. assignment-compatible. Cardinal and integer operands (and their subranges) are 
  1421. also assignment-compatible. though they are not compatible in expressions. 
  1422.  
  1423. A string of length n1 can be assigned to an array variable with n2 > n1 
  1424. elements of type CHAR. In this case, the string value is extended with a null 
  1425. character 0C. A string of length 1 is compatible with the type CHAR. 
  1426.  
  1427. Examples of assignments: 
  1428.  
  1429.   i := k;
  1430.   p := i = j;
  1431.   j := log2( i+j );
  1432.   s := { 2, 3, 5, 7, 11, 13 };
  1433.   a[ i ] := (i + j) * (i - j);
  1434.   t^.key := i;
  1435.   w[ i+1 ].ch := "A";
  1436.  
  1437. If the language-extensions are enabled then an expression with an extended-type 
  1438. may assigned to the left variable, too. 
  1439.  
  1440.  
  1441. ΓòÉΓòÉΓòÉ 8.2. Procedure calls ΓòÉΓòÉΓòÉ
  1442.  
  1443. ΓûÉ ProcedureCall  = Designator [ ActualParams ]
  1444. ΓûÉ ActualParams   = "(" [ Expr { "," Expr } ] ")"
  1445.  
  1446. A procedure call serves to activate a procedure. The program flow is transfered 
  1447. to the activated procedure for execution, and after its completion execution 
  1448. continues with the statement after the procedure call. The procedure call may 
  1449. contain a list of actual parameters that are substituted in place of their 
  1450. corresponding formal-parameters defined in the procedure-declaration. The 
  1451. positions of the actual and formal parameters establishes the correspondence 
  1452. between them. There are two kinds of parameters: variable and value parameters. 
  1453.  
  1454. In the case of variable parameters, the actual parameter can only be a 
  1455. designator denoting a variable. If it designates an element of a structured 
  1456. variable, all selectors are evaluated before the formal-to-actual parameter 
  1457. substitution. All of this takes place before the execution of the called 
  1458. procedure. If the parameter is a value parameter, the corresponding actual 
  1459. parameter must be an expression. This expression is evaluated prior to the 
  1460. procedure activation, and the resulting value is assigned to the formal 
  1461. parameter, which now constitutes a local variable. 
  1462.  
  1463. The types of corresponding actual and formal parameters must be equal in the 
  1464. case of variable parameters and assignment-compatible in the case of value 
  1465. parameters. If the language-extensions are enabled then if the formal parameter 
  1466. is a variable of a record type or a value parameter of a record-pointer-type, 
  1467. then the actual parameter can be of an extended type similar to the assignment 
  1468. rules. 
  1469.  
  1470. Examples of procedure calls: 
  1471.  
  1472.   Read( i );
  1473.   Write( j*2+1, 6 );
  1474.   INC( a[i] );
  1475.  
  1476.  
  1477. ΓòÉΓòÉΓòÉ 8.3. Statement sequences ΓòÉΓòÉΓòÉ
  1478.  
  1479. ΓûÉ StmtSeq        = Stmt { ";" Stmt }
  1480.  
  1481. A computation is a sequence of actions that transforms an intial state into a 
  1482. final one that, it is hoped, satisfies the stated result condition. In 
  1483. Modula-2, the statement is the basic unit of execution. Thus the execution 
  1484. sequence of actions is expressed in a statement sequence 
  1485.  
  1486.  Stmt1; Stmt2; Stmt3; ... Stmti; ... Stmtn;
  1487.  
  1488. The semicolon is a statement separator that indicates that the action specified 
  1489. by a given statement is to be succeeded by the one textually following the 
  1490. separator. Only flow-of-control statements such as a return-statement or an 
  1491. exit-statement or loop constructs can cause the execution to continue somewhere 
  1492. else. 
  1493.  
  1494.  
  1495. ΓòÉΓòÉΓòÉ 8.4. If statements ΓòÉΓòÉΓòÉ
  1496.  
  1497. ΓûÉ IfStmt         = IF BoolExpr THEN StmtSeq
  1498. ΓûÉ                  { ELSIF BoolExpr THEN StmtSeq }
  1499. ΓûÉ                  [ ELSE StmtSeq ] END
  1500. ΓûÉ BoolExpr       = Expr
  1501.  
  1502. If-Statements specify the conditional execution of guarded statements. The 
  1503. boolean expression preceding a statement sequence serves as a guard. These 
  1504. expressions are evaluated in sequence of occurance, until one evaluates to 
  1505. TRUE, whence its associated statement sequence is executed. If no boolean 
  1506. expression is evaluated to TRUE, the statement sequence following the symbol 
  1507. ELSE is executed, if there. 
  1508.  
  1509. Example: 
  1510.  
  1511.   IF (ch >= "A") & (ch <= "Z") THEN
  1512.     ReadIdentifier
  1513.   ELSIF (ch >= '0') & (ch <= '9') THEN
  1514.     ReadNumber
  1515.   ELSIF ch = '"' THEN
  1516.     ReadString( '"' );
  1517.   ELSIF ch = "'" THEN
  1518.     ReadString( "'" );
  1519.   ELSE
  1520.     SpecialCharacter
  1521.   END;
  1522.  
  1523.  
  1524. ΓòÉΓòÉΓòÉ 8.5. Case statements ΓòÉΓòÉΓòÉ
  1525.  
  1526. ΓûÉ CaseStmt       = CASE Expr OF Case { "|" Case } [ ELSE StmtSeq ] END
  1527. ΓûÉ Case           = CaseLabelList ":" StmtSeq
  1528. ΓûÉ CaseLabelList  = CaseLabels { "," CaseLabels }
  1529. ΓûÉ CaseLabels     = ConstExpr [ ".." ConstExpr ]
  1530.  
  1531. Case statements specify the selection and execution of a statement-sequence 
  1532. according to the value of an expression. First the case expression is 
  1533. evaluated; then the statement sequence is executed whose case label list 
  1534. contains the obtained value. The type of the case expression can only be a 
  1535. basic-type (except reals), an enumeration-type, or a subrange-type. All labels 
  1536. must be strictly-compatible with that type. Case labels are constants, and no 
  1537. value must occur more than once. If the value of the expression does not occur 
  1538. as a label of any case, the statement sequence following the symbol ELSE is 
  1539. selected, if there is one. 
  1540.  
  1541. Example: 
  1542.  
  1543.   CASE ch OF
  1544.     "A".."Z"  : ReadIdentifier;
  1545.   | "0".."9"  : ReadNumber;
  1546.   | "'" , '"' : ReadString( ch );
  1547.   ELSE          SpecialCharacter;
  1548.   END;
  1549.  
  1550.  
  1551. ΓòÉΓòÉΓòÉ 8.6. While statements ΓòÉΓòÉΓòÉ
  1552.  
  1553. ΓûÉ WhileStmt      = WHILE BoolExpr DO StmtSeq END
  1554. ΓûÉ BoolExpr       = Expr
  1555.  
  1556. While-statements specify repetition. If the boolean expression yields TRUE, the 
  1557. statement-sequence is executed. The expression evaluation and the statement 
  1558. execution are repeated as long as the boolean expression yields TRUE. 
  1559.  
  1560. Examples include: 
  1561.  
  1562.   WHILE j > 0 DO
  1563.     j := j DIV 2;
  1564.     i := i + 1
  1565.   END;
  1566.  
  1567.   WHILE i # j DO
  1568.     IF i > j THEN
  1569.       i := i - j;
  1570.     ELSE
  1571.       j := j - i;
  1572.     END;
  1573.   END;
  1574.  
  1575.   WHILE (t # NIL) & (t^.key # i) DO
  1576.     t := t^.left
  1577.   END;
  1578.  
  1579.  
  1580. ΓòÉΓòÉΓòÉ 8.7. Repeat statements ΓòÉΓòÉΓòÉ
  1581.  
  1582. ΓûÉ RepeatStmt     = REPEAT StmtSeq UNTIL BoolExpr
  1583. ΓûÉ BoolExpr       = Expr
  1584.  
  1585. Repeat-statements specify the repeated execution of a statement-sequence 
  1586. depending on the value of a boolean expression. The expression is evaluated 
  1587. after each execution of the statement sequence, and the repetition stops as 
  1588. soon as it yields the value TRUE. The statement sequence is executed at least 
  1589. once. 
  1590.  
  1591. Example: 
  1592.  
  1593.   REPEAT
  1594.     k := i MOD j;
  1595.     i := j;
  1596.     j := k;
  1597.   UNTIL j = 0;
  1598.  
  1599.  
  1600. ΓòÉΓòÉΓòÉ 8.8. For statements ΓòÉΓòÉΓòÉ
  1601.  
  1602. ΓûÉ ForStmt        = FOR ControlVar ":=" Expr TO Expr [ BY ConstExpr ]
  1603. ΓûÉ                  DO StmtSeq END
  1604. ΓûÉ ControlVar     = Ident
  1605. ΓûÉ ConstExpr      = Expr
  1606.  
  1607. A for-statement specifies the repeated execution of a statement-sequence for a 
  1608. fixed number of times while a progression of values is assigned to an integer- 
  1609. or cardinal variable called the control variable of the for-statement. The 
  1610. control variable cannot be a component of a structured variable, it cannot be 
  1611. imported, nor can it be a parameter, unless the language-extensions are 
  1612. enabled. Its value should not be changed by the statement sequence. 
  1613.  
  1614. The statement 
  1615.  
  1616.   FOR v := low TO high BY step DO
  1617.     statements
  1618.   END;
  1619. is equivalent to 
  1620.  
  1621.   v := low;
  1622.   temp := high;
  1623.   IF step > 0 THEN
  1624.     WHILE v <= temp DO
  1625.       statements;
  1626.       v := v + step;
  1627.     END;
  1628.   ELSE
  1629.     WHILE v >= temp DO
  1630.       statements;
  1631.       v := v + step;
  1632.     END;
  1633.   END;
  1634.  
  1635. 'low' must be assignment-compatible with 'v', 'high' must be compatible (that 
  1636. is comparable) with 'v', and 'step' must be a nonzero constant expression of an 
  1637. integer or cardinal type. If 'step' is not specified, it is assumed to be 1. 
  1638.  
  1639. Examples: 
  1640.  
  1641.   FOR i := 1 TO 80 DO
  1642.     j := j + a[ i ];
  1643.   END;
  1644.  
  1645.   FOR i := 80 TO 2 BY -1 DO
  1646.     a[ i ] := a[ i-1 ];
  1647.   END;
  1648.  
  1649.  
  1650. ΓòÉΓòÉΓòÉ 8.9. Loop/Exit statements ΓòÉΓòÉΓòÉ
  1651.  
  1652. ΓûÉ Stmt           = LoopStmt | EXIT
  1653. ΓûÉ LoopStmt       = LOOP StmtSeq END
  1654.  
  1655. A loop-statement specifies the repeted execution of a statement-sequence. It is 
  1656. terminated upon execution of an EXIT statement within that sequence. 
  1657.  
  1658. An exit statement is denoted by the symbol EXIT. It specifies termination of 
  1659. the enclosing loop statement and continuation with the statement following that 
  1660. loop statement. Exit statements are contextually, although not syntactically, 
  1661. associated with the loop statement that contains them. This compiler, however, 
  1662. issues a warning, if an EXIT is specified without an enclosing loop statement. 
  1663.  
  1664. Loop-Exit statements are useful to express repetitions with several exit points 
  1665. or cases where the exit condition is in the middle of the repeated statement 
  1666. sequence. 
  1667.  
  1668. Example: 
  1669.  
  1670.   LOOP
  1671.     ReadInt( i );
  1672.     IF i < 0 THEN
  1673.       EXIT;
  1674.     END;
  1675.     WriteInt( i );
  1676.   END;
  1677.  
  1678.  
  1679. ΓòÉΓòÉΓòÉ 8.10. With statements ΓòÉΓòÉΓòÉ
  1680.  
  1681. ΓûÉ WithStmt       = WITH RecDesignator DO StmtSeq END
  1682. ΓûÉ RecDesignator  = Designator | Guard
  1683. ΓûÉ Guard          = Qualident ":" Qualident
  1684.  
  1685. The with statement specifies a record variable and a statement-sequence. In 
  1686. these statements the qualification of field identifiers may be omitted, if they 
  1687. are to refer to the variable specified in the with clause. If the designator 
  1688. denotes a component of a structured variable, the selector is evaluated once 
  1689. before the statement sequence. The with statement opens a new scope 
  1690.  
  1691. Example (refer to examples in the section about variable-declarations): 
  1692.  
  1693.   WITH t^ DO
  1694.     key := 0;
  1695.     left := NIL;
  1696.     right := NIL
  1697.   END;
  1698.  
  1699. If the language-extensions are enabled, then a with statement can execute a 
  1700. statement sequence depending on the result of a type-test and apply a 
  1701. type-guard to every occurance of the tested variable within this statement 
  1702. sequence. 
  1703.  
  1704. If 'v' is a variable parameter of record type or a pointer to record variable, 
  1705. and if it is of a static type 'T0', the statement 
  1706.  
  1707.   WITH v : T1 DO ... END
  1708.  
  1709. has the following meaning: if the dynamic-type of 'v' is 'T1', then the 
  1710. statement sequence is executed, where 'v' is regarded as if it had the static 
  1711. type 'T1'; else the program execution is halted (in this compiler with result 
  1712. code 3). 
  1713.  
  1714. Example: 
  1715.  
  1716.   TYPE
  1717.     (* basic employee structure *)
  1718.     Employee      = POINTER TO EmployeeDesc;
  1719.     EmployeeDesc  = RECORD
  1720.       Name          : ARRAY [0..30] OF CHAR;
  1721.       Salary        : REAL;
  1722.                     END;
  1723.     (* extended employee record for secretaries *)
  1724.     Secretary     = POINTER TO SecretaryDesc;
  1725.     SecretaryDesc = RECORD( Employee )
  1726.       Bonus         : REAL;
  1727.                     END;
  1728.   VAR
  1729.     EmployeeVar   : Employee;
  1730.  
  1731.   (* .............................. *)
  1732.  
  1733.   WITH EmployeeVar : Secretary DO
  1734.     Employee^.Salary := 1234.00;
  1735.     Employee^.Bonus := 77.00;
  1736.   END;
  1737.  
  1738. The regional-type-guard does not open a new scope, but a local-type-guard in a 
  1739. with clause does. 
  1740.  
  1741. Same example with local-type-guard: 
  1742.  
  1743.   WITH EmployeeVar( Secretary )^ DO
  1744.     Salary := 1234.00;
  1745.     Bonus := 77.00;
  1746.   END;
  1747.  
  1748.  
  1749. ΓòÉΓòÉΓòÉ 8.11. Return statements ΓòÉΓòÉΓòÉ
  1750.  
  1751. ΓûÉ ReturnStmt     = RETURN [ Expr ]
  1752.  
  1753. A return statement causes the termination of a procedure. It is denoted by the 
  1754. symbol RETURN, followed by an expression if the procedure is a function 
  1755. procedure. The type of the expression must be assignment-compatible with the 
  1756. result type specified in the procedure heading. 
  1757.  
  1758. Function procedures require the presence of a return statement indicating the 
  1759. result value. In proper procedures, a return statement is implied by the 
  1760. procedure block. Any explicit return statement therefore appears as an 
  1761. additional (usually an exceptional) termination point. 
  1762.  
  1763.  
  1764. ΓòÉΓòÉΓòÉ 9. Type compability rules ΓòÉΓòÉΓòÉ
  1765.  
  1766. Throughout this documentation terms are used to refer to various levels of type 
  1767. compatibilities. This section provides the complete definitions for the 
  1768. following terms amd compatibility rules: 
  1769.  
  1770.   - Same types
  1771.  - Equal types
  1772.  - Type extensions
  1773.  - Assignment compatibility
  1774.  - Expression compatibility
  1775.  - Extended expression compatibility
  1776.  - Strict expression compatibility
  1777.  - Array compatibility
  1778.  - Matching formal parameter lists
  1779.  - Type transfer functions
  1780.  
  1781. The rules are somewhat extended when compared with Standard Modula-2 because of 
  1782. different basic type sizes and because of this compiler's language extensions. 
  1783. Nevertheless, downward compatibility is given for programs restricting 
  1784. themsevles to types as described in Wirth's 'Programming in Modula-2, 4th 
  1785. edition'. Wirth's standard mentions the basic types INTEGER, LONGINT and 
  1786. CARDINAL, but neither SHORTINT nor SHORTCARD nor LONGCARD is described in his 
  1787. book, and the LONGINT is only briefly mentioned, without further discussion as 
  1788. to the implications in compatibility rules. 
  1789.  
  1790. This compiler tries to stick as closely as possible to Wirth's standard while 
  1791. also providing SHORT and LONG versions for integers and cardinals, and for 
  1792. standard TRUNC and FLOAT functions. 
  1793.  
  1794.  
  1795. ΓòÉΓòÉΓòÉ 9.1. Same types ΓòÉΓòÉΓòÉ
  1796.  
  1797. Two variables 'a' and 'b' with types 'Ta' and 'Tb' are of the same type if 
  1798.  
  1799.      1.   'Ta' and 'Tb' are both denoted by the same type identifier, or 
  1800.      2.   'Ta' is declared to equal 'Tb' in a type declaration of the form 'Ta 
  1801.           = Tb', or 
  1802.      3.   'a' and 'b' appear in the same identifier list in a variable, record 
  1803.           field, or formal parameter declaration and are not open arrays. 
  1804.  
  1805.  
  1806. ΓòÉΓòÉΓòÉ 9.2. Equal types ΓòÉΓòÉΓòÉ
  1807.  
  1808. Two types 'Ta' and 'Tb' are equal if 
  1809.  
  1810.      1.   'Ta' and 'Tb' are the same type 
  1811.      2.   'Ta' and 'Tb' are open array-types with equal element types, or 
  1812.      3.   'Ta' and 'Tb' are procedure-types whose formal-parameter lists match. 
  1813.  
  1814.  
  1815. ΓòÉΓòÉΓòÉ 9.3. Type extension (base type) ΓòÉΓòÉΓòÉ
  1816.  
  1817. This rule only applies if the language-extensions are enabled. 
  1818.  
  1819. Given a type declaration 'Tb=RECORD(Ta)...END', 'Tb' is a direct extension of 
  1820. 'Ta', and 'Ta' is a direct base type of 'Tb'. 
  1821.  
  1822. A type 'Tb' is an extension of type 'Ta', that is, 'Ta' is a base type of 'Tb', 
  1823. if 
  1824.  
  1825.      1.   'Ta' and 'Tb' are the same types, or 
  1826.      2.   'Tb' is a direct extension of an extension of 'Ta' 
  1827.  
  1828.  If 'Pa = POINTER TO Ta' and 'Pb = POINTER TO Tb', 'Pb' is an extension of 'Pa' 
  1829.  ('Pa' is a base type of 'Pb') if 'Tb' is an extension of 'Ta'. 
  1830.  
  1831.  
  1832. ΓòÉΓòÉΓòÉ 9.4. Assignment compatibility ΓòÉΓòÉΓòÉ
  1833.  
  1834. An expression 'e' of type 'Te' is assignment compatible with a variable 'v' of 
  1835. type 'Tv' if one of the following conditions hold: 
  1836.  
  1837.      1.     'Te' and 'Tv' are the same type. 
  1838.      2.     'Te' and 'Tv' are cardinal or integer types and 
  1839.             TSIZE(Tv)>=TSIZE(Te). 
  1840.      3.     'Te' and 'Tv' are real types and TSIZE(Tv)>=TSIZE(Te). 
  1841.      4.     'Te' and 'Tv' are record-types and 'Te' is an extension of 'Tv' and 
  1842.             the dynamic type of 'v' is 'Tv'. 
  1843.      5.     'Te' and 'Tv' are pointer-types and 'Te' is an extension of 'Tv'. 
  1844.      6.     'Tv' is a pointer-type and 'e' is NIL. 
  1845.      7.     'Tv' is a character array-type with n elements, and 'e' is a 
  1846.             string-constant with m characters, and m < n. 
  1847.      8.     'Tv' is a procedure-type and 'e' is the name of a procedure whose 
  1848.             formal-parameters match those of 'Tv'. 
  1849.      9.     'Tv' or 'Te' is one of the SYSTEM-types BYTE, WORD, DWORD or 
  1850.             LONGWORD, FWORD, QWORD, TBYTE and 'TSIZE(Tv)=TSIZE(Te)'. 
  1851.      10.    'Tv' is the SYSTEM-type SHORTADDRESS (or near ADDRESS for 
  1852.             memory-models Tiny, Small, Medium, or Flat32) and 'Te' is a 
  1853.             cardinal or integer or near pointer type and 'TSIZE(Tv)>=TSIZE(Te)' 
  1854.      11.    'Tv' is a cardinal or integer or near pointer type and 'Te' is the 
  1855.             SYSTEM-type SHORTADDRESS (or near ADDRESS for memory-models Tiny, 
  1856.             Small, Medium, or Flat32) and 'TSIZE(Tv)>=TSIZE(Te)' 
  1857.      12.    Either 'Tv' or 'Ta' is the SYSTEM-type LONGADDRESS (or far ADDRESS 
  1858.             for memory-model Compact or Large) and the other 'Ta' or 'Tv' is 
  1859.             any far pointer-type. 
  1860.  
  1861.  
  1862. ΓòÉΓòÉΓòÉ 9.5. Expression compatibility ΓòÉΓòÉΓòÉ
  1863.  
  1864. For a given operator, the types of its operands are expression compatible if 
  1865. they conform to the following table, which also shows the result type of the 
  1866. expression. Pointer type 'P1' must be an extension of type 'P0'. If the 
  1867. language-extensions are enabled, then some additional expression 
  1868. compatibilities are available. 
  1869.  
  1870. The SYSTEM-types SHORTADDRESS, ADDRESS and LONGADDRESS are treated like 
  1871. cardinals. And if the operator is neither the '=' nor '#' nor '<>' relation and 
  1872. if the address type is a far pointer then only the offset part is taken for the 
  1873. evaluation. If there are far address operands in a relational expression then 
  1874. only the '=' or '#' or '<>' are permitted. If there are address operands in a 
  1875. non-relational expression then the result type is the type of the address 
  1876. operand. 
  1877.  
  1878. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1879. ΓöéOperator  ΓöéOperand1      ΓöéOperand2      ΓöéResult Type         Γöé
  1880. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1881. Γöé+ - * DIV ΓöéSHORTINT      ΓöéSHORTINT      Γöésmallest integer    Γöé
  1882. ΓöéMOD       ΓöéINTEGER       ΓöéINTEGER       Γöéincluding both      Γöé
  1883. Γöé          ΓöéLONGINT       ΓöéLONGINT       Γöéoperand types       Γöé
  1884. Γöé          Γöéint-subrange  Γöéint-subrange  Γöé                    Γöé
  1885. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1886. Γöé+ -       ΓöéSHORTINT      Γöé              Γöésame integer type   Γöé
  1887. Γöé          ΓöéINTEGER       Γöé              Γöé                    Γöé
  1888. Γöé          ΓöéLONGINT       Γöé              Γöé                    Γöé
  1889. Γöé          Γöéint-subrange  Γöé              Γöé                    Γöé
  1890. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1891. Γöé+ - *     ΓöéSHORTREAL REALΓöéSHORTREAL REALΓöésmallest real       Γöé
  1892. Γöé          ΓöéLONGREAL      ΓöéLONGREAL      Γöéincluding both      Γöé
  1893. Γöé          Γöé              Γöé              Γöéoperand types       Γöé
  1894. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1895. Γöé+ -       ΓöéSHORTREAL REALΓöé              Γöésame real type      Γöé
  1896. Γöé          ΓöéLONGREAL      Γöé              Γöé                    Γöé
  1897. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1898. Γöé/         ΓöéSHORTREAL REALΓöéSHORTREAL REALΓöésmallest real       Γöé
  1899. Γöé          ΓöéLONGREAL      ΓöéLONGREAL      Γöéincluding both      Γöé
  1900. Γöé          Γöé              Γöé              Γöéoperand types       Γöé
  1901. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1902. Γöé+ - * /   Γöéset type      Γöésame set type Γöésame set type       Γöé
  1903. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1904. ΓöéOR AND &  ΓöéBOOLEAN       ΓöéBOOLEAN       ΓöéBOOLEAN             Γöé
  1905. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1906. ΓöéNOT ~     ΓöéBOOLEAN       Γöé              ΓöéBOOLEAN             Γöé
  1907. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1908. Γöé= <> < <= ΓöéSHORTINT      ΓöéSHORTINT      ΓöéBOOLEAN             Γöé
  1909. Γöé> >= #    ΓöéINTEGER       ΓöéINTEGER       Γöé                    Γöé
  1910. Γöé          ΓöéLONGINT       ΓöéLONGINT       Γöé                    Γöé
  1911. Γöé          Γöéint-subrange  Γöéint-subrange  Γöé                    Γöé
  1912. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1913. Γöé= <> < <= ΓöéSHORTCARD     ΓöéSHORTCARD     ΓöéBOOLEAN             Γöé
  1914. Γöé> >= #    ΓöéCARDINAL      ΓöéCARDINAL      Γöé                    Γöé
  1915. Γöé          ΓöéLONGCARD      ΓöéLONGCARD      Γöé                    Γöé
  1916. Γöé          Γöécard-subrange Γöécard-subrange Γöé                    Γöé
  1917. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1918. Γöé= <> < <= ΓöéSHORTREAL REALΓöéSHORTREAL REALΓöéBOOLEAN             Γöé
  1919. Γöé> >= #    ΓöéLONGREAL      ΓöéLONGREAL      Γöé                    Γöé
  1920. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1921. Γöé= <> < <= ΓöéCHAR          ΓöéCHAR          ΓöéBOOLEAN             Γöé
  1922. Γöé> >= #    Γöéchar-subrange Γöéchar-subrange Γöé                    Γöé
  1923. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1924. Γöé= <> < <= ΓöéBOOLEAN       ΓöéBOOLEAN       ΓöéBOOLEAN             Γöé
  1925. Γöé> >= #    Γöé              Γöé              Γöé                    Γöé
  1926. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1927. Γöé= <> <= >=Γöéset type      Γöésame set type ΓöéBOOLEAN             Γöé
  1928. Γöé#         Γöé              Γöé              Γöé                    Γöé
  1929. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1930. Γöé= <> #    Γöépointer type  Γöépointer type  ΓöéBOOLEAN             Γöé
  1931. Γöé          ΓöéP0 or P1      ΓöéP0 or P1      Γöé                    Γöé
  1932. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1933. Γöé= <> < <= Γöéenum          Γöésame enum     ΓöéBOOLEAN             Γöé
  1934. Γöé> >= #    Γöé              Γöé              Γöé                    Γöé
  1935. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1936. ΓöéIN        ΓöéSHORTCARD     ΓöéSET OF 1st    ΓöéBOOLEAN             Γöé
  1937. Γöé          ΓöéSHORTINT CHAR Γöétype          Γöé                    Γöé
  1938. Γöé          ΓöéBOOLEAN       Γöé              Γöé                    Γöé
  1939. Γöé          Γöébyte-enum     Γöé              Γöé                    Γöé
  1940. Γöé          Γöébyte-subrange Γöé              Γöé                    Γöé
  1941. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1942.  
  1943.  
  1944. ΓòÉΓòÉΓòÉ 9.6. Extented expression compatibility ΓòÉΓòÉΓòÉ
  1945.  
  1946. This Modula-2 compiler implementation provides some additional expression 
  1947. compatibilies. They are only available if the language-extensions are enabled 
  1948. and include further logical, relational and also bitwise operators. Type T1 
  1949. must be an extension of type T0 for the relation 'T0 IS T1'. 
  1950.  
  1951. The following table shows the additional compatibilities: 
  1952.  
  1953. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1954. ΓöéOperator  ΓöéOperand1  ΓöéOperand2  ΓöéResult Type         Γöé
  1955. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1956. ΓöéXOR       ΓöéBOOLEAN   ΓöéBOOLEAN   ΓöéBOOLEAN             Γöé
  1957. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1958. ΓöéOR XOR ANDΓöéSHORTINT  ΓöéSHORTINT  Γöésmallest integer    Γöé
  1959. ΓöéSHL SHR & ΓöéINTEGER   ΓöéINTEGER   Γöéincluding both      Γöé
  1960. Γöé          ΓöéLONGINT   ΓöéLONGINT   Γöéoperand types       Γöé
  1961. Γöé          Γöésubrange  Γöésubrange  Γöé                    Γöé
  1962. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1963. ΓöéOR XOR ANDΓöéSHORTCARD ΓöéSHORTCARD Γöésmallest cardinal   Γöé
  1964. ΓöéSHL SHR & ΓöéCARDINAL  ΓöéCARDINAL  Γöéincluding both      Γöé
  1965. Γöé          ΓöéLONGCARD  ΓöéLONGCARD  Γöéoperand types       Γöé
  1966. Γöé          Γöésubrange  Γöésubrange  Γöé                    Γöé
  1967. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1968. ΓöéNOT ~     ΓöéSHORTINT  Γöé          Γöésame integer        Γöé
  1969. Γöé          ΓöéINTEGER   Γöé          Γöé                    Γöé
  1970. Γöé          ΓöéLONGINT   Γöé          Γöé                    Γöé
  1971. Γöé          Γöésubrange  Γöé          Γöé                    Γöé
  1972. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1973. ΓöéNOT ~     ΓöéSHORTCARD Γöé          Γöésame cardinal       Γöé
  1974. Γöé          ΓöéCARDINAL  Γöé          Γöé                    Γöé
  1975. Γöé          ΓöéLONGCARD  Γöé          Γöé                    Γöé
  1976. Γöé          Γöésubrange  Γöé          Γöé                    Γöé
  1977. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1978. Γöé= <> #    Γöéprocedure Γöésame      Γöésame procedure type Γöé
  1979. Γöé          Γöétype T    Γöéprocedure ΓöéT                   Γöé
  1980. Γöé          Γöé          Γöétype T    Γöé                    Γöé
  1981. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1982. ΓöéIS        Γöétype T0   Γöéextended  ΓöéBOOLEAN             Γöé
  1983. Γöé          Γöé          Γöétype T1   Γöé                    Γöé
  1984. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1985.  
  1986.  
  1987. ΓòÉΓòÉΓòÉ 9.7. Strict expression compatibility ΓòÉΓòÉΓòÉ
  1988.  
  1989. Two operands are strictly compatible if they are expression-compatible and if 
  1990. their types are of equal sizes. Strict expression compatibility is required for 
  1991. operands in the following contexts: 
  1992.  
  1993. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1994. ΓöéContext        ΓöéOperand1    ΓöéOperand2    Γöé
  1995. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1996. Γöécase-statement Γöécase label  Γöécase expr   Γöé
  1997. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1998. Γöéprocedure-call Γöéactual      Γöéformal VAR  Γöé
  1999. Γöé               Γöéparameter   Γöéparameter   Γöé
  2000. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  2001.  
  2002.  
  2003. ΓòÉΓòÉΓòÉ 9.8. Array compatibility ΓòÉΓòÉΓòÉ
  2004.  
  2005. An actual parameter 'a' of type 'Ta' is array conpatible with a 
  2006. formal-parameter 'f' of type 'Tf' if 
  2007.  
  2008.      1.     'Tf' and 'Ta' are the same type, or 
  2009.      2.     'Tf' is an open array, 'Ta' is any array, and their element types 
  2010.             are array compatible, or 
  2011.      3.     'Tf' is 'ARRAY OF CHAR' and 'a' is a string. 
  2012.  
  2013.  
  2014. ΓòÉΓòÉΓòÉ 9.9. Matching formal parameter lists ΓòÉΓòÉΓòÉ
  2015.  
  2016. Two formal-parameter lists match if 
  2017.  
  2018.      1.     they have the same number of parameters 
  2019.      2.     they have either the same function result type or none, and 
  2020.      3.     parameters at corresponding positions have equal types, and 
  2021.      4.     parameters at corresponding positions are both either value or 
  2022.             variable parameters. 
  2023.  
  2024.  
  2025. ΓòÉΓòÉΓòÉ 9.10. Type transfer functions ΓòÉΓòÉΓòÉ
  2026.  
  2027. Besides the items exported from the pseudo-module SYSTEM, there is another 
  2028. system-dependent facilitiy. It is the possibility to use a type-identifier 'T' 
  2029. as name denoting the type transfer function from the type of the operand to the 
  2030. type 'T'. Such functions are of course highly implementation dependent since 
  2031. they do not involve any explicit conversion instructions. They are simply 
  2032. reinterpreting an operand as a value of another type. The programmer should be 
  2033. aware of the fact that type transfers are highly non-portable. Though Modula-2 
  2034. has strict type checkings, it provides some portable type checking relaxations 
  2035. through standard type transfer functions, e.g. VAL(T,x), CHR(x) or ORD(x), as 
  2036. well as standard type resizing functions, e.g. SHORT(x) or LONG(x). 
  2037.  
  2038. Examples for type transfer include: 
  2039.  
  2040.   VAR  i : SHORTINT;
  2041.   VAR ch : CHAR;
  2042.   VAR  b : BOOLEAN;
  2043.   VAR  v : SHORTREAL;
  2044.   VAR  c : LONGCARD;
  2045.     ....
  2046.   BEGIN
  2047.     (* BOOLEAN b interpreted as SHORTINT *)
  2048.       i := SHORTINT( b );
  2049.     (* BOOLEAN b interpreted as CHAR *)
  2050.       ch := CHAR( b );
  2051.     (* LONGCARD c interpreted as SHORTREAL *)
  2052.       v := SHORTREAL( c );
  2053.   END ....
  2054.  
  2055.  
  2056. ΓòÉΓòÉΓòÉ 10. SYSTEM module ΓòÉΓòÉΓòÉ
  2057.  
  2058. The module SYSTEM contains certain constants, types, function-procedures, and 
  2059. proper-procedures that are necessary to implement low-level operations 
  2060. particular to a given computer and/or operating system. These include, for 
  2061. example, facilities for accessing devices that are controlled by the computer, 
  2062. and facilities to break the type compatibility rules otherwise imposed by the 
  2063. language definition. 
  2064.  
  2065. It is strongly recommended that the use of the module SYSTEM be restricted to 
  2066. specific modules (called low-level modules). Such modules are inherently 
  2067. nonportable and unsafe, but easily recognized due to the identifier SYSTEM 
  2068. appearing in their import list. 
  2069.  
  2070. Note: Because the items imported from SYSTEM obey special rules, this module 
  2071. must be known to the compiler. It is therefore called a pseudo-module and need 
  2072. not be supplied as a separate definition module. 
  2073.  
  2074. This compiler also implements all the standard-identifiers in the SYSTEM 
  2075. module, from where they are automatically exported to all modules. 
  2076.  
  2077.  
  2078. ΓòÉΓòÉΓòÉ 10.1. SYSTEM constants ΓòÉΓòÉΓòÉ
  2079.  
  2080. The following constants denote the active memory model, the target 
  2081. operating-system and the target processors. They are only qualified exported. 
  2082. Their values are set up during compiler intialization and are influenced by 
  2083. corresponding command line switches. The following table shows the possible 
  2084. constants and their values: 
  2085.  
  2086.      SYSTEM.TinyModel TRUE if compiling for 16-bit tiny memory model 
  2087.           FALSE otherwise 
  2088.      SYSTEM.SmallModel TRUE if compiling for 16-bit small memory model 
  2089.           FALSE otherwise 
  2090.      SYSTEM.MediumModel TRUE if compiling for 16-bit medium memory model 
  2091.           FALSE otherwise 
  2092.      SYSTEM.CompactModel TRUE if compiling for 16-bit compact memory model 
  2093.           FALSE otherwise 
  2094.      SYSTEM.LargeModel TRUE if compiling for 16-bit large memory model 
  2095.           FALSE otherwise 
  2096.      SYSTEM.Flat32Model TRUE if compiling for flat 32-bit memory model 
  2097.           FALSE otherwise 
  2098.      SYSTEM.DOS TRUE if compiling for DOS, 
  2099.           FALSE otherwise. 
  2100.      SYSTEM.WIN TRUE if compiling for MS-Windows 3.x, 
  2101.           FALSE otherwise. 
  2102.      SYSTEM.OS2 TRUE if compiling for OS/2, 
  2103.           FALSE otherwise. 
  2104.      SYSTEM.Processor 8086 if compiling for 8086/8088 CPU, 
  2105.           80286 if compiling for 80286 CPU, 
  2106.           80386 if compiling for 80386 CPU, 
  2107.           80486 if compiling for 80486 CPU, 
  2108.           80586 if compiling for 80586 (PENTIUM) or higher CPU 
  2109.      SYSTEM.NumericProcessor TRUE if compiling for 80x87 numeric coprocessor, 
  2110.           FALSE if no numeric coprocessor specified. 
  2111.           Note:OS/2 2.x or 3.0 provides a software emulation if there is no 
  2112.           numeric coprocessor installed in the computer system. 
  2113.  
  2114.  
  2115. ΓòÉΓòÉΓòÉ 10.2. SYSTEM types ΓòÉΓòÉΓòÉ
  2116.  
  2117. The Modula-2 language usually enforces a strict type checking during 
  2118. compilation. This can be relaxed when using one of the SYSTEM types BYTE, WORD, 
  2119. DWORD, FWORD, QWORD or TBYTE. No operation except assignment is defined for 
  2120. them. However, if a formal-parameter of a procedure is of one of above 
  2121. mentioned types, the corresponding actual type may be of any type that uses the 
  2122. same amount of storage units in the given implementation. If the formal 
  2123. parameter is an 'ARRAY OF T', where 'T' is one of above mentioned types, its 
  2124. corresponding actual parameter 'A' may be of any type as long as 
  2125. SIZE(A)=TSIZE(T)*n holds true, that is, the storage size must be a whole 
  2126. multiple of the type size of 'T'. The following table shows the type size of 
  2127. above mentioned types: 
  2128.  
  2129.      Type                               Size 
  2130.  
  2131.      SYSTEM.BYTE                        1 
  2132.      SYSTEM.WORD                        2 
  2133.      SYSTEM.DWORD                       4 
  2134.      SYSTEM.LONGWORD                    same as SYSTEM.DWORD 
  2135.      SYSTEM.FWORD                       6 
  2136.      SYSTEM.QWORD                       8 
  2137.  
  2138.  The following pointer types are expression-compatible and 
  2139.  assignment-compatible with all pointer-types with same (possibly implicit) 
  2140.  NEAR or FAR attribute and same type size. If they denote (a possibly implicit) 
  2141.  NEAR pointer, they may also be assignment-compatible with cardinal and integer 
  2142.  types. They are defined as follows: 
  2143.  
  2144.      SYSTEM.SHORTADDRESS NEAR POINTER TO BYTE 
  2145.      SYSTEM.ADDRESS if compiling for compact or large memory-models: 
  2146.           FAR POINTER TO BYTE 
  2147.           otherwise: 
  2148.           NEAR POINTER TO BYTE 
  2149.      SYSTEM.LONGADDRESS FAR POINTER TO BYTE 
  2150.      SYSTEM.PROCESS SYSTEM.ADDRESS 
  2151.  
  2152.  
  2153. ΓòÉΓòÉΓòÉ 10.3. SYSTEM function procedures ΓòÉΓòÉΓòÉ
  2154.  
  2155. The SYSTEM function procedures provide basic runtime services and low-level 
  2156. facilities. Some are generic and are expanded like macros during compilation. 
  2157. Others are implemented as genuine procedures in the SYSTEM.MOD module. In this 
  2158. compiler all standard-functions have their origin in the SYSTEM module as well. 
  2159.  
  2160. The following non-standard function procedures are available and described in 
  2161. the next sections: 
  2162.  
  2163.   - generic LEN( a, n )
  2164.  - generic LEN( a )
  2165.  - generic TSIZE( T )
  2166.  - generic DSIZE( a, n )
  2167.  - generic DSIZE( a )
  2168.  - generic ADR( x )
  2169.  - generic LONGADR( x )
  2170.  - generic SHORTADR( x )
  2171.  - generic OFS( x )
  2172.  - generic SEG( x )
  2173.  - generic currentFile( )
  2174.  - generic currentLine( )
  2175.  - PROCEDURE GetExitProc( ) : PROC
  2176.  
  2177. The following runtime functions are implemented in the SYSTEM module: 
  2178.  
  2179.  - PROCEDURE TestBit
  2180.   ( Set:ADDRESS; BitPos:SHORTCARD ):BOOLEAN;
  2181.  - PROCEDURE LongMul
  2182.   ( i,j:LONGCARD ):LONGCARD;
  2183.  - PROCEDURE LongIMul
  2184.   ( i,j:LONGINT ):LONGINT;
  2185.  - PROCEDURE LongDiv
  2186.   ( i,j:LONGCARD ):LONGCARD;
  2187.  - PROCEDURE LongIDiv
  2188.   ( i,j:LONGINT ):LONGINT;
  2189.  - PROCEDURE LongMod
  2190.   ( i,j:LONGCARD ):LONGCARD;
  2191.  - PROCEDURE LongIMod
  2192.   ( i,j:LONGINT ):LONGINT;
  2193.  - PROCEDURE LongShl
  2194.   ( i,j:LONGCARD ):LONGCARD;
  2195.  - PROCEDURE LongShr
  2196.   ( i,j:LONGCARD ):LONGCARD;
  2197.  - PROCEDURE LongSar
  2198.   ( i,j:LONGINT ):LONGINT;
  2199.  - PROCEDURE somResolve
  2200.   ( Object : LONGWORD; MethodToken : LONGWORD ) : LONGWORD;
  2201.  - PROCEDURE somFindSMethodOk
  2202.   ( classObject : LONGWORD; idMethod : LONGWORD ) : LONGWORD;
  2203.  - PROCEDURE somGetClass
  2204.   ( Object : LONGWORD ) : LONGWORD;
  2205.  
  2206.  
  2207. ΓòÉΓòÉΓòÉ 10.3.1. SYSTEM function LEN ΓòÉΓòÉΓòÉ
  2208.  
  2209. The function LEN(a,n) returns for an array operand 'a' in dimension 'n' the 
  2210. number of elements as a cardinal number. The function LEN(a) is equivalent to 
  2211. LEN(a,0). The following example illustrates its usage: 
  2212.  
  2213.     ..........
  2214.   FROM SYSTEM IMPORT LEN;
  2215.     ..........
  2216.   CONST
  2217.     Len0 = 15;
  2218.     Len1 = 20;
  2219.     Len2 = 25;
  2220.     ..........
  2221.   VAR
  2222.     A : ARRAY [1..Len0], [1..Len1], [1..Len2] OF INTEGER;
  2223.     i : CARDINAL;
  2224.     j : CARDINAL;
  2225.     k : CARDINAL;
  2226.     ..........
  2227.   BEGIN
  2228.     i := LEN( A );        (* i := 15 *)
  2229.     j := LEN( A, 1 );     (* j := 20 *)
  2230.     k := LEN( A, 2 );     (* k := 25 *)
  2231.   END
  2232.     ..........
  2233.  
  2234.  
  2235. ΓòÉΓòÉΓòÉ 10.3.2. SYSTEM function TSIZE ΓòÉΓòÉΓòÉ
  2236.  
  2237. The function TSIZE(T) returns for a given type 'T' its byte size as a cardinal 
  2238. or integer number. This function is usually needed when allocating dynamic 
  2239. memory objects. 
  2240.  
  2241. The following example illustrates its usage: 
  2242.  
  2243.   IMPORT Storage;
  2244.   IMPORT SYSTEM;
  2245.     ...........
  2246.   TYPE
  2247.     A : ARRAY [0..10] OF LONGINT;
  2248.     ...........
  2249.   VAR
  2250.     pa : POINTER TO A;
  2251.     ...........
  2252.   BEGIN
  2253.     (* Allocate 11 * TSIZE( LONGINT ) = 11 * 4 = 44 bytes *)
  2254.     Storage.ALLOCATE( pa, SYSTEM.TSIZE( A ) );
  2255.     ...........
  2256.   END
  2257.     ...........
  2258.  
  2259.  
  2260. ΓòÉΓòÉΓòÉ 10.3.3. SYSTEM function DSIZE ΓòÉΓòÉΓòÉ
  2261.  
  2262. The function DSIZE(a,n) returns for an array operand 'a' in dimension 'n' the 
  2263. operand size as a cardinal number. The function DSIZE(a) is equivalent to 
  2264. DSIZE(a,0). The following example illustrates its usage: 
  2265.  
  2266.     ..........
  2267.   FROM SYSTEM IMPORT DSIZE;
  2268.     ..........
  2269.   CONST
  2270.     Len0 = 15;
  2271.     Len1 = 20;
  2272.     Len2 = 25;
  2273.     ..........
  2274.   VAR
  2275.     A : ARRAY [1..Len0], [1..Len1], [1..Len2] OF INTEGER;
  2276.     i : CARDINAL;
  2277.     j : CARDINAL;
  2278.     k : CARDINAL;
  2279.     ..........
  2280.   BEGIN
  2281.     i := DSIZE( A );        (* i := 15*20*25*TSIZE(INTEGER) *)
  2282.     j := DSIZE( A, 1 );     (* j := 20*25*TSIZE(INTEGER) *)
  2283.     k := DSIZE( A, 2 );     (* k := 25*TSIZE(INTEGER) *)
  2284.   END
  2285.     ..........
  2286.  
  2287.  
  2288. ΓòÉΓòÉΓòÉ 10.3.4. SYSTEM function ADR ΓòÉΓòÉΓòÉ
  2289.  
  2290. The function ADR(x) returns the address of a given operand 'x'. The result type 
  2291. is ADDRESS. The function ADR(x) is like a SHORTADR(x) if compiling for one of 
  2292. the non-segmented small data models Tiny, Small, Medium or Flat32. Otherwise it 
  2293. is like a LONGADR(x) if compiling for one of the segmented large data models 
  2294. Compact or Large. 
  2295.  
  2296.  
  2297. ΓòÉΓòÉΓòÉ 10.3.5. SYSTEM function LONGADR ΓòÉΓòÉΓòÉ
  2298.  
  2299. The function LONGADR(x) returns the far address of a given operand 'x'. The 
  2300. result type is the segmented far pointer LONGADDRESS which is 
  2301. expression-compatible with any far pointer or cardinal expression, and it is 
  2302. assignment-compatible with any far pointer. 
  2303.  
  2304.  
  2305. ΓòÉΓòÉΓòÉ 10.3.6. SYSTEM function SHORTADR ΓòÉΓòÉΓòÉ
  2306.  
  2307. The function SHORTADR(x) returns the near address of a given operand 'x'. The 
  2308. result type is the non-segmented near pointer SHORTADDRESS which is 
  2309. expression-compatible with any near pointer or cardinal expression, and it is 
  2310. assignment-compatible with any near pointer or cardinal or integer operand. 
  2311.  
  2312.  
  2313. ΓòÉΓòÉΓòÉ 10.3.7. SYSTEM function OFS ΓòÉΓòÉΓòÉ
  2314.  
  2315. The function OFS(x) returns the offset part of the address of operand 'x'. If 
  2316. the address of x is a far address, then it is stripped off its segment part. 
  2317. The result type is LONGCARD for 32-bit memory-models and CARDINAL for 16-bit 
  2318. memory-models. 
  2319.  
  2320.  
  2321. ΓòÉΓòÉΓòÉ 10.3.8. SYSTEM function SEG ΓòÉΓòÉΓòÉ
  2322.  
  2323. The function SEG(x) returns the segment part of the address of operand 'x', 
  2324. stripping off its offset part. The result type is CARDINAL. 
  2325.  
  2326.  
  2327. ΓòÉΓòÉΓòÉ 10.3.9. SYSTEM function currentFile ΓòÉΓòÉΓòÉ
  2328.  
  2329. The function currentFile() returns a zero-terminated string of the current 
  2330. source module's file name. This function is mainly used for debugging purposes 
  2331. or for error routines. 
  2332.  
  2333.  
  2334. ΓòÉΓòÉΓòÉ 10.3.10. SYSTEM function currentLine ΓòÉΓòÉΓòÉ
  2335.  
  2336. The function currentLine() returns a zero-terminated string of the currently 
  2337. compiled line number of the source module. This function is mainly used for 
  2338. debugging purposes or for error routines. 
  2339.  
  2340.  
  2341. ΓòÉΓòÉΓòÉ 10.3.11. SYSTEM function GetExitProc ΓòÉΓòÉΓòÉ
  2342.  
  2343. The procedure 
  2344.  
  2345.   PROCEDURE GetExitProc() : PROC;
  2346.  
  2347. is declared in module SYSTEM. It returns the latest procedure from a chain of 
  2348. exit procedures. For further information on how to implement a module-specific 
  2349. exit procedure, see documentation section SetExitProc. 
  2350.  
  2351.  
  2352. ΓòÉΓòÉΓòÉ 10.4. SYSTEM proper procedures ΓòÉΓòÉΓòÉ
  2353.  
  2354. The SYSTEM proper procedures provide basic runtime services and low-level 
  2355. facilities. Some are generic and are expanded like macros during compilation. 
  2356. Others are implemented as genuine procedures in the SYSTEM.MOD module. In this 
  2357. compiler all standard-procedures have their origin in the SYSTEM module as 
  2358. well. 
  2359.  
  2360. The following non-standard procedures are available and described in the next 
  2361. sections: 
  2362.  
  2363.   - INLINE
  2364.   ( ... )
  2365.  - PROCEDURE IOTRANSFER
  2366.   ( VAR p1,p2:ADDRESS; va:CARDINAL );
  2367.  - PROCEDURE LISTEN
  2368.   ( );
  2369.  - PROCEDURE NEWPROCESS
  2370.   ( p:PROC; a:ADDRESS; n:CARDINAL; VAR p1:ADDRESS );
  2371.  - PROCEDURE TRANSFER
  2372.   ( VAR p1,p2:ADDRESS );
  2373.  - PROCEDURE ExitProgram
  2374.   ( ExitCode:SHORTCARD );
  2375.  - generic NEW( p )
  2376.  - generic DISPOSE( p )
  2377.  - PROCEDURE SetExitProc
  2378.   ( UserProc : PROC );
  2379.  
  2380. The following runtime procedures are implemented in the SYSTEM module: 
  2381.  
  2382.  - PROCEDURE OrBytes
  2383.   ( Dest,Source1,Source2:ADDRESS; Size:LONGCARD );
  2384.  - PROCEDURE XorBytes
  2385.   ( Dest,Source1,Source2:ADDRESS; Size:LONGCARD );
  2386.  - PROCEDURE AndBytes
  2387.   ( Dest,Source1,Source2:ADDRESS; Size:LONGCARD );
  2388.  - PROCEDURE MemSet
  2389.   ( Dest:ADDRESS; Val:WORD; Size:LONGCARD );
  2390.  - PROCEDURE MemCmp
  2391.   ( Dest,Source: ADDRESS; Size:LONGCARD );
  2392.  - PROCEDURE MemCpy
  2393.   ( Dest,Source: ADDRESS; Size:LONGCARD );
  2394.  - PROCEDURE SetBitRange
  2395.   ( Dest:ADDRESS; FromBit:SHORTCARD; ToBit:SHORTCARD );
  2396.  - PROCEDURE DelBitRange
  2397.   ( Dest:ADDRESS; FromBit:SHORTCARD; ToBit:SHORTCARD );
  2398.  - PROCEDURE TestBit
  2399.   ( Set:ADDRESS; BitPos:SHORTCARD ):BOOLEAN;
  2400.  - PROCEDURE Push
  2401.   ( Param:ADDRESS; Size:LONGCARD );
  2402.  - PROCEDURE PushString
  2403.   ( Str:ADDRESS; StrSize:LONGCARD; Size:LONGCARD );
  2404.  - PROCEDURE LocalCopy
  2405.   ( VAR Source:ADDRESS; Size:LONGCARD );
  2406.  - PROCEDURE LocalFree
  2407.   ( VAR Source:ADDRESS );
  2408.  - PROCEDURE StartUp
  2409.   ( );
  2410.  - PROCEDURE TypeGuard
  2411.   ( Wanted : TypeDescADDRESS; Actual : TypeDescADDRESS );
  2412.  - PROCEDURE EnterPriority
  2413.   ( Level : SHORTCARD );
  2414.  - PROCEDURE ExitPriority
  2415.   ( );
  2416.  - PROCEDURE LinkVMT
  2417.   ( TypeInfo : TypeDescADDRESS; VMT : TypeDescADDRESS );
  2418.  - PROCEDURE CopyVMT
  2419.   ( Dest, Origin : TypeDescADDRESS; Size : LONGCARD );
  2420.  - PROCEDURE InitVMT
  2421.   ( Dest : TypeDescADDRESS; Size : LONGCARD );
  2422.  - PROCEDURE InitSOM
  2423.   ( );
  2424.  
  2425.  
  2426. ΓòÉΓòÉΓòÉ 10.4.1. Standard procedure NEW ΓòÉΓòÉΓòÉ
  2427.  
  2428. The standard procedure NEW is rooted in the SYSTEM module for this compiler. 
  2429. The procedure-call 
  2430.  
  2431.   NEW( p )
  2432.  
  2433. is expanded into the procedure-call 
  2434.  
  2435.   ALLOCATE( p, TSIZE( p^ ) )
  2436.  
  2437. during compilation. This means a dynamic memory allocation from a global heap 
  2438. to the pointer variable 'p'. The size of the allocated memory is that of the 
  2439. type being pointed at by 'p'. 
  2440.  
  2441. If the language-extensions are enabled and if 'p' is a pointer to a record-type 
  2442. not referring to an instance of an OS/2 System Object Model (SOM), then the 
  2443. procedure-call 
  2444.  
  2445.   NEW( p )
  2446.  
  2447. is translated into the sequence 
  2448.  
  2449.   ALLOCATE
  2450.  ( p,
  2451.   TSIZE( <type descriptor address> ) +
  2452.   TSIZE( <record type> )
  2453.  );
  2454.  t := p;
  2455.  IF t # NIL THEN
  2456.   IF <extended type> THEN
  2457.    t^ := ADR( <type desciptor> );
  2458.   ELSE
  2459.    t^ := NIL;
  2460.   END;
  2461.   p := ADDRESS( t ) + TSIZE( <type descriptor address> );
  2462.  END;
  2463.  
  2464. Before allocating a memory block for a record, few more bytes are to be 
  2465. allocated for a pointer to an internally maintained type descriptor. This 
  2466. additional information is needed e.g. for dynamic type-tests for records, for 
  2467. type-guard selectors, or for rergional type-guards. 
  2468.  
  2469. The standard procedure NEW can also be used for creating instances of the OS/2 
  2470. System Object Model. If 'p' has been declared as such a SOM-pointer then the 
  2471. procedure-call 
  2472.  
  2473.   NEW( p )
  2474.  
  2475. is translated into a sequence where a static SOM method resolution yields a 
  2476. pointer to the OS/2 procedure 'somNew', which is called for creating a new 
  2477. instance of the desired object class. 
  2478.  
  2479. This compiler uses various optimizations during code generation. For this 
  2480. purpose it keeps track of the contents of all pointers used. In particular the 
  2481. compiler assumes that any pointer 'p' whose value has been set by a NEW(p) can 
  2482. only point to inside the heap, but not to other variables, thus enabling the 
  2483. code optimizer to continue keeping values from non-heap variables in 
  2484. CPU-registers. 
  2485.  
  2486.  
  2487. ΓòÉΓòÉΓòÉ 10.4.2. Standard procedure DISPOSE ΓòÉΓòÉΓòÉ
  2488.  
  2489. The standard procedure DISPOSE is rooted in the SYSTEM module for this 
  2490. compiler. The procedure-call 
  2491.  
  2492.   DISPOSE( p )
  2493.  
  2494. is expanded into the procedure-call 
  2495.  
  2496.   DEALLOCATE( p, TSIZE( p^ ) )
  2497.  
  2498. during compilation. This means that a previously allocated dynamic memory block 
  2499. is released and 'p' is set to NIL. The size of the deallocated memory is that 
  2500. of the type being pointed at by 'p'. 
  2501.  
  2502. If the language-extensions are enabled then if 'p' is a pointer to a 
  2503. record-type then a procedure-call 
  2504.  
  2505.   DISPOSE( p )
  2506.  
  2507. is translated into the sequence 
  2508.  
  2509.   p := ADDRESS( p ) - TSIZE( <type descriptor address> );
  2510.  DEALLOCATE
  2511.  ( p,
  2512.   TSIZE( record type ) +
  2513.   TSIZE( <type descriptor address> )
  2514.  );
  2515.  
  2516. This means, that 'p' is first decremented by the size of the address of an 
  2517. internally maintained type descriptor before deallocation, because each 
  2518. allocated record memory block keeps a pointer to a type descriptor in the bytes 
  2519. preceding the record area, and these bytes must be freed up, too. 
  2520.  
  2521. The standard procedure DISPOSE can also be used for releasing instances of the 
  2522. OS/2 System Object Model. If 'p' has been declared as such a SOM-pointer then 
  2523. the procedure-call 
  2524.  
  2525.   DISPOSE( p )
  2526.  
  2527. is translated into a sequence where a static SOM method resolution yields a 
  2528. pointer to the OS/2 procedure 'somFree', which is called for releasing the 
  2529. SOM-Object. 
  2530.  
  2531.  
  2532. ΓòÉΓòÉΓòÉ 10.4.3. SYSTEM procedure ExitProgram ΓòÉΓòÉΓòÉ
  2533.  
  2534. The procedure 
  2535.  
  2536.   PROCEDURE ExitProgram( ExitCode : SHORTCARD );
  2537.  
  2538. is declared in module SYSTEM. It accepts one value parameter. This procedure is 
  2539. automatically called at the end of a main program-module. The standard 
  2540. procedure-call 
  2541.  
  2542.   HALT();
  2543.  
  2544. is translated into a 
  2545.  
  2546.   SYSTEM.ExitProgram( 0 );
  2547.  
  2548. by this compiler. ExitProgram receives one cardinal value parameter for the 
  2549. exit code. Under OS/2 2.x or 3.0 such an exit code is returned to the caller, 
  2550. e.g. after a DosExecProgram(...) API function call in one of the parameters 
  2551. passed by reference. 
  2552.  
  2553. If the language-extensions are enabled then any type-test failure causes the 
  2554. call SYSTEM.ExitProgram(3) to be executed. 
  2555.  
  2556.  
  2557. ΓòÉΓòÉΓòÉ 10.4.4. SYSTEM procedure SetExitProc ΓòÉΓòÉΓòÉ
  2558.  
  2559. The procedure 
  2560.  
  2561.   PROCEDURE SetExitProc( UserProc : PROC );
  2562.  
  2563. is declared in module SYSTEM. It accepts one value parameter 'UserProc'. 
  2564. Procedure SetExitProc is typically used to add a new procedure or to restore an 
  2565. old procedure to the top of a chain of exit procedures which are executed 
  2566. during program termination. 
  2567.  
  2568. The following example illustrates how to implement a module-specific exit 
  2569. procedure: 
  2570.  
  2571.   IMPLEMENTATION MODULE <module-id>;
  2572.     ...
  2573.   VAR
  2574.     PreviousExitProc : PROC;
  2575.     ...
  2576.   PROCEDURE <exit-id>();
  2577.   BEGIN
  2578.     <module specific exit code>
  2579.     SYSTEM.SetExitProc( PreviousExitProc );
  2580.   END <exit-id>;
  2581.     ...
  2582.   BEGIN
  2583.     <module initialization>
  2584.     PreviousExitProc := SYSTEM.GetExitProc();
  2585.     SYSTEM.SetExitProc( <exit-id> );
  2586.   END <module-id>.
  2587.  
  2588.  
  2589. ΓòÉΓòÉΓòÉ 10.5. Coroutines ΓòÉΓòÉΓòÉ
  2590.  
  2591. The standard book 'Programming in Modula-2', 4th edition, by N.Wirth, describes 
  2592. a Modula-2 interface for the implementation of quasi-concurrent processes on a 
  2593. conventional single-processor computer. The word process is here used with the 
  2594. meaning of a coroutine. Coroutines are processes that are executed by a single 
  2595. processor. A coroutine may also be invoked by a device interrupt. 
  2596.  
  2597. This compiler provides no special implementation for coroutines, except for 
  2598. some primitive cooperative multitasking within an OS/2-process. If compiling 
  2599. for OS/2 2.x or 3.0, module 'Processes' should be used instead, where 
  2600. coroutines are implemented as OS/2 threads. OS/2 exception handlers can be 
  2601. easily installed using the OS/2 2.x or 3.0 exception management API 
  2602. 'DOSEXCEPTIONS'. 
  2603.  
  2604. Nevertheless, module SYSTEM provides an interface for implementing an own 
  2605. coroutine system using the following procedure declarations: 
  2606.  
  2607.   PROCEDURE NEWPROCESS
  2608.   ( p:PROC; a:ADDRESS; n:CARDINAL; VAR p1:ADDRESS );
  2609.  
  2610.   PROCEDURE TRANSFER
  2611.   ( VAR p1,p2:ADDRESS );
  2612.  
  2613.   PROCEDURE IOTRANSFER
  2614.   ( VAR p1,p2:ADDRESS; va:CARDINAL );
  2615.  
  2616.   PROCEDURE LISTEN
  2617.   ( );
  2618.  
  2619. NEWPROCESS serves to create a new process (coroutine), where the parameters 
  2620. have the following meanings: 
  2621.  
  2622.      P    denotes the procedure which constitutes the process, 
  2623.      A    is the base address of the process' workspace 
  2624.      n    is the size of this workspace, 
  2625.      p1   as a result parameter is the address of a newly created process 
  2626.           descriptor. 
  2627.  
  2628.  A new process with 'P' as program and 'A' as workspace of size 'n' is assigned 
  2629.  to 'p1'. This process is allocated, but not activated. 'P' must be a 
  2630.  parameterless procedure declared at level 0. 
  2631.  
  2632.  A transfer of control between two processes is specified by a call to 
  2633.  
  2634.     PROCEDURE TRANSFER( VAR p1,p2:ADDRESS )
  2635.  
  2636.  This call suspends the current process, assigns it to 'p1', and resumes the 
  2637.  process designated by 'p2'. Evidently, 'p2' must have been assigned a process 
  2638.  by an earlier call to either NEWPROCESS or TRANSFER. Both procedures must be 
  2639.  imported from module SYSTEM. A program is to terminate whenever control 
  2640.  reaches the end of a procedure which is the body of a process. Because of this 
  2641.  requirement, this compiler automatically generates a HALT()  at the end of 
  2642.  procedures containing TRANSFER(...) statements. Since the assignment to 'p1' 
  2643.  is to occur after identification of the new process 'p2', the actual 
  2644.  parameters may be identical. 
  2645.  
  2646.  The procedure IOTRANSFER is simular to TRANSFER except that it accepts an 
  2647.  additional interrupt vector number 'va' which is also stored in the process 
  2648.  descriptor pointed at by 'p1'. After execution of an IOTRANSFER any new CPU 
  2649.  interrupt causes the routine to be resumed at the point as specified in the 
  2650.  process descriptor 'p1'. 
  2651.  
  2652.  The parameterless procedure LISTEN serves to temporarily lower a current 
  2653.  module's priority, allowing any pending interrupt requests (IOTRANSFERs) to 
  2654.  occur. 
  2655.  
  2656.  
  2657. ΓòÉΓòÉΓòÉ 10.6. SYSTEM INLINE assembly ΓòÉΓòÉΓòÉ
  2658.  
  2659. Modula-2 is mainly a high-level language. Low-level support is generally not 
  2660. directly programmable under a high-level language unless using the features 
  2661. provided by the preudo-module SYSTEM. Sometimes there is a need to implement 
  2662. functions on a CPU-instructions level. While other compilers leave this problem 
  2663. to an external assembler program, this Modula-2 compiler has chosen a different 
  2664. approach. A SYSTEM.INLINE(...) statement invokes a complete symbolic nested 
  2665. assembler for the INTEL 80x86 and 80x87 processor families. It is beyond the 
  2666. scope of this compiler reference to provide a detailed assembler description. 
  2667. The INLINE statement accepts a variable number of a actual parameters, which 
  2668. are treated as assembler -instructions and -directives. For further information 
  2669. on how to program in assembler the following literature is recommended: 
  2670.  
  2671.   - 'The 80386/387 Architecture' by Stephen P. Morse,
  2672.   1987, John Wiley & Sons, New York
  2673.  - '386 DX Microprocessor Programmer's Reference Manual'
  2674.   1990, Intel Corporation, Literature Sales
  2675.  
  2676. A complete language-grammar for the INLINE assembler has been included in a 
  2677. following documention section for a quick reference. 
  2678.  
  2679. An INLINE-statement must preserve all registers, except for eAX. 
  2680.  
  2681.  
  2682. ΓòÉΓòÉΓòÉ 10.6.1. Parameter passing conventions ΓòÉΓòÉΓòÉ
  2683.  
  2684. This compiler basically passes its procedure parameters on the CPU-stack. Under 
  2685. OS/2 this is almost identical with IBM's _System linkage convention. 
  2686.  
  2687. A procedure heading may originally be declared in a C-style or Pascal-style 
  2688. manner, using either (*$CDECL+*) or (*$CDECL-*) directives. The default is 
  2689. Pascal-style procedures. If a procedure is Pascal-like, then the parameters are 
  2690. to be passed from left to right, and the callee has to clear the stack before 
  2691. returning to the caller. If a procedure is C-style, parameters are passed in 
  2692. reversed order, that is, from right to left, and it is up to the caller to 
  2693. clear the stack immediately after the procedure-call. 
  2694.  
  2695. Modula-2 also requires additional parameters to be passed on the stack for open 
  2696. array HIGH bounds. These are to be pushed on the stack before any of the 
  2697. regular parameters. The called Pascal-style procedure is expected to clear the 
  2698. stack space of the regular parameters only, while the caller has to clear the 
  2699. additional stack space for the invisible HIGH bounds. 
  2700.  
  2701. The following INLINE assembly sequence demonstrates a common 32-bit flat memory 
  2702. model procedure call: 
  2703.  
  2704.   SYSTEM.INLINE
  2705.   (
  2706.     ;--------------------------------------
  2707.     ; sample calling Pascal-style procedure
  2708.     ;--------------------------------------
  2709.     PUSH <HIGH outer dimension for n-th open array parameter>
  2710.      :
  2711.     PUSH <HIGH inner dimension for n-th open array parameter>
  2712.      :
  2713.     PUSH <HIGH outer dimension for 1-st open array parameter>
  2714.      :
  2715.     PUSH <HIGH inner dimension for 1-st open array parameter>
  2716.      :
  2717.     PUSH <1-st parameter>
  2718.     PUSH <2-nd parameter>
  2719.      :
  2720.     PUSH <last parameter>
  2721.     CALL <target-procedure>
  2722.     ADD  ESP, <total size of HIGH bound parameters, if any>
  2723.      :
  2724.   );
  2725.  
  2726. C-style procedures are not expected to process any HIGH bounds for open arrays. 
  2727. Hence the same example, this time C-style, looks like this: 
  2728.  
  2729.   SYSTEM.INLINE
  2730.   (
  2731.     ;---------------------------------
  2732.     ; sample calling C-style procedure
  2733.     ;---------------------------------
  2734.     PUSH <last parameter>
  2735.      :
  2736.     PUSH <2-nd parameter>
  2737.     PUSH <1-st parameter>
  2738.     CALL <target procedure>
  2739.     ADD  ESP, <total size of regular parameters>
  2740.      :
  2741.   );
  2742.  
  2743. Once a called procedure receives control, it has executed an ENTER instruction, 
  2744. which among others saves caller's stack frame pointers and sets up a new local 
  2745. stack frame for local variables. Local variables as well as parameters are to 
  2746. be accessed via base pointers, as in the following example: 
  2747.  
  2748.   SYSTEM.INLINE
  2749.   (
  2750.     ;-------------------------------------
  2751.     ; sample accessing procedure parameter
  2752.     ;-------------------------------------
  2753.     MOV EAX, <parameter-id>[ EBP ]
  2754.      :
  2755.     ;---------------------------------
  2756.     ; sample accessing local variable
  2757.     ;---------------------------------
  2758.     MOV <local-var-id>[ EBP ], EAX
  2759.      :
  2760.   );
  2761.  
  2762. If a Pascal-style procedure is originally declared with language extensions 
  2763. enabled then the compiler also pushes one DWORD for each record  VAR-parameter 
  2764. on the stack because of the dynamic type informations. This is even done before 
  2765. pushing any HIGH bounds and the regular parameters. The dynamic type 
  2766. informations are only needed when using object oriented language constructs 
  2767. such as the IS-relation. The current Modula-2 compiler release 2.01 does not 
  2768. support OOP-extensions on an INLINE-assembly level. The called procedure's 
  2769. RET-instruction only has to clear the stack space of the regular parameters. 
  2770. The remainder (that is, HIGH bounds and type-infos) are to be cleared by the 
  2771. caller. Hence it follows that, as long as the called procedure does not use the 
  2772. additional invisible parameters, it can be fully implemented in 
  2773. INLINE-assembler or even in another programming language. 
  2774.  
  2775. If a called procedure returns a structured value, the caller has to push a 
  2776. hidden address of the structure on the stack. This way the callee will know 
  2777. where to place its return value. This hidden parameter is treated as if it had 
  2778. been declared like a regular first VAR-parameter. 
  2779.  
  2780.  
  2781. ΓòÉΓòÉΓòÉ 10.6.2. Function return registers ΓòÉΓòÉΓòÉ
  2782.  
  2783. Any function procedure has to return a value in CPU-registers. Depending on the 
  2784. type size of the returning formal parameter, the following registers take the 
  2785. return value: 
  2786.  
  2787.    AL           1-byte  return type
  2788.    AX           2-bytes return type
  2789.    EAX          4-bytes return type (32-bit code)
  2790.    DX:AX        4-bytes return type (16-bit code)
  2791.    ST(0)        REAL,SHORTREAL,LONGREAL return type
  2792.  
  2793.  
  2794. ΓòÉΓòÉΓòÉ 11. Processes ΓòÉΓòÉΓòÉ
  2795.  
  2796. Because Modula-2 was originally designed to write among other things operating 
  2797. systems, it includes coroutines for the expression of concurrent activities. 
  2798. This compiler has chosen another way for implementing concurrent processes 
  2799. under OS/2 2.x or 3.0. Rather than reinventing the wheel this compiler 
  2800. restricts itself to using already available preemptive multitasking features, 
  2801. namely those from the API module 'DOSPROCESS'. This API provides multitasking 
  2802. features and is used by a module called 'Processes'. Module 'Processes' follows 
  2803. Wirth's suggestions in an appendix of his book 'Programming in Modula-2', 4th 
  2804. edition. Modula-2 processes are mapped to OS/2 threads. Hence, using module 
  2805. 'Processes' enables the program to run several preemptive tasks within an OS/2 
  2806. 2.x or 3.0 process, using OS/2 2.x or 3.0 threads. 
  2807.  
  2808. Module 'Processes' provides the following interface: 
  2809.  
  2810.   DEFINITION MODULE Processes;
  2811.   TYPE SIGNAL;
  2812.   PROCEDURE StartProcess( P : PROC; n : CARDINAL );
  2813.   (*
  2814.      start a concurrent process with program P
  2815.      and workspace of size n.
  2816.      PROC is a standard type defined as PROC = PROCEDURE().
  2817.   *)
  2818.   PROCEDURE SEND( VAR s : SIGNAL );
  2819.   (*
  2820.      one process waiting for s is resumed
  2821.   *)
  2822.   PROCEDURE WAIT( VAR s : SIGNAL );
  2823.   (*
  2824.      wait for some other process to send s
  2825.   *)
  2826.   PROCEDURE Awaited( s : SIGNAL ) : BOOLEAN;
  2827.   (*
  2828.      Awaited( s ) = "at least one process is waiting for s"
  2829.   *)
  2830.   PROCEDURE Init( VAR s : SIGNAL );
  2831.   (*
  2832.      compulsory initialization
  2833.   *)
  2834.   END Processes.
  2835.  
  2836.  
  2837. ΓòÉΓòÉΓòÉ 12. Compilation units ΓòÉΓòÉΓòÉ
  2838.  
  2839. ΓûÉ CompilationUnit = DefModule | [ IMPLEMENTATION ] ProgramModule
  2840. ΓûÉ
  2841. ΓûÉ ProgramModule   = MODULE Ident Priority ";" { Import } Block Ident "."
  2842. ΓûÉ Priority        = [ "[" ConstExpr "]" ]
  2843. ΓûÉ Import          = [ FROM Ident ] IMPORT IdentList ";"
  2844. ΓûÉ IdentList       = Ident { "," Ident }
  2845. ΓûÉ
  2846. ΓûÉ DefModule = DEFINITION MODULE Ident ";" { Import } { Def } END Ident "."
  2847. ΓûÉ Def       = CONST { ConstDef ";" } | TYPE { TypeDef ";" } |
  2848. ΓûÉ             VAR { VarDecl ";" } | ProcedureHeading ";"
  2849. ΓûÉ ConstDef  = Ident "=" ConstExpr
  2850. ΓûÉ TypeDef   = TypeDecl | Ident
  2851.  
  2852. A text source file is accepted by the compiler as a unit and is called a 
  2853. compilation unit. There a three kinds of compilation units: 
  2854.  
  2855.   - main modules
  2856.  - definition modules
  2857.  - implementation modules
  2858.  
  2859. A main module constitutes a main program and consists of a so-called program 
  2860. module. In particular, it has no export list. Imported items are defined in 
  2861. other, separately compilable program parts which themselves are subdivided into 
  2862. two units, called definition and implementation module. 
  2863.  
  2864. A definition module specifies the names and properties of items that are 
  2865. relevant to clients, i.e. other modules which import from it. These items are 
  2866. automatically qualified exported and might consist of constants, types, 
  2867. variables and specifications of procedure headings. The corresponding 
  2868. implementation module contains local items and statements that need not be 
  2869. known to a client. It also contains the complete procedure declarations, and 
  2870. possibly further declarations of items not exported. Definition and 
  2871. implementation modules exist in pairs. In this compiler, an implementation 
  2872. module need not be written, if the definition module refers to a non-Modula-2 
  2873. interface such as operating system APIs or if the definition modules only 
  2874. contains constants and type definitions and no runtime items such as variables 
  2875. or procedures. Both definition and implementation modules may contain import 
  2876. lists, and all items defined in the definition module are available in the 
  2877. corresponding implementation module without explicit import. 
  2878.  
  2879. The definition module evidently represents the interface between the 
  2880. implementation module on one side and its clients on the other side. The 
  2881. definition module contains those declarations which are relevant to the client 
  2882. modules, and presumably no other ones. In this compiler the definition module 
  2883. can also represent an operating system's API. In such cases the implementation 
  2884. module is usually supplied by third parties and often implemented and 
  2885. precompiled in other languages. Definition modules in this compiler can refer 
  2886. to external .OBJ, .LIB, or .DLL files containing other compiler output objects, 
  2887. static and dynamic link libraries. 
  2888.  
  2889. Definition modules imply the use of qualified export. Type definitions may 
  2890. consist of the full specification of the (fully transparent) type, or they may 
  2891. consist of the type identifier only. In this case the full specification must 
  2892. appear in the corresponding implementation module, and its export is said to be 
  2893. opaque. The type is known in the importing client modules by its name only, and 
  2894. all its properties are hidden. Therefore, procedures operating on operands of 
  2895. this type, and in particular operating on its components, must be defined in 
  2896. the same implementation module which hides the type's properties. Opaque export 
  2897. in  this compiler is restricted to pointers and to non-real basic-types only. 
  2898. Assignment and test for equality are applicable to all opaque types. 
  2899.  
  2900. As in local modules, the body of an implementation module acts as an 
  2901. initialization facility for its local objects. Before its execution, the 
  2902. imported modules are intialized in the order in which they are listed. If 
  2903. circular references occur among modules, their order of initialization is not 
  2904. defined. 
  2905.  
  2906.  
  2907. ΓòÉΓòÉΓòÉ 13. Compiler usage ΓòÉΓòÉΓòÉ
  2908.  
  2909. This compiler is invoked from an OS/2 2.x or 3.0 command line processor. It 
  2910. uses the following command line syntax: 
  2911.  
  2912.   MOD source-file {switches}
  2913.  
  2914. The command is started with a 'MOD' or 'MOD.EXE', to be followed by the 
  2915. Modula-2 source file name and optional switches. A source file contains a 
  2916. complete compilation-unit and has the file name extension '.MOD' for program 
  2917. modules or '.DEF' for definition modules. The default extension is '.MOD'. 
  2918. Module names may be up to 255 characters long and are case sensitive. This 
  2919. Modula-2 compiler takes up to 8 first characters in uppercase notation for the 
  2920. corresponding file names and appends the file name with above mentioned file 
  2921. extensions. This 8.3 file name convention is compatible with the FAT file 
  2922. systems. It can also be used with the new installable file system called OS/2 
  2923. 2.x or 3.0 High Performance File System (or HPFS in short). HPFS supports long 
  2924. file names and treats them as case sensitive. This Modula-2 compiler, however, 
  2925. only recognizes files, whose names are up to 8 characters long and treats them 
  2926. as case insensitive. The output file name for the object file is the same as 
  2927. the input source file name, but in all capital letters and with an '.OBJ' 
  2928. extension instead of '.MOD' or '.DEF'. 
  2929.  
  2930. Note: Linker definition files under OS/2 2.x or 3.0 or MS-Windows 3.x use the 
  2931. same '.DEF' file extension as Modula-2 sources. So it is strongly recommended 
  2932. to keep the linker definition files and Modula-2 definition files in separate 
  2933. file directories. 
  2934.  
  2935. If the Make or Build switch is specified for a compilation on the command line, 
  2936. then the Modula-2 compiler also produces a complete linker response file (file 
  2937. extension '.RSP') and a possible linker definition file (file extension '.LDF') 
  2938. in addition to the object files (file extension '.OBJ'). These output files are 
  2939. suitable for the OS/2 2.x or 3.0 LINK386.EXE or LINK.EXE linker programs, which 
  2940. create the final executable file (file extension .EXE). 
  2941.  
  2942. The following example shows, how to compile and link a flat memory-model 32-bit 
  2943. main program module from file 'TEST.MOD' producing a TEST.EXE file with the 
  2944. final executable program: 
  2945.  
  2946.   MOD TEST.MOD -m -o -mf
  2947.   LINK386 @TEST.RSP
  2948.  
  2949. The example produces a TEST.EXE file ready to be run. 
  2950.  
  2951. In order to correctly run the compiler must consult some environment variables 
  2952. to find the drives letters and file directories for the source and object 
  2953. files. The command line switches inform the Modula-2 compiler how to perform 
  2954. its compilation. 
  2955.  
  2956. The necessary environment settings and the command lines switches are described 
  2957. in the following documentation sections. 
  2958.  
  2959.  
  2960. ΓòÉΓòÉΓòÉ 13.1. Command line switches ΓòÉΓòÉΓòÉ
  2961.  
  2962. Some of this Modula-2 compiler's features are controlled through command line 
  2963. switches. These are serving as global compiler directives. Some of them can 
  2964. also be specified as special comments inside the source files in which case 
  2965. they said to be local (effective only during compilation of the module where 
  2966. they are specified). Command line switches are effective for all the modules 
  2967. being compiled, and not only for one module. The command line switches are 
  2968. specified after the source file name. They are separated by blanks. Every 
  2969. switch is introduced by a '-' character, to be immediately followed by the 
  2970. switch string itself. The switch strings are case insensitive, e.g. -B and -b 
  2971. are both the same. 
  2972.  
  2973. The following command line switches are available with this compiler: 
  2974.  
  2975.      -M                       Make for linker: Recompile updated dependent 
  2976.                               modules 
  2977.      -B                       Build for linker: Recommpile all dependent 
  2978.                               modules 
  2979.      -P                       Verbose compilation with error prompts 
  2980.      -XL                      Extended Modula-2 language 
  2981.      -XI                      Undocumented CPU instructions 
  2982.      -XF                      relaxed function designators 
  2983.      -8086                    Target CPU 8086 
  2984.      -x86                     Target CPU 286, 386, 486 or 586 
  2985.      -F                       Numeric coprocessor 
  2986.      -E=directory             Target directory for executable file 
  2987.      -SS=stacksize            Stack size for executable file in K bytes 
  2988.      -C=number                Cancel after number semantic errors 
  2989.      -R4 or -R8               4-bytes- or 8-bytes-REAL 
  2990.      -D                       Debugger support 
  2991.      -L                       Line numbers into object files 
  2992.      -Mx                      Memory model 
  2993.                               (Tiny,Small,Medium,Compact,Large,Flat32) 
  2994.      -OB                      Expression optimization 
  2995.      -OI                      Pointer and index optimization 
  2996.      -OG                      Global data flow 
  2997.      -O                       Optimize all: -OG -OB -OI 
  2998.      -DOS                     Target operating system DOS 
  2999.      -OS2                     Target operating system OS/2 1.3 or 2.x or 3.0 
  3000.      -WIN                     Target operating system MS-Windows 3.x 
  3001.      -SSFAR                   Assume far stack segment 
  3002.      -A -A1 -A2 -A4           Record field alignment 
  3003.      -V                       Assume volatile global variables 
  3004.      -PM:type                 OS/2 application type PM, VIO, or NOVIO 
  3005.      -$=char                  Redefine introducing character for compiler 
  3006.                               directives 
  3007.      -CDECL                   Assume C-style procedures 
  3008.      -H2 or -H4               2-bytes- or 4-bytes-HIGH 
  3009.      -FSAVE                   Save all FPU registers at the beginning of a 
  3010.                               procedure 
  3011.  
  3012.  The following default switches are used for the OS/2 2.x or 3.0 operating 
  3013.  system: 
  3014.  
  3015.     -386 -OS2 -MF -E=.\ -SS=8 -C=15 -R8 -A -PM:VIO -H4
  3016.  
  3017.  
  3018. ΓòÉΓòÉΓòÉ 13.1.1. Memory models ΓòÉΓòÉΓòÉ
  3019.  
  3020. This compiler supports up to six different memory models. Memory models are 
  3021. needed to tell the compiler, where and how to place code and data segments for 
  3022. the final executable file. This information is required because of the 
  3023. segmented memory access mechanism of the Intel 80x86 processor family. A modern 
  3024. computer usually provides many megabytes of direct random access memory (DRAM) 
  3025. for its programs to run in. But if the processor is running under a 16-bit 
  3026. mode, all the CPU registers are only 16 bits wide, covering only a 64 KB range 
  3027. for 16-bit pointers. This means that the RAM can only be accessed in small 
  3028. portions not more than 64 KB at a time. This kind of memory access is called 
  3029. segmented memory access. Every 16-bit pointer can only point to inside a 
  3030. segment less than 64 KB. Segment descriptors are needed at runtime to let the 
  3031. system know the beginning of actual code or data segments inside the physical 
  3032. memory. Segment registers are refering to such desciptors. Hence a complete 
  3033. linear memory address is made up of two components: 
  3034.  16-bit-segment : 16-or-32-bit-offset 
  3035. A pointer with both segment and offset components is called a far pointer while 
  3036. a pointer which contains only the offset portion of a memory address is called 
  3037. a near pointer. A near pointer refers to a default memory segment stored in one 
  3038. of the segment registers DS or CS (data or code segment). If compiling for 
  3039. 32-bit programs, the offset portion is 32 bits wide, covering an address range 
  3040. of up to 4 Giga Bytes. This is more than enough for modern programs for the 
  3041. foreseeable future. Hence 32-bit programs only need a linear flat memory 
  3042. access. All the necessary segment registers in such a flat model are set once 
  3043. by the operating system to the same physical base address. A common problem 
  3044. with 16-bit programs in particular is the one how to distribute the memory 
  3045. segments among the modules and their data. Depending on the memory model chosen 
  3046. the following approach has been implemented for this Modula-2 compiler: 
  3047.  
  3048.   Model Name    Align  Combine  Class     Group    Remarks
  3049.  
  3050.   S     _TEXT    WORD  PUBLIC   'CODE'      -
  3051.         _DATA    WORD  PUBLIC   'DATA'     DGROUP
  3052.         _BSS     WORD  PUBLIC   'BSS'      DGROUP
  3053.         STACK    PARA  STACK    'STACK'    DGROUP   (1)
  3054.  
  3055.   M     x_TEXT   WORD  PUBLIC   'CODE'      -       (3)
  3056.         _DATA    WORD  PUBLIC   'DATA'     DGROUP
  3057.         _BSS     WORD  PUBLIC   'BSS'      DGROUP
  3058.         STACK    PARA  STACK    'STACK'    DGROUP   (1)
  3059.  
  3060.   C     _TEXT    WORD  PUBLIC   'CODE'      -
  3061.         x_DATA   WORD  private  'FAR_DATA'  -
  3062.         x_BSS    WORD  private  'FAR_BSS'   -
  3063.         STACK    PARA  STACK    'STACK'    DGROUP   (1)
  3064.  
  3065.   L     x_TEXT   WORD  PUBLIC   'CODE'      -       (3)
  3066.         x_DATA   WORD  private  'FAR_DATA'  -
  3067.         x_BSS    WORD  private  'FAR_BSS'   -
  3068.         STACK    PARA  STACK    'STACK'    DGROUP   (1)
  3069.  
  3070.   F     _TEXT   DWORD  PUBLIC   'CODE'      -       (2)
  3071.         _DATA   DWORD  PUBLIC   'DATA'     DGROUP   (2)
  3072.         _BSS    DWORD  PUBLIC   'BSS'      DGROUP   (2)
  3073.         STACK   DWORD  STACK    'STACK'    DGROUP   (1) (2)
  3074.  
  3075. Remarks: 
  3076.  
  3077.      (1)    STACK only defined in main module. 
  3078.      (2)    32-bit segment 
  3079.      (3)    x_TEXT: 
  3080.             one logical code segment per module x. 
  3081.             x_BSS: 
  3082.             one logical uninitialized data segment per module x. 
  3083.             x_DATA: 
  3084.             one logical initialized data segment per module x. 
  3085.  
  3086.  When compiling for a 16-bit code, select the appropriate memory model with a 
  3087.  command line switch according to the following total program code and data 
  3088.  sizes: 
  3089.  
  3090.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3091.   ΓöéSwitch    ΓöéCode Size      ΓöéData Size      ΓöéMode           Γöé
  3092.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3093.   Γöé-MS       Γöéless than 64 KBΓöéless than 64 KBΓöé16-bit code    Γöé
  3094.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3095.   Γöé-MM       Γöémore than 64 KBΓöéless than 64 KBΓöé16-bit code    Γöé
  3096.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3097.   Γöé-MC       Γöéless than 64 KBΓöémore than 64 KBΓöé16-bit code    Γöé
  3098.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3099.   Γöé-ML       Γöémore than 64 KBΓöémore than 64 KBΓöé16-bit code    Γöé
  3100.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3101.   Γöé-MF       Γöé0..4 GB        Γöé0..4 GB        Γöé32-bit code    Γöé
  3102.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3103.  
  3104.  
  3105. ΓòÉΓòÉΓòÉ 13.1.2. Target operating system ΓòÉΓòÉΓòÉ
  3106.  
  3107. This Modula-2 implementation accepts the following target operating system 
  3108. switches: 
  3109.  
  3110.      Compiler 
  3111.      switch         Description 
  3112.  
  3113.       -OS2          Produce 80x86 protected mode object code for IBM OS/2 2.x 
  3114.                     or 3.0 or 1.3 
  3115.       -WIN          Produce 80x86 protected mode object code for MS Windows 3.x 
  3116.       -DOS          Produce 80x86 object code for DOS 
  3117.  
  3118.  However, the current compiler version 2.01 is only distributed with standard 
  3119.  modules and APIs for OS/2 2.x or 3.0. Future versions will also include the 
  3120.  full standard libraries for DOS and MS-Windows. 
  3121.  
  3122.  
  3123. ΓòÉΓòÉΓòÉ 13.1.3. Target processors ΓòÉΓòÉΓòÉ
  3124.  
  3125. This Modula-2 compiler produces object code for the Intel 80x86 family 
  3126. processor. A coprocessor switch is to be specified if the INLINE assembler is 
  3127. to accept 80x87 numeric coprocessor instructions. The main code generator 
  3128. always assumes the existence of the 80x87 numeric coprocessor or a software 
  3129. emulation, regardless of the coprocessor switch. Under OS/2 2.x or 3.0 a 
  3130. coprocessor emulation is supplied with the operating system. The current 
  3131. compiler version 2.01 has no coprocessor emulator itself. Under OS/2 2.x or 3.0 
  3132. the default target processor is 80386 for the 32-bit flat memory-model. 
  3133.  
  3134. Summary of target processor switches: 
  3135.  
  3136.   -8086 
  3137.   -80286 or -286 
  3138.   -80386 or -386 
  3139.   -80486 or -486 
  3140.   -80586 or -586 
  3141.   -F 
  3142.  
  3143.  
  3144. ΓòÉΓòÉΓòÉ 13.1.4. Make and Build ΓòÉΓòÉΓòÉ
  3145.  
  3146. A Modula-2 program typically consists of many modules which are related with 
  3147. each other in a hierarchical order. The top level module is usually a main 
  3148. program module or a dynamic link implementation module and it may import lower 
  3149. level modules. The lower level modules may in turn import other low level 
  3150. modules etc. If a low level module has been changed and is to be recompiled, 
  3151. all modules importing the changed module are affected. If the low level module 
  3152. has been updated in its definition module then all importing modules must be 
  3153. recompiled as well. 
  3154.  
  3155. This process of recompiling dependent importing modules is called a 'make' or 
  3156. 'build'. A 'make' function only recompiles updated dependent modules, while a 
  3157. 'build' function compiles all the dependent modules (updated or not). Other 
  3158. compilers often need the services of a separate make-utility using a special 
  3159. make-file with a description of the module's interdependences in order to 
  3160. invoke the recompilation of dependent modules. This Modula-2 version, however, 
  3161. has already integrated the make- or build- functions in its compiler program. 
  3162. It is activated with one of the simple command line switches: 
  3163.  
  3164.      -M     Also recompile updated dependent modules 
  3165.      -B     Also recompile all dependent modules 
  3166.  
  3167.  If one the above mentioned switches is specified on the command line the 
  3168.  compiler also produces a complete linker response and linker definition files 
  3169.  which can be used for the 32-bit LINK386.EXE or 16-bit LINK.EXE programs for 
  3170.  producing the final executable program file. 
  3171.  
  3172.  
  3173. ΓòÉΓòÉΓòÉ 13.1.5. Language and CPU extensions ΓòÉΓòÉΓòÉ
  3174.  
  3175. This Modula-2 compiler provides an extended language grammar if the following 
  3176. command line switch has been specified: 
  3177.  
  3178.  -XL 
  3179.  
  3180. The Intel 80x86 CPU family provides some undocumented code instructions which 
  3181. can make machine code shorter and quicker when used. The code generator of this 
  3182. Modula-2 compiler can make use of them if the extended instructions switch is 
  3183. specified on the command line: 
  3184.  
  3185.  -XI 
  3186.  
  3187. The undocumented instructions should work with any INTEL 80386 or higher CPU, 
  3188. but they are not necessarily available with CPUs from other manufacturers, 
  3189. which are otherwise compatible. 
  3190.  
  3191. It is often desirable to ignore return values from function designators, 
  3192. especially when using OS/2 APIs. This does not agree with the stricter Modula-2 
  3193. language definition. This compiler, however, accepts the relaxed function 
  3194. designator switch 
  3195.  
  3196.  -XF 
  3197.  
  3198. from the command line. It enables the programmer to use function procedure 
  3199. identifiers like normal procedure calls, just ignoring the return value. 
  3200.  
  3201.  
  3202. ΓòÉΓòÉΓòÉ 13.1.6. Stack segment ΓòÉΓòÉΓòÉ
  3203.  
  3204. There are two command line switches affecting the runtime stack: 
  3205.  
  3206.   -SSFAR
  3207.  -SS=stacksize
  3208.  
  3209. The '-SSFAR' tells the compiler that the stack segment is not supposed to 
  3210. reside in the default data segment group DGROUP. This switch is needed for 
  3211. 16-bit memory-model dynamic link libraries whose functions are typically called 
  3212. from another program using the caller's CPU stack for local variables and 
  3213. actual parameters. This switch is not needed for 32-bit flat memory-model 
  3214. dynamic link libraries because the flat linear address scheme doesn't care 
  3215. about memory segmentation. 
  3216.  
  3217. The 'SS=stacksize' tells the compiler to pass on the stack size in number of 
  3218. KBytes to the linker response file. Under 16-bit memory-models the value range 
  3219. for the stacksize must not exceed 64 KBytes because of the 16-bit memory 
  3220. segmentation. For 32-bit programs the maximum value currently is 65536 KBytes. 
  3221. The default stack size is 8 KBytes. 
  3222.  
  3223. Command line examples: 
  3224.  
  3225.   REM
  3226.   REM build an optimized 16-bit small memory model
  3227.   REM dynamic link library
  3228.   REM
  3229.   MOD      MYLIB.MOD -OS2 -MS -O -SSFAR -B
  3230.   LINK    @MYLIB.RSP
  3231.   REM
  3232.   REM make an optimized 32-bit flat memory model program
  3233.   REM with a stacksize of 128 KBytes
  3234.   REM
  3235.   MOD      MYPROG.MOD -OS2 -MF -O -SS=128 -M
  3236.   LINK386 @MYPROG.RSP
  3237.  
  3238.  
  3239. ΓòÉΓòÉΓòÉ 13.1.7. Debugger support ΓòÉΓòÉΓòÉ
  3240.  
  3241. The current compiler version 2.01 provides no debugger. Future releases may 
  3242. include special Modula-2 debuggers. Nevertheless, some basic debugger 
  3243. information can be stored into the output object files. The linker places these 
  3244. informations into the final executable file. The following debug switches are 
  3245. supported: 
  3246.  
  3247.   -L
  3248.  -D
  3249.  
  3250. The '-L' switch tells the compiler to store the line numbers of the input 
  3251. source files into the output object files, from where they are passed on by the 
  3252. linker program into the map file and executable file. If compiling for the 
  3253. 32-bit OS/2 target platform, the internal source line number format is readable 
  3254. for any HLL-compatible debugger, such as IBM's SD386 from the Developer 
  3255. Connection for OS/2, Volume 6 or later, (Development Tools, Disc 1). Otherwise 
  3256. the source line numbers are generated in a format which should be readable for 
  3257. CodeView-compatible debuggers. 
  3258.  
  3259. The '-D' switch causes the compiler's code generator to produce code which 
  3260. spills any register held values into the memory variables for each of the 
  3261. Modula-2 source expressions. This ensures proper updated memory values when 
  3262. stepping through the source lines with a debugger. For this purpose the '-D' 
  3263. switch disables the '-OB' and '-OI' optimizer switches. 
  3264.  
  3265. The '-D' switch also causes the compiler to generate HLL-compatible symbolic 
  3266. debug infos. These are written into the output OBJ-file and passed on by the 
  3267. linker into the final executable file. 
  3268.  
  3269. Command line example for making and debugging a 32-bit OS/2 program: 
  3270.  
  3271.   MOD MYPROG.MOD -B -O -L
  3272.   LINK386 @MYPROG.RSP
  3273.   SD386 MYPROG.EXE
  3274.  
  3275.  
  3276. ΓòÉΓòÉΓòÉ 13.1.8. Optimizations ΓòÉΓòÉΓòÉ
  3277.  
  3278. Modula-2 is a high-level programming language providing a fair degree of 
  3279. hardware independence. Because of this the compiler parser does not immediately 
  3280. translate source statements into a machine code. It rather produces an 
  3281. intermediate form of statements which in turn are transformed into the target 
  3282. CPU machine code. In order to make use of the special CPU capabilities for 
  3283. shorter and quicker programs some optimizations can take place before producing 
  3284. the machine code. This compiler provides the following optimizer switches: 
  3285.  
  3286.   -OG
  3287.  -OB
  3288.  -OI
  3289.  -O
  3290.  
  3291. The '-OG' switch causes the compiler to perform a global data flow analysis 
  3292. accross basic blocks. A statement-sequence for a procedure or module body is 
  3293. subdivided into basic blocks because of various branchings taking place at 
  3294. runtime by flow-of-control statements. The global dataflow information serves 
  3295. as the basis for further live variable analysis which tries to find out for how 
  3296. long any variable might be needed by succeeding statements. This information in 
  3297. turn is used for the allocation of stack memory during runtime for local 
  3298. temporary variables and for loop optimizations. Temporary variables are created 
  3299. during runtime to hold intermediate expressions during program execution. The 
  3300. goal is to use as little stack memory as possible for temporaries keeping them 
  3301. rather in CPU registers whenever possible. The goal of the loop optimization is 
  3302. to keep inner loop variables in CPU registers, too, if possible, because inner 
  3303. loop variables are usually more often accessed. 
  3304.  
  3305. The global dataflow analysis also serves as a basis for an available register 
  3306. analysis which tries to determine for how long any register byte might keep its 
  3307. value even accross basic blocks without changing the intended program 
  3308. semantics. This helps to avoid unecessary reloads of CPU registers during 
  3309. program execution. 
  3310.  
  3311. The '-OB' switch causes the compiler to perform an expression optimization. If 
  3312. the source program repeatedly specifies the same complex expression then it is 
  3313. often possible to compute such an expression only once during program execution 
  3314. and to store it in a temporary variable. Such a common expression could then be 
  3315. used by simply refering to that temporary variable instead of completely 
  3316. recomputing the expression each time it is needed. Common expressions are 
  3317. recognized within basic blocks and to some degree even globally outside basic 
  3318. blocks by this compiler. 
  3319.  
  3320. The '-OB' switch also tells the compiler to reduce in strength intermediate 
  3321. statements created after the parsing. Multiplication and division operations 
  3322. for example can often be reduced to quicker shift instructions. 
  3323.  
  3324. The '-OI' switch causes the compiler to produce more efficient machine code for 
  3325. indexed and/or dereferenced pointer expressions. An Intel 80x86 CPU operand can 
  3326. have index and/or base register(s) and a scale factor in addition to the memory 
  3327. offset. The goal of this optimization is to keep as many pointers or indices as 
  3328. possible in base or index registers for machine code operands during program 
  3329. execution. 
  3330.  
  3331. The '-O' switch causes the compiler to perform all of above  mentioned 
  3332. optimizations. It is just a short notation for '-OG -OB -OI'. 
  3333.  
  3334.  
  3335. ΓòÉΓòÉΓòÉ 13.1.9. Record field alignments ΓòÉΓòÉΓòÉ
  3336.  
  3337. This compiler provides various schemes for record field alignments. A record 
  3338. field can be aligned on a byte, word or double word boundary. Proper alignments 
  3339. can reduce the memory access time for record fields. If, for example, a double 
  3340. word sized record field has to be accessed in a 32-bit program, more than one 
  3341. step would be needed if it were not double word aligned in the memory. 
  3342. Alignment is done by this compiler through implicit insertion of unnamed filler 
  3343. bytes. 
  3344.  
  3345. The following alignment switches are recognized by the compiler: 
  3346.  
  3347.   -A    default alignment
  3348.  -A1    byte alignment
  3349.  -A2    word alignment
  3350.  -A4    double word alignment
  3351.  
  3352. The '-A1' switch tells the compiler to align every record field on a byte 
  3353. boundary. This means no filler bytes are inserted whatsoever between record 
  3354. fields. 
  3355.  
  3356. The '-A2' switch tells the compiler to align any record field with a type size 
  3357. greater than 1 byte or with a record type on a 2-bytes word boundary by 
  3358. inserting filler bytes between record fields as needed. 
  3359.  
  3360. The '-A4' switch tells the compiler to align any record field with a type size 
  3361. greater than 1 byte or with a record type on a 4-bytes double word boundary by 
  3362. inserting filler bytes between record fields as needed. 
  3363.  
  3364. If no alignment or '-A' switch is specified on the command line then a default 
  3365. alignment scheme applies for record fields as follows: 
  3366. If the field is of record type then align it on a near pointer size (2 bytes 
  3367. for 16-bit memory-models, 4 bytes for 32-bit memory-models). 
  3368. Otherwise if the field size is 1 byte, perform byte alignment. 
  3369. Otherwise if the field size is 2 bytes, perform word alignment. 
  3370. Otherwise perform word alignment for 16-bit memory-models and double word 
  3371. alignment for 32-bit memory-models. 
  3372.  
  3373. If the type of the record field is a (possibly multidimensional) array then 
  3374. alignment for any of above mentioned alignment schemes is based upon the array 
  3375. element type. 
  3376.  
  3377.  
  3378. ΓòÉΓòÉΓòÉ 13.1.10. OS/2 application types ΓòÉΓòÉΓòÉ
  3379.  
  3380. Under OS/2 there are 3 different application types: 
  3381.  
  3382.      -PM:NOVIO           full screen text mode applications 
  3383.      -PM:VIO             window compatible text mode applications 
  3384.      -PM:PM              Presentation Manager applications 
  3385.  
  3386.  A full screen application is not compatible with the OS/2 Presentation 
  3387.  Manager. It is run in a separate text-mode screen session. Full screen 
  3388.  applications may use low-level facilities for screen display and mouse or 
  3389.  keyboard inputs. 
  3390.  
  3391.  A window compatible text mode application only uses a certain subset of the 
  3392.  OS/2 API for screen, mouse and keyboard. They can be run as text mode full 
  3393.  screen or windowed applications. All Modula-2 standard libraries for this 
  3394.  compiler have been written for a window compatible mode. The compiler itself 
  3395.  is window compatible, too. 
  3396.  
  3397.  A Presentation Manager application runs under the graphical user interface 
  3398.  using windows. It does not run as a text mode application for a separate 
  3399.  session. The Presentation Manager provides a CUA-compatible user interface for 
  3400.  programs using windows and graphic objects, with full mouse support. 
  3401.  
  3402.  Only one of above mentioned switches can be specified on the command line. The 
  3403.  default application type is window compatible: '-PM:VIO'. 
  3404.  
  3405.  
  3406. ΓòÉΓòÉΓòÉ 13.1.11. C-style procedures ΓòÉΓòÉΓòÉ
  3407.  
  3408. The following switches tell the compiler to assume C-style parameter passing 
  3409. order or a C-style procedure return code. The default is a Pascal-like 
  3410. parameter passing convention and a Pascal-like return code. 
  3411.  
  3412.      -CPARAM             C-style order of parameter passing 
  3413.      -CRET               C-style procedure return: Caller clears local stack 
  3414.      -CDECL              -CPARAM and -CRET combined. 
  3415.  
  3416.  These parameters are needed for compatibility with functions written in the 
  3417.  C-language, e.g. OS/2 2.x or 3.0 APIs or C-libraries. 
  3418.  
  3419.  Note: These parameters are active for all modules being compiled, including 
  3420.  possible imported modules. Modula-2 procedures usually conform to a 
  3421.  Pascal-like manner for parameter passing in order to produce shorter and safer 
  3422.  machine code. C-style parameters and procedure returns should be the 
  3423.  execption. It is recommended not to use these switches on the command line, 
  3424.  but only locally as compiler directives before individual procedure 
  3425.  declarations inside the source files. 
  3426.  
  3427.  
  3428. ΓòÉΓòÉΓòÉ 13.1.12. Miscellaneous switches ΓòÉΓòÉΓòÉ
  3429.  
  3430. The following miscellaneous switches are recognized by this compiler: 
  3431.  
  3432.      -P                       verbose compilation with error prompts 
  3433.      -W0                      warning level 0 
  3434.      -W1                      warning level 1 
  3435.      -E=directory             executable file directory 
  3436.      -C=number                cancel of <number> compiler error 
  3437.      -R4                      REAL = SHORTREAL 
  3438.      -R8                      REAL = LONGREAL 
  3439.      -H2                      HIGH returns 2-bytes CARDINAL 
  3440.      -H4                      HIGH returns 4-bytes LONGCARD 
  3441.      -V                       assume volatile global variables 
  3442.      -FSAVE                   Save all FPU registers are the beginning of a 
  3443.                               procedure. 
  3444.      -$=char                  redefine the introducing character for compiler 
  3445.                               directives 
  3446.  
  3447.  The '-P' switch causes a source file display during compilation. It also 
  3448.  activates error prompts for semantic errors, asking the user to hit any key 
  3449.  for the continuation of the compilation. If this switch is not specified then 
  3450.  only error messages without prompts are displayed. 
  3451.  
  3452.  The '-W0' or '-W1' switches will set the warning level for the compilation. If 
  3453.  the warning level is 1 then the compiler also displays warning messages. If 
  3454.  the warning level is 0 then no warnings are displayed. Error messages are 
  3455.  always displayed. 
  3456.  
  3457.  The '-E=directory' switch specifies the directory in which the linker response 
  3458.  and linker definition files and the final executable files are to be written. 
  3459.  The default executable directory is the current one (-E=.\). 
  3460.  
  3461.  Command line example: 
  3462.  
  3463.     REM
  3464.     REM make an optimized executable program for
  3465.     REM the directory C:\MOD32\OS2BIN
  3466.     REM
  3467.     MOD       MYPROG.MOD -M -O -E=C:\MOD32\OS2BIN
  3468.     LINK386  @C:\MOD32\OS2BIN\MYPROG.RSP
  3469.  
  3470.  The '-R4' or '-R8' switches tell the compiler, what type size to be used for 
  3471.  the REAL type. A REAL can be either a 4-bytes SHORTREAL or a 8-bytes LONGREAL. 
  3472.  The default is REAL=LONGREAL. This switch has been introduced to ensure 
  3473.  compatibility with other Modula-2 compilers. 
  3474.  
  3475.  The '-H2' or '-H4' switches tell the compiler, what type size to be returned 
  3476.  for standard procedure HIGH. The default is LONGCARD for 32-bit flat 
  3477.  memory-model, and CARDINAL for any 16-bit memory-model. 
  3478.  
  3479.  The '-V' switch tells the compiler to treat non-stack (that is, non-local) 
  3480.  variables as volatile. Volatiles variables are only kept in registers for the 
  3481.  duration of a single machine code instruction, if at all. Volatile variables 
  3482.  might be accessed concurrently by several asynchronous processes. That's why 
  3483.  they cannot be kept in registers accros multiple instructions. An example of 
  3484.  volatile variables is that of memory mapped devices. 
  3485.  
  3486.  The switch '-FSAVE' tells the compiler to generate code for saving all FPU 
  3487.  register at the beginning of a procedure. And it also causes the compiler to 
  3488.  generate FPU restoration code before leaving the procedure. This is useful for 
  3489.  Pascal-style behavior: Callee saves FPU registers. If this switch is not 
  3490.  specified then the compiler assumes that the caller has to save any FPU 
  3491.  register before calling the procedure. 
  3492.  
  3493.  The switch '-$=char' tells the compiler to use another character for starting 
  3494.  comment embedded compiler-directives. The default compiler-directive 
  3495.  introducing character is the dollar sign '$'. Compiler-directives serve as 
  3496.  local compiler switches for the duration of the compilation of a source 
  3497.  module. They are embedded in special source file comments and started with 
  3498.  this special character. 
  3499.  
  3500.  Example: 
  3501.  
  3502.     REM
  3503.     REM compile with a redefined compiler directive
  3504.     REM introducing character
  3505.     REM
  3506.     MOD  MYPROG.MOD  -O -$=?
  3507.  
  3508.  If the source file MYPROG.MOD for above mentioned example contains 
  3509.  compiler-directives, they are now only recognized with the new '?' introducing 
  3510.  special character. Example: 
  3511.  
  3512.     MODULE MyProg;
  3513.  
  3514.       (*$R8 no more recognized as compiler directive R8 *)
  3515.  
  3516.       (*?A4 now recognized as compiler directive A4 *)
  3517.  
  3518.       .........
  3519.  
  3520.     END MyProg.
  3521.  
  3522.  Defining a new introducing character for comment embedded compiler-directives 
  3523.  helps to avoid clashes with other Modula-2 compilers using a similar syntax 
  3524.  for comment embedded directives. 
  3525.  
  3526.  
  3527. ΓòÉΓòÉΓòÉ 13.2. Compiler directives ΓòÉΓòÉΓòÉ
  3528.  
  3529. Many of the command line switches are also available locally inside source 
  3530. modules. They are embedded in special comments and serve as local compiler 
  3531. directives. They overwrite the command line or default switches for the 
  3532. duration of the compilation of a source module. The following summary lists the 
  3533. frequently used compiler directives recognized by this compiler: 
  3534.  
  3535.      (*$XL+*) or (*$XL-*) enable or disable language-extensions 
  3536.      (*$XI+*) or (*$XI-*) enable or disable usage of undocumented CPU 
  3537.           instructions 
  3538.      (*$XF+*) or (*$XF-*) enable or disable relaxed function designators 
  3539.      (*$8086*) 
  3540.      (*$80286*) or (*$286*) 
  3541.      (*$80386*) or (*$386*) 
  3542.      (*$80486*) or (*$486*) 
  3543.      (*$80586*) or (*$586*) Compile for specified target-CPU 
  3544.      (*$F+*) or (*$F-*) Assume existence of a numeric coprocessor for 
  3545.           INLINE-assembler 
  3546.      (*$R4*) or (*$R8*) Assume REAL=SHORTREAL or REAL=LONGREAL 
  3547.      (*$D+*) or (*$D-*) Enable or disable debugger support 
  3548.      (*$L+*) or (*$L-*) Enable or disable the passing on of source line-numbers 
  3549.           to output object files. 
  3550.      (*$OB+*) or (*$OB-*) Enable or disable expression optimization 
  3551.      (*$OG+*) or (*$OG-*) Enable or disable global dataflow optimization for 
  3552.           register assignments and loop optimizations. 
  3553.      (*$OI+*) or (*$OI-*) Enable or disable pointer and index optimizations for 
  3554.           CPU base/index register usage. 
  3555.      (*$O+*) or (*$O-*) Enable or disable all compiler optimizations 
  3556.      (*$DLL*) Only recognized at the beginning of a definition module. The 
  3557.           corresponding implementation module is to become a dynamic link 
  3558.           library. 
  3559.      (*$PREFIX*) Only recognized at the beginning of a definition module, whose 
  3560.           corresponding implementation module is to become a dynamic link 
  3561.           library. All public symbols of the compiled dynamic link library will 
  3562.           be qualified with the module name. Otherwise OS/2 by default uses 
  3563.           public DLL symbols in an unqualified manner. 
  3564.      (*$SSFAR*) Only recognized at the beginning of a program module. A far 
  3565.           stack-segment is assumed for the compilation of the module. 
  3566.      (*$A*) 
  3567.      (*$A1*) 
  3568.      (*$A2*) 
  3569.      (*$A4*) Record field alignment (A = default alignment scheme, An = 
  3570.           n-boundary alignment scheme) 
  3571.      (*$V+*) or (*$V-*) Enable or disable the assumption that global variables 
  3572.           are volatile 
  3573.      (*$CPARAM+*) or (*$CPARAM-*) C-style or Pascal-style parameter passing 
  3574.           order for procedures 
  3575.      (*$CRET+*) or (*$CRET-*) C-style or Pascal-style procedure return code 
  3576.      (*$CDECL+*) or (*$CDECL-*) C-style or Pascal-style procedures. Combines 
  3577.           (*$CPARAM╤æ*) and (*$CRET╤æ*). 
  3578.      (*$SOM+*) or (*$SOM-*) The following record-type declarations are treated 
  3579.           as OS/2 SOM classes or as Modula-2 records. 
  3580.      (*$API16+*) or (*$API16-*) Only accepted in a definition module for an old 
  3581.           OS/2 16-bit API. If set on, the following APIs (procedure headings in 
  3582.           definition module) are to be treated as 16-bit APIs. Even though the 
  3583.           procedure headings are declared like any flat memory model API, they 
  3584.           are thunked to a 16-bit code whenever called, using 'SYSTEM.Thunk', 
  3585.           from where control is then transfered to the 16-bit library. Thunking 
  3586.           from 0:32 to 16:16 addressing is needed for flat 32-bit OS/2, because 
  3587.           there are still some older 16-bit kernel APIs left from previous 
  3588.           versions of OS/2, without corresponding new 32-bit APIs. Otherwise 
  3589.           there is no need for using this compiler directive. 
  3590.      (*$H2*) or (*$H4*) Standard procedure HIGH returns CARDINAL or LONGCARD 
  3591.           value. 
  3592.      (*$W1*) or (*$W0*) Enable or disable Warnings during the compilation. 
  3593.  
  3594.  Any comment embedded compiler directive must be started with a special 
  3595.  character, usually a dollar sign '$'. Another special character can be used as 
  3596.  specified with command line switch '-$=char' to avoid clashes with other 
  3597.  Modula-2 compilers using a similar comment embedded directive syntax. 
  3598.  
  3599.  
  3600. ΓòÉΓòÉΓòÉ 13.3. Conditional compilation ΓòÉΓòÉΓòÉ
  3601.  
  3602. This compiler also enables conditional compilation using the following comment 
  3603. embedded compiler directives: 
  3604.  
  3605.  
  3606.   (*$IF BoolExpr *)     or
  3607.   (*$IF NOT BoolExpr *) or
  3608.   (*$IFDEF Ident *)     or
  3609.   (*$IFNDEF Ident *)
  3610.      ........
  3611.   (*$ELSE *)
  3612.      ........
  3613.   (*$ENDIF *)
  3614.  
  3615. where 'Ident' is any existing identifier and 'BoolExpr' is any existing boolean 
  3616. constant identifier. 
  3617.  
  3618. Example: 
  3619.  
  3620.     PROCEDURE CAP( ch:CHAR ):CHAR;
  3621.     CONST
  3622.       UseCountryCode = SYSTEM.OS2 AND SYSTEM.Flat32Model;
  3623.     VAR
  3624.       (*$IF UseCountryCode *)
  3625.         CountryCode : COUNTRYCODE;
  3626.         rc          : APIRET;
  3627.       (*$ENDIF *)
  3628.     BEGIN
  3629.       (*$IF UseCountryCode *)
  3630.         (* 32-bit OS/2 uses own case mapping *)
  3631.         CountryCode.Country := 0;
  3632.         CountryCode.CodePage := 0;
  3633.         rc := DosMapCase( 1, CountryCode, ch );
  3634.       (*$ELSE*)
  3635.         (* use Modula's case mapping *)
  3636.         CASE ch OF
  3637.         | '╨ö':      ch := '╨₧';
  3638.         | '╨ñ':      ch := '╨⌐';
  3639.         | '╨æ':      ch := '╨¬';
  3640.         | 'a'..'z': ch := CHR( ORD(ch) - (ORD('a') - ORD('A')) );
  3641.         END;
  3642.       (*$ENDIF*)
  3643.       RETURN ch;
  3644.     END CAP;
  3645.  
  3646.  
  3647. ΓòÉΓòÉΓòÉ 13.4. Linker directives ΓòÉΓòÉΓòÉ
  3648.  
  3649. There is a special linkage directive available with this compiler. It is 
  3650. specified as a special comment embedded directive and is recognized anywhere 
  3651. inside a program module source text. It is started with a $LINK keyword, to be 
  3652. followed by a series of linkage definition statements. The linkage definition 
  3653. statements are directly passed on to the linker response file, along with other 
  3654. default linkage statements. 
  3655.  
  3656. Example: 
  3657.  
  3658. (*$LINK
  3659.   LIBRARY ANIMAL
  3660.     INITINSTANCE
  3661.   DESCRIPTION
  3662.     'Animal class DLL, compiled with Modula-2.'
  3663.   PROTMODE
  3664.   DATA
  3665.    MULTIPLE NONSHARED LOADONCALL
  3666. *)
  3667.  
  3668. If a linker directive specifies an IMPORTS or EXPORTS list, the corresponding 
  3669. default list is no more longer generated from the public symbols of the 
  3670. definition module. Hence an IMPORTS or EXPORTS linker directive must be 
  3671. followed by a complete symbol list. A partial list won't do it. The linkage 
  3672. program (usually LINK386.EXE or LINK.EXE) must be able to understand the linker 
  3673. directives. There is no need for explicit linker directives for a normal 
  3674. program or dynamic link library. The $LINK directive has been introduced mainly 
  3675. because of the deviating specifications for OS/2 SOM libraries. 
  3676.  
  3677. It is beyond the scope of this compiler documentation to provide a complete 
  3678. list of all the possible linker definition statements. The user is referred to 
  3679. the original program manuals for LINK386 or LINK. 
  3680.  
  3681.  
  3682. ΓòÉΓòÉΓòÉ 13.5. Compiler environment ΓòÉΓòÉΓòÉ
  3683.  
  3684. Every program runs in a process which has its own environment. The process 
  3685. environment consists of a series of zero-terminated strings. Every string has 
  3686. the form <identifier>=<contents>. An environment string starts with an 
  3687. identifier which is called an enironment variable. It is followed by an equal 
  3688. sign '=' and a string value. Environment variables usually store information 
  3689. about the operating environment for programs, e.g. the directories to be 
  3690. searched for specific data or programs on the hard disks. 
  3691.  
  3692. This Modula-2 compiler consults the following environment variables: 
  3693.  
  3694.      MOD_SRC Directories for Modula-2 source files (.MOD or .DEF) 
  3695.      MOD_TMP Directory for temporary files (.TMP or .WRK) 
  3696.      MOD_LIB Directories for library files (.LIB or .DLL) 
  3697.      MOD_OBJ_SMALL 
  3698.      MOD_OBJ_MEDIUM 
  3699.      MOD_OBJ_COMPACT 
  3700.      MOD_OBJ_LARGE 
  3701.      MOD_OBJ_FLAT32 Directories for the corresponding memory-model object files 
  3702.           (.OBJ) 
  3703.      DPATH Default directory for object files (.OBJ) 
  3704.      APPEND Default directory for object files (.OBJ) 
  3705.      LIB  Default directory for library files (.LIB or .DLL) 
  3706.  
  3707.  If the MOD_LIB environment variable does not exist then the LIB environment 
  3708.  variable is taken. 
  3709.  
  3710.  If the MOD_OBJ_... environment variable for the corresponding memory-model 
  3711.  does not exist then the DPATH environment variable is taken. If the DPATH 
  3712.  environment variable does not exist then the APPEND environment variable is 
  3713.  taken. The compiler may search multiple paths for objects during possible 
  3714.  recompilation of dependent modules. But it will only use the first path from 
  3715.  the object environment variable for storing newly compiled object files. 
  3716.  
  3717.  If no environment variable exists for object file directories then the current 
  3718.  directory '.\' is used for object files. The same is true for library files. 
  3719.  
  3720.  The LINK.EXE or LINK386.EXE programs do not need any special environment 
  3721.  variables if the corresponding linker response files as made or build by the 
  3722.  compiler are used, except for the TMP variable, which contains the temporary 
  3723.  files directory name. 
  3724.  
  3725.  
  3726. ΓòÉΓòÉΓòÉ 13.6. Dynamic link library creation ΓòÉΓòÉΓòÉ
  3727.  
  3728. A dynamic link library contains executable code for common procedures, just as 
  3729. an ordinary library does. Yet code for procedures in dynamic link libraries is 
  3730. not copied into the executable (.EXE) file. Instead, the library itself is 
  3731. loaded into memory at run time, along with the executable file. 
  3732.  
  3733. Dynamic link libraries serve much the same purpose that standard libraries do, 
  3734. but they have the following advantages: 
  3735.  
  3736.      -    Applications link more quickly. With dynamic linking, the executable 
  3737.           code for a dynamic link library is not copied into the .EXE file of 
  3738.           the application. Instead, only an import definition is copied. 
  3739.      -    Applications require less disk space. With dynamic linking, several 
  3740.           different program applications can access the same dynamic link 
  3741.           procedure stored in one place. Without dynamic linking, the code for 
  3742.           the procedure would be repeated in every .EXE file. 
  3743.      -    Libraries and applications are independent. Dynamic link libraries 
  3744.           can be updated any number of times without relinking the applications 
  3745.           that use them. This may be particularly convenient for a user of 
  3746.           third part-party libraries. In case of updates, only a copy a the new 
  3747.           library needs to be installed on the disk. At run time, the unchanged 
  3748.           applications then automatically call the updated library procedures. 
  3749.      -    Code and data segments can be shared. Without dynamic linking, such 
  3750.           sharing is not possible because each file has its own copy of all the 
  3751.           code and data it uses. By sharing segments with dynamic linking, 
  3752.           memory can be used more efficiently. 
  3753.  
  3754.  Under OS/2 2.x or 3.0 it is also possible to declare commonly used variables 
  3755.  in addtion to the procedures as part of the public interface of a dynamic link 
  3756.  library. As in the case with public procedure, these common variables are only 
  3757.  allocated once and then shared by all the applications. 
  3758.  
  3759.  This compiler supports the creation of dynamic link libraries. A definition 
  3760.  module serves to describe the public interface of a dynamic link library, 
  3761.  while the implementation module declares all private data and the procedures. 
  3762.  From a programmer's point of view there is hardly any difference between an 
  3763.  ordinary module and a dynamic link library. In order to make an implementation 
  3764.  module a dynamic link library from code compiled by this compiler, the 
  3765.  following compiler directive must be specified at the very beginning of the 
  3766.  definition module: 
  3767.  
  3768.     (*$DLL*)
  3769.  
  3770.  If compiling for a segmented 16-bit memory-model then the stack segment for 
  3771.  the dynamic link library has to treated as a far segment, since it is the 
  3772.  caller's stack, which will be used during run time. The following compiler 
  3773.  directive at the very beginning of the definition module informs the compiler 
  3774.  about the far location of the stack segment: 
  3775.  
  3776.     (*$SSFAR*)
  3777.  
  3778.  The following example illustrates the creation of a dynmaic library for the 
  3779.  standard module 'Terminal' under OS/2 2.x or 3.0. The source files for the 
  3780.  definition and implementation modules might contain this: 
  3781.  
  3782.     (*$DLL Terminal to be implemented as dynamic link library *)
  3783.     DEFINITION MODULE Terminal;
  3784.       PROCEDURE Read( VAR ch: CHAR );
  3785.       PROCEDURE BusyRead( VAR ch: CHAR );
  3786.       PROCEDURE ReadAgain();
  3787.       PROCEDURE ScanCode():SHORTCARD;
  3788.       PROCEDURE SetEcho( Flag: BOOLEAN );
  3789.       PROCEDURE GetEcho( VAR Flag: BOOLEAN );
  3790.       PROCEDURE Write( ch: CHAR );
  3791.       PROCEDURE WriteLn();
  3792.       PROCEDURE WriteString( s: ARRAY OF CHAR );
  3793.     END Terminal.
  3794.  
  3795.     IMPLEMENTATION MODULE Terminal;
  3796.       (* private code and data declarations ... *)
  3797.     END Terminal.
  3798.  
  3799.  The steps for making the dynamic link library are much the same that the 
  3800.  creation process for an ordinary execution file would require: 
  3801.  
  3802.     REM
  3803.     REM      Make the dynamic link library
  3804.     REM      TERMINAL.DLL
  3805.     REM
  3806.     MOD      TERMINAL.MOD -m -o
  3807.     LINK386 @TERMINAL.RSP
  3808.  
  3809.  Indeed, the internal format of executable files and those of dynamic link 
  3810.  libraries are almost the same. Only the file name extensions are different: 
  3811.  
  3812.     .DLL for dynamic link libraries
  3813.    .EXE for executable applications
  3814.  
  3815.  
  3816. ΓòÉΓòÉΓòÉ 14. Language extensions ΓòÉΓòÉΓòÉ
  3817.  
  3818. Modula-2 is a powerful high-level programming language. The language-grammar is 
  3819. based upon the book 'Programming in Modula-2', 4th edition, by N.Wirth. 
  3820. Nevertheless, the Modula-2 language is not perfect. Modern software engeneering 
  3821. requires language tools for object oriented programming and to some degree a 
  3822. cooperation with modules written in other programming languages such as 
  3823. C-language. A programming language also has to provide access to operating 
  3824. system APIs. For these reasons this compiler provides some extensions to the 
  3825. standard Modula-2 language. The extensions are enabled globally via the command 
  3826. line switch 
  3827.  
  3828.  -XL 
  3829.  
  3830. or locally via the comment embedded compiler directive 
  3831.  
  3832.  (*$XL+*) 
  3833.  
  3834. and they provide the following additional features: 
  3835.  
  3836.   - Extended identifiers
  3837.  - New reserved words
  3838.  - Object oriented features
  3839.   - Extending record types
  3840.   - Dynamic type tests for records
  3841.   - Type guard selectors
  3842.   - Regional type guards
  3843.   - Type bound procedures
  3844.  - System Object Model
  3845.  - Bitwise operators
  3846.  - New logical operators
  3847.  - Typed constants
  3848.  - Multidimensional open array parameters
  3849.  - Segmentation
  3850.  - Extended imports
  3851.  
  3852. Using any of above mentioned features makes the program less portable for other 
  3853. Modula-2 compilers. But they can make software implementation a lot more easier 
  3854. for many projects. The following documentation sections provide further 
  3855. information on each of above mentioned extended language feature. 
  3856.  
  3857.  
  3858. ΓòÉΓòÉΓòÉ 14.1. Extended Identifiers ΓòÉΓòÉΓòÉ
  3859.  
  3860. Modula-2 identifiers consist of case sensitive letters and digits. They must 
  3861. start with a digit. For the majority of application programs this is 
  3862. sufficient. Only in cases of mixed language programming or of using operating 
  3863. system APIs the identifier rules do not always satisfy the programmer's needs. 
  3864. OS/2 2.x or 3.0 APIs and C-language modules allow the underscore character '_' 
  3865. in their identifier strings. That's why this Modula-2 compiler will also 
  3866. accecpt the underscore '_' in addition to normal letters and digits for its 
  3867. identifiers if the command line language-extensions switch or compiler 
  3868. directive for the language-extensions has been set on. 
  3869.  
  3870.  
  3871. ΓòÉΓòÉΓòÉ 14.2. New reserved words ΓòÉΓòÉΓòÉ
  3872.  
  3873. Some of the extended language features such as the object-oriented programming 
  3874. or the new bitwise and logical operators require the following new reserved 
  3875. words: 
  3876.  
  3877.    FAR
  3878.    IS
  3879.    NEAR
  3880.    SHL
  3881.    SHR
  3882.    XOR
  3883.  
  3884. The above mentioned identifiers will be treated as keywords only if the command 
  3885. line switch or the comment embedded compiler directive for the 
  3886. language-extensions has been set on. They are then not available as user 
  3887. defined identifiers. 
  3888.  
  3889.  
  3890. ΓòÉΓòÉΓòÉ 14.3. Object oriented features ΓòÉΓòÉΓòÉ
  3891.  
  3892. This Modula-2 compiler has been extended with object oriented language 
  3893. constructs. They are closely based on the new Oberon language, which has been 
  3894. developed in the late 1980s as a successor of the Modula-2 language by Niklaus 
  3895. Wirth at the ETH Z╨ærich. The Oberon language has been fully described in the 
  3896. books: 
  3897.  
  3898.      -  'Programming in Oberon', by Martin Reiser, 1992, Addison Wesley, New 
  3899.         York. 
  3900.      -  'Object-Oriented Programming in Oberon-2', by Hanspeter M╨ñssenbeck, 
  3901.         1993, Springer-Verlag, New York. 
  3902.  
  3903.  Almost since the beginnings of programming, software development has been 
  3904.  dominated by a procedure-oriented way of thinking. Programs are decomposed 
  3905.  into procedures that transform input data into output data. 
  3906.  
  3907.  The object-oriented way of thinking focuses on the data rather than on the 
  3908.  procedures. The data and the operations applicable to them constitute objects 
  3909.  that can be asked to handle certain requests and to return data as their 
  3910.  result. 
  3911.  
  3912.  The point here is that one does not have to bother about the type of the 
  3913.  object to which a request is sent. Every type of object has its own handlers 
  3914.  called methods for processing any requests. 
  3915.  
  3916.  Object oriented languages usually provide the following features: 
  3917.  
  3918.     - Information hiding
  3919.    - Data abstraction
  3920.    - Inheritance
  3921.    - Dynamic bindings
  3922.  
  3923.  Information hiding means that the implementation of complex data is 
  3924.  encapsulated in objects and that clients have access only to an abstract view 
  3925.  of it. Clients cannot directly access the encapsulated data, but must use 
  3926.  procedures that are part of the respective object. Thus clients are not 
  3927.  troubled with implementation details and are not affected by later changes in 
  3928.  the implementation of the object. Information hiding has also been available 
  3929.  with non-object-oriented programming languages for many years. Modula-2, for 
  3930.  example, can achieve this through modules with exported handler procedures. 
  3931.  However, there is more than that to object orientation. 
  3932.  
  3933.  Data abstraction is the next step after information hiding. The objects 
  3934.  described above exist only once, yet sometimes multiple copies of them are 
  3935.  needed. Just as the programmer can declare any number of variables of a 
  3936.  specific type, object oriented programming makes it prossible to declare 
  3937.  multiple objects of a common abstract data type, including specific operations 
  3938.  for them. An abstract data type is thus a unit consisting of data and the 
  3939.  operations applicable to them. Multiple variables of such a type can be 
  3940.  declared. Under Modula-2 this is mainly done with variables of a record-type, 
  3941.  which might also contain fields of procedure-types for the handlers and 
  3942.  operations. Handler procedures could also be separately declared, along with 
  3943.  the record types, within the same module block. 
  3944.  
  3945.  Inheritance is a concept not found in any conventional programming language. 
  3946.  It means that an existing abstract data type, that is a record-type, can be 
  3947.  extended to a new one that inherits all the data and operations of the 
  3948.  existing type. The new type can include additional data and operations and can 
  3949.  even modify inherited operations. This makes it possible to design a type as a 
  3950.  semifinished product, store it in a library, and later extend it to produce 
  3951.  various final products. An important consequence of inheritance is that the 
  3952.  extended type is compatible with the original one. All procedures that work 
  3953.  with objects of the original type can also work with objects of the new type. 
  3954.  This considerably promotes the reusability of existing algorithms. 
  3955.  
  3956.  The fourth characteristic of object-oriented programming languages is dynamic 
  3957.  bindings of messages or requests to procedures. Procedures are bound during 
  3958.  run time to the dynamic-type of objects. Dynamic binding has also been known 
  3959.  for a long time in the form of procedure variables. The activation of a 
  3960.  procedure variable causes the invocation of the procedure contained in it at 
  3961.  run time. Working with procedure variables, however, is troublesome and 
  3962.  error-prone, while dynamic binding in object-oriented languages represents a 
  3963.  more elegant and reliable solution. 
  3964.  
  3965.  The following table translates the most important terms of object-oriented 
  3966.  languages into conventional terminology. These terms do not necessarily 
  3967.  represent radically new concepts, but have their corresponding terms in 
  3968.  conventional programming. 
  3969.  
  3970.      OOP term            Conventional term 
  3971.  
  3972.      Class               Extensible record-type with procedure variable 
  3973.                          field(s), defining an abstract data type 
  3974.      Object              Variable pointing to an instance of a (possibly 
  3975.                          extended ) record-type 
  3976.      Message             A call of a procedure associated with the class 
  3977.      Method              Procedure of a class, either declared in same module 
  3978.                          block, or dynamically bound through a record field 
  3979.                          with a compatible procedure-type, or type-bound to the 
  3980.                          class. 
  3981.  
  3982.  To sum it up: Object oriented programming means programming with abstract data 
  3983.  types (classes) using inheritance and dynamic binding. This Modula-2 compiler 
  3984.  provides the following features for object orientation: 
  3985.  
  3986.     - Type extensions
  3987.    - Dynamic type tests for records
  3988.    - Type guard selectors
  3989.    - Regional type guards
  3990.  
  3991.  Object orientation is achieved through the use of above mentioned features and 
  3992.  through the use of procedure variables for the dynamic bindings of methods to 
  3993.  records. Object orientation can be also achieved even more elegantly through 
  3994.  type-bound procedures in connection with above listed features. Examples are 
  3995.  given in the documentation sections about type-tests and about the type-bound 
  3996.  procedures. 
  3997.  
  3998.  
  3999. ΓòÉΓòÉΓòÉ 14.3.1. Type extensions ΓòÉΓòÉΓòÉ
  4000.  
  4001. The extensibility of record-types is the new aspect of object-oriented 
  4002. programming (OOP) and the reason that OOP proves superior to conventional 
  4003. programming in many situations. 
  4004.  
  4005. In this Modula-2 compiler a record-type can be extended to a new type that 
  4006. contains new fields, yet maintains its compatibility with the original type. In 
  4007. the declarations 
  4008.  
  4009.   TYPE
  4010.     T0 = RECORD ... END;
  4011.     T1 = RECORD( T0 ) ... END;
  4012.  
  4013. T1 is a (direct) extension of T0, and T0 is the (direct) base type of T1. Or, 
  4014. to express it in OOP terms: T0 is the base class or superclass of T1, while the 
  4015. extension can be regarded as a subclass of T0. 
  4016.  
  4017. Specifying the name of the base type in parentheses after the symbol RECORD 
  4018. means that the new type is an extension of the base type and thus contains, in 
  4019. addition to its own fields, all fields of the base type, as though they had 
  4020. been explicitly declared here. We say that the extended type inherits the 
  4021. fields of the base type and thus also refer to type extension as inheritance. 
  4022. Type extension also works for pointer types. Example: 
  4023.  
  4024.   TYPE
  4025.     P0 = POINTER TO T0;
  4026.     P1 = POINTER TO T1;         (* P1 extends P0 *)
  4027.     T0 = RECORD ... END;
  4028.     T1 = RECORD( T0 ) ... END;  (* T1 extends T0 *)
  4029.  
  4030.  
  4031. ΓòÉΓòÉΓòÉ 14.3.2. Dynamic type tests for records ΓòÉΓòÉΓòÉ
  4032.  
  4033. A common problem for object orient programming is that of method resolution. 
  4034. Messages or requests can be sent to any variable pointing to a dynamically 
  4035. allocated record (object variable) and the object has to find the proper 
  4036. procedures to handle the requests depending on the actual dynamic type of the 
  4037. object. Since an object variable could also point to any of its base typed 
  4038. records, a sort of dynamic type test is needed before calling a handler for the 
  4039. appropriate type. Such a test must reveal the dynamic type of a record pointer 
  4040. variable. The new relational operator 'IS' performs this type test: 
  4041.  
  4042.   v IS T
  4043.  
  4044. which is satisfied if the actual (or dynamic) type of 'v' is an extension of 
  4045. 'T'; that is equal to 'T' or a proper extension of 'T'. 'T' must extend the 
  4046. declared (or static) type of a variable 'v'; and variable 'v' is a record 
  4047. pointer or a formal VAR parameter of record-type. 
  4048.  
  4049. The following example shows an object oriented source skeleton for a simple 
  4050. graphics editor: 
  4051.  
  4052.   TYPE (* Message types for graphic objects *)
  4053.     Msg          = RECORD
  4054.                    END;
  4055.     DrawMsg      = RECORD( Msg )
  4056.                    END;
  4057.     ClearMsg     = RECORD( Msg )
  4058.                    END;
  4059.     MarkMsg      = RECORD( Msg )
  4060.                    END;
  4061.     MoveMsg      = RECORD( Msg )
  4062.      dX,dY         : INTEGER;
  4063.                    END;
  4064.     ...
  4065.  
  4066.   TYPE (* common graphics figure type *)
  4067.     Figure       = POINTER TO FigureRec;
  4068.   TYPE (* Handler procedure for graphics figure *)
  4069.     Handler      = PROCEDURE( Self : Figure; VAR Message : Msg );
  4070.   TYPE (* common graphics figure structure *)
  4071.     FigureRec    = RECORD
  4072.       Handle       : Handler;
  4073.       selected     : BOOLEAN;
  4074.     END;
  4075.     ...
  4076.  
  4077.   TYPE (* Rectangle = extended Figure *)
  4078.     Rectangle    = POINTER TO RectangleRec;
  4079.     RectangleRec = RECORD( FigureRec )
  4080.       x,y,w,h      : INTEGER;
  4081.     END;
  4082.     ...
  4083.  
  4084.   TYPE (* TextBox = extended Rectangle *)
  4085.     TextBox      = POINTER TO TextBoxRec;
  4086.     TextBoxRec   = RECORD( RectangleRec )
  4087.       text         : ARRAY [0..31] OF CHAR;
  4088.     END;
  4089.     ...
  4090.  
  4091.   (* Message handler for Rectangle *)
  4092.   PROCEDURE HandleRectangle( Self : Figure; Message : Msg );
  4093.   BEGIN
  4094.     WITH Self : Rectangle DO
  4095.       (* 'Self' treated as if it were of type 'Rectangle' *)
  4096.       IF Message IS DrawMsg THEN
  4097.         WITH Message : DrawMsg DO
  4098.           (* draw a rectangle *)
  4099.           ...
  4100.         END;
  4101.       ELSIF Message IS ClearMsg THEN
  4102.         WITH Message : ClearMsg DO
  4103.           (* clear a rectangle *)
  4104.           ...
  4105.         END;
  4106.       ELSIF Message IS MarkMsg THEN
  4107.         WITH Message : MarkMsg DO
  4108.           (* mark a rectangle *)
  4109.           Self^.selected := TRUE;
  4110.           ...
  4111.         END;
  4112.       ELSIF Message IS MoveMsg THEN
  4113.         WITH Message : MoveMsg DO
  4114.           (* move a rectangle *)
  4115.           Self^.x := Self^.x + Message.dX;
  4116.           Self^.y := Self^.y + Message.dY;
  4117.           ...
  4118.         END;
  4119.       ELSE
  4120.         (* Message not understood, typically no action *)
  4121.       END;
  4122.     END;
  4123.   END HandleRectangle;
  4124.   ...
  4125.  
  4126.   (* Message handler for TextBox *)
  4127.   PROCEDURE HandleTextBox( Self : Figure; Message : Msg );
  4128.   BEGIN
  4129.     WITH Self : TextBox DO
  4130.       ...
  4131.     END;
  4132.   END HandleRectangle;
  4133.   ...
  4134.  
  4135.   VAR
  4136.     MyFigure     : Figure;
  4137.     MyRectangle  : Rectangle;
  4138.     MyTextBox    : TextBox;
  4139.     ...
  4140.   BEGIN
  4141.     (* Create new Rectangle object *)
  4142.     NEW( MyRectangle );
  4143.     MyFigure = MyRectangle;
  4144.     ...
  4145.     (* dynamic binding of a Rectangle specific handler *)
  4146.     MyFigure^.Handle := HandleRectangle;
  4147.     ...
  4148.     IF MyFigure IS Figure THEN      (* TRUE *)
  4149.       (* perform Figure specific operations *)
  4150.       ...
  4151.     END;
  4152.     ...
  4153.     IF MyFigure IS Rectangle THEN    (* TRUE *)
  4154.       ...
  4155.       (* perform Rectangle specific operations,
  4156.          e.g. drawing and marking
  4157.       *)
  4158.       MyFigure^.Handle( MyFigure, DrawMsg );
  4159.       MyFigure^.Handle( MyFigure, MarkMsg );
  4160.       ...
  4161.     END;
  4162.     ...
  4163.     IF MyFigure IS TextBox THEN    (* FALSE *)
  4164.       ...
  4165.       (* this would perform TextBox specific operations,
  4166.          if Figure were of type TextBox
  4167.       *)
  4168.       ...
  4169.     END;
  4170.     ...
  4171.   END ...
  4172.  
  4173.  
  4174. ΓòÉΓòÉΓòÉ 14.3.3. Type guard selectors ΓòÉΓòÉΓòÉ
  4175.  
  4176. ΓûÉ Designator  = Qualident { Selector }
  4177. ΓûÉ Selector    = TypeGuard
  4178. ΓûÉ TypeGuard   = "(" Qualident ")"
  4179.  
  4180. Any object (in the sense of OOP) in this compiler is a variable pointing to an 
  4181. instance of a (possibly extended) record-type. Because of the assignment rules 
  4182. for extended records, an object operand must not always refer to the originally 
  4183. declared record-type to be pointed at, but also to any of its extensions. For 
  4184. this reason a new designator selector has been introduced called a type guard. 
  4185.  
  4186. The typeguard 'v(T0)' asserts that the variable 'v' is of dynamic type 'T0'; 
  4187. that is, it aborts program execution if it is not of type T0. The guard is 
  4188. applicable if 
  4189.  
  4190.      (1)     T0 is an extension of the declared type 'T' of 'v', and 
  4191.      (2)     'v' is a formal variable parameter of record-type or 'v' is a 
  4192.              pointer to a record 
  4193.  
  4194.  Specifying a type guard selector for an operand enables the programmer to 
  4195.  treat the operand as if it had been declared with the extended type from the 
  4196.  beginning, without giving up a run time check for proper record type usage. 
  4197.  
  4198.  Example: 
  4199.  
  4200.     TYPE
  4201.       (* common graphics base type *)
  4202.       Figure       = POINTER TO FigureRec;
  4203.       FigureRec    = RECORD
  4204.         selected     : BOOLEAN;
  4205.       END;
  4206.       ...
  4207.       (* extended Figure *)
  4208.       Rectangle    = POINTER TO RectangleRec;
  4209.       RectangleRec = RECORD( FigureRec )
  4210.         x,y,w,h      : INTEGER;
  4211.       END;
  4212.       ...
  4213.       (* extended Rectangle *)
  4214.       TextBox      = POINTER TO TextBoxRec;
  4215.       TextBoxRec   = RECORD( RectangleRec )
  4216.         text         : ARRAY [0..31] OF CHAR;
  4217.       END;
  4218.       ...
  4219.     VAR
  4220.       MyFigure     : Figure;
  4221.       ...
  4222.     BEGIN
  4223.       ...
  4224.       IF MyFigure IS TextBox THEN
  4225.         (* MyFigure has extended type
  4226.            POINTER TO TextBoxRec during run time
  4227.         *)
  4228.         MyFigure( TextBox )^.text := "default string";
  4229.       END;
  4230.       ...
  4231.     END
  4232.     ...
  4233.  
  4234.  
  4235. ΓòÉΓòÉΓòÉ 14.3.4. Regional type guards ΓòÉΓòÉΓòÉ
  4236.  
  4237. ΓûÉ WithStmt       = WITH Guard DO StmtSeq END
  4238. ΓûÉ Guard          = Qualident ":" Qualident
  4239.  
  4240. It is quite common that in a statement-sequence the same type-guard appears a 
  4241. number of times. Therefore a type guard with a wider textual scope is desirable 
  4242. to improve clarity and avoid unnecessary clerical work. The extended form of 
  4243. the with-statement provides such a regional type guard. Unlike the ordinary 
  4244. Modula-2 with-statement this extended form does not automatically make 
  4245. available the record fields for a separate local lexical scope. Record fields 
  4246. still have to be qualified with a record designator, even inside the scope of 
  4247. this extended with-statement. 
  4248.  
  4249. Example: 
  4250.  
  4251.   TYPE
  4252.     (* common graphics base type *)
  4253.     Figure       = POINTER TO FigureRec;
  4254.     FigureRec    = RECORD
  4255.       selected     : BOOLEAN;
  4256.     END;
  4257.     ...
  4258.     (* extended Figure *)
  4259.     Rectangle    = POINTER TO RectangleRec;
  4260.     RectangleRec = RECORD( FigureRec )
  4261.       x,y,w,h      : INTEGER;
  4262.     END;
  4263.     ...
  4264.     (* extended Rectangle *)
  4265.     TextBox      = POINTER TO TextBoxRec;
  4266.     TextBoxRec   = RECORD( RectangleRec )
  4267.       text         : ARRAY [0..31] OF CHAR;
  4268.     END;
  4269.     ...
  4270.   VAR
  4271.     MyFigure     : Figure;
  4272.     ...
  4273.   BEGIN
  4274.     ...
  4275.     IF MyFigure IS Rectangle THEN
  4276.       WITH MyFigure : Rectangle DO
  4277.         (* Designator 'MyFigure' treated as if it were of type
  4278.            POINTER TO RectangleRec inside this scope
  4279.         *)
  4280.         MyFigure^.x := 1;
  4281.         MyFigure^.y := 2;
  4282.         MyFigure^.w := 10;
  4283.         MyFigure^.h := 15;
  4284.       END;
  4285.     END;
  4286.     ...
  4287.   END
  4288.   ...
  4289.  
  4290.  
  4291. ΓòÉΓòÉΓòÉ 14.3.5. Type-bound procedures ΓòÉΓòÉΓòÉ
  4292.  
  4293. ΓûÉ ProcedureHeading = [ NEAR | FAR ] PROCEDURE
  4294. ΓûÉ                    [ Receiver ] Ident [ FormalParameters ]
  4295. ΓûÉ Receiver         = "(" [ [ NEAR | FAR ] VAR ] Ident : Ident ")"
  4296.  
  4297. This Modula-2 compiler supports the concept of type-bound procedures. It is 
  4298. available when the language-extensions are enabled. Type-bound procedures were 
  4299. first introduced with the new Oberon-2 language. Oberon-2 is the 
  4300. object-oriented successor of Modula-2. That's why this Modula-2 compiler has 
  4301. borrowed many of Oberon's object oriented features into a language extension 
  4302. for Modula-2. 
  4303.  
  4304. Globally declared procedures may be associated with a record-type declared in 
  4305. the same module. The procedures are said to be bound to the record type. Such a 
  4306. record-type can be regarded as a class, while its type bound procedures serve 
  4307. as its methods. The methods are responsible for accessing and updating 
  4308. (possibly multiple) instances of a class. 
  4309.  
  4310. The binding is expressed by the type of the receiver in the heading of a 
  4311. procedure-declaration. The receiver may be either expressed as a variable 
  4312. parameter of record-type T or a value parameter of type POINTER TO record-type 
  4313. T. The procedure is bound to the type T and is considered local to it. 
  4314.  
  4315. Binding a procedure P to a type T0 also implies the binding to any type T1 that 
  4316. is an extension of T0. However, a procedure P' (with same name as P) may be 
  4317. explicitly bound to T1, thus overriding the binding of P. P' is considered a 
  4318. redefinition of P for T1. The formal parameters of P and P' must match. Both P' 
  4319. and T1 must be declared in the same module. The same is true for the original P 
  4320. and T. If T1 is exported P' may be exported, too. Unlike Oberon-2, this 
  4321. Modula-2 compiler also accepts the declarations of private type bound 
  4322. procedures, even when overriding an inherited method, which is exported from 
  4323. another definition module. A private type bound procedure is only declared in 
  4324. the implementation or program module, while its type may be declared in the 
  4325. corresponding definition module. 
  4326.  
  4327. If a designator v points to a record and P is a type-bound procedure, the v^.P 
  4328. denotes that procedure P that is bound to the dynamic type of v. Note that this 
  4329. may be a different procedure than the one bound to the static type of v. 
  4330. Variable v is passed to P's receiver according to the parameter passing rules 
  4331. of the procedure-declaration. 
  4332.  
  4333. It is also possible to denote a parent procedure. If r is a receiver 
  4334. VAR-parameter declared with record-type T, r.P^ denotes the redefined procedure 
  4335. P bound to the base type of T. Also, if p is a receiver VAL-parameter declared 
  4336. with the formal pointer-type P pointing to record-type T, p^.P^ denotes the 
  4337. redefined procedure P bound to the base type of T. Denoting a parent procedure 
  4338. always results in a static procedure reference, without taking care about 
  4339. possible dynamic bindings. 
  4340.  
  4341. In a forward declaration of a type-bound procedure, the receiver parameter must 
  4342. be of the same type as in the actual procedure declaration. The same is true 
  4343. for any type-bound procedure heading of a definition module, when it is fully 
  4344. declared in the implementation module. The formal parameter lists of both 
  4345. declarations must match. 
  4346.  
  4347. Example: 
  4348.  
  4349.   TYPE
  4350.     TREE =  POINTER TO NODE;
  4351.     NODE =  RECORD
  4352.       key   : INTEGER;
  4353.       left  : TREE;
  4354.       right : TREE;
  4355.             END;
  4356.  
  4357.   TYPE
  4358.     CENTERTREE = POINTER TO CENTERNODE;
  4359.     CENTERNODE = RECORD( NODE )
  4360.       width      : INTEGER;
  4361.       subnode    : TREE;
  4362.                  END;
  4363.  
  4364.   (* declaring method Insert for TREE *)
  4365.   PROCEDURE( self : TREE ) Insert( node : TREE );
  4366.     VAR p, father : TREE;
  4367.   BEGIN
  4368.     p := self;
  4369.     REPEAT
  4370.       father := p;
  4371.       IF node^.key = p^.key THEN
  4372.         RETURN
  4373.       ELSIF node^.key < p^.key THEN
  4374.         p := p^.left
  4375.       ELSE
  4376.         p := p^.right;
  4377.       END;
  4378.     UNTIL p = NIL;
  4379.     IF node^.key < father^.key THEN
  4380.       father^.left := node;
  4381.     ELSE
  4382.       father^.right := node;
  4383.     END;
  4384.     node^.left := NIL;
  4385.     node^.right := NIL;
  4386.   END Insert;
  4387.  
  4388.   (* overriding method Insert for extended CENTERTREE *)
  4389.   PROCEDURE( self : CENTERTREE ) Insert( node : TREE );
  4390.   BEGIN
  4391.     WriteInt( node( CENTERTREE )^.width );
  4392.     (* now calling parent method bound to TREE *)
  4393.     self^.Insert^( node );
  4394.   END Insert:
  4395.  
  4396.  
  4397. ΓòÉΓòÉΓòÉ 14.4. System Object Model ΓòÉΓòÉΓòÉ
  4398.  
  4399. The OS/2 System Object Model (SOM) is an object-oriented interface for 
  4400. building, exposing, and manipulating software objects. The software objects are 
  4401. packaged into binary class libraries. Unlike object models found in formal 
  4402. object-oriented programming languages, such as C++ or Oberon-2, the design goal 
  4403. for SOM is language neutrality. This means, that the user of an object and the 
  4404. implementer of an object do not need to do their programming in the same 
  4405. language. This independence of implementation and client language extends even 
  4406. to the concept of subclassing (or, to put it into Modula-2 or Oberon-2 terms: 
  4407. extending records ). A user of a SOM class can create a subclass that may or 
  4408. may not be written in the same language as its superclass. 
  4409.  
  4410. A principal benefit of using SOM is that SOM accomodates changes in 
  4411. implementation details and even in certain parts of a class interface, without 
  4412. breaking the binary class interface to a class library and without requiring 
  4413. recompilation of client programs. As a matter of fact, if changes to a SOM 
  4414. class do not require source code changes in client programs, then those client 
  4415. programs will not need to be recompiled. This is not true of many 
  4416. object-oriented languages, and it is therefore one of the chief benefits of 
  4417. using SOM. For instance, SOM classes can undergo structural changes such as the 
  4418. following, yet retain full backward, binary compatibility: 
  4419.  
  4420.  -    Adding new methods 
  4421.  
  4422.  -    Changing the size of an object by adding or deleting instance variables 
  4423.  
  4424.  -    Inserting new classes above your class in the inheritance hierarchy 
  4425.  
  4426.  -    Relocating methods upward in the class hierarchy 
  4427.  
  4428.  In short, typical kinds of changes can be made to an implementation that 
  4429.  evolving software systems experience over the time. 
  4430.  
  4431.  SOM is supposed to be language neutral for three reasons: 
  4432.  
  4433.  1.   All SOM interactions consist of standard procedure calls. On systems that 
  4434.       have standard linkage convention for system calls, SOM interactions 
  4435.       conform to those conventions. Thus, most programming languages that can 
  4436.       make external procedure calls can use SOM. Under Modula-2 for OS/2 this 
  4437.       means calling external procedures, which are to be declared in definition 
  4438.       modules for dynamic link libraries. The OS/2 dynamic link libraries can 
  4439.       contain public SOM classes. 
  4440.  
  4441.  2.   The form of the SOM Application Programming Interface, or API, can vary 
  4442.       from language to language, as a benefit of the SOM bindings.  The way 
  4443.       that programmers invoke methods, create objects, and so on, can be 
  4444.       readily mapped into the semantic rules of a wide range of different 
  4445.       commercial object-oriented programming languages like C++, or even of 
  4446.       procedural languages like C or Modula-2. SOM bindings are the set of 
  4447.       macros and procedure calls that make implementing and using SOM classes 
  4448.       more convenient by tailoring the interface to a particular programming 
  4449.       language. 
  4450.  
  4451.  3.   SOM supports several mechanisms for method resolution that can be readily 
  4452.       mapped into the semantics of a wide range of object-oriented programming 
  4453.       languages. Thus, SOM class libraries can be shared across object-oriented 
  4454.       languages that have different object models. That's why a SOM object can 
  4455.       potentially be accessed with three different forms of method resolution. 
  4456.  
  4457.  The SOM method resolution mechanisms are as follows: 
  4458.  
  4459.  Offset resolution This is roughly equivalent to the C++ virtual function 
  4460.       concept, or to the concept of type-bound procedures in Oberon-2 or this 
  4461.       extended Modula-2. Offset resolution implies a static scheme for typing 
  4462.       objects, with polymorphic behaviour based strictly on class inheritance. 
  4463.       It offers the best performance characteristics for SOM method resolution. 
  4464.       Methods accessible through offset resolution can be regarded as static 
  4465.       methods as they are considered a fixed aspect of an object's interface. 
  4466.  
  4467.  Name lookup resolution This is similar to that employed by Objective-C and 
  4468.       Smalltalk. Name resolution supports untyped (sometimes called dynamically 
  4469.       typed) access to objects, with polymorphism based on the actual protocols 
  4470.       that objects honor. Name resolution offers the opportunity to write code 
  4471.       to manipulate objects with little or no awareness of the type or shape of 
  4472.       the object when the code is compiled. 
  4473.  
  4474.  Dispatch function resolution This is a unique feature of SOM that permits 
  4475.       method resolution based on arbitrary rules known only in the domain of 
  4476.       the receiving object. Languages that require special entry or exit 
  4477.       sequences or local objects that represent distributed object domains are 
  4478.       good candidates for using dispatch function resolution. This technique 
  4479.       offers the highest degree of encapsulation for the implementation of an 
  4480.       object, with some cost in performance. 
  4481.  
  4482.  The original SOM design philosophy requires the usage of a special SOM 
  4483.  compiler, whose input is a language neutral class description, and whose 
  4484.  output are language-specific SOM-bindings. This Modula-2 compiler takes a more 
  4485.  direct approach. No special language independent SOM compiler is needed. 
  4486.  Existing or new SOM class libraries are simply described in terms of Modula-2 
  4487.  definition modules. And any new SOM class can be specified for Modula-2 in an 
  4488.  implementation module. Of course, this approach does not generate language 
  4489.  bindings for other languages, but the final binary SOM class libraries are 
  4490.  fully compatible with the OS/2 System Object Model. And if the implementor 
  4491.  wishes to offer the language-neutral form of a SOM class description, he can 
  4492.  still obtain the OS/2 SOM-compiler with all its reference manuals, and create 
  4493.  the language independent 'interface description language' file (IDL-file) for 
  4494.  the SOM-compiler. The SOM-compiler, in turn, could then produce the other 
  4495.  language bindings. 
  4496.  
  4497.  There is only one predefined root-class for all SOM-classes. Hence all 
  4498.  SOM-classes are finally derived from that root class. This root class is 
  4499.  called 'SOMObject'. It offers basic methods, whose facilities are useful for 
  4500.  any SOM-class. SOM also uses the concept of metaclasses. A metaclass is a 
  4501.  class whose instances are all classes (also known as class objects or class 
  4502.  descriptors). The metaclass provides factory methods for a regular class, 
  4503.  while a regular class provides instance methods. Factory methods provide 
  4504.  methods for creating and constructing instances of regular classes. The root 
  4505.  class for all SOM metaclasses is called 'SOMClass', which has been itself 
  4506.  derived from 'SOMObject'. A new SOM-class is usually bundled with an 
  4507.  associated metaclass in a single module. 
  4508.  
  4509.  
  4510. ΓòÉΓòÉΓòÉ 14.4.1. SOM class definition ΓòÉΓòÉΓòÉ
  4511.  
  4512. Every SOM-class under OS/2 will be finally stored as a binary file in a dynamic 
  4513. link library. If a programmer wishes to access such a library he will need a 
  4514. language-specific application programming interface, called API. Such an API 
  4515. consists of a class description suitable for an inclusion in the compilation 
  4516. process. The C-language, for instance, uses special header files for that 
  4517. purpose. This Modula-2 compiler uses definition modules for the dynamic link 
  4518. libraries containing the SOM-classes. The absence of any corresponding 
  4519. implementation module will not necessarily cause an error message from this 
  4520. compiler. It rather tries to find a foreign precompiled dynamic link library or 
  4521. a linker import library with the same name. The definition module is then 
  4522. associated with that matching library. Or to express it in terms of OS/2 SOM: 
  4523. The definition module containing the object oriented class description is the 
  4524. required language binding for Modula-2. 
  4525.  
  4526. The public interface of a SOM-class can be expressed for this compiler in a 
  4527. Modula-2 definition module. The definition module describes the new class in 
  4528. terms of a language-extended object-oriented syntax, using extended records and 
  4529. type bound procedures. The following example demonstrates all the features of a 
  4530. new SOM class interface description: 
  4531.  
  4532. (*$DLL       to be implemented as a dynamic link library                *)
  4533. (*$XL+       Modula-2 language extensions: '_' allowed for symbol names *)
  4534. (*$CDECL+    C-style procedures                                         *)
  4535. (*$A         default alignment for record fields                        *)
  4536.  
  4537. DEFINITION MODULE Dog;
  4538.  
  4539. (************************************************************************
  4540.   Public interface for a SOM class 'Dog'.
  4541. *************************************************************************)
  4542.  
  4543. IMPORT SOM;  (* needed for basic SOM features *)
  4544.  
  4545.  
  4546. (************************************************************************
  4547.   Additional IMPORT-, TYPE-, and CONST-declarations supporting Dog
  4548. *************************************************************************)
  4549.  
  4550. IMPORT ANIMAL;   (* this module contains the parent class interface *)
  4551. IMPORT OS2DEF;
  4552. TYPE PSZ         = OS2DEF.PSZ;
  4553.  
  4554.  
  4555. (*************************************************************************
  4556.   SOM class API for Dog, including type-bound procedures
  4557. **************************************************************************)
  4558.  
  4559. (* These types are almost always needed for a SOM class description *)
  4560.  
  4561. TYPE PSOMClass              = SOM.PSOMClass;
  4562. TYPE INTEGER4               = SOM.INTEGER4;
  4563. TYPE somMToken              = SOM.somMToken;
  4564. TYPE somDToken              = SOM.somDToken;
  4565. TYPE somMethodProc          = SOM.somMethodProc;
  4566. TYPE PDog                   = POINTER TO Dog;
  4567. TYPE PM_Dog                 = POINTER TO M_Dog;
  4568.  
  4569. (* major and minor version numbers for new SOM class 'Dog' *)
  4570.  
  4571. CONST
  4572.   Dog_MajorVersion     = 0;
  4573.   Dog_MinorVersion     = 0;
  4574.  
  4575. (* Every SOM class has a public <class>ClassData structure,
  4576.    whose fields are tokens needed for method resolution.
  4577.    In this example there are 4 token fields for the 4 methods
  4578.    of the SOM class 'Dog'.
  4579. *)
  4580. TYPE
  4581.   DogClassDataStructure     = RECORD
  4582.     classObject               : PSOMClass;
  4583.     setBreed                  : somMToken;
  4584.     setColor                  : somMToken;
  4585.     getBreed                  : somMToken;
  4586.     getColor                  : somMToken;
  4587.                               END;
  4588.  
  4589. VAR
  4590.   DogClassData : DogClassDataStructure;
  4591.  
  4592.  
  4593. (* Class 'Dog' is expressed as an extension of record type 'Animal'
  4594.    inheriting all record fields and type bound procedures.
  4595.    The directive '$SOM+' tells the compiler to treat the new record
  4596.    type 'Dog' as a SOM class, and not as an extended Modula-2 record.
  4597. *)
  4598. TYPE
  4599.   (*$SOM+ *)
  4600.   Dog = RECORD( ANIMAL.Animal ) END;
  4601.   (*$SOM- *)
  4602.  
  4603.  
  4604. (* Every SOM class must have <class>NewClass procedure *)
  4605.  
  4606. PROCEDURE DogNewClass
  4607. (
  4608.   majorVersion  : INTEGER4;
  4609.   minorVersion  : INTEGER4
  4610. )               : PSOMClass;
  4611.  
  4612.  
  4613. (* A SOM class may have type bound procedures (also known as methods).
  4614.    For every of the following type bound procedures a corresponding
  4615.    token field must have been specified in a previous <class>ClassData
  4616.    record variable.
  4617. *)
  4618. PROCEDURE( Self : PDog ) setBreed
  4619. (
  4620.   myBreed       : OS2DEF.PSZ
  4621. );
  4622.  
  4623. PROCEDURE( Self : PDog ) setColor
  4624. (
  4625.   myColor       : OS2DEF.PSZ
  4626. );
  4627.  
  4628. PROCEDURE( Self : PDog ) getBreed() : OS2DEF.PSZ;
  4629.  
  4630. PROCEDURE( Self : PDog ) getColor() : OS2DEF.PSZ;
  4631.  
  4632.  
  4633. (*************************************************************************
  4634.   SOM class API for M_Dog, including type-bound procedures.
  4635.   This is the meta-class.
  4636.  
  4637.   The meta-class is optional and should be used for factory methods
  4638.   such as constructors or destructors. The meta class syntax is
  4639.   similar to the one of the regular class.
  4640. **************************************************************************)
  4641.  
  4642. CONST
  4643.   M_Dog_MajorVersion   = 0;
  4644.   M_Dog_MinorVersion   = 0;
  4645.  
  4646. TYPE
  4647.   M_DogClassDataStructure   = RECORD
  4648.     classObject               : PSOMClass;
  4649.     newDog                    : somMToken;
  4650.                               END;
  4651.  
  4652. VAR
  4653.   M_DogClassData : M_DogClassDataStructure;
  4654.  
  4655. TYPE
  4656.   (*$SOM+ *)
  4657.   M_Dog = RECORD( ANIMAL.M_Animal ) END;
  4658.   (*$SOM- *)
  4659.  
  4660.  
  4661. PROCEDURE M_DogNewClass
  4662. (
  4663.   majorVersion : INTEGER4;
  4664.   minorVersion : INTEGER4
  4665. )              : PSOMClass;
  4666.  
  4667.  
  4668. PROCEDURE( Self : PM_Dog ) newDog
  4669. (
  4670.   sound         : OS2DEF.PSZ;
  4671.   breed         : OS2DEF.PSZ;
  4672.   color         : OS2DEF.PSZ
  4673. )               : PDog;
  4674.  
  4675.  
  4676. END Dog.
  4677.  
  4678.  
  4679. ΓòÉΓòÉΓòÉ 14.4.2. SOM class usage ΓòÉΓòÉΓòÉ
  4680.  
  4681. An application programmer can fully use a predefined SOM-class. The definition 
  4682. of a SOM-class is made available for a Modula-2 program through an IMPORT 
  4683. statement. Commonly the program will create one or more instances of the 
  4684. SOM-class. In this compiler this can simply be achieved using standard 
  4685. procedure NEW, which makes an internal call to the SOM procedure 'somNew'. 
  4686. Almost all of this compiler's object-oriented features can be applied to 
  4687. instances of a SOM-class, too. This includes dynamic type-tests, designated 
  4688. type-guards, regional type-guards, and calling type-bound procedures. So 
  4689. working with instances of a SOM-class is as easy as working with ordinary 
  4690. extended records. However, the data fields of a SOM-class cannot be accessed 
  4691. directly. They are only indirectly accessable by the implementation's 
  4692. type-bound procedures (that is, the public methods of the SOM-class). That's 
  4693. why in a record definition for a SOM-class the field-components are never 
  4694. specified as record fields. 
  4695.  
  4696. This compiler will translate the following language constructs into appropriate 
  4697. internal SOM procedure calls, if applied to instances of SOM-classes: 
  4698.  
  4699.  Dynamic type test The dynamic type of a SOM object can be tested using the 
  4700.       IS-relation. The compiler produces code for calling the SOM function 
  4701.       procedure 'somIsA'. The method 'somIsA' is inherited from the basic 
  4702.       SOM-class 'SOMObject'. 
  4703.  
  4704.  Type guard Every designated type guard selector and every regional type guard 
  4705.       for SOM-objects is translated by this compiler into a call to the 
  4706.       SOM-procedure 'somIsA'. Its boolean return value is tested during runtime 
  4707.       and 'SYSTEM.ExitProgram' is called for abnormal program termination in 
  4708.       case of a type guard failure. 
  4709.  
  4710.  Calling type-bound procedures The calling of procedures bound to a SOM-class 
  4711.       type involves the internal invocation of runtime procedure 
  4712.       'SYSTEM.somResolve', which in turn calls SOM-procedure 'somResolve'. 
  4713.  
  4714.  Calling a parent method Calling a parent method means a transfer of control to 
  4715.       a procedure bound to the base type of the current extended record. The 
  4716.       procedure of that base record type has the same name. This compiler 
  4717.       translates such a call into a static method resolution, using 
  4718.       'SYSTEM.somFindSMethodOk', which in turn calls SOM-procedure 
  4719.       'somFindSMethodOk'. 
  4720.  
  4721.  Creating a SOM-object using NEW A procedure call NEW( p ) is translated by the 
  4722.       compiler into a code sequence using among others a call to SOM-procedure 
  4723.       'somNew'. 
  4724.  
  4725.  Deleting a SOM-object using DISPOSE A procedure call DISPOSE( p ) is 
  4726.       translated by the compiler into a code sequence using among others a call 
  4727.       to SOM-procedure 'somFree'. 
  4728.  
  4729.  
  4730. ΓòÉΓòÉΓòÉ 14.4.3. SOM class implementation ΓòÉΓòÉΓòÉ
  4731.  
  4732. This Modula-2 compiler supports the creation of new SOM-classes, which are to 
  4733. be derived from existing classes. The public interface of the new SOM-class is 
  4734. specified in a definition module, while the class itself with all the new or 
  4735. overridden methods is to be written in an implementation module. The 
  4736. implementation details are not visible to other client programs. The compiled 
  4737. machine code of the class methods are usually stored in a dynamic link library. 
  4738. So in case of implementing a new SOM-class in Modula-2, the definition module 
  4739. must contain a comment embedded $DLL+ compiler directive at its very beginning. 
  4740.  
  4741. The following sections will illustrate the implementation of a SOM-class. 
  4742. Implementing a new SOM-class is slightly more complicated than the 
  4743. implementation of a new extended Modula-2 (OBERON-style) class. The latter 
  4744. needs only the declaration of all the type-bound procedures that were specified 
  4745. as corresponding procedure headings in the definition module. SOM under OS/2 
  4746. uses a more complicated method resolution mechanism before gaining access to a 
  4747. public type-bound procedure for the SOM-class. The final dynamic link library 
  4748. will offer a public record variable with token fields for all the methods of 
  4749. the SOM-class. During runtime such a token can be transformed to the requested 
  4750. procedure pointer, which can be called as a type bound procedure. Finding a 
  4751. method this way is also known as offset resolution, because SOM treats the 
  4752. public method tokens from the dynamic link library as a kind of index to a 
  4753. SOM-internal virtual method table. The latter is maintained outside Modula's 
  4754. runtime libraries. Apart from this offset resolution SOM also offers name 
  4755. resolution and function dispatch resolution for gaining access to a method. 
  4756. This is needed because some programming languages are not able to support the 
  4757. basic offset resolution, while SOM is to be language-neutral. For above 
  4758. mentioned reasons the implementation of a SOM-class in Modula-2 (and for any 
  4759. other object-oriented language) is more complicated than implementing a pure 
  4760. language-defined class. 
  4761.  
  4762. The implementation module should contain the components listed below: 
  4763.  
  4764.      (1)    SOM-specific comment-embedded compiler directives. 
  4765.      (2)    Common IMPORT statements and individual declarations for constants, 
  4766.             types and variables. 
  4767.      (3)    Implementation header with common declarations for constants, types 
  4768.             and variables. 
  4769.      (4)    Apply and redispatch stubs for all the new methods. 
  4770.      (5)    FORWARD declarations of all private (or privately overridden) 
  4771.             methods. 
  4772.      (6)    Procedures for the creation of the new SOM-class. 
  4773.      (7)    Method procedures for the new SOM-class. 
  4774.      (8)    Module initialization. 
  4775.  
  4776.  If there is an explicit metaclass, it should be implemented in the same module 
  4777.  by specifying above mentioned components (3) to (7) again. A metaclass 
  4778.  provides class methods such as instance creation procedures or contructor 
  4779.  methods. If there is no explicit metaclass, then the one of the parent class 
  4780.  will be taken. 
  4781.  
  4782.  The following documentation sections provide a detailed description of all the 
  4783.  implementation components. The program examples contain placeholders, which 
  4784.  are embraced by '<' and '>', such as <class> or <identifier>. They are to be 
  4785.  replaced by actual name symbols when writing an implementation module. 
  4786.  Placeholder <class> always has to be replaced by the actual name of the new 
  4787.  SOM class. 
  4788.  
  4789.  
  4790. ΓòÉΓòÉΓòÉ 14.4.3.1. SOM class implementation (Compiler directives) ΓòÉΓòÉΓòÉ
  4791.  
  4792. An implementation module for a new SOM-class must be always introduced with 
  4793. some comment embedded compiler directives as follows: 
  4794.  
  4795. IMPLEMENTATION MODULE <module-identifier>;
  4796.  
  4797. (*$XL+       Modula-2 extenmsions: '_' in symbol names, OOP facilities  *)
  4798. (*$CDECL+    C-style procedures                                         *)
  4799. (*$A         default alignment for record fields                        *)
  4800.  
  4801. (*$LINK
  4802.   LIBRARY <module-identifier> INITINSTANCE
  4803.   PROTMODE
  4804.   DATA MULTIPLE NONSHARED LOADONCALL
  4805. *)
  4806.  
  4807. The $LINK switch tells the Modula-2 compiler, that the final SOM-class is to 
  4808. become a dynamic link library, which, contrary to default conventions, will 
  4809. create a new data segment for every client application during run time. 
  4810.  
  4811.  
  4812. ΓòÉΓòÉΓòÉ 14.4.3.2. SOM class implementation (IMPORTs and declarations) ΓòÉΓòÉΓòÉ
  4813.  
  4814. The implementation module begins with a series of common IMPORT statements 
  4815. which are always needed for a new SOM-class. It is followed by Modula's 
  4816. equivalent of the SOM compiler's passthru lines, containing further individual 
  4817. IMPORTs and declarations for constants, types, and variables. 
  4818.  
  4819. (*************************************************************************
  4820.    Common IMPORTs for a SOM-class implementation.
  4821. **************************************************************************)
  4822.  
  4823. IMPORT SOM;             (* basic SOM module, always needed *)
  4824. IMPORT <parent-module>; (* module with parent class, always needed *)
  4825. IMPORT Conversions;     (* data conversion support *)
  4826. FROM   SOMMISC IMPORT somDebug;        (* debugging aid *)
  4827. FROM   SOMMISC IMPORT somWriteString;  (* debugging aid *)
  4828. FROM   SOMMISC IMPORT somWriteLn;      (* debugging aid *)
  4829. FROM   SYSTEM  IMPORT currentFile;     (* debugging aid *)
  4830. FROM   SYSTEM  IMPORT currentLine;     (* debugging aid *)
  4831. FROM   SYSTEM  IMPORT ADR;
  4832.  
  4833. (*************************************************************************
  4834.    This is Modula's equivalent for the language-neutral SOM-emitter's
  4835.    'passthru lines before'.
  4836.  
  4837.    It consists of further individual IMPORTs for the implementation.
  4838. **************************************************************************)
  4839.  
  4840. IMPORT ..... ;
  4841.  
  4842. (*************************************************************************
  4843.    This is Modula's equivalent for the language-neutral SOM-emitter's
  4844.    'passthru lines after'.
  4845.  
  4846.    It consists of private types, constants, variables and/or procedures
  4847.    for the class implementation.
  4848. **************************************************************************)
  4849.  
  4850. CONST
  4851.   .....
  4852. TYPE
  4853.   .....
  4854. VAR
  4855.   .....
  4856.  
  4857.  
  4858. ΓòÉΓòÉΓòÉ 14.4.3.3. SOM class implementation (implementation header) ΓòÉΓòÉΓòÉ
  4859.  
  4860. The implementation header for a new SOM-class, which is usually created by the 
  4861. SOM-compiler from a language-neutral form of the class definition, must be 
  4862. specified manually for this Modula-2 compiler, because current SOM versions do 
  4863. not generate Modula-2 bindings. The basic layout for the implementation header 
  4864. will be always the same, regardless of the new class. It may vary only with the 
  4865. number of instance fields or the number of methods. 
  4866.  
  4867. (*************************************************************************
  4868.    Implementation header for the new SOM class.
  4869.    (constants, types and variables)
  4870. **************************************************************************)
  4871.  
  4872. CONST
  4873.   <class>_MaxNoMethods = <number>;  (* number of new methods *)
  4874.   <class>Debug         = FALSE;     (* enable/disable method debugging *)
  4875.  
  4876. (*
  4877.  * Declare the C specific class data structure;
  4878.  * Place it either here or in the definition module.
  4879.  *)
  4880. TYPE
  4881.   <class>CClassDataStructure  = RECORD
  4882.     parentMtab                  : SOM.somMethodTabs;
  4883.     instanceDataToken           : SOM.somDToken;
  4884.                                 END;
  4885. VAR
  4886.   <class>CClassData           : <class>CClassDataStructure;
  4887.  
  4888. (*
  4889.  * Temporary class data structure used only in class creation
  4890.  *)
  4891. VAR
  4892.   <class>tempClassData        : SOM.somClassDataStructure;
  4893.  
  4894. (*
  4895.  * Internal instance data fields
  4896.  *)
  4897. TYPE
  4898.   <class>Data          = RECORD
  4899.     <1st field>          : <1st type>;
  4900.        ..........................
  4901.     <nth field>          : <nth type>;
  4902.                          END;
  4903.   P<class>Data         = POINTER TO <class>Data;
  4904.  
  4905. (*
  4906.  *   <class>GetData function, gives access to the instance data, if any
  4907.  *)
  4908. PROCEDURE <class>GetData( Self : P<class> ) : P<class>Data;
  4909. BEGIN
  4910.   RETURN SOM.somDataResolve( Self, <class>CClassData.instanceDataToken );
  4911. END <class>GetData;
  4912.  
  4913. (*
  4914.  *  SOM specific identifiers for all
  4915.  *  the new and also the overridden methods
  4916.  *)
  4917. VAR
  4918.   somId_<method-1>         : SOM.somId;
  4919.     ................................
  4920.   somId_<method-n>         : SOM.somId;
  4921.  
  4922.  
  4923. ΓòÉΓòÉΓòÉ 14.4.3.4. SOM class implementation (apply/redispatch stubs) ΓòÉΓòÉΓòÉ
  4924.  
  4925. The implementation header also has to specify for every new method an apply 
  4926. stub and a redispatch stub in addition to the regular method. These are needed 
  4927. because of SOM's method resolution techniques, which might take place during 
  4928. runtime when a client application cannot master the normal offset method 
  4929. resolution. 
  4930.  
  4931. Every method may have an unknown number of formal parameters, which are usually 
  4932. passed as DWORDs on the stack. The apply stub has a formal parameter pointing 
  4933. to the open-ended method parameter list, usually expressed as ARRAY OF DWORD. 
  4934. Each DWORD corresponds to an actual numeric value parameter. Structures and 
  4935. arrays are usually passed by reference, so as to only pass a DWORD-sized 
  4936. address on the stack. A LONGREAL consists of 2 DWORDs. Passing long structures, 
  4937. whose size is not exactly a multiple of DWORDs, should be the rare exception. 
  4938. For such cases the method parameter list could also be declared as an ARRAY OF 
  4939. BYTE parameter in the apply stub. 
  4940.  
  4941. The apply stub has to extract and to pass on the parameters for the target 
  4942. method, before transfering control to the target method, which belongs to the 
  4943. 'Self'-object. 
  4944.  
  4945. The apply and redispatch stubs for a proper procedure method should be 
  4946. implemented as follows for Modula-2: 
  4947.  
  4948. (*
  4949.  *  apply stub for a new proper procedure method
  4950.  *)
  4951. PROCEDURE somAP_<method>
  4952. (
  4953.   somSelf   : P<class>;
  4954.   id        : SOM.somId;
  4955.   desc      : SOM.somId;
  4956.   VAR args  : ARRAY OF SOM.DWORD
  4957. );
  4958. VAR
  4959.   <param-0> : <basic-type>;
  4960.     ....................
  4961.   <param-n> : <basic-type>;
  4962. BEGIN
  4963.   <param-0> := args[0];
  4964.     .................
  4965.   <param-n> := args[n];
  4966.   somSelf^.<method>( <param-0>, ... <param-n> );
  4967. END somAP_<method>;
  4968.  
  4969. (*
  4970.  *  redispatch stub for a new proper procedure method
  4971.  *)
  4972. PROCEDURE somRD_<method>
  4973. (
  4974.   somSelf      : P<class>;
  4975.   <param-0>    : <basic-type>;
  4976.     .......................
  4977.   <param-n>    : <basic-type>
  4978. );
  4979. VAR
  4980.   retBuffer    : SOM.somToken;
  4981.   retValue     : SOM.somToken;
  4982.   args         : SOM.ADDRESS;
  4983.   dispatched   : BOOLEAN;
  4984. BEGIN
  4985.   retValue := ADR( retBuffer );
  4986.   args := ADR( somSelf ) + SIZE( somSelf );
  4987.   dispatched := somSelf^.somDispatch( retValue, somId_<method>, args^ );
  4988. END somRD_<method>;
  4989.  
  4990. If the method is a value returning function procedure, the apply and redispatch 
  4991. stubs look slightly different: 
  4992.  
  4993. (*
  4994.  *  apply stub for a new function procedure method
  4995.  *)
  4996. PROCEDURE somAP_<method>
  4997. (
  4998.   somSelf   : P<class>;
  4999.   id        : SOM.somId;
  5000.   desc      : SOM.somId;
  5001.   VAR args  : ARRAY OF SOM.DWORD
  5002. )           : <returning-type>;
  5003. VAR
  5004.   <param-0> : <basic-type>;
  5005.     ....................
  5006.   <param-n> : <basic-type>;
  5007. BEGIN
  5008.   <param-0> := args[0];
  5009.     .................
  5010.   <param-n> := args[n];
  5011.   RETURN somSelf^.<method>( <param-0>, ... <param-n> );
  5012. END somAP_<method>;
  5013.  
  5014. (*
  5015.  *  redispatch stub for a new function procedure method
  5016.  *)
  5017. PROCEDURE somRD_<method>
  5018. (
  5019.   somSelf      : P<class>;
  5020.   <param-0>    : <basic-type>;
  5021.     .......................
  5022.   <param-n>    : <basic-type>
  5023. )              : <returning-type>;
  5024. VAR
  5025.   retBuffer    : <returning-type>;
  5026.   retValue     : SOM.somToken;
  5027.   args         : SOM.ADDRESS;
  5028.   dispatched   : BOOLEAN;
  5029. BEGIN
  5030.   retValue := ADR( retBuffer );
  5031.   args := ADR( somSelf ) + SIZE( somSelf );
  5032.   dispatched := somSelf^.somDispatch( retValue, somId_<method>, args^ );
  5033.   RETURN retBuffer;
  5034. END somRD_<method>;
  5035.  
  5036.  
  5037. ΓòÉΓòÉΓòÉ 14.4.3.5. SOM class implementation (FORWARD declarations) ΓòÉΓòÉΓòÉ
  5038.  
  5039. During the class creation some static forward references are made to private 
  5040. (or privately overridden) methods, whose headings are not specified in the 
  5041. definition module for the new SOM-class. For every such method a 
  5042. forward-declaration has to be written. Such a declaration only contains the 
  5043. procedure heading, to be followed by the keyword FORWARD. 
  5044.  
  5045. (*
  5046.  *  sample forward declared private proper method
  5047.  *)
  5048. PROCEDURE( Self : P<class> ) <private-method-id>
  5049. ( <parameters> );
  5050. FORWARD;
  5051.  
  5052. (*
  5053.  *  sample forward declared private function method
  5054.  *)
  5055. PROCEDURE( Self : P<class> ) <private-method-id>
  5056. ( <parameters> ) : <returning-type>;
  5057. FORWARD;
  5058.  
  5059.  
  5060. ΓòÉΓòÉΓòÉ 14.4.3.6. SOM class implementation (class creation procedures) ΓòÉΓòÉΓòÉ
  5061.  
  5062. The OS/2 SOM system has to maintain runtime information for every class which 
  5063. might come into existence at some stage of the information processing. A 
  5064. SOM-class may stay alive even accross succeeding processes. But every SOM-class 
  5065. has to be created before usage. Instances of a SOM-class can only be created 
  5066. and accessed after class creation. The class creation is done by calling 
  5067. special SOM procedures from its dynamic link library. The basic layout for 
  5068. class creation procedures remains the same regardless of the class. SOM 
  5069. maintains created classes through internal class descriptors. Such an internal 
  5070. class descriptor is regarded by SOM as an instance of the metaclass and is 
  5071. called a class object, whose pointer is made available after class creation. 
  5072.  
  5073. (*************************************************************************
  5074.     SOM-class creation procedures.
  5075.     Only the <class>NewClass() procedure is publicly
  5076.     available for client programs.
  5077. **************************************************************************)
  5078.  
  5079. (*
  5080.  * class initialization
  5081.  *)
  5082. PROCEDURE <class>somInitializeClass;
  5083. VAR
  5084.   m  : <class>;     (* needed for static method references *)
  5085.   c  : SOM.PSOMClass;
  5086.   md : SOM.somId;
  5087. BEGIN
  5088.  
  5089.   c := <class>tempClassData.classObject;
  5090.   md := SOM.somIdFromString( "----" );
  5091.  
  5092.   (* Add the new methods, including apply and redispatch stubs,
  5093.      to the new SOM class
  5094.   *)
  5095.   <class>ClassData.<method-1> := c^.somAddStaticMethod
  5096.   ( somId_<method-1>, md, m.<method-1>, somRD_<method-1>, somAP_<method-1> );
  5097.     ......................................................................
  5098.   <class>ClassData.<method-n> := c^.somAddStaticMethod
  5099.   ( somId_<method-n>, md, m.<method-n>, somRD_<method-n>, somAP_<method-n> );
  5100.  
  5101.   (* Override inherited methods, if any *)
  5102.   c^.somOverrideSMethod( somId_<override-method-1>, m.<override-method-1> );
  5103.     .....................................................................
  5104.   c^.somOverrideSMethod( somId_<override-method-n>, m.<override-method-n> );
  5105.  
  5106. END <class>somInitializeClass;
  5107.  
  5108. (*
  5109.  *  class creation procedure
  5110.  *)
  5111. PROCEDURE <class>somCreateClass
  5112. (
  5113.   pClsObj    : SOM.PSOMClass;
  5114.   mClsObj    : SOM.PSOMClass
  5115. );
  5116. VAR
  5117.   classObject : SOM.PSOMClass;
  5118. BEGIN
  5119.   classObject := mClsObj^.somNew();
  5120.   <class>tempClassData.classObject := classObject;
  5121.   classObject^.somInitClass
  5122.   (
  5123.     "<class>",
  5124.     pClsObj,
  5125.     SIZE( <class>Data ),
  5126.     <class>_MaxNoMethods,
  5127.     <class>_MajorVersion,
  5128.     <class>_MinorVersion
  5129.   );
  5130.   <class>CClassData.instanceDataToken := classObject^.somGetInstanceToken();
  5131.   <class>somInitializeClass();
  5132.   <class>CClassData.parentMtab := classObject^.somGetPClsMtab();
  5133.   classObject^.somSetClassData( SYSTEM.ADR( <class>ClassData ) );
  5134.   classObject^.somClassReady();
  5135.   (* make newly created class object visible *)
  5136.   <class>ClassData.classObject := classObject;
  5137. END <class>somCreateClass;
  5138.  
  5139. (*
  5140.  *   public NewClass-procedure
  5141.  *)
  5142. PROCEDURE <class>NewClass
  5143. (
  5144.   majorVersion  : SOM.INTEGER4;
  5145.   minorVersion  : SOM.INTEGER4
  5146. )               : SOM.PSOMClass;
  5147. VAR
  5148.   pClsObj       : SOM.PSOMClass;
  5149.   mClsObj       : SOM.PSOMClass;
  5150.   line          : LONGCARD;
  5151.   b             : BOOLEAN;
  5152. BEGIN
  5153.   (* Check the version numbers *)
  5154.   IF ((majorVersion <> 0) AND (majorVersion <> <class>_MajorVersion)) OR
  5155.      ((minorVersion <> 0) AND (minorVersion > <class>_MinorVersion)) THEN
  5156.     somWriteString( "<class>NewClass: Error, bad version numbers." );
  5157.     somWriteLn();
  5158.     b := Conversions.StrToLongCard( currentLine(), line );
  5159.     SOM.SOMError( SOM.SOMERROR_BadVersion, currentFile(), line );
  5160.   END;
  5161.  
  5162.   (* Don't do anything if class object is already created. *)
  5163.   IF <class>ClassData.classObject <> NIL THEN
  5164.     RETURN <class>ClassData.classObject;
  5165.   END;
  5166.  
  5167.   (* Make sure the environment is initialized. *)
  5168.   IF SOM.SOMClassMgrObject = NIL THEN
  5169.     SOM.SOMClassMgrObject := SOM.somEnvironmentNew();
  5170.     IF SOM.SOMClassMgrObject = NIL THEN
  5171.       b := Conversions.StrToLongCard( currentLine(), line );
  5172.       SOM.SOMError( SOM.SOMERROR_CouldNotStartup, currentFile(), line );
  5173.     END;
  5174.     (* SOMClassMgrObject initialized... *)
  5175.   END;
  5176.  
  5177.   (* Get the parent class object. *)
  5178.   pClsObj := <parent-module>.<parent-class>NewClass( 0, 0 ); (* static *)
  5179.   pClsObj := SOM.SOMClassMgrObject^.somFindClass
  5180.   ( SOM.somIdFromString( "<parent-class>" ), 0, 0 );
  5181.   IF pClsObj = NIL THEN
  5182.     b := Conversions.StrToLongCard( currentLine(), line );
  5183.     SOM.SOMError( SOM.SOMERROR_NoParentClass, currentFile(), line );
  5184.   END;
  5185.  
  5186.   (* Get the metaclass object. *)
  5187.   (* If explicit metaclass, get it from there *)
  5188.     mClsObj := <metaclass>NewClass( 0, 0 );       (* static*)
  5189.     mClsObj := SOM.SOMClassMgrObject^.somFindClass
  5190.     ( SOM.somIdFromString( "<metaclass>" ), 0, 0 );
  5191.   (* else use parent's metaclass:
  5192.     mClsObj := pClsObj^.mtab^.classObject;
  5193.   *)
  5194.   IF mClsObj = NIL THEN
  5195.     b := Conversions.StrToLongCard( currentLine(), line );
  5196.     SOM.SOMError( SOM.SOMERROR_NoMetaClass, currentFile(), line );
  5197.   END;
  5198.  
  5199.   SOM.somConstructClass
  5200.   ( <class>somCreateClass, pClsObj, mClsObj, SYSTEM.ADR( <class>tempClassData ) );
  5201.  
  5202.   RETURN <class>ClassData.classObject;
  5203. END <class>NewClass;
  5204.  
  5205.  
  5206. ΓòÉΓòÉΓòÉ 14.4.3.7. SOM class implementation (method procedures) ΓòÉΓòÉΓòÉ
  5207.  
  5208. The final part of a new SOM-class implementation consists of the declarations 
  5209. for all new and overridden methods. Every method must be fully declared as a 
  5210. type-bound procedure. The following examples show the basic layouts for 
  5211. implementing proper methods and function methods: 
  5212.  
  5213. (*
  5214.  *  sample proper method procedure, type-bound to new SOM-class
  5215.  *)
  5216. PROCEDURE( Self : P<class> ) <method-id> ( <parameters> );
  5217. VAR
  5218.   somThis   : P<class>Data;
  5219. BEGIN
  5220.   somThis := <class>GetData( Self );
  5221.   IF <class>Debug THEN
  5222.     somDebug( "<class>", "<method-id>", currentFile(), currentLine() );
  5223.   END;
  5224.   .........
  5225. END <method-id>;
  5226.  
  5227. (*
  5228.  *  sample function method procedure, type-bound to new SOM-class
  5229.  *)
  5230. PROCEDURE( Self : P<class> ) <method-id> ( <parameters> ) : <return-type>;
  5231. VAR
  5232.   somThis   : P<class>Data;
  5233. BEGIN
  5234.   somThis := <class>GetData( Self );
  5235.   IF <class>Debug THEN
  5236.     somDebug( "<class>", "<method-id>", currentFile(), currentLine() );
  5237.   END;
  5238.   .........
  5239.   RETURN <expression>;
  5240. END <method-id>;
  5241.  
  5242.  
  5243. ΓòÉΓòÉΓòÉ 14.4.3.8. SOM class implementation (module initialization) ΓòÉΓòÉΓòÉ
  5244.  
  5245. A SOM-class is usually implemented in a module, which can be compiled and 
  5246. linked into a dynamic library. Such a library must have a per-instance 
  5247. initialization routine, which looks like this: 
  5248.  
  5249. (*
  5250.  * sample module initialization for a new SOM-class
  5251.  *)
  5252. BEGIN (* of class module *)
  5253.   (* intialize SOM's environment, if not yet active *)
  5254.   IF SOM.SOMClassMgrObject = NIL THEN
  5255.     SOM.SOMClassMgrObject := SOM.somEnvironmentNew();
  5256.   END;
  5257.  
  5258.   (* initialize some record fields for class-supporting structures *)
  5259.   <class>CClassData.parentMtab := NIL;
  5260.   <class>ClassData.classObject := NIL;
  5261.  
  5262.   (* find the identifier tokens for all the new or overridden methods *)
  5263.   somId_<method_0>      := SOM.somIdFromString( "<method_0>"     );
  5264.     ............................................................
  5265.   somId_<method_n>      := SOM.somIdFromString( "<method_n>"     );
  5266.  
  5267.   (* if an explicit metaclass has been declared in the same module then
  5268.    * initialize some record fields for metaclass-supporting structures
  5269.    *)
  5270.   M_<class>CClassData.parentMtab := NIL;
  5271.   M_<class>ClassData.classObject := NIL;
  5272.  
  5273.   (* if an explicit metaclass has been declared in the same module then
  5274.    * find the identifier tokens for all the new or overridden methods
  5275.    * belonging to the metaclass.
  5276.    *)
  5277.   somId_<method_0>      := SOM.somIdFromString( "<method_0>"     );
  5278.     ............................................................
  5279.   somId_<method_n>      := SOM.somIdFromString( "<method_n>"     );
  5280.  
  5281. END <module-identifier>.
  5282.  
  5283.  
  5284. ΓòÉΓòÉΓòÉ 14.5. Bitwise operators ΓòÉΓòÉΓòÉ
  5285.  
  5286. This Modula-2 compiler provides extended arithmetic bitwise operators. They are 
  5287. applicable for cardinal or integer operands and work bit by bit. Bitwise 
  5288. operators are available only if the command line switch or the compiler 
  5289. directive for the language extensions is enabled. Their purpose is to simplify 
  5290. access to bitfields from the operating system interfaces such as the OS/2 2.x 
  5291. or 3.0 APIs. And they also simplify the porting of low-level code written in 
  5292. other programming languages. Most of the bitwise operators could also be 
  5293. implemented using set-operators for variables with set-types. Using set-typed 
  5294. variables with the corresponding set-operators acting upon them is the prefered 
  5295. way to implement bitwise operations when source code portability is an issue. 
  5296. Using the new bitwise operators should be restricted to low-level modules only. 
  5297. The following table gives a summary of the new arithmetic bitwise operators: 
  5298.  
  5299.      OR        bitwise or 
  5300.      XOR       bitwise exclusive or 
  5301.      AND       bitwise and 
  5302.      &         bitwise and, same as AND 
  5303.      SHL       bitwise shift left 
  5304.      SHR       bitwise shift right 
  5305.      NOT       unary bitwise negation 
  5306.      ~         unary bitwise negation 
  5307.  
  5308.  
  5309. ΓòÉΓòÉΓòÉ 14.6. New logical operators ΓòÉΓòÉΓòÉ
  5310.  
  5311. Modula-2 provides a set of logical operators for boolean expressions. There is, 
  5312. however, no direct implementation for the logical exclusive 'OR'. An exclusive 
  5313. 'OR' yields a TRUE only if either a first or a second boolean expression is 
  5314. TRUE, but not both of them at the same time. Example: 
  5315.  
  5316.   IF (Contition1 AND NOT Condition2) OR
  5317.      (NOT Condition1 AND Condition2) THEN
  5318.     (* execute if either, but not both conditions are met *)
  5319.   END
  5320.  
  5321. If the command line switch or the compiler directive for the language 
  5322. extensions is enabled then the above mentioned example could be easier 
  5323. expressed with the new 'XOR' operator: 
  5324.  
  5325.   IF Condition1 XOR Condition2 THEN
  5326.     (* execute if either, but not both conditions are met *)
  5327.   END
  5328.  
  5329.  
  5330. ΓòÉΓòÉΓòÉ 14.7. Typed constants ΓòÉΓòÉΓòÉ
  5331.  
  5332. ΓûÉ ConstDecl      = ConstDef | ConstVarDecl "=" TypedConst
  5333. ΓûÉ ConstVarDecl   = Ident ":" FormalType
  5334. ΓûÉ TypedConst     = ConstExpr | PointerConst | ArrayConst | RecordConst
  5335. ΓûÉ PointerConst   = POINTER TO Qualident |
  5336. ΓûÉ                  PROCEDURE Qualident |
  5337. ΓûÉ                  "^" Qualident
  5338. ΓûÉ RecordConst    = "(" FieldConstList ")"
  5339. ΓûÉ FieldConstList = FieldConst { ";" FieldConst }
  5340. ΓûÉ FieldConst     = [ FieldId ":" TypedConst ]
  5341. ΓûÉ FieldId        = Ident
  5342. ΓûÉ ArrayConst     = "[" TypedConstList "]"
  5343. ΓûÉ TypedConstList = TypedConst { "," TypedConst }
  5344.  
  5345. The original Modula-2 language offers no facilities for initialized variables 
  5346. with the exception of modules, which can contain statement-sequences for 
  5347. assigning the starting values to variables. Though modules are executed 
  5348. automatically at the beginning of the program execution, they are somehow 
  5349. wasteful because of the assignments. 
  5350.  
  5351. This compiler provides an additional way for initializing variables. If the 
  5352. command line switch or the compiler directive for the language extensions is 
  5353. enabled then variables can be declared with initial values with no need for any 
  5354. explicit assignments. Initialized variables are called typed constants. Typed 
  5355. constants are not restricted to basic types. They can also be used for 
  5356. structured types such as arrays or records. Typed constants are like variable 
  5357. declarations with additional specifications of their initial values. The linker 
  5358. program places all typed constants in a special intialized segment along with 
  5359. any internally produced strings and other constants. When the data segments are 
  5360. loaded into memory by the operating system for the later program execution, all 
  5361. the intial values are loaded with them. Typed constants are particularly useful 
  5362. for long initialized tables. Constant variable declarations with typed 
  5363. constants can only be specified within a 'CONST' section. The constant value 
  5364. must be assignment compatible with the type of the corresponding constant 
  5365. variable declaration. 
  5366.  
  5367. A typed constant for an array-type consists of a list of typed constants for 
  5368. the array elements. The list elements are separated by commas, and the list 
  5369. itself is enclosed by squared brackets. If the number of typed constants in 
  5370. that list is less than the number of declared array elements then the remaining 
  5371. array elements are automatically initialized with binary zeroes. If the 
  5372. declared variable has a character array type then a string can also be 
  5373. specified as the corresponding typed constant. 
  5374.  
  5375. A typed constant for a record-type consists of a list of field constants. The 
  5376. field constants are separated by semicolons. Every field constant is introduced 
  5377. by the field name, to be followed by a colon and the typed constant. The field 
  5378. constant list itself is enclosed by the bracket pair '(' and ')'. The order of 
  5379. the field constants must be the same as the one in the corresponding 
  5380. record-type. Any field without a corresponding field constant is initialized 
  5381. with binary zeroes (unless overlapped by case variants with specified field 
  5382. constants). 
  5383.  
  5384. A pointer constant can be specified for data pointers or for procedure 
  5385. variables. They are finally fixed by the linker, because they are to represent 
  5386. the addresses of variables or procedures. A data pointer is introduced by a 
  5387. 'POINTER TO' sequence, while a procedure constant has to be preceded by the 
  5388. 'PROCEDURE' keyword. An alternative short notation is also available for 
  5389. pointer constants, using only a '^' sign, in which case the declared variable 
  5390. type is consulted by the compiler for the correct choice between data or 
  5391. procedure pointer. The pointer constant is always concluded by a (possibly 
  5392. qualified) name of the variable or procedure, whose address is to be taken as 
  5393. the constant value. 
  5394.  
  5395. Examples: 
  5396.  
  5397.   TYPE
  5398.     ArrayType  = ARRAY [0..10] OF CHAR;
  5399.     RecType    = RECORD
  5400.       Str        : ArrayType;
  5401.       Len        : INTEGER;
  5402.       Handler    : PROC;
  5403.       Next       : POINTER TO RecType;
  5404.                  END;
  5405.     ...
  5406.  
  5407.   PROCEDURE MyProc();
  5408.   BEGIN
  5409.     ...
  5410.   END MyProc;
  5411.   ...
  5412.  
  5413.   VAR
  5414.    YourRecVar  : RecType;
  5415.    ...
  5416.  
  5417.   CONST
  5418.     MyRecVar     : RecType =
  5419.     (
  5420.       Str        : "MyString";
  5421.       Len        : 8;
  5422.       Handler    : ^MyProc;
  5423.       Next       : ^YourRecVar;
  5424.     );
  5425.   ...
  5426.  
  5427. The constant variable declaration may also specify a one-dimensional open array 
  5428. as its type. In this case the number of reserved array elements is determined 
  5429. by the number of typed constant elements. Example: 
  5430.  
  5431.   CONST
  5432.     (* zero terminated initialized text string variables *)
  5433.     Msg1  : ARRAY OF CHAR = "This is message 1";
  5434.     Msg2  : ARRAY OF CHAR = "This is another text string";
  5435.     (* initialized integer array variable with 6 elements *)
  5436.     Token : ARRAY OF INTEGER = [ 1, 2, 3, 4, 5, 6 ];
  5437.  
  5438.  
  5439. ΓòÉΓòÉΓòÉ 14.8. Multidimensional open array parameters ΓòÉΓòÉΓòÉ
  5440.  
  5441. ΓûÉ FormalType       = { ARRAY OF } Qualident
  5442.  
  5443. Standard Modula-2 offers open arrays for formal-parameters for 
  5444. procedure-declarations or for procedure-types. In this compiler, if the command 
  5445. line switch or the compiler directive for the language extensions is enabled, 
  5446. multidimensional arrays are permitted. The corresponding actual parameter must 
  5447. be an assignment-compatible array with the same number of dimensions. The high 
  5448. bounds for all dimensions are automatically pushed on the stack before any of 
  5449. the actual parameters. Each dimension size can be determined by HIGH(x) or a 
  5450. SYSTEM.LEN(x) expressions. Example: 
  5451.  
  5452.   PROCEDURE MyProc( x : ARRAY OF ARRAY OF ARRAY OF INTEGER );
  5453.   VAR
  5454.     High0 : LONGCARD;
  5455.     High1 : LONGCARD;
  5456.     High2 : LONGCARD;
  5457.     Len0  : LONGCARD;
  5458.     Len1  : LONGCARD;
  5459.     Len2  : LONGCARD;
  5460.   BEGIN
  5461.     High0 := HIGH( x );            (* HIGH outer dimension *)
  5462.     High1 := HIGH( x[0] );         (* HIGH middle dimension *)
  5463.     High2 := HIGH( x[0][0] );      (* HIGH inner dimension *)
  5464.     Len0 := SYSTEM.LEN( x, 0 );    (* outer dimension length *)
  5465.     Len1 := SYSTEM.LEN( x, 1 );    (* middle dimension length *)
  5466.     Len2 := SYSTEM.LEN( x, 2 );    (* inner dimension length *)
  5467.     ...
  5468.   END MyProc;
  5469.   ...
  5470.  
  5471.  
  5472. ΓòÉΓòÉΓòÉ 14.9. Segmentation ΓòÉΓòÉΓòÉ
  5473.  
  5474. As mentioned in the documentation section about the memory-models the Intel 
  5475. 80x86 CPU family provides only a segmented memory access. In the 16-bit 
  5476. memory-models this means that a pointer range cannot exceed 64 KB. 16-bit 
  5477. segment selectors are needed for accessing various segments. System maintained 
  5478. segment descriptors contain information about segment sizes and their linear 
  5479. starting addresses. Because of this, two different pointer kinds are available. 
  5480. A near pointer contains the offset relative to memory default segment, whose 
  5481. selector is stored in the default data segment register DS for data pointers, 
  5482. or in the default code segment register CS for code pointers. A far pointer 
  5483. contains in  addition to an offset portion a 16-bit segment selector. 
  5484.  
  5485. Depending on the memory-model chosen for the compilation, the default pointer 
  5486. is a far or near one. The default pointer can be overwritten by this compiler, 
  5487. however, if the command line switch or the compiler directive for the language 
  5488. extensions is enabled, using the new 'FAR' or 'NEAR' keywords. These keywords 
  5489. are available in the following contexts: 
  5490.  
  5491. ΓûÉ ProcedureHeading = [ NEAR | FAR ] PROCEDURE
  5492. ΓûÉ                    [ Receiver ] Ident [ FormalParameters ]
  5493. ΓûÉ Receiver         = "(" [ [ NEAR | FAR ] VAR ] Ident : Ident ")"
  5494. ΓûÉ FormalParameters = "(" FPSectionList ")" [ ":" Qualident ]
  5495. ΓûÉ FPSectionList    = [ FPSection { ";" FPSection } ]
  5496. ΓûÉ FPSection        = [ [ NEAR | FAR ] VAR ] IdentList ":" FormalType
  5497.  
  5498. ΓûÉ PointerType    = [ NEAR | FAR ] POINTER TO Type
  5499.  
  5500. ΓûÉ ProcedureType  = [ NEAR | FAR ] PROCEDURE [ FormalTypeList ]
  5501. ΓûÉ FormalTypeList = "(" FTSectionList ")" [ ":" Qualident ]
  5502. ΓûÉ FTSectionList  = [ FTSection { "," FTSection } ]
  5503. ΓûÉ FTSection      = [ [ NEAR | FAR ] VAR ] FormalType
  5504.  
  5505. A procedure or procedure-type can be declared as FAR or NEAR. A far procedure 
  5506. is used for far code entry and exit, with segmented call and return 
  5507. instructions produced by the code generator. A near procedure is used for code 
  5508. which is to reside in the same code segment, using only the code offset 
  5509. portions for the call and return instructions as produced by the code 
  5510. generator. 
  5511.  
  5512. A pointer type can be optionally declared as FAR or NEAR, overwriting the 
  5513. default attribute, which is NEAR for near data memory-models Tiny, Small, 
  5514. Compact, or Flat32, and which is FAR otherwise. A far pointer consists of 
  5515.  16-bit segment : 16-or-32-bit offset 
  5516. while a near pointer only contains the 
  5517.  16-or-32-bit offset 
  5518. portion. 
  5519.  
  5520. A formal VAR parameter may be preceded by a FAR or NEAR keyword, thus 
  5521. overwriting the default attribute, which is FAR for far data memory-models 
  5522. Compact or Large, and which is NEAR otherwise. A FAR VAR parameter points to a 
  5523. variable passed by reference, which resides in a different data segment. A NEAR 
  5524. VAR parameter, also passed by reference, is supposed to reside in the same 
  5525. default data segment. 
  5526.  
  5527.  
  5528. ΓòÉΓòÉΓòÉ 14.10. Extended imports ΓòÉΓòÉΓòÉ
  5529.  
  5530. ΓûÉ Import          = FROM Ident IMPORT IdentList ";" |
  5531. ΓûÉ                   IMPORT [ FROM ] Ident { "," [ FROM ] Ident }
  5532.  
  5533. Standard-Modula offers no way to import all the identifiers from another 
  5534. definition module in an unqualified manner without explicitly specifying all 
  5535. the needed identifiers, e.g. 
  5536.  
  5537.   FROM WINFRAME IMPORT
  5538.     WinCreateStdWindow,
  5539.     WinFlashWindow,
  5540.     :
  5541.   BEGIN
  5542.     (* unqualified reference to imported WinCreateStdWindow *)
  5543.     WinCreateStdWindow( ... );
  5544.     (* qualified reference available, too *)
  5545.     WINFRAME.WinCreateStdWindow( ... );
  5546.   END ...;
  5547.  
  5548. However, when dealing with a large number of items to be imported in an 
  5549. unqualified manner, it will mean writing long import lists. This will often be 
  5550. the case when writing programs for the OS/2 Presentation Manager or the 
  5551. Workplace Shell. That's why this compiler offers a special extension to the 
  5552. import statement, namely the unqualified import of a whole definition module. 
  5553. This extension causes the parser to look for identifiers not only within the 
  5554. current module being compiled, but also in the imported definition module. The 
  5555. visibility scope extends into the unqualified imported definition modules. Even 
  5556. if two unqualified imported definition modules contain the same identifier, the 
  5557. first one is shadowed by the second one. To pick up above mentioned example, 
  5558. this time using the new import construct: 
  5559.  
  5560.   IMPORT FROM WINFRAME;
  5561.     :
  5562.   BEGIN
  5563.     (* unqualified reference to imported WinCreateStdWindow *)
  5564.     WinCreateStdWindow( ... );
  5565.     (* qualified reference still available, too *)
  5566.     WINFRAME.WinCreateStdWindow( ... );
  5567.   END ...;
  5568.  
  5569.  
  5570. ΓòÉΓòÉΓòÉ 15. Language grammar ΓòÉΓòÉΓòÉ
  5571.  
  5572. The Modula-2 and INLINE assembler languages are formed according to a set of 
  5573. grammar rules. An extended Backus-Naur formalism is used to describe the 
  5574. syntax. 
  5575.  
  5576. This compiler's Modula-2-grammar does not only support Wirth's standard syntax 
  5577. but also some powerful language-extensions. 
  5578.  
  5579. The INLINE-assembler-grammar has been designed with ease of use in mind. Some 
  5580. of the reserved words such as 32-bit register names are only available for 
  5581. 32-bit programs. 
  5582.  
  5583.  
  5584. ΓòÉΓòÉΓòÉ 15.1. Modula-2 grammar ΓòÉΓòÉΓòÉ
  5585.  
  5586. CompilationUnit = DefModule | [ IMPLEMENTATION ] ProgramModule
  5587. ProgramModule   = MODULE Ident Priority ";" { Import } Block Ident "."
  5588. Priority        = [ "[" ConstExpr "]" ]
  5589. Import          = FROM Ident IMPORT IdentList ";" |
  5590.                   IMPORT [ FROM ] Ident { "," [ FROM ] Ident }
  5591. IdentList       = Ident { "," Ident }
  5592.  
  5593. DefModule = DEFINITION MODULE Ident ";" { Import } { Def } END Ident "."
  5594. Def       = CONST { ConstDef ";" } | TYPE { TypeDef ";" } |
  5595.             VAR { VarDecl ";" } | ProcedureHeading ";"
  5596.  
  5597. ConstDef  = Ident "=" ConstExpr
  5598. TypeDef   = TypeDecl | Ident
  5599.  
  5600. ProcedureHeading = [ NEAR | FAR ] PROCEDURE
  5601.                    [ Receiver ] Ident [ FormalParameters ]
  5602. Receiver         = "(" [ [ NEAR | FAR ] VAR ] Ident : Ident ")"
  5603. FormalParameters = "(" FPSectionList ")" [ ":" Qualident ]
  5604. FPSectionList    = [ FPSection { ";" FPSection } ]
  5605. FPSection        = [ [ NEAR | FAR ] VAR ] IdentList ":" FormalType
  5606. FormalType       = { ARRAY OF } Qualident
  5607.  
  5608. Qualident        = { Qualifier "." } Ident
  5609. Qualifier        = Ident
  5610.  
  5611. Block         = { Decl } [ BEGIN StmtSeq ] END
  5612. Decl          = CONST { ConstDecl ";" } | TYPE { TypeDecl ";" } |
  5613.                 VAR { VarDecl ";" } | ProcedureDecl | ModuleDecl
  5614.  
  5615. ConstDecl       = ConstDef | ConstVarDecl "=" TypedConst
  5616. ConstVarDecl    = Ident ":" FormalType
  5617. TypeDecl        = Ident = Type
  5618. VarDecl         = VarIdent { "," VarIdent } ":" Type
  5619. VarIdent        = Ident [ FarPointerConst ]
  5620. FarPointerConst = "[" ConstExpr ":" ConstExpr "]"
  5621. ProcedureDecl   = ProcedureHeading ";" Block Ident |
  5622.                   ProcedureHeading ";" FORWARD
  5623. ModuleDecl      = MODULE Ident [ Priority ] { Import } [ Export ]
  5624.                   Block Ident
  5625. Export          = EXPORT [ QUALIFIED ] IdentList ";"
  5626.  
  5627. TypedConst     = ConstExpr | PointerConst | ArrayConst | RecordConst
  5628. PointerConst   = POINTER TO Qualident |
  5629.                  PROCEDURE Qualident |
  5630.                  "^" Qualident
  5631. RecordConst    = "(" FieldConstList ")"
  5632. FieldConstList = FieldConst { ";" FieldConst }
  5633. FieldConst     = [ FieldId ":" TypedConst ]
  5634. FieldId        = Ident
  5635. ArrayConst     = "[" TypedConstList "]"
  5636. TypedConstList = TypedConst { "," TypedConst }
  5637.  
  5638. Type           = SimpleType | ArrayType | RecordType | SetType |
  5639.                  PointerType | ProcedureType
  5640. SimpleType     = Qualident | Enumeration | SubrangeType
  5641. Enumeration    = "(" IdentList ")"
  5642. SubrangeType   = [ BaseType ] "[" ConstExpr ".." ConstExpr "]"
  5643. BaseType       = Qualident
  5644. ArrayType      = ARRAY IndexType { "," IndexType } OF Type
  5645. IndexType      = SimpleType
  5646. RecordType     = RECORD [ "(" RecordBase ")" ] FieldListSeq END
  5647. RecordBase     = Qualident
  5648. FieldListSeq   = FieldList { ";" FieldList }
  5649. FieldList      = [ IdentList ":" Type | Variants ]
  5650. Variants       = CASE [ Ident ":" ] Qualident
  5651.                  OF VariantList ElseVariant END
  5652. VariantList    = Variant { "|" Variant }
  5653. ElseVariant    = ELSE FieldListSeq
  5654. Variant        = CaseLabelList ":" FieldListSeq
  5655. SetType        = SET OF SimpleType
  5656. PointerType    = [ NEAR | FAR ] POINTER TO Type
  5657. ProcedureType  = [ NEAR | FAR ] PROCEDURE [ FormalTypeList ]
  5658. FormalTypeList = "(" FTSectionList ")" [ ":" Qualident ]
  5659. FTSectionList  = [ FTSection { "," FTSection } ]
  5660. FTSection      = [ [ NEAR | FAR ] VAR ] FormalType
  5661.  
  5662. StmtSeq        = Stmt { ";" Stmt }
  5663. Stmt           = [ Assignment | ProcedureCall | IfStmt | CaseStmt |
  5664.                  WhileStmt | RepeatStmt | LoopStmt | ForStmt |
  5665.                  WithStmt | EXIT | ReturnStmt ]
  5666. Assignment     = Designator ":=" Expr
  5667. ProcedureCall  = Designator [ ActualParams ]
  5668. ActualParams   = "(" [ Expr { "," Expr } ] ")"
  5669. IfStmt         = IF BoolExpr THEN StmtSeq
  5670.                  { ELSIF BoolExpr THEN StmtSeq }
  5671.                  [ ELSE StmtSeq ] END
  5672. BoolExpr       = Expr
  5673. CaseStmt       = CASE Expr OF Case { "|" Case } [ ELSE StmtSeq ] END
  5674. Case           = CaseLabelList ":" StmtSeq
  5675. CaseLabelList  = CaseLabels { "," CaseLabels }
  5676. CaseLabels     = ConstExpr [ ".." ConstExpr ]
  5677. WhileStmt      = WHILE BoolExpr DO StmtSeq END
  5678. RepeatStmt     = REPEAT StmtSeq UNTIL BoolExpr
  5679. LoopStmt       = LOOP StmtSeq END
  5680. ForStmt        = FOR ControlVar ":=" Expr TO Expr [ BY ConstExpr ]
  5681.                  DO StmtSeq END
  5682. ControlVar     = Ident
  5683. WithStmt       = WITH RecDesignator DO StmtSeq END
  5684. RecDesignator  = Designator | Guard
  5685. Guard          = Qualident ":" Qualident
  5686. ReturnStmt     = RETURN [ Expr ]
  5687.  
  5688. ConstExpr       = Expr
  5689. Expr            = SimpleExpr [ Relation SimpleExpr ]
  5690. SimpleExpr      = [ "+" | "-" ] Term { AddOperator Term }
  5691. Term            = Factor { MulOperator Factor }
  5692. Factor          = CharConst | Number | String | Set |
  5693.                   Designator [ ActualParams ] | "(" Expr ")" |
  5694.                   Not Factor
  5695. Set             = Qualident "{" [ ElemList ] "}"
  5696. ElemList        = Elem { "," Elem }
  5697. Elem            = Expr { ".." Elem }
  5698. Relation        = "=" | "<>" | "#" | "<" | "<=" | ">" | ">=" | IN | IS
  5699. AddOperator     = "+" | "-" | OR | XOR
  5700. MulOperator     = "*" | "/" | DIV | MOD | AND | "&" | SHL | SHR
  5701. Not             = NOT | "~"
  5702.  
  5703. Designator  = Qualident { Selector }
  5704. Selector    = "." Ident | "[" IndexList "]" | "^" | TypeGuard
  5705. IndexList   = Expr { "," Expr }
  5706. TypeGuard   = "(" Qualident ")"
  5707.  
  5708. CharConst   = "'" Character "'" | Digit { HexDigit } "X" |
  5709.               OctalDigit { OctalDigit } "C"
  5710. String      = "'" { Character } "'" | """ { Character } """
  5711. Number      = Integer | Real
  5712. Integer     = Digit { Digit } | OctalDigit { OctalDigit } "B" |
  5713.               Digit { HexDigit } "H"
  5714. Real        = Digit { Digit } "." { Digit } [ ScaleFactor ]
  5715. ScaleFactor = "E" [ "+" | "-" ] Digit { Digit }
  5716. HexDigit    = Digit | "A" | "B" | "C" | "D" | "E" | "F"
  5717. Digit       = "0"  | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
  5718. OctalDigit  = "0"  | "1" | "2" | "3" | "4" | "5" | "6" | "7"
  5719. Ident       = FirstLetter { "_" | Letter | Digit }
  5720. FirstLetter = "_" | Letter
  5721.  
  5722.  
  5723. ΓòÉΓòÉΓòÉ 15.2. INLINE assembler grammar ΓòÉΓòÉΓòÉ
  5724.  
  5725. Any identifier from the token stream is assigned to either token 'Ident', 
  5726. 'ConstId', 'Qualifier' or 'Keyword'. From a very strict lexical point of view 
  5727. they look much the same. However, the lexical analyzer of this INLINE assembler 
  5728. has been expanded so that it can find proper token assignments through detailed 
  5729. semantic checks. The lexical rules for numbers and character constants are 
  5730. equal to those of Modula-2. 
  5731.  
  5732. Inline     = "(" InlineList ")"
  5733. InlineList = CodeList { InstrList }
  5734. InstrList  = CSEG eol CodeList | DSEG eol DataList |
  5735.              SSEG eol DataList | ISEG eol InitList
  5736. CodeList   = Code { eol Code }
  5737. Code       = CodeInstr | CondCode
  5738. DataList   = Data { eol Data }
  5739. Data       = DataInstr | CondData
  5740. InitList   = Init
  5741. Init       = InitInstr | CondInit
  5742.  
  5743. CondCode   = IF CondExpr [ THEN | eol ] CodeList [ ELSE CodeList ] ENDIF
  5744. CondData   = IF CondExpr [ THEN | eol ] DataList [ ELSE DataList ] ENDIF
  5745. CondInit   = IF CondExpr [ THEN | eol ] InitList [ ELSE InitList ] ENDIF
  5746. CondExpr   = ImmedExpr
  5747.  
  5748. CodeInstr  = [ Label ] [ CodeStmt ]
  5749. CodeStmt   = InstrId [ Operand [ Operand [ Operand ] ] ] |
  5750.              CodeDirective CodeConstLst
  5751. Label      = AnyId ":"
  5752. InstrId    = [ RepPrefix ] AnyId | AND | OR | XOR | NOT | DIV | SHL | SHR
  5753. RepPrefix  = REP | REPE | REPZ | REPNE | REPNZ
  5754. AnyId      = Ident | ConstId
  5755.  
  5756. Operand    = UserReg | SegReg | MemDesignator | ImmedExpr | SegExpr |
  5757.              OfsExpr | FloatStack | ControlReg | DebugReg | TestReg
  5758.  
  5759. UserReg    = AX | BX | CX | DX | SI | DI | BP | SP |
  5760.              AL | AH | BL | BH | CL | CH | DL | DH | Reg32
  5761. Reg32      = EAX | EBX | ECX | EDX | ESI | EDI | EBP | ESP
  5762. SegReg     = CS | DS | ES | SS | FS | GS
  5763. FloatStack = ST [ "(" ImmedExpr ")" ]
  5764. ControlReg = CR0 | CR2 | CR3
  5765. DebugReg   = DR0 | DR1 | DR2 | DR3 | DR6 | DR7
  5766. TestReg    = TR6 | TR7
  5767.  
  5768. MemDesignator = [ Attr ] Mem
  5769. Mem           = MemId [ DispExpr | "[" IndexExpr "]" ]  |  "[" MemExpr "]"
  5770. DispExpr      = Unary DispTerm { Unary DispTerm }
  5771. DispTerm      = ImmedTerm
  5772. IndexExpr     = IndexStart { Unary DispTerm | RegTerm }
  5773. IndexStart    = [ "-" ] DispTerm | RegTerm
  5774. RegTerm       = BX | BP | SI | DI | reg32 [ "*" ScaleFactor ]
  5775. ScaleFactor   = ImmedFactor
  5776.  
  5777. MemExpr       = MemStart { Unary DispTerm | "+" RegTerm }
  5778. MemStart      = [ "-" ] DispTerm | RegTerm | MemId
  5779. MemId         = Designator
  5780.  
  5781. Attr          = FAR | NEAR | SHORT |
  5782.                 SegReg ":" | SizeAttr | SizeAttr SegReg ":"
  5783. SizeAttr      = SizeId [ PTR ] | LOW | HIGH
  5784. SizeId        = BYTE | WORD | DWORD | FWORD | QWORD | TBYTE
  5785.  
  5786. SegExpr       = SEG MemId
  5787. OfsExpr       = OFFSET MemId
  5788.  
  5789. Designator     = Qualident { "." MemberId }
  5790. Qualident      = { QualifierList "." } UserId
  5791. QualifiedConst = { QualifierList "." } ConstId
  5792. QualifierList  = Qualifier { "." Qualifier }
  5793. UserId         = Ident | Keyword
  5794. MemberId       = AnyId | Keyword
  5795.  
  5796. CodeDirective   = DataDirective
  5797. CodeConstLst    = CodeConst { "," CodeConst }
  5798. CodeConst       = ImmedExpr | SegExpr | OfsExpr | FarPointerConst |
  5799.                   Designator | DupSize DUP "(" CodeConstLst ")"
  5800. FarPointerConst = "[" ImmedExpr ":" ImmedExpr "]"
  5801.  
  5802. DataInstr     = [ DataName DataDirective DataAttrLst ]
  5803. DataName      = [ AnyId ]
  5804. DataDirective = DB | DW | DD | DF | DQ | DT
  5805. DataAttrLst   = DataAttr { ",' DataAttr }
  5806. DataAttr      = "?" | DupSize DUP "(" DataAttrLst ")"
  5807. DupSize       = ImmedExpr
  5808.  
  5809. InitInstr     = [ InitName InitDecl ]
  5810. InitName      = [ AnyId ]
  5811. InitDecl      = CodeDirective CodeConstLst
  5812.  
  5813. ImmedExpr        = SimpleImmedExpr { Relation SimpleImmedExpr }
  5814. SimpleImmedExpr  = [ Unary ] ImmedTerm { AddOperator ImmedTerm }
  5815. ImmedTerm        = ImmedFactor { MulOperator ImmedFactor }
  5816. ImmedFactor      = QualifiedConst | Number | String | CharConst |
  5817.                    "(" ImmedExpr ")" | NOT ImmedFactor |
  5818.                    TYPE VarId | SIZE VarId | LENGTH VarId
  5819. VarId            = Designator
  5820.  
  5821. AddOperator   = "+" | "-" | OR | XOR
  5822. MulOperator   = "*" | "/" | DIV | MOD | "&" | AND | SHL | SHR
  5823. Unary         = "+" | "-"
  5824.  
  5825.