Pārlūkot izejas kodu

step11: separate compilation units DEFINITION/IMPLEMENTATION/IMPORT; 157/157 tests green

Eric Streit 3 nedēļas atpakaļ
vecāks
revīzija
480e5149c4
100 mainītis faili ar 4171 papildinājumiem un 2455 dzēšanām
  1. BIN
      DBadExp.MC4
  2. BIN
      DBadImp.MC4
  3. BIN
      DBasic.MC4
  4. BIN
      DCase.MC4
  5. BIN
      DFrom.MC4
  6. BIN
      DFunc.MC4
  7. BIN
      DInit.MC4
  8. BIN
      DMulti.MC4
  9. BIN
      DType.MC4
  10. BIN
      M2c
  11. 177 24
      M2c.atg
  12. 34 30
      M2c.err
  13. 2311 2158
      M2c.lst
  14. 83 58
      M2c.mod
  15. BIN
      M2c.o
  16. 334 131
      M2cP.mod
  17. BIN
      M2cP.o
  18. 28 26
      M2cS.mod
  19. BIN
      M2cS.o
  20. 4 0
      MGen.def
  21. 9 0
      MGen.mod
  22. BIN
      MGen.o
  23. 13 0
      S4L.LST
  24. 7 0
      S4L.def
  25. 18 0
      S4Limpl.LST
  26. 12 0
      S4Limpl.mod
  27. 32 0
      Showcase4.LST
  28. BIN
      Showcase4.MC4
  29. 26 0
      Showcase4.mod
  30. 48 0
      SymTab.def
  31. 267 0
      SymTab.mod
  32. BIN
      SymTab.o
  33. 49 28
      compiler.frm
  34. 73 0
      docs/summary_step11.md
  35. 68 0
      run_tests.sh
  36. 9 0
      tests/a_lib.LST
  37. 3 0
      tests/a_lib.def
  38. 10 0
      tests/a_libimpl.LST
  39. 4 0
      tests/a_libimpl.mod
  40. 10 0
      tests/b_lib.LST
  41. 4 0
      tests/b_lib.def
  42. 15 0
      tests/b_libimpl.LST
  43. 9 0
      tests/b_libimpl.mod
  44. 13 0
      tests/d_bad_dup.LST
  45. 6 0
      tests/d_bad_dup.mod
  46. 13 0
      tests/d_bad_exp.LST
  47. 6 0
      tests/d_bad_exp.mod
  48. 13 0
      tests/d_bad_imp.LST
  49. 6 0
      tests/d_bad_imp.mod
  50. 11 0
      tests/d_bad_nobody.LST
  51. 4 0
      tests/d_bad_nobody.mod
  52. 9 0
      tests/d_bad_nodef.LST
  53. 2 0
      tests/d_bad_nodef.mod
  54. 12 0
      tests/d_bad_sig.LST
  55. 5 0
      tests/d_bad_sig.mod
  56. 15 0
      tests/d_basic.LST
  57. 9 0
      tests/d_basic.mod
  58. 19 0
      tests/d_case.LST
  59. 13 0
      tests/d_case.mod
  60. 10 0
      tests/d_duplib.LST
  61. 4 0
      tests/d_duplib.def
  62. 14 0
      tests/d_from.LST
  63. 8 0
      tests/d_from.mod
  64. 12 0
      tests/d_func.LST
  65. 6 0
      tests/d_func.mod
  66. 12 0
      tests/d_init.LST
  67. 6 0
      tests/d_init.mod
  68. 12 0
      tests/d_lib.LST
  69. 6 0
      tests/d_lib.def
  70. 10 0
      tests/d_lib2.LST
  71. 4 0
      tests/d_lib2.def
  72. 19 0
      tests/d_lib2impl.LST
  73. 13 0
      tests/d_lib2impl.mod
  74. 18 0
      tests/d_libimpl.LST
  75. 12 0
      tests/d_libimpl.mod
  76. 13 0
      tests/d_multi.LST
  77. 7 0
      tests/d_multi.mod
  78. 10 0
      tests/d_nolib.LST
  79. 4 0
      tests/d_nolib.def
  80. 9 0
      tests/d_sglib.LST
  81. 3 0
      tests/d_sglib.def
  82. 15 0
      tests/d_type.LST
  83. 9 0
      tests/d_type.mod
  84. 10 0
      tests/e_lib.LST
  85. 4 0
      tests/e_lib.def
  86. 10 0
      tests/e_libimpl.LST
  87. 4 0
      tests/e_libimpl.mod
  88. 9 0
      tests/f_lib.LST
  89. 3 0
      tests/f_lib.def
  90. 12 0
      tests/f_libimpl.LST
  91. 6 0
      tests/f_libimpl.mod
  92. 9 0
      tests/l1.LST
  93. 3 0
      tests/l1.def
  94. 10 0
      tests/l1impl.LST
  95. 4 0
      tests/l1impl.mod
  96. 9 0
      tests/l2.LST
  97. 3 0
      tests/l2.def
  98. 11 0
      tests/l2impl.LST
  99. 5 0
      tests/l2impl.mod
  100. 10 0
      tests/t_lib.LST

BIN
DBadExp.MC4


BIN
DBadImp.MC4


BIN
DBasic.MC4


BIN
DCase.MC4


BIN
DFrom.MC4


BIN
DFunc.MC4


BIN
DInit.MC4


BIN
DMulti.MC4


BIN
DType.MC4


BIN
M2c


+ 177 - 24
M2c.atg

