Przeglądaj źródła

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

Eric Streit 1 miesiąc temu
rodzic
commit
4e53b4263b

BIN
M2c


+ 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
M2cP.o


BIN
MBadParam.MC4 → MBadArity.MC4


BIN
MBadFunc.MC4 → MBadMActual.MC4


BIN
MBadMFunc.MC4


BIN
MBadMVar.MC4


BIN
MBadNope.MC4


BIN
MBare.MC4


BIN
MFunc.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)

BIN
MGen.o


BIN
MOpen.MC4


BIN
MParam.MC4


BIN
MVarPar.MC4


+ 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

BIN
SymTab.o


+ 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.