Explorar o código

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

Eric Streit hai 1 mes
pai
achega
480e5149c4
Modificáronse 100 ficheiros con 4171 adicións e 2455 borrados
  1. BIN=BIN
      DBadExp.MC4
  2. BIN=BIN
      DBadImp.MC4
  3. BIN=BIN
      DBasic.MC4
  4. BIN=BIN
      DCase.MC4
  5. BIN=BIN
      DFrom.MC4
  6. BIN=BIN
      DFunc.MC4
  7. BIN=BIN
      DInit.MC4
  8. BIN=BIN
      DMulti.MC4
  9. BIN=BIN
      DType.MC4
  10. BIN=BIN
      M2c
  11. 177 24
      M2c.atg
  12. 34 30
      M2c.err
  13. 2311 2158
      M2c.lst
  14. 83 58
      M2c.mod
  15. BIN=BIN
      M2c.o
  16. 334 131
      M2cP.mod
  17. BIN=BIN
      M2cP.o
  18. 28 26
      M2cS.mod
  19. BIN=BIN
      M2cS.o
  20. 4 0
      MGen.def
  21. 9 0
      MGen.mod
  22. BIN=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=BIN
      Showcase4.MC4
  29. 26 0
      Showcase4.mod
  30. 48 0
      SymTab.def
  31. 267 0
      SymTab.mod
  32. BIN=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=BIN
DBadExp.MC4


BIN=BIN
DBadImp.MC4


BIN=BIN
DBasic.MC4


BIN=BIN
DCase.MC4


BIN=BIN
DFrom.MC4


BIN=BIN
DFunc.MC4


BIN=BIN
DInit.MC4


BIN=BIN
DMulti.MC4


BIN=BIN
DType.MC4


BIN=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=BIN
M2c.o


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 334 - 131
M2cP.mod


BIN=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=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=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=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=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
+
+

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio