Преглед изворни кода

step7: module procedures — params, VAR, functions, open formals, bare calls; 120/120 tests green

Eric Streit пре 3 недеља
родитељ
комит
4e53b4263b
45 измењених фајлова са 2676 додато и 2057 уклоњено
  1. BIN
      M2c
  2. 69 18
      M2c.atg
  3. 2033 1982
      M2c.lst
  4. 65 15
      M2cP.mod
  5. BIN
      M2cP.o
  6. BIN
      MBadArity.MC4
  7. BIN
      MBadMActual.MC4
  8. BIN
      MBadMFunc.MC4
  9. BIN
      MBadMVar.MC4
  10. BIN
      MBadNope.MC4
  11. BIN
      MBare.MC4
  12. BIN
      MFunc.MC4
  13. 9 0
      MGen.def
  14. 93 3
      MGen.mod
  15. BIN
      MGen.o
  16. BIN
      MOpen.MC4
  17. BIN
      MParam.MC4
  18. BIN
      MVarPar.MC4
  19. 10 0
      SymTab.def
  20. 46 0
      SymTab.mod
  21. BIN
      SymTab.o
  22. 49 0
      docs/summary_step7.md
  23. 14 2
      run_tests.sh
  24. 18 0
      tests/m_bad_arity.LST
  25. 11 0
      tests/m_bad_arity.mod
  26. 0 19
      tests/m_bad_func.LST
  27. 0 12
      tests/m_bad_func.mod
  28. 18 0
      tests/m_bad_mactual.LST
  29. 11 0
      tests/m_bad_mactual.mod
  30. 17 0
      tests/m_bad_mfunc.LST
  31. 10 0
      tests/m_bad_mfunc.mod
  32. 20 0
      tests/m_bad_mvar.LST
  33. 13 0
      tests/m_bad_mvar.mod
  34. 16 0
      tests/m_bad_nope.LST
  35. 9 0
      tests/m_bad_nope.mod
  36. 21 0
      tests/m_bare.LST
  37. 15 0
      tests/m_bare.mod
  38. 21 0
      tests/m_func.LST
  39. 15 0
      tests/m_func.mod
  40. 21 0
      tests/m_open.LST
  41. 15 0
      tests/m_open.mod
  42. 3 4
      tests/m_param.LST
  43. 2 2
      tests/m_param.mod
  44. 19 0
      tests/m_varpar.LST
  45. 13 0
      tests/m_varpar.mod

+ 69 - 18
M2c.atg

@@ -4,8 +4,9 @@ COMPILER M2c
 
    - program module only, no DEFINITION / IMPLEMENTATION split
    - 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
+     VARs, CONSTs and procedures (value/VAR params, functions, open
+     array formals with fixed actuals); use as M.x / M.P(args);
+     no EXPORT of types, no PRIORITY
    - procedures: declarations (nested), value and VAR parameters,
      functions with RETURN, recursion, FORWARD headings;
      no procedure types/variables, no cones
@@ -586,7 +587,8 @@ PRODUCTIONS
                                              storable, pushedDst,
                                              pushedFld: BOOLEAN;
                                              dstBytes, srcBytes: CARDINAL;
-                                             elemDt: SymTab.TypeIndex; .)
+                                             elemDt: SymTab.TypeIndex;
+                                             modBare: INTEGER; .)
     =                                   (. sfx := FALSE; pushedDst := FALSE;
                                            pushedFld := FALSE; .)
       DesignHead<dt, dk, bn, FALSE, lxD>
@@ -759,10 +761,35 @@ PRODUCTIONS
                                          ELSE MGen.Drop
                                          END; .)
       | CallTail<bn, lxD, sfx, FALSE, okC, FALSE>