@@ -1,7 +1,33 @@
 COMPILER M2c
 (* Modula-2 program modules with procedures and composites, MC64 backend
-   (see MGen for details).
+   (see MGen for details). Step 11 adds separate compilation units
+   (DEFINITION / IMPLEMENTATION / IMPORT) into a single image:
 
+   - session: M2c f1.def f2.mod ... prog.mod — definition files,
+     then implementations, then exactly one program module;
+     one <Program>.MC4 image, one .LST per input, fail-fast on the
+     first bad file. SymTab.Init + MGen.OpenModule run once in the
+     driver; the program unit sets the image name (SetModName).
+   - DEFINITION MODULE L: CONST/TYPE/VAR + procedure headings only;
+     everything declared is exported (export tables + in-memory
+     interface side table); VAR/CONST allocate their global slots
+     once ("L.x"); proc headings reserve numbers via the forward
+     machinery. No nested MODULEs, no BEGIN.
+   - IMPLEMENTATION MODULE L: needs its definition (201); re-enters
+     the interface implicitly (redeclared exports are 200
+     duplicates); headings match via ReuseProc/VerifyProc (231);
+     private decls allowed; every heading needs its body (231);
+     optional BEGIN init runs at startup in file order.
+   - IMPORT L validates a known definition (201); FROM L IMPORT x
+     materializes real alias symbols (types/consts/vars share the
+     definition's descriptors and globals via GlobAlias; procs
+     share the number, so call checking is unchanged). Ghost
+     names are 201, bad kinds 221, duplicates 200.
+   - caps (phase): 8 definitions, 32 interface names each,
+     64 FROM-aliases; still one image, depCount 0 (no multi-.MC4,
+     no circular imports, no opaque types).
+
+   Older notes (steps 1-10):
    - program module only, no DEFINITION / IMPLEMENTATION split
    - local MODULEs (single-file, no nesting): EXPORT of VARs, CONSTs,
      TYPEs and procedures (value/VAR params, functions, open array
@@ -88,34 +114,63 @@ TOKENS
           | '"' { noQuote2 } '"' .
 
 PRODUCTIONS
-  M2c                                   (. VAR m1, m2: SymTab.Name; .)
-    = "MODULE"
-      GetIdent<m1>                      (. SymTab.Init; MGen.OpenModule(m1);
-                                           IF ~SymTab.Enter(m1, SymTab.KindModule)
-                                           THEN SemError(200) END .)
-      ";"
-      { Import } Block<FALSE> GetIdent<m2>
-                                        (. IF ~SymTab.Equal(m1, m2)
-                                           THEN SemError(202) END .)
-      "."                               (. IF SymTab.AnyForward() THEN
-                                           SemError(231)
-                                         END;
-                                         MGen.EndModule;
-                                         SymTab.PrintTable; .) .
+  (* NOTE: Coco/R numbers tokens by first occurrence; M2c.mod's Msg
+     table is regenerated from M2c.err on every build (via
+     compiler.frm). After grammar edits, rebuild and check that
+     the messages still name the right tokens. *)
+  M2c
+    = Unit .
+  Unit
+    = DefUnit | ImplUnit | ProgUnit .
   Import                                (. VAR n: SymTab.Name; .)
     = "FROM"
-      GetIdent<n>                       (. IF ~SymTab.Enter(n, SymTab.KindImport)
-                                           THEN SemError(200) END .)
+      GetIdent<n>                       (. IF ~SymTab.IsDefMod(n) THEN
+                                             SemError(201)
+                                           END; .)
       "IMPORT"
-      ImportList ";"
+      ImpItem<n> { "," ImpItem<n> } ";"
     | "IMPORT"
-      ImportList ";" .
-  ImportList                            (. VAR n: SymTab.Name; .)
-    = GetIdent<n>                       (. IF ~SymTab.Enter(n, SymTab.KindImport)
-                                           THEN SemError(200) END .)
+      GetIdent<n>                       (. IF ~SymTab.IsDefMod(n) THEN
+                                             SemError(201)
+                                           END; .)
       { ","
-        GetIdent<n>                     (. IF ~SymTab.Enter(n, SymTab.KindImport)
-                                           THEN SemError(200) END .) } .
+        GetIdent<n>                     (. IF ~SymTab.IsDefMod(n) THEN
+                                             SemError(201)
+                                           END; .) } ";" .
+  ImpItem<mod: SymTab.Name>             (. VAR a: SymTab.Name;
+                                             k: INTEGER; .)
+    = GetIdent<a>                       (. IF ~SymTab.ImpBind(mod, a) THEN
+                                             SemError(201)
+                                           ELSE
+                                             k := SymTab.ExpKind(mod, a);
+                                             IF k = SymTab.KindType THEN
+                                               IF ~SymTab.Enter(a, k) THEN
+                                                 SemError(200);
+                                                 SymTab.ImpUnbind(a)
+                                               ELSE
+                                                 SymTab.SetSymType(a,
+                                                   SymTab.ExpType(mod, a))
+                                               END
+                                             ELSIF (k = SymTab.KindConst)
+                                                OR (k = SymTab.KindVar) THEN
+                                               IF ~SymTab.Enter(a, k) THEN
+                                                 SemError(200);
+                                                 SymTab.ImpUnbind(a)
+                                               ELSE
+                                                 SymTab.SetSymType(a,
+                                                   SymTab.ExpType(mod, a))
+                                               END
+                                             ELSIF k = SymTab.KindProc THEN
+                                               IF ~SymTab.EnterImpProc(a,
+                                                 SymTab.ExpProc(mod, a)) THEN
+                                                 SemError(200);
+                                                 SymTab.ImpUnbind(a)
+                                               END
+                                             ELSE
+                                               SemError(221);
+                                               SymTab.ImpUnbind(a)
+                                             END
+                                           END; .) .
   Block <isProc: BOOLEAN>               (. VAR began: BOOLEAN; .)
     =                                   (. began := FALSE; .)
       { Declaration }
@@ -2159,4 +2214,102 @@ PRODUCTIONS
   GetIdent <VAR n: SymTab.Name>
     = ident                           (. LexName(n); .) .
 
+  (* ---- step-11 separate compilation units (at end: the DEFINITION
+     and IMPLEMENTATION keywords take fresh token numbers, leaving
+     every existing token — and M2c.mod's messages — untouched) ---- *)
+  DefUnit                               (. VAR m1, m2: SymTab.Name; .)
+    = "DEFINITION" "MODULE"
+      GetIdent<m1>                      (. IF ~SymTab.EnterModule(m1) THEN
+                                             SemError(200)
+                                           END; .)
+      ";"
+      { Import }
+      { DefDecl }
+      "END"
+      GetIdent<m2>                      (. IF ~SymTab.Equal(m1, m2) THEN
+                                             SemError(202)
+                                           END;
+                                           IF ~SymTab.ExitDefinition() THEN
+                                             SemError(230)
+                                           END; .)
+      "." .
+  DefDecl
+    = "CONST" { ConstDecl ";" }
+    | "TYPE" { TypeDecl ";" }
+    | "VAR" { VarDecl ";" }
+    | DefProcHead .
+  DefProcHead                           (. VAR n: SymTab.Name;
+                                             rt: SymTab.TypeIndex;
+                                             hasR, ok: BOOLEAN; .)
+    = "PROCEDURE"                       (. hasR := FALSE; .)
+      GetIdent<n>                       (. IF ~SymTab.EnterProc(n) THEN
+                                             SemError(200)
+                                           END;
+                                           SymTab.OpenProcScope; .)
+      [ "(" FormalParams ")" ]
+      [ ":" QualIdent<rt>               (. hasR := TRUE; .) ]
+                                        (. IF hasR THEN
+                                             ok := SymTab.SetProcRet(rt)
+                                           ELSE
+                                             ok := SymTab.SetProcRet(
+                                                     SymTab.InvalidType)
+                                           END;
+                                           IF ~ok THEN SemError(231) END;
+                                           IF ~SymTab.VerifyProc() THEN
+                                             SemError(231)
+                                           END;
+                                           SymTab.SetForward;
+                                           SymTab.CloseProc; .)
+      ";" .
+  ImplUnit                              (. VAR m1, m2: SymTab.Name;
+                                             hasInit: BOOLEAN;
+                                             initL, initN: INTEGER; .)
+    = "IMPLEMENTATION" "MODULE"
+      GetIdent<m1>                      (. hasInit := FALSE;
+                                           IF ~SymTab.OpenImplementation(m1)
+                                           THEN
+                                             SemError(201)
+                                           END; .)
+      ";"
+      { Import }
+      { Declaration }
+      [ "BEGIN"                         (. hasInit := TRUE;
+                                           initL := MGen.NewLabel();
+                                           MGen.Jmp(initL);
+                                           initN := MGen.ModInitBegin();
+                                           IF initN < 0 THEN
+                                             SemError(230)
+                                           END; .)
+        StatSeq ]
+      "END"
+      GetIdent<m2>                      (. IF ~SymTab.Equal(m1, m2) THEN
+                                             SemError(202)
+                                           END;
+                                           IF hasInit THEN
+                                             MGen.ModInitEnd(initN);
+                                             MGen.DefLabel(initL)
+                                           END;
+                                           IF ~SymTab.CloseImplementation()
+                                           THEN
+                                             SemError(231)
+                                           END; .) .
+  ProgUnit                              (. VAR m1, m2: SymTab.Name; .)
+    = "MODULE"
+      GetIdent<m1>                      (. IF ~SymTab.NoteProgram() THEN
+                                             SemError(230)
+                                           END;
+                                           MGen.SetModName(m1);
+                                           IF ~SymTab.Enter(m1,
+                                             SymTab.KindModule)
+                                           THEN SemError(200) END; .)
+      ";"
+      { Import } Block<FALSE> GetIdent<m2>
+                                        (. IF ~SymTab.Equal(m1, m2)
+                                           THEN SemError(202) END; .)
+      "."                               (. IF SymTab.AnyForward() THEN
+                                             SemError(231)
+                                           END;
+                                           MGen.EndModule;
+                                           SymTab.PrintTable; .) .
+
 END M2c.

+ 34 - 30
M2c.err

@@ -3,24 +3,24 @@
 |  2: Msg("integer expected")
 |  3: Msg("real expected")
 |  4: Msg("string expected")
-|  5: Msg("'MODULE' expected")
-|  6: Msg("';' expected")
-|  7: Msg("'.' expected")
-|  8: Msg("'FROM' expected")
-|  9: Msg("'IMPORT' expected")
-| 10: Msg("',' expected")
-| 11: Msg("'BEGIN' expected")
-| 12: Msg("'END' expected")
-| 13: Msg("'CONST' expected")
-| 14: Msg("'TYPE' expected")
-| 15: Msg("'VAR' expected")
-| 16: Msg("'=' expected")
-| 17: Msg("':' expected")
-| 18: Msg("'PROCEDURE' expected")
-| 19: Msg("'(' expected")
-| 20: Msg("')' expected")
-| 21: Msg("'FORWARD' expected")
-| 22: Msg("'EXPORT' expected")
+|  5: Msg("'FROM' expected")
+|  6: Msg("'IMPORT' expected")
+|  7: Msg("',' expected")
+|  8: Msg("';' expected")
+|  9: Msg("'BEGIN' expected")
+| 10: Msg("'END' expected")
+| 11: Msg("'CONST' expected")
+| 12: Msg("'TYPE' expected")
+| 13: Msg("'VAR' expected")
+| 14: Msg("'=' expected")
+| 15: Msg("':' expected")
+| 16: Msg("'PROCEDURE' expected")
+| 17: Msg("'(' expected")
+| 18: Msg("')' expected")
+| 19: Msg("'FORWARD' expected")
+| 20: Msg("'MODULE' expected")
+| 21: Msg("'EXPORT' expected")
+| 22: Msg("'.' expected")
 | 23: Msg("'[' expected")
 | 24: Msg("'..' expected")
 | 25: Msg("']' expected")
@@ -73,15 +73,19 @@
 | 72: Msg("'~' expected")
 | 73: Msg("'{' expected")
 | 74: Msg("'}' expected")
-| 75: Msg("not expected")
-| 76: Msg("invalid MulOp")
-| 77: Msg("invalid Fact")
-| 78: Msg("invalid AddOp")
-| 79: Msg("invalid Rel")
-| 80: Msg("invalid ByLit")
-| 81: Msg("invalid AssignOrCall")
-| 82: Msg("invalid SimpleType")
-| 83: Msg("invalid Type")
-| 84: Msg("invalid ProcedureDecl")
-| 85: Msg("invalid Declaration")
-| 86: Msg("invalid Import")
+| 75: Msg("'DEFINITION' expected")
+| 76: Msg("'IMPLEMENTATION' expected")
+| 77: Msg("not expected")
+| 78: Msg("invalid DefDecl")
+| 79: Msg("invalid MulOp")
+| 80: Msg("invalid Fact")
+| 81: Msg("invalid AddOp")
+| 82: Msg("invalid Rel")
+| 83: Msg("invalid ByLit")
+| 84: Msg("invalid AssignOrCall")
+| 85: Msg("invalid SimpleType")
+| 86: Msg("invalid Type")
+| 87: Msg("invalid ProcedureDecl")
+| 88: Msg("invalid Declaration")
+| 89: Msg("invalid Import")
+| 90: Msg("invalid Unit")

+ 2311 - 2158
M2c.lst

@@ -22,2177 +22,2330 @@ Listing:
 
     1  COMPILER M2c
     2  (* Modula-2 program modules with procedures and composites, MC64 backend
-    3     (see MGen for details).
-    4  
-    5     - program module only, no DEFINITION / IMPLEMENTATION split
-    6     - local MODULEs (single-file, no nesting): EXPORT of VARs, CONSTs,
-    7       TYPEs and procedures (value/VAR params, functions, open array
-    8       formals with fixed actuals); use as M.x / M.P(args); optional
-    9       BEGIN..END init bodies run at startup in declaration order;
-   10       no PRIORITY
-   11     - procedures: declarations (nested), value and VAR parameters,
-   12       functions with RETURN, recursion, FORWARD headings;
-   13       no procedure types/variables, no cones
-   14     - composites (Phase 3): fixed ARRAYs (bounds, 1D/multi-D indexing,
-   15       unchecked, byte-packed CHAR/BOOLEAN), RECORDs (field offsets,
-   16       .field, WITH incl. nested), SETs (+ union, - difference,
-   17       * intersection, inclusive .. ranges), POINTERs (NEW/DISPOSE via
-   18       VM ALLOCATE, ^, NIL), strings (ARRAY OF CHAR literal assign).
-   19       Open arrays deferred; whole array/record copy deferred except
-   20       string literals; VAR actuals must be simple (no a[i]/p^/fields
-   21       as VAR actuals, 233); value composite params rejected (230);
-   22       composite function returns rejected (unchecked, avoid wrong LEAVE).
-   23     - statements: assignment, procedure call, IF, CASE, WHILE,
-   24       REPEAT, LOOP/EXIT, FOR, WITH, RETURN, NEW, DISPOSE
-   25     - symbol table (SymTab) with static type checking: error codes
-   26       200/201/202 and 210-224 (as before), plus 231 (procedure
-   27       forward mismatch or missing body), 232 (bad RETURN), 233
-   28       (invalid procedure call); same lenient rules (single pass,
-   29       declare-before-use, except POINTER bases may be same-scope
-   30       aliases with structural pointer compatibility in Assignable;
-   31       INTEGER, CARDINAL and subranges form one
-   32       integer family; no mixed INTEGER/REAL arithmetic; INTEGER
-   33       assigns to REAL; 1-character literal is CHAR; InvalidType
-   34       suppresses follow-on errors)
-   35     - backend (MGen): single-module MC64 image <ModName>.MC4,
-   36       runnable with mcint. Procedures take table entries 1..N
-   37       (0 = module body), run with ENTER frames, called via ED
-   38       (global), EC (directly nested) or EE (display walk); actuals
-   39       evaluate left-to-right into temps, then push reversed.
-   40       Lowered: scalar + composite globals/frame vars (multi-slot,
-   41       byte sizes, field/element offsets), CONST literals,
-   42       SET masks with literals/ranges/IN/=/#/+-/*; full scalar +
-   43       composite expressions (scaled indexing via IdxScale, field
-   44       via FieldAdd, deref via 41H/60H, byte ops 0DH/1DH for CHAR);
-   45       control flow via E0/E1 jumps; composite assign via
-   46       StoreIndir0/StoreByte (scalar elems) and copy_block (strings).
-   47       The rest parses and type-checks
-   48       but gets error 230: open arrays, whole array/record copy
-   49       (except string literals), value composite params/returns,
-   50       non-literal CONST expressions and BY steps,
-   51       EXIT outside LOOP, imported names used as values.
-   52     - test convention (the language has no I/O): a global
-   53         VAR ExitCode : INTEGER;
-   54       is printed as decimal + CRLF through an embedded helper;
-   55       without it the program just ends.
-   56     - known semantic edges: INTEGER DIV/MOD truncate toward zero;
-   57       CARDINAL past MAXINT compares as signed; AND/OR are eager;
-   58       REAL widens to binary64; unchecked ARRAY indexing (no DA/DB);
-   59       NIL dereference reads 0 (no static check, no VM trap yet);
-   60       CHAR/BOOLEAN arrays byte-packed (1 byte/elem, slots over-
-   61       allocated 8x); at most 64 procedures, 64 actuals
-   62       per call, 16 names per FP-section, 8-deep nested calls,
-   63       8-deep WITH, 1024 slots max per type. *)
-   64  
-   65  IMPORT SymTab, MGen;
-   66  
-   67  CHARACTERS
-   68    eol      = CHR(13) .
-   69    letter   = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
-   70    digit    = "0123456789" .
-   71    hexDigit = digit + "ABCDEF" .
-   72    noQuote1 = ANY - "'" - eol .
-   73    noQuote2 = ANY - '"' - eol .
-   74  
-   75  IGNORE CHR(9) .. CHR(13)
-   76  
-   77  COMMENTS
-   78    FROM "(*" TO "*)" NESTED
-   79  
-   80  TOKENS
-   81    ident   = letter { letter | digit } .
-   82    integer = digit { digit }
-   83            | digit { digit } CONTEXT("..")
-   84            | digit { hexDigit } "H" .
-   85    real    = digit { digit } "." { digit }
-   86              [ "E" [ "+" | "-" ] digit { digit } ] .
-   87    string  = "'" { noQuote1 } "'"
-   88            | '"' { noQuote2 } '"' .
-   89  
-   90  PRODUCTIONS
-   91    M2c                                   (. VAR m1, m2: SymTab.Name; .)
-   92      = "MODULE"
-   93        GetIdent<m1>                      (. SymTab.Init; MGen.OpenModule(m1);
-   94                                             IF ~SymTab.Enter(m1, SymTab.KindModule)
-   95                                             THEN SemError(200) END .)
-   96        ";"
-   97        { Import } Block<FALSE> GetIdent<m2>
-   98                                          (. IF ~SymTab.Equal(m1, m2)
-   99                                             THEN SemError(202) END .)
-  100        "."                               (. IF SymTab.AnyForward() THEN
-  101                                             SemError(231)
-  102                                           END;
-  103                                           MGen.EndModule;
-  104                                           SymTab.PrintTable; .) .
-  105    Import                                (. VAR n: SymTab.Name; .)
-  106      = "FROM"
-  107        GetIdent<n>                       (. IF ~SymTab.Enter(n, SymTab.KindImport)
-  108                                             THEN SemError(200) END .)
-  109        "IMPORT"
-  110        ImportList ";"
-  111      | "IMPORT"
-  112        ImportList ";" .
-  113    ImportList                            (. VAR n: SymTab.Name; .)
-  114      = GetIdent<n>                       (. IF ~SymTab.Enter(n, SymTab.KindImport)
-  115                                             THEN SemError(200) END .)
-  116        { ","
-  117          GetIdent<n>                     (. IF ~SymTab.Enter(n, SymTab.KindImport)
-  118                                             THEN SemError(200) END .) } .
-  119    Block <isProc: BOOLEAN>               (. VAR began: BOOLEAN; .)
-  120      =                                   (. began := FALSE; .)
-  121        { Declaration }
-  122        [ "BEGIN"                         (. began := TRUE;
-  123                                             IF isProc THEN
-  124                                               MGen.ProcEntry(
-  125                                                 SymTab.CurProc(),
-  126                                                 SymTab.ProcNLocals())
-  127                                             ELSE MGen.BeginBody
-  128                                             END; .)
-  129          StatSeq ]
-  130        "END"                             (. IF isProc THEN
-  131                                             IF ~began THEN
-  132                                               MGen.ProcEntry(
-  133                                                 SymTab.CurProc(),
-  134                                                 SymTab.ProcNLocals())
-  135                                             END;
-  136                                             IF SymTab.InFunction() THEN
-  137                                               MGen.PushInt(0)
-  138                                             END;
-  139                                             MGen.Leave(SymTab.CurNPar(),
-  140                                               SymTab.InFunction())
-  141                                           END; .) .
-  142    Declaration = "CONST"
-  143                            {
-  144                              ConstDecl ";" }
-  145                | "TYPE"
-  146                            {
-  147                              TypeDecl ";" }
-  148                | "VAR"
-  149                            {
-  150                              VarDecl ";" }
-  151                | ProcedureDecl ";"
-  152                | ModuleDecl ";" .
-  153    ConstDecl                             (. VAR n: SymTab.Name;
-  154                                               t: SymTab.TypeIndex;
-  155                                               lx: MGen.LitStr;
-  156                                               cls: INTEGER; .)
-  157      = GetIdent<n>                       (. IF ~SymTab.Enter(n, SymTab.KindConst)
-  158                                             THEN SemError(200) END .)
-  159        "="                               (. MGen.NoEmitEnter; .)
-  160        ConstExpr<t, lx>                  (. SymTab.SetSymType(n, t);
-  161                                             cls := SymTab.ClassOf(t);
-  162                                             IF cls = SymTab.ClStr THEN
-  163                                               SemError(230)
-  164                                             ELSIF ~MGen.IsLit(lx) THEN
-  165                                               SemError(230)
-  166                                             END;
-  167                                             MGen.DeclConst(n, lx, t);
-  168                                             MGen.NoEmitExit; .) .
-  169    ConstExpr <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr>
-  170                                          (. VAR vD: BOOLEAN;
-  171                                               vnD: SymTab.Name; .)
-  172      = Expr<t, lx, vD, vnD> .
-  173    TypeDecl                              (. VAR n: SymTab.Name;
-  174                                               t0, t1: SymTab.TypeIndex; .)
-  175      = GetIdent<n>                       (. IF ~SymTab.Enter(n, SymTab.KindType)
-  176                                             THEN SemError(200) END;
-  177                                             t0 := SymTab.NewAlias();
-  178                                             SymTab.SetSymType(n, t0); .)
-  179        "="
-  180        Type<t1>                          (. IF t1 = t0 THEN SemError(223);
-  181                                               SymTab.SetTarget(t0,
-  182                                                 SymTab.InvalidType)
-  183                                             ELSE SymTab.SetTarget(t0, t1) END; .) .
-  184    VarDecl                               (. VAR t: SymTab.TypeIndex;
-  185                                               i: CARDINAL;
-  186                                               nm: SymTab.Name;
-  187                                               cls: INTEGER;
-  188                                               sl: CARDINAL; .)
-  189      = VarIdents ":"
-  190        Type<t>                           (. cls := SymTab.ClassOf(t);
-  191                                             IF (cls # SymTab.ClInt)
-  192                                                & (cls # SymTab.ClReal)
-  193                                                & (cls # SymTab.ClBool)
-  194                                                & (cls # SymTab.ClChar)
-  195                                                & (cls # SymTab.ClEnum)
-  196                                                & (cls # SymTab.ClSet)
-  197                                                & (cls # SymTab.ClArray)
-  198                                                & (cls # SymTab.ClRecord)
-  199                                                & (cls # SymTab.ClPtr) THEN
-  200                                               SemError(230)
-  201                                             END;
-  202                                             sl := SymTab.TypeSlots(t);
-  203                                             IF sl = 0 THEN
-  204                                               SemError(230);
-  205                                               sl := 1
-  206                                             END;
-  207                                             i := 0;
-  208                                             WHILE i < SymTab.PendCount() DO
-  209                                               SymTab.PendName(i, nm);
-  210                                               IF SymTab.SymDepth(nm) = 0 THEN
-  211                                                 MGen.DeclVarSized(nm, sl)
-  212                                               END;
-  213                                               INC(i)
-  214                                             END;
-  215                                             SymTab.FixPending(t); .) .
-  216    VarIdents                             (. VAR n: SymTab.Name; .)
-  217      = GetIdent<n>                       (. IF ~SymTab.EnterPending(n,
-  218                                               SymTab.KindVar)
-  219                                             THEN SemError(200) END .)
-  220        { ","
-  221          GetIdent<n>                     (. IF ~SymTab.EnterPending(n,
-  222                                               SymTab.KindVar)
-  223                                             THEN SemError(200) END .) } .
-  224    ProcedureDecl                         (. VAR n, m: SymTab.Name;
-  225                                               rt: SymTab.TypeIndex;
-  226                                               hasR, ok: BOOLEAN;
-  227                                               endL: INTEGER; .)
-  228      = "PROCEDURE"                       (. hasR := FALSE; .)
-  229        GetIdent<n>                       (. IF SymTab.IsForward(n) THEN
-  230                                               SymTab.ReuseProc(n)
-  231                                             ELSIF ~SymTab.EnterProc(n) THEN
-  232                                               SemError(200)
-  233                                             END;
-  234                                             SymTab.OpenProcScope;
-  235                                             endL := MGen.NewLabel();
-  236                                             MGen.Jmp(endL); .)
-  237        [ "(" FormalParams ")" ]
-  238        [ ":" QualIdent<rt>               (. hasR := TRUE; .) ]
-  239                                          (. IF hasR THEN
-  240                                               ok := SymTab.SetProcRet(rt)
-  241                                             ELSE
-  242                                               ok := SymTab.SetProcRet(
-  243                                                       SymTab.InvalidType)
-  244                                             END;
-  245                                             IF ~ok THEN SemError(231) END;
-  246                                             IF ~SymTab.VerifyProc() THEN
-  247                                               SemError(231)
-  248                                             END; .)
-  249        ";"
-  250        ( Block<TRUE> GetIdent<m>         (. IF ~SymTab.Equal(n, m) THEN
-  251                                             SemError(202) END;
-  252                                             MGen.DefLabel(endL);
-  253                                             SymTab.CloseProc; .)
-  254        | "FORWARD"                     (. SymTab.SetForward;
-  255                                             SymTab.CloseProc;
-  256                                             MGen.DefLabel(endL); .) ) .
-  257    ModuleDecl                            (. VAR n, m, e: SymTab.Name;
-  258                                               noMod, enterOk,
-  259                                               hasInit: BOOLEAN;
-  260                                               initL, initN: INTEGER; .)
-  261      = "MODULE"                          (. noMod := SymTab.InProc()
-  262                                                    OR SymTab.InModule();
-  263                                             enterOk := FALSE;
-  264                                             hasInit := FALSE; .)
-  265        GetIdent<n>                       (. IF noMod THEN
-  266                                             SemError(230)
-  267                                           ELSIF ~SymTab.EnterModule(n) THEN
-  268                                             SemError(200)
-  269                                           ELSE
-  270                                             enterOk := TRUE
-  271                                           END; .)
-  272        [ "EXPORT"
-  273          GetIdent<e>                     (. IF ~noMod & enterOk THEN
-  274                                             IF ~SymTab.ModuleAddExp(e) THEN
-  275                                               SemError(200)
-  276                                             END
-  277                                           END; .)
-  278          { "," GetIdent<e>               (. IF ~noMod & enterOk THEN
-  279                                             IF ~SymTab.ModuleAddExp(e) THEN
-  280                                               SemError(200)
-  281                                             END
-  282                                           END; .) } ]
-  283        ";"
-  284        { Declaration }
-  285        [ "BEGIN"                         (. hasInit := TRUE;
-  286                                             IF ~noMod & enterOk THEN
-  287                                               initL := MGen.NewLabel();
-  288                                               MGen.Jmp(initL);
-  289                                               initN := MGen.ModInitBegin();
-  290                                               IF initN < 0 THEN
-  291                                                 SemError(230)
-  292                                               END
-  293                                             END; .)
-  294          StatSeq ]
-  295        "END"
-  296        GetIdent<m>                       (. IF ~SymTab.Equal(n, m) THEN
-  297                                             SemError(202)
-  298                                           END;
-  299                                           IF hasInit & ~noMod & enterOk THEN
-  300                                             MGen.ModInitEnd(initN);
-  301                                             MGen.DefLabel(initL)
-  302                                           END;
-  303                                           IF ~noMod & enterOk THEN
-  304                                             IF ~SymTab.ExitModule() THEN
-  305                                               SemError(201)
-  306                                             END
-  307                                           END; .) .
-  308    FormalParams = FPSection { ";" FPSection } .
-  309    FPSection                             (. VAR isV: BOOLEAN;
-  310                                               nn, i: CARDINAL;
-  311                                               pn: ARRAY [0 .. 15] OF SymTab.Name;
-  312                                               n: SymTab.Name;
-  313                                               t: SymTab.TypeIndex; .)
-  314      =                                   (. isV := FALSE; nn := 0; .)
-  315        [ "VAR"                           (. isV := TRUE; .) ]
-  316        GetIdent<n>                       (. IF nn <= HIGH(pn) THEN
-  317                                               MGen.CopyName(n, pn[nn])
-  318                                             END;
-  319                                             INC(nn); .)
-  320        { "," GetIdent<n>                 (. IF nn <= HIGH(pn) THEN
-  321                                               MGen.CopyName(n, pn[nn])
-  322                                             END;
-  323                                             INC(nn); .) }
-  324        ":" Type<t>                       (. IF ~isV
-  325                                                & (t # SymTab.InvalidType)
-  326                                                & (SymTab.TypeSlots(t) > 1) THEN
-  327                                               SemError(230)
-  328                                             END;
-  329                                             i := 0;
-  330                                             WHILE i < nn DO
-  331                                               IF i <= HIGH(pn) THEN
-  332                                                 IF ~SymTab.EnterParam(
-  333                                                      pn[i], isV, t) THEN
-  334                                                   SemError(200)
-  335                                                 END
-  336                                               END;
-  337                                               INC(i)
-  338                                             END; .) .
-  339    QualIdent <VAR t: SymTab.TypeIndex>
-  340                                          (. VAR n, m: SymTab.Name; .)
-  341      = GetIdent<n>                       (. IF ~SymTab.Lookup(n) THEN
-  342                                               SemError(201);
-  343                                               t := SymTab.InvalidType
-  344                                             ELSIF SymTab.SymKind(n)
-  345                                                = SymTab.KindModule THEN
-  346                                               t := SymTab.InvalidType
-  347                                             ELSIF (SymTab.SymKind(n) #
-  348                                                    SymTab.KindType)
-  349                                                & (SymTab.SymKind(n) #
-  350                                                   SymTab.KindPredef)
-  351                                                & (SymTab.SymKind(n) #
-  352                                                   SymTab.KindImport) THEN
-  353                                               SemError(221);
-  354                                               t := SymTab.InvalidType
-  355                                             ELSE t := SymTab.SymType(n) END; .)
-  356        { "."
-  357          GetIdent<m>                     (. IF SymTab.SymKind(n)
-  358                                              = SymTab.KindModule THEN
-  359                                             IF SymTab.ExpKind(n, m)
-  360                                                = SymTab.KindType THEN
-  361                                               t := SymTab.ExpType(n, m)
-  362                                             ELSIF SymTab.SelfKind(n, m)
-  363                                                = SymTab.KindType THEN
-  364                                               t := SymTab.SymType(m)
-  365                                             ELSE
-  366                                               IF SymTab.ExpKind(n, m) < 0 THEN
-  367                                                 IF SymTab.SelfKind(n, m) < 0 THEN
-  368                                                   SemError(201)
-  369                                                 ELSE SemError(221)
-  370                                                 END
-  371                                               ELSE SemError(221)
-  372                                               END;
-  373                                               t := SymTab.InvalidType
-  374                                             END
-  375                                           ELSE
-  376                                             t := SymTab.InvalidType
-  377                                           END; .) } .
-  378  
-  379    (* Types: ProcedureType removed; subrange factored for LL(1) *)
-  380    Type <VAR t: SymTab.TypeIndex>
-  381      = SimpleType<t> | ArrayType<t> | RecordType<t>
-  382      | SetType<t> | PointerType<t> .
-  383    SimpleType <VAR t: SymTab.TypeIndex>
-  384                                          (. VAR t1, t2: SymTab.TypeIndex;
-  385                                               lx1, lx2: MGen.LitStr;
-  386                                               vD: BOOLEAN;
-  387                                               vnD: SymTab.Name;
-  388                                               loI, hiI: INTEGER;
-  389                                               lok, hik: BOOLEAN; .)
-  390      = QualIdent<t> [ "["
-  391                        (. MGen.NoEmitEnter; lok := FALSE; hik := FALSE;
-  392                           loI := 0; hiI := -1; .)
-  393                        ConstExpr<t1, lx1> (. IF (t1 # SymTab.InvalidType)
-  394                                              & (SymTab.ClassOf(t1) #
-  395                                                 SymTab.ClInt)
-  396                                              & (SymTab.ClassOf(t1) #
-  397                                                 SymTab.ClChar)
-  398                                              & (SymTab.ClassOf(t1) #
-  399                                                 SymTab.ClEnum) THEN
-  400                                              SemError(224) END; .)
-  401                        ".."
-  402                        ConstExpr<t2, lx2> (. IF (t2 # SymTab.InvalidType)
-  403                                              & (SymTab.ClassOf(t2) #
-  404                                                 SymTab.ClInt)
-  405                                              & (SymTab.ClassOf(t2) #
-  406                                                 SymTab.ClChar)
-  407                                              & (SymTab.ClassOf(t2) #
-  408                                                 SymTab.ClEnum) THEN
-  409                                              SemError(224) END; .)
-  410                        "]"
-  411                                       (. IF (t1 # SymTab.InvalidType)
-  412                                           & (t2 # SymTab.InvalidType) THEN
-  413                                             IF MGen.IsLit(lx1) THEN
-  414                                               IF SymTab.ClassOf(t1)
-  415                                                  = SymTab.ClChar THEN
-  416                                                 loI := MGen.CharOrd(lx1);
-  417                                                 lok := TRUE
-  418                                               ELSIF MGen.ParseInt(lx1, loI) THEN
-  419                                                 lok := TRUE
-  420                                               END
-  421                                             END;
-  422                                             IF MGen.IsLit(lx2) THEN
-  423                                               IF SymTab.ClassOf(t2)
-  424                                                  = SymTab.ClChar THEN
-  425                                                 hiI := MGen.CharOrd(lx2);
-  426                                                 hik := TRUE
-  427                                               ELSIF MGen.ParseInt(lx2, hiI) THEN
-  428                                                 hik := TRUE
-  429                                               END
-  430                                             END
-  431                                           END;
-  432                                          IF lok & hik THEN
-  433                                            t := SymTab.NewSubB(t1, loI, hiI)
-  434                                          ELSE
-  435                                            t := SymTab.NewSub(t1);
-  436                                            IF (t1 # SymTab.InvalidType)
-  437                                               & (t2 # SymTab.InvalidType) THEN
-  438                                              SemError(230)
-  439                                            END
-  440                                          END;
-  441                                          MGen.NoEmitExit; .) ]
-  442      | "["                               (. MGen.NoEmitEnter; lok := FALSE;
-  443                                             hik := FALSE; loI := 0; hiI := -1; .)
-  444        ConstExpr<t1, lx1>                (. IF (t1 # SymTab.InvalidType)
-  445                                              & (SymTab.ClassOf(t1) #
-  446                                                 SymTab.ClInt)
-  447                                              & (SymTab.ClassOf(t1) #
-  448                                                 SymTab.ClChar)
+    3     (see MGen for details). Step 11 adds separate compilation units
+    4     (DEFINITION / IMPLEMENTATION / IMPORT) into a single image:
+    5  
+    6     - session: M2c f1.def f2.mod ... prog.mod — definition files,
+    7       then implementations, then exactly one program module;
+    8       one <Program>.MC4 image, one .LST per input, fail-fast on the
+    9       first bad file. SymTab.Init + MGen.OpenModule run once in the
+   10       driver; the program unit sets the image name (SetModName).
+   11     - DEFINITION MODULE L: CONST/TYPE/VAR + procedure headings only;
+   12       everything declared is exported (export tables + in-memory
+   13       interface side table); VAR/CONST allocate their global slots
+   14       once ("L.x"); proc headings reserve numbers via the forward
+   15       machinery. No nested MODULEs, no BEGIN.
+   16     - IMPLEMENTATION MODULE L: needs its definition (201); re-enters
+   17       the interface implicitly (redeclared exports are 200
+   18       duplicates); headings match via ReuseProc/VerifyProc (231);
+   19       private decls allowed; every heading needs its body (231);
+   20       optional BEGIN init runs at startup in file order.
+   21     - IMPORT L validates a known definition (201); FROM L IMPORT x
+   22       materializes real alias symbols (types/consts/vars share the
+   23       definition's descriptors and globals via GlobAlias; procs
+   24       share the number, so call checking is unchanged). Ghost
+   25       names are 201, bad kinds 221, duplicates 200.
+   26     - caps (phase): 8 definitions, 32 interface names each,
+   27       64 FROM-aliases; still one image, depCount 0 (no multi-.MC4,
+   28       no circular imports, no opaque types).
+   29  
+   30     Older notes (steps 1-10):
+   31     - program module only, no DEFINITION / IMPLEMENTATION split
+   32     - local MODULEs (single-file, no nesting): EXPORT of VARs, CONSTs,
+   33       TYPEs and procedures (value/VAR params, functions, open array
+   34       formals with fixed actuals); use as M.x / M.P(args); optional
+   35       BEGIN..END init bodies run at startup in declaration order;
+   36       no PRIORITY
+   37     - procedures: declarations (nested), value and VAR parameters,
+   38       functions with RETURN, recursion, FORWARD headings;
+   39       no procedure types/variables, no cones
+   40     - composites (Phase 3): fixed ARRAYs (bounds, 1D/multi-D indexing,
+   41       unchecked, byte-packed CHAR/BOOLEAN), RECORDs (field offsets,
+   42       .field, WITH incl. nested), SETs (+ union, - difference,
+   43       * intersection, inclusive .. ranges), POINTERs (NEW/DISPOSE via
+   44       VM ALLOCATE, ^, NIL), strings (ARRAY OF CHAR literal assign).
+   45       Open arrays deferred; whole array/record copy deferred except
+   46       string literals; VAR actuals must be simple (no a[i]/p^/fields
+   47       as VAR actuals, 233); value composite params rejected (230);
+   48       composite function returns rejected (unchecked, avoid wrong LEAVE).
+   49     - statements: assignment, procedure call, IF, CASE, WHILE,
+   50       REPEAT, LOOP/EXIT, FOR, WITH, RETURN, NEW, DISPOSE
+   51     - symbol table (SymTab) with static type checking: error codes
+   52       200/201/202 and 210-224 (as before), plus 231 (procedure
+   53       forward mismatch or missing body), 232 (bad RETURN), 233
+   54       (invalid procedure call); same lenient rules (single pass,
+   55       declare-before-use, except POINTER bases may be same-scope
+   56       aliases with structural pointer compatibility in Assignable;
+   57       INTEGER, CARDINAL and subranges form one
+   58       integer family; no mixed INTEGER/REAL arithmetic; INTEGER
+   59       assigns to REAL; 1-character literal is CHAR; InvalidType
+   60       suppresses follow-on errors)
+   61     - backend (MGen): single-module MC64 image <ModName>.MC4,
+   62       runnable with mcint. Procedures take table entries 1..N
+   63       (0 = module body), run with ENTER frames, called via ED
+   64       (global), EC (directly nested) or EE (display walk); actuals
+   65       evaluate left-to-right into temps, then push reversed.
+   66       Lowered: scalar + composite globals/frame vars (multi-slot,
+   67       byte sizes, field/element offsets), CONST literals,
+   68       SET masks with literals/ranges/IN/=/#/+-/*; full scalar +
+   69       composite expressions (scaled indexing via IdxScale, field
+   70       via FieldAdd, deref via 41H/60H, byte ops 0DH/1DH for CHAR);
+   71       control flow via E0/E1 jumps; composite assign via
+   72       StoreIndir0/StoreByte (scalar elems) and copy_block (strings).
+   73       The rest parses and type-checks
+   74       but gets error 230: open arrays, whole array/record copy
+   75       (except string literals), value composite params/returns,
+   76       non-literal CONST expressions and BY steps,
+   77       EXIT outside LOOP, imported names used as values.
+   78     - test convention (the language has no I/O): a global
+   79         VAR ExitCode : INTEGER;
+   80       is printed as decimal + CRLF through an embedded helper;
+   81       without it the program just ends.
+   82     - known semantic edges: INTEGER DIV/MOD truncate toward zero;
+   83       CARDINAL past MAXINT compares as signed; AND/OR are eager;
+   84       REAL widens to binary64; unchecked ARRAY indexing (no DA/DB);
+   85       NIL dereference reads 0 (no static check, no VM trap yet);
+   86       CHAR/BOOLEAN arrays byte-packed (1 byte/elem, slots over-
+   87       allocated 8x); at most 64 procedures, 64 actuals
+   88       per call, 16 names per FP-section, 8-deep nested calls,
+   89       8-deep WITH, 1024 slots max per type. *)
+   90  
+   91  IMPORT SymTab, MGen;
+   92  
+   93  CHARACTERS
+   94    eol      = CHR(13) .
+   95    letter   = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
+   96    digit    = "0123456789" .
+   97    hexDigit = digit + "ABCDEF" .
+   98    noQuote1 = ANY - "'" - eol .
+   99    noQuote2 = ANY - '"' - eol .
+  100  
+  101  IGNORE CHR(9) .. CHR(13)
+  102  
+  103  COMMENTS
+  104    FROM "(*" TO "*)" NESTED
+  105  
+  106  TOKENS
+  107    ident   = letter { letter | digit } .
+  108    integer = digit { digit }
+  109            | digit { digit } CONTEXT("..")
+  110            | digit { hexDigit } "H" .
+  111    real    = digit { digit } "." { digit }
+  112              [ "E" [ "+" | "-" ] digit { digit } ] .
+  113    string  = "'" { noQuote1 } "'"
+  114            | '"' { noQuote2 } '"' .
+  115  
+  116  PRODUCTIONS
+  117    (* NOTE: Coco/R numbers tokens by first occurrence; M2c.mod's Msg
+  118       table is regenerated from M2c.err on every build (via
+  119       compiler.frm). After grammar edits, rebuild and check that
+  120       the messages still name the right tokens. *)
+  121    M2c
+  122      = Unit .
+  123    Unit
+  124      = DefUnit | ImplUnit | ProgUnit .
+  125    Import                                (. VAR n: SymTab.Name; .)
+  126      = "FROM"
+  127        GetIdent<n>                       (. IF ~SymTab.IsDefMod(n) THEN
+  128                                               SemError(201)
+  129                                             END; .)
+  130        "IMPORT"
+  131        ImpItem<n> { "," ImpItem<n> } ";"
+  132      | "IMPORT"
+  133        GetIdent<n>                       (. IF ~SymTab.IsDefMod(n) THEN
+  134                                               SemError(201)
+  135                                             END; .)
+  136        { ","
+  137          GetIdent<n>                     (. IF ~SymTab.IsDefMod(n) THEN
+  138                                               SemError(201)
+  139                                             END; .) } ";" .
+  140    ImpItem<mod: SymTab.Name>             (. VAR a: SymTab.Name;
+  141                                               k: INTEGER; .)
+  142      = GetIdent<a>                       (. IF ~SymTab.ImpBind(mod, a) THEN
+  143                                               SemError(201)
+  144                                             ELSE
+  145                                               k := SymTab.ExpKind(mod, a);
+  146                                               IF k = SymTab.KindType THEN
+  147                                                 IF ~SymTab.Enter(a, k) THEN
+  148                                                   SemError(200);
+  149                                                   SymTab.ImpUnbind(a)
+  150                                                 ELSE
+  151                                                   SymTab.SetSymType(a,
+  152                                                     SymTab.ExpType(mod, a))
+  153                                                 END
+  154                                               ELSIF (k = SymTab.KindConst)
+  155                                                  OR (k = SymTab.KindVar) THEN
+  156                                                 IF ~SymTab.Enter(a, k) THEN
+  157                                                   SemError(200);
+  158                                                   SymTab.ImpUnbind(a)
+  159                                                 ELSE
+  160                                                   SymTab.SetSymType(a,
+  161                                                     SymTab.ExpType(mod, a))
+  162                                                 END
+  163                                               ELSIF k = SymTab.KindProc THEN
+  164                                                 IF ~SymTab.EnterImpProc(a,
+  165                                                   SymTab.ExpProc(mod, a)) THEN
+  166                                                   SemError(200);
+  167                                                   SymTab.ImpUnbind(a)
+  168                                                 END
+  169                                               ELSE
+  170                                                 SemError(221);
+  171                                                 SymTab.ImpUnbind(a)
+  172                                               END
+  173                                             END; .) .
+  174    Block <isProc: BOOLEAN>               (. VAR began: BOOLEAN; .)
+  175      =                                   (. began := FALSE; .)
+  176        { Declaration }
+  177        [ "BEGIN"                         (. began := TRUE;
+  178                                             IF isProc THEN
+  179                                               MGen.ProcEntry(
+  180                                                 SymTab.CurProc(),
+  181                                                 SymTab.ProcNLocals())
+  182                                             ELSE MGen.BeginBody
+  183                                             END; .)
+  184          StatSeq ]
+  185        "END"                             (. IF isProc THEN
+  186                                             IF ~began THEN
+  187                                               MGen.ProcEntry(
+  188                                                 SymTab.CurProc(),
+  189                                                 SymTab.ProcNLocals())
+  190                                             END;
+  191                                             IF SymTab.InFunction() THEN
+  192                                               MGen.PushInt(0)
+  193                                             END;
+  194                                             MGen.Leave(SymTab.CurNPar(),
+  195                                               SymTab.InFunction())
+  196                                           END; .) .
+  197    Declaration = "CONST"
+  198                            {
+  199                              ConstDecl ";" }
+  200                | "TYPE"
+  201                            {
+  202                              TypeDecl ";" }
+  203                | "VAR"
+  204                            {
+  205                              VarDecl ";" }
+  206                | ProcedureDecl ";"
+  207                | ModuleDecl ";" .
+  208    ConstDecl                             (. VAR n: SymTab.Name;
+  209                                               t: SymTab.TypeIndex;
+  210                                               lx: MGen.LitStr;
+  211                                               cls: INTEGER; .)
+  212      = GetIdent<n>                       (. IF ~SymTab.Enter(n, SymTab.KindConst)
+  213                                             THEN SemError(200) END .)
+  214        "="                               (. MGen.NoEmitEnter; .)
+  215        ConstExpr<t, lx>                  (. SymTab.SetSymType(n, t);
+  216                                             cls := SymTab.ClassOf(t);
+  217                                             IF cls = SymTab.ClStr THEN
+  218                                               SemError(230)
+  219                                             ELSIF ~MGen.IsLit(lx) THEN
+  220                                               SemError(230)
+  221                                             END;
+  222                                             MGen.DeclConst(n, lx, t);
+  223                                             MGen.NoEmitExit; .) .
+  224    ConstExpr <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr>
+  225                                          (. VAR vD: BOOLEAN;
+  226                                               vnD: SymTab.Name; .)
+  227      = Expr<t, lx, vD, vnD> .
+  228    TypeDecl                              (. VAR n: SymTab.Name;
+  229                                               t0, t1: SymTab.TypeIndex; .)
+  230      = GetIdent<n>                       (. IF ~SymTab.Enter(n, SymTab.KindType)
+  231                                             THEN SemError(200) END;
+  232                                             t0 := SymTab.NewAlias();
+  233                                             SymTab.SetSymType(n, t0); .)
+  234        "="
+  235        Type<t1>                          (. IF t1 = t0 THEN SemError(223);
+  236                                               SymTab.SetTarget(t0,
+  237                                                 SymTab.InvalidType)
+  238                                             ELSE SymTab.SetTarget(t0, t1) END; .) .
+  239    VarDecl                               (. VAR t: SymTab.TypeIndex;
+  240                                               i: CARDINAL;
+  241                                               nm: SymTab.Name;
+  242                                               cls: INTEGER;
+  243                                               sl: CARDINAL; .)
+  244      = VarIdents ":"
+  245        Type<t>                           (. cls := SymTab.ClassOf(t);
+  246                                             IF (cls # SymTab.ClInt)
+  247                                                & (cls # SymTab.ClReal)
+  248                                                & (cls # SymTab.ClBool)
+  249                                                & (cls # SymTab.ClChar)
+  250                                                & (cls # SymTab.ClEnum)
+  251                                                & (cls # SymTab.ClSet)
+  252                                                & (cls # SymTab.ClArray)
+  253                                                & (cls # SymTab.ClRecord)
+  254                                                & (cls # SymTab.ClPtr) THEN
+  255                                               SemError(230)
+  256                                             END;
+  257                                             sl := SymTab.TypeSlots(t);
+  258                                             IF sl = 0 THEN
+  259                                               SemError(230);
+  260                                               sl := 1
+  261                                             END;
+  262                                             i := 0;
+  263                                             WHILE i < SymTab.PendCount() DO
+  264                                               SymTab.PendName(i, nm);
+  265                                               IF SymTab.SymDepth(nm) = 0 THEN
+  266                                                 MGen.DeclVarSized(nm, sl)
+  267                                               END;
+  268                                               INC(i)
+  269                                             END;
+  270                                             SymTab.FixPending(t); .) .
+  271    VarIdents                             (. VAR n: SymTab.Name; .)
+  272      = GetIdent<n>                       (. IF ~SymTab.EnterPending(n,
+  273                                               SymTab.KindVar)
+  274                                             THEN SemError(200) END .)
+  275        { ","
+  276          GetIdent<n>                     (. IF ~SymTab.EnterPending(n,
+  277                                               SymTab.KindVar)
+  278                                             THEN SemError(200) END .) } .
+  279    ProcedureDecl                         (. VAR n, m: SymTab.Name;
+  280                                               rt: SymTab.TypeIndex;
+  281                                               hasR, ok: BOOLEAN;
+  282                                               endL: INTEGER; .)
+  283      = "PROCEDURE"                       (. hasR := FALSE; .)
+  284        GetIdent<n>                       (. IF SymTab.IsForward(n) THEN
+  285                                               SymTab.ReuseProc(n)
+  286                                             ELSIF ~SymTab.EnterProc(n) THEN
+  287                                               SemError(200)
+  288                                             END;
+  289                                             SymTab.OpenProcScope;
+  290                                             endL := MGen.NewLabel();
+  291                                             MGen.Jmp(endL); .)
+  292        [ "(" FormalParams ")" ]
+  293        [ ":" QualIdent<rt>               (. hasR := TRUE; .) ]
+  294                                          (. IF hasR THEN
+  295                                               ok := SymTab.SetProcRet(rt)
+  296                                             ELSE
+  297                                               ok := SymTab.SetProcRet(
+  298                                                       SymTab.InvalidType)
+  299                                             END;
+  300                                             IF ~ok THEN SemError(231) END;
+  301                                             IF ~SymTab.VerifyProc() THEN
+  302                                               SemError(231)
+  303                                             END; .)
+  304        ";"
+  305        ( Block<TRUE> GetIdent<m>         (. IF ~SymTab.Equal(n, m) THEN
+  306                                             SemError(202) END;
+  307                                             MGen.DefLabel(endL);
+  308                                             SymTab.CloseProc; .)
+  309        | "FORWARD"                     (. SymTab.SetForward;
+  310                                             SymTab.CloseProc;
+  311                                             MGen.DefLabel(endL); .) ) .
+  312    ModuleDecl                            (. VAR n, m, e: SymTab.Name;
+  313                                               noMod, enterOk,
+  314                                               hasInit: BOOLEAN;
+  315                                               initL, initN: INTEGER; .)
+  316      = "MODULE"                          (. noMod := SymTab.InProc()
+  317                                                    OR SymTab.InModule();
+  318                                             enterOk := FALSE;
+  319                                             hasInit := FALSE; .)
+  320        GetIdent<n>                       (. IF noMod THEN
+  321                                             SemError(230)
+  322                                           ELSIF ~SymTab.EnterModule(n) THEN
+  323                                             SemError(200)
+  324                                           ELSE
+  325                                             enterOk := TRUE
+  326                                           END; .)
+  327        [ "EXPORT"
+  328          GetIdent<e>                     (. IF ~noMod & enterOk THEN
+  329                                             IF ~SymTab.ModuleAddExp(e) THEN
+  330                                               SemError(200)
+  331                                             END
+  332                                           END; .)
+  333          { "," GetIdent<e>               (. IF ~noMod & enterOk THEN
+  334                                             IF ~SymTab.ModuleAddExp(e) THEN
+  335                                               SemError(200)
+  336                                             END
+  337                                           END; .) } ]
+  338        ";"
+  339        { Declaration }
+  340        [ "BEGIN"                         (. hasInit := TRUE;
+  341                                             IF ~noMod & enterOk THEN
+  342                                               initL := MGen.NewLabel();
+  343                                               MGen.Jmp(initL);
+  344                                               initN := MGen.ModInitBegin();
+  345                                               IF initN < 0 THEN
+  346                                                 SemError(230)
+  347                                               END
+  348                                             END; .)
+  349          StatSeq ]
+  350        "END"
+  351        GetIdent<m>                       (. IF ~SymTab.Equal(n, m) THEN
+  352                                             SemError(202)
+  353                                           END;
+  354                                           IF hasInit & ~noMod & enterOk THEN
+  355                                             MGen.ModInitEnd(initN);
+  356                                             MGen.DefLabel(initL)
+  357                                           END;
+  358                                           IF ~noMod & enterOk THEN
+  359                                             IF ~SymTab.ExitModule() THEN
+  360                                               SemError(201)
+  361                                             END
+  362                                           END; .) .
+  363    FormalParams = FPSection { ";" FPSection } .
+  364    FPSection                             (. VAR isV: BOOLEAN;
+  365                                               nn, i: CARDINAL;
+  366                                               pn: ARRAY [0 .. 15] OF SymTab.Name;
+  367                                               n: SymTab.Name;
+  368                                               t: SymTab.TypeIndex; .)
+  369      =                                   (. isV := FALSE; nn := 0; .)
+  370        [ "VAR"                           (. isV := TRUE; .) ]
+  371        GetIdent<n>                       (. IF nn <= HIGH(pn) THEN
+  372                                               MGen.CopyName(n, pn[nn])
+  373                                             END;
+  374                                             INC(nn); .)
+  375        { "," GetIdent<n>                 (. IF nn <= HIGH(pn) THEN
+  376                                               MGen.CopyName(n, pn[nn])
+  377                                             END;
+  378                                             INC(nn); .) }
+  379        ":" Type<t>                       (. IF ~isV
+  380                                                & (t # SymTab.InvalidType)
+  381                                                & (SymTab.TypeSlots(t) > 1) THEN
+  382                                               SemError(230)
+  383                                             END;
+  384                                             i := 0;
+  385                                             WHILE i < nn DO
+  386                                               IF i <= HIGH(pn) THEN
+  387                                                 IF ~SymTab.EnterParam(
+  388                                                      pn[i], isV, t) THEN
+  389                                                   SemError(200)
+  390                                                 END
+  391                                               END;
+  392                                               INC(i)
+  393                                             END; .) .
+  394    QualIdent <VAR t: SymTab.TypeIndex>
+  395                                          (. VAR n, m: SymTab.Name; .)
+  396      = GetIdent<n>                       (. IF ~SymTab.Lookup(n) THEN
+  397                                               SemError(201);
+  398                                               t := SymTab.InvalidType
+  399                                             ELSIF SymTab.SymKind(n)
+  400                                                = SymTab.KindModule THEN
+  401                                               t := SymTab.InvalidType
+  402                                             ELSIF (SymTab.SymKind(n) #
+  403                                                    SymTab.KindType)
+  404                                                & (SymTab.SymKind(n) #
+  405                                                   SymTab.KindPredef)
+  406                                                & (SymTab.SymKind(n) #
+  407                                                   SymTab.KindImport) THEN
+  408                                               SemError(221);
+  409                                               t := SymTab.InvalidType
+  410                                             ELSE t := SymTab.SymType(n) END; .)
+  411        { "."
+  412          GetIdent<m>                     (. IF SymTab.SymKind(n)
+  413                                              = SymTab.KindModule THEN
+  414                                             IF SymTab.ExpKind(n, m)
+  415                                                = SymTab.KindType THEN
+  416                                               t := SymTab.ExpType(n, m)
+  417                                             ELSIF SymTab.SelfKind(n, m)
+  418                                                = SymTab.KindType THEN
+  419                                               t := SymTab.SymType(m)
+  420                                             ELSE
+  421                                               IF SymTab.ExpKind(n, m) < 0 THEN
+  422                                                 IF SymTab.SelfKind(n, m) < 0 THEN
+  423                                                   SemError(201)
+  424                                                 ELSE SemError(221)
+  425                                                 END
+  426                                               ELSE SemError(221)
+  427                                               END;
+  428                                               t := SymTab.InvalidType
+  429                                             END
+  430                                           ELSE
+  431                                             t := SymTab.InvalidType
+  432                                           END; .) } .
+  433  
+  434    (* Types: ProcedureType removed; subrange factored for LL(1) *)
+  435    Type <VAR t: SymTab.TypeIndex>
+  436      = SimpleType<t> | ArrayType<t> | RecordType<t>
+  437      | SetType<t> | PointerType<t> .
+  438    SimpleType <VAR t: SymTab.TypeIndex>
+  439                                          (. VAR t1, t2: SymTab.TypeIndex;
+  440                                               lx1, lx2: MGen.LitStr;
+  441                                               vD: BOOLEAN;
+  442                                               vnD: SymTab.Name;
+  443                                               loI, hiI: INTEGER;
+  444                                               lok, hik: BOOLEAN; .)
+  445      = QualIdent<t> [ "["
+  446                        (. MGen.NoEmitEnter; lok := FALSE; hik := FALSE;
+  447                           loI := 0; hiI := -1; .)
+  448                        ConstExpr<t1, lx1> (. IF (t1 # SymTab.InvalidType)
   449                                              & (SymTab.ClassOf(t1) #
-  450                                                 SymTab.ClEnum) THEN
-  451                                              SemError(224) END; .)
-  452        ".."
-  453        ConstExpr<t2, lx2>                (. IF (t2 # SymTab.InvalidType)
-  454                                              & (SymTab.ClassOf(t2) #
-  455                                                 SymTab.ClInt)
-  456                                              & (SymTab.ClassOf(t2) #
-  457                                                 SymTab.ClChar)
+  450                                                 SymTab.ClInt)
+  451                                              & (SymTab.ClassOf(t1) #
+  452                                                 SymTab.ClChar)
+  453                                              & (SymTab.ClassOf(t1) #
+  454                                                 SymTab.ClEnum) THEN
+  455                                              SemError(224) END; .)
+  456                        ".."
+  457                        ConstExpr<t2, lx2> (. IF (t2 # SymTab.InvalidType)
   458                                              & (SymTab.ClassOf(t2) #
-  459                                                 SymTab.ClEnum) THEN
-  460                                              SemError(224) END; .)
-  461        "]"                               (. IF (t1 # SymTab.InvalidType)
-  462                                             & (t2 # SymTab.InvalidType) THEN
-  463                                               IF MGen.IsLit(lx1) THEN
-  464                                                 IF SymTab.ClassOf(t1)
-  465                                                    = SymTab.ClChar THEN
-  466                                                   loI := MGen.CharOrd(lx1);
-  467                                                   lok := TRUE
-  468                                                 ELSIF MGen.ParseInt(lx1,
-  469                                                           loI) THEN
-  470                                                   lok := TRUE
-  471                                                 END
-  472                                               END;
-  473                                               IF MGen.IsLit(lx2) THEN
-  474                                                 IF SymTab.ClassOf(t2)
-  475                                                    = SymTab.ClChar THEN
-  476                                                   hiI := MGen.CharOrd(lx2);
-  477                                                   hik := TRUE
-  478                                                 ELSIF MGen.ParseInt(lx2,
-  479                                                           hiI) THEN
-  480                                                   hik := TRUE
-  481                                                 END
-  482                                               END
-  483                                             END;
-  484                                            IF lok & hik THEN
-  485                                              t := SymTab.NewSubB(t1, loI, hiI)
-  486                                            ELSE
-  487                                              t := SymTab.NewSub(t1);
-  488                                              IF (t1 # SymTab.InvalidType)
-  489                                                 & (t2 # SymTab.InvalidType) THEN
-  490                                                SemError(230)
-  491                                              END
-  492                                            END;
-  493                                             MGen.NoEmitExit; .)
-  494      | Enum<t> .
-  495    Enum <VAR t: SymTab.TypeIndex>
-  496                                          (. VAR n: SymTab.Name;
-  497                                               ord: INTEGER; .)
-  498      = "("                               (. t := SymTab.NewEnum();
-  499                                             ord := 0; .)
-  500        GetIdent<n>                       (. IF ~SymTab.Enter(n,
-  501                                               SymTab.KindConst)
-  502                                             THEN SemError(200) END;
-  503                                             SymTab.SetSymType(n, t);
-  504                                             SymTab.EnumAdd(t);
-  505                                             MGen.DeclConstInt(n, ord);
-  506                                             INC(ord); .)
-  507        { ","
-  508          GetIdent<n>                     (. IF ~SymTab.Enter(n,
-  509                                               SymTab.KindConst)
-  510                                             THEN SemError(200) END;
-  511                                             SymTab.SetSymType(n, t);
-  512                                             SymTab.EnumAdd(t);
-  513                                             MGen.DeclConstInt(n, ord);
-  514                                             INC(ord); .) }
-  515        ")" .
-  516    ArrayType <VAR t: SymTab.TypeIndex>
-  517                                          (. VAR s, s2, e: SymTab.TypeIndex;
-  518                                               idx: ARRAY [0 .. 7] OF
-  519                                                 SymTab.TypeIndex;
-  520                                               nc, kk: CARDINAL;
-  521                                               loA, hiA: INTEGER;
-  522                                               isOpenA: BOOLEAN; .)
-  523      = "ARRAY"
-  524        [ SimpleType<s>                     (. IF (s # SymTab.InvalidType)
-  525                                              & (SymTab.ClassOf(s) #
-  526                                                 SymTab.ClInt)
-  527                                              & (SymTab.ClassOf(s) #
-  528                                                 SymTab.ClChar)
-  529                                              & (SymTab.ClassOf(s) #
-  530                                                 SymTab.ClEnum) THEN
-  531                                              SemError(224) END;
-  532                                             nc := 0; isOpenA := FALSE;
-  533                                             idx[nc] := s; INC(nc); .)
-  534          { ","
-  535            SimpleType<s2>                  (. IF (s2 # SymTab.InvalidType)
-  536                                              & (SymTab.ClassOf(s2) #
-  537                                                 SymTab.ClInt)
-  538                                              & (SymTab.ClassOf(s2) #
-  539                                                 SymTab.ClChar)
-  540                                              & (SymTab.ClassOf(s2) #
-  541                                                 SymTab.ClEnum) THEN
-  542                                              SemError(224) END;
-  543                                             IF nc <= HIGH(idx) THEN
-  544                                               idx[nc] := s2; INC(nc)
-  545                                             END; .) }
-  546        |                                   (. nc := 0; isOpenA := TRUE; .) ]
-  547        "OF"
-  548        Type<e>                           (. IF isOpenA THEN
-  549                                             t := SymTab.NewOpen(e)
-  550                                           ELSE
-  551                                             t := e;
-  552                                             kk := nc;
-  553                                             WHILE kk > 0 DO
-  554                                               DEC(kk);
-  555                                               loA := SymTab.TypeLo(idx[kk]);
-  556                                               hiA := SymTab.TypeHi(idx[kk]);
-  557                                               IF SymTab.TypeLen(idx[kk]) = 0 THEN
-  558                                                 IF idx[kk]
-  559                                                    # SymTab.InvalidType THEN
-  560                                                   SemError(230)
-  561                                                 END;
-  562                                                 loA := 0; hiA := -1
-  563                                               END;
-  564                                               t := SymTab.NewArrayB(t,
-  565                                                       loA, hiA)
-  566                                             END
-  567                                           END; .) .
-  568    RecordType <VAR t: SymTab.TypeIndex>
-  569      = "RECORD"                          (. t := SymTab.NewRecord(); .)
-  570        FieldSeq<t>
-  571        "END" .
-  572    FieldSeq <rt: SymTab.TypeIndex>
-  573      = Field<rt> { ";"
-  574                    Field<rt> } .
-  575    Field <rt: SymTab.TypeIndex>
-  576                                          (. VAR et: SymTab.TypeIndex; .)
-  577      = [ FieldIdents<rt> ":"
-  578          Type<et>                       (. IF (et # SymTab.InvalidType)
-  579                                             & SymTab.IsOpen(et) THEN
-  580                                             SemError(230)
-  581                                           END;
-  582                                           SymTab.FixPendingF(rt, et); .) ] .
-  583    FieldIdents <rt: SymTab.TypeIndex>
-  584                                          (. VAR n: SymTab.Name; .)
-  585      = GetIdent<n>                       (. IF ~SymTab.FieldPending(rt, n)
-  586                                             THEN SemError(200) END .)
-  587        { ","
-  588          GetIdent<n>                     (. IF ~SymTab.FieldPending(rt, n)
-  589                                             THEN SemError(200) END .) } .
-  590    SetType <VAR t: SymTab.TypeIndex>
-  591                                          (. VAR s: SymTab.TypeIndex; .)
-  592      = "SET"
-  593        "OF"
-  594        SimpleType<s>                     (. IF (s # SymTab.InvalidType)
-  595                                              & (SymTab.ClassOf(s) #
-  596                                                 SymTab.ClInt)
-  597                                              & (SymTab.ClassOf(s) #
-  598                                                 SymTab.ClChar)
-  599                                              & (SymTab.ClassOf(s) #
-  600                                                 SymTab.ClEnum) THEN
-  601                                              SemError(224) END;
-  602                                             t := SymTab.NewSet(s); .) .
-  603    PointerType <VAR t: SymTab.TypeIndex>
-  604                                          (. VAR b: SymTab.TypeIndex; .)
-  605      = "POINTER"
-  606        "TO"
-  607        Type<b>                           (. t := SymTab.NewPtr(b); .) .
-  608  
-  609    (* Statements: RETURN added; calls via AssignOrCall *)
-  610    StatSeq    = Stat { ";"
-  611                       Stat } .
-  612    Stat                                  (. VAR lx: INTEGER; .)
-  613      = [ AssignOrCall | IfStat | CaseStat | WhileStat
-  614        | RepeatStat | LoopStat | ForStat | WithStat | ReturnStat
-  615        | NewStat | DispStat | WriteIntStat | WriteStrStat
-  616        | "EXIT"                 (. IF MGen.TopLoop(lx) THEN
-  617                                      MGen.Jmp(lx)
-  618                                    ELSE SemError(230) END; .) ] .
-  619    AssignOrCall                          (. VAR dt, et: SymTab.TypeIndex;
-  620                                               dk: INTEGER;
-  621                                               bn: SymTab.Name;
-  622                                               lxD, lxe: MGen.LitStr;
-  623                                               vE: BOOLEAN;
-  624                                               vnE: SymTab.Name;
-  625                                               sfx: BOOLEAN;
-  626                                               okC: BOOLEAN;
-  627                                               isR, conv,
-  628                                               storable, pushedDst,
-  629                                               pushedFld: BOOLEAN;
-  630                                               dstBytes, srcBytes: CARDINAL;
-  631                                               elemDt: SymTab.TypeIndex;
-  632                                               modBare: INTEGER; .)
-  633      =                                   (. sfx := FALSE; pushedDst := FALSE;
-  634                                             pushedFld := FALSE; .)
-  635        DesignHead<dt, dk, bn, FALSE, lxD>
-  636        DesignTail<dt, dk, bn, FALSE, lxD, sfx>
-  637        ( ":="
-  638                                          (. storable :=
-  639                                               (dk = SymTab.KindVar)
-  640                                               OR (dk = SymTab.KindParam)
-  641                                               OR (dk = SymTab.KindVarPar);
-  642                                             IF (dk = SymTab.KindField)
-  643                                                & (~sfx)
-  644                                                & (dt # SymTab.InvalidType) THEN
-  645                                               MGen.WithAddr(bn);
-  646                                               pushedFld := TRUE
-  647                                             END;
-  648                                             IF storable & ~sfx
-  649                                                & (dt # SymTab.InvalidType)
-  650                                                & ((SymTab.ClassOf(dt)
-  651                                                   = SymTab.ClArray)
-  652                                                   OR (SymTab.ClassOf(dt)
-  653                                                      = SymTab.ClRecord)) THEN
-  654                                               MGen.PushAddr(bn);
-  655                                               pushedDst := TRUE
-  656                                             ELSIF ((dk = SymTab.KindVar)
-  657                                                    OR (dk
-  658                                                        = SymTab.KindParam)
-  659                                                    OR (dk
-  660                                                        = SymTab.KindVarPar)
-  661                                                    OR (dk
-  662                                                        = SymTab.KindField))
-  663                                                & sfx
-  664                                                & (dt # SymTab.InvalidType)
-  665                                                & ((SymTab.ClassOf(dt)
-  666                                                   = SymTab.ClArray)
-  667                                                   OR (SymTab.ClassOf(dt)
-  668                                                      = SymTab.ClRecord)) THEN
-  669                                               pushedDst := TRUE
-  670                                             END;
-  671                                             IF storable & ~sfx
-  672                                                & ~pushedDst THEN
-  673                                               IF (dt # SymTab.InvalidType)
-  674                                                  & (SymTab.TypeSlots(dt)
-  675                                                     > 1) THEN
-  676                                               ELSE MGen.StoreSetup(bn)
-  677                                               END
-  678                                             END; .)
-  679          Expr<et, lxe, vE, vnE>                                                  (. IF (dt # SymTab.InvalidType)
-  680                                             & (dk # SymTab.KindVar)
-  681                                             & (dk # SymTab.KindParam)
-  682                                             & (dk # SymTab.KindVarPar)
-  683                                             & (dk # SymTab.KindField)
-  684                                             & (dk # SymTab.KindImport) THEN
-  685                                             SemError(210)
-  686                                           ELSIF pushedDst THEN
-  687                                             IF et = SymTab.InvalidType THEN
-  688                                               MGen.Drop; MGen.Drop
-  689                                             ELSIF (SymTab.ClassOf(dt)
-  690                                                    = SymTab.ClArray)
-  691                                                & (SymTab.ClassOf(
-  692                                                   SymTab.ArrayElem(dt))
-  693                                                   = SymTab.ClChar)
-  694                                                & (SymTab.ClassOf(et)
-  695                                                   = SymTab.ClStr) THEN
-  696                                               srcBytes :=
-  697                                                 MGen.StrLenOf(lxe) + 1;
-  698                                               dstBytes :=
-  699                                                 SymTab.TypeSlots(dt) * 8;
-  700                                               IF srcBytes > dstBytes THEN
-  701                                                 SemError(210);
-  702                                                 MGen.Drop; MGen.Drop
-  703                                               ELSE
-  704                                                 MGen.PushBytes(srcBytes);
-  705                                                 MGen.CopyBlock
-  706                                               END
-  707                                             ELSIF ~SymTab.Assignable(et,
-  708                                                       dt) THEN
-  709                                               SemError(210);
-  710                                               MGen.Drop; MGen.Drop
-  711                                             ELSE
-  712                                               dstBytes :=
-  713                                                 SymTab.TypeSlots(dt) * 8;
-  714                                               MGen.PushBytes(dstBytes);
-  715                                               MGen.CopyBlock
-  716                                             END
-  717                                           ELSIF pushedFld THEN
-  718                                             IF et = SymTab.InvalidType THEN
-  719                                               MGen.Drop; MGen.Drop
-  720                                             ELSIF (SymTab.TypeSlots(dt) > 1) THEN
-  721                                               IF (SymTab.ClassOf(dt)
-  722                                                  = SymTab.ClArray)
-  723                                                  & (SymTab.ClassOf(
-  724                                                     SymTab.ArrayElem(dt))
-  725                                                     = SymTab.ClChar)
-  726                                                  & (SymTab.ClassOf(et)
-  727                                                     = SymTab.ClStr) THEN
-  728                                                 srcBytes :=
-  729                                                   MGen.StrLenOf(lxe) + 1;
-  730                                                 dstBytes :=
-  731                                                   SymTab.TypeSlots(dt) * 8;
-  732                                                 IF srcBytes > dstBytes THEN
-  733                                                   SemError(210);
-  734                                                   MGen.Drop; MGen.Drop
-  735                                                 ELSE
-  736                                                   MGen.PushBytes(srcBytes);
-  737                                                   MGen.CopyBlock
-  738                                                 END
-  739                                               ELSIF ~SymTab.Assignable(et,
-  740                                                         dt) THEN
-  741                                                 SemError(210);
-  742                                                 MGen.Drop; MGen.Drop
-  743                                               ELSE
-  744                                                 dstBytes :=
-  745                                                   SymTab.TypeSlots(dt) * 8;
-  746                                                 MGen.PushBytes(dstBytes);
-  747                                                 MGen.CopyBlock
-  748                                               END
-  749                                             ELSE
-  750                                               IF ~SymTab.Assignable(et,
-  751                                                         dt) THEN
-  752                                                 SemError(210);
-  753                                                 MGen.Drop; MGen.Drop
-  754                                               ELSE
-  755                                                 isR :=
-  756                                                   (SymTab.ClassOf(dt)
-  757                                                    = SymTab.ClReal);
-  758                                                 conv := isR
-  759                                                   & SymTab.IsIntFamily(et);
-  760                                                 IF conv THEN
-  761                                                   MGen.IntToReal
-  762                                                 END;
-  763                                                 IF (SymTab.ClassOf(dt)
-  764                                                    = SymTab.ClChar)
-  765                                                    OR (SymTab.ClassOf(dt)
-  766                                                       = SymTab.ClBool) THEN
-  767                                                   MGen.StoreByte
-  768                                                 ELSE MGen.StoreIndir0
-  769                                                 END
-  770                                               END
+  459                                                 SymTab.ClInt)
+  460                                              & (SymTab.ClassOf(t2) #
+  461                                                 SymTab.ClChar)
+  462                                              & (SymTab.ClassOf(t2) #
+  463                                                 SymTab.ClEnum) THEN
+  464                                              SemError(224) END; .)
+  465                        "]"
+  466                                       (. IF (t1 # SymTab.InvalidType)
+  467                                           & (t2 # SymTab.InvalidType) THEN
+  468                                             IF MGen.IsLit(lx1) THEN
+  469                                               IF SymTab.ClassOf(t1)
+  470                                                  = SymTab.ClChar THEN
+  471                                                 loI := MGen.CharOrd(lx1);
+  472                                                 lok := TRUE
+  473                                               ELSIF MGen.ParseInt(lx1, loI) THEN
+  474                                                 lok := TRUE
+  475                                               END
+  476                                             END;
+  477                                             IF MGen.IsLit(lx2) THEN
+  478                                               IF SymTab.ClassOf(t2)
+  479                                                  = SymTab.ClChar THEN
+  480                                                 hiI := MGen.CharOrd(lx2);
+  481                                                 hik := TRUE
+  482                                               ELSIF MGen.ParseInt(lx2, hiI) THEN
+  483                                                 hik := TRUE
+  484                                               END
+  485                                             END
+  486                                           END;
+  487                                          IF lok & hik THEN
+  488                                            t := SymTab.NewSubB(t1, loI, hiI)
+  489                                          ELSE
+  490                                            t := SymTab.NewSub(t1);
+  491                                            IF (t1 # SymTab.InvalidType)
+  492                                               & (t2 # SymTab.InvalidType) THEN
+  493                                              SemError(230)
+  494                                            END
+  495                                          END;
+  496                                          MGen.NoEmitExit; .) ]
+  497      | "["                               (. MGen.NoEmitEnter; lok := FALSE;
+  498                                             hik := FALSE; loI := 0; hiI := -1; .)
+  499        ConstExpr<t1, lx1>                (. IF (t1 # SymTab.InvalidType)
+  500                                              & (SymTab.ClassOf(t1) #
+  501                                                 SymTab.ClInt)
+  502                                              & (SymTab.ClassOf(t1) #
+  503                                                 SymTab.ClChar)
+  504                                              & (SymTab.ClassOf(t1) #
+  505                                                 SymTab.ClEnum) THEN
+  506                                              SemError(224) END; .)
+  507        ".."
+  508        ConstExpr<t2, lx2>                (. IF (t2 # SymTab.InvalidType)
+  509                                              & (SymTab.ClassOf(t2) #
+  510                                                 SymTab.ClInt)
+  511                                              & (SymTab.ClassOf(t2) #
+  512                                                 SymTab.ClChar)
+  513                                              & (SymTab.ClassOf(t2) #
+  514                                                 SymTab.ClEnum) THEN
+  515                                              SemError(224) END; .)
+  516        "]"                               (. IF (t1 # SymTab.InvalidType)
+  517                                             & (t2 # SymTab.InvalidType) THEN
+  518                                               IF MGen.IsLit(lx1) THEN
+  519                                                 IF SymTab.ClassOf(t1)
+  520                                                    = SymTab.ClChar THEN
+  521                                                   loI := MGen.CharOrd(lx1);
+  522                                                   lok := TRUE
+  523                                                 ELSIF MGen.ParseInt(lx1,
+  524                                                           loI) THEN
+  525                                                   lok := TRUE
+  526                                                 END
+  527                                               END;
+  528                                               IF MGen.IsLit(lx2) THEN
+  529                                                 IF SymTab.ClassOf(t2)
+  530                                                    = SymTab.ClChar THEN
+  531                                                   hiI := MGen.CharOrd(lx2);
+  532                                                   hik := TRUE
+  533                                                 ELSIF MGen.ParseInt(lx2,
+  534                                                           hiI) THEN
+  535                                                   hik := TRUE
+  536                                                 END
+  537                                               END
+  538                                             END;
+  539                                            IF lok & hik THEN
+  540                                              t := SymTab.NewSubB(t1, loI, hiI)
+  541                                            ELSE
+  542                                              t := SymTab.NewSub(t1);
+  543                                              IF (t1 # SymTab.InvalidType)
+  544                                                 & (t2 # SymTab.InvalidType) THEN
+  545                                                SemError(230)
+  546                                              END
+  547                                            END;
+  548                                             MGen.NoEmitExit; .)
+  549      | Enum<t> .
+  550    Enum <VAR t: SymTab.TypeIndex>
+  551                                          (. VAR n: SymTab.Name;
+  552                                               ord: INTEGER; .)
+  553      = "("                               (. t := SymTab.NewEnum();
+  554                                             ord := 0; .)
+  555        GetIdent<n>                       (. IF ~SymTab.Enter(n,
+  556                                               SymTab.KindConst)
+  557                                             THEN SemError(200) END;
+  558                                             SymTab.SetSymType(n, t);
+  559                                             SymTab.EnumAdd(t);
+  560                                             MGen.DeclConstInt(n, ord);
+  561                                             INC(ord); .)
+  562        { ","
+  563          GetIdent<n>                     (. IF ~SymTab.Enter(n,
+  564                                               SymTab.KindConst)
+  565                                             THEN SemError(200) END;
+  566                                             SymTab.SetSymType(n, t);
+  567                                             SymTab.EnumAdd(t);
+  568                                             MGen.DeclConstInt(n, ord);
+  569                                             INC(ord); .) }
+  570        ")" .
+  571    ArrayType <VAR t: SymTab.TypeIndex>
+  572                                          (. VAR s, s2, e: SymTab.TypeIndex;
+  573                                               idx: ARRAY [0 .. 7] OF
+  574                                                 SymTab.TypeIndex;
+  575                                               nc, kk: CARDINAL;
+  576                                               loA, hiA: INTEGER;
+  577                                               isOpenA: BOOLEAN; .)
+  578      = "ARRAY"
+  579        [ SimpleType<s>                     (. IF (s # SymTab.InvalidType)
+  580                                              & (SymTab.ClassOf(s) #
+  581                                                 SymTab.ClInt)
+  582                                              & (SymTab.ClassOf(s) #
+  583                                                 SymTab.ClChar)
+  584                                              & (SymTab.ClassOf(s) #
+  585                                                 SymTab.ClEnum) THEN
+  586                                              SemError(224) END;
+  587                                             nc := 0; isOpenA := FALSE;
+  588                                             idx[nc] := s; INC(nc); .)
+  589          { ","
+  590            SimpleType<s2>                  (. IF (s2 # SymTab.InvalidType)
+  591                                              & (SymTab.ClassOf(s2) #
+  592                                                 SymTab.ClInt)
+  593                                              & (SymTab.ClassOf(s2) #
+  594                                                 SymTab.ClChar)
+  595                                              & (SymTab.ClassOf(s2) #
+  596                                                 SymTab.ClEnum) THEN
+  597                                              SemError(224) END;
+  598                                             IF nc <= HIGH(idx) THEN
+  599                                               idx[nc] := s2; INC(nc)
+  600                                             END; .) }
+  601        |                                   (. nc := 0; isOpenA := TRUE; .) ]
+  602        "OF"
+  603        Type<e>                           (. IF isOpenA THEN
+  604                                             t := SymTab.NewOpen(e)
+  605                                           ELSE
+  606                                             t := e;
+  607                                             kk := nc;
+  608                                             WHILE kk > 0 DO
+  609                                               DEC(kk);
+  610                                               loA := SymTab.TypeLo(idx[kk]);
+  611                                               hiA := SymTab.TypeHi(idx[kk]);
+  612                                               IF SymTab.TypeLen(idx[kk]) = 0 THEN
+  613                                                 IF idx[kk]
+  614                                                    # SymTab.InvalidType THEN
+  615                                                   SemError(230)
+  616                                                 END;
+  617                                                 loA := 0; hiA := -1
+  618                                               END;
+  619                                               t := SymTab.NewArrayB(t,
+  620                                                       loA, hiA)
+  621                                             END
+  622                                           END; .) .
+  623    RecordType <VAR t: SymTab.TypeIndex>
+  624      = "RECORD"                          (. t := SymTab.NewRecord(); .)
+  625        FieldSeq<t>
+  626        "END" .
+  627    FieldSeq <rt: SymTab.TypeIndex>
+  628      = Field<rt> { ";"
+  629                    Field<rt> } .
+  630    Field <rt: SymTab.TypeIndex>
+  631                                          (. VAR et: SymTab.TypeIndex; .)
+  632      = [ FieldIdents<rt> ":"
+  633          Type<et>                       (. IF (et # SymTab.InvalidType)
+  634                                             & SymTab.IsOpen(et) THEN
+  635                                             SemError(230)
+  636                                           END;
+  637                                           SymTab.FixPendingF(rt, et); .) ] .
+  638    FieldIdents <rt: SymTab.TypeIndex>
+  639                                          (. VAR n: SymTab.Name; .)
+  640      = GetIdent<n>                       (. IF ~SymTab.FieldPending(rt, n)
+  641                                             THEN SemError(200) END .)
+  642        { ","
+  643          GetIdent<n>                     (. IF ~SymTab.FieldPending(rt, n)
+  644                                             THEN SemError(200) END .) } .
+  645    SetType <VAR t: SymTab.TypeIndex>
+  646                                          (. VAR s: SymTab.TypeIndex; .)
+  647      = "SET"
+  648        "OF"
+  649        SimpleType<s>                     (. IF (s # SymTab.InvalidType)
+  650                                              & (SymTab.ClassOf(s) #
+  651                                                 SymTab.ClInt)
+  652                                              & (SymTab.ClassOf(s) #
+  653                                                 SymTab.ClChar)
+  654                                              & (SymTab.ClassOf(s) #
+  655                                                 SymTab.ClEnum) THEN
+  656                                              SemError(224) END;
+  657                                             t := SymTab.NewSet(s); .) .
+  658    PointerType <VAR t: SymTab.TypeIndex>
+  659                                          (. VAR b: SymTab.TypeIndex; .)
+  660      = "POINTER"
+  661        "TO"
+  662        Type<b>                           (. t := SymTab.NewPtr(b); .) .
+  663  
+  664    (* Statements: RETURN added; calls via AssignOrCall *)
+  665    StatSeq    = Stat { ";"
+  666                       Stat } .
+  667    Stat                                  (. VAR lx: INTEGER; .)
+  668      = [ AssignOrCall | IfStat | CaseStat | WhileStat
+  669        | RepeatStat | LoopStat | ForStat | WithStat | ReturnStat
+  670        | NewStat | DispStat | WriteIntStat | WriteStrStat
+  671        | "EXIT"                 (. IF MGen.TopLoop(lx) THEN
+  672                                      MGen.Jmp(lx)
+  673                                    ELSE SemError(230) END; .) ] .
+  674    AssignOrCall                          (. VAR dt, et: SymTab.TypeIndex;
+  675                                               dk: INTEGER;
+  676                                               bn: SymTab.Name;
+  677                                               lxD, lxe: MGen.LitStr;
+  678                                               vE: BOOLEAN;
+  679                                               vnE: SymTab.Name;
+  680                                               sfx: BOOLEAN;
+  681                                               okC: BOOLEAN;
+  682                                               isR, conv,
+  683                                               storable, pushedDst,
+  684                                               pushedFld: BOOLEAN;
+  685                                               dstBytes, srcBytes: CARDINAL;
+  686                                               elemDt: SymTab.TypeIndex;
+  687                                               modBare: INTEGER; .)
+  688      =                                   (. sfx := FALSE; pushedDst := FALSE;
+  689                                             pushedFld := FALSE; .)
+  690        DesignHead<dt, dk, bn, FALSE, lxD>
+  691        DesignTail<dt, dk, bn, FALSE, lxD, sfx>
+  692        ( ":="
+  693                                          (. storable :=
+  694                                               (dk = SymTab.KindVar)
+  695                                               OR (dk = SymTab.KindParam)
+  696                                               OR (dk = SymTab.KindVarPar);
+  697                                             IF (dk = SymTab.KindField)
+  698                                                & (~sfx)
+  699                                                & (dt # SymTab.InvalidType) THEN
+  700                                               MGen.WithAddr(bn);
+  701                                               pushedFld := TRUE
+  702                                             END;
+  703                                             IF storable & ~sfx
+  704                                                & (dt # SymTab.InvalidType)
+  705                                                & ((SymTab.ClassOf(dt)
+  706                                                   = SymTab.ClArray)
+  707                                                   OR (SymTab.ClassOf(dt)
+  708                                                      = SymTab.ClRecord)) THEN
+  709                                               MGen.PushAddr(bn);
+  710                                               pushedDst := TRUE
+  711                                             ELSIF ((dk = SymTab.KindVar)
+  712                                                    OR (dk
+  713                                                        = SymTab.KindParam)
+  714                                                    OR (dk
+  715                                                        = SymTab.KindVarPar)
+  716                                                    OR (dk
+  717                                                        = SymTab.KindField))
+  718                                                & sfx
+  719                                                & (dt # SymTab.InvalidType)
+  720                                                & ((SymTab.ClassOf(dt)
+  721                                                   = SymTab.ClArray)
+  722                                                   OR (SymTab.ClassOf(dt)
+  723                                                      = SymTab.ClRecord)) THEN
+  724                                               pushedDst := TRUE
+  725                                             END;
+  726                                             IF storable & ~sfx
+  727                                                & ~pushedDst THEN
+  728                                               IF (dt # SymTab.InvalidType)
+  729                                                  & (SymTab.TypeSlots(dt)
+  730                                                     > 1) THEN
+  731                                               ELSE MGen.StoreSetup(bn)
+  732                                               END
+  733                                             END; .)
+  734          Expr<et, lxe, vE, vnE>                                                  (. IF (dt # SymTab.InvalidType)
+  735                                             & (dk # SymTab.KindVar)
+  736                                             & (dk # SymTab.KindParam)
+  737                                             & (dk # SymTab.KindVarPar)
+  738                                             & (dk # SymTab.KindField)
+  739                                             & (dk # SymTab.KindImport) THEN
+  740                                             SemError(210)
+  741                                           ELSIF pushedDst THEN
+  742                                             IF et = SymTab.InvalidType THEN
+  743                                               MGen.Drop; MGen.Drop
+  744                                             ELSIF (SymTab.ClassOf(dt)
+  745                                                    = SymTab.ClArray)
+  746                                                & (SymTab.ClassOf(
+  747                                                   SymTab.ArrayElem(dt))
+  748                                                   = SymTab.ClChar)
+  749                                                & (SymTab.ClassOf(et)
+  750                                                   = SymTab.ClStr) THEN
+  751                                               srcBytes :=
+  752                                                 MGen.StrLenOf(lxe) + 1;
+  753                                               dstBytes :=
+  754                                                 SymTab.TypeSlots(dt) * 8;
+  755                                               IF srcBytes > dstBytes THEN
+  756                                                 SemError(210);
+  757                                                 MGen.Drop; MGen.Drop
+  758                                               ELSE
+  759                                                 MGen.PushBytes(srcBytes);
+  760                                                 MGen.CopyBlock
+  761                                               END
+  762                                             ELSIF ~SymTab.Assignable(et,
+  763                                                       dt) THEN
+  764                                               SemError(210);
+  765                                               MGen.Drop; MGen.Drop
+  766                                             ELSE
+  767                                               dstBytes :=
+  768                                                 SymTab.TypeSlots(dt) * 8;
+  769                                               MGen.PushBytes(dstBytes);
+  770                                               MGen.CopyBlock
   771                                             END
-  772                                           ELSIF (dt # SymTab.InvalidType)
-  773                                             & ~sfx
-  774                                             & (SymTab.TypeSlots(dt) > 1) THEN
-  775                                             IF ~SymTab.Assignable(et, dt) THEN
-  776                                               SemError(210)
-  777                                             ELSE SemError(230)
-  778                                             END
-  779                                           ELSIF ~SymTab.Assignable(et, dt) THEN
-  780                                             SemError(210) END;
-  781                                           IF dk = SymTab.KindImport THEN
-  782                                             SemError(230)
-  783                                           END;
-  784                                           isR := (dt # SymTab.InvalidType)
-  785                                                  & ~pushedDst
-  786                                                  & ~pushedFld
-  787                                                  & (SymTab.ClassOf(dt)
-  788                                                     = SymTab.ClReal);
-  789                                           conv := isR
-  790                                                   & SymTab.IsIntFamily(et);
-  791                                           IF pushedDst THEN
-  792                                           ELSIF pushedFld THEN
-  793                                           ELSIF (dt # SymTab.InvalidType)
-  794                                              & sfx THEN
-  795                                             IF conv THEN
-  796                                               MGen.IntToReal
-  797                                             END;
-  798                                             IF (SymTab.ClassOf(dt)
-  799                                                = SymTab.ClChar)
-  800                                                OR (SymTab.ClassOf(dt)
-  801                                                   = SymTab.ClBool) THEN
-  802                                               MGen.StoreByte
-  803                                             ELSE MGen.StoreIndir0
-  804                                             END
-  805                                           ELSIF storable & ~sfx THEN
-  806                                             IF (dt # SymTab.InvalidType)
-  807                                                & (SymTab.TypeSlots(dt)
-  808                                                   > 1) THEN
-  809                                               MGen.Drop
-  810                                             ELSE
-  811                                               IF conv THEN
-  812                                                 MGen.IntToReal
-  813                                               END;
-  814                                               MGen.StoreFinish(bn)
-  815                                             END
-  816                                           ELSE MGen.Drop
-  817                                           END; .)
-  818        | CallTail<bn, lxD, sfx, FALSE, okC, FALSE>
-  819        |                             (. IF (SymTab.SymKind(bn)
-  820                                                = SymTab.KindModule)
-  821                                               & sfx
-  822                                               & (SymTab.StrLen(lxD) > 0) THEN
-  823                                             modBare := SymTab.ExpProc(bn,
-  824                                                              lxD);
-  825                                             IF modBare < 0 THEN
-  826                                               IF SymTab.ExpKind(bn,
-  827                                                    lxD) # -1 THEN
-  828                                                 SemError(233)
-  829                                               END
-  830                                             ELSIF SymTab.ProcNParByNum(
-  831                                                      modBare) # 0 THEN
-  832                                               SemError(233)
-  833                                             ELSE
-  834                                               MGen.CallProc(modBare);
-  835                                               IF SymTab.ProcRetByNum(
-  836                                                    modBare)
-  837                                                  # SymTab.InvalidType THEN
-  838                                                 MGen.Drop
-  839                                               END
-  840                                             END
-  841                                           ELSE
-  842                                             MGen.ActBegin(bn);
-  843                                             IF MGen.ActEnd(bn, FALSE,
-  844                                                    FALSE) # 0 THEN
-  845                                               SemError(233)
-  846                                             END
-  847                                           END; .) ) .
-  848    CallTail <pn: SymTab.Name; exp: SymTab.Name; sfx: BOOLEAN;
-  849              inExpr: BOOLEAN; VAR ok: BOOLEAN; hasDead: BOOLEAN>
-  850                                          (. VAR t: SymTab.TypeIndex;
-  851                                               lx: MGen.LitStr;
-  852                                               v: BOOLEAN;
-  853                                               vn: SymTab.Name;
-  854                                               isModP: BOOLEAN;
-  855                                               modPNum: INTEGER;
-  856                                               modErr: BOOLEAN; .)
-  857      = "("                               (. ok := FALSE; modErr := FALSE;
-  858                                             isModP :=
-  859                                               (SymTab.SymKind(pn)
-  860                                                = SymTab.KindModule)
-  861                                               & sfx
-  862                                               & (SymTab.StrLen(exp) > 0);
-  863                                             IF hasDead THEN MGen.Drop END;
-  864                                             IF isModP THEN
-  865                                               modPNum := SymTab.ExpProc(pn,
-  866                                                                exp);
-  867                                               IF (modPNum < 0)
-  868                                                  & (SymTab.SelfKind(pn,
-  869                                                       exp)
-  870                                                     = SymTab.KindProc) THEN
-  871                                                 modPNum :=
-  872                                                   SymTab.ProcNum(exp)
-  873                                               END;
-  874                                               IF modPNum < 0 THEN
-  875                                                 IF SymTab.ExpKind(pn,
-  876                                                      exp) # -1 THEN
-  877                                                   SemError(233)
-  878                                                 END;
-  879                                                 modErr := TRUE
-  880                                               ELSIF inExpr
-  881                                                  & (SymTab.ProcRetByNum(
-  882                                                       modPNum)
-  883                                                     = SymTab.InvalidType)
-  884                                               THEN
-  885                                                 SemError(233);
-  886                                                 modErr := TRUE
-  887                                               END;
-  888                                               MGen.ActBeginNum(modPNum)
-  889                                             ELSE
-  890                                               MGen.ActBegin(pn)
-  891                                             END; .)
-  892        [ Expr<t, lx, v, vn>              (. IF isModP THEN
-  893                                             IF ~modErr
-  894                                                & (MGen.ActValue(t, v, vn)
-  895                                                   # 0) THEN
-  896                                               SemError(233);
-  897                                               modErr := TRUE
-  898                                             END
-  899                                           ELSIF MGen.ActValue(t, v, vn) # 0 THEN
-  900                                             SemError(233)
-  901                                           END; .)
-  902          { "," Expr<t, lx, v, vn>        (. IF isModP THEN
-  903                                             IF ~modErr
-  904                                                & (MGen.ActValue(t, v, vn)
-  905                                                   # 0) THEN
-  906                                               SemError(233);
-  907                                               modErr := TRUE
-  908                                             END
-  909                                           ELSIF MGen.ActValue(t, v, vn) # 0 THEN
-  910                                             SemError(233)
-  911                                           END; .) } ]
-  912        ")"                               (. IF isModP THEN
-  913                                             IF ~modErr THEN
-  914                                               IF MGen.ActEndNum(modPNum,
-  915                                                    inExpr) # 0 THEN
-  916                                                 SemError(233)
-  917                                               ELSE ok := TRUE
-  918                                               END
-  919                                             END
-  920                                           ELSIF MGen.ActEnd(pn, sfx,
-  921                                                    inExpr) # 0
-  922                                           THEN SemError(233)
-  923                                           ELSE ok := TRUE
-  924                                           END; .) .
-  925    IfStat                                (. VAR t: SymTab.TypeIndex;
-  926                                               lxC: MGen.LitStr;
-  927                                               vC: BOOLEAN;
-  928                                               vnC: SymTab.Name;
-  929                                               elseL, endL: INTEGER;
-  930                                               hasElse: BOOLEAN; .)
-  931      = "IF"
-  932        Expr<t, lxC, vC, vnC>             (. IF ~SymTab.BoolCheck(t) THEN
-  933                                             SemError(214) END;
-  934                                             elseL := MGen.NewLabel();
-  935                                             endL := MGen.NewLabel();
-  936                                             MGen.Jz(elseL);
-  937                                             hasElse := FALSE; .)
-  938        "THEN"
-  939        StatSeq
-  940        { "ELSIF"                         (. MGen.Jmp(endL);
-  941                                             MGen.DefLabel(elseL); .)
-  942          Expr<t, lxC, vC, vnC>           (. IF ~SymTab.BoolCheck(t) THEN
-  943                                             SemError(214) END;
-  944                                             elseL := MGen.NewLabel();
-  945                                             MGen.Jz(elseL); .)
-  946          "THEN"
-  947          StatSeq }
-  948        [ "ELSE"                          (. MGen.Jmp(endL);
-  949                                             MGen.DefLabel(elseL);
-  950                                             hasElse := TRUE; .)
-  951          StatSeq ]
-  952        "END"                             (. IF ~hasElse THEN
-  953                                             MGen.DefLabel(elseL)
-  954                                           END;
-  955                                           MGen.DefLabel(endL); .) .
-  956    CaseStat                              (. VAR st: SymTab.TypeIndex;
-  957                                               lxS: MGen.LitStr;
-  958                                               vS: BOOLEAN;
-  959                                               vnS: SymTab.Name;
-  960                                               tmp, endL: INTEGER; .)
-  961      = "CASE"
-  962        Expr<st, lxS, vS, vnS>            (. tmp := MGen.TempGlobal();
-  963                                             MGen.StoreTemp(tmp);
-  964                                             endL := MGen.NewLabel(); .)
-  965        "OF"
-  966        Case<st, tmp, endL> { "|"
-  967                   Case<st, tmp, endL> }
-  968        [ "ELSE"
-  969          StatSeq ]
-  970        "END"                             (. MGen.DefLabel(endL); .) .
-  971    Case <sel: SymTab.TypeIndex; tmp: INTEGER; endL: INTEGER>
-  972                                          (. VAR lB, lN: INTEGER; .)
-  973      = [ LabelList<sel, tmp, lB, lN> ":" (. MGen.DefLabel(lB); .)
-  974          StatSeq                         (. MGen.Jmp(endL);
-  975                                             MGen.DefLabel(lN); .) ] .
-  976    LabelList <sel: SymTab.TypeIndex; tmp: INTEGER;
-  977               VAR lB: INTEGER; VAR lN: INTEGER>
-  978      =                                   (. lB := MGen.NewLabel();
-  979                                             lN := MGen.NewLabel(); .)
-  980        Labels<sel, tmp, lB> { ","
-  981                      Labels<sel, tmp, lB> }
-  982                                          (. MGen.Jmp(lN); .) .
-  983    Labels <sel: SymTab.TypeIndex; tmp: INTEGER; bodyL: INTEGER>
-  984                                          (. VAR t, t2: SymTab.TypeIndex;
-  985                                               lx1, lx2: MGen.LitStr;
-  986                                               v1, v2: BOOLEAN;
-  987                                               vn1, vn2: SymTab.Name;
-  988                                               ta, tb, chunk: INTEGER;
-  989                                               r, hasRange: BOOLEAN; .)
-  990      = ConstExpr<t, lx1>                 (. IF ~SymTab.EqCheck(t, sel) THEN
-  991                                             SemError(213) END;
-  992                                             r := (SymTab.ClassOf(sel)
-  993                                                   = SymTab.ClReal)
-  994                                                  & (SymTab.ClassOf(t)
-  995                                                     = SymTab.ClReal);
-  996                                             ta := MGen.TempGlobal();
-  997                                             MGen.StoreTemp(ta);
-  998                                             hasRange := FALSE; .)
-  999        [ ".."
- 1000          ConstExpr<t2, lx2>              (. IF ~SymTab.EqCheck(t2, sel) THEN
- 1001                                             SemError(213) END;
- 1002                                             tb := MGen.TempGlobal();
- 1003                                             MGen.StoreTemp(tb);
- 1004                                             hasRange := TRUE; .) ]
- 1005                                          (. IF hasRange THEN
- 1006                                               MGen.LoadTemp(tmp);
- 1007                                               MGen.LoadTemp(ta);
- 1008                                               IF r THEN MGen.RealGe
- 1009                                               ELSE MGen.IGe END;
- 1010                                               MGen.LoadTemp(tmp);
- 1011                                               MGen.LoadTemp(tb);
- 1012                                               IF r THEN MGen.RealLe
- 1013                                               ELSE MGen.ILe END;
- 1014                                               MGen.And
- 1015                                             ELSE
- 1016                                               MGen.LoadTemp(tmp);
- 1017                                               MGen.LoadTemp(ta);
- 1018                                               IF r THEN MGen.RealEq
- 1019                                               ELSE MGen.Eq END
- 1020                                             END;
- 1021                                             chunk := MGen.NewLabel();
- 1022                                             MGen.Jz(chunk);
- 1023                                             MGen.Jmp(bodyL);
- 1024                                             MGen.DefLabel(chunk); .) .
- 1025    WhileStat                             (. VAR t: SymTab.TypeIndex;
- 1026                                               lxC: MGen.LitStr;
- 1027                                               vC: BOOLEAN;
- 1028                                               vnC: SymTab.Name;
- 1029                                               topL, endL: INTEGER; .)
- 1030      = "WHILE"                           (. topL := MGen.NewLabel();
- 1031                                             endL := MGen.NewLabel();
- 1032                                             MGen.DefLabel(topL); .)
- 1033        Expr<t, lxC, vC, vnC>             (. IF ~SymTab.BoolCheck(t) THEN
- 1034                                             SemError(214) END;
- 1035                                             MGen.Jz(endL); .)
- 1036        "DO"
- 1037        StatSeq
- 1038        "END"                             (. MGen.Jmp(topL);
- 1039                                             MGen.DefLabel(endL); .) .
- 1040    RepeatStat                            (. VAR t: SymTab.TypeIndex;
- 1041                                               lxC: MGen.LitStr;
- 1042                                               vC: BOOLEAN;
- 1043                                               vnC: SymTab.Name;
- 1044                                               topL: INTEGER; .)
- 1045      = "REPEAT"                          (. topL := MGen.NewLabel();
- 1046                                             MGen.DefLabel(topL); .)
- 1047        StatSeq
- 1048        "UNTIL"
- 1049        Expr<t, lxC, vC, vnC>             (. IF ~SymTab.BoolCheck(t) THEN
- 1050                                             SemError(214) END;
- 1051                                             MGen.Jz(topL); .) .
- 1052    LoopStat                              (. VAR topL, exitL: INTEGER; .)
- 1053      = "LOOP"                            (. topL := MGen.NewLabel();
- 1054                                             exitL := MGen.NewLabel();
- 1055                                             MGen.DefLabel(topL);
- 1056                                             MGen.PushLoop(exitL); .)
- 1057        StatSeq
- 1058        "END"                             (. MGen.Jmp(topL);
- 1059                                             MGen.DefLabel(exitL);
- 1060                                             MGen.PopLoop; .) .
- 1061    ForStat                               (. VAR n, lv: SymTab.Name;
- 1062                                               fk: INTEGER;
- 1063                                               lo, hi: SymTab.TypeIndex;
- 1064                                               lxLo, lxHi: MGen.LitStr;
- 1065                                               vLo, vHi: BOOLEAN;
- 1066                                               vnLo, vnHi: SymTab.Name;
- 1067                                               byV, ht: INTEGER;
- 1068                                               lTop, lChk, lEnd: INTEGER;
- 1069                                               neg, storable: BOOLEAN; .)
- 1070      = "FOR"
- 1071        GetIdent<n>                       (. IF ~SymTab.Lookup(n) THEN
- 1072                                              SemError(201);
- 1073                                              fk := -1
- 1074                                            ELSIF (SymTab.SymKind(n) #
- 1075                                                   SymTab.KindVar)
- 1076                                              & (SymTab.SymKind(n) #
- 1077                                                 SymTab.KindParam)
- 1078                                              & (SymTab.SymKind(n) #
- 1079                                                 SymTab.KindVarPar)
- 1080                                              & (SymTab.SymKind(n) #
- 1081                                                 SymTab.KindField) THEN
- 1082                                              SemError(220);
- 1083                                              fk := -1
- 1084                                            ELSIF (SymTab.SymType(n) #
- 1085                                                   SymTab.InvalidType)
- 1086                                              & ~SymTab.IsIntFamily(
- 1087                                                  SymTab.SymType(n)) THEN
- 1088                                              SemError(220);
- 1089                                              fk := -1
- 1090                                            ELSE
- 1091                                              fk := SymTab.SymKind(n)
- 1092                                            END;
- 1093                                            MGen.CopyName(n, lv);
- 1094                                            storable := (fk = SymTab.KindVar)
- 1095                                              OR (fk = SymTab.KindParam)
- 1096                                              OR (fk = SymTab.KindVarPar);
- 1097                                            IF storable THEN
- 1098                                              MGen.StoreSetup(lv)
- 1099                                            END; .)
- 1100        ":="
- 1101        Expr<lo, lxLo, vLo, vnLo>         (. IF (lo # SymTab.InvalidType)
- 1102                                             & ~SymTab.IsIntFamily(lo) THEN
- 1103                                             SemError(220) END;
- 1104                                             IF storable THEN
- 1105                                               MGen.StoreFinish(lv)
- 1106                                             ELSE MGen.Drop
- 1107                                             END; .)
- 1108        "TO"
- 1109        Expr<hi, lxHi, vHi, vnHi>         (. IF (hi # SymTab.InvalidType)
- 1110                                             & ~SymTab.IsIntFamily(hi) THEN
- 1111                                             SemError(220) END;
- 1112                                             ht := MGen.TempGlobal();
- 1113                                             MGen.StoreTemp(ht);
- 1114                                             byV := 1; neg := FALSE; .)
- 1115        [ "BY"
- 1116          ByLit<byV>                      (. neg := byV < 0; .) ]
- 1117        "DO"                              (. lTop := MGen.NewLabel();
- 1118                                             lChk := MGen.NewLabel();
- 1119                                             lEnd := MGen.NewLabel();
- 1120                                             MGen.Jmp(lChk);
- 1121                                             MGen.DefLabel(lTop); .)
- 1122        StatSeq
- 1123        "END"                             (. MGen.PushVar(lv);
- 1124                                             MGen.PushInt(byV);
- 1125                                             MGen.Add;
- 1126                                             IF storable THEN
- 1127                                               MGen.StoreFinish(lv)
- 1128                                             ELSE MGen.Drop
- 1129                                             END;
- 1130                                             MGen.DefLabel(lChk);
- 1131                                             MGen.PushVar(lv);
- 1132                                             MGen.LoadTemp(ht);
- 1133                                             IF neg THEN MGen.IGe
- 1134                                             ELSE MGen.ILe END;
- 1135                                             MGen.Jz(lEnd);
- 1136                                             MGen.Jmp(lTop);
- 1137                                             MGen.DefLabel(lEnd); .) .
- 1138    ByLit <VAR v: INTEGER>                (. VAR s: ARRAY [0 .. 255] OF CHAR; .)
- 1139      = integer                           (. LexString(s);
- 1140                                             IF ~MGen.ParseInt(s, v) THEN
- 1141                                               v := 1
- 1142                                             END; .)
- 1143      | "-" integer                       (. LexString(s);
- 1144                                             IF MGen.ParseInt(s, v) THEN
- 1145                                               v := -v
- 1146                                             ELSE v := -1
- 1147                                             END; .) .
- 1148    WithStat                              (. VAR dt: SymTab.TypeIndex;
- 1149                                               dk: INTEGER;
- 1150                                               bnW: SymTab.Name;
- 1151                                               lxW: MGen.LitStr;
- 1152                                               sfxW: BOOLEAN;
- 1153                                               pushed: BOOLEAN; .)
- 1154      = "WITH"
- 1155        DesignHead<dt, dk, bnW, FALSE, lxW>
- 1156        DesignTail<dt, dk, bnW, FALSE, lxW, sfxW>
- 1157                                        (. pushed := FALSE;
- 1158                                             IF dt = SymTab.InvalidType THEN
- 1159                                               IF sfxW THEN MGen.Drop END
- 1160                                             ELSIF SymTab.ClassOf(dt)
- 1161                                                    # SymTab.ClRecord THEN
- 1162                                               SemError(215);
- 1163                                               IF sfxW THEN MGen.Drop END
- 1164                                             ELSE
- 1165                                               IF ~sfxW THEN
- 1166                                                 IF (dk
- 1167                                                    = SymTab.KindVar)
- 1168                                                    OR (dk
- 1169                                                       = SymTab.KindParam)
- 1170                                                    OR (dk
- 1171                                                    = SymTab.KindVarPar) THEN
- 1172                                                   MGen.PushAddr(bnW)
- 1173                                                 ELSIF dk
- 1174                                                   = SymTab.KindField THEN
- 1175                                                   MGen.WithAddr(bnW)
- 1176                                                 ELSE MGen.PushInt(0)
- 1177                                                 END
- 1178                                               END;
- 1179                                               MGen.WithEnter(dt);
- 1180                                               pushed :=
- 1181                                                 SymTab.PushRecord(dt);
- 1182                                               IF ~pushed THEN
- 1183                                                 SemError(215)
- 1184                                               END
- 1185                                             END; .)
- 1186        "DO"
- 1187        StatSeq
- 1188        "END"                             (. IF pushed THEN
- 1189                                               SymTab.PopScope;
- 1190                                               MGen.WithExit
- 1191                                             END; .) .
- 1192    ReturnStat                            (. VAR t: SymTab.TypeIndex;
- 1193                                               lx: MGen.LitStr;
- 1194                                               v: BOOLEAN;
- 1195                                               vn: SymTab.Name;
- 1196                                               hasE, doRet, conv: BOOLEAN; .)
- 1197      = "RETURN"                          (. hasE := FALSE; .)
- 1198        [ Expr<t, lx, v, vn>              (. hasE := TRUE;
- 1199                                             doRet := FALSE;
- 1200                                             IF ~SymTab.InProc() THEN
- 1201                                               SemError(232)
- 1202                                             ELSIF ~SymTab.InFunction() THEN
- 1203                                               SemError(232)
- 1204                                             ELSIF ~SymTab.Assignable(
- 1205                                                       t, SymTab.CurRet()) THEN
- 1206                                               SemError(232)
- 1207                                             ELSE doRet := TRUE
- 1208                                             END;
- 1209                                             conv := doRet
- 1210                                                     & SymTab.IsIntFamily(t)
- 1211                                                     & (SymTab.ClassOf(
- 1212                                                          SymTab.CurRet())
- 1213                                                        = SymTab.ClReal);
- 1214                                             IF doRet THEN
- 1215                                               IF conv THEN
- 1216                                                 MGen.IntToReal
- 1217                                               END;
- 1218                                               MGen.Leave(
- 1219                                                 SymTab.CurNPar(), TRUE)
- 1220                                             ELSE MGen.Drop
- 1221                                             END; .) ]
- 1222                                           (. IF ~hasE THEN
- 1223                                               IF ~SymTab.InProc() THEN
- 1224                                                 SemError(232)
- 1225                                               ELSIF SymTab.InFunction() THEN
- 1226                                                 SemError(232)
- 1227                                               ELSE MGen.Leave(
- 1228                                                 SymTab.CurNPar(), FALSE)
- 1229                                               END
- 1230                                             END; .) .
- 1231    NewStat                               (. VAR dt: SymTab.TypeIndex;
- 1232                                               dk: INTEGER;
- 1233                                               bnN: SymTab.Name;
- 1234                                               lxN: MGen.LitStr;
- 1235                                               sfxN: BOOLEAN;
- 1236                                               baseT: SymTab.TypeIndex;
- 1237                                               slN: CARDINAL; .)
- 1238      = "NEW"
- 1239        "(" DesignHead<dt, dk, bnN, FALSE, lxN>
- 1240            DesignTail<dt, dk, bnN, FALSE, lxN, sfxN>
- 1241        ")"                               (. IF dt = SymTab.InvalidType THEN
- 1242                                             IF sfxN THEN MGen.Drop END
- 1243                                           ELSIF SymTab.ClassOf(dt)
- 1244                                                  # SymTab.ClPtr THEN
- 1245                                             SemError(219);
- 1246                                             IF sfxN THEN MGen.Drop END
- 1247                                           ELSE
- 1248                                             baseT := SymTab.PtrBase(dt);
- 1249                                             slN := SymTab.TypeSlots(baseT);
- 1250                                             IF slN = 0 THEN
- 1251                                               SemError(230);
- 1252                                               slN := 1
- 1253                                             END;
- 1254                                             IF ~sfxN THEN
- 1255                                               IF (dk = SymTab.KindVar)
- 1256                                                  OR (dk
- 1257                                                      = SymTab.KindParam)
- 1258                                                  OR (dk
- 1259                                                   = SymTab.KindVarPar) THEN
- 1260                                                 MGen.PushAddr(bnN)
- 1261                                               ELSIF dk
- 1262                                                 = SymTab.KindField THEN
- 1263                                                 MGen.WithAddr(bnN)
- 1264                                               ELSE MGen.PushInt(0)
- 1265                                               END
- 1266                                             END;
- 1267                                             MGen.PushBytes(slN * 8);
- 1268                                             MGen.AllocOp
- 1269                                           END; .) .
- 1270    DispStat                              (. VAR dt: SymTab.TypeIndex;
- 1271                                               dk: INTEGER;
- 1272                                               bnD: SymTab.Name;
- 1273                                               lxD: MGen.LitStr;
- 1274                                               sfxD: BOOLEAN;
- 1275                                               baseT: SymTab.TypeIndex;
- 1276                                               slD: CARDINAL; .)
- 1277      = "DISPOSE"
- 1278        "(" DesignHead<dt, dk, bnD, FALSE, lxD>
- 1279            DesignTail<dt, dk, bnD, FALSE, lxD, sfxD>
- 1280        ")"                               (. IF dt = SymTab.InvalidType THEN
- 1281                                             IF sfxD THEN MGen.Drop END
- 1282                                           ELSIF SymTab.ClassOf(dt)
- 1283                                                  # SymTab.ClPtr THEN
- 1284                                             SemError(219);
- 1285                                             IF sfxD THEN MGen.Drop END
- 1286                                           ELSE
- 1287                                             baseT := SymTab.PtrBase(dt);
- 1288                                             slD := SymTab.TypeSlots(baseT);
- 1289                                             IF slD = 0 THEN
- 1290                                               SemError(230);
- 1291                                               slD := 1
- 1292                                             END;
- 1293                                             IF ~sfxD THEN
- 1294                                               IF (dk = SymTab.KindVar)
- 1295                                                  OR (dk
- 1296                                                      = SymTab.KindParam)
- 1297                                                  OR (dk
- 1298                                                   = SymTab.KindVarPar) THEN
- 1299                                                 MGen.PushAddr(bnD)
- 1300                                               ELSIF dk
- 1301                                                 = SymTab.KindField THEN
- 1302                                                 MGen.WithAddr(bnD)
- 1303                                               ELSE MGen.PushInt(0)
- 1304                                               END
- 1305                                             END;
- 1306                                             MGen.PushBytes(slD * 8);
- 1307                                             MGen.DeallocOp
- 1308                                           END; .) .
- 1309    WriteIntStat                          (. VAR t: SymTab.TypeIndex;
- 1310                                               lx: MGen.LitStr;
- 1311                                               v: BOOLEAN;
- 1312                                               vn: SymTab.Name; .)
- 1313      = "WriteInt"
- 1314        "(" Expr<t, lx, v, vn> ")"        (. IF t = SymTab.InvalidType THEN
- 1315                                             MGen.Drop
- 1316                                           ELSIF ~SymTab.IsIntFamily(t) THEN
- 1317                                             SemError(210);
- 1318                                             MGen.Drop
- 1319                                           ELSE
- 1320                                             MGen.CallPrint
- 1321                                           END; .) .
- 1322    WriteStrStat                          (. VAR t: SymTab.TypeIndex;
- 1323                                               lx: MGen.LitStr;
- 1324                                               v: BOOLEAN;
- 1325                                               vn: SymTab.Name; .)
- 1326      = "WriteString"
- 1327        "(" Expr<t, lx, v, vn> ")"        (. IF t = SymTab.InvalidType THEN
- 1328                                             MGen.Drop
- 1329                                           ELSIF (SymTab.ClassOf(t)
- 1330                                                  = SymTab.ClStr) THEN
- 1331                                             MGen.PushInt(1);
- 1332                                             MGen.SysCall
- 1333                                           ELSIF (SymTab.ClassOf(t)
- 1334                                                  = SymTab.ClArray)
- 1335                                              & (SymTab.ClassOf(
- 1336                                                 SymTab.ArrayElem(t))
- 1337                                                 = SymTab.ClChar) THEN
- 1338                                             MGen.PushInt(1);
- 1339                                             MGen.SysCall
- 1340                                           ELSE
- 1341                                             SemError(210);
- 1342                                             MGen.Drop
- 1343                                           END; .) .
- 1344  
- 1345    (* Expressions: Designator without ActualParameters (calls use
- 1346       CallTail). Each expression synthesizes its SymTab type in t,
- 1347       the source text in lx for single literals ("" otherwise), and
- 1348       whether it is a plain variable (v/vn) for VAR actuals.
- 1349       Values travel on the MC64 stack. *)
- 1350    DesignHead <VAR t: SymTab.TypeIndex; VAR k: INTEGER;
- 1351                VAR bn: SymTab.Name; doLoad: BOOLEAN; VAR lx: MGen.LitStr>
- 1352                                          (. VAR n: SymTab.Name;
- 1353                                               cls: INTEGER; .)
- 1354      = GetIdent<n>                       (. MGen.CopyName(n, bn);
- 1355                                             lx[0] := 0C;
- 1356                                             IF ~SymTab.Lookup(n) THEN
- 1357                                               SemError(201);
- 1358                                               t := SymTab.InvalidType; k := -1;
- 1359                                               IF doLoad THEN
- 1360                                                 MGen.PushInt(0)
- 1361                                               END
- 1362                                             ELSE
- 1363                                               t := SymTab.SymType(n);
- 1364                                               k := SymTab.SymKind(n);
- 1365                                               IF k = SymTab.KindConst THEN
- 1366                                                 IF SymTab.Equal(n, "TRUE") THEN
- 1367                                                   t := SymTab.BoolType();
- 1368                                                   MGen.CopyName("TRUE", lx);
- 1369                                                   IF doLoad THEN
- 1370                                                     MGen.PushInt(1)
- 1371                                                   END
- 1372                                                 ELSIF SymTab.Equal(n,
- 1373                                                         "FALSE") THEN
- 1374                                                   t := SymTab.BoolType();
- 1375                                                   MGen.CopyName("FALSE", lx);
- 1376                                                   IF doLoad THEN
- 1377                                                     MGen.PushInt(0)
- 1378                                                   END
- 1379                                                 ELSE
- 1380                                                   cls :=
- 1381                                                     SymTab.ClassOf(t);
- 1382                                                   IF (t #
- 1383                                                       SymTab.InvalidType)
- 1384                                                      & (cls # SymTab.ClStr)
- 1385                                                      & ((cls = SymTab.ClInt)
- 1386                                                      OR (cls = SymTab.ClReal)
- 1387                                                      OR (cls = SymTab.ClBool)
- 1388                                                      OR (cls = SymTab.ClChar)
- 1389                                                      OR (cls
- 1390                                                          = SymTab.ClEnum)) THEN
- 1391                                                     IF doLoad THEN
- 1392                                                       MGen.LoadVar(n)
- 1393                                                     END
- 1394                                                   ELSIF doLoad THEN
- 1395                                                     MGen.PushInt(0)
- 1396                                                   END
- 1397                                                 END
- 1398                                                ELSIF (k = SymTab.KindVar)
- 1399                                                   OR (k = SymTab.KindParam)
- 1400                                                   OR (k
- 1401                                                       = SymTab.KindVarPar) THEN
- 1402                                                  cls := SymTab.ClassOf(t);
- 1403                                                  IF (cls = SymTab.ClInt)
- 1404                                                     OR (cls = SymTab.ClReal)
- 1405                                                     OR (cls = SymTab.ClBool)
- 1406                                                     OR (cls = SymTab.ClChar)
- 1407                                                     OR (cls
- 1408                                                         = SymTab.ClEnum)
- 1409                                                     OR (cls
- 1410                                                         = SymTab.ClSet)
- 1411                                                     OR (cls
- 1412                                                         = SymTab.ClPtr) THEN
- 1413                                                    IF doLoad THEN
- 1414                                                      MGen.PushVar(n)
- 1415                                                    END
- 1416                                                  ELSIF (cls
- 1417                                                         = SymTab.ClArray)
- 1418                                                     OR (cls
- 1419                                                         = SymTab.ClRecord) THEN
- 1420                                                    IF doLoad THEN
- 1421                                                      MGen.PushAddr(n)
- 1422                                                    END
- 1423                                                  ELSIF t
- 1424                                                    = SymTab.InvalidType THEN
- 1425                                                    IF doLoad THEN
- 1426                                                      MGen.PushInt(0)
- 1427                                                    END
- 1428                                                  ELSE SemError(230);
- 1429                                                    IF doLoad THEN
- 1430                                                      MGen.PushInt(0)
- 1431                                                    END
- 1432                                                  END
- 1433                                               ELSE
- 1434                                                 IF doLoad THEN
- 1435                                                   IF k = SymTab.KindField THEN
- 1436                                                     MGen.WithAddr(n);
- 1437                                                     cls := SymTab.ClassOf(t);
- 1438                                                     IF (t
- 1439                                                        = SymTab.InvalidType)
- 1440                                                        OR (cls
- 1441                                                           = SymTab.ClArray)
- 1442                                                        OR (cls
- 1443                                                           = SymTab.ClRecord) THEN
- 1444                                                     ELSE
- 1445                                                       IF (cls
- 1446                                                          = SymTab.ClChar)
- 1447                                                          OR (cls
- 1448                                                             = SymTab.ClBool) THEN
- 1449                                                         MGen.LoadByte
- 1450                                                       ELSE MGen.LoadIndir
- 1451                                                       END
- 1452                                                     END
- 1453                                                   ELSE MGen.PushInt(0)
- 1454                                                   END
- 1455                                                 END;
- 1456                                                 IF k = SymTab.KindField THEN
- 1457                                                 ELSIF k
- 1458                                                       = SymTab.KindImport THEN
- 1459                                                   SemError(230)
- 1460                                                 END
- 1461                                               END
- 1462                                             END; .) .
- 1463    DesignTail <VAR t: SymTab.TypeIndex; VAR k: INTEGER;
- 1464                VAR bn: SymTab.Name; doLoad: BOOLEAN; VAR lx: MGen.LitStr;
- 1465                VAR sfx: BOOLEAN>
- 1466                                          (. VAR m: SymTab.Name;
- 1467                                               it: SymTab.TypeIndex;
- 1468                                               lxI: MGen.LitStr;
- 1469                                               vI: BOOLEAN;
- 1470                                               vnI: SymTab.Name;
- 1471                                               loA: INTEGER;
- 1472                                               elemT: SymTab.TypeIndex;
- 1473                                               esl, ebytes: CARDINAL;
- 1474                                               firstT: BOOLEAN;
- 1475                                               clsI: INTEGER;
- 1476                                               sk: INTEGER;
- 1477                                               qM: SymTab.Name; .)
- 1478      =                                   (. sfx := FALSE; .)
- 1479        { "."                             (. firstT := ~sfx;
- 1480                                             sfx := TRUE; lx[0] := 0C;
- 1481                                             IF ~doLoad & firstT THEN
- 1482                                               IF (k = SymTab.KindVar)
- 1483                                                  OR (k = SymTab.KindParam)
- 1484                                                  OR (k
- 1485                                                      = SymTab.KindVarPar) THEN
- 1486                                                 MGen.PushAddr(bn)
- 1487                                               ELSIF k
- 1488                                                 = SymTab.KindField THEN
- 1489                                                 MGen.WithAddr(bn)
- 1490                                               ELSIF k
- 1491                                                 = SymTab.KindModule THEN
- 1492                                               ELSE MGen.PushInt(0)
- 1493                                               END
- 1494                                             END; .)
- 1495          GetIdent<m>                     (. IF (k = SymTab.KindModule) THEN
- 1496                                               IF SymTab.ExpKind(bn, m) = -1 THEN
- 1497                                                 sk := SymTab.SelfKind(bn, m);
- 1498                                                 IF sk = SymTab.KindProc THEN
- 1499                                                   MGen.CopyName(m, lx);
- 1500                                                   t := SymTab.InvalidType;
- 1501                                                   IF doLoad THEN
- 1502                                                     MGen.Drop; MGen.PushInt(0)
- 1503                                                   ELSIF firstT THEN
- 1504                                                   ELSE MGen.Drop
- 1505                                                   END
- 1506                                                 ELSIF sk # -1 THEN
- 1507                                                   t := SymTab.SymType(m);
- 1508                                                   k := sk;
- 1509                                                   SymTab.SelfQual(m, qM);
- 1510                                                   IF doLoad THEN
- 1511                                                     MGen.Drop;
- 1512                                                     MGen.GlobalAddr(qM)
- 1513                                                   ELSE
- 1514                                                     IF firstT THEN
- 1515                                                     ELSE MGen.Drop
- 1516                                                     END;
- 1517                                                     MGen.GlobalAddr(qM)
- 1518                                                   END
- 1519                                                 ELSE
- 1520                                                   SemError(201);
- 1521                                                   MGen.CopyName(m, lx);
- 1522                                                   t := SymTab.InvalidType;
- 1523                                                   IF doLoad THEN
- 1524                                                     MGen.Drop; MGen.PushInt(0)
- 1525                                                   ELSIF firstT THEN
- 1526                                                   ELSE MGen.Drop
- 1527                                                   END
- 1528                                                 END
- 1529                                               ELSIF SymTab.ExpKind(bn, m)
- 1530                                                      = SymTab.KindProc THEN
- 1531                                                 MGen.CopyName(m, lx);
- 1532                                                 t := SymTab.InvalidType;
- 1533                                                 IF doLoad THEN
- 1534                                                   MGen.Drop; MGen.PushInt(0)
- 1535                                                 ELSIF firstT THEN
- 1536                                                 ELSE MGen.Drop
- 1537                                                 END
- 1538                                               ELSE
- 1539                                                 t := SymTab.ExpType(bn, m);
- 1540                                                 k := SymTab.ExpKind(bn, m);
- 1541                                                 SymTab.ExpQual(bn, m, qM);
- 1542                                                 IF doLoad THEN
- 1543                                                   MGen.Drop;
- 1544                                                   MGen.GlobalAddr(qM)
- 1545                                                 ELSE
- 1546                                                   IF firstT THEN
- 1547                                                   ELSE MGen.Drop
- 1548                                                   END;
- 1549                                                   MGen.GlobalAddr(qM)
- 1550                                                 END
- 1551                                               END
- 1552                                             ELSIF t = SymTab.InvalidType THEN
- 1553                                               IF ~doLoad & firstT THEN
- 1554                                                 MGen.Drop
- 1555                                               ELSIF doLoad THEN
- 1556                                                 MGen.Drop; MGen.PushInt(0)
- 1557                                               END
- 1558                                             ELSIF SymTab.ClassOf(t) #
- 1559                                                   SymTab.ClRecord THEN
- 1560                                               SemError(215);
- 1561                                               t := SymTab.InvalidType;
- 1562                                               IF doLoad THEN
- 1563                                                 MGen.Drop; MGen.PushInt(0)
- 1564                                               ELSIF firstT THEN
- 1565                                                 MGen.Drop
- 1566                                               END
- 1567                                             ELSIF ~SymTab.FieldExists(t, m) THEN
- 1568                                               SemError(216);
- 1569                                               t := SymTab.InvalidType;
- 1570                                               IF doLoad THEN
- 1571                                                 MGen.Drop; MGen.PushInt(0)
- 1572                                               ELSIF firstT THEN
- 1573                                                 MGen.Drop
- 1574                                               END
- 1575                                             ELSE
- 1576                                               loA := SymTab.FieldOffset(t, m);
- 1577                                               elemT := SymTab.FieldType(t, m);
- 1578                                               IF loA < 0 THEN
- 1579                                                 SemError(216);
- 1580                                                 t := SymTab.InvalidType;
- 1581                                                 IF doLoad THEN
- 1582                                                   MGen.Drop; MGen.PushInt(0)
- 1583                                                 ELSIF firstT THEN
- 1584                                                   MGen.Drop
- 1585                                                 END
- 1586                                               ELSE
- 1587                                                 MGen.FieldAdd(
- 1588                                                   VAL(CARDINAL, loA));
- 1589                                                 t := elemT
- 1590                                               END
- 1591                                             END; .)
- 1592        | "["                             (. firstT := ~sfx;
- 1593                                             sfx := TRUE; lx[0] := 0C;
- 1594                                             IF ~doLoad & firstT THEN
- 1595                                               IF (k = SymTab.KindVar)
- 1596                                                  OR (k = SymTab.KindParam)
- 1597                                                  OR (k
- 1598                                                      = SymTab.KindVarPar) THEN
- 1599                                                 MGen.PushAddr(bn)
- 1600                                               ELSIF k
- 1601                                                 = SymTab.KindField THEN
- 1602                                                 MGen.WithAddr(bn)
- 1603                                               ELSE MGen.PushInt(0)
- 1604                                               END
- 1605                                             END; .)
- 1606          Expr<it, lxI, vI, vnI>          (. IF t = SymTab.InvalidType THEN
- 1607                                             MGen.Drop;
- 1608                                             IF doLoad THEN
- 1609                                               MGen.Drop; MGen.PushInt(0)
- 1610                                             ELSE
- 1611                                               IF ~firstT THEN
- 1612                                               ELSE MGen.Drop
- 1613                                               END
- 1614                                             END
- 1615                                           ELSIF SymTab.ClassOf(t) #
- 1616                                                   SymTab.ClArray THEN
- 1617                                             SemError(217);
- 1618                                             t := SymTab.InvalidType;
- 1619                                             MGen.Drop;
- 1620                                             IF doLoad THEN
- 1621                                               MGen.Drop; MGen.PushInt(0)
- 1622                                             ELSE
- 1623                                               IF ~firstT THEN
- 1624                                               ELSE MGen.Drop
- 1625                                               END
- 1626                                             END
- 1627                                           ELSE
- 1628                                             clsI := SymTab.ClassOf(it);
- 1629                                             IF (it
- 1630                                                # SymTab.InvalidType)
- 1631                                                & (clsI # SymTab.ClInt)
- 1632                                                & (clsI # SymTab.ClChar)
- 1633                                                & (clsI # SymTab.ClEnum)
- 1634                                                & (clsI
- 1635                                                   # SymTab.ClBool) THEN
- 1636                                               SemError(218);
- 1637                                               t := SymTab.InvalidType;
- 1638                                               MGen.Drop;
- 1639                                               IF doLoad THEN
- 1640                                                 MGen.Drop; MGen.PushInt(0)
+  772                                           ELSIF pushedFld THEN
+  773                                             IF et = SymTab.InvalidType THEN
+  774                                               MGen.Drop; MGen.Drop
+  775                                             ELSIF (SymTab.TypeSlots(dt) > 1) THEN
+  776                                               IF (SymTab.ClassOf(dt)
+  777                                                  = SymTab.ClArray)
+  778                                                  & (SymTab.ClassOf(
+  779                                                     SymTab.ArrayElem(dt))
+  780                                                     = SymTab.ClChar)
+  781                                                  & (SymTab.ClassOf(et)
+  782                                                     = SymTab.ClStr) THEN
+  783                                                 srcBytes :=
+  784                                                   MGen.StrLenOf(lxe) + 1;
+  785                                                 dstBytes :=
+  786                                                   SymTab.TypeSlots(dt) * 8;
+  787                                                 IF srcBytes > dstBytes THEN
+  788                                                   SemError(210);
+  789                                                   MGen.Drop; MGen.Drop
+  790                                                 ELSE
+  791                                                   MGen.PushBytes(srcBytes);
+  792                                                   MGen.CopyBlock
+  793                                                 END
+  794                                               ELSIF ~SymTab.Assignable(et,
+  795                                                         dt) THEN
+  796                                                 SemError(210);
+  797                                                 MGen.Drop; MGen.Drop
+  798                                               ELSE
+  799                                                 dstBytes :=
+  800                                                   SymTab.TypeSlots(dt) * 8;
+  801                                                 MGen.PushBytes(dstBytes);
+  802                                                 MGen.CopyBlock
+  803                                               END
+  804                                             ELSE
+  805                                               IF ~SymTab.Assignable(et,
+  806                                                         dt) THEN
+  807                                                 SemError(210);
+  808                                                 MGen.Drop; MGen.Drop
+  809                                               ELSE
+  810                                                 isR :=
+  811                                                   (SymTab.ClassOf(dt)
+  812                                                    = SymTab.ClReal);
+  813                                                 conv := isR
+  814                                                   & SymTab.IsIntFamily(et);
+  815                                                 IF conv THEN
+  816                                                   MGen.IntToReal
+  817                                                 END;
+  818                                                 IF (SymTab.ClassOf(dt)
+  819                                                    = SymTab.ClChar)
+  820                                                    OR (SymTab.ClassOf(dt)
+  821                                                       = SymTab.ClBool) THEN
+  822                                                   MGen.StoreByte
+  823                                                 ELSE MGen.StoreIndir0
+  824                                                 END
+  825                                               END
+  826                                             END
+  827                                           ELSIF (dt # SymTab.InvalidType)
+  828                                             & ~sfx
+  829                                             & (SymTab.TypeSlots(dt) > 1) THEN
+  830                                             IF ~SymTab.Assignable(et, dt) THEN
+  831                                               SemError(210)
+  832                                             ELSE SemError(230)
+  833                                             END
+  834                                           ELSIF ~SymTab.Assignable(et, dt) THEN
+  835                                             SemError(210) END;
+  836                                           IF dk = SymTab.KindImport THEN
+  837                                             SemError(230)
+  838                                           END;
+  839                                           isR := (dt # SymTab.InvalidType)
+  840                                                  & ~pushedDst
+  841                                                  & ~pushedFld
+  842                                                  & (SymTab.ClassOf(dt)
+  843                                                     = SymTab.ClReal);
+  844                                           conv := isR
+  845                                                   & SymTab.IsIntFamily(et);
+  846                                           IF pushedDst THEN
+  847                                           ELSIF pushedFld THEN
+  848                                           ELSIF (dt # SymTab.InvalidType)
+  849                                              & sfx THEN
+  850                                             IF conv THEN
+  851                                               MGen.IntToReal
+  852                                             END;
+  853                                             IF (SymTab.ClassOf(dt)
+  854                                                = SymTab.ClChar)
+  855                                                OR (SymTab.ClassOf(dt)
+  856                                                   = SymTab.ClBool) THEN
+  857                                               MGen.StoreByte
+  858                                             ELSE MGen.StoreIndir0
+  859                                             END
+  860                                           ELSIF storable & ~sfx THEN
+  861                                             IF (dt # SymTab.InvalidType)
+  862                                                & (SymTab.TypeSlots(dt)
+  863                                                   > 1) THEN
+  864                                               MGen.Drop
+  865                                             ELSE
+  866                                               IF conv THEN
+  867                                                 MGen.IntToReal
+  868                                               END;
+  869                                               MGen.StoreFinish(bn)
+  870                                             END
+  871                                           ELSE MGen.Drop
+  872                                           END; .)
+  873        | CallTail<bn, lxD, sfx, FALSE, okC, FALSE>
+  874        |                             (. IF (SymTab.SymKind(bn)
+  875                                                = SymTab.KindModule)
+  876                                               & sfx
+  877                                               & (SymTab.StrLen(lxD) > 0) THEN
+  878                                             modBare := SymTab.ExpProc(bn,
+  879                                                              lxD);
+  880                                             IF modBare < 0 THEN
+  881                                               IF SymTab.ExpKind(bn,
+  882                                                    lxD) # -1 THEN
+  883                                                 SemError(233)
+  884                                               END
+  885                                             ELSIF SymTab.ProcNParByNum(
+  886                                                      modBare) # 0 THEN
+  887                                               SemError(233)
+  888                                             ELSE
+  889                                               MGen.CallProc(modBare);
+  890                                               IF SymTab.ProcRetByNum(
+  891                                                    modBare)
+  892                                                  # SymTab.InvalidType THEN
+  893                                                 MGen.Drop
+  894                                               END
+  895                                             END
+  896                                           ELSE
+  897                                             MGen.ActBegin(bn);
+  898                                             IF MGen.ActEnd(bn, FALSE,
+  899                                                    FALSE) # 0 THEN
+  900                                               SemError(233)
+  901                                             END
+  902                                           END; .) ) .
+  903    CallTail <pn: SymTab.Name; exp: SymTab.Name; sfx: BOOLEAN;
+  904              inExpr: BOOLEAN; VAR ok: BOOLEAN; hasDead: BOOLEAN>
+  905                                          (. VAR t: SymTab.TypeIndex;
+  906                                               lx: MGen.LitStr;
+  907                                               v: BOOLEAN;
+  908                                               vn: SymTab.Name;
+  909                                               isModP: BOOLEAN;
+  910                                               modPNum: INTEGER;
+  911                                               modErr: BOOLEAN; .)
+  912      = "("                               (. ok := FALSE; modErr := FALSE;
+  913                                             isModP :=
+  914                                               (SymTab.SymKind(pn)
+  915                                                = SymTab.KindModule)
+  916                                               & sfx
+  917                                               & (SymTab.StrLen(exp) > 0);
+  918                                             IF hasDead THEN MGen.Drop END;
+  919                                             IF isModP THEN
+  920                                               modPNum := SymTab.ExpProc(pn,
+  921                                                                exp);
+  922                                               IF (modPNum < 0)
+  923                                                  & (SymTab.SelfKind(pn,
+  924                                                       exp)
+  925                                                     = SymTab.KindProc) THEN
+  926                                                 modPNum :=
+  927                                                   SymTab.ProcNum(exp)
+  928                                               END;
+  929                                               IF modPNum < 0 THEN
+  930                                                 IF SymTab.ExpKind(pn,
+  931                                                      exp) # -1 THEN
+  932                                                   SemError(233)
+  933                                                 END;
+  934                                                 modErr := TRUE
+  935                                               ELSIF inExpr
+  936                                                  & (SymTab.ProcRetByNum(
+  937                                                       modPNum)
+  938                                                     = SymTab.InvalidType)
+  939                                               THEN
+  940                                                 SemError(233);
+  941                                                 modErr := TRUE
+  942                                               END;
+  943                                               MGen.ActBeginNum(modPNum)
+  944                                             ELSE
+  945                                               MGen.ActBegin(pn)
+  946                                             END; .)
+  947        [ Expr<t, lx, v, vn>              (. IF isModP THEN
+  948                                             IF ~modErr
+  949                                                & (MGen.ActValue(t, v, vn)
+  950                                                   # 0) THEN
+  951                                               SemError(233);
+  952                                               modErr := TRUE
+  953                                             END
+  954                                           ELSIF MGen.ActValue(t, v, vn) # 0 THEN
+  955                                             SemError(233)
+  956                                           END; .)
+  957          { "," Expr<t, lx, v, vn>        (. IF isModP THEN
+  958                                             IF ~modErr
+  959                                                & (MGen.ActValue(t, v, vn)
+  960                                                   # 0) THEN
+  961                                               SemError(233);
+  962                                               modErr := TRUE
+  963                                             END
+  964                                           ELSIF MGen.ActValue(t, v, vn) # 0 THEN
+  965                                             SemError(233)
+  966                                           END; .) } ]
+  967        ")"                               (. IF isModP THEN
+  968                                             IF ~modErr THEN
+  969                                               IF MGen.ActEndNum(modPNum,
+  970                                                    inExpr) # 0 THEN
+  971                                                 SemError(233)
+  972                                               ELSE ok := TRUE
+  973                                               END
+  974                                             END
+  975                                           ELSIF MGen.ActEnd(pn, sfx,
+  976                                                    inExpr) # 0
+  977                                           THEN SemError(233)
+  978                                           ELSE ok := TRUE
+  979                                           END; .) .
+  980    IfStat                                (. VAR t: SymTab.TypeIndex;
+  981                                               lxC: MGen.LitStr;
+  982                                               vC: BOOLEAN;
+  983                                               vnC: SymTab.Name;
+  984                                               elseL, endL: INTEGER;
+  985                                               hasElse: BOOLEAN; .)
+  986      = "IF"
+  987        Expr<t, lxC, vC, vnC>             (. IF ~SymTab.BoolCheck(t) THEN
+  988                                             SemError(214) END;
+  989                                             elseL := MGen.NewLabel();
+  990                                             endL := MGen.NewLabel();
+  991                                             MGen.Jz(elseL);
+  992                                             hasElse := FALSE; .)
+  993        "THEN"
+  994        StatSeq
+  995        { "ELSIF"                         (. MGen.Jmp(endL);
+  996                                             MGen.DefLabel(elseL); .)
+  997          Expr<t, lxC, vC, vnC>           (. IF ~SymTab.BoolCheck(t) THEN
+  998                                             SemError(214) END;
+  999                                             elseL := MGen.NewLabel();
+ 1000                                             MGen.Jz(elseL); .)
+ 1001          "THEN"
+ 1002          StatSeq }
+ 1003        [ "ELSE"                          (. MGen.Jmp(endL);
+ 1004                                             MGen.DefLabel(elseL);
+ 1005                                             hasElse := TRUE; .)
+ 1006          StatSeq ]
+ 1007        "END"                             (. IF ~hasElse THEN
+ 1008                                             MGen.DefLabel(elseL)
+ 1009                                           END;
+ 1010                                           MGen.DefLabel(endL); .) .
+ 1011    CaseStat                              (. VAR st: SymTab.TypeIndex;
+ 1012                                               lxS: MGen.LitStr;
+ 1013                                               vS: BOOLEAN;
+ 1014                                               vnS: SymTab.Name;
+ 1015                                               tmp, endL: INTEGER; .)
+ 1016      = "CASE"
+ 1017        Expr<st, lxS, vS, vnS>            (. tmp := MGen.TempGlobal();
+ 1018                                             MGen.StoreTemp(tmp);
+ 1019                                             endL := MGen.NewLabel(); .)
+ 1020        "OF"
+ 1021        Case<st, tmp, endL> { "|"
+ 1022                   Case<st, tmp, endL> }
+ 1023        [ "ELSE"
+ 1024          StatSeq ]
+ 1025        "END"                             (. MGen.DefLabel(endL); .) .
+ 1026    Case <sel: SymTab.TypeIndex; tmp: INTEGER; endL: INTEGER>
+ 1027                                          (. VAR lB, lN: INTEGER; .)
+ 1028      = [ LabelList<sel, tmp, lB, lN> ":" (. MGen.DefLabel(lB); .)
+ 1029          StatSeq                         (. MGen.Jmp(endL);
+ 1030                                             MGen.DefLabel(lN); .) ] .
+ 1031    LabelList <sel: SymTab.TypeIndex; tmp: INTEGER;
+ 1032               VAR lB: INTEGER; VAR lN: INTEGER>
+ 1033      =                                   (. lB := MGen.NewLabel();
+ 1034                                             lN := MGen.NewLabel(); .)
+ 1035        Labels<sel, tmp, lB> { ","
+ 1036                      Labels<sel, tmp, lB> }
+ 1037                                          (. MGen.Jmp(lN); .) .
+ 1038    Labels <sel: SymTab.TypeIndex; tmp: INTEGER; bodyL: INTEGER>
+ 1039                                          (. VAR t, t2: SymTab.TypeIndex;
+ 1040                                               lx1, lx2: MGen.LitStr;
+ 1041                                               v1, v2: BOOLEAN;
+ 1042                                               vn1, vn2: SymTab.Name;
+ 1043                                               ta, tb, chunk: INTEGER;
+ 1044                                               r, hasRange: BOOLEAN; .)
+ 1045      = ConstExpr<t, lx1>                 (. IF ~SymTab.EqCheck(t, sel) THEN
+ 1046                                             SemError(213) END;
+ 1047                                             r := (SymTab.ClassOf(sel)
+ 1048                                                   = SymTab.ClReal)
+ 1049                                                  & (SymTab.ClassOf(t)
+ 1050                                                     = SymTab.ClReal);
+ 1051                                             ta := MGen.TempGlobal();
+ 1052                                             MGen.StoreTemp(ta);
+ 1053                                             hasRange := FALSE; .)
+ 1054        [ ".."
+ 1055          ConstExpr<t2, lx2>              (. IF ~SymTab.EqCheck(t2, sel) THEN
+ 1056                                             SemError(213) END;
+ 1057                                             tb := MGen.TempGlobal();
+ 1058                                             MGen.StoreTemp(tb);
+ 1059                                             hasRange := TRUE; .) ]
+ 1060                                          (. IF hasRange THEN
+ 1061                                               MGen.LoadTemp(tmp);
+ 1062                                               MGen.LoadTemp(ta);
+ 1063                                               IF r THEN MGen.RealGe
+ 1064                                               ELSE MGen.IGe END;
+ 1065                                               MGen.LoadTemp(tmp);
+ 1066                                               MGen.LoadTemp(tb);
+ 1067                                               IF r THEN MGen.RealLe
+ 1068                                               ELSE MGen.ILe END;
+ 1069                                               MGen.And
+ 1070                                             ELSE
+ 1071                                               MGen.LoadTemp(tmp);
+ 1072                                               MGen.LoadTemp(ta);
+ 1073                                               IF r THEN MGen.RealEq
+ 1074                                               ELSE MGen.Eq END
+ 1075                                             END;
+ 1076                                             chunk := MGen.NewLabel();
+ 1077                                             MGen.Jz(chunk);
+ 1078                                             MGen.Jmp(bodyL);
+ 1079                                             MGen.DefLabel(chunk); .) .
+ 1080    WhileStat                             (. VAR t: SymTab.TypeIndex;
+ 1081                                               lxC: MGen.LitStr;
+ 1082                                               vC: BOOLEAN;
+ 1083                                               vnC: SymTab.Name;
+ 1084                                               topL, endL: INTEGER; .)
+ 1085      = "WHILE"                           (. topL := MGen.NewLabel();
+ 1086                                             endL := MGen.NewLabel();
+ 1087                                             MGen.DefLabel(topL); .)
+ 1088        Expr<t, lxC, vC, vnC>             (. IF ~SymTab.BoolCheck(t) THEN
+ 1089                                             SemError(214) END;
+ 1090                                             MGen.Jz(endL); .)
+ 1091        "DO"
+ 1092        StatSeq
+ 1093        "END"                             (. MGen.Jmp(topL);
+ 1094                                             MGen.DefLabel(endL); .) .
+ 1095    RepeatStat                            (. VAR t: SymTab.TypeIndex;
+ 1096                                               lxC: MGen.LitStr;
+ 1097                                               vC: BOOLEAN;
+ 1098                                               vnC: SymTab.Name;
+ 1099                                               topL: INTEGER; .)
+ 1100      = "REPEAT"                          (. topL := MGen.NewLabel();
+ 1101                                             MGen.DefLabel(topL); .)
+ 1102        StatSeq
+ 1103        "UNTIL"
+ 1104        Expr<t, lxC, vC, vnC>             (. IF ~SymTab.BoolCheck(t) THEN
+ 1105                                             SemError(214) END;
+ 1106                                             MGen.Jz(topL); .) .
+ 1107    LoopStat                              (. VAR topL, exitL: INTEGER; .)
+ 1108      = "LOOP"                            (. topL := MGen.NewLabel();
+ 1109                                             exitL := MGen.NewLabel();
+ 1110                                             MGen.DefLabel(topL);
+ 1111                                             MGen.PushLoop(exitL); .)
+ 1112        StatSeq
+ 1113        "END"                             (. MGen.Jmp(topL);
+ 1114                                             MGen.DefLabel(exitL);
+ 1115                                             MGen.PopLoop; .) .
+ 1116    ForStat                               (. VAR n, lv: SymTab.Name;
+ 1117                                               fk: INTEGER;
+ 1118                                               lo, hi: SymTab.TypeIndex;
+ 1119                                               lxLo, lxHi: MGen.LitStr;
+ 1120                                               vLo, vHi: BOOLEAN;
+ 1121                                               vnLo, vnHi: SymTab.Name;
+ 1122                                               byV, ht: INTEGER;
+ 1123                                               lTop, lChk, lEnd: INTEGER;
+ 1124                                               neg, storable: BOOLEAN; .)
+ 1125      = "FOR"
+ 1126        GetIdent<n>                       (. IF ~SymTab.Lookup(n) THEN
+ 1127                                              SemError(201);
+ 1128                                              fk := -1
+ 1129                                            ELSIF (SymTab.SymKind(n) #
+ 1130                                                   SymTab.KindVar)
+ 1131                                              & (SymTab.SymKind(n) #
+ 1132                                                 SymTab.KindParam)
+ 1133                                              & (SymTab.SymKind(n) #
+ 1134                                                 SymTab.KindVarPar)
+ 1135                                              & (SymTab.SymKind(n) #
+ 1136                                                 SymTab.KindField) THEN
+ 1137                                              SemError(220);
+ 1138                                              fk := -1
+ 1139                                            ELSIF (SymTab.SymType(n) #
+ 1140                                                   SymTab.InvalidType)
+ 1141                                              & ~SymTab.IsIntFamily(
+ 1142                                                  SymTab.SymType(n)) THEN
+ 1143                                              SemError(220);
+ 1144                                              fk := -1
+ 1145                                            ELSE
+ 1146                                              fk := SymTab.SymKind(n)
+ 1147                                            END;
+ 1148                                            MGen.CopyName(n, lv);
+ 1149                                            storable := (fk = SymTab.KindVar)
+ 1150                                              OR (fk = SymTab.KindParam)
+ 1151                                              OR (fk = SymTab.KindVarPar);
+ 1152                                            IF storable THEN
+ 1153                                              MGen.StoreSetup(lv)
+ 1154                                            END; .)
+ 1155        ":="
+ 1156        Expr<lo, lxLo, vLo, vnLo>         (. IF (lo # SymTab.InvalidType)
+ 1157                                             & ~SymTab.IsIntFamily(lo) THEN
+ 1158                                             SemError(220) END;
+ 1159                                             IF storable THEN
+ 1160                                               MGen.StoreFinish(lv)
+ 1161                                             ELSE MGen.Drop
+ 1162                                             END; .)
+ 1163        "TO"
+ 1164        Expr<hi, lxHi, vHi, vnHi>         (. IF (hi # SymTab.InvalidType)
+ 1165                                             & ~SymTab.IsIntFamily(hi) THEN
+ 1166                                             SemError(220) END;
+ 1167                                             ht := MGen.TempGlobal();
+ 1168                                             MGen.StoreTemp(ht);
+ 1169                                             byV := 1; neg := FALSE; .)
+ 1170        [ "BY"
+ 1171          ByLit<byV>                      (. neg := byV < 0; .) ]
+ 1172        "DO"                              (. lTop := MGen.NewLabel();
+ 1173                                             lChk := MGen.NewLabel();
+ 1174                                             lEnd := MGen.NewLabel();
+ 1175                                             MGen.Jmp(lChk);
+ 1176                                             MGen.DefLabel(lTop); .)
+ 1177        StatSeq
+ 1178        "END"                             (. MGen.PushVar(lv);
+ 1179                                             MGen.PushInt(byV);
+ 1180                                             MGen.Add;
+ 1181                                             IF storable THEN
+ 1182                                               MGen.StoreFinish(lv)
+ 1183                                             ELSE MGen.Drop
+ 1184                                             END;
+ 1185                                             MGen.DefLabel(lChk);
+ 1186                                             MGen.PushVar(lv);
+ 1187                                             MGen.LoadTemp(ht);
+ 1188                                             IF neg THEN MGen.IGe
+ 1189                                             ELSE MGen.ILe END;
+ 1190                                             MGen.Jz(lEnd);
+ 1191                                             MGen.Jmp(lTop);
+ 1192                                             MGen.DefLabel(lEnd); .) .
+ 1193    ByLit <VAR v: INTEGER>                (. VAR s: ARRAY [0 .. 255] OF CHAR; .)
+ 1194      = integer                           (. LexString(s);
+ 1195                                             IF ~MGen.ParseInt(s, v) THEN
+ 1196                                               v := 1
+ 1197                                             END; .)
+ 1198      | "-" integer                       (. LexString(s);
+ 1199                                             IF MGen.ParseInt(s, v) THEN
+ 1200                                               v := -v
+ 1201                                             ELSE v := -1
+ 1202                                             END; .) .
+ 1203    WithStat                              (. VAR dt: SymTab.TypeIndex;
+ 1204                                               dk: INTEGER;
+ 1205                                               bnW: SymTab.Name;
+ 1206                                               lxW: MGen.LitStr;
+ 1207                                               sfxW: BOOLEAN;
+ 1208                                               pushed: BOOLEAN; .)
+ 1209      = "WITH"
+ 1210        DesignHead<dt, dk, bnW, FALSE, lxW>
+ 1211        DesignTail<dt, dk, bnW, FALSE, lxW, sfxW>
+ 1212                                        (. pushed := FALSE;
+ 1213                                             IF dt = SymTab.InvalidType THEN
+ 1214                                               IF sfxW THEN MGen.Drop END
+ 1215                                             ELSIF SymTab.ClassOf(dt)
+ 1216                                                    # SymTab.ClRecord THEN
+ 1217                                               SemError(215);
+ 1218                                               IF sfxW THEN MGen.Drop END
+ 1219                                             ELSE
+ 1220                                               IF ~sfxW THEN
+ 1221                                                 IF (dk
+ 1222                                                    = SymTab.KindVar)
+ 1223                                                    OR (dk
+ 1224                                                       = SymTab.KindParam)
+ 1225                                                    OR (dk
+ 1226                                                    = SymTab.KindVarPar) THEN
+ 1227                                                   MGen.PushAddr(bnW)
+ 1228                                                 ELSIF dk
+ 1229                                                   = SymTab.KindField THEN
+ 1230                                                   MGen.WithAddr(bnW)
+ 1231                                                 ELSE MGen.PushInt(0)
+ 1232                                                 END
+ 1233                                               END;
+ 1234                                               MGen.WithEnter(dt);
+ 1235                                               pushed :=
+ 1236                                                 SymTab.PushRecord(dt);
+ 1237                                               IF ~pushed THEN
+ 1238                                                 SemError(215)
+ 1239                                               END
+ 1240                                             END; .)
+ 1241        "DO"
+ 1242        StatSeq
+ 1243        "END"                             (. IF pushed THEN
+ 1244                                               SymTab.PopScope;
+ 1245                                               MGen.WithExit
+ 1246                                             END; .) .
+ 1247    ReturnStat                            (. VAR t: SymTab.TypeIndex;
+ 1248                                               lx: MGen.LitStr;
+ 1249                                               v: BOOLEAN;
+ 1250                                               vn: SymTab.Name;
+ 1251                                               hasE, doRet, conv: BOOLEAN; .)
+ 1252      = "RETURN"                          (. hasE := FALSE; .)
+ 1253        [ Expr<t, lx, v, vn>              (. hasE := TRUE;
+ 1254                                             doRet := FALSE;
+ 1255                                             IF ~SymTab.InProc() THEN
+ 1256                                               SemError(232)
+ 1257                                             ELSIF ~SymTab.InFunction() THEN
+ 1258                                               SemError(232)
+ 1259                                             ELSIF ~SymTab.Assignable(
+ 1260                                                       t, SymTab.CurRet()) THEN
+ 1261                                               SemError(232)
+ 1262                                             ELSE doRet := TRUE
+ 1263                                             END;
+ 1264                                             conv := doRet
+ 1265                                                     & SymTab.IsIntFamily(t)
+ 1266                                                     & (SymTab.ClassOf(
+ 1267                                                          SymTab.CurRet())
+ 1268                                                        = SymTab.ClReal);
+ 1269                                             IF doRet THEN
+ 1270                                               IF conv THEN
+ 1271                                                 MGen.IntToReal
+ 1272                                               END;
+ 1273                                               MGen.Leave(
+ 1274                                                 SymTab.CurNPar(), TRUE)
+ 1275                                             ELSE MGen.Drop
+ 1276                                             END; .) ]
+ 1277                                           (. IF ~hasE THEN
+ 1278                                               IF ~SymTab.InProc() THEN
+ 1279                                                 SemError(232)
+ 1280                                               ELSIF SymTab.InFunction() THEN
+ 1281                                                 SemError(232)
+ 1282                                               ELSE MGen.Leave(
+ 1283                                                 SymTab.CurNPar(), FALSE)
+ 1284                                               END
+ 1285                                             END; .) .
+ 1286    NewStat                               (. VAR dt: SymTab.TypeIndex;
+ 1287                                               dk: INTEGER;
+ 1288                                               bnN: SymTab.Name;
+ 1289                                               lxN: MGen.LitStr;
+ 1290                                               sfxN: BOOLEAN;
+ 1291                                               baseT: SymTab.TypeIndex;
+ 1292                                               slN: CARDINAL; .)
+ 1293      = "NEW"
+ 1294        "(" DesignHead<dt, dk, bnN, FALSE, lxN>
+ 1295            DesignTail<dt, dk, bnN, FALSE, lxN, sfxN>
+ 1296        ")"                               (. IF dt = SymTab.InvalidType THEN
+ 1297                                             IF sfxN THEN MGen.Drop END
+ 1298                                           ELSIF SymTab.ClassOf(dt)
+ 1299                                                  # SymTab.ClPtr THEN
+ 1300                                             SemError(219);
+ 1301                                             IF sfxN THEN MGen.Drop END
+ 1302                                           ELSE
+ 1303                                             baseT := SymTab.PtrBase(dt);
+ 1304                                             slN := SymTab.TypeSlots(baseT);
+ 1305                                             IF slN = 0 THEN
+ 1306                                               SemError(230);
+ 1307                                               slN := 1
+ 1308                                             END;
+ 1309                                             IF ~sfxN THEN
+ 1310                                               IF (dk = SymTab.KindVar)
+ 1311                                                  OR (dk
+ 1312                                                      = SymTab.KindParam)
+ 1313                                                  OR (dk
+ 1314                                                   = SymTab.KindVarPar) THEN
+ 1315                                                 MGen.PushAddr(bnN)
+ 1316                                               ELSIF dk
+ 1317                                                 = SymTab.KindField THEN
+ 1318                                                 MGen.WithAddr(bnN)
+ 1319                                               ELSE MGen.PushInt(0)
+ 1320                                               END
+ 1321                                             END;
+ 1322                                             MGen.PushBytes(slN * 8);
+ 1323                                             MGen.AllocOp
+ 1324                                           END; .) .
+ 1325    DispStat                              (. VAR dt: SymTab.TypeIndex;
+ 1326                                               dk: INTEGER;
+ 1327                                               bnD: SymTab.Name;
+ 1328                                               lxD: MGen.LitStr;
+ 1329                                               sfxD: BOOLEAN;
+ 1330                                               baseT: SymTab.TypeIndex;
+ 1331                                               slD: CARDINAL; .)
+ 1332      = "DISPOSE"
+ 1333        "(" DesignHead<dt, dk, bnD, FALSE, lxD>
+ 1334            DesignTail<dt, dk, bnD, FALSE, lxD, sfxD>
+ 1335        ")"                               (. IF dt = SymTab.InvalidType THEN
+ 1336                                             IF sfxD THEN MGen.Drop END
+ 1337                                           ELSIF SymTab.ClassOf(dt)
+ 1338                                                  # SymTab.ClPtr THEN
+ 1339                                             SemError(219);
+ 1340                                             IF sfxD THEN MGen.Drop END
+ 1341                                           ELSE
+ 1342                                             baseT := SymTab.PtrBase(dt);
+ 1343                                             slD := SymTab.TypeSlots(baseT);
+ 1344                                             IF slD = 0 THEN
+ 1345                                               SemError(230);
+ 1346                                               slD := 1
+ 1347                                             END;
+ 1348                                             IF ~sfxD THEN
+ 1349                                               IF (dk = SymTab.KindVar)
+ 1350                                                  OR (dk
+ 1351                                                      = SymTab.KindParam)
+ 1352                                                  OR (dk
+ 1353                                                   = SymTab.KindVarPar) THEN
+ 1354                                                 MGen.PushAddr(bnD)
+ 1355                                               ELSIF dk
+ 1356                                                 = SymTab.KindField THEN
+ 1357                                                 MGen.WithAddr(bnD)
+ 1358                                               ELSE MGen.PushInt(0)
+ 1359                                               END
+ 1360                                             END;
+ 1361                                             MGen.PushBytes(slD * 8);
+ 1362                                             MGen.DeallocOp
+ 1363                                           END; .) .
+ 1364    WriteIntStat                          (. VAR t: SymTab.TypeIndex;
+ 1365                                               lx: MGen.LitStr;
+ 1366                                               v: BOOLEAN;
+ 1367                                               vn: SymTab.Name; .)
+ 1368      = "WriteInt"
+ 1369        "(" Expr<t, lx, v, vn> ")"        (. IF t = SymTab.InvalidType THEN
+ 1370                                             MGen.Drop
+ 1371                                           ELSIF ~SymTab.IsIntFamily(t) THEN
+ 1372                                             SemError(210);
+ 1373                                             MGen.Drop
+ 1374                                           ELSE
+ 1375                                             MGen.CallPrint
+ 1376                                           END; .) .
+ 1377    WriteStrStat                          (. VAR t: SymTab.TypeIndex;
+ 1378                                               lx: MGen.LitStr;
+ 1379                                               v: BOOLEAN;
+ 1380                                               vn: SymTab.Name; .)
+ 1381      = "WriteString"
+ 1382        "(" Expr<t, lx, v, vn> ")"        (. IF t = SymTab.InvalidType THEN
+ 1383                                             MGen.Drop
+ 1384                                           ELSIF (SymTab.ClassOf(t)
+ 1385                                                  = SymTab.ClStr) THEN
+ 1386                                             MGen.PushInt(1);
+ 1387                                             MGen.SysCall
+ 1388                                           ELSIF (SymTab.ClassOf(t)
+ 1389                                                  = SymTab.ClArray)
+ 1390                                              & (SymTab.ClassOf(
+ 1391                                                 SymTab.ArrayElem(t))
+ 1392                                                 = SymTab.ClChar) THEN
+ 1393                                             MGen.PushInt(1);
+ 1394                                             MGen.SysCall
+ 1395                                           ELSE
+ 1396                                             SemError(210);
+ 1397                                             MGen.Drop
+ 1398                                           END; .) .
+ 1399  
+ 1400    (* Expressions: Designator without ActualParameters (calls use
+ 1401       CallTail). Each expression synthesizes its SymTab type in t,
+ 1402       the source text in lx for single literals ("" otherwise), and
+ 1403       whether it is a plain variable (v/vn) for VAR actuals.
+ 1404       Values travel on the MC64 stack. *)
+ 1405    DesignHead <VAR t: SymTab.TypeIndex; VAR k: INTEGER;
+ 1406                VAR bn: SymTab.Name; doLoad: BOOLEAN; VAR lx: MGen.LitStr>
+ 1407                                          (. VAR n: SymTab.Name;
+ 1408                                               cls: INTEGER; .)
+ 1409      = GetIdent<n>                       (. MGen.CopyName(n, bn);
+ 1410                                             lx[0] := 0C;
+ 1411                                             IF ~SymTab.Lookup(n) THEN
+ 1412                                               SemError(201);
+ 1413                                               t := SymTab.InvalidType; k := -1;
+ 1414                                               IF doLoad THEN
+ 1415                                                 MGen.PushInt(0)
+ 1416                                               END
+ 1417                                             ELSE
+ 1418                                               t := SymTab.SymType(n);
+ 1419                                               k := SymTab.SymKind(n);
+ 1420                                               IF k = SymTab.KindConst THEN
+ 1421                                                 IF SymTab.Equal(n, "TRUE") THEN
+ 1422                                                   t := SymTab.BoolType();
+ 1423                                                   MGen.CopyName("TRUE", lx);
+ 1424                                                   IF doLoad THEN
+ 1425                                                     MGen.PushInt(1)
+ 1426                                                   END
+ 1427                                                 ELSIF SymTab.Equal(n,
+ 1428                                                         "FALSE") THEN
+ 1429                                                   t := SymTab.BoolType();
+ 1430                                                   MGen.CopyName("FALSE", lx);
+ 1431                                                   IF doLoad THEN
+ 1432                                                     MGen.PushInt(0)
+ 1433                                                   END
+ 1434                                                 ELSE
+ 1435                                                   cls :=
+ 1436                                                     SymTab.ClassOf(t);
+ 1437                                                   IF (t #
+ 1438                                                       SymTab.InvalidType)
+ 1439                                                      & (cls # SymTab.ClStr)
+ 1440                                                      & ((cls = SymTab.ClInt)
+ 1441                                                      OR (cls = SymTab.ClReal)
+ 1442                                                      OR (cls = SymTab.ClBool)
+ 1443                                                      OR (cls = SymTab.ClChar)
+ 1444                                                      OR (cls
+ 1445                                                          = SymTab.ClEnum)) THEN
+ 1446                                                     IF doLoad THEN
+ 1447                                                       MGen.LoadVar(n)
+ 1448                                                     END
+ 1449                                                   ELSIF doLoad THEN
+ 1450                                                     MGen.PushInt(0)
+ 1451                                                   END
+ 1452                                                 END
+ 1453                                                ELSIF (k = SymTab.KindVar)
+ 1454                                                   OR (k = SymTab.KindParam)
+ 1455                                                   OR (k
+ 1456                                                       = SymTab.KindVarPar) THEN
+ 1457                                                  cls := SymTab.ClassOf(t);
+ 1458                                                  IF (cls = SymTab.ClInt)
+ 1459                                                     OR (cls = SymTab.ClReal)
+ 1460                                                     OR (cls = SymTab.ClBool)
+ 1461                                                     OR (cls = SymTab.ClChar)
+ 1462                                                     OR (cls
+ 1463                                                         = SymTab.ClEnum)
+ 1464                                                     OR (cls
+ 1465                                                         = SymTab.ClSet)
+ 1466                                                     OR (cls
+ 1467                                                         = SymTab.ClPtr) THEN
+ 1468                                                    IF doLoad THEN
+ 1469                                                      MGen.PushVar(n)
+ 1470                                                    END
+ 1471                                                  ELSIF (cls
+ 1472                                                         = SymTab.ClArray)
+ 1473                                                     OR (cls
+ 1474                                                         = SymTab.ClRecord) THEN
+ 1475                                                    IF doLoad THEN
+ 1476                                                      MGen.PushAddr(n)
+ 1477                                                    END
+ 1478                                                  ELSIF t
+ 1479                                                    = SymTab.InvalidType THEN
+ 1480                                                    IF doLoad THEN
+ 1481                                                      MGen.PushInt(0)
+ 1482                                                    END
+ 1483                                                  ELSE SemError(230);
+ 1484                                                    IF doLoad THEN
+ 1485                                                      MGen.PushInt(0)
+ 1486                                                    END
+ 1487                                                  END
+ 1488                                               ELSE
+ 1489                                                 IF doLoad THEN
+ 1490                                                   IF k = SymTab.KindField THEN
+ 1491                                                     MGen.WithAddr(n);
+ 1492                                                     cls := SymTab.ClassOf(t);
+ 1493                                                     IF (t
+ 1494                                                        = SymTab.InvalidType)
+ 1495                                                        OR (cls
+ 1496                                                           = SymTab.ClArray)
+ 1497                                                        OR (cls
+ 1498                                                           = SymTab.ClRecord) THEN
+ 1499                                                     ELSE
+ 1500                                                       IF (cls
+ 1501                                                          = SymTab.ClChar)
+ 1502                                                          OR (cls
+ 1503                                                             = SymTab.ClBool) THEN
+ 1504                                                         MGen.LoadByte
+ 1505                                                       ELSE MGen.LoadIndir
+ 1506                                                       END
+ 1507                                                     END
+ 1508                                                   ELSE MGen.PushInt(0)
+ 1509                                                   END
+ 1510                                                 END;
+ 1511                                                 IF k = SymTab.KindField THEN
+ 1512                                                 ELSIF k
+ 1513                                                       = SymTab.KindImport THEN
+ 1514                                                   SemError(230)
+ 1515                                                 END
+ 1516                                               END
+ 1517                                             END; .) .
+ 1518    DesignTail <VAR t: SymTab.TypeIndex; VAR k: INTEGER;
+ 1519                VAR bn: SymTab.Name; doLoad: BOOLEAN; VAR lx: MGen.LitStr;
+ 1520                VAR sfx: BOOLEAN>
+ 1521                                          (. VAR m: SymTab.Name;
+ 1522                                               it: SymTab.TypeIndex;
+ 1523                                               lxI: MGen.LitStr;
+ 1524                                               vI: BOOLEAN;
+ 1525                                               vnI: SymTab.Name;
+ 1526                                               loA: INTEGER;
+ 1527                                               elemT: SymTab.TypeIndex;
+ 1528                                               esl, ebytes: CARDINAL;
+ 1529                                               firstT: BOOLEAN;
+ 1530                                               clsI: INTEGER;
+ 1531                                               sk: INTEGER;
+ 1532                                               qM: SymTab.Name; .)
+ 1533      =                                   (. sfx := FALSE; .)
+ 1534        { "."                             (. firstT := ~sfx;
+ 1535                                             sfx := TRUE; lx[0] := 0C;
+ 1536                                             IF ~doLoad & firstT THEN
+ 1537                                               IF (k = SymTab.KindVar)
+ 1538                                                  OR (k = SymTab.KindParam)
+ 1539                                                  OR (k
+ 1540                                                      = SymTab.KindVarPar) THEN
+ 1541                                                 MGen.PushAddr(bn)
+ 1542                                               ELSIF k
+ 1543                                                 = SymTab.KindField THEN
+ 1544                                                 MGen.WithAddr(bn)
+ 1545                                               ELSIF k
+ 1546                                                 = SymTab.KindModule THEN
+ 1547                                               ELSE MGen.PushInt(0)
+ 1548                                               END
+ 1549                                             END; .)
+ 1550          GetIdent<m>                     (. IF (k = SymTab.KindModule) THEN
+ 1551                                               IF SymTab.ExpKind(bn, m) = -1 THEN
+ 1552                                                 sk := SymTab.SelfKind(bn, m);
+ 1553                                                 IF sk = SymTab.KindProc THEN
+ 1554                                                   MGen.CopyName(m, lx);
+ 1555                                                   t := SymTab.InvalidType;
+ 1556                                                   IF doLoad THEN
+ 1557                                                     MGen.Drop; MGen.PushInt(0)
+ 1558                                                   ELSIF firstT THEN
+ 1559                                                   ELSE MGen.Drop
+ 1560                                                   END
+ 1561                                                 ELSIF sk # -1 THEN
+ 1562                                                   t := SymTab.SymType(m);
+ 1563                                                   k := sk;
+ 1564                                                   SymTab.SelfQual(m, qM);
+ 1565                                                   IF doLoad THEN
+ 1566                                                     MGen.Drop;
+ 1567                                                     MGen.GlobalAddr(qM)
+ 1568                                                   ELSE
+ 1569                                                     IF firstT THEN
+ 1570                                                     ELSE MGen.Drop
+ 1571                                                     END;
+ 1572                                                     MGen.GlobalAddr(qM)
+ 1573                                                   END
+ 1574                                                 ELSE
+ 1575                                                   SemError(201);
+ 1576                                                   MGen.CopyName(m, lx);
+ 1577                                                   t := SymTab.InvalidType;
+ 1578                                                   IF doLoad THEN
+ 1579                                                     MGen.Drop; MGen.PushInt(0)
+ 1580                                                   ELSIF firstT THEN
+ 1581                                                   ELSE MGen.Drop
+ 1582                                                   END
+ 1583                                                 END
+ 1584                                               ELSIF SymTab.ExpKind(bn, m)
+ 1585                                                      = SymTab.KindProc THEN
+ 1586                                                 MGen.CopyName(m, lx);
+ 1587                                                 t := SymTab.InvalidType;
+ 1588                                                 IF doLoad THEN
+ 1589                                                   MGen.Drop; MGen.PushInt(0)
+ 1590                                                 ELSIF firstT THEN
+ 1591                                                 ELSE MGen.Drop
+ 1592                                                 END
+ 1593                                               ELSE
+ 1594                                                 t := SymTab.ExpType(bn, m);
+ 1595                                                 k := SymTab.ExpKind(bn, m);
+ 1596                                                 SymTab.ExpQual(bn, m, qM);
+ 1597                                                 IF doLoad THEN
+ 1598                                                   MGen.Drop;
+ 1599                                                   MGen.GlobalAddr(qM)
+ 1600                                                 ELSE
+ 1601                                                   IF firstT THEN
+ 1602                                                   ELSE MGen.Drop
+ 1603                                                   END;
+ 1604                                                   MGen.GlobalAddr(qM)
+ 1605                                                 END
+ 1606                                               END
+ 1607                                             ELSIF t = SymTab.InvalidType THEN
+ 1608                                               IF ~doLoad & firstT THEN
+ 1609                                                 MGen.Drop
+ 1610                                               ELSIF doLoad THEN
+ 1611                                                 MGen.Drop; MGen.PushInt(0)
+ 1612                                               END
+ 1613                                             ELSIF SymTab.ClassOf(t) #
+ 1614                                                   SymTab.ClRecord THEN
+ 1615                                               SemError(215);
+ 1616                                               t := SymTab.InvalidType;
+ 1617                                               IF doLoad THEN
+ 1618                                                 MGen.Drop; MGen.PushInt(0)
+ 1619                                               ELSIF firstT THEN
+ 1620                                                 MGen.Drop
+ 1621                                               END
+ 1622                                             ELSIF ~SymTab.FieldExists(t, m) THEN
+ 1623                                               SemError(216);
+ 1624                                               t := SymTab.InvalidType;
+ 1625                                               IF doLoad THEN
+ 1626                                                 MGen.Drop; MGen.PushInt(0)
+ 1627                                               ELSIF firstT THEN
+ 1628                                                 MGen.Drop
+ 1629                                               END
+ 1630                                             ELSE
+ 1631                                               loA := SymTab.FieldOffset(t, m);
+ 1632                                               elemT := SymTab.FieldType(t, m);
+ 1633                                               IF loA < 0 THEN
+ 1634                                                 SemError(216);
+ 1635                                                 t := SymTab.InvalidType;
+ 1636                                                 IF doLoad THEN
+ 1637                                                   MGen.Drop; MGen.PushInt(0)
+ 1638                                                 ELSIF firstT THEN
+ 1639                                                   MGen.Drop
+ 1640                                                 END
  1641                                               ELSE
- 1642                                                 IF ~firstT THEN
- 1643                                                 ELSE MGen.Drop
- 1644                                                 END
+ 1642                                                 MGen.FieldAdd(
+ 1643                                                   VAL(CARDINAL, loA));
+ 1644                                                 t := elemT
  1645                                               END
- 1646                                             ELSE
- 1647                                               loA := SymTab.ArrayLo(t);
- 1648                                               elemT := SymTab.ArrayElem(t);
- 1649                                               esl := SymTab.TypeSlots(elemT);
- 1650                                               IF esl = 0 THEN
- 1651                                                 SemError(230);
- 1652                                                 esl := 1
- 1653                                               END;
- 1654                                               IF (SymTab.ClassOf(elemT)
- 1655                                                  = SymTab.ClChar)
- 1656                                                  OR (SymTab.ClassOf(elemT)
- 1657                                                     = SymTab.ClBool) THEN
- 1658                                                 ebytes := 1
- 1659                                               ELSE ebytes := esl * 8
- 1660                                               END;
- 1661                                               MGen.IdxScale(loA, ebytes);
- 1662                                               t := elemT
- 1663                                             END
- 1664                                           END; .)
- 1665          { ","
- 1666            Expr<it, lxI, vI, vnI>        (. IF t = SymTab.InvalidType THEN
- 1667                                             MGen.Drop;
- 1668                                             IF doLoad THEN
- 1669                                               MGen.Drop; MGen.PushInt(0);
- 1670                                               t := SymTab.InvalidType
- 1671                                             END
- 1672                                           ELSIF SymTab.ClassOf(t) #
- 1673                                                   SymTab.ClArray THEN
- 1674                                             SemError(217);
- 1675                                             t := SymTab.InvalidType;
- 1676                                             MGen.Drop;
- 1677                                             IF doLoad THEN
- 1678                                               MGen.Drop; MGen.PushInt(0)
- 1679                                             END
- 1680                                           ELSE
- 1681                                             clsI := SymTab.ClassOf(it);
- 1682                                             IF (it
- 1683                                                # SymTab.InvalidType)
- 1684                                                & (clsI # SymTab.ClInt)
- 1685                                                & (clsI # SymTab.ClChar)
- 1686                                                & (clsI # SymTab.ClEnum)
- 1687                                                & (clsI
- 1688                                                   # SymTab.ClBool) THEN
- 1689                                               SemError(218);
- 1690                                               t := SymTab.InvalidType;
- 1691                                               MGen.Drop;
- 1692                                               IF doLoad THEN
- 1693                                                 MGen.Drop; MGen.PushInt(0)
- 1694                                               END
- 1695                                             ELSE
- 1696                                               loA := SymTab.ArrayLo(t);
- 1697                                               elemT := SymTab.ArrayElem(t);
- 1698                                               esl := SymTab.TypeSlots(elemT);
- 1699                                               IF esl = 0 THEN
- 1700                                                 SemError(230);
- 1701                                                 esl := 1
- 1702                                               END;
- 1703                                               IF (SymTab.ClassOf(elemT)
- 1704                                                  = SymTab.ClChar)
- 1705                                                  OR (SymTab.ClassOf(elemT)
- 1706                                                     = SymTab.ClBool) THEN
- 1707                                                 ebytes := 1
- 1708                                               ELSE ebytes := esl * 8
- 1709                                               END;
- 1710                                               MGen.IdxScale(loA, ebytes);
- 1711                                               t := elemT
- 1712                                             END
- 1713                                           END; .) }
- 1714          "]"
- 1715        | "^"                             (. firstT := ~sfx;
- 1716                                             sfx := TRUE; lx[0] := 0C;
- 1717                                             IF ~doLoad & firstT THEN
- 1718                                               IF (k = SymTab.KindVar)
- 1719                                                  OR (k = SymTab.KindParam)
- 1720                                                  OR (k
- 1721                                                      = SymTab.KindVarPar) THEN
- 1722                                                 MGen.PushAddr(bn)
- 1723                                               ELSIF k
- 1724                                                 = SymTab.KindField THEN
- 1725                                                 MGen.WithAddr(bn)
- 1726                                               ELSE MGen.PushInt(0)
- 1727                                               END
- 1728                                             END; .)
- 1729                                          (. IF t = SymTab.InvalidType THEN
- 1730                                               IF doLoad THEN
- 1731                                                 MGen.Drop; MGen.PushInt(0)
- 1732                                               ELSIF firstT THEN
- 1733                                                 MGen.Drop
- 1734                                               END
- 1735                                             ELSIF SymTab.ClassOf(t) #
- 1736                                                   SymTab.ClPtr THEN
- 1737                                               SemError(219);
- 1738                                               t := SymTab.InvalidType;
- 1739                                               IF doLoad THEN
- 1740                                                 MGen.Drop; MGen.PushInt(0)
- 1741                                               ELSIF firstT THEN
- 1742                                                 MGen.Drop
- 1743                                               END
- 1744                                             ELSE
- 1745                                               elemT := SymTab.PtrBase(t);
- 1746                                               t := elemT;
+ 1646                                             END; .)
+ 1647        | "["                             (. firstT := ~sfx;
+ 1648                                             sfx := TRUE; lx[0] := 0C;
+ 1649                                             IF ~doLoad & firstT THEN
+ 1650                                               IF (k = SymTab.KindVar)
+ 1651                                                  OR (k = SymTab.KindParam)
+ 1652                                                  OR (k
+ 1653                                                      = SymTab.KindVarPar) THEN
+ 1654                                                 MGen.PushAddr(bn)
+ 1655                                               ELSIF k
+ 1656                                                 = SymTab.KindField THEN
+ 1657                                                 MGen.WithAddr(bn)
+ 1658                                               ELSE MGen.PushInt(0)
+ 1659                                               END
+ 1660                                             END; .)
+ 1661          Expr<it, lxI, vI, vnI>          (. IF t = SymTab.InvalidType THEN
+ 1662                                             MGen.Drop;
+ 1663                                             IF doLoad THEN
+ 1664                                               MGen.Drop; MGen.PushInt(0)
+ 1665                                             ELSE
+ 1666                                               IF ~firstT THEN
+ 1667                                               ELSE MGen.Drop
+ 1668                                               END
+ 1669                                             END
+ 1670                                           ELSIF SymTab.ClassOf(t) #
+ 1671                                                   SymTab.ClArray THEN
+ 1672                                             SemError(217);
+ 1673                                             t := SymTab.InvalidType;
+ 1674                                             MGen.Drop;
+ 1675                                             IF doLoad THEN
+ 1676                                               MGen.Drop; MGen.PushInt(0)
+ 1677                                             ELSE
+ 1678                                               IF ~firstT THEN
+ 1679                                               ELSE MGen.Drop
+ 1680                                               END
+ 1681                                             END
+ 1682                                           ELSE
+ 1683                                             clsI := SymTab.ClassOf(it);
+ 1684                                             IF (it
+ 1685                                                # SymTab.InvalidType)
+ 1686                                                & (clsI # SymTab.ClInt)
+ 1687                                                & (clsI # SymTab.ClChar)
+ 1688                                                & (clsI # SymTab.ClEnum)
+ 1689                                                & (clsI
+ 1690                                                   # SymTab.ClBool) THEN
+ 1691                                               SemError(218);
+ 1692                                               t := SymTab.InvalidType;
+ 1693                                               MGen.Drop;
+ 1694                                               IF doLoad THEN
+ 1695                                                 MGen.Drop; MGen.PushInt(0)
+ 1696                                               ELSE
+ 1697                                                 IF ~firstT THEN
+ 1698                                                 ELSE MGen.Drop
+ 1699                                                 END
+ 1700                                               END
+ 1701                                             ELSE
+ 1702                                               loA := SymTab.ArrayLo(t);
+ 1703                                               elemT := SymTab.ArrayElem(t);
+ 1704                                               esl := SymTab.TypeSlots(elemT);
+ 1705                                               IF esl = 0 THEN
+ 1706                                                 SemError(230);
+ 1707                                                 esl := 1
+ 1708                                               END;
+ 1709                                               IF (SymTab.ClassOf(elemT)
+ 1710                                                  = SymTab.ClChar)
+ 1711                                                  OR (SymTab.ClassOf(elemT)
+ 1712                                                     = SymTab.ClBool) THEN
+ 1713                                                 ebytes := 1
+ 1714                                               ELSE ebytes := esl * 8
+ 1715                                               END;
+ 1716                                               MGen.IdxScale(loA, ebytes);
+ 1717                                               t := elemT
+ 1718                                             END
+ 1719                                           END; .)
+ 1720          { ","
+ 1721            Expr<it, lxI, vI, vnI>        (. IF t = SymTab.InvalidType THEN
+ 1722                                             MGen.Drop;
+ 1723                                             IF doLoad THEN
+ 1724                                               MGen.Drop; MGen.PushInt(0);
+ 1725                                               t := SymTab.InvalidType
+ 1726                                             END
+ 1727                                           ELSIF SymTab.ClassOf(t) #
+ 1728                                                   SymTab.ClArray THEN
+ 1729                                             SemError(217);
+ 1730                                             t := SymTab.InvalidType;
+ 1731                                             MGen.Drop;
+ 1732                                             IF doLoad THEN
+ 1733                                               MGen.Drop; MGen.PushInt(0)
+ 1734                                             END
+ 1735                                           ELSE
+ 1736                                             clsI := SymTab.ClassOf(it);
+ 1737                                             IF (it
+ 1738                                                # SymTab.InvalidType)
+ 1739                                                & (clsI # SymTab.ClInt)
+ 1740                                                & (clsI # SymTab.ClChar)
+ 1741                                                & (clsI # SymTab.ClEnum)
+ 1742                                                & (clsI
+ 1743                                                   # SymTab.ClBool) THEN
+ 1744                                               SemError(218);
+ 1745                                               t := SymTab.InvalidType;
+ 1746                                               MGen.Drop;
  1747                                               IF doLoad THEN
- 1748                                                 IF ~(firstT
- 1749                                                    & ((k
- 1750                                                        = SymTab.KindVar)
- 1751                                                    OR (k
- 1752                                                        = SymTab.KindParam)
- 1753                                                    OR (k
- 1754                                                        = SymTab.KindVarPar)))
- 1755                                                 THEN
- 1756                                                   MGen.LoadIndir
- 1757                                                 END
- 1758                                               ELSE
- 1759                                                 MGen.LoadIndir
- 1760                                               END
- 1761                                             END; .) } .
- 1762    Expr <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
- 1763          VAR v: BOOLEAN; VAR vn: SymTab.Name>
- 1764                                          (. VAR t2: SymTab.TypeIndex;
- 1765                                               tc, op: INTEGER;
- 1766                                               lx2: MGen.LitStr;
- 1767                                               v2: BOOLEAN;
- 1768                                               vn2: SymTab.Name;
- 1769                                               r: BOOLEAN; .)
- 1770      = SimExpr<t, lx, v, vn> [ Rel<op> SimExpr<t2, lx2, v2, vn2>
- 1771        (. lx[0] := 0C; v := FALSE; MGen.ClrStash();
- 1772           IF op = SymTab.OpIn THEN
- 1773             IF SymTab.InCheck(t, t2) THEN
- 1774               t := SymTab.BoolType();
- 1775               MGen.BitIn
- 1776             ELSE SemError(222);
- 1777               t := SymTab.InvalidType;
- 1778               MGen.Drop; MGen.Drop; MGen.PushInt(0)
- 1779             END
- 1780           ELSIF (t # SymTab.InvalidType)
- 1781              & (t2 # SymTab.InvalidType)
- 1782              & (SymTab.ClassOf(t) = SymTab.ClArray)
- 1783              & (SymTab.ClassOf(t2) = SymTab.ClArray)
- 1784              & (SymTab.ClassOf(SymTab.ArrayElem(t)) = SymTab.ClChar)
- 1785              & (SymTab.ClassOf(SymTab.ArrayElem(t2)) = SymTab.ClChar)
- 1786              & ~SymTab.IsOpen(t) & ~SymTab.IsOpen(t2) THEN
- 1787             t := SymTab.BoolType();
- 1788             MGen.PushBytes(SymTab.TypeSlots(t) * 8);
- 1789             MGen.PushBytes(SymTab.TypeSlots(t2) * 8);
- 1790             MGen.StrComp;
- 1791             IF op = SymTab.OpEq THEN MGen.Or; MGen.Not
- 1792             ELSIF (op = SymTab.OpNeq1)
- 1793                   OR (op = SymTab.OpNeq2) THEN MGen.Or
- 1794             ELSIF op = SymTab.OpLt THEN
- 1795               MGen.Swap; MGen.Drop
- 1796             ELSIF op = SymTab.OpLe THEN
- 1797               MGen.Drop; MGen.Not
- 1798             ELSIF op = SymTab.OpGt THEN
- 1799               MGen.Drop
- 1800             ELSE
- 1801               MGen.Swap; MGen.Drop; MGen.Not
- 1802             END
- 1803           ELSIF (t # SymTab.InvalidType)
- 1804              & (t2 # SymTab.InvalidType)
- 1805              & ((SymTab.ClassOf(t) = SymTab.ClArray)
- 1806                 OR (SymTab.ClassOf(t) = SymTab.ClRecord)
- 1807                 OR (SymTab.ClassOf(t2) = SymTab.ClArray)
- 1808                 OR (SymTab.ClassOf(t2) = SymTab.ClRecord)) THEN
- 1809             SemError(213); t := SymTab.InvalidType;
- 1810             MGen.Drop; MGen.Drop; MGen.PushInt(0)
- 1811           ELSE
- 1812             tc := SymTab.ClassOf(t);
- 1813             IF SymTab.RelCheck(t, t2, op) THEN
- 1814               t := SymTab.BoolType()
- 1815             ELSE SemError(213); t := SymTab.InvalidType END;
- 1816             IF t # SymTab.InvalidType THEN
- 1817               r := tc = SymTab.ClReal;
- 1818               IF r THEN
- 1819                 IF op = SymTab.OpEq THEN MGen.RealEq
- 1820                 ELSIF (op = SymTab.OpNeq1)
- 1821                       OR (op = SymTab.OpNeq2) THEN MGen.RealNe
- 1822                 ELSIF op = SymTab.OpLt THEN MGen.RealLt
- 1823                 ELSIF op = SymTab.OpLe THEN MGen.RealLe
- 1824                 ELSIF op = SymTab.OpGt THEN MGen.RealGt
- 1825                 ELSE MGen.RealGe END
- 1826               ELSE
- 1827                 IF op = SymTab.OpEq THEN MGen.Eq
- 1828                 ELSIF (op = SymTab.OpNeq1)
- 1829                       OR (op = SymTab.OpNeq2) THEN MGen.Neq
- 1830                 ELSIF op = SymTab.OpLt THEN MGen.ILt
- 1831                 ELSIF op = SymTab.OpLe THEN MGen.ILe
- 1832                 ELSIF op = SymTab.OpGt THEN MGen.IGt
- 1833                 ELSE MGen.IGe END
- 1834               END
- 1835             ELSE MGen.Drop; MGen.Drop; MGen.PushInt(0)
- 1836             END
- 1837           END; .) ] .
- 1838    Rel <VAR op: INTEGER>
- 1839      = "="                     (. op := SymTab.OpEq; .)
- 1840      | "#"                     (. op := SymTab.OpNeq1; .)
- 1841      | "<>"                    (. op := SymTab.OpNeq2; .)
- 1842      | "<"                     (. op := SymTab.OpLt; .)
- 1843      | "<="                    (. op := SymTab.OpLe; .)
- 1844      | ">"                     (. op := SymTab.OpGt; .)
- 1845      | ">="                    (. op := SymTab.OpGe; .)
- 1846      | "IN"                    (. op := SymTab.OpIn; .) .
- 1847    SimExpr <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
- 1848             VAR v: BOOLEAN; VAR vn: SymTab.Name>
- 1849                                          (. VAR t2, res2: SymTab.TypeIndex;
- 1850                                               op: INTEGER;
- 1851                                               lx2: MGen.LitStr;
- 1852                                               v2: BOOLEAN;
- 1853                                               vn2: SymTab.Name;
- 1854                                               neg, isR: BOOLEAN; .)
- 1855      =                                   (. neg := FALSE; .)
- 1856        [ "+" | "-"                       (. neg := TRUE; .) ]
- 1857        Term<t, lx, v, vn>                (. IF neg THEN
- 1858                                             v := FALSE;
- 1859                                             MGen.ClrStash();
- 1860                                             IF MGen.IsLit(lx) THEN
- 1861                                               MGen.NegFold(lx, lx)
- 1862                                             ELSE lx[0] := 0C
- 1863                                             END;
- 1864                                             IF SymTab.ClassOf(t)
- 1865                                                = SymTab.ClReal THEN
- 1866                                               MGen.NegReal
- 1867                                             ELSE MGen.NegInt
- 1868                                             END
- 1869                                           END; .)
- 1870        { AddOp<op> Term<t2, lx2, v2, vn2>
- 1871        (. lx[0] := 0C; v := FALSE; MGen.ClrStash();
- 1872           IF op = SymTab.OpOr THEN
- 1873             IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
- 1874               t := SymTab.BoolType()
- 1875             ELSE SemError(212); t := SymTab.InvalidType END;
- 1876             MGen.Or
- 1877           ELSIF (t # SymTab.InvalidType)
- 1878              & (t2 # SymTab.InvalidType)
- 1879              & (SymTab.ClassOf(t) = SymTab.ClSet)
- 1880              & (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
- 1881             IF op = SymTab.OpAdd THEN
- 1882               MGen.Or
- 1883             ELSE
- 1884               MGen.PushBits(0FFFFFFFFFFFFFFFFH);
- 1885               MGen.BitXor;
- 1886               MGen.And
- 1887             END
- 1888           ELSE
- 1889             IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN t := res2
- 1890             ELSE SemError(211); t := SymTab.InvalidType END;
- 1891             isR := (t # SymTab.InvalidType)
- 1892                    & (SymTab.ClassOf(t) = SymTab.ClReal);
- 1893             IF op = SymTab.OpAdd THEN
- 1894               IF isR THEN MGen.RealAdd ELSE MGen.Add END
- 1895             ELSE
- 1896               IF isR THEN MGen.RealSub ELSE MGen.Sub END
- 1897             END
- 1898           END; .) } .
- 1899    AddOp <VAR op: INTEGER>
- 1900      = "+"                     (. op := SymTab.OpAdd; .)
- 1901      | "-"                     (. op := SymTab.OpSub; .)
- 1902      | "OR"                    (. op := SymTab.OpOr; .) .
- 1903    Term <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
- 1904          VAR v: BOOLEAN; VAR vn: SymTab.Name>
- 1905                                          (. VAR t2, res2: SymTab.TypeIndex;
- 1906                                               op: INTEGER;
- 1907                                               lx2: MGen.LitStr;
- 1908                                               v2: BOOLEAN;
- 1909                                               vn2: SymTab.Name;
- 1910                                               isR: BOOLEAN;
- 1911                                               mt: INTEGER; .)
- 1912      = Fact<t, lx, v, vn> { MulOp<op> Fact<t2, lx2, v2, vn2>
- 1913        (. lx[0] := 0C; v := FALSE; MGen.ClrStash();
- 1914           IF op = SymTab.OpAnd THEN
- 1915             IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
- 1916               t := SymTab.BoolType()
- 1917             ELSE SemError(212); t := SymTab.InvalidType END;
- 1918             MGen.And
- 1919           ELSIF (op = SymTab.OpTimes)
- 1920              & (t # SymTab.InvalidType)
- 1921              & (t2 # SymTab.InvalidType)
- 1922              & (SymTab.ClassOf(t) = SymTab.ClSet)
- 1923              & (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
- 1924             MGen.And
- 1925           ELSE
- 1926             IF SymTab.ArithCheck(t, t2,
- 1927                  (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
- 1928                  res2) THEN t := res2
- 1929             ELSE SemError(211); t := SymTab.InvalidType END;
- 1930             isR := (t # SymTab.InvalidType)
- 1931                    & (SymTab.ClassOf(t) = SymTab.ClReal);
- 1932             IF op = SymTab.OpTimes THEN
- 1933               IF isR THEN MGen.RealMul ELSE MGen.MulU END
- 1934             ELSIF op = SymTab.OpSlash THEN
- 1935               IF isR THEN MGen.RealDiv ELSE MGen.DivI END
- 1936             ELSIF op = SymTab.OpDiv THEN
- 1937               MGen.DivI
+ 1748                                                 MGen.Drop; MGen.PushInt(0)
+ 1749                                               END
+ 1750                                             ELSE
+ 1751                                               loA := SymTab.ArrayLo(t);
+ 1752                                               elemT := SymTab.ArrayElem(t);
+ 1753                                               esl := SymTab.TypeSlots(elemT);
+ 1754                                               IF esl = 0 THEN
+ 1755                                                 SemError(230);
+ 1756                                                 esl := 1
+ 1757                                               END;
+ 1758                                               IF (SymTab.ClassOf(elemT)
+ 1759                                                  = SymTab.ClChar)
+ 1760                                                  OR (SymTab.ClassOf(elemT)
+ 1761                                                     = SymTab.ClBool) THEN
+ 1762                                                 ebytes := 1
+ 1763                                               ELSE ebytes := esl * 8
+ 1764                                               END;
+ 1765                                               MGen.IdxScale(loA, ebytes);
+ 1766                                               t := elemT
+ 1767                                             END
+ 1768                                           END; .) }
+ 1769          "]"
+ 1770        | "^"                             (. firstT := ~sfx;
+ 1771                                             sfx := TRUE; lx[0] := 0C;
+ 1772                                             IF ~doLoad & firstT THEN
+ 1773                                               IF (k = SymTab.KindVar)
+ 1774                                                  OR (k = SymTab.KindParam)
+ 1775                                                  OR (k
+ 1776                                                      = SymTab.KindVarPar) THEN
+ 1777                                                 MGen.PushAddr(bn)
+ 1778                                               ELSIF k
+ 1779                                                 = SymTab.KindField THEN
+ 1780                                                 MGen.WithAddr(bn)
+ 1781                                               ELSE MGen.PushInt(0)
+ 1782                                               END
+ 1783                                             END; .)
+ 1784                                          (. IF t = SymTab.InvalidType THEN
+ 1785                                               IF doLoad THEN
+ 1786                                                 MGen.Drop; MGen.PushInt(0)
+ 1787                                               ELSIF firstT THEN
+ 1788                                                 MGen.Drop
+ 1789                                               END
+ 1790                                             ELSIF SymTab.ClassOf(t) #
+ 1791                                                   SymTab.ClPtr THEN
+ 1792                                               SemError(219);
+ 1793                                               t := SymTab.InvalidType;
+ 1794                                               IF doLoad THEN
+ 1795                                                 MGen.Drop; MGen.PushInt(0)
+ 1796                                               ELSIF firstT THEN
+ 1797                                                 MGen.Drop
+ 1798                                               END
+ 1799                                             ELSE
+ 1800                                               elemT := SymTab.PtrBase(t);
+ 1801                                               t := elemT;
+ 1802                                               IF doLoad THEN
+ 1803                                                 IF ~(firstT
+ 1804                                                    & ((k
+ 1805                                                        = SymTab.KindVar)
+ 1806                                                    OR (k
+ 1807                                                        = SymTab.KindParam)
+ 1808                                                    OR (k
+ 1809                                                        = SymTab.KindVarPar)))
+ 1810                                                 THEN
+ 1811                                                   MGen.LoadIndir
+ 1812                                                 END
+ 1813                                               ELSE
+ 1814                                                 MGen.LoadIndir
+ 1815                                               END
+ 1816                                             END; .) } .
+ 1817    Expr <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
+ 1818          VAR v: BOOLEAN; VAR vn: SymTab.Name>
+ 1819                                          (. VAR t2: SymTab.TypeIndex;
+ 1820                                               tc, op: INTEGER;
+ 1821                                               lx2: MGen.LitStr;
+ 1822                                               v2: BOOLEAN;
+ 1823                                               vn2: SymTab.Name;
+ 1824                                               r: BOOLEAN; .)
+ 1825      = SimExpr<t, lx, v, vn> [ Rel<op> SimExpr<t2, lx2, v2, vn2>
+ 1826        (. lx[0] := 0C; v := FALSE; MGen.ClrStash();
+ 1827           IF op = SymTab.OpIn THEN
+ 1828             IF SymTab.InCheck(t, t2) THEN
+ 1829               t := SymTab.BoolType();
+ 1830               MGen.BitIn
+ 1831             ELSE SemError(222);
+ 1832               t := SymTab.InvalidType;
+ 1833               MGen.Drop; MGen.Drop; MGen.PushInt(0)
+ 1834             END
+ 1835           ELSIF (t # SymTab.InvalidType)
+ 1836              & (t2 # SymTab.InvalidType)
+ 1837              & (SymTab.ClassOf(t) = SymTab.ClArray)
+ 1838              & (SymTab.ClassOf(t2) = SymTab.ClArray)
+ 1839              & (SymTab.ClassOf(SymTab.ArrayElem(t)) = SymTab.ClChar)
+ 1840              & (SymTab.ClassOf(SymTab.ArrayElem(t2)) = SymTab.ClChar)
+ 1841              & ~SymTab.IsOpen(t) & ~SymTab.IsOpen(t2) THEN
+ 1842             t := SymTab.BoolType();
+ 1843             MGen.PushBytes(SymTab.TypeSlots(t) * 8);
+ 1844             MGen.PushBytes(SymTab.TypeSlots(t2) * 8);
+ 1845             MGen.StrComp;
+ 1846             IF op = SymTab.OpEq THEN MGen.Or; MGen.Not
+ 1847             ELSIF (op = SymTab.OpNeq1)
+ 1848                   OR (op = SymTab.OpNeq2) THEN MGen.Or
+ 1849             ELSIF op = SymTab.OpLt THEN
+ 1850               MGen.Swap; MGen.Drop
+ 1851             ELSIF op = SymTab.OpLe THEN
+ 1852               MGen.Drop; MGen.Not
+ 1853             ELSIF op = SymTab.OpGt THEN
+ 1854               MGen.Drop
+ 1855             ELSE
+ 1856               MGen.Swap; MGen.Drop; MGen.Not
+ 1857             END
+ 1858           ELSIF (t # SymTab.InvalidType)
+ 1859              & (t2 # SymTab.InvalidType)
+ 1860              & ((SymTab.ClassOf(t) = SymTab.ClArray)
+ 1861                 OR (SymTab.ClassOf(t) = SymTab.ClRecord)
+ 1862                 OR (SymTab.ClassOf(t2) = SymTab.ClArray)
+ 1863                 OR (SymTab.ClassOf(t2) = SymTab.ClRecord)) THEN
+ 1864             SemError(213); t := SymTab.InvalidType;
+ 1865             MGen.Drop; MGen.Drop; MGen.PushInt(0)
+ 1866           ELSE
+ 1867             tc := SymTab.ClassOf(t);
+ 1868             IF SymTab.RelCheck(t, t2, op) THEN
+ 1869               t := SymTab.BoolType()
+ 1870             ELSE SemError(213); t := SymTab.InvalidType END;
+ 1871             IF t # SymTab.InvalidType THEN
+ 1872               r := tc = SymTab.ClReal;
+ 1873               IF r THEN
+ 1874                 IF op = SymTab.OpEq THEN MGen.RealEq
+ 1875                 ELSIF (op = SymTab.OpNeq1)
+ 1876                       OR (op = SymTab.OpNeq2) THEN MGen.RealNe
+ 1877                 ELSIF op = SymTab.OpLt THEN MGen.RealLt
+ 1878                 ELSIF op = SymTab.OpLe THEN MGen.RealLe
+ 1879                 ELSIF op = SymTab.OpGt THEN MGen.RealGt
+ 1880                 ELSE MGen.RealGe END
+ 1881               ELSE
+ 1882                 IF op = SymTab.OpEq THEN MGen.Eq
+ 1883                 ELSIF (op = SymTab.OpNeq1)
+ 1884                       OR (op = SymTab.OpNeq2) THEN MGen.Neq
+ 1885                 ELSIF op = SymTab.OpLt THEN MGen.ILt
+ 1886                 ELSIF op = SymTab.OpLe THEN MGen.ILe
+ 1887                 ELSIF op = SymTab.OpGt THEN MGen.IGt
+ 1888                 ELSE MGen.IGe END
+ 1889               END
+ 1890             ELSE MGen.Drop; MGen.Drop; MGen.PushInt(0)
+ 1891             END
+ 1892           END; .) ] .
+ 1893    Rel <VAR op: INTEGER>
+ 1894      = "="                     (. op := SymTab.OpEq; .)
+ 1895      | "#"                     (. op := SymTab.OpNeq1; .)
+ 1896      | "<>"                    (. op := SymTab.OpNeq2; .)
+ 1897      | "<"                     (. op := SymTab.OpLt; .)
+ 1898      | "<="                    (. op := SymTab.OpLe; .)
+ 1899      | ">"                     (. op := SymTab.OpGt; .)
+ 1900      | ">="                    (. op := SymTab.OpGe; .)
+ 1901      | "IN"                    (. op := SymTab.OpIn; .) .
+ 1902    SimExpr <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
+ 1903             VAR v: BOOLEAN; VAR vn: SymTab.Name>
+ 1904                                          (. VAR t2, res2: SymTab.TypeIndex;
+ 1905                                               op: INTEGER;
+ 1906                                               lx2: MGen.LitStr;
+ 1907                                               v2: BOOLEAN;
+ 1908                                               vn2: SymTab.Name;
+ 1909                                               neg, isR: BOOLEAN; .)
+ 1910      =                                   (. neg := FALSE; .)
+ 1911        [ "+" | "-"                       (. neg := TRUE; .) ]
+ 1912        Term<t, lx, v, vn>                (. IF neg THEN
+ 1913                                             v := FALSE;
+ 1914                                             MGen.ClrStash();
+ 1915                                             IF MGen.IsLit(lx) THEN
+ 1916                                               MGen.NegFold(lx, lx)
+ 1917                                             ELSE lx[0] := 0C
+ 1918                                             END;
+ 1919                                             IF SymTab.ClassOf(t)
+ 1920                                                = SymTab.ClReal THEN
+ 1921                                               MGen.NegReal
+ 1922                                             ELSE MGen.NegInt
+ 1923                                             END
+ 1924                                           END; .)
+ 1925        { AddOp<op> Term<t2, lx2, v2, vn2>
+ 1926        (. lx[0] := 0C; v := FALSE; MGen.ClrStash();
+ 1927           IF op = SymTab.OpOr THEN
+ 1928             IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
+ 1929               t := SymTab.BoolType()
+ 1930             ELSE SemError(212); t := SymTab.InvalidType END;
+ 1931             MGen.Or
+ 1932           ELSIF (t # SymTab.InvalidType)
+ 1933              & (t2 # SymTab.InvalidType)
+ 1934              & (SymTab.ClassOf(t) = SymTab.ClSet)
+ 1935              & (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
+ 1936             IF op = SymTab.OpAdd THEN
+ 1937               MGen.Or
  1938             ELSE
- 1939               mt := MGen.TempGlobal();
- 1940               MGen.ModI(mt)
- 1941             END
- 1942           END; .) } .
- 1943    MulOp <VAR op: INTEGER>
- 1944      = "*"                     (. op := SymTab.OpTimes; .)
- 1945      | "/"                     (. op := SymTab.OpSlash; .)
- 1946      | "DIV"                   (. op := SymTab.OpDiv; .)
- 1947      | "MOD"                   (. op := SymTab.OpMod; .)
- 1948      | "AND"                   (. op := SymTab.OpAnd; .)
- 1949      | "&"                     (. op := SymTab.OpAnd; .) .
- 1950    Fact <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
- 1951          VAR v: BOOLEAN; VAR vn: SymTab.Name>
- 1952                                          (. VAR s: ARRAY [0 .. 255] OF CHAR;
- 1953                                               t2, et, dt, st: SymTab.TypeIndex;
- 1954                                               dk: INTEGER;
- 1955                                               bnF: SymTab.Name;
- 1956                                               lxD, lx2: MGen.LitStr;
- 1957                                               v2: BOOLEAN;
- 1958                                               vn2: SymTab.Name;
- 1959                                               vi, mpF: INTEGER;
- 1960                                               c: CARDINAL;
- 1961                                               b: LONGCARD;
- 1962                                               sfxF: BOOLEAN;
- 1963                                               okF: BOOLEAN; .)
- 1964      = integer                         (. LexString(s);
- 1965                                           MGen.CopyName(s, lx);
- 1966                                           v := FALSE; MGen.ClrStash();
- 1967                                           IF MGen.ParseInt(s, vi) THEN
- 1968                                             MGen.PushInt(vi)
- 1969                                           ELSIF MGen.ParseCard(s, c) THEN
- 1970                                             MGen.PushBits(
- 1971                                               VAL(LONGCARD, c))
- 1972                                           ELSE MGen.PushInt(0)
- 1973                                           END;
- 1974                                           t := SymTab.IntType(); .)
- 1975      | real                            (. LexString(s);
- 1976                                           MGen.CopyName(s, lx);
- 1977                                           v := FALSE; MGen.ClrStash();
- 1978                                           IF MGen.ParseReal(s, b) THEN
- 1979                                             MGen.PushBits(b)
- 1980                                           ELSE MGen.PushBits(0H)
- 1981                                           END;
- 1982                                           t := SymTab.RealType(); .)
- 1983      | string                          (. LexString(s);
- 1984                                           v := FALSE; MGen.ClrStash();
- 1985                                           IF SymTab.StrLen(s) <= 3 THEN
- 1986                                             t := SymTab.CharType();
- 1987                                             MGen.CopyName(s, lx);
- 1988                                             MGen.PushInt(
- 1989                                               MGen.CharOrd(s))
- 1990                                           ELSE t := SymTab.NewStr();
- 1991                                             MGen.CopyName(s, lx);
- 1992                                             MGen.EmitString(s)
- 1993                                           END; .)
- 1994      | "HIGH"
- 1995        "(" DesignHead<dt, dk, bnF, FALSE, lxD>
- 1996            DesignTail<dt, dk, bnF, FALSE, lxD, sfxF>
- 1997        ")"                               (. lx[0] := 0C; v := FALSE; MGen.ClrStash();
- 1998                                             IF dt = SymTab.InvalidType THEN
- 1999                                               IF sfxF THEN MGen.Drop END;
- 2000                                               MGen.PushInt(0);
- 2001                                               t := SymTab.InvalidType
- 2002                                             ELSIF SymTab.ClassOf(dt)
- 2003                                                    # SymTab.ClArray THEN
- 2004                                               SemError(217);
- 2005                                               IF sfxF THEN MGen.Drop END;
- 2006                                               MGen.PushInt(0);
- 2007                                               t := SymTab.InvalidType
- 2008                                             ELSIF SymTab.IsOpen(dt) THEN
- 2009                                               IF sfxF THEN MGen.Drop END;
- 2010                                               IF (dk = SymTab.KindParam)
- 2011                                                  OR (dk
- 2012                                                   = SymTab.KindVarPar) THEN
- 2013                                                 IF SymTab.CurDepth()
- 2014                                                    = SymTab.SymDepth(bnF) THEN
- 2015                                                   MGen.LoadLocal(
- 2016                                                     SymTab.SymSlot(bnF) + 1)
- 2017                                                 ELSE
- 2018                                                   MGen.FrameAddr(
- 2019                                                     SymTab.SymSlot(bnF) + 1,
- 2020                                                     VAL(CARDINAL,
- 2021                                                       SymTab.CurDepth() - 1
- 2022                                                       - SymTab.SymDepth(bnF)));
- 2023                                                   MGen.LoadIndir
- 2024                                                 END;
- 2025                                                 MGen.PushInt(1);
- 2026                                                 MGen.Sub;
- 2027                                                 t := SymTab.IntType()
- 2028                                               ELSE
- 2029                                                 MGen.PushInt(0);
- 2030                                                 t := SymTab.InvalidType
- 2031                                               END
- 2032                                             ELSE
- 2033                                               IF sfxF THEN MGen.Drop END;
- 2034                                               MGen.PushInt(
- 2035                                                 SymTab.ArrayHi(dt));
- 2036                                               t := SymTab.IntType()
- 2037                                             END; .)
- 2038      | DesignHead<dt, dk, bnF, TRUE, lxD>
- 2039        DesignTail<dt, dk, bnF, TRUE, lxD, sfxF>
- 2040                                          (. t := dt;
- 2041                                             MGen.CopyName(lxD, lx);
- 2042                                             IF sfxF
- 2043                                                & (t # SymTab.InvalidType)
- 2044                                                & MGen.ActIsVarNext()
- 2045                                                & ((dk = SymTab.KindVar)
- 2046                                                   OR (dk
- 2047                                                       = SymTab.KindParam)
- 2048                                                   OR (dk
- 2049                                                       = SymTab.KindVarPar)
- 2050                                                   OR (dk
- 2051                                                       = SymTab.KindField))
- 2052                                                & (SymTab.SymKind(bnF)
- 2053                                                   # SymTab.KindModule)
- 2054                                                & (SymTab.ClassOf(t)
- 2055                                                   # SymTab.ClChar)
- 2056                                                & (SymTab.ClassOf(t)
- 2057                                                   # SymTab.ClBool) THEN
- 2058                                               MGen.StashAddr()
- 2059                                             END;
- 2060                                             IF sfxF
- 2061                                                & (t # SymTab.InvalidType)
- 2062                                                & (SymTab.ClassOf(t)
- 2063                                                   # SymTab.ClArray)
- 2064                                                & (SymTab.ClassOf(t)
- 2065                                                   # SymTab.ClRecord) THEN
- 2066                                               IF (SymTab.ClassOf(t)
- 2067                                                  = SymTab.ClChar)
- 2068                                                  OR (SymTab.ClassOf(t)
- 2069                                                     = SymTab.ClBool) THEN
- 2070                                                 MGen.LoadByte
- 2071                                               ELSE MGen.LoadIndir
- 2072                                               END
- 2073                                             END;
- 2074                                             v := ~sfxF
- 2075                                                  & ((dk = SymTab.KindVar)
- 2076                                                  OR (dk = SymTab.KindParam)
- 2077                                                  OR (dk
- 2078                                                      = SymTab.KindVarPar));
- 2079                                             MGen.CopyName(bnF, vn); .)
- 2080        [ CallTail<bnF, lxD, sfxF, TRUE, okF, TRUE>
- 2081                                          (. IF okF THEN
- 2082                                               IF SymTab.SymKind(bnF)
- 2083                                                  = SymTab.KindProc THEN
- 2084                                                 t := SymTab.ProcRet(bnF)
- 2085                                               ELSIF (SymTab.SymKind(bnF)
- 2086                                                         = SymTab.KindModule)
- 2087                                                  & sfxF
- 2088                                                  & (SymTab.StrLen(lxD) > 0) THEN
- 2089                                                 mpF := SymTab.ExpProc(bnF,
- 2090                                                          lxD);
- 2091                                                 IF (mpF < 0)
- 2092                                                    & (SymTab.SelfKind(bnF,
- 2093                                                         lxD)
- 2094                                                       = SymTab.KindProc) THEN
- 2095                                                   mpF := SymTab.ProcNum(lxD)
- 2096                                                 END;
- 2097                                                 IF mpF >= 0 THEN
- 2098                                                   t := SymTab.ProcRetByNum(mpF)
- 2099                                                 ELSE
- 2100                                                   t := SymTab.InvalidType
- 2101                                                 END
- 2102                                               ELSE
- 2103                                                 t := SymTab.InvalidType
- 2104                                               END
- 2105                                             ELSE t := SymTab.InvalidType
- 2106                                             END;
- 2107                                             lx[0] := 0C; v := FALSE;
- 2108                                             MGen.ClrStash(); .) ]
- 2109      | "("
- 2110        Expr<et, lx, v, vn> ")"         (. t := et; .)
- 2111      | ( "NOT" | "~" )
- 2112        Fact<t2, lx2, v2, vn2>          (. lx[0] := 0C; v := FALSE; MGen.ClrStash();
- 2113                                           IF SymTab.BoolCheck(t2) THEN
- 2114                                             t := SymTab.BoolType()
- 2115                                           ELSE SemError(212);
- 2116                                             t := SymTab.InvalidType END;
- 2117                                           MGen.Not; .)
- 2118      | SetLit<st>                      (. lx[0] := 0C; v := FALSE; MGen.ClrStash();
- 2119                                           t := st; .) .
- 2120    SetLit <VAR t: SymTab.TypeIndex>
- 2121                                          (. VAR first, et: SymTab.TypeIndex;
- 2122                                               lxE, lxE2: MGen.LitStr;
- 2123                                               vE, vE2: BOOLEAN;
- 2124                                               vnE, vnE2: SymTab.Name;
- 2125                                               hasR: BOOLEAN; .)
- 2126      = "{"
- 2127                                  (. MGen.PushInt(0);
- 2128                                     t := SymTab.SetFor(SymTab.IntType()); .)
- 2129        [ Elem<et, lxE, lxE2, hasR>   (. first := et;
- 2130                                         t := SymTab.SetFor(et);
- 2131                                         MGen.ClrStash();
- 2132                                         IF hasR THEN
- 2133                                           MGen.PushInt(1); MGen.Add;
- 2134                                           MGen.FieldMask
- 2135                                         ELSE MGen.Power2 END;
- 2136                                         MGen.Or; .)
- 2137          { ","
- 2138            Elem<et, lxE, lxE2, hasR> (. IF ~SymTab.SetElemCheck(first, et) THEN
- 2139                                         SemError(222) END;
- 2140                                         MGen.ClrStash();
- 2141                                         IF hasR THEN
- 2142                                           MGen.PushInt(1); MGen.Add;
- 2143                                           MGen.FieldMask
- 2144                                         ELSE MGen.Power2 END;
- 2145                                         MGen.Or; .) } ]
- 2146        "}" .
- 2147    Elem <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
- 2148          VAR lx2: MGen.LitStr; VAR hasR: BOOLEAN>
- 2149                                          (. VAR t2: SymTab.TypeIndex;
- 2150                                               vD, vD2: BOOLEAN;
- 2151                                               vnD, vnD2: SymTab.Name; .)
- 2152      = Expr<t, lx, vD, vnD>              (. hasR := FALSE;
- 2153                                             lx2[0] := 0C; .)
- 2154        [ ".."
- 2155          Expr<t2, lx2, vD2, vnD2>        (. IF ~SymTab.SetElemCheck(t, t2) THEN
- 2156                                             SemError(222) END;
- 2157                                             hasR := TRUE; .) ] .
- 2158  
- 2159    GetIdent <VAR n: SymTab.Name>
- 2160      = ident                           (. LexName(n); .) .
- 2161  
- 2162  END M2c.
+ 1939               MGen.PushBits(0FFFFFFFFFFFFFFFFH);
+ 1940               MGen.BitXor;
+ 1941               MGen.And
+ 1942             END
+ 1943           ELSE
+ 1944             IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN t := res2
+ 1945             ELSE SemError(211); t := SymTab.InvalidType END;
+ 1946             isR := (t # SymTab.InvalidType)
+ 1947                    & (SymTab.ClassOf(t) = SymTab.ClReal);
+ 1948             IF op = SymTab.OpAdd THEN
+ 1949               IF isR THEN MGen.RealAdd ELSE MGen.Add END
+ 1950             ELSE
+ 1951               IF isR THEN MGen.RealSub ELSE MGen.Sub END
+ 1952             END
+ 1953           END; .) } .
+ 1954    AddOp <VAR op: INTEGER>
+ 1955      = "+"                     (. op := SymTab.OpAdd; .)
+ 1956      | "-"                     (. op := SymTab.OpSub; .)
+ 1957      | "OR"                    (. op := SymTab.OpOr; .) .
+ 1958    Term <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
+ 1959          VAR v: BOOLEAN; VAR vn: SymTab.Name>
+ 1960                                          (. VAR t2, res2: SymTab.TypeIndex;
+ 1961                                               op: INTEGER;
+ 1962                                               lx2: MGen.LitStr;
+ 1963                                               v2: BOOLEAN;
+ 1964                                               vn2: SymTab.Name;
+ 1965                                               isR: BOOLEAN;
+ 1966                                               mt: INTEGER; .)
+ 1967      = Fact<t, lx, v, vn> { MulOp<op> Fact<t2, lx2, v2, vn2>
+ 1968        (. lx[0] := 0C; v := FALSE; MGen.ClrStash();
+ 1969           IF op = SymTab.OpAnd THEN
+ 1970             IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
+ 1971               t := SymTab.BoolType()
+ 1972             ELSE SemError(212); t := SymTab.InvalidType END;
+ 1973             MGen.And
+ 1974           ELSIF (op = SymTab.OpTimes)
+ 1975              & (t # SymTab.InvalidType)
+ 1976              & (t2 # SymTab.InvalidType)
+ 1977              & (SymTab.ClassOf(t) = SymTab.ClSet)
+ 1978              & (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
+ 1979             MGen.And
+ 1980           ELSE
+ 1981             IF SymTab.ArithCheck(t, t2,
+ 1982                  (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
+ 1983                  res2) THEN t := res2
+ 1984             ELSE SemError(211); t := SymTab.InvalidType END;
+ 1985             isR := (t # SymTab.InvalidType)
+ 1986                    & (SymTab.ClassOf(t) = SymTab.ClReal);
+ 1987             IF op = SymTab.OpTimes THEN
+ 1988               IF isR THEN MGen.RealMul ELSE MGen.MulU END
+ 1989             ELSIF op = SymTab.OpSlash THEN
+ 1990               IF isR THEN MGen.RealDiv ELSE MGen.DivI END
+ 1991             ELSIF op = SymTab.OpDiv THEN
+ 1992               MGen.DivI
+ 1993             ELSE
+ 1994               mt := MGen.TempGlobal();
+ 1995               MGen.ModI(mt)
+ 1996             END
+ 1997           END; .) } .
+ 1998    MulOp <VAR op: INTEGER>
+ 1999      = "*"                     (. op := SymTab.OpTimes; .)
+ 2000      | "/"                     (. op := SymTab.OpSlash; .)
+ 2001      | "DIV"                   (. op := SymTab.OpDiv; .)
+ 2002      | "MOD"                   (. op := SymTab.OpMod; .)
+ 2003      | "AND"                   (. op := SymTab.OpAnd; .)
+ 2004      | "&"                     (. op := SymTab.OpAnd; .) .
+ 2005    Fact <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
+ 2006          VAR v: BOOLEAN; VAR vn: SymTab.Name>
+ 2007                                          (. VAR s: ARRAY [0 .. 255] OF CHAR;
+ 2008                                               t2, et, dt, st: SymTab.TypeIndex;
+ 2009                                               dk: INTEGER;
+ 2010                                               bnF: SymTab.Name;
+ 2011                                               lxD, lx2: MGen.LitStr;
+ 2012                                               v2: BOOLEAN;
+ 2013                                               vn2: SymTab.Name;
+ 2014                                               vi, mpF: INTEGER;
+ 2015                                               c: CARDINAL;
+ 2016                                               b: LONGCARD;
+ 2017                                               sfxF: BOOLEAN;
+ 2018                                               okF: BOOLEAN; .)
+ 2019      = integer                         (. LexString(s);
+ 2020                                           MGen.CopyName(s, lx);
+ 2021                                           v := FALSE; MGen.ClrStash();
+ 2022                                           IF MGen.ParseInt(s, vi) THEN
+ 2023                                             MGen.PushInt(vi)
+ 2024                                           ELSIF MGen.ParseCard(s, c) THEN
+ 2025                                             MGen.PushBits(
+ 2026                                               VAL(LONGCARD, c))
+ 2027                                           ELSE MGen.PushInt(0)
+ 2028                                           END;
+ 2029                                           t := SymTab.IntType(); .)
+ 2030      | real                            (. LexString(s);
+ 2031                                           MGen.CopyName(s, lx);
+ 2032                                           v := FALSE; MGen.ClrStash();
+ 2033                                           IF MGen.ParseReal(s, b) THEN
+ 2034                                             MGen.PushBits(b)
+ 2035                                           ELSE MGen.PushBits(0H)
+ 2036                                           END;
+ 2037                                           t := SymTab.RealType(); .)
+ 2038      | string                          (. LexString(s);
+ 2039                                           v := FALSE; MGen.ClrStash();
+ 2040                                           IF SymTab.StrLen(s) <= 3 THEN
+ 2041                                             t := SymTab.CharType();
+ 2042                                             MGen.CopyName(s, lx);
+ 2043                                             MGen.PushInt(
+ 2044                                               MGen.CharOrd(s))
+ 2045                                           ELSE t := SymTab.NewStr();
+ 2046                                             MGen.CopyName(s, lx);
+ 2047                                             MGen.EmitString(s)
+ 2048                                           END; .)
+ 2049      | "HIGH"
+ 2050        "(" DesignHead<dt, dk, bnF, FALSE, lxD>
+ 2051            DesignTail<dt, dk, bnF, FALSE, lxD, sfxF>
+ 2052        ")"                               (. lx[0] := 0C; v := FALSE; MGen.ClrStash();
+ 2053                                             IF dt = SymTab.InvalidType THEN
+ 2054                                               IF sfxF THEN MGen.Drop END;
+ 2055                                               MGen.PushInt(0);
+ 2056                                               t := SymTab.InvalidType
+ 2057                                             ELSIF SymTab.ClassOf(dt)
+ 2058                                                    # SymTab.ClArray THEN
+ 2059                                               SemError(217);
+ 2060                                               IF sfxF THEN MGen.Drop END;
+ 2061                                               MGen.PushInt(0);
+ 2062                                               t := SymTab.InvalidType
+ 2063                                             ELSIF SymTab.IsOpen(dt) THEN
+ 2064                                               IF sfxF THEN MGen.Drop END;
+ 2065                                               IF (dk = SymTab.KindParam)
+ 2066                                                  OR (dk
+ 2067                                                   = SymTab.KindVarPar) THEN
+ 2068                                                 IF SymTab.CurDepth()
+ 2069                                                    = SymTab.SymDepth(bnF) THEN
+ 2070                                                   MGen.LoadLocal(
+ 2071                                                     SymTab.SymSlot(bnF) + 1)
+ 2072                                                 ELSE
+ 2073                                                   MGen.FrameAddr(
+ 2074                                                     SymTab.SymSlot(bnF) + 1,
+ 2075                                                     VAL(CARDINAL,
+ 2076                                                       SymTab.CurDepth() - 1
+ 2077                                                       - SymTab.SymDepth(bnF)));
+ 2078                                                   MGen.LoadIndir
+ 2079                                                 END;
+ 2080                                                 MGen.PushInt(1);
+ 2081                                                 MGen.Sub;
+ 2082                                                 t := SymTab.IntType()
+ 2083                                               ELSE
+ 2084                                                 MGen.PushInt(0);
+ 2085                                                 t := SymTab.InvalidType
+ 2086                                               END
+ 2087                                             ELSE
+ 2088                                               IF sfxF THEN MGen.Drop END;
+ 2089                                               MGen.PushInt(
+ 2090                                                 SymTab.ArrayHi(dt));
+ 2091                                               t := SymTab.IntType()
+ 2092                                             END; .)
+ 2093      | DesignHead<dt, dk, bnF, TRUE, lxD>
+ 2094        DesignTail<dt, dk, bnF, TRUE, lxD, sfxF>
+ 2095                                          (. t := dt;
+ 2096                                             MGen.CopyName(lxD, lx);
+ 2097                                             IF sfxF
+ 2098                                                & (t # SymTab.InvalidType)
+ 2099                                                & MGen.ActIsVarNext()
+ 2100                                                & ((dk = SymTab.KindVar)
+ 2101                                                   OR (dk
+ 2102                                                       = SymTab.KindParam)
+ 2103                                                   OR (dk
+ 2104                                                       = SymTab.KindVarPar)
+ 2105                                                   OR (dk
+ 2106                                                       = SymTab.KindField))
+ 2107                                                & (SymTab.SymKind(bnF)
+ 2108                                                   # SymTab.KindModule)
+ 2109                                                & (SymTab.ClassOf(t)
+ 2110                                                   # SymTab.ClChar)
+ 2111                                                & (SymTab.ClassOf(t)
+ 2112                                                   # SymTab.ClBool) THEN
+ 2113                                               MGen.StashAddr()
+ 2114                                             END;
+ 2115                                             IF sfxF
+ 2116                                                & (t # SymTab.InvalidType)
+ 2117                                                & (SymTab.ClassOf(t)
+ 2118                                                   # SymTab.ClArray)
+ 2119                                                & (SymTab.ClassOf(t)
+ 2120                                                   # SymTab.ClRecord) THEN
+ 2121                                               IF (SymTab.ClassOf(t)
+ 2122                                                  = SymTab.ClChar)
+ 2123                                                  OR (SymTab.ClassOf(t)
+ 2124                                                     = SymTab.ClBool) THEN
+ 2125                                                 MGen.LoadByte
+ 2126                                               ELSE MGen.LoadIndir
+ 2127                                               END
+ 2128                                             END;
+ 2129                                             v := ~sfxF
+ 2130                                                  & ((dk = SymTab.KindVar)
+ 2131                                                  OR (dk = SymTab.KindParam)
+ 2132                                                  OR (dk
+ 2133                                                      = SymTab.KindVarPar));
+ 2134                                             MGen.CopyName(bnF, vn); .)
+ 2135        [ CallTail<bnF, lxD, sfxF, TRUE, okF, TRUE>
+ 2136                                          (. IF okF THEN
+ 2137                                               IF SymTab.SymKind(bnF)
+ 2138                                                  = SymTab.KindProc THEN
+ 2139                                                 t := SymTab.ProcRet(bnF)
+ 2140                                               ELSIF (SymTab.SymKind(bnF)
+ 2141                                                         = SymTab.KindModule)
+ 2142                                                  & sfxF
+ 2143                                                  & (SymTab.StrLen(lxD) > 0) THEN
+ 2144                                                 mpF := SymTab.ExpProc(bnF,
+ 2145                                                          lxD);
+ 2146                                                 IF (mpF < 0)
+ 2147                                                    & (SymTab.SelfKind(bnF,
+ 2148                                                         lxD)
+ 2149                                                       = SymTab.KindProc) THEN
+ 2150                                                   mpF := SymTab.ProcNum(lxD)
+ 2151                                                 END;
+ 2152                                                 IF mpF >= 0 THEN
+ 2153                                                   t := SymTab.ProcRetByNum(mpF)
+ 2154                                                 ELSE
+ 2155                                                   t := SymTab.InvalidType
+ 2156                                                 END
+ 2157                                               ELSE
+ 2158                                                 t := SymTab.InvalidType
+ 2159                                               END
+ 2160                                             ELSE t := SymTab.InvalidType
+ 2161                                             END;
+ 2162                                             lx[0] := 0C; v := FALSE;
+ 2163                                             MGen.ClrStash(); .) ]
+ 2164      | "("
+ 2165        Expr<et, lx, v, vn> ")"         (. t := et; .)
+ 2166      | ( "NOT" | "~" )
+ 2167        Fact<t2, lx2, v2, vn2>          (. lx[0] := 0C; v := FALSE; MGen.ClrStash();
+ 2168                                           IF SymTab.BoolCheck(t2) THEN
+ 2169                                             t := SymTab.BoolType()
+ 2170                                           ELSE SemError(212);
+ 2171                                             t := SymTab.InvalidType END;
+ 2172                                           MGen.Not; .)
+ 2173      | SetLit<st>                      (. lx[0] := 0C; v := FALSE; MGen.ClrStash();
+ 2174                                           t := st; .) .
+ 2175    SetLit <VAR t: SymTab.TypeIndex>
+ 2176                                          (. VAR first, et: SymTab.TypeIndex;
+ 2177                                               lxE, lxE2: MGen.LitStr;
+ 2178                                               vE, vE2: BOOLEAN;
+ 2179                                               vnE, vnE2: SymTab.Name;
+ 2180                                               hasR: BOOLEAN; .)
+ 2181      = "{"
+ 2182                                  (. MGen.PushInt(0);
+ 2183                                     t := SymTab.SetFor(SymTab.IntType()); .)
+ 2184        [ Elem<et, lxE, lxE2, hasR>   (. first := et;
+ 2185                                         t := SymTab.SetFor(et);
+ 2186                                         MGen.ClrStash();
+ 2187                                         IF hasR THEN
+ 2188                                           MGen.PushInt(1); MGen.Add;
+ 2189                                           MGen.FieldMask
+ 2190                                         ELSE MGen.Power2 END;
+ 2191                                         MGen.Or; .)
+ 2192          { ","
+ 2193            Elem<et, lxE, lxE2, hasR> (. IF ~SymTab.SetElemCheck(first, et) THEN
+ 2194                                         SemError(222) END;
+ 2195                                         MGen.ClrStash();
+ 2196                                         IF hasR THEN
+ 2197                                           MGen.PushInt(1); MGen.Add;
+ 2198                                           MGen.FieldMask
+ 2199                                         ELSE MGen.Power2 END;
+ 2200                                         MGen.Or; .) } ]
+ 2201        "}" .
+ 2202    Elem <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
+ 2203          VAR lx2: MGen.LitStr; VAR hasR: BOOLEAN>
+ 2204                                          (. VAR t2: SymTab.TypeIndex;
+ 2205                                               vD, vD2: BOOLEAN;
+ 2206                                               vnD, vnD2: SymTab.Name; .)
+ 2207      = Expr<t, lx, vD, vnD>              (. hasR := FALSE;
+ 2208                                             lx2[0] := 0C; .)
+ 2209        [ ".."
+ 2210          Expr<t2, lx2, vD2, vnD2>        (. IF ~SymTab.SetElemCheck(t, t2) THEN
+ 2211                                             SemError(222) END;
+ 2212                                             hasR := TRUE; .) ] .
+ 2213  
+ 2214    GetIdent <VAR n: SymTab.Name>
+ 2215      = ident                           (. LexName(n); .) .
+ 2216  
+ 2217    (* ---- step-11 separate compilation units (at end: the DEFINITION
+ 2218       and IMPLEMENTATION keywords take fresh token numbers, leaving
+ 2219       every existing token — and M2c.mod's messages — untouched) ---- *)
+ 2220    DefUnit                               (. VAR m1, m2: SymTab.Name; .)
+ 2221      = "DEFINITION" "MODULE"
+ 2222        GetIdent<m1>                      (. IF ~SymTab.EnterModule(m1) THEN
+ 2223                                               SemError(200)
+ 2224                                             END; .)
+ 2225        ";"
+ 2226        { Import }
+ 2227        { DefDecl }
+ 2228        "END"
+ 2229        GetIdent<m2>                      (. IF ~SymTab.Equal(m1, m2) THEN
+ 2230                                               SemError(202)
+ 2231                                             END;
+ 2232                                             IF ~SymTab.ExitDefinition() THEN
+ 2233                                               SemError(230)
+ 2234                                             END; .)
+ 2235        "." .
+ 2236    DefDecl
+ 2237      = "CONST" { ConstDecl ";" }
+ 2238      | "TYPE" { TypeDecl ";" }
+ 2239      | "VAR" { VarDecl ";" }
+ 2240      | DefProcHead .
+ 2241    DefProcHead                           (. VAR n: SymTab.Name;
+ 2242                                               rt: SymTab.TypeIndex;
+ 2243                                               hasR, ok: BOOLEAN; .)
+ 2244      = "PROCEDURE"                       (. hasR := FALSE; .)
+ 2245        GetIdent<n>                       (. IF ~SymTab.EnterProc(n) THEN
+ 2246                                               SemError(200)
+ 2247                                             END;
+ 2248                                             SymTab.OpenProcScope; .)
+ 2249        [ "(" FormalParams ")" ]
+ 2250        [ ":" QualIdent<rt>               (. hasR := TRUE; .) ]
+ 2251                                          (. IF hasR THEN
+ 2252                                               ok := SymTab.SetProcRet(rt)
+ 2253                                             ELSE
+ 2254                                               ok := SymTab.SetProcRet(
+ 2255                                                       SymTab.InvalidType)
+ 2256                                             END;
+ 2257                                             IF ~ok THEN SemError(231) END;
+ 2258                                             IF ~SymTab.VerifyProc() THEN
+ 2259                                               SemError(231)
+ 2260                                             END;
+ 2261                                             SymTab.SetForward;
+ 2262                                             SymTab.CloseProc; .)
+ 2263        ";" .
+ 2264    ImplUnit                              (. VAR m1, m2: SymTab.Name;
+ 2265                                               hasInit: BOOLEAN;
+ 2266                                               initL, initN: INTEGER; .)
+ 2267      = "IMPLEMENTATION" "MODULE"
+ 2268        GetIdent<m1>                      (. hasInit := FALSE;
+ 2269                                             IF ~SymTab.OpenImplementation(m1)
+ 2270                                             THEN
+ 2271                                               SemError(201)
+ 2272                                             END; .)
+ 2273        ";"
+ 2274        { Import }
+ 2275        { Declaration }
+ 2276        [ "BEGIN"                         (. hasInit := TRUE;
+ 2277                                             initL := MGen.NewLabel();
+ 2278                                             MGen.Jmp(initL);
+ 2279                                             initN := MGen.ModInitBegin();
+ 2280                                             IF initN < 0 THEN
+ 2281                                               SemError(230)
+ 2282                                             END; .)
+ 2283          StatSeq ]
+ 2284        "END"
+ 2285        GetIdent<m2>                      (. IF ~SymTab.Equal(m1, m2) THEN
+ 2286                                               SemError(202)
+ 2287                                             END;
+ 2288                                             IF hasInit THEN
+ 2289                                               MGen.ModInitEnd(initN);
+ 2290                                               MGen.DefLabel(initL)
+ 2291                                             END;
+ 2292                                             IF ~SymTab.CloseImplementation()
+ 2293                                             THEN
+ 2294                                               SemError(231)
+ 2295                                             END; .) .
+ 2296    ProgUnit                              (. VAR m1, m2: SymTab.Name; .)
+ 2297      = "MODULE"
+ 2298        GetIdent<m1>                      (. IF ~SymTab.NoteProgram() THEN
+ 2299                                               SemError(230)
+ 2300                                             END;
+ 2301                                             MGen.SetModName(m1);
+ 2302                                             IF ~SymTab.Enter(m1,
+ 2303                                               SymTab.KindModule)
+ 2304                                             THEN SemError(200) END; .)
+ 2305        ";"
+ 2306        { Import } Block<FALSE> GetIdent<m2>
+ 2307                                          (. IF ~SymTab.Equal(m1, m2)
+ 2308                                             THEN SemError(202) END; .)
+ 2309        "."                               (. IF SymTab.AnyForward() THEN
+ 2310                                               SemError(231)
+ 2311                                             END;
+ 2312                                             MGen.EndModule;
+ 2313                                             SymTab.PrintTable; .) .
+ 2314  
+ 2315  END M2c.
 
     0 errors
 
 
 Statistics:
 
-  nr of terminals:        76 (limit   400)
-  nr of non-terminals:    57 (limit   210)
-  nr of pragmas:           0 (limit   424)
-  nr of symbolnodes:     133 (limit   500)
-  nr of graphnodes:      572 (limit  1500)
+  nr of terminals:        78 (limit   400)
+  nr of non-terminals:    63 (limit   210)
+  nr of pragmas:           0 (limit   422)
+  nr of symbolnodes:     141 (limit   500)
+  nr of graphnodes:      643 (limit  1500)
   nr of conditionsets:     7 (limit   100)
   nr of charactersets:     9 (limit   250)
 

+ 83 - 58
M2c.mod

@@ -6,7 +6,7 @@ MODULE M2c;
   FROM M2cS IMPORT lst, src, errors, Error, CharAt;
   FROM M2cP IMPORT Parse, Successful;
   IMPORT
-    Strings, Storage, SYSTEM, FileIO;
+    Strings, Storage, SYSTEM, FileIO, SymTab, MGen;
 
   TYPE
     INT32 = FileIO.INT32 (* 32 bit integers needed *);
@@ -100,24 +100,24 @@ MODULE M2c;
         |  2: Msg("integer expected")
         |  3: Msg("real expected")
         |  4: Msg("string expected")
-        |  5: Msg("'MODULE' expected")
-        |  6: Msg("';' expected")
-        |  7: Msg("'.' expected")
-        |  8: Msg("'FROM' expected")
-        |  9: Msg("'IMPORT' expected")
-        | 10: Msg("',' expected")
-        | 11: Msg("'BEGIN' expected")
-        | 12: Msg("'END' expected")
-        | 13: Msg("'CONST' expected")
-        | 14: Msg("'TYPE' expected")
-        | 15: Msg("'VAR' expected")
-        | 16: Msg("'=' expected")
-        | 17: Msg("':' expected")
-        | 18: Msg("'PROCEDURE' expected")
-        | 19: Msg("'(' expected")
-        | 20: Msg("')' expected")
-        | 21: Msg("'FORWARD' expected")
-        | 22: Msg("'EXPORT' expected")
+        |  5: Msg("'FROM' expected")
+        |  6: Msg("'IMPORT' expected")
+        |  7: Msg("',' expected")
+        |  8: Msg("';' expected")
+        |  9: Msg("'BEGIN' expected")
+        | 10: Msg("'END' expected")
+        | 11: Msg("'CONST' expected")
+        | 12: Msg("'TYPE' expected")
+        | 13: Msg("'VAR' expected")
+        | 14: Msg("'=' expected")
+        | 15: Msg("':' expected")
+        | 16: Msg("'PROCEDURE' expected")
+        | 17: Msg("'(' expected")
+        | 18: Msg("')' expected")
+        | 19: Msg("'FORWARD' expected")
+        | 20: Msg("'MODULE' expected")
+        | 21: Msg("'EXPORT' expected")
+        | 22: Msg("'.' expected")
         | 23: Msg("'[' expected")
         | 24: Msg("'..' expected")
         | 25: Msg("']' expected")
@@ -170,18 +170,22 @@ MODULE M2c;
         | 72: Msg("'~' expected")
         | 73: Msg("'{' expected")
         | 74: Msg("'}' expected")
-        | 75: Msg("not expected")
-        | 76: Msg("invalid MulOp")
-        | 77: Msg("invalid Fact")
-        | 78: Msg("invalid AddOp")
-        | 79: Msg("invalid Rel")
-        | 80: Msg("invalid ByLit")
-        | 81: Msg("invalid AssignOrCall")
-        | 82: Msg("invalid SimpleType")
-        | 83: Msg("invalid Type")
-        | 84: Msg("invalid ProcedureDecl")
-        | 85: Msg("invalid Declaration")
-        | 86: Msg("invalid Import")
+        | 75: Msg("'DEFINITION' expected")
+        | 76: Msg("'IMPLEMENTATION' expected")
+        | 77: Msg("not expected")
+        | 78: Msg("invalid DefDecl")
+        | 79: Msg("invalid MulOp")
+        | 80: Msg("invalid Fact")
+        | 81: Msg("invalid AddOp")
+        | 82: Msg("invalid Rel")
+        | 83: Msg("invalid ByLit")
+        | 84: Msg("invalid AssignOrCall")
+        | 85: Msg("invalid SimpleType")
+        | 86: Msg("invalid Type")
+        | 87: Msg("invalid ProcedureDecl")
+        | 88: Msg("invalid Declaration")
+        | 89: Msg("invalid Import")
+        | 90: Msg("invalid Unit")
         
         (* add customized cases here *)
         | 200: Msg("duplicate identifier")
@@ -274,6 +278,7 @@ MODULE M2c;
 
   VAR
     sourceName, listName: ARRAY [0 .. 255] OF CHAR;
+    failed: BOOLEAN;
 
   BEGIN
     (* check on correct parameter usage *)
@@ -283,39 +288,59 @@ MODULE M2c;
       HALT
     END;
 
-    (* open the source file - Scanner.src *)
-    FileIO.Open(src, sourceName, FALSE);
-    IF ~ FileIO.Okay THEN
-      FileIO.WriteString(FileIO.StdOut, "Could not open input file");
-      FileIO.WriteLn(FileIO.StdOut);
-      HALT
-    END;
-
-    (* open the output file for the source listing - Scanner.lst *)
-    ChangeExtension(sourceName, ".LST", listName);
-    FileIO.Open(lst, listName, TRUE);
-    IF ~ FileIO.Okay THEN
-      FileIO.WriteString(FileIO.StdOut, "Could not open listing file");
-      FileIO.WriteLn(FileIO.StdOut);
-      (* default Scanner.lst to screen *) lst := FileIO.StdOut;
-    END;
+    (* one session for all files: definitions, then
+       implementations, then the program (see M2c.atg) *)
+    SymTab.Init;
+    MGen.OpenModule("");
 
     (* install error reporting procedure - Scanner.Error *)
     Error := StoreError;
 
-    (* instigate the compilation - Parser.Parse *)
-    FileIO.WriteString(FileIO.StdOut, "Parsing"); FileIO.WriteLn(FileIO.StdOut);
-    Parse;
+    failed := FALSE;
+    LOOP
+      IF sourceName[0] = 0C THEN EXIT END;
+
+      (* open the source file - Scanner.src *)
+      FileIO.Open(src, sourceName, FALSE);
+      IF ~ FileIO.Okay THEN
+        FileIO.WriteString(FileIO.StdOut, "Could not open input file");
+        FileIO.WriteLn(FileIO.StdOut);
+        HALT
+      END;
+
+      (* open the output file for the source listing - Scanner.lst *)
+      ChangeExtension(sourceName, ".LST", listName);
+      FileIO.Open(lst, listName, TRUE);
+      IF ~ FileIO.Okay THEN
+        FileIO.WriteString(FileIO.StdOut, "Could not open listing file");
+        FileIO.WriteLn(FileIO.StdOut);
+        (* default Scanner.lst to screen *) lst := FileIO.StdOut;
+      END;
+
+      (* instigate the compilation - Parser.Parse *)
+      FileIO.WriteString(FileIO.StdOut, "Parsing ");
+      FileIO.WriteString(FileIO.StdOut, sourceName);
+      FileIO.WriteLn(FileIO.StdOut);
+      Parse;
+
+      (* generate the source listing on lst file *)
+      PrintListing;
+      IF lst # FileIO.StdOut THEN FileIO.Close(lst) END;
+
+      (* fail fast: later files build on this one's tables *)
+      IF NOT Successful()
+        THEN
+          FileIO.WriteString(FileIO.StdOut, "Incorrect source");
+          FileIO.WriteLn(FileIO.StdOut);
+          failed := TRUE;
+          EXIT
+      END;
 
-    (* generate the source listing on lst file *)
-    PrintListing;
-    IF lst # FileIO.StdOut THEN FileIO.Close(lst) END;
+      FileIO.NextParameter(sourceName);
+    END;
 
     (* examine the outcome *)
-    IF NOT Successful()
-      THEN
-        FileIO.WriteString(FileIO.StdOut, "Incorrect source");
-      ELSE
-        FileIO.WriteString(FileIO.StdOut, "Parsed correctly");
+    IF NOT failed THEN
+      FileIO.WriteString(FileIO.StdOut, "Parsed correctly");
     END;
   END M2c.

BIN
M2c.o


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 334 - 131
M2cP.mod


BIN
M2cP.o


+ 28 - 26
M2cS.mod

@@ -5,7 +5,7 @@ IMPLEMENTATION MODULE M2cS;
 IMPORT FileIO, Storage;
 
 CONST
-  noSYMB  = 75; (*error token code*)
+  noSYMB  = 77; (*error token code*)
   (* not only for errors but also for not finished states of scanner analysis *)
   eof     = 32C (* MS-DOS Keyboard eof char *);
   EOF     = 0C;
@@ -105,36 +105,38 @@ PROCEDURE Get (VAR sym: CARDINAL);
         "A": IF Equal("AND") THEN sym := 68; 
              ELSIF Equal("ARRAY") THEN sym := 26; 
              END
-      | "B": IF Equal("BEGIN") THEN sym := 11; 
+      | "B": IF Equal("BEGIN") THEN sym := 9; 
              ELSIF Equal("BY") THEN sym := 46; 
              END
       | "C": IF Equal("CASE") THEN sym := 38; 
-             ELSIF Equal("CONST") THEN sym := 13; 
+             ELSIF Equal("CONST") THEN sym := 11; 
              END
-      | "D": IF Equal("DISPOSE") THEN sym := 51; 
+      | "D": IF Equal("DEFINITION") THEN sym := 75; 
+             ELSIF Equal("DISPOSE") THEN sym := 51; 
              ELSIF Equal("DIV") THEN sym := 66; 
              ELSIF Equal("DO") THEN sym := 41; 
              END
       | "E": IF Equal("ELSE") THEN sym := 37; 
              ELSIF Equal("ELSIF") THEN sym := 36; 
-             ELSIF Equal("END") THEN sym := 12; 
+             ELSIF Equal("END") THEN sym := 10; 
              ELSIF Equal("EXIT") THEN sym := 32; 
-             ELSIF Equal("EXPORT") THEN sym := 22; 
+             ELSIF Equal("EXPORT") THEN sym := 21; 
              END
       | "F": IF Equal("FOR") THEN sym := 45; 
-             ELSIF Equal("FORWARD") THEN sym := 21; 
-             ELSIF Equal("FROM") THEN sym := 8; 
+             ELSIF Equal("FORWARD") THEN sym := 19; 
+             ELSIF Equal("FROM") THEN sym := 5; 
              END
       | "H": IF Equal("HIGH") THEN sym := 70; 
              END
       | "I": IF Equal("IF") THEN sym := 34; 
-             ELSIF Equal("IMPORT") THEN sym := 9; 
+             ELSIF Equal("IMPLEMENTATION") THEN sym := 76; 
+             ELSIF Equal("IMPORT") THEN sym := 6; 
              ELSIF Equal("IN") THEN sym := 61; 
              END
       | "L": IF Equal("LOOP") THEN sym := 44; 
              END
       | "M": IF Equal("MOD") THEN sym := 67; 
-             ELSIF Equal("MODULE") THEN sym := 5; 
+             ELSIF Equal("MODULE") THEN sym := 20; 
              END
       | "N": IF Equal("NEW") THEN sym := 50; 
              ELSIF Equal("NOT") THEN sym := 71; 
@@ -143,7 +145,7 @@ PROCEDURE Get (VAR sym: CARDINAL);
              ELSIF Equal("OR") THEN sym := 63; 
              END
       | "P": IF Equal("POINTER") THEN sym := 30; 
-             ELSIF Equal("PROCEDURE") THEN sym := 18; 
+             ELSIF Equal("PROCEDURE") THEN sym := 16; 
              END
       | "R": IF Equal("RECORD") THEN sym := 28; 
              ELSIF Equal("REPEAT") THEN sym := 42; 
@@ -153,11 +155,11 @@ PROCEDURE Get (VAR sym: CARDINAL);
              END
       | "T": IF Equal("THEN") THEN sym := 35; 
              ELSIF Equal("TO") THEN sym := 31; 
-             ELSIF Equal("TYPE") THEN sym := 14; 
+             ELSIF Equal("TYPE") THEN sym := 12; 
              END
       | "U": IF Equal("UNTIL") THEN sym := 43; 
              END
-      | "V": IF Equal("VAR") THEN sym := 15; 
+      | "V": IF Equal("VAR") THEN sym := 13; 
              END
       | "W": IF Equal("WHILE") THEN sym := 40; 
              ELSIF Equal("WITH") THEN sym := 48; 
@@ -231,17 +233,17 @@ PROCEDURE Get (VAR sym: CARDINAL);
             ELSIF (ch = "E") THEN state := 6; apx := Long0 
             ELSE sym := 3; RETURN
             END;
-      | 14: sym := 6; RETURN
-      | 15: IF (ch = ".") THEN state := 22; 
-            ELSE sym := 7; RETURN
+      | 14: sym := 7; RETURN
+      | 15: sym := 8; RETURN
+      | 16: sym := 14; RETURN
+      | 17: IF (ch = "=") THEN state := 24; 
+            ELSE sym := 15; RETURN
             END;
-      | 16: sym := 10; RETURN
-      | 17: sym := 16; RETURN
-      | 18: IF (ch = "=") THEN state := 24; 
-            ELSE sym := 17; RETURN
+      | 18: sym := 17; RETURN
+      | 19: sym := 18; RETURN
+      | 20: IF (ch = ".") THEN state := 22; 
+            ELSE sym := 22; RETURN
             END;
-      | 19: sym := 19; RETURN
-      | 20: sym := 20; RETURN
       | 21: sym := 23; RETURN
       | 22: sym := 24; RETURN
       | 23: sym := 25; RETURN
@@ -345,12 +347,12 @@ BEGIN
   start[ 28] := 42; start[ 29] := 42; start[ 30] := 42; start[ 31] := 42; 
   start[ 32] := 42; start[ 33] := 42; start[ 34] := 10; start[ 35] := 28; 
   start[ 36] := 42; start[ 37] := 42; start[ 38] := 37; start[ 39] :=  9; 
-  start[ 40] := 19; start[ 41] := 20; start[ 42] := 35; start[ 43] := 34; 
-  start[ 44] := 16; start[ 45] := 26; start[ 46] := 15; start[ 47] := 36; 
+  start[ 40] := 18; start[ 41] := 19; start[ 42] := 35; start[ 43] := 34; 
+  start[ 44] := 14; start[ 45] := 26; start[ 46] := 20; start[ 47] := 36; 
   start[ 48] := 12; start[ 49] := 12; start[ 50] := 12; start[ 51] := 12; 
   start[ 52] := 12; start[ 53] := 12; start[ 54] := 12; start[ 55] := 12; 
-  start[ 56] := 12; start[ 57] := 12; start[ 58] := 18; start[ 59] := 14; 
-  start[ 60] := 29; start[ 61] := 17; start[ 62] := 32; start[ 63] := 42; 
+  start[ 56] := 12; start[ 57] := 12; start[ 58] := 17; start[ 59] := 15; 
+  start[ 60] := 29; start[ 61] := 16; start[ 62] := 32; start[ 63] := 42; 
   start[ 64] := 42; start[ 65] :=  1; start[ 66] :=  1; start[ 67] :=  1; 
   start[ 68] :=  1; start[ 69] :=  1; start[ 70] :=  1; start[ 71] :=  1; 
   start[ 72] :=  1; start[ 73] :=  1; start[ 74] :=  1; start[ 75] :=  1; 

BIN
M2cS.o


+ 4 - 0
MGen.def

@@ -33,6 +33,10 @@ TYPE
 PROCEDURE OpenModule (name: ARRAY OF CHAR);
 (* Resets all state; reserves slots 0..3 for the print helper. *)
 
+PROCEDURE SetModName (name: ARRAY OF CHAR);
+(* Sets the output image name (multi-file sessions: the program
+   unit calls this; EndModule writes <name>.MC4). *)
+
 PROCEDURE DeclVar (name: ARRAY OF CHAR);
 (* Assigns the next global slot to name (any type; one slot). *)
 

+ 9 - 0
MGen.mod

@@ -205,6 +205,10 @@ PROCEDURE QualGlob (name: ARRAY OF CHAR; VAR q: ARRAY OF CHAR);
   VAR m: SymTab.Name;
     i, k: CARDINAL;
   BEGIN
+    IF SymTab.GlobAlias(name, m) THEN
+      StrCpy(q, m);
+      RETURN
+    END;
     IF SymTab.InModule() & (SymTab.SymLev(name) > 0) THEN
       SymTab.CurModName(m);
       i := 0; k := 0;
@@ -270,6 +274,11 @@ PROCEDURE OpenModule (name: ARRAY OF CHAR);
     dummy := AssignSlot(""); dummy := AssignSlot("")
   END OpenModule;
 
+PROCEDURE SetModName (name: ARRAY OF CHAR);
+  BEGIN
+    StrCpy(modName, name)
+  END SetModName;
+
 PROCEDURE DeclVar (name: ARRAY OF CHAR);
   VAR idx : INTEGER;
   BEGIN

BIN
MGen.o


+ 13 - 0
S4L.LST

@@ -0,0 +1,13 @@
+Listing:
+
+    1  DEFINITION MODULE S4L;
+    2  CONST base = 100;
+    3  TYPE Pair = RECORD a, b : INTEGER END;
+    4  VAR n : INTEGER;
+    5  PROCEDURE Add(x, y : INTEGER) : INTEGER;
+    6  PROCEDURE Bump(VAR x : INTEGER);
+    7  END S4L.
+
+    0 errors
+
+

+ 7 - 0
S4L.def

@@ -0,0 +1,7 @@
+DEFINITION MODULE S4L;
+CONST base = 100;
+TYPE Pair = RECORD a, b : INTEGER END;
+VAR n : INTEGER;
+PROCEDURE Add(x, y : INTEGER) : INTEGER;
+PROCEDURE Bump(VAR x : INTEGER);
+END S4L.

+ 18 - 0
S4Limpl.LST

@@ -0,0 +1,18 @@
+Listing:
+
+    1  IMPLEMENTATION MODULE S4L;
+    2  PROCEDURE Add(x, y : INTEGER) : INTEGER;
+    3  BEGIN
+    4    RETURN x + y
+    5  END Add;
+    6  PROCEDURE Bump(VAR x : INTEGER);
+    7  BEGIN
+    8    x := x + 10
+    9  END Bump;
+   10  BEGIN
+   11    n := 7
+   12  END S4L.
+
+    0 errors
+
+

+ 12 - 0
S4Limpl.mod

@@ -0,0 +1,12 @@
+IMPLEMENTATION MODULE S4L;
+PROCEDURE Add(x, y : INTEGER) : INTEGER;
+BEGIN
+  RETURN x + y
+END Add;
+PROCEDURE Bump(VAR x : INTEGER);
+BEGIN
+  x := x + 10
+END Bump;
+BEGIN
+  n := 7
+END S4L.

+ 32 - 0
Showcase4.LST

@@ -0,0 +1,32 @@
+Listing:
+
+    1  MODULE Showcase4;
+    2  
+    3  (* Step-11 tour: DEFINITION/IMPLEMENTATION library, IMPORT + FROM,
+    4     qualified and unqualified use, lib init before program body. *)
+    5  
+    6  FROM S4L IMPORT Pair, Add;
+    7  VAR p, q : Pair;
+    8  VAR w : INTEGER;
+    9  VAR total : INTEGER;
+   10  VAR ExitCode : INTEGER;
+   11  
+   12  BEGIN
+   13    total := 0;
+   14    WriteString("show4");
+   15    w := S4L.n;
+   16    S4L.Bump(w);
+   17    S4L.n := w;
+   18    total := total + S4L.n;
+   19    p.a := 1; p.b := 2;
+   20    q := p;
+   21    total := total + q.a + q.b;
+   22    total := total + Add(S4L.base, 5);
+   23    total := total + S4L.base;
+   24    WriteInt(total);
+   25    ExitCode := total
+   26  END Showcase4.
+
+    0 errors
+
+

BIN
Showcase4.MC4


+ 26 - 0
Showcase4.mod

@@ -0,0 +1,26 @@
+MODULE Showcase4;
+
+(* Step-11 tour: DEFINITION/IMPLEMENTATION library, IMPORT + FROM,
+   qualified and unqualified use, lib init before program body. *)
+
+FROM S4L IMPORT Pair, Add;
+VAR p, q : Pair;
+VAR w : INTEGER;
+VAR total : INTEGER;
+VAR ExitCode : INTEGER;
+
+BEGIN
+  total := 0;
+  WriteString("show4");
+  w := S4L.n;
+  S4L.Bump(w);
+  S4L.n := w;
+  total := total + S4L.n;
+  p.a := 1; p.b := 2;
+  q := p;
+  total := total + q.a + q.b;
+  total := total + Add(S4L.base, 5);
+  total := total + S4L.base;
+  WriteInt(total);
+  ExitCode := total
+END Showcase4.

+ 48 - 0
SymTab.def

@@ -155,6 +155,54 @@ PROCEDURE SelfKind (mod, exp: ARRAY OF CHAR): INTEGER;
 PROCEDURE SelfQual (exp: ARRAY OF CHAR; VAR qual: Name);
 (* CurMod.exp for a self reference (call only when SelfKind # -1). *)
 
+(* ---------------- separate compilation units (step 11) *)
+(* DEFINITION modules publish every declared name into the export
+   tables and record an in-memory interface (side table: kind, type,
+   proc number); the body scope is popped. IMPLEMENTATION modules
+   re-enter that interface into a fresh scope (no new MGen slots),
+   match procedure headings via the forward machinery (231 on
+   mismatch), and must supply every body (231). All units share one
+   image: globals/procs accumulate, library inits run first.
+   FROM-imported names materialize as real alias symbols (procs
+   share the original number, so call checking is unchanged);
+   VAR/CONST aliases map to the definition's global via GlobAlias. *)
+
+PROCEDURE ExitDefinition (): BOOLEAN;
+(* Publishes the current module scope, records the interface,
+   pops scope + context. FALSE when a phase cap breaks (too many
+   definitions, names, or exports). *)
+
+PROCEDURE OpenImplementation (name: ARRAY OF CHAR): BOOLEAN;
+(* Re-enters a recorded interface for its implementation body.
+   FALSE when no definition is known (stale state untouched). *)
+
+PROCEDURE CloseImplementation (): BOOLEAN;
+(* 231-check (every definition proc got a body), pops scope +
+   context. State is popped even on FALSE. *)
+
+PROCEDURE IsDefMod (name: ARRAY OF CHAR): BOOLEAN;
+(* TRUE for a module with a recorded definition interface. *)
+
+PROCEDURE ImpBind (mod, exp: ARRAY OF CHAR): BOOLEAN;
+(* Records a FROM-import alias target ("mod.exp"). FALSE when the
+   export is unknown or the alias table is full. *)
+
+PROCEDURE ImpUnbind (name: ARRAY OF CHAR);
+(* Drops an alias binding (failed materialization cleanup). *)
+
+PROCEDURE EnterImpProc (name: ARRAY OF CHAR; pnum: INTEGER): BOOLEAN;
+(* Enters an imported procedure alias sharing pnum (signature and
+   codegen resolve through the shared procs[] entry; the current
+   procedure context is untouched). FALSE on duplicate or full. *)
+
+PROCEDURE GlobAlias (name: ARRAY OF CHAR; VAR q: Name): BOOLEAN;
+(* TRUE + qualified definition global ("M.x") for a VAR/CONST
+   FROM-import alias (MGen slot lookup hook). *)
+
+PROCEDURE NoteProgram (): BOOLEAN;
+(* Claims the single program unit of the session (FALSE when one
+   already exists). *)
+
 PROCEDURE PushRecord (t: TypeIndex): BOOLEAN;
 (* Pushes a scope containing t's fields (as KindField). FALSE if t
    is not a record type (or invalid). Caller must PopScope after. *)

+ 267 - 0
SymTab.mod

@@ -92,6 +92,21 @@ VAR
   expTypeA : ARRAY [0 .. 127] OF TypeIndex;
   expProcA : ARRAY [0 .. 127] OF INTEGER;
   nExps : CARDINAL;
+  defNames : ARRAY [0 .. 7] OF Name;
+  defNSyms : ARRAY [0 .. 7] OF CARDINAL;
+  defSyms : ARRAY [0 .. 7] OF ARRAY [0 .. 31] OF Name;
+  defKinds : ARRAY [0 .. 7] OF ARRAY [0 .. 31] OF INTEGER;
+  defTypes : ARRAY [0 .. 7] OF ARRAY [0 .. 31] OF TypeIndex;
+  defPnums : ARRAY [0 .. 7] OF ARRAY [0 .. 31] OF INTEGER;
+  defProcLo : ARRAY [0 .. 7] OF CARDINAL;
+  defProcHi : ARRAY [0 .. 7] OF CARDINAL;
+  nDefs : CARDINAL;
+  defMark : CARDINAL;
+  curDef : INTEGER;
+  impNames : ARRAY [0 .. 63] OF Name;
+  impQuals : ARRAY [0 .. 63] OF Name;
+  nImps : CARDINAL;
+  progDone : BOOLEAN;
 
 (* ---------------- strings ---------------- *)
 
@@ -397,6 +412,7 @@ PROCEDURE EnterModule (name: ARRAY OF CHAR): BOOLEAN;
     INC(modTop);
     PushScope;
     modLevs[modTop - 1] := curLev;
+    defMark := nProcs;
     RETURN TRUE
   END EnterModule;
 
@@ -547,6 +563,255 @@ PROCEDURE SelfQual (exp: ARRAY OF CHAR; VAR qual: Name);
     IF k <= HIGH(qual) THEN qual[k] := 0C END
   END SelfQual;
 
+(* ---------------- separate compilation units ---------------- *)
+
+PROCEDURE DefFind (name: ARRAY OF CHAR): INTEGER;
+(* Recorded-definition index or -1. *)
+  VAR i : CARDINAL;
+  BEGIN
+    i := 0;
+    WHILE i < nDefs DO
+      IF Equal(defNames[i], name) THEN RETURN VAL(INTEGER, i) END;
+      INC(i)
+    END;
+    RETURN -1
+  END DefFind;
+
+PROCEDURE ExitDefinition (): BOOLEAN;
+(* Publishes every interface name of the current module scope into
+   the export tables, records the interface side table, pops scope
+   + module context. The level-0 module symbol survives for L.x
+   heads and IsDefMod checks. FALSE on phase-cap overflow. *)
+  VAR mi : CARDINAL;
+    i, n : CARDINAL;
+    k : INTEGER;
+    ok : BOOLEAN;
+  BEGIN
+    IF modTop = 0 THEN RETURN FALSE END;
+    mi := modTop - 1;
+    ok := TRUE;
+    IF mtop = 0 THEN RETURN FALSE END;
+    i := marks[mtop - 1];
+    WHILE i < nSyms DO
+      k := syms[i].kind;
+      IF (k = KindConst) OR (k = KindType) OR (k = KindVar)
+         OR (k = KindProc) THEN
+        IF nExps > 127 THEN ok := FALSE
+        ELSE
+          Assign(expMod[nExps], modNames[mi]);
+          Assign(expName[nExps], syms[i].name);
+          expKindA[nExps] := k;
+          expTypeA[nExps] := syms[i].typ;
+          IF k = KindProc THEN expProcA[nExps] := syms[i].pnum
+          ELSE expProcA[nExps] := -1
+          END;
+          INC(nExps)
+        END
+      END;
+      INC(i)
+    END;
+    IF nDefs > 7 THEN ok := FALSE END;
+    n := 0;
+    IF ok THEN
+      Assign(defNames[nDefs], modNames[mi]);
+      defProcLo[nDefs] := defMark + 1;
+      defProcHi[nDefs] := nProcs;
+      i := marks[mtop - 1];
+      WHILE i < nSyms DO
+        k := syms[i].kind;
+        IF (k = KindConst) OR (k = KindType) OR (k = KindVar)
+           OR (k = KindProc) THEN
+          IF n > 31 THEN ok := FALSE
+          ELSE
+            Assign(defSyms[nDefs][n], syms[i].name);
+            defKinds[nDefs][n] := k;
+            defTypes[nDefs][n] := syms[i].typ;
+            defPnums[nDefs][n] := syms[i].pnum;
+            INC(n)
+          END
+        END;
+        INC(i)
+      END;
+      defNSyms[nDefs] := n;
+      IF ok THEN INC(nDefs) END
+    END;
+    PopScope;
+    DEC(modTop);
+    RETURN ok
+  END ExitDefinition;
+
+PROCEDURE OpenImplementation (name: ARRAY OF CHAR): BOOLEAN;
+(* Re-enters a recorded interface into a fresh module scope:
+   constants/types/variables as plain symbols (MGen slots were
+   allocated once at definition and resolve via the module
+   context), procedures as forward-pending aliases so headings
+   match through the ReuseProc/VerifyProc path. *)
+  VAR d : INTEGER;
+    i : CARDINAL;
+    idx : INTEGER;
+  BEGIN
+    d := DefFind(name);
+    IF d < 0 THEN RETURN FALSE END;
+    IF modTop > 7 THEN RETURN FALSE END;
+    Assign(modNames[modTop], name);
+    modNExps[modTop] := 0;
+    INC(modTop);
+    PushScope;
+    modLevs[modTop - 1] := curLev;
+    i := 0;
+    WHILE i < defNSyms[d] DO
+      idx := RawEnter(defSyms[d][i], defKinds[d][i]);
+      IF idx = -1 THEN
+        PopScope; DEC(modTop); RETURN FALSE
+      END;
+      syms[idx].typ := defTypes[d][i];
+      IF defKinds[d][i] = KindProc THEN
+        syms[idx].pnum := defPnums[d][i];
+        curProc := defPnums[d][i];
+        IF (curProc >= 1) & (curProc <= VAL(INTEGER, nProcs)) THEN
+          procs[curProc].fwd := TRUE;
+          procs[curProc].dHead := -1;
+          procs[curProc].dTail := -1
+        END
+      END;
+      INC(i)
+    END;
+    curProc := 0;
+    curDef := d;
+    RETURN TRUE
+  END OpenImplementation;
+
+PROCEDURE CloseImplementation (): BOOLEAN;
+(* Every definition procedure must have its body by now (231
+   otherwise). Scope + context pop either way. *)
+  VAR d : INTEGER;
+    k : CARDINAL;
+    ok : BOOLEAN;
+  BEGIN
+    d := curDef;
+    ok := TRUE;
+    IF (d >= 0) & (d < 8) THEN
+      k := defProcLo[d];
+      WHILE k <= defProcHi[d] DO
+        IF (k >= 1) & (k <= VAL(CARDINAL, nProcs)) THEN
+          IF procs[k].fwd THEN ok := FALSE END
+        END;
+        INC(k)
+      END
+    END;
+    IF modTop > 0 THEN
+      PopScope;
+      DEC(modTop)
+    END;
+    curDef := -1;
+    curProc := 0;
+    RETURN ok
+  END CloseImplementation;
+
+PROCEDURE IsDefMod (name: ARRAY OF CHAR): BOOLEAN;
+  VAR idx : INTEGER;
+  BEGIN
+    idx := Find(name);
+    IF idx = -1 THEN RETURN FALSE END;
+    IF syms[idx].kind # KindModule THEN RETURN FALSE END;
+    RETURN DefFind(name) # -1
+  END IsDefMod;
+
+PROCEDURE ImpBind (mod, exp: ARRAY OF CHAR): BOOLEAN;
+(* Records unqualified exp -> "mod.exp" for GlobAlias. The caller
+   validates the kind through ExpKind and materializes the alias
+   symbol (ImpUnbind on failure). *)
+  VAR i : CARDINAL;
+    j, k : CARDINAL;
+  BEGIN
+    IF ExpFind(mod, exp) = -1 THEN RETURN FALSE END;
+    i := 0;
+    WHILE i < nImps DO
+      IF Equal(impNames[i], exp) THEN
+        j := 0; k := 0;
+        WHILE (k < HIGH(impQuals[i])) & (mod[j] # 0C) DO
+          impQuals[i][k] := mod[j]; INC(k); INC(j)
+        END;
+        IF k <= HIGH(impQuals[i]) THEN impQuals[i][k] := "."; INC(k) END;
+        j := 0;
+        WHILE (k < HIGH(impQuals[i])) & (exp[j] # 0C) DO
+          impQuals[i][k] := exp[j]; INC(k); INC(j)
+        END;
+        IF k <= HIGH(impQuals[i]) THEN impQuals[i][k] := 0C END;
+        RETURN TRUE
+      END;
+      INC(i)
+    END;
+    IF nImps > 63 THEN RETURN FALSE END;
+    Assign(impNames[nImps], exp);
+    j := 0; k := 0;
+    WHILE (k < HIGH(impQuals[nImps])) & (mod[j] # 0C) DO
+      impQuals[nImps][k] := mod[j]; INC(k); INC(j)
+    END;
+    IF k <= HIGH(impQuals[nImps]) THEN
+      impQuals[nImps][k] := "."; INC(k)
+    END;
+    j := 0;
+    WHILE (k < HIGH(impQuals[nImps])) & (exp[j] # 0C) DO
+      impQuals[nImps][k] := exp[j]; INC(k); INC(j)
+    END;
+    IF k <= HIGH(impQuals[nImps]) THEN impQuals[nImps][k] := 0C END;
+    INC(nImps);
+    RETURN TRUE
+  END ImpBind;
+
+PROCEDURE ImpUnbind (name: ARRAY OF CHAR);
+  VAR i, j : CARDINAL;
+  BEGIN
+    i := 0;
+    WHILE i < nImps DO
+      IF Equal(impNames[i], name) THEN
+        j := i;
+        WHILE j + 1 < nImps DO
+          Assign(impNames[j], impNames[j + 1]);
+          Assign(impQuals[j], impQuals[j + 1]);
+          INC(j)
+        END;
+        DEC(nImps);
+        RETURN
+      END;
+      INC(i)
+    END
+  END ImpUnbind;
+
+PROCEDURE EnterImpProc (name: ARRAY OF CHAR; pnum: INTEGER): BOOLEAN;
+  VAR idx : INTEGER;
+  BEGIN
+    IF DupInLevel(name) THEN RETURN FALSE END;
+    IF (pnum < 1) OR (pnum > VAL(INTEGER, nProcs)) THEN RETURN FALSE END;
+    idx := RawEnter(name, KindProc);
+    IF idx = -1 THEN RETURN FALSE END;
+    syms[idx].pnum := pnum;
+    syms[idx].typ := procs[pnum].ret;
+    RETURN TRUE
+  END EnterImpProc;
+
+PROCEDURE GlobAlias (name: ARRAY OF CHAR; VAR q: Name): BOOLEAN;
+  VAR i : CARDINAL;
+  BEGIN
+    i := 0;
+    WHILE i < nImps DO
+      IF Equal(impNames[i], name) THEN
+        Assign(q, impQuals[i]);
+        RETURN TRUE
+      END;
+      INC(i)
+    END;
+    RETURN FALSE
+  END GlobAlias;
+
+PROCEDURE NoteProgram (): BOOLEAN;
+  BEGIN
+    IF progDone THEN RETURN FALSE END;
+    progDone := TRUE;
+    RETURN TRUE
+  END NoteProgram;
+
 (* ---------------- type descriptors ---------------- *)
 
 PROCEDURE NewDesc (form: INTEGER; ref: TypeIndex): TypeIndex;
@@ -1380,6 +1645,8 @@ PROCEDURE Init;
     nProcs := 0; nParams := 0;
     pdep := 0; curProc := 0;
     modTop := 0; nExps := 0;
+    nDefs := 0; defMark := 0; curDef := -1;
+    nImps := 0; progDone := FALSE;
     procSt[0] := 0; locCnt[0] := 0; parCnt[0] := 0;
     retSt[0] := InvalidType;
     dInt := NewDesc(FInt, InvalidType);

BIN
SymTab.o


+ 49 - 28
compiler.frm

@@ -6,7 +6,7 @@ MODULE -->Grammar;
   FROM -->Scanner IMPORT lst, src, errors, Error, CharAt;
   FROM -->Parser IMPORT Parse, Successful;
   IMPORT
-    Strings, Storage, SYSTEM, FileIO;
+    Strings, Storage, SYSTEM, FileIO, SymTab, MGen;
 
   TYPE
     INT32 = FileIO.INT32 (* 32 bit integers needed *);
@@ -187,6 +187,7 @@ MODULE -->Grammar;
 
   VAR
     sourceName, listName: ARRAY [0 .. 255] OF CHAR;
+    failed: BOOLEAN;
 
   BEGIN
     (* check on correct parameter usage *)
@@ -196,39 +197,59 @@ MODULE -->Grammar;
       HALT
     END;
 
-    (* open the source file - Scanner.src *)
-    FileIO.Open(src, sourceName, FALSE);
-    IF ~ FileIO.Okay THEN
-      FileIO.WriteString(FileIO.StdOut, "Could not open input file");
-      FileIO.WriteLn(FileIO.StdOut);
-      HALT
-    END;
-
-    (* open the output file for the source listing - Scanner.lst *)
-    ChangeExtension(sourceName, ".LST", listName);
-    FileIO.Open(lst, listName, TRUE);
-    IF ~ FileIO.Okay THEN
-      FileIO.WriteString(FileIO.StdOut, "Could not open listing file");
-      FileIO.WriteLn(FileIO.StdOut);
-      (* default Scanner.lst to screen *) lst := FileIO.StdOut;
-    END;
+    (* one session for all files: definitions, then
+       implementations, then the program (see M2c.atg) *)
+    SymTab.Init;
+    MGen.OpenModule("");
 
     (* install error reporting procedure - Scanner.Error *)
     Error := StoreError;
 
-    (* instigate the compilation - Parser.Parse *)
-    FileIO.WriteString(FileIO.StdOut, "Parsing"); FileIO.WriteLn(FileIO.StdOut);
-    Parse;
+    failed := FALSE;
+    LOOP
+      IF sourceName[0] = 0C THEN EXIT END;
+
+      (* open the source file - Scanner.src *)
+      FileIO.Open(src, sourceName, FALSE);
+      IF ~ FileIO.Okay THEN
+        FileIO.WriteString(FileIO.StdOut, "Could not open input file");
+        FileIO.WriteLn(FileIO.StdOut);
+        HALT
+      END;
+
+      (* open the output file for the source listing - Scanner.lst *)
+      ChangeExtension(sourceName, ".LST", listName);
+      FileIO.Open(lst, listName, TRUE);
+      IF ~ FileIO.Okay THEN
+        FileIO.WriteString(FileIO.StdOut, "Could not open listing file");
+        FileIO.WriteLn(FileIO.StdOut);
+        (* default Scanner.lst to screen *) lst := FileIO.StdOut;
+      END;
 
-    (* generate the source listing on lst file *)
-    PrintListing;
-    IF lst # FileIO.StdOut THEN FileIO.Close(lst) END;
+      (* instigate the compilation - Parser.Parse *)
+      FileIO.WriteString(FileIO.StdOut, "Parsing ");
+      FileIO.WriteString(FileIO.StdOut, sourceName);
+      FileIO.WriteLn(FileIO.StdOut);
+      Parse;
+
+      (* generate the source listing on lst file *)
+      PrintListing;
+      IF lst # FileIO.StdOut THEN FileIO.Close(lst) END;
+
+      (* fail fast: later files build on this one's tables *)
+      IF NOT Successful()
+        THEN
+          FileIO.WriteString(FileIO.StdOut, "Incorrect source");
+          FileIO.WriteLn(FileIO.StdOut);
+          failed := TRUE;
+          EXIT
+      END;
+
+      FileIO.NextParameter(sourceName);
+    END;
 
     (* examine the outcome *)
-    IF NOT Successful()
-      THEN
-        FileIO.WriteString(FileIO.StdOut, "Incorrect source");
-      ELSE
-        FileIO.WriteString(FileIO.StdOut, "Parsed correctly");
+    IF NOT failed THEN
+      FileIO.WriteString(FileIO.StdOut, "Parsed correctly");
     END;
   END -->Grammar.

+ 73 - 0
docs/summary_step11.md

@@ -0,0 +1,73 @@
+# Step 11 — Separate compilation units (DEFINITION/IMPLEMENTATION/IMPORT)
+
+157/157 tests green (144 + 7 run + 6 rejection), mc64 boot + example
+green, Showcases unchanged (157, 83, 168), new Showcase4 prints 225
+as hand-computed.
+
+## Goal
+
+`DEFINITION`/`IMPLEMENTATION` compilation units with `IMPORT`/`FROM`,
+compiled from several files into a single `.MC4` image (the remaining
+big item from the step-10 limits).
+
+## What was built
+
+- Driver (`compiler.frm`, the true source of generated `M2c.mod`):
+  multi-file session `M2c lib.def libimpl.mod ... prog.mod`, one
+  `.LST` per input, fail-fast on the first bad file (no HALT abort:
+  a clean `EXIT` with `Incorrect source`). `SymTab.Init` and
+  `MGen.OpenModule("")` run once; the program unit sets the image
+  name (`MGen.SetModName`).
+- Grammar (`M2c.atg`): `M2c = Unit`, `Unit = DefUnit | ImplUnit |
+  ProgUnit`. New `DEFINITION`/`IMPLEMENTATION` keywords were added in
+  end-of-file productions so existing token numbers only shifted by
+  position — CR regenerates `M2c.mod`'s `Msg` table from `M2c.err`
+  (verified identical mapping); new-productions note added.
+- `SymTab`: definition interfaces publish to the existing export
+  tables plus an in-memory side table (8 defs, 32 names each);
+  `OpenImplementation` re-enters the interface into a fresh scope
+  (slots allocated once at definition, found via the module
+  context); procedure headings match through the forward machinery
+  (`ReuseProc`/`VerifyProc`, 231 on mismatch); `CloseImplementation`
+  requires every body (231). `FROM L IMPORT x` materializes real
+  alias symbols (`EnterImpProc` shares the proc number, so call
+  checking is unchanged; VAR/CONST aliases resolve through the new
+  `GlobAlias` hook in `MGen.QualGlob`, the single funnel for all
+  global use-paths). Ghosts are 201, bad kinds 221, duplicates 200.
+- `run_tests.sh`: `expect_run_files` / `expect_fail_files` for
+  multi-file sessions.
+
+## Tests — 157/157 (144 + 7 + 6)
+
+7 run: `d_basic` 25 (FROM var/func, qualified const/var/call,
+`VAR` param, lib init), `d_from` 12 (exported array type, private
+impl helper, `VAR` composite formal), `d_multi` 82 (two libs,
+implementation-level `IMPORT`), `d_init` 510 (init order across
+files, init reading another lib via `FROM`), `d_func` 55
+(recursive lib function), `d_type` 1122 (exported record, `VAR`
+record formal), `d_case` 25 (qualified enum `CASE` labels).
+6 rejections, each exactly one error: `d_bad_nodef` 201,
+`d_bad_sig` 231, `d_bad_nobody` 231, `d_bad_imp` 201,
+`d_bad_exp` 201, `d_bad_dup` 200.
+
+## Bugs found and fixed
+
+1. `DefProcHead` double-semicolon: heading already consumes its own
+   `;` (`';' expected` on the first definition).
+2. `HALT` on compile failure aborts (SIGABRT, `Abandon` noise in
+   every rejection run) — replaced with a clean loop `EXIT`.
+3. Value composite formals in a test (`Sum(x : Vec)`) correctly hit
+   the pre-existing 230 rule — test switched to `VAR` formal.
+4. `M2c.mod` is REGENERATED by CR from `compiler.frm` on every
+   build: driver edits first went to `M2c.mod` and were silently
+   lost. Driver work belongs in `compiler.frm` (same for the `Msg`
+   table, auto-mirrored from `M2c.err`).
+
+## Known limits (deferred)
+
+`M.x` as a `VAR` actual is still 233 (pre-existing local-module
+limitation, confirmed identical on step-10 build — Showcase4 works
+around it via a temp); second program unit rejected (230 + follow-on
+200); multi-`.MC4` images with `depCount` loading (still single
+image, `depCount` 0); circular imports; opaque types; `WITH`-field
+`VAR` actuals; `CHAR`/`BOOLEAN` tails as `VAR` actuals.

+ 68 - 0
run_tests.sh

@@ -102,6 +102,57 @@ expect_run_none() {
   fi
 }
 
+expect_run_files() {
+  # $1 = program module (MC4 base), $2 = expected value, rest = sources
+  prog="$1"
+  want="$2"
+  shift 2
+  mcd="$prog.MC4"
+  rm -f "$mcd"
+  out=$(./M2c "$@" 2>&1)
+  case "$out" in
+    *"Parsed correctly"*) ;;
+    *)
+      echo "FAIL $prog: M2c rejected it: $out"
+      fail=$((fail+1)); return ;;
+  esac
+  if [ ! -f "$mcd" ]; then
+    echo "FAIL $prog: no $mcd produced"
+    fail=$((fail+1)); return
+  fi
+  got=$("$MCINT" "$mcd" 2>&1 | head -n 1 | tr -d '\r')
+  if [ "$got" = "$want" ]; then
+    echo "ok   $prog -> $got"
+    pass=$((pass+1))
+  else
+    echo "FAIL $prog: printed [$got], expected [$want]"
+    fail=$((fail+1))
+  fi
+}
+
+expect_fail_files() {
+  # $1 = message in the failing file's .LST, rest = sources
+  want="$1"
+  shift
+  out=$(./M2c "$@" 2>&1)
+  case "$out" in
+    *"Incorrect source"*) ;;
+    *)
+      echo "FAIL $*: expected rejection, got: $out"
+      fail=$((fail+1)); return ;;
+  esac
+  last=""
+  for f in "$@"; do last="$f"; done
+  lst=$(echo "$last" | sed 's/\.[^.]*$/.LST/')
+  if grep -q "$want" "$lst" 2>/dev/null; then
+    echo "ok   $last rejected with [$want]"
+    pass=$((pass+1))
+  else
+    echo "FAIL $last: [$want] not found in $lst"
+    fail=$((fail+1))
+  fi
+}
+
 echo "=== Phase-0 tests (still green) ==="
 expect_ok ok_minimal.mod
 expect_ok ok_nobegin.mod
@@ -284,5 +335,22 @@ expect_fail b_bad_ret.mod "bad RETURN"
 expect_fail b_bad_nest.mod "not supported in this phase"
 expect_fail b_bad_dup.mod "duplicate identifier"
 
+echo "=== Step-11 run tests (DEFINITION/IMPLEMENTATION/IMPORT) ==="
+expect_run_files DBasic 25 tests/d_lib.def tests/d_libimpl.mod tests/d_basic.mod
+expect_run_files DFrom 12 tests/d_lib2.def tests/d_lib2impl.mod tests/d_from.mod
+expect_run_files DMulti 82 tests/a_lib.def tests/a_libimpl.mod tests/b_lib.def tests/b_libimpl.mod tests/d_multi.mod
+expect_run_files DInit 510 tests/l1.def tests/l1impl.mod tests/l2.def tests/l2impl.mod tests/d_init.mod
+expect_run_files DFunc 55 tests/f_lib.def tests/f_libimpl.mod tests/d_func.mod
+expect_run_files DType 1122 tests/t_lib.def tests/t_libimpl.mod tests/d_type.mod
+expect_run_files DCase 25 tests/e_lib.def tests/e_libimpl.mod tests/d_case.mod
+
+echo "=== Step-11 rejection tests ==="
+expect_fail_files "undeclared identifier" tests/d_bad_nodef.mod
+expect_fail_files "procedure forward mismatch" tests/d_sglib.def tests/d_bad_sig.mod
+expect_fail_files "procedure forward mismatch" tests/d_nolib.def tests/d_bad_nobody.mod
+expect_fail_files "undeclared identifier" tests/d_bad_imp.mod
+expect_fail_files "undeclared identifier" tests/d_lib.def tests/d_libimpl.mod tests/d_bad_exp.mod
+expect_fail_files "duplicate identifier" tests/d_duplib.def tests/d_bad_dup.mod
+
 echo "=== $pass passed, $fail failed ==="
 test "$fail" = 0

+ 9 - 0
tests/a_lib.LST

@@ -0,0 +1,9 @@
+Listing:
+
+    1  DEFINITION MODULE ALib;
+    2  VAR aval : INTEGER;
+    3  END ALib.
+
+    0 errors
+
+

+ 3 - 0
tests/a_lib.def

@@ -0,0 +1,3 @@
+DEFINITION MODULE ALib;
+VAR aval : INTEGER;
+END ALib.

+ 10 - 0
tests/a_libimpl.LST

@@ -0,0 +1,10 @@
+Listing:
+
+    1  IMPLEMENTATION MODULE ALib;
+    2  BEGIN
+    3    aval := 40
+    4  END ALib.
+
+    0 errors
+
+

+ 4 - 0
tests/a_libimpl.mod

@@ -0,0 +1,4 @@
+IMPLEMENTATION MODULE ALib;
+BEGIN
+  aval := 40
+END ALib.

+ 10 - 0
tests/b_lib.LST

@@ -0,0 +1,10 @@
+Listing:
+
+    1  DEFINITION MODULE BLib;
+    2  VAR bval : INTEGER;
+    3  PROCEDURE GetB : INTEGER;
+    4  END BLib.
+
+    0 errors
+
+

+ 4 - 0
tests/b_lib.def

@@ -0,0 +1,4 @@
+DEFINITION MODULE BLib;
+VAR bval : INTEGER;
+PROCEDURE GetB : INTEGER;
+END BLib.

+ 15 - 0
tests/b_libimpl.LST

@@ -0,0 +1,15 @@
+Listing:
+
+    1  IMPLEMENTATION MODULE BLib;
+    2  IMPORT ALib;
+    3  PROCEDURE GetB : INTEGER;
+    4  BEGIN
+    5    RETURN bval + ALib.aval
+    6  END GetB;
+    7  BEGIN
+    8    bval := 2
+    9  END BLib.
+
+    0 errors
+
+

+ 9 - 0
tests/b_libimpl.mod

@@ -0,0 +1,9 @@
+IMPLEMENTATION MODULE BLib;
+IMPORT ALib;
+PROCEDURE GetB : INTEGER;
+BEGIN
+  RETURN bval + ALib.aval
+END GetB;
+BEGIN
+  bval := 2
+END BLib.

+ 13 - 0
tests/d_bad_dup.LST

@@ -0,0 +1,13 @@
+Listing:
+
+    1  IMPLEMENTATION MODULE DLibD;
+    2  VAR v : INTEGER;
+*****      ^ duplicate identifier
+    3  PROCEDURE P;
+    4  BEGIN
+    5  END P;
+    6  END DLibD.
+
+    1 error
+
+

+ 6 - 0
tests/d_bad_dup.mod

@@ -0,0 +1,6 @@
+IMPLEMENTATION MODULE DLibD;
+VAR v : INTEGER;
+PROCEDURE P;
+BEGIN
+END P;
+END DLibD.

+ 13 - 0
tests/d_bad_exp.LST

@@ -0,0 +1,13 @@
+Listing:
+
+    1  MODULE DBadExp;
+    2  FROM DLib IMPORT ghost;
+*****                   ^ undeclared identifier
+    3  VAR ExitCode : INTEGER;
+    4  BEGIN
+    5    ExitCode := 1
+    6  END DBadExp.
+
+    1 error
+
+

+ 6 - 0
tests/d_bad_exp.mod

@@ -0,0 +1,6 @@
+MODULE DBadExp;
+FROM DLib IMPORT ghost;
+VAR ExitCode : INTEGER;
+BEGIN
+  ExitCode := 1
+END DBadExp.

+ 13 - 0
tests/d_bad_imp.LST

@@ -0,0 +1,13 @@
+Listing:
+
+    1  MODULE DBadImp;
+    2  IMPORT Ghost;
+*****         ^ undeclared identifier
+    3  VAR ExitCode : INTEGER;
+    4  BEGIN
+    5    ExitCode := 1
+    6  END DBadImp.
+
+    1 error
+
+

+ 6 - 0
tests/d_bad_imp.mod

@@ -0,0 +1,6 @@
+MODULE DBadImp;
+IMPORT Ghost;
+VAR ExitCode : INTEGER;
+BEGIN
+  ExitCode := 1
+END DBadImp.

+ 11 - 0
tests/d_bad_nobody.LST

@@ -0,0 +1,11 @@
+Listing:
+
+    1  IMPLEMENTATION MODULE DLibN;
+    2  BEGIN
+    3    v := 1
+    4  END DLibN.
+*****      ^ procedure forward mismatch or missing body
+
+    1 error
+
+

+ 4 - 0
tests/d_bad_nobody.mod

@@ -0,0 +1,4 @@
+IMPLEMENTATION MODULE DLibN;
+BEGIN
+  v := 1
+END DLibN.

+ 9 - 0
tests/d_bad_nodef.LST

@@ -0,0 +1,9 @@
+Listing:
+
+    1  IMPLEMENTATION MODULE Ghost;
+*****                         ^ undeclared identifier
+    2  END Ghost.
+
+    1 error
+
+

+ 2 - 0
tests/d_bad_nodef.mod

@@ -0,0 +1,2 @@
+IMPLEMENTATION MODULE Ghost;
+END Ghost.

+ 12 - 0
tests/d_bad_sig.LST

@@ -0,0 +1,12 @@
+Listing:
+
+    1  IMPLEMENTATION MODULE DLibS;
+    2  PROCEDURE P(x : BOOLEAN);
+*****                         ^ procedure forward mismatch or missing body
+    3  BEGIN
+    4  END P;
+    5  END DLibS.
+
+    1 error
+
+

+ 5 - 0
tests/d_bad_sig.mod

@@ -0,0 +1,5 @@
+IMPLEMENTATION MODULE DLibS;
+PROCEDURE P(x : BOOLEAN);
+BEGIN
+END P;
+END DLibS.

+ 15 - 0
tests/d_basic.LST

@@ -0,0 +1,15 @@
+Listing:
+
+    1  MODULE DBasic;
+    2  FROM DLib IMPORT v, P;
+    3  VAR w : INTEGER;
+    4  VAR ExitCode : INTEGER;
+    5  BEGIN
+    6    w := v + DLib.c;
+    7    DLib.Q(w);
+    8    ExitCode := P(w) + DLib.v
+    9  END DBasic.
+
+    0 errors
+
+

+ 9 - 0
tests/d_basic.mod

@@ -0,0 +1,9 @@
+MODULE DBasic;
+FROM DLib IMPORT v, P;
+VAR w : INTEGER;
+VAR ExitCode : INTEGER;
+BEGIN
+  w := v + DLib.c;
+  DLib.Q(w);
+  ExitCode := P(w) + DLib.v
+END DBasic.

+ 19 - 0
tests/d_case.LST

@@ -0,0 +1,19 @@
+Listing:
+
+    1  MODULE DCase;
+    2  IMPORT ELib;
+    3  VAR r : INTEGER;
+    4  VAR ExitCode : INTEGER;
+    5  BEGIN
+    6    r := 0;
+    7    CASE ELib.c OF
+    8      ELib.Red : r := 1 |
+    9      ELib.Green : r := 2 |
+   10      ELib.Blue : r := 3
+   11    END;
+   12    ExitCode := r * 10 + 5
+   13  END DCase.
+
+    0 errors
+
+

+ 13 - 0
tests/d_case.mod

@@ -0,0 +1,13 @@
+MODULE DCase;
+IMPORT ELib;
+VAR r : INTEGER;
+VAR ExitCode : INTEGER;
+BEGIN
+  r := 0;
+  CASE ELib.c OF
+    ELib.Red : r := 1 |
+    ELib.Green : r := 2 |
+    ELib.Blue : r := 3
+  END;
+  ExitCode := r * 10 + 5
+END DCase.

+ 10 - 0
tests/d_duplib.LST

@@ -0,0 +1,10 @@
+Listing:
+
+    1  DEFINITION MODULE DLibD;
+    2  VAR v : INTEGER;
+    3  PROCEDURE P;
+    4  END DLibD.
+
+    0 errors
+
+

+ 4 - 0
tests/d_duplib.def

@@ -0,0 +1,4 @@
+DEFINITION MODULE DLibD;
+VAR v : INTEGER;
+PROCEDURE P;
+END DLibD.

+ 14 - 0
tests/d_from.LST

@@ -0,0 +1,14 @@
+Listing:
+
+    1  MODULE DFrom;
+    2  FROM DLib2 IMPORT Vec, Sum;
+    3  VAR a : Vec;
+    4  VAR ExitCode : INTEGER;
+    5  BEGIN
+    6    a[1] := 1; a[2] := 2; a[3] := 3;
+    7    ExitCode := Sum(a)
+    8  END DFrom.
+
+    0 errors
+
+

+ 8 - 0
tests/d_from.mod

@@ -0,0 +1,8 @@
+MODULE DFrom;
+FROM DLib2 IMPORT Vec, Sum;
+VAR a : Vec;
+VAR ExitCode : INTEGER;
+BEGIN
+  a[1] := 1; a[2] := 2; a[3] := 3;
+  ExitCode := Sum(a)
+END DFrom.

+ 12 - 0
tests/d_func.LST

@@ -0,0 +1,12 @@
+Listing:
+
+    1  MODULE DFunc;
+    2  FROM FLib IMPORT Fib;
+    3  VAR ExitCode : INTEGER;
+    4  BEGIN
+    5    ExitCode := Fib(10)
+    6  END DFunc.
+
+    0 errors
+
+

+ 6 - 0
tests/d_func.mod

@@ -0,0 +1,6 @@
+MODULE DFunc;
+FROM FLib IMPORT Fib;
+VAR ExitCode : INTEGER;
+BEGIN
+  ExitCode := Fib(10)
+END DFunc.

+ 12 - 0
tests/d_init.LST

@@ -0,0 +1,12 @@
+Listing:
+
+    1  MODULE DInit;
+    2  IMPORT L1Mod, L2Mod;
+    3  VAR ExitCode : INTEGER;
+    4  BEGIN
+    5    ExitCode := L1Mod.a * 100 + L2Mod.b
+    6  END DInit.
+
+    0 errors
+
+

+ 6 - 0
tests/d_init.mod

@@ -0,0 +1,6 @@
+MODULE DInit;
+IMPORT L1Mod, L2Mod;
+VAR ExitCode : INTEGER;
+BEGIN
+  ExitCode := L1Mod.a * 100 + L2Mod.b
+END DInit.

+ 12 - 0
tests/d_lib.LST

@@ -0,0 +1,12 @@
+Listing:
+
+    1  DEFINITION MODULE DLib;
+    2  CONST c = 7;
+    3  VAR v : INTEGER;
+    4  PROCEDURE P(x : INTEGER) : INTEGER;
+    5  PROCEDURE Q(VAR x : INTEGER);
+    6  END DLib.
+
+    0 errors
+
+

+ 6 - 0
tests/d_lib.def

@@ -0,0 +1,6 @@
+DEFINITION MODULE DLib;
+CONST c = 7;
+VAR v : INTEGER;
+PROCEDURE P(x : INTEGER) : INTEGER;
+PROCEDURE Q(VAR x : INTEGER);
+END DLib.

+ 10 - 0
tests/d_lib2.LST

@@ -0,0 +1,10 @@
+Listing:
+
+    1  DEFINITION MODULE DLib2;
+    2  TYPE Vec = ARRAY [1 .. 3] OF INTEGER;
+    3  PROCEDURE Sum(VAR x : Vec) : INTEGER;
+    4  END DLib2.
+
+    0 errors
+
+

+ 4 - 0
tests/d_lib2.def

@@ -0,0 +1,4 @@
+DEFINITION MODULE DLib2;
+TYPE Vec = ARRAY [1 .. 3] OF INTEGER;
+PROCEDURE Sum(VAR x : Vec) : INTEGER;
+END DLib2.

+ 19 - 0
tests/d_lib2impl.LST

@@ -0,0 +1,19 @@
+Listing:
+
+    1  IMPLEMENTATION MODULE DLib2;
+    2  PROCEDURE Twice(x : INTEGER) : INTEGER;
+    3  BEGIN
+    4    RETURN x * 2
+    5  END Twice;
+    6  PROCEDURE Sum(VAR x : Vec) : INTEGER;
+    7  VAR i, s : INTEGER;
+    8  BEGIN
+    9    s := 0;
+   10    FOR i := 1 TO 3 DO s := s + Twice(x[i]) END;
+   11    RETURN s
+   12  END Sum;
+   13  END DLib2.
+
+    0 errors
+
+

+ 13 - 0
tests/d_lib2impl.mod

@@ -0,0 +1,13 @@
+IMPLEMENTATION MODULE DLib2;
+PROCEDURE Twice(x : INTEGER) : INTEGER;
+BEGIN
+  RETURN x * 2
+END Twice;
+PROCEDURE Sum(VAR x : Vec) : INTEGER;
+VAR i, s : INTEGER;
+BEGIN
+  s := 0;
+  FOR i := 1 TO 3 DO s := s + Twice(x[i]) END;
+  RETURN s
+END Sum;
+END DLib2.

+ 18 - 0
tests/d_libimpl.LST

@@ -0,0 +1,18 @@
+Listing:
+
+    1  IMPLEMENTATION MODULE DLib;
+    2  PROCEDURE P(x : INTEGER) : INTEGER;
+    3  BEGIN
+    4    RETURN x * 2
+    5  END P;
+    6  PROCEDURE Q(VAR x : INTEGER);
+    7  BEGIN
+    8    x := x + 1
+    9  END Q;
+   10  BEGIN
+   11    v := 3
+   12  END DLib.
+
+    0 errors
+
+

+ 12 - 0
tests/d_libimpl.mod

@@ -0,0 +1,12 @@
+IMPLEMENTATION MODULE DLib;
+PROCEDURE P(x : INTEGER) : INTEGER;
+BEGIN
+  RETURN x * 2
+END P;
+PROCEDURE Q(VAR x : INTEGER);
+BEGIN
+  x := x + 1
+END Q;
+BEGIN
+  v := 3
+END DLib.

+ 13 - 0
tests/d_multi.LST

@@ -0,0 +1,13 @@
+Listing:
+
+    1  MODULE DMulti;
+    2  IMPORT ALib;
+    3  FROM BLib IMPORT GetB;
+    4  VAR ExitCode : INTEGER;
+    5  BEGIN
+    6    ExitCode := GetB() + ALib.aval
+    7  END DMulti.
+
+    0 errors
+
+

+ 7 - 0
tests/d_multi.mod

@@ -0,0 +1,7 @@
+MODULE DMulti;
+IMPORT ALib;
+FROM BLib IMPORT GetB;
+VAR ExitCode : INTEGER;
+BEGIN
+  ExitCode := GetB() + ALib.aval
+END DMulti.

+ 10 - 0
tests/d_nolib.LST

@@ -0,0 +1,10 @@
+Listing:
+
+    1  DEFINITION MODULE DLibN;
+    2  VAR v : INTEGER;
+    3  PROCEDURE P;
+    4  END DLibN.
+
+    0 errors
+
+

+ 4 - 0
tests/d_nolib.def

@@ -0,0 +1,4 @@
+DEFINITION MODULE DLibN;
+VAR v : INTEGER;
+PROCEDURE P;
+END DLibN.

+ 9 - 0
tests/d_sglib.LST

@@ -0,0 +1,9 @@
+Listing:
+
+    1  DEFINITION MODULE DLibS;
+    2  PROCEDURE P(x : INTEGER);
+    3  END DLibS.
+
+    0 errors
+
+

+ 3 - 0
tests/d_sglib.def

@@ -0,0 +1,3 @@
+DEFINITION MODULE DLibS;
+PROCEDURE P(x : INTEGER);
+END DLibS.

+ 15 - 0
tests/d_type.LST

@@ -0,0 +1,15 @@
+Listing:
+
+    1  MODULE DType;
+    2  FROM TLib IMPORT Point, Move;
+    3  VAR p : Point;
+    4  VAR ExitCode : INTEGER;
+    5  BEGIN
+    6    p.x := 1; p.y := 2;
+    7    Move(p, 10, 20);
+    8    ExitCode := p.x * 100 + p.y
+    9  END DType.
+
+    0 errors
+
+

+ 9 - 0
tests/d_type.mod

@@ -0,0 +1,9 @@
+MODULE DType;
+FROM TLib IMPORT Point, Move;
+VAR p : Point;
+VAR ExitCode : INTEGER;
+BEGIN
+  p.x := 1; p.y := 2;
+  Move(p, 10, 20);
+  ExitCode := p.x * 100 + p.y
+END DType.

+ 10 - 0
tests/e_lib.LST

@@ -0,0 +1,10 @@
+Listing:
+
+    1  DEFINITION MODULE ELib;
+    2  TYPE Color = (Red, Green, Blue);
+    3  VAR c : Color;
+    4  END ELib.
+
+    0 errors
+
+

+ 4 - 0
tests/e_lib.def

@@ -0,0 +1,4 @@
+DEFINITION MODULE ELib;
+TYPE Color = (Red, Green, Blue);
+VAR c : Color;
+END ELib.

+ 10 - 0
tests/e_libimpl.LST

@@ -0,0 +1,10 @@
+Listing:
+
+    1  IMPLEMENTATION MODULE ELib;
+    2  BEGIN
+    3    c := Green
+    4  END ELib.
+
+    0 errors
+
+

+ 4 - 0
tests/e_libimpl.mod

@@ -0,0 +1,4 @@
+IMPLEMENTATION MODULE ELib;
+BEGIN
+  c := Green
+END ELib.

+ 9 - 0
tests/f_lib.LST

@@ -0,0 +1,9 @@
+Listing:
+
+    1  DEFINITION MODULE FLib;
+    2  PROCEDURE Fib(n : INTEGER) : INTEGER;
+    3  END FLib.
+
+    0 errors
+
+

+ 3 - 0
tests/f_lib.def

@@ -0,0 +1,3 @@
+DEFINITION MODULE FLib;
+PROCEDURE Fib(n : INTEGER) : INTEGER;
+END FLib.

+ 12 - 0
tests/f_libimpl.LST

@@ -0,0 +1,12 @@
+Listing:
+
+    1  IMPLEMENTATION MODULE FLib;
+    2  PROCEDURE Fib(n : INTEGER) : INTEGER;
+    3  BEGIN
+    4    IF n <= 1 THEN RETURN n ELSE RETURN Fib(n - 1) + Fib(n - 2) END
+    5  END Fib;
+    6  END FLib.
+
+    0 errors
+
+

+ 6 - 0
tests/f_libimpl.mod

@@ -0,0 +1,6 @@
+IMPLEMENTATION MODULE FLib;
+PROCEDURE Fib(n : INTEGER) : INTEGER;
+BEGIN
+  IF n <= 1 THEN RETURN n ELSE RETURN Fib(n - 1) + Fib(n - 2) END
+END Fib;
+END FLib.

+ 9 - 0
tests/l1.LST

@@ -0,0 +1,9 @@
+Listing:
+
+    1  DEFINITION MODULE L1Mod;
+    2  VAR a : INTEGER;
+    3  END L1Mod.
+
+    0 errors
+
+

+ 3 - 0
tests/l1.def

@@ -0,0 +1,3 @@
+DEFINITION MODULE L1Mod;
+VAR a : INTEGER;
+END L1Mod.

+ 10 - 0
tests/l1impl.LST

@@ -0,0 +1,10 @@
+Listing:
+
+    1  IMPLEMENTATION MODULE L1Mod;
+    2  BEGIN
+    3    a := 5
+    4  END L1Mod.
+
+    0 errors
+
+

+ 4 - 0
tests/l1impl.mod

@@ -0,0 +1,4 @@
+IMPLEMENTATION MODULE L1Mod;
+BEGIN
+  a := 5
+END L1Mod.

+ 9 - 0
tests/l2.LST

@@ -0,0 +1,9 @@
+Listing:
+
+    1  DEFINITION MODULE L2Mod;
+    2  VAR b : INTEGER;
+    3  END L2Mod.
+
+    0 errors
+
+

+ 3 - 0
tests/l2.def

@@ -0,0 +1,3 @@
+DEFINITION MODULE L2Mod;
+VAR b : INTEGER;
+END L2Mod.

+ 11 - 0
tests/l2impl.LST

@@ -0,0 +1,11 @@
+Listing:
+
+    1  IMPLEMENTATION MODULE L2Mod;
+    2  FROM L1Mod IMPORT a;
+    3  BEGIN
+    4    b := a * 2
+    5  END L2Mod.
+
+    0 errors
+
+

+ 5 - 0
tests/l2impl.mod

@@ -0,0 +1,5 @@
+IMPLEMENTATION MODULE L2Mod;
+FROM L1Mod IMPORT a;
+BEGIN
+  b := a * 2
+END L2Mod.

+ 10 - 0
tests/t_lib.LST

@@ -0,0 +1,10 @@
+Listing:
+
+    1  DEFINITION MODULE TLib;
+    2  TYPE Point = RECORD x, y : INTEGER END;
+    3  PROCEDURE Move(VAR p : Point; dx, dy : INTEGER);
+    4  END TLib.
+
+    0 errors
+
+

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels