Przeglądaj źródła

step6: local MODULEs — vars, consts, parameterless procs, M.x access; 112/112 tests green

Eric Streit 3 tygodni temu
rodzic
commit
9a9789ee2b
57 zmienionych plików z 3275 dodań i 2210 usunięć
  1. BIN
      M2c
  2. 125 15
      M2c.atg
  3. 65 64
      M2c.err
  4. 1989 1879
      M2c.lst
  5. 65 64
      M2c.mod
  6. BIN
      M2c.o
  7. 254 128
      M2cP.mod
  8. BIN
      M2cP.o
  9. 54 53
      M2cS.mod
  10. BIN
      M2cS.o
  11. BIN
      MArr.MC4
  12. BIN
      MBadDup.MC4
  13. BIN
      MBadEnd.MC4
  14. BIN
      MBadExp.MC4
  15. BIN
      MBadFunc.MC4
  16. BIN
      MBadGhost.MC4
  17. BIN
      MBadNest.MC4
  18. BIN
      MBadParam.MC4
  19. BIN
      MBadPriv.MC4
  20. BIN
      MConst.MC4
  21. 11 0
      MGen.def
  22. 74 7
      MGen.mod
  23. BIN
      MGen.o
  24. BIN
      MMod.MC4
  25. BIN
      MMulti.MC4
  26. BIN
      MOuter.MC4
  27. 40 0
      SymTab.def
  28. 148 0
      SymTab.mod
  29. BIN
      SymTab.o
  30. 65 0
      docs/summary_step6.md
  31. 17 0
      run_tests.sh
  32. 15 0
      tests/m_arr.LST
  33. 9 0
      tests/m_arr.mod
  34. 18 0
      tests/m_bad_dup.LST
  35. 11 0
      tests/m_bad_dup.mod
  36. 15 0
      tests/m_bad_end.LST
  37. 8 0
      tests/m_bad_end.mod
  38. 15 0
      tests/m_bad_exp.LST
  39. 8 0
      tests/m_bad_exp.mod
  40. 19 0
      tests/m_bad_func.LST
  41. 12 0
      tests/m_bad_func.mod
  42. 15 0
      tests/m_bad_ghost.LST
  43. 8 0
      tests/m_bad_ghost.mod
  44. 19 0
      tests/m_bad_nest.LST
  45. 12 0
      tests/m_bad_nest.mod
  46. 21 0
      tests/m_bad_param.LST
  47. 14 0
      tests/m_bad_param.mod
  48. 16 0
      tests/m_bad_priv.LST
  49. 9 0
      tests/m_bad_priv.mod
  50. 14 0
      tests/m_const.LST
  51. 8 0
      tests/m_const.mod
  52. 21 0
      tests/m_mod.LST
  53. 15 0
      tests/m_mod.mod
  54. 19 0
      tests/m_multi.LST
  55. 13 0
      tests/m_multi.mod
  56. 20 0
      tests/m_outer.LST
  57. 14 0
      tests/m_outer.mod

BIN
M2c


+ 125 - 15
M2c.atg

@@ -3,7 +3,9 @@ COMPILER M2c
    (see MGen for details).
 
    - program module only, no DEFINITION / IMPLEMENTATION split
-   - no local modules, no EXPORT, no PRIORITY
+   - local MODULEs (single-file, no nesting, no bodies): EXPORT of
+     VARs, CONSTs and parameterless proper procedures; use as M.x /
+     M.P(); no EXPORT of types, no module params/functions, no PRIORITY
    - procedures: declarations (nested), value and VAR parameters,
      functions with RETURN, recursion, FORWARD headings;
      no procedure types/variables, no cones
@@ -144,7 +146,8 @@ PRODUCTIONS
               | "VAR"
                           {
                             VarDecl ";" }
-              | ProcedureDecl ";" .
+              | ProcedureDecl ";"
+              | ModuleDecl ";" .
   ConstDecl                             (. VAR n: SymTab.Name;
                                              t: SymTab.TypeIndex;
                                              lx: MGen.LitStr;
@@ -249,6 +252,40 @@ PRODUCTIONS
       | "FORWARD"                     (. SymTab.SetForward;
                                            SymTab.CloseProc;
                                            MGen.DefLabel(endL); .) ) .