-      |                             (. MGen.ActBegin(bn);
-                                       IF MGen.ActEnd(bn, FALSE, FALSE) # 0 THEN
-                                         SemError(233)
-                                       END; .) ) .
+      |                             (. IF (SymTab.SymKind(bn)
+                                              = SymTab.KindModule)
+                                             & sfx
+                                             & (SymTab.StrLen(lxD) > 0) THEN
+                                           modBare := SymTab.ExpProc(bn,
+                                                            lxD);
+                                           IF modBare < 0 THEN
+                                             IF SymTab.ExpKind(bn,
+                                                  lxD) # -1 THEN
+                                               SemError(233)
+                                             END
+                                           ELSIF SymTab.ProcNParByNum(
+                                                    modBare) # 0 THEN
+                                             SemError(233)
+                                           ELSE
+                                             MGen.CallProc(modBare);
+                                             IF SymTab.ProcRetByNum(
+                                                  modBare)
+                                                # SymTab.InvalidType THEN
+                                               MGen.Drop
+                                             END
+                                           END
+                                         ELSE
+                                           MGen.ActBegin(bn);
+                                           IF MGen.ActEnd(bn, FALSE,
+                                                  FALSE) # 0 THEN
+                                             SemError(233)
+                                           END
+                                         END; .) ) .
   CallTail <pn: SymTab.Name; exp: SymTab.Name; sfx: BOOLEAN;
             inExpr: BOOLEAN; VAR ok: BOOLEAN; hasDead: BOOLEAN>
                                         (. VAR t: SymTab.TypeIndex;
@@ -780,15 +807,30 @@ PRODUCTIONS
                                              & (SymTab.StrLen(exp) > 0);
                                            IF hasDead THEN MGen.Drop END;
                                            IF isModP THEN
-                                             IF inExpr THEN
+                                             modPNum := SymTab.ExpProc(pn,
+                                                              exp);
+                                             IF modPNum < 0 THEN
+                                               IF SymTab.ExpKind(pn,
+                                                    exp) # -1 THEN
+                                                 SemError(233)
+                                               END;
+                                               modErr := TRUE
+                                             ELSIF inExpr
+                                                & (SymTab.ProcRetByNum(
+                                                     modPNum)
+                                                   = SymTab.InvalidType)
+                                             THEN
                                                SemError(233);
                                                modErr := TRUE
-                                             END
+                                             END;
+                                             MGen.ActBeginNum(modPNum)
                                            ELSE
                                              MGen.ActBegin(pn)
                                            END; .)
       [ Expr<t, lx, v, vn>              (. IF isModP THEN
-                                           IF ~modErr THEN
+                                           IF ~modErr
+                                              & (MGen.ActValue(t, v, vn)
+                                                 # 0) THEN
                                              SemError(233);
                                              modErr := TRUE
                                            END
@@ -796,7 +838,9 @@ PRODUCTIONS
                                            SemError(233)
                                          END; .)
         { "," Expr<t, lx, v, vn>        (. IF isModP THEN
-                                           IF ~modErr THEN
+                                           IF ~modErr
+                                              & (MGen.ActValue(t, v, vn)
+                                                 # 0) THEN
                                              SemError(233);
                                              modErr := TRUE
                                            END
@@ -804,14 +848,11 @@ PRODUCTIONS
                                            SemError(233)
                                          END; .) } ]
       ")"                               (. IF isModP THEN
-                                           IF ~inExpr & ~modErr THEN
-                                             modPNum := SymTab.ExpProc(pn,
-                                                              exp);
-                                             IF modPNum < 0 THEN
+                                           IF ~modErr THEN
+                                             IF MGen.ActEndNum(modPNum,
+                                                  inExpr) # 0 THEN
                                                SemError(233)
-                                             ELSE
-                                               MGen.CallProc(modPNum);
-                                               ok := TRUE
+                                             ELSE ok := TRUE
                                              END
                                            END
                                          ELSIF MGen.ActEnd(pn, sfx,
@@ -1391,6 +1432,7 @@ PRODUCTIONS
         GetIdent<m>                     (. IF (k = SymTab.KindModule) THEN
                                              IF SymTab.ExpKind(bn, m) = -1 THEN
                                                SemError(201);
+                                               MGen.CopyName(m, lx);
                                                t := SymTab.InvalidType;
                                                IF doLoad THEN
                                                  MGen.Drop; MGen.PushInt(0)
@@ -1934,6 +1976,15 @@ PRODUCTIONS
                                              IF SymTab.SymKind(bnF)
                                                 = SymTab.KindProc THEN
                                                t := SymTab.ProcRet(bnF)
+                                             ELSIF (SymTab.SymKind(bnF)
+                                                       = SymTab.KindModule)
+                                                & sfxF
+                                                & (SymTab.StrLen(lxD) > 0)
+                                                & (SymTab.ExpProc(bnF,
+                                                     lxD) >= 0) THEN
+                                               t := SymTab.ProcRetByNum(
+                                                      SymTab.ExpProc(bnF,
+                                                        lxD))
                                              ELSE
                                                t := SymTab.InvalidType
                                              END

+ 2033 - 1982
M2c.lst

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

+ 65 - 15
M2cP.mod

@@ -391,6 +391,15 @@ PROCEDURE Fact (VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
             IF SymTab.SymKind(bnF)
                = SymTab.KindProc THEN
               t := SymTab.ProcRet(bnF)
+            ELSIF (SymTab.SymKind(bnF)
+                      = SymTab.KindModule)
+               & sfxF
+               & (SymTab.StrLen(lxD) > 0)
+               & (SymTab.ExpProc(bnF,
+                    lxD) >= 0) THEN
+              t := SymTab.ProcRetByNum(
+                     SymTab.ExpProc(bnF,
+                       lxD))
             ELSE
               t := SymTab.InvalidType
             END
@@ -697,17 +706,32 @@ PROCEDURE CallTail (pn: SymTab.Name; exp: SymTab.Name; sfx: BOOLEAN;
       & (SymTab.StrLen(exp) > 0);
     IF hasDead THEN MGen.Drop END;
     IF isModP THEN
-      IF inExpr THEN
+      modPNum := SymTab.ExpProc(pn,
+                       exp);
+      IF modPNum < 0 THEN
+        IF SymTab.ExpKind(pn,
+             exp) # -1 THEN
+          SemError(233)
+        END;
+        modErr := TRUE
+      ELSIF inExpr
+         & (SymTab.ProcRetByNum(
+              modPNum)
+            = SymTab.InvalidType)
+      THEN
         SemError(233);
         modErr := TRUE
-      END
+      END;
+      MGen.ActBeginNum(modPNum)
     ELSE
       MGen.ActBegin(pn)
     END;;
     IF In(symSet[1], sym) THEN
       Expr(t, lx, v, vn);
       IF isModP THEN
-      IF ~modErr THEN
+      IF ~modErr
+         & (MGen.ActValue(t, v, vn)
+            # 0) THEN
         SemError(233);
         modErr := TRUE
       END
@@ -718,7 +742,9 @@ PROCEDURE CallTail (pn: SymTab.Name; exp: SymTab.Name; sfx: BOOLEAN;
         Get;
         Expr(t, lx, v, vn);
         IF isModP THEN
-        IF ~modErr THEN
+        IF ~modErr
+           & (MGen.ActValue(t, v, vn)
+              # 0) THEN
           SemError(233);
           modErr := TRUE
         END
@@ -729,14 +755,11 @@ PROCEDURE CallTail (pn: SymTab.Name; exp: SymTab.Name; sfx: BOOLEAN;
     END;
     Expect(20);
     IF isModP THEN
-    IF ~inExpr & ~modErr THEN
-      modPNum := SymTab.ExpProc(pn,
-                       exp);
-      IF modPNum < 0 THEN
+    IF ~modErr THEN
+      IF MGen.ActEndNum(modPNum,
+           inExpr) # 0 THEN
         SemError(233)
-      ELSE
-        MGen.CallProc(modPNum);
-        ok := TRUE
+      ELSE ok := TRUE
       END
     END
     ELSIF MGen.ActEnd(pn, sfx,
@@ -785,6 +808,7 @@ PROCEDURE DesignTail (VAR t: SymTab.TypeIndex; VAR k: INTEGER;
         IF (k = SymTab.KindModule) THEN
           IF SymTab.ExpKind(bn, m) = -1 THEN
             SemError(201);
+            MGen.CopyName(m, lx);
             t := SymTab.InvalidType;
             IF doLoad THEN
               MGen.Drop; MGen.PushInt(0)
@@ -1616,6 +1640,7 @@ PROCEDURE AssignOrCall;
     pushedFld: BOOLEAN;
     dstBytes, srcBytes: CARDINAL;
     elemDt: SymTab.TypeIndex;
+    modBare: INTEGER;
   BEGIN
     sfx := FALSE; pushedDst := FALSE;
     pushedFld := FALSE;;
@@ -1793,10 +1818,35 @@ PROCEDURE AssignOrCall;
     ELSIF (sym = 19) THEN
       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;;
+      IF (SymTab.SymKind(bn)
+             = SymTab.KindModule)
+            & sfx
+            & (SymTab.StrLen(lxD) > 0) THEN
+          modBare := SymTab.ExpProc(bn,
+                           lxD);
+          IF modBare < 0 THEN
+            IF SymTab.ExpKind(bn,
+                 lxD) # -1 THEN
+              SemError(233)
+            END
+          ELSIF SymTab.ProcNParByNum(
+                   modBare) # 0 THEN
+            SemError(233)
+          ELSE
+            MGen.CallProc(modBare);
+            IF SymTab.ProcRetByNum(
+                 modBare)
+               # SymTab.InvalidType THEN
+              MGen.Drop
+            END
+          END
+        ELSE
+          MGen.ActBegin(bn);
+          IF MGen.ActEnd(bn, FALSE,
+                 FALSE) # 0 THEN
+            SemError(233)
+          END
+        END;;
     ELSE SynError(81);
     END;
   END AssignOrCall;


BIN
MBadParam.MC4 → MBadArity.MC4


BIN
MBadFunc.MC4 → MBadMActual.MC4







+ 9 - 0
MGen.def

@@ -296,6 +296,15 @@ 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). *)
 
+PROCEDURE ActBeginNum (num: INTEGER);
+(* Opens an actual-parameter frame for the procedure numbered num
+   (exported module procs, invisible by name after ExitModule). *)
+
+PROCEDURE ActEndNum (num: INTEGER; inExpr: BOOLEAN): INTEGER;
+(* By-number ActEnd: verifies arity, reloads actuals reversed and
+   emits the global call (module procs are always global-level).
+   0 = ok, 1 = error 233. *)
+
 (* ---- control flow (E0/E1 with fixups) ---- *)
 
 PROCEDURE NewLabel (): INTEGER;

+ 93 - 3
MGen.mod

@@ -73,6 +73,8 @@ TYPE
     known : BOOLEAN;
     nf : CARDINAL;
     pn : ARRAY [0 .. 63] OF CHAR;
+    byNum : BOOLEAN;
+    num : INTEGER;
   END;
 
 VAR
@@ -664,9 +666,57 @@ PROCEDURE ActBegin (pn: ARRAY OF CHAR);
       & (SymTab.SymKind(pn) = SymTab.KindProc);
     IF actSt[fr].known THEN actSt[fr].nf := SymTab.ProcNPar(pn)
     ELSE actSt[fr].nf := 0
-    END
+    END;
+    actSt[fr].byNum := FALSE;
+    actSt[fr].num := -1
   END ActBegin;
 
+PROCEDURE ActBeginNum (num: INTEGER);
+(* Actuals for a procedure known by number (exported module procs,
+   whose names vanish with the module body scope). *)
+  VAR fr : CARDINAL;
+    k : CARDINAL;
+  BEGIN
+    fr := actTop;
+    IF fr > MaxActDepth THEN fr := MaxActDepth
+    ELSE INC(actTop)
+    END;
+    actSt[fr].pn[0] := 0C;
+    actSt[fr].n := 0;
+    k := 0;
+    WHILE k <= MaxActN DO
+      actSt[fr].lens[k] := -1;
+      actSt[fr].sfxs[k] := FALSE;
+      actSt[fr].idxs[k] := TRUE;
+      INC(k)
+    END;
+    actSt[fr].known := SymTab.ProcValid(num);
+    IF actSt[fr].known THEN actSt[fr].nf := SymTab.ProcNParByNum(num)
+    ELSE actSt[fr].nf := 0
+    END;
+    actSt[fr].byNum := TRUE;
+    actSt[fr].num := num
+  END ActBeginNum;
+
+PROCEDURE ActFormalType (fr, i: CARDINAL): INTEGER;
+(* i-th formal type of the frame's callee, by number or by name. *)
+  BEGIN
+    IF actSt[fr].byNum THEN
+      RETURN SymTab.ParamTypeByNum(actSt[fr].num, i)
+    ELSE
+      RETURN SymTab.ParamType(actSt[fr].pn, i)
+    END
+  END ActFormalType;
+
+PROCEDURE ActFormalIsVar (fr, i: CARDINAL): BOOLEAN;
+  BEGIN
+    IF actSt[fr].byNum THEN
+      RETURN SymTab.ParamIsVarByNum(actSt[fr].num, i)
+    ELSE
+      RETURN SymTab.ParamIsVar(actSt[fr].pn, i)
+    END
+  END ActFormalIsVar;
+
 PROCEDURE ActValue (t: INTEGER; v: BOOLEAN;
                     vn: ARRAY OF CHAR): INTEGER;
   VAR fr : CARDINAL;
@@ -684,8 +734,8 @@ PROCEDURE ActValue (t: INTEGER; v: BOOLEAN;
       RETURN 1
     END;
     IF actSt[fr].known & (i < actSt[fr].nf) THEN
-      ftyp := SymTab.ParamType(actSt[fr].pn, i);
-      fv := SymTab.ParamIsVar(actSt[fr].pn, i);
+      ftyp := ActFormalType(fr, i);
+      fv := ActFormalIsVar(fr, i);
       IF SymTab.IsOpen(ftyp) THEN
         IF (t = SymTab.InvalidType)
            OR SymTab.IsOpen(t)
@@ -778,6 +828,46 @@ PROCEDURE ActEnd (pn: ARRAY OF CHAR; sfx, inExpr: BOOLEAN): INTEGER;
     RETURN 0
   END ActEnd;
 
+PROCEDURE ActEndNum (num: INTEGER; inExpr: BOOLEAN): INTEGER;
+(* Ends a by-number call (module procedures are always global-level,
+   so a plain global call is correct; the M. prefix is qualification,
+   not a tail, hence no sfx check). *)
+  VAR fr : CARDINAL;
+    i : CARDINAL;
+    n : INTEGER;
+  BEGIN
+    fr := ActFrameIdx();
+    IF actTop > 0 THEN DEC(actTop) END;
+    n := VAL(INTEGER, actSt[fr].n);
+    IF ~SymTab.ProcValid(num)
+       OR (n # VAL(INTEGER, SymTab.ProcNParByNum(num))) THEN
+      IF inExpr THEN EmitOp(OPimm0) END;
+      RETURN 1
+    END;
+    IF inExpr & (SymTab.ProcRetByNum(num) = SymTab.InvalidType) THEN
+      EmitOp(OPimm0);
+      RETURN 1
+    END;
+    i := actSt[fr].n;
+    WHILE i > 0 DO
+      DEC(i);
+      IF i <= MaxActN THEN
+        IF (actSt[fr].lens[i] >= 0)
+           & SymTab.IsOpen(SymTab.ParamTypeByNum(num, i)) THEN
+          LoadTemp(actSt[fr].lens[i]);
+          LoadTemp(actSt[fr].tmps[i])
+        ELSE
+          LoadTemp(actSt[fr].tmps[i])
+        END
+      END
+    END;
+    CallProc(num);
+    IF ~inExpr & (SymTab.ProcRetByNum(num) # SymTab.InvalidType) THEN
+      EmitOp(OPext); EmitOp(SUBdrop)
+    END;
+    RETURN 0
+  END ActEndNum;
+
 PROCEDURE EmitMag (c: CARDINAL);
   BEGIN
     IF c <= 255 THEN EmitOpB(OPimmB, c)





+ 10 - 0
SymTab.def

@@ -289,6 +289,16 @@ PROCEDURE ParamType (name: ARRAY OF CHAR; i: CARDINAL): TypeIndex;
 PROCEDURE ParamIsVar (name: ARRAY OF CHAR; i: CARDINAL): BOOLEAN;
 (* i-th formal parameter (0-based), InvalidType/FALSE if absent. *)
 
+PROCEDURE ProcValid (num: INTEGER): BOOLEAN;
+(* TRUE if num is a declared procedure number (survives scope pops,
+   so module procs stay callable after ExitModule). *)
+
+PROCEDURE ProcNParByNum (num: INTEGER): CARDINAL;
+PROCEDURE ParamTypeByNum (num: INTEGER; i: CARDINAL): TypeIndex;
+PROCEDURE ParamIsVarByNum (num: INTEGER; i: CARDINAL): BOOLEAN;
+PROCEDURE ProcRetByNum (num: INTEGER): TypeIndex;
+(* Same signature queries as above, keyed by procedure number. *)
+
 PROCEDURE SymSlot (name: ARRAY OF CHAR): INTEGER;
 (* Frame slot (params >= 3, locals negative). Only meaningful
    for variables at proc depth > 0. *)

+ 46 - 0
SymTab.mod

@@ -1211,6 +1211,52 @@ PROCEDURE ParamIsVar (name: ARRAY OF CHAR; i: CARDINAL): BOOLEAN;
     RETURN params[h].isVar
   END ParamIsVar;
 
+PROCEDURE NumHead (num: INTEGER): INTEGER;
+(* Param list head by number: define list if present, else forward. *)
+  BEGIN
+    IF (num < 1) OR (num > VAL(INTEGER, nProcs)) THEN RETURN -1 END;
+    IF procs[num].dHead # -1 THEN RETURN procs[num].dHead END;
+    RETURN procs[num].fHead
+  END NumHead;
+
+PROCEDURE ProcValid (num: INTEGER): BOOLEAN;
+  BEGIN
+    RETURN (num >= 1) & (num <= VAL(INTEGER, nProcs))
+  END ProcValid;
+
+PROCEDURE ProcNParByNum (num: INTEGER): CARDINAL;
+  VAR h : INTEGER;
+    c : CARDINAL;
+  BEGIN
+    h := NumHead(num); c := 0;
+    WHILE h # -1 DO INC(c); h := params[h].next END;
+    RETURN c
+  END ProcNParByNum;
+
+PROCEDURE ParamTypeByNum (num: INTEGER; i: CARDINAL): TypeIndex;
+  VAR h : INTEGER;
+  BEGIN
+    h := NumHead(num);
+    WHILE (h # -1) & (i > 0) DO h := params[h].next; DEC(i) END;
+    IF h = -1 THEN RETURN InvalidType END;
+    RETURN params[h].typ
+  END ParamTypeByNum;
+
+PROCEDURE ParamIsVarByNum (num: INTEGER; i: CARDINAL): BOOLEAN;
+  VAR h : INTEGER;
+  BEGIN
+    h := NumHead(num);
+    WHILE (h # -1) & (i > 0) DO h := params[h].next; DEC(i) END;
+    IF h = -1 THEN RETURN FALSE END;
+    RETURN params[h].isVar
+  END ParamIsVarByNum;
+
+PROCEDURE ProcRetByNum (num: INTEGER): TypeIndex;
+  BEGIN
+    IF ~ProcValid(num) THEN RETURN InvalidType END;
+    RETURN procs[num].ret
+  END ProcRetByNum;
+
 PROCEDURE SymSlot (name: ARRAY OF CHAR): INTEGER;
   VAR idx : INTEGER;
   BEGIN


+ 49 - 0
docs/summary_step7.md

@@ -0,0 +1,49 @@
+# Step 7 — Module procedures with parameters and functions (uncommitted)
+
+120/120 tests green (112 regressions + 5 run + 5 rejection, minus 2 retired),
+mc64 boot + example green, Showcase still 157.
+
+## Goal
+
+Finish local-`MODULE` procedures: value/`VAR` parameters (incl. open-array
+formals), functions returning values usable in expressions, bare `M.P;`
+calls, and single-error cascades for bad module calls.
+
+## What was built
+
+- `SymTab`: `procs[]` survives scope pops, so four by-number accessors
+  (`ProcValid`, `ProcNParByNum`, `ParamTypeByNum`, `ParamIsVarByNum`,
+  `ProcRetByNum`) keep exported procs callable after `ExitModule`.
+- `MGen`: `ActFrame` gained `byNum`/`num`; new `ActBeginNum`/`ActEndNum`
+  (global `ED` call — module procs never need the display); `ActValue`
+  checks formals through `ActFormalType`/`ActFormalIsVar` so value, `VAR`
+  and open-array actuals share one path.
+- `M2c.atg`: `CallTail` module path now takes real actuals (arity/type via
+  233), rejects proper procs in expressions, routes unknown exports through
+  the module path; `Fact` synthesizes the module-function return type;
+  `AssignOrCall` bare branch handles `M.P;` (with `Drop` for functions).
+- `run_tests.sh`: step-7 sections added.
+
+## Tests — 120/120 (112 + 5 + 5 − 2 retired)
+
+5 run: `m_param` 15 (value param), `m_varpar` 15 (`VAR` param),
+`m_func` 45 (function in expr + `M.Get()`/`M.Get;` statements with
+side-effect count), `m_open` 10 (open-array formal, `HIGH`), `m_bare` 2
+(`M.Inc;` without parens). 5 rejections, each exactly one error:
+`m_bad_arity`, `m_bad_mactual`, `m_bad_mvar` (module var as `VAR` actual),
+`m_bad_mfunc` (proper proc in expression) → 233; `m_bad_nope` → 201.
+Retired: `m_bad_param`, `m_bad_func` — valid programs now (deleted).
+
+## Bugs found and fixed
+
+1. `M.Nope()` double-reported (201 + 233): unknown exports left `lx` empty
+   so `CallTail` fell into the regular path. Unknown exports now `CopyName`
+   into `lx` (module path) and stay quiet there — the 201 was already
+   reported, mirroring how unknown plain names pass `ActEnd` quietly.
+   Same treatment for bare `M.Nope;`.
+
+## Known limits (deferred)
+
+Type exports, `DEFINITION`/`IMPLEMENTATION` split, module `BEGIN` bodies,
+`VAR` actuals with tails (`M.cnt` as `VAR` actual → 233), open-to-open
+actuals, value composite params, forward-declared module procs (untested).

+ 14 - 2
run_tests.sh

@@ -232,9 +232,21 @@ 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 "=== Step-7 run tests (module procedures) ==="
+expect_run m_param.mod 15
+expect_run m_varpar.mod 15
+expect_run m_func.mod 45
+expect_run m_open.mod 10
+expect_run m_bare.mod 2
+
+echo "=== Step-7 rejection tests ==="
+expect_fail m_bad_arity.mod "invalid procedure call"
+expect_fail m_bad_mactual.mod "invalid procedure call"
+expect_fail m_bad_mvar.mod "invalid procedure call"
+expect_fail m_bad_mfunc.mod "invalid procedure call"
+expect_fail m_bad_nope.mod "undeclared identifier"
+
 echo "=== $pass passed, $fail failed ==="
 test "$fail" = 0

+ 18 - 0
tests/m_bad_arity.LST

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

+ 11 - 0
tests/m_bad_arity.mod

@@ -0,0 +1,11 @@
+MODULE MBadArity;
+MODULE M EXPORT Add;
+PROCEDURE Add(x : INTEGER);
+BEGIN
+END Add;
+END M;
+VAR ExitCode : INTEGER;
+BEGIN
+  M.Add(1, 2);
+  ExitCode := 0
+END MBadArity.

+ 0 - 19
tests/m_bad_func.LST

@@ -1,19 +0,0 @@
-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
-
-

+ 0 - 12
tests/m_bad_func.mod

@@ -1,12 +0,0 @@
-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.

+ 18 - 0
tests/m_bad_mactual.LST

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

+ 11 - 0
tests/m_bad_mactual.mod

@@ -0,0 +1,11 @@
+MODULE MBadMActual;
+MODULE M EXPORT Add;
+PROCEDURE Add(x : INTEGER);
+BEGIN
+END Add;
+END M;
+VAR ExitCode : INTEGER;
+BEGIN
+  M.Add("s");
+  ExitCode := 0
+END MBadMActual.

+ 17 - 0
tests/m_bad_mfunc.LST

@@ -0,0 +1,17 @@
+Listing:
+
+    1  MODULE MBadMFunc;
+    2  MODULE M EXPORT Bump;
+    3  PROCEDURE Bump;
+    4  BEGIN
+    5  END Bump;
+    6  END M;
+    7  VAR ExitCode : INTEGER;
+    8  BEGIN
+    9    ExitCode := M.Bump()
+*****                      ^ invalid procedure call
+   10  END MBadMFunc.
+
+    1 error
+
+

+ 10 - 0
tests/m_bad_mfunc.mod

@@ -0,0 +1,10 @@
+MODULE MBadMFunc;
+MODULE M EXPORT Bump;
+PROCEDURE Bump;
+BEGIN
+END Bump;
+END M;
+VAR ExitCode : INTEGER;
+BEGIN
+  ExitCode := M.Bump()
+END MBadMFunc.

+ 20 - 0
tests/m_bad_mvar.LST

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

+ 13 - 0
tests/m_bad_mvar.mod

@@ -0,0 +1,13 @@
+MODULE MBadMVar;
+MODULE M EXPORT cnt, Bump;
+VAR cnt : INTEGER;
+PROCEDURE Bump(VAR x : INTEGER);
+BEGIN
+  x := x + 1
+END Bump;
+END M;
+VAR ExitCode : INTEGER;
+BEGIN
+  M.Bump(M.cnt);
+  ExitCode := 0
+END MBadMVar.

+ 16 - 0
tests/m_bad_nope.LST

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

+ 9 - 0
tests/m_bad_nope.mod

@@ -0,0 +1,9 @@
+MODULE MBadNope;
+MODULE M EXPORT cnt;
+VAR cnt : INTEGER;
+END M;
+VAR ExitCode : INTEGER;
+BEGIN
+  M.Nope();
+  ExitCode := 0
+END MBadNope.

+ 21 - 0
tests/m_bare.LST

@@ -0,0 +1,21 @@
+Listing:
+
+    1  MODULE MBare;
+    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 := 0;
+   12    M.Inc;
+   13    M.Inc();
+   14    ExitCode := M.cnt
+   15  END MBare.
+
+    0 errors
+
+

+ 15 - 0
tests/m_bare.mod

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

+ 21 - 0
tests/m_func.LST

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

+ 15 - 0
tests/m_func.mod

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

+ 21 - 0
tests/m_open.LST

@@ -0,0 +1,21 @@
+Listing:
+
+    1  MODULE MOpen;
+    2  MODULE M EXPORT Total;
+    3  PROCEDURE Total(x : ARRAY OF INTEGER) : INTEGER;
+    4  VAR i, s : INTEGER;
+    5  BEGIN
+    6    s := 0;
+    7    FOR i := 0 TO HIGH(x) DO s := s + x[i] END;
+    8    RETURN s
+    9  END Total;
+   10  END M;
+   11  VAR a : ARRAY [1 .. 4] OF INTEGER; ExitCode : INTEGER;
+   12  BEGIN
+   13    a[1] := 1; a[2] := 2; a[3] := 3; a[4] := 4;
+   14    ExitCode := M.Total(a)
+   15  END MOpen.
+
+    0 errors
+
+

+ 15 - 0
tests/m_open.mod

@@ -0,0 +1,15 @@
+MODULE MOpen;
+MODULE M EXPORT Total;
+PROCEDURE Total(x : ARRAY OF INTEGER) : INTEGER;
+VAR i, s : INTEGER;
+BEGIN
+  s := 0;
+  FOR i := 0 TO HIGH(x) DO s := s + x[i] END;
+  RETURN s
+END Total;
+END M;
+VAR a : ARRAY [1 .. 4] OF INTEGER; ExitCode : INTEGER;
+BEGIN
+  a[1] := 1; a[2] := 2; a[3] := 3; a[4] := 4;
+  ExitCode := M.Total(a)
+END MOpen.

+ 3 - 4
tests/m_bad_param.LST → tests/m_param.LST

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

+ 2 - 2
tests/m_bad_param.mod → tests/m_param.mod

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

+ 19 - 0
tests/m_varpar.LST

@@ -0,0 +1,19 @@
+Listing:
+
+    1  MODULE MVarPar;
+    2  MODULE M EXPORT Bump;
+    3  PROCEDURE Bump(VAR x : INTEGER);
+    4  BEGIN
+    5    x := x + 10
+    6  END Bump;
+    7  END M;
+    8  VAR v, ExitCode : INTEGER;
+    9  BEGIN
+   10    v := 5;
+   11    M.Bump(v);
+   12    ExitCode := v
+   13  END MVarPar.
+
+    0 errors
+
+

+ 13 - 0
tests/m_varpar.mod

@@ -0,0 +1,13 @@
+MODULE MVarPar;
+MODULE M EXPORT Bump;
+PROCEDURE Bump(VAR x : INTEGER);
+BEGIN
+  x := x + 10
+END Bump;
+END M;
+VAR v, ExitCode : INTEGER;
+BEGIN
+  v := 5;
+  M.Bump(v);
+  ExitCode := v
+END MVarPar.