<> <> <> DIRECTORY M2D USING [StrForm, ObjPtr, ConstPtr, VarPtr, ProcPtr, CodePtr, FieldPtr, StrPtr, EnumPtr, RangePtr, SetPtr, PointerPtr, ProcTypPtr, ArrayPtr, RecordPtr, ParPtr, WordSize, Proc, undftyp, notyp, inttyp, cardtyp, dbltyp, realtyp, bitstyp, chartyp, stringtyp, UNION], M2F USING [GenStParam, GenStFct], M2G USING [LabelTabPtr, LabelTable, NofCases, GenItem, GenSingSet, GenSet, GenTrap, GenIndex, GenField, GenDeRef, PrepCall, GenCall, GenParam], M2H USING [ItemPtr, Item, LoadAdr, Load, LoadStk, GenIn, GenOp, GenNeg, GenNot, GenAnd, GenOr], M2I USING [pc, AllocString], M2S USING [Symbol, sym, numtyp, intval, dblval, realval, id, GetSym, KeepId, Mark], M2T USING [Scope, LastObj, NewScope, NewObj, NewStr, NewPar, CloseScope, ParamLink, Find, FindExport, FindField], M2Q; M2QImpl: CEDAR PROGRAM IMPORTS M2D, M2F, M2G, M2H, M2I, M2S, M2T EXPORTS M2Q = BEGIN OPEN M2Q; MaxInt: CARDINAL = 77777B; EnumTypSize : CARDINAL = 1; SetTypSize: CARDINAL = 1; PointerTypSize: CARDINAL = 1; ProcTypSize: CARDINAL = 1; DynArrDesSize: CARDINAL = 2; dummyContxt: M2D.ProcPtr _ NEW [M2D.Proc _ [cell: 2]]; InitQ: PUBLIC PROC = {}; err: PROC [n: CARDINAL] = { M2S.Mark [n] }; CheckSym: PROC [s: M2S.Symbol, n: CARDINAL] = { IF M2S.sym = s THEN M2S.GetSym ELSE M2S.Mark [n] }; qualident: PROC RETURNS [obj: M2D.ObjPtr] = { -- sym = ident -- obj _ M2T.Find [M2S.id]; M2S.GetSym; WHILE (M2S.sym = period) AND (obj # NIL) AND (obj^.class = Module) DO M2S.GetSym; IF M2S.sym = ident THEN { obj _ M2T.FindExport [M2S.id, NARROW [obj^.ext]]; M2S.GetSym } ELSE err [10] ENDLOOP }; CheckComp: PROC [t0, t1: M2D.StrPtr] = { IF (t0 # t1) AND ((t0 # M2D.inttyp) OR (t1 # M2D.cardtyp)) THEN err [61] }; CaseLabelList: PUBLIC PROC [Ltyp: M2D.StrPtr, n: CARDINAL, tab: M2G.LabelTabPtr] RETURNS [N: CARDINAL] = { x: M2H.ItemPtr _ NEW [M2H.Item]; y: M2H.ItemPtr _ NEW [M2H.Item]; f: M2D.StrForm _ Ltyp^.form; IF f = Range THEN { range: M2D.RangePtr _ NARROW [Ltyp^.ext]; Ltyp _ range^.BaseTyp } ELSE IF (f > Int) AND (f # Enum) THEN err [38]; DO ConstExpression [x]; CheckComp [Ltyp, x.typ]; IF M2S.sym = ellipsis THEN { M2S.GetSym; ConstExpression [y]; CheckComp [Ltyp, y.typ] } ELSE y^ _ x^; <> IF n < M2G.NofCases THEN { i: CARDINAL _ n; DO IF i = 0 THEN EXIT; IF tab[i-1].low <= y.val.I THEN { IF tab[i-1].high >= x.val.I THEN err [62]; EXIT }; tab[i] _ tab[i-1]; i _ i-1 ENDLOOP; tab[i].low _ x.val.I; tab[i].high _ y.val.I; tab[i].label _ M2I.pc; n _ n + 1 } ELSE err [92]; IF M2S.sym = comma THEN M2S.GetSym ELSE IF (M2S.sym >= lparen) AND (M2S.sym <= ident) THEN err [11] ELSE EXIT ENDLOOP; N _ n }; FieldListSequence: PROC [adr: CARDINAL] RETURNS [maxAdr: CARDINAL] = {fld0, fld1, tagfldtyp: M2D.ObjPtr; typ: M2D.StrPtr; VariantPart: PROC = { tabPtr: M2G.LabelTabPtr _ NEW [M2G.LabelTable]; lastadr: CARDINAL; N: CARDINAL; maxAdr _ adr; N _ 0; DO IF M2S.sym < bar THEN { N _ CaseLabelList [typ, N, tabPtr]; CheckSym [colon, 13]; lastadr _ FieldListSequence [adr]; IF lastadr > maxAdr THEN maxAdr _ lastadr }; IF M2S.sym = bar THEN M2S.GetSym ELSE EXIT ENDLOOP; IF M2S.sym = else THEN { M2S.GetSym; lastadr _ FieldListSequence [adr]; IF lastadr > maxAdr THEN maxAdr _ lastadr }}; typ _ M2D.undftyp; IF (M2S.sym = ident) OR (M2S.sym = case) THEN DO IF M2S.sym = ident THEN { fld0 _ M2T.LastObj []; fld1 _ fld0; DO IF M2S.sym = ident THEN { fld1 _ M2T.NewObj [M2S.id, Field]; M2S.KeepId; M2S.GetSym } ELSE err [10]; IF M2S.sym = comma THEN M2S.GetSym ELSE IF M2S.sym = ident THEN err [11] ELSE EXIT ENDLOOP; CheckSym [colon, 13]; typ _ Type []; WHILE fld0 # fld1 DO fld0 _ fld0^.next; { field: M2D.FieldPtr _ NARROW [fld0^.ext]; fld0^.typ _ typ; field^.offset _ adr }; adr _ adr + typ^.size ENDLOOP } ELSE IF M2S.sym = case THEN { M2S.GetSym; fld1 _ NIL; tagfldtyp _ NIL; IF M2S.sym = ident THEN { fld1 _ M2T.NewObj [M2S.id, Field]; M2S.KeepId; M2S.GetSym }; CheckSym [colon, 13]; IF M2S.sym = ident THEN tagfldtyp _ qualident [] ELSE err [10]; IF (tagfldtyp # NIL) AND (tagfldtyp^.class = Typ) THEN typ _ tagfldtyp^.typ ELSE err [52]; IF fld1 # NIL THEN { field: M2D.FieldPtr _ NARROW [fld1^.ext]; field^.offset _ adr; fld1^.typ _ typ; adr _ adr + typ^.size }; CheckSym [of, 23]; VariantPart; adr _ maxAdr; CheckSym [end, 20] }; IF M2S.sym = semicolon THEN M2S.GetSym ELSE IF M2S.sym = ident THEN err [12] ELSE EXIT ENDLOOP; maxAdr _ adr }; SubRange: PROC RETURNS [typ: M2D.StrPtr] = { x: M2H.ItemPtr _ NEW [M2H.Item]; y: M2H.ItemPtr _ NEW [M2H.Item]; f: M2D.StrForm; range: M2D.RangePtr _ NIL; typ _ M2T.NewStr [Range]; range _ NARROW [typ^.ext]; ConstExpression [x]; f _ x^.typ^.form; IF (f <= Int) OR (f = Enum) THEN range^.min _ x^.val.I ELSE err [82]; CheckSym [ellipsis, 21]; ConstExpression [y]; CheckComp [x^.typ, y^.typ]; IF (y^.typ = M2D.cardtyp) AND (y^.val.C > MaxInt) THEN err [95]; range^.max _ y^.val.I; IF range^.min > range^.max THEN err [63]; range^.BaseTyp _ x^.typ; typ^.size _ x^.typ^.size }; SimpleType: PROC RETURNS [typ: M2D.StrPtr] = { obj: M2D.ObjPtr; typ0: M2D.StrPtr; n: CARDINAL; range: M2D.RangePtr _ NIL; enum: M2D.EnumPtr _ NIL; typ _ M2D.undftyp; IF M2S.sym = ident THEN { obj _ qualident []; IF (obj # NIL) AND (obj^.class = Typ) THEN typ _ obj^.typ ELSE err [52]; IF M2S.sym = lbrak THEN { M2S.GetSym; typ0 _ typ; typ _ SubRange []; range _ NARROW [typ^.ext]; IF range^.BaseTyp # typ0 THEN IF (typ0 = M2D.inttyp) AND(range^.BaseTyp = M2D.cardtyp) THEN range^.BaseTyp _ M2D.inttyp ELSE err [61]; IF M2S.sym = rbrak THEN M2S.GetSym ELSE { err [16]; IF M2S.sym = rparen THEN M2S.GetSym }}} ELSE IF M2S.sym = lparen THEN { M2S.GetSym; typ _ M2T.NewStr [Enum]; enum _ NARROW [typ^.ext]; obj _ NIL; n _ 0; DO const: M2D.ConstPtr _ NIL; IF M2S.sym = ident THEN { obj _ M2T.NewObj [M2S.id, Const]; M2S.KeepId; const _ NARROW [obj^.ext]; const^.conval.C _ n; n _ n + 1; obj^.typ _ typ; M2S.GetSym } ELSE err [10]; IF M2S.sym = comma THEN M2S.GetSym ELSE IF M2S.sym = ident THEN err [11] ELSE EXIT ENDLOOP; enum^.NofConst _ n; typ^.size _ EnumTypSize; CheckSym [rparen, 15] } ELSE IF M2S.sym = lbrak THEN { M2S.GetSym; typ _ SubRange []; IF M2S.sym = rbrak THEN M2S.GetSym ELSE { err [16]; IF M2S.sym = rparen THEN M2S.GetSym }} ELSE err [32] }; FormalType: PUBLIC PROC RETURNS [typ: M2D.StrPtr] = { objtyp: M2D.ObjPtr; array: M2D.ArrayPtr _ NIL; typ _ M2D.undftyp; IF M2S.sym = array THEN { M2S.GetSym; typ _ M2T.NewStr [Array]; array _ NARROW [typ^.ext]; typ^.strobj _ NIL; typ^.size _ DynArrDesSize; array^.dyn _ TRUE; CheckSym [of, 23]; IF M2S.sym = ident THEN { objtyp _ qualident []; IF (objtyp # NIL) AND (objtyp^.class = Typ) THEN array^.ElemTyp _ objtyp^.typ ELSE err [52] } ELSE err [10] } ELSE IF M2S.sym = ident THEN { objtyp _ qualident []; IF (objtyp # NIL) AND (objtyp^.class = Typ) THEN typ _ objtyp^.typ ELSE err [52] } ELSE err [10] }; FormalTypeList: PROC [proctyp: M2D.ProcTypPtr] = { obj: M2D.ObjPtr; partyp: M2D.StrPtr; isvar: BOOLEAN; IF (M2S.sym = ident) OR (M2S.sym = var) OR (M2S.sym = array) THEN DO IF M2S.sym = var THEN { M2S.GetSym; isvar _ TRUE } ELSE isvar _ FALSE; partyp _ FormalType []; M2T.NewPar [partyp, isvar]; IF M2S.sym = comma THEN M2S.GetSym ELSE IF M2S.sym = ident THEN err [11] ELSE EXIT ENDLOOP; CheckSym [rparen, 15]; proctyp^.firstPar _ M2T.ParamLink []; IF M2S.sym = colon THEN { M2S.GetSym; proctyp^.resTyp _ M2D.undftyp; IF M2S.sym = ident THEN { obj _ qualident []; IF (obj # NIL) AND (obj^.class = Typ) THEN proctyp^.resTyp _ obj^.typ ELSE err [52] } ELSE err [10] } ELSE proctyp^.resTyp _ M2D.notyp }; ArrayType: PROC RETURNS [typ: M2D.StrPtr] = { a, b: INTEGER; array: M2D.ArrayPtr _ NIL; typ _ M2T.NewStr [Array]; array _ NARROW [typ^.ext]; array^.dyn _ FALSE; a _ 0; array^.IndexTyp _ SimpleType []; IF array^.IndexTyp^.form = Range THEN { range: M2D.RangePtr _ NARROW [array^.IndexTyp^.ext]; a _ range^.min; b _ range^.max } ELSE { err [94]; b _ 0 }; IF M2S.sym = of THEN { M2S.GetSym; array^.ElemTyp _ Type [] } ELSE IF M2S.sym = comma THEN { M2S.GetSym; array^.ElemTyp _ ArrayType [] } ELSE { err [23]; array^.ElemTyp _ M2D.undftyp }; a _ b-a+1; b _ array^.ElemTyp^.size; IF array^.ElemTyp^.form = Char THEN {} ELSE IF MaxInt / b >= a THEN a _ a*b ELSE { err [210]; a _ 1 }; typ^.size _ a }; OpaqueType: PUBLIC PROC RETURNS [typ: M2D.StrPtr] = { typ _ M2T.NewStr [Opaque]; typ^.size _ PointerTypSize }; Type: PUBLIC PROC RETURNS [typ: M2D.StrPtr] = { obj: M2D.ObjPtr; btyp: M2D.StrPtr; IF M2S.sym < lparen THEN { err [33]; DO M2S.GetSym; IF M2S.sym >= lparen THEN EXIT ENDLOOP }; IF M2S.sym = array THEN { M2S.GetSym; typ _ ArrayType [] } ELSE IF M2S.sym = record THEN { record: M2D.RecordPtr _ NIL; M2S.GetSym; typ _ M2T.NewStr [Record]; record _ NARROW [typ^.ext]; obj _ M2T.NewScope [Typ]; -- header -- typ^.size _ FieldListSequence [0]; record^.firstFld _ obj^.next; CheckSym [end, 20]; M2T.CloseScope } ELSE IF M2S.sym = set THEN { set: M2D.SetPtr _ NIL; M2S.GetSym; CheckSym [of, 23]; typ _ M2T.NewStr [Set]; set _ NARROW [typ^.ext]; set^.BaseTyp _ SimpleType []; btyp _ set^.BaseTyp; IF btyp^.form = Enum THEN { enum: M2D.EnumPtr _ NARROW [btyp^.ext]; IF enum^.NofConst > M2D.WordSize THEN err [209] } ELSE IF btyp^.form = Range THEN { range: M2D.RangePtr _ NARROW [btyp^.ext]; IF (range^.min < 0) OR (range^.max >= M2D.WordSize) THEN err [209] } ELSE err [60]; typ^.size _ SetTypSize } ELSE IF M2S.sym = pointer THEN { pointer: M2D.PointerPtr _ NIL; M2S.GetSym; typ _ M2T.NewStr [Pointer]; pointer _ NARROW [typ^.ext]; pointer^.BaseId _ 0; typ^.size _ PointerTypSize; CheckSym [to, 24]; IF M2S.sym = ident THEN { obj _ qualident []; IF obj = NIL THEN { pointer^.BaseTyp _ M2D.undftyp; pointer^.BaseId _ M2S.id; M2S.KeepId-- forward ref --} ELSE IF obj^.class = Typ THEN pointer^.BaseTyp _ obj^.typ ELSE err [52] } ELSE pointer^.BaseTyp _ Type [] } ELSE IF M2S.sym = procedure THEN { proctyp: M2D.ProcTypPtr; M2S.GetSym; typ _ M2T.NewStr [ProcTyp]; proctyp _ NARROW[typ^.ext]; typ^.size _ ProcTypSize; IF M2S.sym = lparen THEN { M2S.GetSym; FormalTypeList [proctyp] } ELSE proctyp^.resTyp _ NIL } ELSE typ _ SimpleType []; IF (M2S.sym < semicolon) OR (M2S.sym > else) THEN { err [34]; WHILE (M2S.sym < ident) OR (M2S.sym > else) AND (M2S.sym < begin) DO M2S.GetSym ENDLOOP }}; Selector: PUBLIC PROC [x: M2H.ItemPtr, obj: M2D.ObjPtr] = { y: M2H.ItemPtr _ NEW [M2H.Item _ [contxt: x^.contxt]]; M2G.GenItem [x, obj, M2T.Scope]; DO IF M2S.sym = lbrak THEN { M2S.GetSym; DO M2H.LoadAdr [x]; Expression [y]; M2G.GenIndex [x, y]; IF M2S.sym = comma THEN M2S.GetSym ELSE EXIT ENDLOOP; CheckSym [rbrak, 16] } ELSE IF M2S.sym = period THEN { M2S.GetSym; IF M2S.sym = ident THEN { IF (x^.typ # NIL) AND (x^.typ^.form = Record) THEN { obj _ M2T.FindField [M2S.id, NARROW[x^.typ^.ext]]; M2G.GenField [x, obj] } ELSE err [57]; M2S.GetSym } ELSE err [10] } ELSE IF M2S.sym = arrow THEN { M2S.GetSym; M2G.GenDeRef [x] } ELSE EXIT ENDLOOP }; FormalParameters: PUBLIC PROC [proc: M2D.ProcPtr] = { isvar: BOOLEAN; par, par0: M2D.ObjPtr; typ0: M2D.StrPtr; proc^.cell _ 0; proc^.adr _ 0; IF (M2S.sym = ident) OR (M2S.sym = var) THEN DO par0 _ M2T.LastObj []; isvar _ FALSE; IF M2S.sym = var THEN { M2S.GetSym; isvar _ TRUE }; DO IF M2S.sym = ident THEN { par _ M2T.NewObj [M2S.id, Var]; M2S.KeepId; M2S.GetSym } ELSE err [10]; IF M2S.sym = comma THEN M2S.GetSym ELSE IF M2S.sym = ident THEN err [11] ELSE IF M2S.sym = var THEN { err [11]; M2S.GetSym } ELSE EXIT ENDLOOP; CheckSym [colon, 13]; typ0 _ FormalType []; par0 _ par0^.next; WHILE par0 # NIL DO var0: M2D.VarPtr _ NARROW [par0^.ext]; par0^.typ _ typ0; var0^.mod _ 0; var0^.lev _ proc^.lev; var0^.varpar _ isvar; IF proc^.cell >= 14 THEN { err [99]; proc^.cell _ 0 }; var0^.cell _ proc^.cell; proc^.cell _ proc^.cell + 1; IF typ0^.form = Array THEN { array: M2D.ArrayPtr _ NARROW [typ0^.ext]; IF array^.dyn THEN { IF proc^.cell >= 14 THEN { err [99]; proc^.cell _ 0 }; proc^.cell _ proc^.cell + 1 } -- size ELSE IF NOT isvar THEN proc^.adr _ proc^.adr + typ0^.size } ELSE IF (typ0^.form = Record) AND NOT isvar THEN proc^.adr _ proc^.adr + typ0^.size; par0 _ par0^.next ENDLOOP; IF M2S.sym = semicolon THEN M2S.GetSym ELSE IF M2S.sym = ident THEN err [12] ELSE EXIT ENDLOOP; CheckSym [rparen, 15] }; ActualParameters: PUBLIC PROC [x: M2H.ItemPtr] = { apar: M2H.ItemPtr _ NEW [M2H.Item _ [contxt: x^.contxt]]; fpar: M2D.ParPtr _ M2G.PrepCall [x]; IF M2S.sym # rparen THEN DO Expression [apar]; IF fpar # NIL THEN { M2G.GenParam [apar, fpar]; x^.expRegs _ M2D.UNION [x^.expRegs, apar^.expRegs]; fpar _ fpar^.next } ELSE err [64]; IF M2S.sym = comma THEN M2S.GetSym ELSE IF (M2S.sym >= lparen) AND (M2S.sym <= ident) THEN err [11] ELSE EXIT ENDLOOP; IF fpar = NIL THEN M2G.GenCall [x] ELSE err [65] }; StandProcCall: PUBLIC PROC [p: M2H.ItemPtr] = { code: M2D.CodePtr _ NARROW [p^.obj^.ext]; m: CARDINAL _ code^.num; n: CARDINAL; x: M2H.ItemPtr _ NEW [M2H.Item _ [contxt: p^.contxt]]; IF m = 1 THEN { M2G.GenTrap [10]; p^.typ _ M2D.notyp } ELSE { CheckSym [lparen, 22]; n _ 0; DO Expression [x]; M2F.GenStParam [p, x, m, n]; n _ n + 1; IF M2S.sym = comma THEN M2S.GetSym ELSE IF M2S.sym # ident THEN EXIT ENDLOOP; CheckSym [rparen, 15]; M2F.GenStFct [p, m, n] }}; Element: PROC [x: M2H.ItemPtr] = { e1: M2H.ItemPtr _ NEW [M2H.Item _ [contxt: x^.contxt]]; e2: M2H.ItemPtr _ NEW [M2H.Item _ [contxt: x^.contxt]]; Expression [e1]; IF M2S.sym = ellipsis THEN { M2S.GetSym; IF e1^.mode = conMd THEN { Expression [e2]; IF e2^.mode # conMd THEN err [90] } ELSE { M2H.Load [e1]; Expression [e2] }; M2G.GenSet [x, e1, e2] } ELSE M2G.GenSingSet [x, e1] }; Sets: PROC [x: M2H.ItemPtr, styp: M2D.StrPtr] = { y: M2H.ItemPtr _ NEW [M2H.Item _ [contxt: x^.contxt]]; x^.typ _ styp; y^.typ _ styp; IF M2S.sym # rbrace THEN { Element [x]; DO IF M2S.sym = comma THEN M2S.GetSym ELSE IF (M2S.sym >= lparen) AND (M2S.sym <= ident) THEN err [11] ELSE EXIT; M2H.Load [x]; Element [y]; M2H.Load [y]; M2H.GenOp [plus, x, y] ENDLOOP } ELSE { x^.mode _ conMd; x^.val.S _ ALL [FALSE] }; CheckSym [rbrace, 17] }; Factor: PROC [x: M2H.ItemPtr] = { obj: M2D.ObjPtr; xt: M2D.StrPtr; IF M2S.sym < lparen THEN { err [31]; DO M2S.GetSym; IF M2S.sym >= lparen THEN EXIT ENDLOOP }; IF M2S.sym = ident THEN { obj _ qualident []; IF M2S.sym = lbrace THEN { M2S.GetSym; IF (obj # NIL) AND (obj^.class = Typ) AND (obj^.typ^.form = Set) THEN Sets [x, obj^.typ] ELSE { err [52]; Sets [x, M2D.bitstyp] }} ELSE { Selector [x, obj]; IF x^.mode = codMd THEN { code: M2D.CodePtr _ NARROW [x^.obj^.ext]; IF code^.num > 0 THEN StandProcCall [x] } ELSE IF M2S.sym = lparen THEN { M2S.GetSym; IF x^.mode = typMd THEN -- type transfer function -- { xt _ x^.typ; Expression [x]; M2H.Load [x]; IF xt^.size # x.typ^.size THEN err [81]; x^.typ _ xt } ELSE ActualParameters [x]; CheckSym [rparen, 15] }}} ELSE IF M2S.sym = number THEN { M2S.GetSym; x^.mode _ conMd; SELECT M2S.numtyp FROM cardint => { x^.typ _ M2D.cardtyp; x^.val.C _ M2S.intval }; longint => { x^.typ _ M2D.dbltyp; x^.val.D _ M2S.dblval }; char => { x^.typ _ M2D.chartyp; x^.val.C _ M2S.intval }; real => { x^.typ _ M2D.realtyp; x^.val.R _ M2S.realval }; longreal => { x^.typ _ M2D.realtyp; x^.val.R _ M2S.realval } ENDCASE } ELSE IF M2S.sym = string THEN { x^.typ _ M2D.stringtyp; x^.mode _ conMd; [ x^.val.D0, x^.val.D1 ] _ M2I.AllocString [M2S.id]; M2S.GetSym } ELSE IF M2S.sym = lparen THEN { M2S.GetSym; Expression [x]; CheckSym [rparen, 15] } ELSE IF M2S.sym = lbrace THEN { M2S.GetSym; Sets [x, M2D.bitstyp] } ELSE IF M2S.sym = not THEN { M2S.GetSym; Factor [x]; M2H.GenNot [x] } ELSE { err [31]; x^.typ _ M2D.undftyp; x^.mode _ stkMd }}; Term: PROC [x: M2H.ItemPtr] = { y: M2H.ItemPtr _ NEW [M2H.Item _ [contxt: x^.contxt]]; mulop: M2S.Symbol; Factor [x]; WHILE (M2S.sym >= times) AND (M2S.sym <= and) DO mulop _ M2S.sym; M2S.GetSym; IF x^.mode # conMd THEN IF x^.typ^.form = Set THEN M2H.Load [x] ELSE M2H.LoadStk [x]; IF mulop = and THEN M2H.GenAnd [x]; Factor [y]; IF y^.mode # conMd THEN IF y^.typ^.form = Set THEN M2H.Load [y] ELSE M2H.LoadStk [y]; M2H.GenOp [mulop, x, y] ENDLOOP }; SimpleExpression: PROC [x: M2H.ItemPtr] = { y: M2H.ItemPtr _ NEW [M2H.Item _ [contxt: x^.contxt]]; addop: M2S.Symbol; IF M2S.sym = minus THEN { M2S.GetSym; Term [x]; M2H.GenNeg [x] } ELSE { IF M2S.sym = plus THEN M2S.GetSym; Term [x] }; WHILE (M2S.sym >= plus) AND (M2S.sym <= or) DO addop _ M2S.sym; M2S.GetSym; IF addop = or THEN { IF x^.mode # conMd THEN M2H.LoadStk [x]; M2H.GenOr [x]; Term [y]; IF y^.mode # conMd THEN M2H.LoadStk [y] } ELSE { M2H.Load [x]; Term [y]; M2H.Load [y] }; M2H.GenOp [addop, x, y] ENDLOOP }; Expression: PUBLIC PROC [x: M2H.ItemPtr] = { y: M2H.ItemPtr _ NEW [M2H.Item _ [contxt: x^.contxt]]; relation: M2S.Symbol; SimpleExpression [x]; IF (M2S.sym >= eql) AND (M2S.sym <= geq) THEN { relation _ M2S.sym; M2S.GetSym; IF x^.mode # conMd THEN IF x^.typ^.form = Set THEN M2H.Load [x] ELSE M2H.LoadStk [x]; SimpleExpression [y]; IF y^.mode # conMd THEN M2H.Load [y]; M2H.GenOp [relation, x, y] } ELSE IF M2S.sym = in THEN { M2S.GetSym; IF x^.mode # conMd THEN M2H.LoadStk [x]; SimpleExpression [y]; M2H.Load [y]; M2H.GenIn [x, y] }}; ConstExpression: PUBLIC PROC [x: M2H.ItemPtr] = { x^.contxt _ dummyContxt; Expression [x]; IF x^.mode # conMd THEN { err [44]; x^.mode _ conMd; x^.val.C _ 1 }}; END.