Explorar o código

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

Eric Streit hai 1 mes
pai
achega
9a9789ee2b
Modificáronse 57 ficheiros con 3275 adicións e 2210 borrados
  1. BIN=BIN
      M2c
  2. 125 15
      M2c.atg
  3. 65 64
      M2c.err
  4. 1989 1879
      M2c.lst
  5. 65 64
      M2c.mod
  6. BIN=BIN
      M2c.o
  7. 254 128
      M2cP.mod
  8. BIN=BIN
      M2cP.o
  9. 54 53
      M2cS.mod
  10. BIN=BIN
      M2cS.o
  11. BIN=BIN
      MArr.MC4
  12. BIN=BIN
      MBadDup.MC4
  13. BIN=BIN
      MBadEnd.MC4
  14. BIN=BIN
      MBadExp.MC4
  15. BIN=BIN
      MBadFunc.MC4
  16. BIN=BIN
      MBadGhost.MC4
  17. BIN=BIN
      MBadNest.MC4
  18. BIN=BIN
      MBadParam.MC4
  19. BIN=BIN
      MBadPriv.MC4
  20. BIN=BIN
      MConst.MC4
  21. 11 0
      MGen.def
  22. 74 7
      MGen.mod
  23. BIN=BIN
      MGen.o
  24. BIN=BIN
      MMod.MC4
  25. BIN=BIN
      MMulti.MC4
  26. BIN=BIN
      MOuter.MC4
  27. 40 0
      SymTab.def
  28. 148 0
      SymTab.mod
  29. BIN=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=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=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=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=BIN
M2cS.o


BIN=BIN
MArr.MC4


BIN=BIN
MBadDup.MC4


BIN=BIN
MBadEnd.MC4


BIN=BIN
MBadExp.MC4


BIN=BIN
MBadFunc.MC4


BIN=BIN
MBadGhost.MC4


BIN=BIN
MBadNest.MC4


BIN=BIN
MBadParam.MC4


BIN=BIN
MBadPriv.MC4


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


BIN=BIN
MMod.MC4


BIN=BIN
MMulti.MC4


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