+  ModuleDecl                            (. VAR n, m, e: SymTab.Name;
+                                             noMod, enterOk: BOOLEAN; .)
+    = "MODULE"                          (. noMod := SymTab.InProc()
+                                                  OR SymTab.InModule();
+                                           enterOk := FALSE; .)
+      GetIdent<n>                       (. IF noMod THEN
+                                           SemError(230)
+                                         ELSIF ~SymTab.EnterModule(n) THEN
+                                           SemError(200)
+                                         ELSE
+                                           enterOk := TRUE
+                                         END; .)
+      [ "EXPORT"
+        GetIdent<e>                     (. IF ~noMod & enterOk THEN
+                                           IF ~SymTab.ModuleAddExp(e) THEN
+                                             SemError(200)
+                                           END
+                                         END; .)
+        { "," GetIdent<e>               (. IF ~noMod & enterOk THEN
+                                           IF ~SymTab.ModuleAddExp(e) THEN
+                                             SemError(200)
+                                           END
+                                         END; .) } ]
+      ";"
+      { Declaration }
+      "END"
+      GetIdent<m>                       (. IF ~SymTab.Equal(n, m) THEN
+                                           SemError(202)
+                                         END;
+                                         IF ~noMod & enterOk THEN
+                                           IF ~SymTab.ExitModule() THEN
+                                             SemError(201)
+                                           END
+                                         END; .) .
   FormalParams = FPSection { ";" FPSection } .
   FPSection                             (. VAR isV: BOOLEAN;
                                              nn, i: CARDINAL;
@@ -553,7 +590,8 @@ PRODUCTIONS
     =                                   (. sfx := FALSE; pushedDst := FALSE;
                                            pushedFld := FALSE; .)
       DesignHead<dt, dk, bn, FALSE, lxD>
-      ( DesignTail<dt, dk, bn, FALSE, lxD, sfx> ":="
+      DesignTail<dt, dk, bn, FALSE, lxD, sfx>
+      ( ":="
                                         (. storable :=
                                              (dk = SymTab.KindVar)
                                              OR (dk = SymTab.KindParam)
@@ -720,27 +758,64 @@ PRODUCTIONS
                                            END
                                          ELSE MGen.Drop
                                          END; .)
-      | CallTail<bn, sfx, FALSE, okC, FALSE>
+      | CallTail<bn, lxD, sfx, FALSE, okC, FALSE>
       |                             (. MGen.ActBegin(bn);
                                        IF MGen.ActEnd(bn, FALSE, FALSE) # 0 THEN
                                          SemError(233)
                                        END; .) ) .
-  CallTail <pn: SymTab.Name; sfx: BOOLEAN; inExpr: BOOLEAN;
-            VAR ok: BOOLEAN; hasDead: BOOLEAN>
+  CallTail <pn: SymTab.Name; exp: SymTab.Name; sfx: BOOLEAN;
+            inExpr: BOOLEAN; VAR ok: BOOLEAN; hasDead: BOOLEAN>
                                         (. VAR t: SymTab.TypeIndex;
                                              lx: MGen.LitStr;
                                              v: BOOLEAN;
-                                             vn: SymTab.Name; .)
-    = "("                               (. ok := FALSE;
+                                             vn: SymTab.Name;
+                                             isModP: BOOLEAN;
+                                             modPNum: INTEGER;
+                                             modErr: BOOLEAN; .)
+    = "("                               (. ok := FALSE; modErr := FALSE;
+                                           isModP :=
+                                             (SymTab.SymKind(pn)
+                                              = SymTab.KindModule)
+                                             & sfx
+                                             & (SymTab.StrLen(exp) > 0);
                                            IF hasDead THEN MGen.Drop END;
-                                           MGen.ActBegin(pn); .)
-      [ Expr<t, lx, v, vn>              (. IF MGen.ActValue(t, v, vn) # 0 THEN
+                                           IF isModP THEN
+                                             IF inExpr THEN
+                                               SemError(233);
+                                               modErr := TRUE
+                                             END
+                                           ELSE
+                                             MGen.ActBegin(pn)
+                                           END; .)
+      [ Expr<t, lx, v, vn>              (. IF isModP THEN
+                                           IF ~modErr THEN
+                                             SemError(233);
+                                             modErr := TRUE
+                                           END
+                                         ELSIF MGen.ActValue(t, v, vn) # 0 THEN
                                            SemError(233)
                                          END; .)
-        { "," Expr<t, lx, v, vn>        (. IF MGen.ActValue(t, v, vn) # 0 THEN
+        { "," Expr<t, lx, v, vn>        (. IF isModP THEN
+                                           IF ~modErr THEN
+                                             SemError(233);
+                                             modErr := TRUE
+                                           END
+                                         ELSIF MGen.ActValue(t, v, vn) # 0 THEN
                                            SemError(233)
                                          END; .) } ]
-      ")"                               (. IF MGen.ActEnd(pn, sfx, inExpr) # 0
+      ")"                               (. IF isModP THEN
+                                           IF ~inExpr & ~modErr THEN
+                                             modPNum := SymTab.ExpProc(pn,
+                                                              exp);
+                                             IF modPNum < 0 THEN
+                                               SemError(233)
+                                             ELSE
+                                               MGen.CallProc(modPNum);
+                                               ok := TRUE
+                                             END
+                                           END
+                                         ELSIF MGen.ActEnd(pn, sfx,
+                                                  inExpr) # 0
                                          THEN SemError(233)
                                          ELSE ok := TRUE
                                          END; .) .
@@ -1294,7 +1369,8 @@ PRODUCTIONS
                                              elemT: SymTab.TypeIndex;
                                              esl, ebytes: CARDINAL;
                                              firstT: BOOLEAN;
-                                             clsI: INTEGER; .)
+                                             clsI: INTEGER;
+                                             qM: SymTab.Name; .)
     =                                   (. sfx := FALSE; .)
       { "."                             (. firstT := ~sfx;
                                            sfx := TRUE; lx[0] := 0C;
@@ -1307,10 +1383,44 @@ PRODUCTIONS
                                              ELSIF k
                                                = SymTab.KindField THEN
                                                MGen.WithAddr(bn)
+                                             ELSIF k
+                                               = SymTab.KindModule THEN
                                              ELSE MGen.PushInt(0)
                                              END
                                            END; .)
-        GetIdent<m>                     (. IF t = SymTab.InvalidType THEN
+        GetIdent<m>                     (. IF (k = SymTab.KindModule) THEN
+                                             IF SymTab.ExpKind(bn, m) = -1 THEN
+                                               SemError(201);
+                                               t := SymTab.InvalidType;
+                                               IF doLoad THEN
+                                                 MGen.Drop; MGen.PushInt(0)
+                                               ELSIF firstT THEN
+                                               ELSE MGen.Drop
+                                               END
+                                             ELSIF SymTab.ExpKind(bn, m)
+                                                    = SymTab.KindProc THEN
+                                               MGen.CopyName(m, lx);
+                                               t := SymTab.InvalidType;
+                                               IF doLoad THEN
+                                                 MGen.Drop; MGen.PushInt(0)
+                                               ELSIF firstT THEN
+                                               ELSE MGen.Drop
+                                               END
+                                             ELSE
+                                               t := SymTab.ExpType(bn, m);
+                                               k := SymTab.ExpKind(bn, m);
+                                               SymTab.ExpQual(bn, m, qM);
+                                               IF doLoad THEN
+                                                 MGen.Drop;
+                                                 MGen.GlobalAddr(qM)
+                                               ELSE
+                                                 IF firstT THEN
+                                                 ELSE MGen.Drop
+                                                 END;
+                                                 MGen.GlobalAddr(qM)
+                                               END
+                                             END
+                                           ELSIF t = SymTab.InvalidType THEN
                                              IF ~doLoad & firstT THEN
                                                MGen.Drop
                                              ELSIF doLoad THEN
@@ -1819,7 +1929,7 @@ PRODUCTIONS
                                                 OR (dk
                                                     = SymTab.KindVarPar));
                                            MGen.CopyName(bnF, vn); .)
-      [ CallTail<bnF, sfxF, TRUE, okF, TRUE>
+      [ CallTail<bnF, lxD, sfxF, TRUE, okF, TRUE>
                                         (. IF okF THEN
                                              IF SymTab.SymKind(bnF)
                                                 = SymTab.KindProc THEN

+ 65 - 64
M2c.err

@@ -20,67 +20,68 @@
 | 19: Msg("'(' expected")
 | 20: Msg("')' expected")
 | 21: Msg("'FORWARD' expected")
-| 22: Msg("'[' expected")
-| 23: Msg("'..' expected")
-| 24: Msg("']' expected")
-| 25: Msg("'ARRAY' expected")
-| 26: Msg("'OF' expected")
-| 27: Msg("'RECORD' expected")
-| 28: Msg("'SET' expected")
-| 29: Msg("'POINTER' expected")
-| 30: Msg("'TO' expected")
-| 31: Msg("'EXIT' expected")
-| 32: Msg("':=' expected")
-| 33: Msg("'IF' expected")
-| 34: Msg("'THEN' expected")
-| 35: Msg("'ELSIF' expected")
-| 36: Msg("'ELSE' expected")
-| 37: Msg("'CASE' expected")
-| 38: Msg("'|' expected")
-| 39: Msg("'WHILE' expected")
-| 40: Msg("'DO' expected")
-| 41: Msg("'REPEAT' expected")
-| 42: Msg("'UNTIL' expected")
-| 43: Msg("'LOOP' expected")
-| 44: Msg("'FOR' expected")
-| 45: Msg("'BY' expected")
-| 46: Msg("'-' expected")
-| 47: Msg("'WITH' expected")
-| 48: Msg("'RETURN' expected")
-| 49: Msg("'NEW' expected")
-| 50: Msg("'DISPOSE' expected")
-| 51: Msg("'WriteInt' expected")
-| 52: Msg("'WriteString' expected")
-| 53: Msg("'^' expected")
-| 54: Msg("'#' expected")
-| 55: Msg("'<>' expected")
-| 56: Msg("'<' expected")
-| 57: Msg("'<=' expected")
-| 58: Msg("'>' expected")
-| 59: Msg("'>=' expected")
-| 60: Msg("'IN' expected")
-| 61: Msg("'+' expected")
-| 62: Msg("'OR' expected")
-| 63: Msg("'*' expected")
-| 64: Msg("'/' expected")
-| 65: Msg("'DIV' expected")
-| 66: Msg("'MOD' expected")
-| 67: Msg("'AND' expected")
-| 68: Msg("'&' expected")
-| 69: Msg("'HIGH' expected")
-| 70: Msg("'NOT' expected")
-| 71: Msg("'~' expected")
-| 72: Msg("'{' expected")
-| 73: Msg("'}' expected")
-| 74: Msg("not expected")
-| 75: Msg("invalid MulOp")
-| 76: Msg("invalid Fact")
-| 77: Msg("invalid AddOp")
-| 78: Msg("invalid Rel")
-| 79: Msg("invalid ByLit")
-| 80: Msg("invalid AssignOrCall")
-| 81: Msg("invalid SimpleType")
-| 82: Msg("invalid Type")
-| 83: Msg("invalid ProcedureDecl")
-| 84: Msg("invalid Declaration")
-| 85: Msg("invalid Import")
+| 22: Msg("'EXPORT' expected")
+| 23: Msg("'[' expected")
+| 24: Msg("'..' expected")
+| 25: Msg("']' expected")
+| 26: Msg("'ARRAY' expected")
+| 27: Msg("'OF' expected")
+| 28: Msg("'RECORD' expected")
+| 29: Msg("'SET' expected")
+| 30: Msg("'POINTER' expected")
+| 31: Msg("'TO' expected")
+| 32: Msg("'EXIT' expected")
+| 33: Msg("':=' expected")
+| 34: Msg("'IF' expected")
+| 35: Msg("'THEN' expected")
+| 36: Msg("'ELSIF' expected")
+| 37: Msg("'ELSE' expected")
+| 38: Msg("'CASE' expected")
+| 39: Msg("'|' expected")
+| 40: Msg("'WHILE' expected")
+| 41: Msg("'DO' expected")
+| 42: Msg("'REPEAT' expected")
+| 43: Msg("'UNTIL' expected")
+| 44: Msg("'LOOP' expected")
+| 45: Msg("'FOR' expected")
+| 46: Msg("'BY' expected")
+| 47: Msg("'-' expected")
+| 48: Msg("'WITH' expected")
+| 49: Msg("'RETURN' expected")
+| 50: Msg("'NEW' expected")
+| 51: Msg("'DISPOSE' expected")
+| 52: Msg("'WriteInt' expected")
+| 53: Msg("'WriteString' expected")
+| 54: Msg("'^' expected")
+| 55: Msg("'#' expected")
+| 56: Msg("'<>' expected")
+| 57: Msg("'<' expected")
+| 58: Msg("'<=' expected")
+| 59: Msg("'>' expected")
+| 60: Msg("'>=' expected")
+| 61: Msg("'IN' expected")
+| 62: Msg("'+' expected")
+| 63: Msg("'OR' expected")
+| 64: Msg("'*' expected")
+| 65: Msg("'/' expected")
+| 66: Msg("'DIV' expected")
+| 67: Msg("'MOD' expected")
+| 68: Msg("'AND' expected")
+| 69: Msg("'&' expected")
+| 70: Msg("'HIGH' expected")
+| 71: Msg("'NOT' expected")
+| 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")

+ 1989 - 1879
M2c.lst

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

+ 65 - 64
M2c.mod

@@ -117,70 +117,71 @@ MODULE M2c;
         | 19: Msg("'(' expected")
         | 20: Msg("')' expected")
         | 21: Msg("'FORWARD' expected")
-        | 22: Msg("'[' expected")
-        | 23: Msg("'..' expected")
-        | 24: Msg("']' expected")
-        | 25: Msg("'ARRAY' expected")
-        | 26: Msg("'OF' expected")
-        | 27: Msg("'RECORD' expected")
-        | 28: Msg("'SET' expected")
-        | 29: Msg("'POINTER' expected")
-        | 30: Msg("'TO' expected")
-        | 31: Msg("'EXIT' expected")
-        | 32: Msg("':=' expected")
-        | 33: Msg("'IF' expected")
-        | 34: Msg("'THEN' expected")
-        | 35: Msg("'ELSIF' expected")
-        | 36: Msg("'ELSE' expected")
-        | 37: Msg("'CASE' expected")
-        | 38: Msg("'|' expected")
-        | 39: Msg("'WHILE' expected")
-        | 40: Msg("'DO' expected")
-        | 41: Msg("'REPEAT' expected")
-        | 42: Msg("'UNTIL' expected")
-        | 43: Msg("'LOOP' expected")
-        | 44: Msg("'FOR' expected")
-        | 45: Msg("'BY' expected")
-        | 46: Msg("'-' expected")
-        | 47: Msg("'WITH' expected")
-        | 48: Msg("'RETURN' expected")
-        | 49: Msg("'NEW' expected")
-        | 50: Msg("'DISPOSE' expected")
-        | 51: Msg("'WriteInt' expected")
-        | 52: Msg("'WriteString' expected")
-        | 53: Msg("'^' expected")
-        | 54: Msg("'#' expected")
-        | 55: Msg("'<>' expected")
-        | 56: Msg("'<' expected")
-        | 57: Msg("'<=' expected")
-        | 58: Msg("'>' expected")
-        | 59: Msg("'>=' expected")
-        | 60: Msg("'IN' expected")
-        | 61: Msg("'+' expected")
-        | 62: Msg("'OR' expected")
-        | 63: Msg("'*' expected")
-        | 64: Msg("'/' expected")
-        | 65: Msg("'DIV' expected")
-        | 66: Msg("'MOD' expected")
-        | 67: Msg("'AND' expected")
-        | 68: Msg("'&' expected")
-        | 69: Msg("'HIGH' expected")
-        | 70: Msg("'NOT' expected")
-        | 71: Msg("'~' expected")
-        | 72: Msg("'{' expected")
-        | 73: Msg("'}' expected")
-        | 74: Msg("not expected")
-        | 75: Msg("invalid MulOp")
-        | 76: Msg("invalid Fact")
-        | 77: Msg("invalid AddOp")
-        | 78: Msg("invalid Rel")
-        | 79: Msg("invalid ByLit")
-        | 80: Msg("invalid AssignOrCall")
-        | 81: Msg("invalid SimpleType")
-        | 82: Msg("invalid Type")
-        | 83: Msg("invalid ProcedureDecl")
-        | 84: Msg("invalid Declaration")
-        | 85: Msg("invalid Import")
+        | 22: Msg("'EXPORT' expected")
+        | 23: Msg("'[' expected")
+        | 24: Msg("'..' expected")
+        | 25: Msg("']' expected")
+        | 26: Msg("'ARRAY' expected")
+        | 27: Msg("'OF' expected")
+        | 28: Msg("'RECORD' expected")
+        | 29: Msg("'SET' expected")
+        | 30: Msg("'POINTER' expected")
+        | 31: Msg("'TO' expected")
+        | 32: Msg("'EXIT' expected")
+        | 33: Msg("':=' expected")
+        | 34: Msg("'IF' expected")
+        | 35: Msg("'THEN' expected")
+        | 36: Msg("'ELSIF' expected")
+        | 37: Msg("'ELSE' expected")
+        | 38: Msg("'CASE' expected")
+        | 39: Msg("'|' expected")
+        | 40: Msg("'WHILE' expected")
+        | 41: Msg("'DO' expected")
+        | 42: Msg("'REPEAT' expected")
+        | 43: Msg("'UNTIL' expected")
+        | 44: Msg("'LOOP' expected")
+        | 45: Msg("'FOR' expected")
+        | 46: Msg("'BY' expected")
+        | 47: Msg("'-' expected")
+        | 48: Msg("'WITH' expected")
+        | 49: Msg("'RETURN' expected")
+        | 50: Msg("'NEW' expected")
+        | 51: Msg("'DISPOSE' expected")
+        | 52: Msg("'WriteInt' expected")
+        | 53: Msg("'WriteString' expected")
+        | 54: Msg("'^' expected")
+        | 55: Msg("'#' expected")
+        | 56: Msg("'<>' expected")
+        | 57: Msg("'<' expected")
+        | 58: Msg("'<=' expected")
+        | 59: Msg("'>' expected")
+        | 60: Msg("'>=' expected")
+        | 61: Msg("'IN' expected")
+        | 62: Msg("'+' expected")
+        | 63: Msg("'OR' expected")
+        | 64: Msg("'*' expected")
+        | 65: Msg("'/' expected")
+        | 66: Msg("'DIV' expected")
+        | 67: Msg("'MOD' expected")
+        | 68: Msg("'AND' expected")
+        | 69: Msg("'&' expected")
+        | 70: Msg("'HIGH' expected")
+        | 71: Msg("'NOT' expected")
+        | 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")
         
         (* add customized cases here *)
         | 200: Msg("duplicate identifier")

BIN
M2c.o


+ 254 - 128
M2cP.mod

@@ -9,7 +9,7 @@ IMPORT SymTab, MGen;
 
 
 CONST 
-  maxT = 74;
+  maxT = 75;
   minErrDist  =  2;  (* minimal distance (good tokens) between two errors *)
   setsize     = 16;  (* sets are stored in 16 bits *)
 
@@ -131,8 +131,8 @@ PROCEDURE Labels (sel: SymTab.TypeIndex; tmp: INTEGER; bodyL: INTEGER); FORWARD;
 PROCEDURE LabelList (sel: SymTab.TypeIndex; tmp: INTEGER;
                       VAR lB: INTEGER; VAR lN: INTEGER); FORWARD;
 PROCEDURE Case (sel: SymTab.TypeIndex; tmp: INTEGER; endL: INTEGER); FORWARD;
-PROCEDURE CallTail (pn: SymTab.Name; sfx: BOOLEAN; inExpr: BOOLEAN;
-                     VAR ok: BOOLEAN; hasDead: BOOLEAN); FORWARD;
+PROCEDURE CallTail (pn: SymTab.Name; exp: SymTab.Name; sfx: BOOLEAN;
+                     inExpr: BOOLEAN; VAR ok: BOOLEAN; hasDead: BOOLEAN); FORWARD;
 PROCEDURE DesignTail (VAR t: SymTab.TypeIndex; VAR k: INTEGER;
                        VAR bn: SymTab.Name; doLoad: BOOLEAN; VAR lx: MGen.LitStr;
                        VAR sfx: BOOLEAN); FORWARD;
@@ -169,6 +169,7 @@ PROCEDURE Type (VAR t: SymTab.TypeIndex); FORWARD;
 PROCEDURE Expr (VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
                  VAR v: BOOLEAN; VAR vn: SymTab.Name); FORWARD;
 PROCEDURE ConstExpr (VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr); FORWARD;
+PROCEDURE ModuleDecl; FORWARD;
 PROCEDURE ProcedureDecl; FORWARD;
 PROCEDURE VarDecl; FORWARD;
 PROCEDURE TypeDecl; FORWARD;
@@ -192,7 +193,7 @@ PROCEDURE Elem (VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
     Expr(t, lx, vD, vnD);
     hasR := FALSE;
     lx2[0] := 0C;;
-    IF (sym = 23) THEN
+    IF (sym = 24) THEN
       Get;
       Expr(t2, lx2, vD2, vnD2);
       IF ~SymTab.SetElemCheck(t, t2) THEN
@@ -208,7 +209,7 @@ PROCEDURE SetLit (VAR t: SymTab.TypeIndex);
     vnE, vnE2: SymTab.Name;
     hasR: BOOLEAN;
   BEGIN
-    Expect(72);
+    Expect(73);
     MGen.PushInt(0);
     t := SymTab.SetFor(SymTab.IntType());;
     IF In(symSet[1], sym) THEN
@@ -232,31 +233,31 @@ PROCEDURE SetLit (VAR t: SymTab.TypeIndex);
         MGen.Or;;
       END;
     END;
-    Expect(73);
+    Expect(74);
   END SetLit;
 
 PROCEDURE MulOp (VAR op: INTEGER);
   BEGIN
     CASE sym OF
-      63 :
+      64 :
         Get;
         op := SymTab.OpTimes;;
-    | 64 :
+    | 65 :
         Get;
         op := SymTab.OpSlash;;
-    | 65 :
+    | 66 :
         Get;
         op := SymTab.OpDiv;;
-    | 66 :
+    | 67 :
         Get;
         op := SymTab.OpMod;;
-    | 67 :
+    | 68 :
         Get;
         op := SymTab.OpAnd;;
-    | 68 :
+    | 69 :
         Get;
         op := SymTab.OpAnd;;
-    ELSE SynError(75);
+    ELSE SynError(76);
     END;
   END MulOp;
 
@@ -312,7 +313,7 @@ PROCEDURE Fact (VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
           MGen.CopyName(s, lx);
           MGen.EmitString(s)
         END;;
-    | 69 :
+    | 70 :
         Get;
         Expect(19);
         DesignHead(dt, dk, bnF, FALSE, lxD);
@@ -385,7 +386,7 @@ PROCEDURE Fact (VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
                  = SymTab.KindVarPar));
         MGen.CopyName(bnF, vn);;
         IF (sym = 19) THEN
-          CallTail(bnF, sfxF, TRUE, okF, TRUE);
+          CallTail(bnF, lxD, sfxF, TRUE, okF, TRUE);
           IF okF THEN
             IF SymTab.SymKind(bnF)
                = SymTab.KindProc THEN
@@ -402,8 +403,8 @@ PROCEDURE Fact (VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
         Expr(et, lx, v, vn);
         Expect(20);
         t := et;;
-    | 70, 71 :
-        IF (sym = 70) THEN
+    | 71, 72 :
+        IF (sym = 71) THEN
           Get;
         ELSE
           Get;
@@ -415,26 +416,26 @@ PROCEDURE Fact (VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
         ELSE SemError(212);
           t := SymTab.InvalidType END;
         MGen.Not;;
-    | 72 :
+    | 73 :
         SetLit(st);
         lx[0] := 0C; v := FALSE;
         t := st;;
-    ELSE SynError(76);
+    ELSE SynError(77);
     END;
   END Fact;
 
 PROCEDURE AddOp (VAR op: INTEGER);
   BEGIN
-    IF (sym = 61) THEN
+    IF (sym = 62) THEN
       Get;
       op := SymTab.OpAdd;;
-    ELSIF (sym = 46) THEN
+    ELSIF (sym = 47) THEN
       Get;
       op := SymTab.OpSub;;
-    ELSIF (sym = 62) THEN
+    ELSIF (sym = 63) THEN
       Get;
       op := SymTab.OpOr;;
-    ELSE SynError(77);
+    ELSE SynError(78);
     END;
   END AddOp;
 
@@ -491,28 +492,28 @@ PROCEDURE Rel (VAR op: INTEGER);
       16 :
         Get;
         op := SymTab.OpEq;;
-    | 54 :
+    | 55 :
         Get;
         op := SymTab.OpNeq1;;
-    | 55 :
+    | 56 :
         Get;
         op := SymTab.OpNeq2;;
-    | 56 :
+    | 57 :
         Get;
         op := SymTab.OpLt;;
-    | 57 :
+    | 58 :
         Get;
         op := SymTab.OpLe;;
-    | 58 :
+    | 59 :
         Get;
         op := SymTab.OpGt;;
-    | 59 :
+    | 60 :
         Get;
         op := SymTab.OpGe;;
-    | 60 :
+    | 61 :
         Get;
         op := SymTab.OpIn;;
-    ELSE SynError(78);
+    ELSE SynError(79);
     END;
   END Rel;
 
@@ -526,8 +527,8 @@ PROCEDURE SimExpr (VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
     neg, isR: BOOLEAN;
   BEGIN
     neg := FALSE;;
-    IF (sym = 46) OR (sym = 61) THEN
-      IF (sym = 61) THEN
+    IF (sym = 47) OR (sym = 62) THEN
+      IF (sym = 62) THEN
         Get;
       ELSE
         Get;
@@ -547,7 +548,7 @@ PROCEDURE SimExpr (VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
     ELSE MGen.NegInt
     END
     END;;
-    WHILE (sym = 46) OR (sym = 61) OR (sym = 62) DO
+    WHILE (sym = 47) OR (sym = 62) OR (sym = 63) DO
       AddOp(op);
       Term(t2, lx2, v2, vn2);
       lx[0] := 0C; v := FALSE;
@@ -590,7 +591,7 @@ PROCEDURE ByLit (VAR v: INTEGER);
       IF ~MGen.ParseInt(s, v) THEN
         v := 1
       END;;
-    ELSIF (sym = 46) THEN
+    ELSIF (sym = 47) THEN
       Get;
       Expect(2);
       LexString(s);
@@ -598,7 +599,7 @@ PROCEDURE ByLit (VAR v: INTEGER);
         v := -v
       ELSE v := -1
       END;;
-    ELSE SynError(79);
+    ELSE SynError(80);
     END;
   END ByLit;
 
@@ -620,7 +621,7 @@ PROCEDURE Labels (sel: SymTab.TypeIndex; tmp: INTEGER; bodyL: INTEGER);
     ta := MGen.TempGlobal();
     MGen.StoreTemp(ta);
     hasRange := FALSE;;
-    IF (sym = 23) THEN
+    IF (sym = 24) THEN
       Get;
       ConstExpr(t2, lx2);
       IF ~SymTab.EqCheck(t2, sel) THEN
@@ -677,32 +678,69 @@ PROCEDURE Case (sel: SymTab.TypeIndex; tmp: INTEGER; endL: INTEGER);
     END;
   END Case;
 
-PROCEDURE CallTail (pn: SymTab.Name; sfx: BOOLEAN; inExpr: BOOLEAN;
-                     VAR ok: BOOLEAN; hasDead: BOOLEAN);
+PROCEDURE CallTail (pn: SymTab.Name; exp: SymTab.Name; sfx: BOOLEAN;
+                     inExpr: BOOLEAN; VAR ok: BOOLEAN; hasDead: BOOLEAN);
   VAR t: SymTab.TypeIndex;
     lx: MGen.LitStr;
     v: BOOLEAN;
     vn: SymTab.Name;
+    isModP: BOOLEAN;
+    modPNum: INTEGER;
+    modErr: BOOLEAN;
   BEGIN
     Expect(19);
-    ok := FALSE;
+    ok := FALSE; modErr := FALSE;
+    isModP :=
+      (SymTab.SymKind(pn)
+       = SymTab.KindModule)
+      & sfx
+      & (SymTab.StrLen(exp) > 0);
     IF hasDead THEN MGen.Drop END;
-    MGen.ActBegin(pn);;
+    IF isModP THEN
+      IF inExpr THEN
+        SemError(233);
+        modErr := TRUE
+      END
+    ELSE
+      MGen.ActBegin(pn)
+    END;;
     IF In(symSet[1], sym) THEN
       Expr(t, lx, v, vn);
-      IF MGen.ActValue(t, v, vn) # 0 THEN
+      IF isModP THEN
+      IF ~modErr THEN
+        SemError(233);
+        modErr := TRUE
+      END
+      ELSIF MGen.ActValue(t, v, vn) # 0 THEN
       SemError(233)
       END;;
       WHILE (sym = 10) DO
         Get;
         Expr(t, lx, v, vn);
-        IF MGen.ActValue(t, v, vn) # 0 THEN
+        IF isModP THEN
+        IF ~modErr THEN
+          SemError(233);
+          modErr := TRUE
+        END
+        ELSIF MGen.ActValue(t, v, vn) # 0 THEN
         SemError(233)
         END;;
       END;
     END;
     Expect(20);
-    IF MGen.ActEnd(pn, sfx, inExpr) # 0
+    IF isModP THEN
+    IF ~inExpr & ~modErr THEN
+      modPNum := SymTab.ExpProc(pn,
+                       exp);
+      IF modPNum < 0 THEN
+        SemError(233)
+      ELSE
+        MGen.CallProc(modPNum);
+        ok := TRUE
+      END
+    END
+    ELSIF MGen.ActEnd(pn, sfx,
+           inExpr) # 0
     THEN SemError(233)
     ELSE ok := TRUE
     END;;
@@ -721,9 +759,10 @@ PROCEDURE DesignTail (VAR t: SymTab.TypeIndex; VAR k: INTEGER;
     esl, ebytes: CARDINAL;
     firstT: BOOLEAN;
     clsI: INTEGER;
+    qM: SymTab.Name;
   BEGIN
     sfx := FALSE;;
-    WHILE (sym = 7) OR (sym = 22) OR (sym = 53) DO
+    WHILE (sym = 7) OR (sym = 23) OR (sym = 54) DO
       IF (sym = 7) THEN
         Get;
         firstT := ~sfx;
@@ -737,11 +776,45 @@ PROCEDURE DesignTail (VAR t: SymTab.TypeIndex; VAR k: INTEGER;
           ELSIF k
             = SymTab.KindField THEN
             MGen.WithAddr(bn)
+          ELSIF k
+            = SymTab.KindModule THEN
           ELSE MGen.PushInt(0)
           END
         END;;
         GetIdent(m);
-        IF t = SymTab.InvalidType THEN
+        IF (k = SymTab.KindModule) THEN
+          IF SymTab.ExpKind(bn, m) = -1 THEN
+            SemError(201);
+            t := SymTab.InvalidType;
+            IF doLoad THEN
+              MGen.Drop; MGen.PushInt(0)
+            ELSIF firstT THEN
+            ELSE MGen.Drop
+            END
+          ELSIF SymTab.ExpKind(bn, m)
+                 = SymTab.KindProc THEN
+            MGen.CopyName(m, lx);
+            t := SymTab.InvalidType;
+            IF doLoad THEN
+              MGen.Drop; MGen.PushInt(0)
+            ELSIF firstT THEN
+            ELSE MGen.Drop
+            END
+          ELSE
+            t := SymTab.ExpType(bn, m);
+            k := SymTab.ExpKind(bn, m);
+            SymTab.ExpQual(bn, m, qM);
+            IF doLoad THEN
+              MGen.Drop;
+              MGen.GlobalAddr(qM)
+            ELSE
+              IF firstT THEN
+              ELSE MGen.Drop
+              END;
+              MGen.GlobalAddr(qM)
+            END
+          END
+        ELSIF t = SymTab.InvalidType THEN
           IF ~doLoad & firstT THEN
             MGen.Drop
           ELSIF doLoad THEN
@@ -781,7 +854,7 @@ PROCEDURE DesignTail (VAR t: SymTab.TypeIndex; VAR k: INTEGER;
             t := elemT
           END
         END;;
-      ELSIF (sym = 22) THEN
+      ELSIF (sym = 23) THEN
         Get;
         firstT := ~sfx;
         sfx := TRUE; lx[0] := 0C;
@@ -909,7 +982,7 @@ PROCEDURE DesignTail (VAR t: SymTab.TypeIndex; VAR k: INTEGER;
           END
           END;;
         END;
-        Expect(24);
+        Expect(25);
       ELSE
         Get;
         firstT := ~sfx;
@@ -1086,7 +1159,7 @@ PROCEDURE WriteStrStat;
     v: BOOLEAN;
     vn: SymTab.Name;
   BEGIN
-    Expect(52);
+    Expect(53);
     Expect(19);
     Expr(t, lx, v, vn);
     Expect(20);
@@ -1115,7 +1188,7 @@ PROCEDURE WriteIntStat;
     v: BOOLEAN;
     vn: SymTab.Name;
   BEGIN
-    Expect(51);
+    Expect(52);
     Expect(19);
     Expr(t, lx, v, vn);
     Expect(20);
@@ -1138,7 +1211,7 @@ PROCEDURE DispStat;
     baseT: SymTab.TypeIndex;
     slD: CARDINAL;
   BEGIN
-    Expect(50);
+    Expect(51);
     Expect(19);
     DesignHead(dt, dk, bnD, FALSE, lxD);
     DesignTail(dt, dk, bnD, FALSE, lxD, sfxD);
@@ -1183,7 +1256,7 @@ PROCEDURE NewStat;
     baseT: SymTab.TypeIndex;
     slN: CARDINAL;
   BEGIN
-    Expect(49);
+    Expect(50);
     Expect(19);
     DesignHead(dt, dk, bnN, FALSE, lxN);
     DesignTail(dt, dk, bnN, FALSE, lxN, sfxN);
@@ -1226,7 +1299,7 @@ PROCEDURE ReturnStat;
     vn: SymTab.Name;
     hasE, doRet, conv: BOOLEAN;
   BEGIN
-    Expect(48);
+    Expect(49);
     hasE := FALSE;;
     IF In(symSet[1], sym) THEN
       Expr(t, lx, v, vn);
@@ -1274,7 +1347,7 @@ PROCEDURE WithStat;
     sfxW: BOOLEAN;
     pushed: BOOLEAN;
   BEGIN
-    Expect(47);
+    Expect(48);
     DesignHead(dt, dk, bnW, FALSE, lxW);
     DesignTail(dt, dk, bnW, FALSE, lxW, sfxW);
     pushed := FALSE;
@@ -1306,7 +1379,7 @@ PROCEDURE WithStat;
           SemError(215)
         END
       END;;
-    Expect(40);
+    Expect(41);
     StatSeq;
     Expect(12);
     IF pushed THEN
@@ -1326,7 +1399,7 @@ PROCEDURE ForStat;
     lTop, lChk, lEnd: INTEGER;
     neg, storable: BOOLEAN;
   BEGIN
-    Expect(44);
+    Expect(45);
     GetIdent(n);
     IF ~SymTab.Lookup(n) THEN
      SemError(201);
@@ -1357,7 +1430,7 @@ PROCEDURE ForStat;
     IF storable THEN
      MGen.StoreSetup(lv)
     END;;
-    Expect(32);
+    Expect(33);
     Expr(lo, lxLo, vLo, vnLo);
     IF (lo # SymTab.InvalidType)
     & ~SymTab.IsIntFamily(lo) THEN
@@ -1366,7 +1439,7 @@ PROCEDURE ForStat;
       MGen.StoreFinish(lv)
     ELSE MGen.Drop
     END;;
-    Expect(30);
+    Expect(31);
     Expr(hi, lxHi, vHi, vnHi);
     IF (hi # SymTab.InvalidType)
     & ~SymTab.IsIntFamily(hi) THEN
@@ -1374,12 +1447,12 @@ PROCEDURE ForStat;
     ht := MGen.TempGlobal();
     MGen.StoreTemp(ht);
     byV := 1; neg := FALSE;;
-    IF (sym = 45) THEN
+    IF (sym = 46) THEN
       Get;
       ByLit(byV);
       neg := byV < 0;;
     END;
-    Expect(40);
+    Expect(41);
     lTop := MGen.NewLabel();
     lChk := MGen.NewLabel();
     lEnd := MGen.NewLabel();
@@ -1407,7 +1480,7 @@ PROCEDURE ForStat;
 PROCEDURE LoopStat;
   VAR topL, exitL: INTEGER;
   BEGIN
-    Expect(43);
+    Expect(44);
     topL := MGen.NewLabel();
     exitL := MGen.NewLabel();
     MGen.DefLabel(topL);
@@ -1426,11 +1499,11 @@ PROCEDURE RepeatStat;
     vnC: SymTab.Name;
     topL: INTEGER;
   BEGIN
-    Expect(41);
+    Expect(42);
     topL := MGen.NewLabel();
     MGen.DefLabel(topL);;
     StatSeq;
-    Expect(42);
+    Expect(43);
     Expr(t, lxC, vC, vnC);
     IF ~SymTab.BoolCheck(t) THEN
     SemError(214) END;
@@ -1444,7 +1517,7 @@ PROCEDURE WhileStat;
     vnC: SymTab.Name;
     topL, endL: INTEGER;
   BEGIN
-    Expect(39);
+    Expect(40);
     topL := MGen.NewLabel();
     endL := MGen.NewLabel();
     MGen.DefLabel(topL);;
@@ -1452,7 +1525,7 @@ PROCEDURE WhileStat;
     IF ~SymTab.BoolCheck(t) THEN
     SemError(214) END;
     MGen.Jz(endL);;
-    Expect(40);
+    Expect(41);
     StatSeq;
     Expect(12);
     MGen.Jmp(topL);
@@ -1466,18 +1539,18 @@ PROCEDURE CaseStat;
     vnS: SymTab.Name;
     tmp, endL: INTEGER;
   BEGIN
-    Expect(37);
+    Expect(38);
     Expr(st, lxS, vS, vnS);
     tmp := MGen.TempGlobal();
     MGen.StoreTemp(tmp);
     endL := MGen.NewLabel();;
-    Expect(26);
+    Expect(27);
     Case(st, tmp, endL);
-    WHILE (sym = 38) DO
+    WHILE (sym = 39) DO
       Get;
       Case(st, tmp, endL);
     END;
-    IF (sym = 36) THEN
+    IF (sym = 37) THEN
       Get;
       StatSeq;
     END;
@@ -1493,7 +1566,7 @@ PROCEDURE IfStat;
     elseL, endL: INTEGER;
     hasElse: BOOLEAN;
   BEGIN
-    Expect(33);
+    Expect(34);
     Expr(t, lxC, vC, vnC);
     IF ~SymTab.BoolCheck(t) THEN
     SemError(214) END;
@@ -1501,9 +1574,9 @@ PROCEDURE IfStat;
     endL := MGen.NewLabel();
     MGen.Jz(elseL);
     hasElse := FALSE;;
-    Expect(34);
+    Expect(35);
     StatSeq;
-    WHILE (sym = 35) DO
+    WHILE (sym = 36) DO
       Get;
       MGen.Jmp(endL);
       MGen.DefLabel(elseL);;
@@ -1512,10 +1585,10 @@ PROCEDURE IfStat;
       SemError(214) END;
       elseL := MGen.NewLabel();
       MGen.Jz(elseL);;
-      Expect(34);
+      Expect(35);
       StatSeq;
     END;
-    IF (sym = 36) THEN
+    IF (sym = 37) THEN
       Get;
       MGen.Jmp(endL);
       MGen.DefLabel(elseL);
@@ -1547,9 +1620,9 @@ PROCEDURE AssignOrCall;
     sfx := FALSE; pushedDst := FALSE;
     pushedFld := FALSE;;
     DesignHead(dt, dk, bn, FALSE, lxD);
-    IF (sym = 7) OR (sym = 22) OR (sym = 32) OR (sym = 53) THEN
-      DesignTail(dt, dk, bn, FALSE, lxD, sfx);
-      Expect(32);
+    DesignTail(dt, dk, bn, FALSE, lxD, sfx);
+    IF (sym = 33) THEN
+      Get;
       storable :=
         (dk = SymTab.KindVar)
         OR (dk = SymTab.KindParam)
@@ -1718,13 +1791,13 @@ PROCEDURE AssignOrCall;
       ELSE MGen.Drop
       END;;
     ELSIF (sym = 19) THEN
-      CallTail(bn, sfx, FALSE, okC, FALSE);
+      CallTail(bn, lxD, sfx, FALSE, okC, FALSE);
     ELSIF In(symSet[3], sym) THEN
       MGen.ActBegin(bn);
       IF MGen.ActEnd(bn, FALSE, FALSE) # 0 THEN
         SemError(233)
       END;;
-    ELSE SynError(80);
+    ELSE SynError(81);
     END;
   END AssignOrCall;
 
@@ -1735,31 +1808,31 @@ PROCEDURE Stat;
       CASE sym OF
         1 :
           AssignOrCall;
-      | 33 :
+      | 34 :
           IfStat;
-      | 37 :
+      | 38 :
           CaseStat;
-      | 39 :
+      | 40 :
           WhileStat;
-      | 41 :
+      | 42 :
           RepeatStat;
-      | 43 :
-          LoopStat;
       | 44 :
+          LoopStat;
+      | 45 :
           ForStat;
-      | 47 :
-          WithStat;
       | 48 :
-          ReturnStat;
+          WithStat;
       | 49 :
-          NewStat;
+          ReturnStat;
       | 50 :
-          DispStat;
+          NewStat;
       | 51 :
-          WriteIntStat;
+          DispStat;
       | 52 :
+          WriteIntStat;
+      | 53 :
           WriteStrStat;
-      | 31 :
+      | 32 :
           Get;
           IF MGen.TopLoop(lx) THEN
             MGen.Jmp(lx)
@@ -1838,8 +1911,8 @@ PROCEDURE Enum (VAR t: SymTab.TypeIndex);
 PROCEDURE PointerType (VAR t: SymTab.TypeIndex);
   VAR b: SymTab.TypeIndex;
   BEGIN
-    Expect(29);
     Expect(30);
+    Expect(31);
     Type(b);
     t := SymTab.NewPtr(b);;
   END PointerType;
@@ -1847,8 +1920,8 @@ PROCEDURE PointerType (VAR t: SymTab.TypeIndex);
 PROCEDURE SetType (VAR t: SymTab.TypeIndex);
   VAR s: SymTab.TypeIndex;
   BEGIN
-    Expect(28);
-    Expect(26);
+    Expect(29);
+    Expect(27);
     SimpleType(s);
     IF (s # SymTab.InvalidType)
      & (SymTab.ClassOf(s) #
@@ -1863,7 +1936,7 @@ PROCEDURE SetType (VAR t: SymTab.TypeIndex);
 
 PROCEDURE RecordType (VAR t: SymTab.TypeIndex);
   BEGIN
-    Expect(27);
+    Expect(28);
     t := SymTab.NewRecord();;
     FieldSeq(t);
     Expect(12);
@@ -1877,9 +1950,9 @@ PROCEDURE ArrayType (VAR t: SymTab.TypeIndex);
     loA, hiA: INTEGER;
     isOpenA: BOOLEAN;
   BEGIN
-    Expect(25);
-    IF (sym = 1) OR (sym = 19) OR (sym = 22) OR (sym = 26) THEN
-      IF (sym = 1) OR (sym = 19) OR (sym = 22) THEN
+    Expect(26);
+    IF (sym = 1) OR (sym = 19) OR (sym = 23) OR (sym = 27) THEN
+      IF (sym = 1) OR (sym = 19) OR (sym = 23) THEN
         SimpleType(s);
         IF (s # SymTab.InvalidType)
         & (SymTab.ClassOf(s) #
@@ -1910,7 +1983,7 @@ PROCEDURE ArrayType (VAR t: SymTab.TypeIndex);
         nc := 0; isOpenA := TRUE;;
       END;
     END;
-    Expect(26);
+    Expect(27);
     Type(e);
     IF isOpenA THEN
     t := SymTab.NewOpen(e)
@@ -1944,7 +2017,7 @@ PROCEDURE SimpleType (VAR t: SymTab.TypeIndex);
   BEGIN
     IF (sym = 1) THEN
       QualIdent(t);
-      IF (sym = 22) THEN
+      IF (sym = 23) THEN
         Get;
         MGen.NoEmitEnter; lok := FALSE; hik := FALSE;
         loI := 0; hiI := -1;;
@@ -1957,7 +2030,7 @@ PROCEDURE SimpleType (VAR t: SymTab.TypeIndex);
         & (SymTab.ClassOf(t1) #
            SymTab.ClEnum) THEN
         SemError(224) END;;
-        Expect(23);
+        Expect(24);
         ConstExpr(t2, lx2);
         IF (t2 # SymTab.InvalidType)
         & (SymTab.ClassOf(t2) #
@@ -1967,7 +2040,7 @@ PROCEDURE SimpleType (VAR t: SymTab.TypeIndex);
         & (SymTab.ClassOf(t2) #
            SymTab.ClEnum) THEN
         SemError(224) END;;
-        Expect(24);
+        Expect(25);
         IF (t1 # SymTab.InvalidType)
          & (t2 # SymTab.InvalidType) THEN
            IF MGen.IsLit(lx1) THEN
@@ -2000,7 +2073,7 @@ PROCEDURE SimpleType (VAR t: SymTab.TypeIndex);
         END;
         MGen.NoEmitExit;;
       END;
-    ELSIF (sym = 22) THEN
+    ELSIF (sym = 23) THEN
       Get;
       MGen.NoEmitEnter; lok := FALSE;
       hik := FALSE; loI := 0; hiI := -1;;
@@ -2013,7 +2086,7 @@ PROCEDURE SimpleType (VAR t: SymTab.TypeIndex);
        & (SymTab.ClassOf(t1) #
           SymTab.ClEnum) THEN
        SemError(224) END;;
-      Expect(23);
+      Expect(24);
       ConstExpr(t2, lx2);
       IF (t2 # SymTab.InvalidType)
        & (SymTab.ClassOf(t2) #
@@ -2023,7 +2096,7 @@ PROCEDURE SimpleType (VAR t: SymTab.TypeIndex);
        & (SymTab.ClassOf(t2) #
           SymTab.ClEnum) THEN
        SemError(224) END;;
-      Expect(24);
+      Expect(25);
       IF (t1 # SymTab.InvalidType)
       & (t2 # SymTab.InvalidType) THEN
         IF MGen.IsLit(lx1) THEN
@@ -2059,7 +2132,7 @@ PROCEDURE SimpleType (VAR t: SymTab.TypeIndex);
       MGen.NoEmitExit;;
     ELSIF (sym = 19) THEN
       Enum(t);
-    ELSE SynError(81);
+    ELSE SynError(82);
     END;
   END SimpleType;
 
@@ -2157,17 +2230,17 @@ PROCEDURE VarIdents;
 
 PROCEDURE Type (VAR t: SymTab.TypeIndex);
   BEGIN
-    IF (sym = 1) OR (sym = 19) OR (sym = 22) THEN
+    IF (sym = 1) OR (sym = 19) OR (sym = 23) THEN
       SimpleType(t);
-    ELSIF (sym = 25) THEN
+    ELSIF (sym = 26) THEN
       ArrayType(t);
-    ELSIF (sym = 27) THEN
-      RecordType(t);
     ELSIF (sym = 28) THEN
-      SetType(t);
+      RecordType(t);
     ELSIF (sym = 29) THEN
+      SetType(t);
+    ELSIF (sym = 30) THEN
       PointerType(t);
-    ELSE SynError(82);
+    ELSE SynError(83);
     END;
   END Type;
 
@@ -2261,6 +2334,56 @@ PROCEDURE ConstExpr (VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr);
     Expr(t, lx, vD, vnD);
   END ConstExpr;
 
+PROCEDURE ModuleDecl;
+  VAR n, m, e: SymTab.Name;
+    noMod, enterOk: BOOLEAN;
+  BEGIN
+    Expect(5);
+    noMod := SymTab.InProc()
+           OR SymTab.InModule();
+    enterOk := FALSE;;
+    GetIdent(n);
+    IF noMod THEN
+    SemError(230)
+    ELSIF ~SymTab.EnterModule(n) THEN
+    SemError(200)
+    ELSE
+    enterOk := TRUE
+    END;;
+    IF (sym = 22) THEN
+      Get;
+      GetIdent(e);
+      IF ~noMod & enterOk THEN
+      IF ~SymTab.ModuleAddExp(e) THEN
+        SemError(200)
+      END
+      END;;
+      WHILE (sym = 10) DO
+        Get;
+        GetIdent(e);
+        IF ~noMod & enterOk THEN
+        IF ~SymTab.ModuleAddExp(e) THEN
+          SemError(200)
+        END
+        END;;
+      END;
+    END;
+    Expect(6);
+    WHILE (sym = 5) OR (sym = 13) OR (sym = 14) OR (sym = 15) OR (sym = 18) DO
+      Declaration;
+    END;
+    Expect(12);
+    GetIdent(m);
+    IF ~SymTab.Equal(n, m) THEN
+    SemError(202)
+    END;
+    IF ~noMod & enterOk THEN
+    IF ~SymTab.ExitModule() THEN
+      SemError(201)
+    END
+    END;;
+  END ModuleDecl;
+
 PROCEDURE ProcedureDecl;
   VAR n, m: SymTab.Name;
     rt: SymTab.TypeIndex;
@@ -2311,7 +2434,7 @@ PROCEDURE ProcedureDecl;
       SymTab.SetForward;
         SymTab.CloseProc;
         MGen.DefLabel(endL);;
-    ELSE SynError(83);
+    ELSE SynError(84);
     END;
   END ProcedureDecl;
 
@@ -2425,7 +2548,10 @@ PROCEDURE Declaration;
     ELSIF (sym = 18) THEN
       ProcedureDecl;
       Expect(6);
-    ELSE SynError(84);
+    ELSIF (sym = 5) THEN
+      ModuleDecl;
+      Expect(6);
+    ELSE SynError(85);
     END;
   END Declaration;
 
@@ -2447,7 +2573,7 @@ PROCEDURE Block (isProc: BOOLEAN);
   VAR began: BOOLEAN;
   BEGIN
     began := FALSE;;
-    WHILE (sym = 13) OR (sym = 14) OR (sym = 15) OR (sym = 18) DO
+    WHILE (sym = 5) OR (sym = 13) OR (sym = 14) OR (sym = 15) OR (sym = 18) DO
       Declaration;
     END;
     IF (sym = 11) THEN
@@ -2491,7 +2617,7 @@ PROCEDURE Import;
       Get;
       ImportList;
       Expect(6);
-    ELSE SynError(85);
+    ELSE SynError(86);
     END;
   END Import;
 
@@ -2543,30 +2669,30 @@ BEGIN
   symSet[ 0, 4] := BITSET{};
   symSet[ 1, 0] := BITSET{1, 2, 3, 4};
   symSet[ 1, 1] := BITSET{3};
-  symSet[ 1, 2] := BITSET{14};
-  symSet[ 1, 3] := BITSET{13};
-  symSet[ 1, 4] := BITSET{5, 6, 7, 8};
+  symSet[ 1, 2] := BITSET{15};
+  symSet[ 1, 3] := BITSET{14};
+  symSet[ 1, 4] := BITSET{6, 7, 8, 9};
   symSet[ 2, 0] := BITSET{};
   symSet[ 2, 1] := BITSET{};
   symSet[ 2, 2] := BITSET{};
-  symSet[ 2, 3] := BITSET{15};
-  symSet[ 2, 4] := BITSET{0, 1, 2, 3, 4};
+  symSet[ 2, 3] := BITSET{};
+  symSet[ 2, 4] := BITSET{0, 1, 2, 3, 4, 5};
   symSet[ 3, 0] := BITSET{6, 12};
   symSet[ 3, 1] := BITSET{};
-  symSet[ 3, 2] := BITSET{3, 4, 6, 10};
+  symSet[ 3, 2] := BITSET{4, 5, 7, 11};
   symSet[ 3, 3] := BITSET{};
   symSet[ 3, 4] := BITSET{};
   symSet[ 4, 0] := BITSET{1};
-  symSet[ 4, 1] := BITSET{15};
-  symSet[ 4, 2] := BITSET{1, 5, 7, 9, 11, 12, 15};
-  symSet[ 4, 3] := BITSET{0, 1, 2, 3, 4};
+  symSet[ 4, 1] := BITSET{};
+  symSet[ 4, 2] := BITSET{0, 2, 6, 8, 10, 12, 13};
+  symSet[ 4, 3] := BITSET{0, 1, 2, 3, 4, 5};
   symSet[ 4, 4] := BITSET{};
   symSet[ 5, 0] := BITSET{};
   symSet[ 5, 1] := BITSET{0};
   symSet[ 5, 2] := BITSET{};
-  symSet[ 5, 3] := BITSET{6, 7, 8, 9, 10, 11, 12};
+  symSet[ 5, 3] := BITSET{7, 8, 9, 10, 11, 12, 13};
   symSet[ 5, 4] := BITSET{};
-  symSet[ 6, 0] := BITSET{11, 12, 13, 14, 15};
+  symSet[ 6, 0] := BITSET{5, 11, 12, 13, 14, 15};
   symSet[ 6, 1] := BITSET{2};
   symSet[ 6, 2] := BITSET{};
   symSet[ 6, 3] := BITSET{};

BIN
M2cP.o


+ 54 - 53
M2cS.mod

@@ -5,7 +5,7 @@ IMPLEMENTATION MODULE M2cS;
 IMPORT FileIO, Storage;
 
 CONST
-  noSYMB  = 74; (*error token code*)
+  noSYMB  = 75; (*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;
@@ -102,66 +102,67 @@ PROCEDURE Get (VAR sym: CARDINAL);
   PROCEDURE CheckLiteral;
     BEGIN
       CASE CurrentCh(bp0) OF
-        "A": IF Equal("AND") THEN sym := 67; 
-             ELSIF Equal("ARRAY") THEN sym := 25; 
+        "A": IF Equal("AND") THEN sym := 68; 
+             ELSIF Equal("ARRAY") THEN sym := 26; 
              END
       | "B": IF Equal("BEGIN") THEN sym := 11; 
-             ELSIF Equal("BY") THEN sym := 45; 
+             ELSIF Equal("BY") THEN sym := 46; 
              END
-      | "C": IF Equal("CASE") THEN sym := 37; 
+      | "C": IF Equal("CASE") THEN sym := 38; 
              ELSIF Equal("CONST") THEN sym := 13; 
              END
-      | "D": IF Equal("DISPOSE") THEN sym := 50; 
-             ELSIF Equal("DIV") THEN sym := 65; 
-             ELSIF Equal("DO") THEN sym := 40; 
+      | "D": IF Equal("DISPOSE") THEN sym := 51; 
+             ELSIF Equal("DIV") THEN sym := 66; 
+             ELSIF Equal("DO") THEN sym := 41; 
              END
-      | "E": IF Equal("ELSE") THEN sym := 36; 
-             ELSIF Equal("ELSIF") THEN sym := 35; 
+      | "E": IF Equal("ELSE") THEN sym := 37; 
+             ELSIF Equal("ELSIF") THEN sym := 36; 
              ELSIF Equal("END") THEN sym := 12; 
-             ELSIF Equal("EXIT") THEN sym := 31; 
+             ELSIF Equal("EXIT") THEN sym := 32; 
+             ELSIF Equal("EXPORT") THEN sym := 22; 
              END
-      | "F": IF Equal("FOR") THEN sym := 44; 
+      | "F": IF Equal("FOR") THEN sym := 45; 
              ELSIF Equal("FORWARD") THEN sym := 21; 
              ELSIF Equal("FROM") THEN sym := 8; 
              END
-      | "H": IF Equal("HIGH") THEN sym := 69; 
+      | "H": IF Equal("HIGH") THEN sym := 70; 
              END
-      | "I": IF Equal("IF") THEN sym := 33; 
+      | "I": IF Equal("IF") THEN sym := 34; 
              ELSIF Equal("IMPORT") THEN sym := 9; 
-             ELSIF Equal("IN") THEN sym := 60; 
+             ELSIF Equal("IN") THEN sym := 61; 
              END
-      | "L": IF Equal("LOOP") THEN sym := 43; 
+      | "L": IF Equal("LOOP") THEN sym := 44; 
              END
-      | "M": IF Equal("MOD") THEN sym := 66; 
+      | "M": IF Equal("MOD") THEN sym := 67; 
              ELSIF Equal("MODULE") THEN sym := 5; 
              END
-      | "N": IF Equal("NEW") THEN sym := 49; 
-             ELSIF Equal("NOT") THEN sym := 70; 
+      | "N": IF Equal("NEW") THEN sym := 50; 
+             ELSIF Equal("NOT") THEN sym := 71; 
              END
-      | "O": IF Equal("OF") THEN sym := 26; 
-             ELSIF Equal("OR") THEN sym := 62; 
+      | "O": IF Equal("OF") THEN sym := 27; 
+             ELSIF Equal("OR") THEN sym := 63; 
              END
-      | "P": IF Equal("POINTER") THEN sym := 29; 
+      | "P": IF Equal("POINTER") THEN sym := 30; 
              ELSIF Equal("PROCEDURE") THEN sym := 18; 
              END
-      | "R": IF Equal("RECORD") THEN sym := 27; 
-             ELSIF Equal("REPEAT") THEN sym := 41; 
-             ELSIF Equal("RETURN") THEN sym := 48; 
+      | "R": IF Equal("RECORD") THEN sym := 28; 
+             ELSIF Equal("REPEAT") THEN sym := 42; 
+             ELSIF Equal("RETURN") THEN sym := 49; 
              END
-      | "S": IF Equal("SET") THEN sym := 28; 
+      | "S": IF Equal("SET") THEN sym := 29; 
              END
-      | "T": IF Equal("THEN") THEN sym := 34; 
-             ELSIF Equal("TO") THEN sym := 30; 
+      | "T": IF Equal("THEN") THEN sym := 35; 
+             ELSIF Equal("TO") THEN sym := 31; 
              ELSIF Equal("TYPE") THEN sym := 14; 
              END
-      | "U": IF Equal("UNTIL") THEN sym := 42; 
+      | "U": IF Equal("UNTIL") THEN sym := 43; 
              END
       | "V": IF Equal("VAR") THEN sym := 15; 
              END
-      | "W": IF Equal("WHILE") THEN sym := 39; 
-             ELSIF Equal("WITH") THEN sym := 47; 
-             ELSIF Equal("WriteInt") THEN sym := 51; 
-             ELSIF Equal("WriteString") THEN sym := 52; 
+      | "W": IF Equal("WHILE") THEN sym := 40; 
+             ELSIF Equal("WITH") THEN sym := 48; 
+             ELSIF Equal("WriteInt") THEN sym := 52; 
+             ELSIF Equal("WriteString") THEN sym := 53; 
              END
       ELSE
       END
@@ -241,31 +242,31 @@ PROCEDURE Get (VAR sym: CARDINAL);
             END;
       | 19: sym := 19; RETURN
       | 20: sym := 20; RETURN
-      | 21: sym := 22; RETURN
-      | 22: sym := 23; RETURN
-      | 23: sym := 24; RETURN
-      | 24: sym := 32; RETURN
-      | 25: sym := 38; RETURN
-      | 26: sym := 46; RETURN
-      | 27: sym := 53; RETURN
-      | 28: sym := 54; RETURN
+      | 21: sym := 23; RETURN
+      | 22: sym := 24; RETURN
+      | 23: sym := 25; RETURN
+      | 24: sym := 33; RETURN
+      | 25: sym := 39; RETURN
+      | 26: sym := 47; RETURN
+      | 27: sym := 54; RETURN
+      | 28: sym := 55; RETURN
       | 29: IF (ch = ">") THEN state := 30; 
             ELSIF (ch = "=") THEN state := 31; 
-            ELSE sym := 56; RETURN
+            ELSE sym := 57; RETURN
             END;
-      | 30: sym := 55; RETURN
-      | 31: sym := 57; RETURN
+      | 30: sym := 56; RETURN
+      | 31: sym := 58; RETURN
       | 32: IF (ch = "=") THEN state := 33; 
-            ELSE sym := 58; RETURN
+            ELSE sym := 59; RETURN
             END;
-      | 33: sym := 59; RETURN
-      | 34: sym := 61; RETURN
-      | 35: sym := 63; RETURN
-      | 36: sym := 64; RETURN
-      | 37: sym := 68; RETURN
-      | 38: sym := 71; RETURN
-      | 39: sym := 72; RETURN
-      | 40: sym := 73; RETURN
+      | 33: sym := 60; RETURN
+      | 34: sym := 62; RETURN
+      | 35: sym := 64; RETURN
+      | 36: sym := 65; RETURN
+      | 37: sym := 69; RETURN
+      | 38: sym := 72; RETURN
+      | 39: sym := 73; RETURN
+      | 40: sym := 74; RETURN
       | 41: sym := 0; ch := 0C; DEC(bp); RETURN
       ELSE sym := noSYMB; RETURN (*NextCh already done*)
       END

BIN
M2cS.o


BIN
MArr.MC4


BIN
MBadDup.MC4


BIN
MBadEnd.MC4


BIN
MBadExp.MC4


BIN
MBadFunc.MC4


BIN
MBadGhost.MC4


BIN
MBadNest.MC4


BIN
MBadParam.MC4


BIN
MBadPriv.MC4


BIN
MConst.MC4


+ 11 - 0
MGen.def

@@ -281,6 +281,17 @@ PROCEDURE ActValue (t: INTEGER; v: BOOLEAN;
    formals need assignment compatibility (INTEGER widens to REAL).
    Always consumes the value (temp store). 1 means error 233. *)
 
+PROCEDURE ActIsVarNext (): BOOLEAN;
+(* TRUE if the current formal (actSt.n) is a VAR parameter
+   (known callee, in range). Used to keep addresses (not values)
+   for VAR a[i] actuals. *)
+
+PROCEDURE NoteSfx (b: BOOLEAN);
+(* Records tails-present for the current actual (top frame). *)
+
+PROCEDURE NoteIdx (b: BOOLEAN);
+(* Records index-only tails for the current actual (top frame). *)
+
 PROCEDURE ActEnd (pn: ARRAY OF CHAR; sfx, inExpr: BOOLEAN): INTEGER;
 (* Verifies arity and callee kind, reloads actuals reversed and
    emits the depth-correct call (0 = ok, 1 = error 233). *)

+ 74 - 7
MGen.mod

@@ -68,6 +68,8 @@ TYPE
     n : CARDINAL;
     tmps : ARRAY [0 .. MaxActN] OF INTEGER;
     lens : ARRAY [0 .. MaxActN] OF INTEGER;
+    sfxs : ARRAY [0 .. MaxActN] OF BOOLEAN;
+    idxs : ARRAY [0 .. MaxActN] OF BOOLEAN;
     known : BOOLEAN;
     nf : CARDINAL;
     pn : ARRAY [0 .. 63] OF CHAR;
@@ -194,6 +196,27 @@ PROCEDURE FindVar (name: ARRAY OF CHAR): INTEGER;
     RETURN -1
   END FindVar;
 
+PROCEDURE QualGlob (name: ARRAY OF CHAR; VAR q: ARRAY OF CHAR);
+  VAR m: SymTab.Name;
+    i, k: CARDINAL;
+  BEGIN
+    IF SymTab.InModule() & (SymTab.SymLev(name) > 0) THEN
+      SymTab.CurModName(m);
+      i := 0; k := 0;
+      WHILE (k < HIGH(q)) & (m[i] # 0C) DO
+        q[k] := m[i]; INC(k); INC(i)
+      END;
+      IF k <= HIGH(q) THEN q[k] := "."; INC(k) END;
+      i := 0;
+      WHILE (k < HIGH(q)) & (name[i] # 0C) DO
+        q[k] := name[i]; INC(k); INC(i)
+      END;
+      IF k <= HIGH(q) THEN q[k] := 0C END
+    ELSE
+      StrCpy(q, name)
+    END
+  END QualGlob;
+
 PROCEDURE AssignSlots (name: ARRAY OF CHAR; n: CARDINAL): INTEGER;
   VAR base : CARDINAL;
   BEGIN
@@ -250,8 +273,10 @@ PROCEDURE DeclVar (name: ARRAY OF CHAR);
 
 PROCEDURE DeclVarSized (name: ARRAY OF CHAR; slots: CARDINAL);
   VAR idx : INTEGER;
+    q: ARRAY [0 .. 63] OF CHAR;
   BEGIN
-    idx := AssignSlots(name, slots);
+    QualGlob(name, q);
+    idx := AssignSlots(q, slots);
     IF idx < 0 THEN RETURN END
   END DeclVarSized;
 
@@ -272,8 +297,10 @@ PROCEDURE DeclConst (name: ARRAY OF CHAR; lit: LitStr; t: INTEGER);
     v : INTEGER;
     c : CARDINAL;
     b : LONGCARD;
+    q: ARRAY [0 .. 63] OF CHAR;
   BEGIN
-    idx := AssignSlot(name);
+    QualGlob(name, q);
+    idx := AssignSlot(q);
     IF idx < 0 THEN RETURN END;
     cls := SymTab.ClassOf(t);
     IF ~IsLit(lit) OR (cls = SymTab.ClStr) THEN
@@ -294,8 +321,10 @@ PROCEDURE DeclConst (name: ARRAY OF CHAR; lit: LitStr; t: INTEGER);
 
 PROCEDURE DeclConstInt (name: ARRAY OF CHAR; v: INTEGER);
   VAR idx : INTEGER;
+    q: ARRAY [0 .. 63] OF CHAR;
   BEGIN
-    idx := AssignSlot(name);
+    QualGlob(name, q);
+    idx := AssignSlot(q);
     IF idx < 0 THEN RETURN END;
     BufInit(idx, 0, v, 0H)
   END DeclConstInt;
@@ -323,8 +352,10 @@ PROCEDURE BeginBody;
 
 PROCEDURE LoadVar (name: ARRAY OF CHAR);
   VAR idx : INTEGER;
+    q: ARRAY [0 .. 63] OF CHAR;
   BEGIN
-    idx := FindVar(name);
+    QualGlob(name, q);
+    idx := FindVar(q);
     IF idx < 0 THEN EmitOp(OPimm0)
     ELSE EmitOpB(OPloadGlb, VAL(CARDINAL, idx))
     END
@@ -332,8 +363,10 @@ PROCEDURE LoadVar (name: ARRAY OF CHAR);
 
 PROCEDURE StoreVar (name: ARRAY OF CHAR);
   VAR idx : INTEGER;
+    q: ARRAY [0 .. 63] OF CHAR;
   BEGIN
-    idx := FindVar(name);
+    QualGlob(name, q);
+    idx := FindVar(q);
     IF idx < 0 THEN EmitOp(OPext); EmitOp(SUBdrop)
     ELSE EmitOpB(OPstoreGlb, VAL(CARDINAL, idx))
     END
@@ -415,8 +448,10 @@ PROCEDURE LocalAddr (sl: INTEGER);
 
 PROCEDURE GlobalAddr (name: ARRAY OF CHAR);
   VAR idx : INTEGER;
+    q: ARRAY [0 .. 63] OF CHAR;
   BEGIN
-    idx := FindVar(name);
+    QualGlob(name, q);
+    idx := FindVar(q);
     IF idx < 0 THEN EmitOp(OPimm0)
     ELSE EmitOpB(OPglobalAddr, VAL(CARDINAL, idx))
     END
@@ -579,6 +614,35 @@ PROCEDURE ActFrameIdx (): CARDINAL;
     RETURN actTop - 1
   END ActFrameIdx;
 
+PROCEDURE ActIsVarNext (): BOOLEAN;
+  VAR fr, i: CARDINAL;
+  BEGIN
+    IF actTop = 0 THEN RETURN FALSE END;
+    fr := ActFrameIdx();
+    IF ~actSt[fr].known THEN RETURN FALSE END;
+    i := actSt[fr].n;
+    IF i >= actSt[fr].nf THEN RETURN FALSE END;
+    RETURN SymTab.ParamIsVar(actSt[fr].pn, i)
+  END ActIsVarNext;
+
+PROCEDURE NoteSfx (b: BOOLEAN);
+  VAR fr, i: CARDINAL;
+  BEGIN
+    IF actTop = 0 THEN RETURN END;
+    fr := ActFrameIdx();
+    i := actSt[fr].n;
+    IF i <= MaxActN THEN actSt[fr].sfxs[i] := b END
+  END NoteSfx;
+
+PROCEDURE NoteIdx (b: BOOLEAN);
+  VAR fr, i: CARDINAL;
+  BEGIN
+    IF actTop = 0 THEN RETURN END;
+    fr := ActFrameIdx();
+    i := actSt[fr].n;
+    IF i <= MaxActN THEN actSt[fr].idxs[i] := b END
+  END NoteIdx;
+
 PROCEDURE ActBegin (pn: ARRAY OF CHAR);
   VAR fr : CARDINAL;
     k : CARDINAL;
@@ -591,7 +655,10 @@ PROCEDURE ActBegin (pn: ARRAY OF CHAR);
     actSt[fr].n := 0;
     k := 0;
     WHILE k <= MaxActN DO
-      actSt[fr].lens[k] := -1; INC(k)
+      actSt[fr].lens[k] := -1;
+      actSt[fr].sfxs[k] := FALSE;
+      actSt[fr].idxs[k] := TRUE;
+      INC(k)
     END;
     actSt[fr].known := SymTab.Lookup(pn)
       & (SymTab.SymKind(pn) = SymTab.KindProc);

BIN
MGen.o


BIN
MMod.MC4


BIN
MMulti.MC4


BIN
MOuter.MC4


+ 40 - 0
SymTab.def

@@ -108,6 +108,46 @@ PROCEDURE PushScope;
 PROCEDURE PopScope;
 (* WITH statement support: PushRecord pushes a record's fields. *)
 
+PROCEDURE SymLev (name: ARRAY OF CHAR): INTEGER;
+(* Scope level at declaration (-1 if absent). *)
+
+(* ---------------- local modules (single-file, step 6) *)
+(* Local MODULEs live at program level (no nesting, no bodies).
+   EXPORT names are resolved at END (before PopScope) into an export
+   table keyed by (module, name); MGen stores module vars qualified
+   ("M.x") so FindVar has no collisions. *)
+
+PROCEDURE EnterModule (name: ARRAY OF CHAR): BOOLEAN;
+(* Enters KindModule + pushes body scope + module context.
+   FALSE on duplicate. *)
+
+PROCEDURE ModuleAddExp (name: ARRAY OF CHAR): BOOLEAN;
+(* Records an export name for the current module (checked for
+   duplicates in the export list). FALSE if not in a module. *)
+
+PROCEDURE ExitModule(): BOOLEAN;
+(* Resolves exports against the body scope, pops scope + context.
+   TRUE if every EXPORT name was declared (FALSE = ghost export). *)
+
+PROCEDURE InModule (): BOOLEAN;
+(* TRUE inside a local MODULE body (including its procedures). *)
+
+PROCEDURE CurModName (VAR m: Name);
+(* Top module name, empty if none. *)
+
+PROCEDURE ExpKind (mod, exp: ARRAY OF CHAR): INTEGER;
+(* Exported kind, -1 if absent. *)
+
+PROCEDURE ExpType (mod, exp: ARRAY OF CHAR): TypeIndex;
+(* Exported type (InvalidType if absent / not a type-ish export). *)
+
+PROCEDURE ExpProc (mod, exp: ARRAY OF CHAR): INTEGER;
+(* Exported proc number, -1 if absent / not a procedure. *)
+
+PROCEDURE ExpQual (mod, exp: ARRAY OF CHAR; VAR qual: Name);
+(* Qualified MGen name ("M.x"), empty if absent / not a variable
+   or constant. *)
+
 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. *)

+ 148 - 0
SymTab.mod

@@ -81,6 +81,16 @@ VAR
   locCnt : ARRAY [0 .. MaxPDepth] OF CARDINAL;
   parCnt : ARRAY [0 .. MaxPDepth] OF CARDINAL;
   retSt : ARRAY [0 .. MaxPDepth] OF TypeIndex;
+  modNames : ARRAY [0 .. 7] OF Name;
+  modTop : CARDINAL;
+  modExps : ARRAY [0 .. 7] OF ARRAY [0 .. 31] OF Name;
+  modNExps : ARRAY [0 .. 7] OF CARDINAL;
+  expMod : ARRAY [0 .. 127] OF Name;
+  expName : ARRAY [0 .. 127] OF Name;
+  expKindA : ARRAY [0 .. 127] OF INTEGER;
+  expTypeA : ARRAY [0 .. 127] OF TypeIndex;
+  expProcA : ARRAY [0 .. 127] OF INTEGER;
+  nExps : CARDINAL;
 
 (* ---------------- strings ---------------- *)
 
@@ -366,6 +376,143 @@ PROCEDURE PopScope;
     IF curLev > 0 THEN DEC(curLev) END
   END PopScope;
 
+PROCEDURE SymLev (name: ARRAY OF CHAR): INTEGER;
+  VAR idx : INTEGER;
+  BEGIN
+    idx := Find(name);
+    IF idx = -1 THEN RETURN -1 END;
+    RETURN VAL(INTEGER, syms[idx].lev)
+  END SymLev;
+
+(* ---------------- local modules ---------------- *)
+
+PROCEDURE EnterModule (name: ARRAY OF CHAR): BOOLEAN;
+  BEGIN
+    IF DupInLevel(name) THEN RETURN FALSE END;
+    IF RawEnter(name, KindModule) = -1 THEN RETURN FALSE END;
+    IF modTop > 7 THEN RETURN TRUE END;
+    Assign(modNames[modTop], name);
+    modNExps[modTop] := 0;
+    INC(modTop);
+    PushScope;
+    RETURN TRUE
+  END EnterModule;
+
+PROCEDURE ModuleAddExp (name: ARRAY OF CHAR): BOOLEAN;
+  VAR i : CARDINAL;
+  BEGIN
+    IF modTop = 0 THEN RETURN FALSE END;
+    i := 0;
+    WHILE i < modNExps[modTop - 1] DO
+      IF Equal(modExps[modTop - 1][i], name) THEN RETURN FALSE END;
+      INC(i)
+    END;
+    IF modNExps[modTop - 1] > 31 THEN RETURN FALSE END;
+    Assign(modExps[modTop - 1][modNExps[modTop - 1]], name);
+    INC(modNExps[modTop - 1]);
+    RETURN TRUE
+  END ModuleAddExp;
+
+PROCEDURE ExitModule(): BOOLEAN;
+  VAR mi, k : CARDINAL;
+    idx : INTEGER;
+    en : Name;
+    ok : BOOLEAN;
+  BEGIN
+    IF modTop = 0 THEN RETURN TRUE END;
+    mi := modTop - 1;
+    ok := TRUE;
+    k := 0;
+    WHILE k < modNExps[mi] DO
+      Assign(en, modExps[mi][k]);
+      idx := Find(en);
+      IF idx = -1 THEN ok := FALSE
+      ELSIF nExps <= 127 THEN
+        Assign(expMod[nExps], modNames[mi]);
+        Assign(expName[nExps], en);
+        expKindA[nExps] := syms[idx].kind;
+        expTypeA[nExps] := syms[idx].typ;
+        IF syms[idx].kind = KindProc THEN
+          expProcA[nExps] := syms[idx].pnum
+        ELSE
+          expProcA[nExps] := -1
+        END;
+        INC(nExps)
+      END;
+      INC(k)
+    END;
+    PopScope;
+    DEC(modTop);
+    RETURN ok
+  END ExitModule;
+
+PROCEDURE InModule (): BOOLEAN;
+  BEGIN RETURN modTop > 0 END InModule;
+
+PROCEDURE CurModName (VAR m: Name);
+  BEGIN
+    IF modTop = 0 THEN m[0] := 0C
+    ELSE Assign(m, modNames[modTop - 1])
+    END
+  END CurModName;
+
+PROCEDURE ExpFind (mod, exp: ARRAY OF CHAR): INTEGER;
+  VAR i : CARDINAL;
+  BEGIN
+    i := 0;
+    WHILE i < nExps DO
+      IF Equal(expMod[i], mod) & Equal(expName[i], exp) THEN
+        RETURN VAL(INTEGER, i)
+      END;
+      INC(i)
+    END;
+    RETURN -1
+  END ExpFind;
+
+PROCEDURE ExpKind (mod, exp: ARRAY OF CHAR): INTEGER;
+  VAR i : INTEGER;
+  BEGIN
+    i := ExpFind(mod, exp);
+    IF i = -1 THEN RETURN -1 END;
+    RETURN expKindA[i]
+  END ExpKind;
+
+PROCEDURE ExpType (mod, exp: ARRAY OF CHAR): TypeIndex;
+  VAR i : INTEGER;
+  BEGIN
+    i := ExpFind(mod, exp);
+    IF i = -1 THEN RETURN InvalidType END;
+    RETURN expTypeA[i]
+  END ExpType;
+
+PROCEDURE ExpProc (mod, exp: ARRAY OF CHAR): INTEGER;
+  VAR i : INTEGER;
+  BEGIN
+    i := ExpFind(mod, exp);
+    IF i = -1 THEN RETURN -1 END;
+    RETURN expProcA[i]
+  END ExpProc;
+
+PROCEDURE ExpQual (mod, exp: ARRAY OF CHAR; VAR qual: Name);
+  VAR i, j, k : CARDINAL;
+  BEGIN
+    i := ExpFind(mod, exp);
+    IF i = -1 THEN qual[0] := 0C; RETURN END;
+    IF (expKindA[i] # KindVar) & (expKindA[i] # KindConst) THEN
+      qual[0] := 0C; RETURN
+    END;
+    k := 0; j := 0;
+    WHILE (k < HIGH(qual)) & (mod[j] # 0C) DO
+      qual[k] := mod[j]; INC(k); INC(j)
+    END;
+    IF k <= HIGH(qual) THEN qual[k] := "."; INC(k) END;
+    j := 0;
+    WHILE (k < HIGH(qual)) & (exp[j] # 0C) DO
+      qual[k] := exp[j]; INC(k); INC(j)
+    END;
+    IF k <= HIGH(qual) THEN qual[k] := 0C END
+  END ExpQual;
+
 (* ---------------- type descriptors ---------------- *)
 
 PROCEDURE NewDesc (form: INTEGER; ref: TypeIndex): TypeIndex;
@@ -1131,6 +1278,7 @@ PROCEDURE Init;
     nTypes := 0; nFields := 0;
     nProcs := 0; nParams := 0;
     pdep := 0; curProc := 0;
+    modTop := 0; nExps := 0;
     procSt[0] := 0; locCnt[0] := 0; parCnt[0] := 0;
     retSt[0] := InvalidType;
     dInt := NewDesc(FInt, InvalidType);

BIN
SymTab.o


+ 65 - 0
docs/summary_step6.md

@@ -0,0 +1,65 @@
+# Step 6 — Local modules hardened (uncommitted)
+
+112/112 tests green (99 regressions + 5 run + 8 rejection), mc64 boot + example green.
+
+## Goal
+
+Harden the step-6 WIP (single-file local `MODULE`s, no nesting, no bodies):
+exported `VAR`s, `CONST`s and parameterless proper procedures, used as
+`M.x` / `M.P()`. Fix the bugs found by probing, lock behavior in with
+rejection tests, keep every old suite green.
+
+## What was built
+
+- `SymTab`: `ExpQual` now qualifies `KindConst` as well as `KindVar`
+  (`"M.x"`); `ExitModule` became a `BOOLEAN` function — `TRUE` iff every
+  `EXPORT` name was declared (ghost exports report `FALSE`).
+- `M2c.atg`: `ModuleDecl` gained an `enterOk` flag (failed `EnterModule`
+  skips export recording and `ExitModule`, killing the duplicate-module
+  cascade); `END` reports `SemError(201)` on ghost exports; header comment
+  documents local-module support and limits.
+- `run_tests.sh`: new `Step-6` sections (5 run + 8 rejection).
+
+## Tests — 112/112 (99 + 5 + 8)
+
+5 run: `m_mod` 12 (exported var + `Inc()` twice), `m_multi` 7 (two
+modules), `m_arr` 42 (exported array + `M.arr[2]`), `m_outer` 11 (module
+proc touches outer global), `m_const` 7 (exported `CONST`).
+8 rejections, each exactly one error: `m_bad_priv` 201 (private `M.secret`),
+`m_bad_nest` 230 (module in procedure), `m_bad_dup` 200 (duplicate module),
+`m_bad_exp` 200 (duplicate export), `m_bad_ghost` 201 (`EXPORT ghost`),
+`m_bad_param` 233 (`M.Add(5)`), `m_bad_func` 233 (`M.Get()` in expression),
+`m_bad_end` 202 (`END N` mismatch).
+
+## Bugs found and fixed
+
+1. Exported `CONST` read back 0: `ExpQual` returned an empty name for
+   non-`Var` kinds, so `GlobalAddr("")` hit a temp slot. Qualifying
+   `KindConst` fixes the load (`M.C` → 7) with no ATG change (address +
+   `LoadIndir` path is shared with vars).
+2. Ghost `EXPORT` silently accepted: `ExitModule` dropped undeclared names.
+   Now returns `FALSE` and the ATG reports 201 at `END`.
+3. Duplicate module gave 2 errors (200 at name + 200 at its `EXPORT`, since
+   `ModuleAddExp` ran with no module context). `enterOk` guard → 1 error.
+
+## Known limits (each with a rejection test or documented)
+
+Module procedures take no parameters (`M.Add(5)` → 233), module functions
+are statement-only (`M.Get()` in an expression → 233), no type exports
+(`M.T` → 221 + 230 via `QualIdent`), no `DEFINITION`/`IMPLEMENTATION`
+split, no module `BEGIN` bodies, `NoteSfx`/`NoteIdx` VAR-tail helpers still
+unwired (`a[i]`/`p^`/fields as VAR actuals → 233), max 8 modules /
+32 exports per module / 128 exports total.
+
+## Text output (I/O builtins, verified this session)
+
+No new machinery needed for simple output — step-5 builtins cover it:
+`WriteString("...")` / `WriteString(charArrayVar)` emits raw bytes via
+SYSTEM service 1 (no newline); `WriteInt(n)` emits unsigned decimal + CRLF
+via the embedded `EmitPrint` helper; a declared `ExitCode` global is printed
+the same way at program end. Demo verified under `mcint`:
+`WriteString("Hello"); WriteString(" world"); WriteInt(42);`
+→ `Hello world42\r\n`. Limits: no `WriteLn`, single-`CHAR` literals rejected
+(210 — `"A"` lexes as `CHAR`, not a string), `WriteInt` wraps negatives, one
+value per call. A `WriteLn`/`WriteChar` would be a small isolated addition
+(new ATG builtin + `MGen` emitter + tests).

+ 17 - 0
run_tests.sh

@@ -219,5 +219,22 @@ expect_fail r_bad_open.mod "not supported in this phase"
 expect_fail p_bad_dispose.mod "not a POINTER type"
 expect_fail s_bad_op.mod "arithmetic operand must be numeric"
 
+echo "=== Step-6 run tests (local MODULEs) ==="
+expect_run m_mod.mod 12
+expect_run m_multi.mod 7
+expect_run m_arr.mod 42
+expect_run m_outer.mod 11
+expect_run m_const.mod 7
+
+echo "=== Step-6 rejection tests ==="
+expect_fail m_bad_priv.mod "undeclared identifier"
+expect_fail m_bad_nest.mod "not supported in this phase"
+expect_fail m_bad_dup.mod "duplicate identifier"
+expect_fail m_bad_exp.mod "duplicate identifier"
+expect_fail m_bad_ghost.mod "undeclared identifier"
+expect_fail m_bad_param.mod "invalid procedure call"
+expect_fail m_bad_func.mod "invalid procedure call"
+expect_fail m_bad_end.mod "name mismatch"
+
 echo "=== $pass passed, $fail failed ==="
 test "$fail" = 0

+ 15 - 0
tests/m_arr.LST

@@ -0,0 +1,15 @@
+Listing:
+
+    1  MODULE MArr;
+    2  MODULE M EXPORT arr;
+    3  VAR arr : ARRAY [1..3] OF INTEGER;
+    4  END M;
+    5  VAR ExitCode : INTEGER;
+    6  BEGIN
+    7    M.arr[2] := 42;
+    8    ExitCode := M.arr[2]
+    9  END MArr.
+
+    0 errors
+
+

+ 9 - 0
tests/m_arr.mod

@@ -0,0 +1,9 @@
+MODULE MArr;
+MODULE M EXPORT arr;
+VAR arr : ARRAY [1..3] OF INTEGER;
+END M;
+VAR ExitCode : INTEGER;
+BEGIN
+  M.arr[2] := 42;
+  ExitCode := M.arr[2]
+END MArr.

+ 18 - 0
tests/m_bad_dup.LST

@@ -0,0 +1,18 @@
+Listing:
+
+    1  MODULE MBadDup;
+    2  MODULE M EXPORT cnt;
+    3  VAR cnt : INTEGER;
+    4  END M;
+    5  MODULE M EXPORT k;
+*****         ^ duplicate identifier
+    6  VAR k : INTEGER;
+    7  END M;
+    8  VAR ExitCode : INTEGER;
+    9  BEGIN
+   10    ExitCode := 0
+   11  END MBadDup.
+
+    1 error
+
+

+ 11 - 0
tests/m_bad_dup.mod

@@ -0,0 +1,11 @@
+MODULE MBadDup;
+MODULE M EXPORT cnt;
+VAR cnt : INTEGER;
+END M;
+MODULE M EXPORT k;
+VAR k : INTEGER;
+END M;
+VAR ExitCode : INTEGER;
+BEGIN
+  ExitCode := 0
+END MBadDup.

+ 15 - 0
tests/m_bad_end.LST

@@ -0,0 +1,15 @@
+Listing:
+
+    1  MODULE MBadEnd;
+    2  MODULE M EXPORT cnt;
+    3  VAR cnt : INTEGER;
+    4  END N;
+*****      ^ module/procedure name mismatch
+    5  VAR ExitCode : INTEGER;
+    6  BEGIN
+    7    ExitCode := 0
+    8  END MBadEnd.
+
+    1 error
+
+

+ 8 - 0
tests/m_bad_end.mod

@@ -0,0 +1,8 @@
+MODULE MBadEnd;
+MODULE M EXPORT cnt;
+VAR cnt : INTEGER;
+END N;
+VAR ExitCode : INTEGER;
+BEGIN
+  ExitCode := 0
+END MBadEnd.

+ 15 - 0
tests/m_bad_exp.LST

@@ -0,0 +1,15 @@
+Listing:
+
+    1  MODULE MBadExp;
+    2  MODULE M EXPORT cnt, cnt;
+*****                       ^ duplicate identifier
+    3  VAR cnt : INTEGER;
+    4  END M;
+    5  VAR ExitCode : INTEGER;
+    6  BEGIN
+    7    ExitCode := 0
+    8  END MBadExp.
+
+    1 error
+
+

+ 8 - 0
tests/m_bad_exp.mod

@@ -0,0 +1,8 @@
+MODULE MBadExp;
+MODULE M EXPORT cnt, cnt;
+VAR cnt : INTEGER;
+END M;
+VAR ExitCode : INTEGER;
+BEGIN
+  ExitCode := 0
+END MBadExp.

+ 19 - 0
tests/m_bad_func.LST

@@ -0,0 +1,19 @@
+Listing:
+
+    1  MODULE MBadFunc;
+    2  MODULE M EXPORT Get;
+    3  VAR cnt : INTEGER;
+    4  PROCEDURE Get : INTEGER;
+    5  BEGIN
+    6    RETURN 42
+    7  END Get;
+    8  END M;
+    9  VAR ExitCode : INTEGER;
+   10  BEGIN
+   11    ExitCode := M.Get()
+*****                     ^ invalid procedure call
+   12  END MBadFunc.
+
+    1 error
+
+

+ 12 - 0
tests/m_bad_func.mod

@@ -0,0 +1,12 @@
+MODULE MBadFunc;
+MODULE M EXPORT Get;
+VAR cnt : INTEGER;
+PROCEDURE Get : INTEGER;
+BEGIN
+  RETURN 42
+END Get;
+END M;
+VAR ExitCode : INTEGER;
+BEGIN
+  ExitCode := M.Get()
+END MBadFunc.

+ 15 - 0
tests/m_bad_ghost.LST

@@ -0,0 +1,15 @@
+Listing:
+
+    1  MODULE MBadGhost;
+    2  MODULE M EXPORT ghost;
+    3  VAR cnt : INTEGER;
+    4  END M;
+*****      ^ undeclared identifier
+    5  VAR ExitCode : INTEGER;
+    6  BEGIN
+    7    ExitCode := 0
+    8  END MBadGhost.
+
+    1 error
+
+

+ 8 - 0
tests/m_bad_ghost.mod

@@ -0,0 +1,8 @@
+MODULE MBadGhost;
+MODULE M EXPORT ghost;
+VAR cnt : INTEGER;
+END M;
+VAR ExitCode : INTEGER;
+BEGIN
+  ExitCode := 0
+END MBadGhost.

+ 19 - 0
tests/m_bad_nest.LST

@@ -0,0 +1,19 @@
+Listing:
+
+    1  MODULE MBadNest;
+    2  VAR ExitCode : INTEGER;
+    3  PROCEDURE P;
+    4  MODULE M EXPORT cnt;
+*****         ^ not supported in this phase
+    5  VAR cnt : INTEGER;
+    6  END M;
+    7  BEGIN
+    8    ExitCode := 0
+    9  END P;
+   10  BEGIN
+   11    ExitCode := 0
+   12  END MBadNest.
+
+    1 error
+
+

+ 12 - 0
tests/m_bad_nest.mod

@@ -0,0 +1,12 @@
+MODULE MBadNest;
+VAR ExitCode : INTEGER;
+PROCEDURE P;
+MODULE M EXPORT cnt;
+VAR cnt : INTEGER;
+END M;
+BEGIN
+  ExitCode := 0
+END P;
+BEGIN
+  ExitCode := 0
+END MBadNest.

+ 21 - 0
tests/m_bad_param.LST

@@ -0,0 +1,21 @@
+Listing:
+
+    1  MODULE MBadParam;
+    2  MODULE M EXPORT cnt, Add;
+    3  VAR cnt : INTEGER;
+    4  PROCEDURE Add(x : INTEGER);
+    5  BEGIN
+    6    cnt := cnt + x
+    7  END Add;
+    8  END M;
+    9  VAR ExitCode : INTEGER;
+   10  BEGIN
+   11    M.cnt := 10;
+   12    M.Add(5);
+*****          ^ invalid procedure call
+   13    ExitCode := M.cnt
+   14  END MBadParam.
+
+    1 error
+
+

+ 14 - 0
tests/m_bad_param.mod

@@ -0,0 +1,14 @@
+MODULE MBadParam;
+MODULE M EXPORT cnt, Add;
+VAR cnt : INTEGER;
+PROCEDURE Add(x : INTEGER);
+BEGIN
+  cnt := cnt + x
+END Add;
+END M;
+VAR ExitCode : INTEGER;
+BEGIN
+  M.cnt := 10;
+  M.Add(5);
+  ExitCode := M.cnt
+END MBadParam.

+ 16 - 0
tests/m_bad_priv.LST

@@ -0,0 +1,16 @@
+Listing:
+
+    1  MODULE MBadPriv;
+    2  MODULE M EXPORT cnt;
+    3  VAR cnt, secret : INTEGER;
+    4  END M;
+    5  VAR ExitCode : INTEGER;
+    6  BEGIN
+    7    M.secret := 1;
+*****      ^ undeclared identifier
+    8    ExitCode := 0
+    9  END MBadPriv.
+
+    1 error
+
+

+ 9 - 0
tests/m_bad_priv.mod

@@ -0,0 +1,9 @@
+MODULE MBadPriv;
+MODULE M EXPORT cnt;
+VAR cnt, secret : INTEGER;
+END M;
+VAR ExitCode : INTEGER;
+BEGIN
+  M.secret := 1;
+  ExitCode := 0
+END MBadPriv.

+ 14 - 0
tests/m_const.LST

@@ -0,0 +1,14 @@
+Listing:
+
+    1  MODULE MConst;
+    2  MODULE M EXPORT C;
+    3  CONST C = 7;
+    4  END M;
+    5  VAR ExitCode : INTEGER;
+    6  BEGIN
+    7    ExitCode := M.C
+    8  END MConst.
+
+    0 errors
+
+

+ 8 - 0
tests/m_const.mod

@@ -0,0 +1,8 @@
+MODULE MConst;
+MODULE M EXPORT C;
+CONST C = 7;
+END M;
+VAR ExitCode : INTEGER;
+BEGIN
+  ExitCode := M.C
+END MConst.

+ 21 - 0
tests/m_mod.LST

@@ -0,0 +1,21 @@
+Listing:
+
+    1  MODULE MMod;
+    2  MODULE M EXPORT cnt, Inc;
+    3  VAR cnt : INTEGER;
+    4  PROCEDURE Inc;
+    5  BEGIN
+    6    cnt := cnt + 1
+    7  END Inc;
+    8  END M;
+    9  VAR ExitCode : INTEGER;
+   10  BEGIN
+   11    M.cnt := 10;
+   12    M.Inc();
+   13    M.Inc();
+   14    ExitCode := M.cnt
+   15  END MMod.
+
+    0 errors
+
+

+ 15 - 0
tests/m_mod.mod

@@ -0,0 +1,15 @@
+MODULE MMod;
+MODULE M EXPORT cnt, Inc;
+VAR cnt : INTEGER;
+PROCEDURE Inc;
+BEGIN
+  cnt := cnt + 1
+END Inc;
+END M;
+VAR ExitCode : INTEGER;
+BEGIN
+  M.cnt := 10;
+  M.Inc();
+  M.Inc();
+  ExitCode := M.cnt
+END MMod.

+ 19 - 0
tests/m_multi.LST

@@ -0,0 +1,19 @@
+Listing:
+
+    1  MODULE MMulti;
+    2  MODULE M EXPORT cnt;
+    3  VAR cnt : INTEGER;
+    4  END M;
+    5  MODULE N EXPORT k;
+    6  VAR k : INTEGER;
+    7  END N;
+    8  VAR ExitCode : INTEGER;
+    9  BEGIN
+   10    M.cnt := 3;
+   11    N.k := 4;
+   12    ExitCode := M.cnt + N.k
+   13  END MMulti.
+
+    0 errors
+
+

+ 13 - 0
tests/m_multi.mod

@@ -0,0 +1,13 @@
+MODULE MMulti;
+MODULE M EXPORT cnt;
+VAR cnt : INTEGER;
+END M;
+MODULE N EXPORT k;
+VAR k : INTEGER;
+END N;
+VAR ExitCode : INTEGER;
+BEGIN
+  M.cnt := 3;
+  N.k := 4;
+  ExitCode := M.cnt + N.k
+END MMulti.

+ 20 - 0
tests/m_outer.LST

@@ -0,0 +1,20 @@
+Listing:
+
+    1  MODULE MOuter;
+    2  VAR g : INTEGER;
+    3  MODULE M EXPORT Inc;
+    4  PROCEDURE Inc;
+    5  BEGIN
+    6    g := g + 1
+    7  END Inc;
+    8  END M;
+    9  VAR ExitCode : INTEGER;
+   10  BEGIN
+   11    g := 10;
+   12    M.Inc();
+   13    ExitCode := g
+   14  END MOuter.
+
+    0 errors
+
+

+ 14 - 0
tests/m_outer.mod

@@ -0,0 +1,14 @@
+MODULE MOuter;
+VAR g : INTEGER;
+MODULE M EXPORT Inc;
+PROCEDURE Inc;
+BEGIN
+  g := g + 1
+END Inc;
+END M;
+VAR ExitCode : INTEGER;
+BEGIN
+  g := 10;
+  M.Inc();
+  ExitCode := g
+END MOuter.