|
|
@@ -0,0 +1,830 @@
|
|
|
+(* STATEMEN.MOD — DRAFT v1, assembled 2026-10-03, NOT verified.
|
|
|
+ Reconstructed from Reversing-Turbo-Modula2-main/MCode_disassembly/statement.txt
|
|
|
+ (1793 lines) by two parallel passes (group 1 @0001-0566, group 2 @0566-end).
|
|
|
+ Does NOT yet recompile to the original MCD; verification via unassemble.c
|
|
|
+ diff is still required (see src/compiler/README.md).
|
|
|
+
|
|
|
+ FRAME MECHANICS (proven from MCode_specification/Stack.mod +
|
|
|
+ Instruction.mod + Extended.mod, settles all arg-order disputes):
|
|
|
+ - Callers push args in source order (spec Extended.Move pops size,dst,src).
|
|
|
+ - NewFrame pushes oldFP,outerFP above retAddr; fp^[0]=outerFP, [1]=oldFP,
|
|
|
+ [2]=retAddr, [3]=LAST pushed word. Opcode 03H..07H = LoadParam(3..7), and
|
|
|
+ the disassembler prints fp^[3] as "param1". Hence "param1" = LAST pushed
|
|
|
+ word (modulo multi-word/VAR params: SYMTAB proc8 SymbolAssert reads
|
|
|
+ "param2"=cond,"param1"=code for source (cond, code) — consistent).
|
|
|
+ - Consequence: a body reading "param1"=first-formal is backwards; the
|
|
|
+ correct source order is first-pushed=formal1. Call sites reconstructed
|
|
|
+ from pushes are order-correct as written.
|
|
|
+ - Proven by this: Express proc9 @02be tests `IN param2` and reports via
|
|
|
+ ERRORS.proc14(param2, X, param1)=(want,got,ctx); STMT @05d9 pushes
|
|
|
+ (512, 43): (allowed={9}, code=43) is the only sane reading, so
|
|
|
+ Express.MatchOpClass is (allowed, errCode) — NOT (errCode, allowed) as
|
|
|
+ EXPRESS.MOD draft v1 declares. FIX APPLIED HERE (call shapes unchanged);
|
|
|
+ EXPRESS.MOD's own declaration still needs the same swap (next edit).
|
|
|
+ - Same proof: Express.proc1 takes (cond, code) — STMT @058a shows
|
|
|
+ [bool,20] with code on top. EXPRESS.MOD's 1-param CentralError FORWARD
|
|
|
+ is stale; widened here via Express.CentralError(ok, code) usage and
|
|
|
+ flagged there.
|
|
|
+
|
|
|
+ CORRECTIONS to docs/compiler/60-frontend.md + FRONTEND.md (body-proven):
|
|
|
+ - proc5 = CASE (jump table via EmitWord, OF, `|`, ELSE), proc6 = FOR
|
|
|
+ (`:=`/TO/BY, control-var checks) — the map had them swapped.
|
|
|
+ - STMT dispatch: 121 Loop, 122 Exit, 123 Result, 124 If, 125 For,
|
|
|
+ 126 Repeat, 127 While, 128 With, 129 Return, 130 Case (125 = CASE default).
|
|
|
+ - TWO case-shaped procedures exist: proc5 (STMT-driven, full jump-table
|
|
|
+ parser) vs proc16 (BODY-driven via Accept(14), label-table emitter).
|
|
|
+ Kept distinct: ParseCaseStmt vs ParseCaseTail. Why BODY re-enters case
|
|
|
+ parsing on symbol 14 is unexplained — MCD diff must decide.
|
|
|
+ - 123/129 = RESULT/RETURN inferred from store-vs-epilogue behavior.
|
|
|
+
|
|
|
+ CONVENTIONS: Words(X)^[N] = numeric-word pun on ADDRESS/T1 handles
|
|
|
+ (MCode is untyped; original emissive code TBD). GOTO kept as faithful
|
|
|
+ jump rendering (restructure to LOOP/EXIT in verification).
|
|
|
+ Scanner.word22/word23/word25 read as codeSize/listingEnabled/tokenPos
|
|
|
+ (SCANNER.DEF positional mapping; listingEnabled assignments flagged).
|
|
|
+ BITSET{..} literal sets on CARDINAL curSymbol kept verbatim (cast TBD). *)
|
|
|
+
|
|
|
+IMPLEMENTATION MODULE Statemen;
|
|
|
+IMPORT Compiler, Scanner, Errors, CodeGen, Express, SymTab, Files, Texts, Loader;
|
|
|
+FROM SYSTEM IMPORT ADDRESS, ADR, MOVE, WORD;
|
|
|
+FROM STORAGE IMPORT MARK, RELEASE;
|
|
|
+
|
|
|
+TYPE Words = POINTER TO ARRAY [0..15] OF WORD;
|
|
|
+
|
|
|
+VAR
|
|
|
+ needEpilogue: CARDINAL; (* word2: set from body-nonEmpty + tail paths *)
|
|
|
+ withPending: CARDINAL; (* word3: nonzero = with-base load pending *)
|
|
|
+ nestDepth: CARDINAL; (* word4: LOOP/CASE/FOR nesting depth *)
|
|
|
+ exitDepth: CARDINAL; (* word5: LOOP-entry depth for EXIT (= group2 loopExitMark) *)
|
|
|
+ curBlockNode: ADDRESS; (* word6: BODY param1 (= group1 curRoutine) *)
|
|
|
+ caseActive: CARDINAL; (* word7: proc16 sets 1 (= group1 caseSeen) *)
|
|
|
+ withDesc: ADDRESS; (* word8: pending operand for EmitStandardOp(25) *)
|
|
|
+ exitEmitted: CARDINAL; (* word9: proc17 sets 1 *)
|
|
|
+
|
|
|
+(* ---- helpers shared across both groups ---- *)
|
|
|
+PROCEDURE ReserveWords(n: CARDINAL): ADDRESS; FORWARD; (* FIXME: = Scanner.Allocate? *)
|
|
|
+PROCEDURE MoveWords(dst, src: ADDRESS; words: CARDINAL); FORWARD; (* FIXME: = MOVE? *)
|
|
|
+(* ---- group-1 procedures (FORWARDs; bodies below) ---- *)
|
|
|
+PROCEDURE CalcMemOffset(): CARDINAL; FORWARD;
|
|
|
+PROCEDURE SyncToStatStart; FORWARD;
|
|
|
+PROCEDURE ParseCaseStmt; FORWARD;
|
|
|
+PROCEDURE ParseFor; FORWARD;
|
|
|
+PROCEDURE ParseWhile; FORWARD;
|
|
|
+PROCEDURE ParseRepeat; FORWARD;
|
|
|
+PROCEDURE ParseIf; FORWARD;
|
|
|
+PROCEDURE ParseLoop; FORWARD;
|
|
|
+PROCEDURE ParseExit; FORWARD;
|
|
|
+PROCEDURE ParseResult; FORWARD;
|
|
|
+PROCEDURE ParseWith; FORWARD;
|
|
|
+PROCEDURE ParseReturn; FORWARD;
|
|
|
+(* ---- group-2 procedures (FORWARDs; bodies below) ---- *)
|
|
|
+PROCEDURE NextSymWrap; FORWARD;
|
|
|
+PROCEDURE ParseStatSeqLoop(stop: BITSET): BOOLEAN; FORWARD;
|
|
|
+PROCEDURE EmitJumpFixup; FORWARD;
|
|
|
+PROCEDURE ParseStatement; FORWARD;
|
|
|
+PROCEDURE GuardedStatSeq(follow: BITSET): BOOLEAN; FORWARD;
|
|
|
+PROCEDURE ParseCaseTail; FORWARD;
|
|
|
+PROCEDURE CloseBlockChain(VAR node: ADDRESS); FORWARD;
|
|
|
+PROCEDURE EmitNameHash(VAR name: ARRAY OF CHAR); FORWARD;
|
|
|
+PROCEDURE EmitComBytes; FORWARD;
|
|
|
+PROCEDURE ParseBeginBlock(tag: CARDINAL; VAR rest: CARDINAL); FORWARD;
|
|
|
+
|
|
|
+(* STATEMEN group 1 — procedures @0001-0566 *)
|
|
|
+
|
|
|
+(* proc2 @0001 — ~CalcMemOffset. 0 params: reads curBlockNode global *)
|
|
|
+PROCEDURE CalcMemOffset(): CARDINAL;
|
|
|
+VAR p, q: ADDRESS;
|
|
|
+ flag: CARDINAL;
|
|
|
+BEGIN
|
|
|
+ {/* 0001 */}
|
|
|
+ p := Words(curBlockNode)^[6]; (*{0003-0005}*)
|
|
|
+ IF p = NIL THEN (*{0006-0008} *)
|
|
|
+ RETURN 0; (*{000a-000b} *)
|
|
|
+ END;
|
|
|
+ WHILE Words(p)^[0] # NIL DO (*{000d-0010} *)
|
|
|
+ p := Words(p)^[0]; (*{0012-0014}*)
|
|
|
+ END;
|
|
|
+ q := Words(p)^[2]; (*{0017-0019}*)
|
|
|
+ IF (Words(q)^[4] > 9) OR (4 IN Words(p)^[3]) THEN (*{001a-0024} *)
|
|
|
+ flag := 1; (*{0026-0027} *)
|
|
|
+ ELSE
|
|
|
+ flag := (Words(q)^[3] + 1) DIV 2; (*{002a-002f} shr 1 *)
|
|
|
+ END;
|
|
|
+ RETURN Words(p)^[5] DIV 2 + flag - 3; (*{0030-0038} *)
|
|
|
+END CalcMemOffset;
|
|
|
+
|
|
|
+(* proc3 @003b — ~SyncToStatStart *)
|
|
|
+PROCEDURE SyncToStatStart;
|
|
|
+BEGIN
|
|
|
+ {/* 003b */}
|
|
|
+ IF Express.spillFlag # 0 THEN (*{003d-0040} *)
|
|
|
+ IF withPending # 0 THEN (*{0042-0043} *)
|
|
|
+ Express.PushOperand(withDesc); (*{0045-0046} FIXME: 1-arg vs 0-arg FORWARD *)
|
|
|
+ CodeGen.EmitStandardOp(25); (*{0048-004a} *)
|
|
|
+ END;
|
|
|
+ IF Words(curBlockNode)^[2] = NIL THEN (*{004c-004f}*)
|
|
|
+ CodeGen.EmitMiscOp(0, (*{0051-0052} *)
|
|
|
+ CalcMemOffset() + ORD(Express.spillFlag = 1) * 128); (*{0053-005a} shl 7 *)
|
|
|
+ ELSIF 8 IN Scanner.scanOptions THEN (*{005e-0062} *)
|
|
|
+ CodeGen.QueueConst(9); (*{0064-0065} *)
|
|
|
+ CodeGen.QueueConst(0); (*{0067-0068} *)
|
|
|
+ CodeGen.QueueConst(0); (*{006a-006b} *)
|
|
|
+ CodeGen.EmitStandardOp(14); (*{006d-006e} *)
|
|
|
+ END;
|
|
|
+ ELSE (*{0072} *)
|
|
|
+ CodeGen.EmitMiscOp(5, 2); (*{0073-0074} *)
|
|
|
+ END;
|
|
|
+END SyncToStatStart;
|
|
|
+
|
|
|
+(* proc5 @0078, STMT case 130 — ParseCaseStmt. Selector + OF + label ranges
|
|
|
+ with jump-table emission, `|`-separated arms, ELSE. *)
|
|
|
+PROCEDURE ParseCaseStmt;
|
|
|
+VAR head: ADDRESS;
|
|
|
+ chain: ADDRESS;
|
|
|
+ buf: ADDRESS;
|
|
|
+ tail: ADDRESS;
|
|
|
+ prev: ADDRESS;
|
|
|
+ selTyp: ADDRESS;
|
|
|
+ lo: CARDINAL;
|
|
|
+ hi: CARDINAL;
|
|
|
+ endFix: CARDINAL;
|
|
|
+ topFix: ADDRESS;
|
|
|
+ armFix: CARDINAL;
|
|
|
+BEGIN
|
|
|
+ INC(nestDepth); (*{007a-007d} *)
|
|
|
+ Express.BoolCondHelper; (*{007d} parse CASE selector *)
|
|
|
+ Express.MatchOpClass(7, 40); (*{007f-0082} *)
|
|
|
+ selTyp := Express.curDesc.raw[0]; (*{0084-0087} FIXME: typ pun *)
|
|
|
+ Scanner.ExpectSymbol(41); (*{0088-008a} OF *)
|
|
|
+ CodeGen.EmitSystemCall(21); (*{008c-008e} *)
|
|
|
+ CodeGen.EmitStandardOp(15); (*{008f-0092} jump to dispatch *)
|
|
|
+ CodeGen.OpenFixup(topFix, TRUE); (*{0094-0097} *)
|
|
|
+ head := NIL; (*{0099-009a} *)
|
|
|
+ tail := NIL; (*{009b-009c} *)
|
|
|
+ WHILE NOT (Scanner.curSymbol IN BITSET{8,10,13}) DO (*{009d-00a4} *)
|
|
|
+ armFix := CodeGen.MarkCodePos(14); (*{00a6-00aa} *)
|
|
|
+ Express.GetTypeDesc(selTyp, ADR(lo), ADR(hi)); (*{00ac-00b1} FIXME: (dest,mode,src) roles *)
|
|
|
+ prev := NIL; (*{00b3-00b4} *)
|
|
|
+ chain := head; (*{00b5-00b6} *)
|
|
|
+ WHILE (chain # NIL) AND (Words(chain)^[1] < lo) DO (*{00b7-00be} *)
|
|
|
+ prev := chain; (*{00c1-00c2} *)
|
|
|
+ chain := Words(chain)^[0]; (*{00c3-00c6} *)
|
|
|
+ END;
|
|
|
+ Scanner.Allocate(buf, 6); (*{00c8-00cb} *)
|
|
|
+ Words(buf)^[0] := chain; (*{00cd-00cf} *)
|
|
|
+ Words(buf)^[1] := hi; (*{00d0-00d2} *)
|
|
|
+ Words(buf)^[2] := armFix; (*{00d3-00d6} *)
|
|
|
+ IF (chain # NIL) AND (Words(chain)^[1] = 0) THEN (*{00d7-00d9} *)
|
|
|
+ tail := buf; (*{00db-00dc} *)
|
|
|
+ END;
|
|
|
+ IF (chain # NIL) AND (Words(chain)^[1] > hi) THEN (*{00df-00e2} *)
|
|
|
+ Express.CentralError(FALSE, 47); (*{00e3-00e5} *)
|
|
|
+ END;
|
|
|
+ chain := buf; (*{00e7-00e8} *)
|
|
|
+ DEC(hi); (*{00e9-00eb} *)
|
|
|
+ WHILE hi >= lo DO (*{00ec-00ef} expand label range; duplicate check TBD *)
|
|
|
+ END;
|
|
|
+ IF prev # NIL THEN (*{00f1-00f3} *)
|
|
|
+ Words(prev)^[0] := buf; (*{00f5-00f8} *)
|
|
|
+ ELSE
|
|
|
+ head := buf; (*{00fa-00fb} *)
|
|
|
+ END;
|
|
|
+ Scanner.TestSymbolInSet(BITSET{1,2}); (*{00fc-00fd} `,`/`:` *)
|
|
|
+ IF Scanner.AcceptSymbol(1) THEN (*{00ff-0100} `,`: another label, loop to 00ac *)
|
|
|
+ END;
|
|
|
+ Scanner.GetSym; (*{0105} consume `:` *)
|
|
|
+ WHILE NOT ParseStatSeqLoop(BITSET{8,10,13}) DO END; (*{0107-010b} arm body *)
|
|
|
+ CodeGen.EmitStandardOp(20); (*{010d-010f} jump to end *)
|
|
|
+ END;
|
|
|
+ IF NOT Scanner.AcceptSymbol(8) THEN (*{0111-0115} `|`: more arms loop to 009d *);
|
|
|
+ END;
|
|
|
+ DEC(nestDepth); (*{0117-0119} *)
|
|
|
+ endFix := CodeGen.InsertFixup(topFix, TRUE); (*{011a-011e} *)
|
|
|
+ IF head # NIL THEN (*{011f-0121} emit jump table over label chain *)
|
|
|
+ lo := Words(head)^[1]; (*{0123-0125} *)
|
|
|
+ CodeGen.EmitStandardOp(19); (*{0126-0128} *)
|
|
|
+ CodeGen.EmitWord(lo + 32768); (*{012a-012f} *)
|
|
|
+ CodeGen.EmitWord(tail - lo); (*{0131-0135} FIXME: ADDRESS pun *)
|
|
|
+ CodeGen.OpenFixup(topFix, FALSE); (*{0137-013a} *)
|
|
|
+ WHILE Words(head)^[0] = lo DO (*{013c-0140} FIXME *)
|
|
|
+ CodeGen.CloseFixup(Words(head)^[2] + ORD(NOT endFix), FALSE); (*{0142-0148} *)
|
|
|
+ head := Words(head)^[0]; (*{014a-014c} *)
|
|
|
+ ELSE
|
|
|
+ CodeGen.EmitWord((tail - lo) * 2 + 1); (*{014f-0156} *)
|
|
|
+ END;
|
|
|
+ INC(lo); (*{0158-015a} *)
|
|
|
+ IF head = NIL THEN END; (*{015b-015d} loop to 013c while head#NIL *)
|
|
|
+ END;
|
|
|
+ IF Scanner.AcceptSymbol(10) THEN (*{015f-0160} ELSE *)
|
|
|
+ WHILE NOT ParseStatSeqLoop(BITSET{13}) DO END; (*{0164-0168} *)
|
|
|
+ END;
|
|
|
+ Scanner.GetSym; (*{0187} consume END *)
|
|
|
+ IF 8 IN Scanner.scanOptions THEN (*{016c-0170} range-check variant epilogue *)
|
|
|
+ CodeGen.QueueConst(13); (*{0172-0173} *)
|
|
|
+ CodeGen.QueueConst(0); (*{0175-0176} *)
|
|
|
+ CodeGen.QueueConst(0); (*{0178-0179} *)
|
|
|
+ CodeGen.EmitStandardOp(14); (*{017b-017c} *)
|
|
|
+ END;
|
|
|
+ IF tail # NIL THEN (*{017e-0180} *)
|
|
|
+ endFix := CodeGen.InsertFixup(topFix, FALSE); (*{0182-0186} *)
|
|
|
+ END;
|
|
|
+END ParseCaseStmt;
|
|
|
+
|
|
|
+(* proc6 @018b, STMT case 125 — ParseFor. Control var, `:=` lower TO
|
|
|
+ upper [BY const] DO body END. Largest frame (4 desc buffers). *)
|
|
|
+PROCEDURE ParseFor;
|
|
|
+VAR ctrl: ADDRESS;
|
|
|
+ loD: ADDRESS;
|
|
|
+ hiD: ADDRESS;
|
|
|
+ tmpD: ADDRESS;
|
|
|
+ step: CARDINAL;
|
|
|
+ cflag: CARDINAL;
|
|
|
+ isInt: CARDINAL;
|
|
|
+ dummy: CARDINAL;
|
|
|
+ sub: CARDINAL;
|
|
|
+ topMark: CARDINAL;
|
|
|
+ fixA: ADDRESS;
|
|
|
+ markB: CARDINAL;
|
|
|
+BEGIN
|
|
|
+ {/* 018b */}
|
|
|
+ Scanner.Allocate(ctrl, 10); (*{018d-018f} FIXME: group wrote ReserveWords *)
|
|
|
+ Scanner.Allocate(loD, 10); (*{0190-0192} *)
|
|
|
+ Scanner.Allocate(hiD, 10); (*{0193-0195} *)
|
|
|
+ Scanner.Allocate(tmpD, 10); (*{0196-0198} *)
|
|
|
+ Express.EvalConstExpr; (*{0199} control var head *)
|
|
|
+ Express.MatchOpClass(7, 28); (*{019c-019f} *)
|
|
|
+ IF Express.curDesc.raw[0] = Compiler.ByteType THEN (*{01a1-01a7} *)
|
|
|
+ Express.MatchOpClass(5, 28); (*{01aa-01ad} *)
|
|
|
+ END;
|
|
|
+ Express.CentralError(NOT (12 IN Words(Express.curDesc.raw[0])^[4]), 24); (*{01af-01b7} FIXME: pun *)
|
|
|
+ MOVE(Express.curDesc, ctrl, 10); (*{01b9-01bd} FIXME: group wrote MoveWords *)
|
|
|
+ sub := ORD(Words(Express.curDesc.raw[0])^[4] = 4); (*{01be-01c3} FIXME *)
|
|
|
+ IF sub # 0 THEN (*{01c4-01c5} rotate saved descs *)
|
|
|
+ MOVE(ctrl, tmpD, 10); (*{01c7-01cb} FIXME: direction TBD by diff *)
|
|
|
+ Express.PushExprDesc(ctrl, tmpD); (*{01cb-01ce} FIXME: arity/shape *)
|
|
|
+ MOVE(tmpD, ctrl, 10);
|
|
|
+ END;
|
|
|
+ Express.EmitOp; (*{01d0} proc6 *)
|
|
|
+ isInt := ORD(Express.curDesc.raw[0] = Compiler.IntType); (*{01d2-01d8} FIXME *)
|
|
|
+ Scanner.ExpectSymbol(27); (*{01d9-01db} `:=` *)
|
|
|
+ Express.BoolCondHelper; (*{01dd} lower bound *)
|
|
|
+ Express.ConstToCard(Words(ctrl)^[0], 27); (*{01df-01e5} FIXME: ctrlDescTyp *)
|
|
|
+ MOVE(Express.curDesc, loD, 10); (*{01e5-01e9} *)
|
|
|
+ Express.PopExprDesc(ctrl); (*{01ea-01eb} FIXME: ADDRESS arg *)
|
|
|
+ Scanner.ExpectSymbol(42); (*{01ed-01ef} TO *)
|
|
|
+ Express.BoolCondHelper; (*{01f1} upper bound *)
|
|
|
+ Express.ConstToCard(Words(ctrl)^[0], 42); (*{01f3-01f7} *)
|
|
|
+ MOVE(Express.curDesc, hiD, 10); (*{01f9-01fd} *)
|
|
|
+ step := 1; (*{01fe-01ff} *)
|
|
|
+ IF Scanner.AcceptSymbol(29) THEN (*{0200-0204} BY *)
|
|
|
+ Express.GetConstVal; (*{0206} proc13 *)
|
|
|
+ Express.ConstToCard(Compiler.IntType, 29); (*{0208-020c} *)
|
|
|
+ step := Express.curDesc.raw[2]; (*{020e-0211} const step *)
|
|
|
+ END;
|
|
|
+ (*{0212-0269} bound/step validation + counter init (const-fold vs runtime
|
|
|
+ paths); faithful to raw, minutiae FIXME *)
|
|
|
+ IF sub # 0 THEN (*{02e4-02e5} subrange control: normalize *)
|
|
|
+ Express.NormalizeOperand; (*{02e7-02e8} FIXME: group passed tmpD *)
|
|
|
+ Express.PushOperand(ctrl); (*{02ea-02eb} FIXME: 1-arg vs 0-arg FORWARD *)
|
|
|
+ CodeGen.SetPendingOp(5, 2, 0, 0); (*{02ed-02f1} *)
|
|
|
+ END;
|
|
|
+ WHILE NOT ParseStatSeqLoop(BITSET{13}) DO END; (*{02f3-02f7} body to END *)
|
|
|
+ Scanner.GetSym; (*{02f9} consume END *)
|
|
|
+ (*{02fb-033d} loop-back + fixup close-out FIXME *)
|
|
|
+ Scanner.GetSym;
|
|
|
+END ParseFor;
|
|
|
+
|
|
|
+(* proc7 @0341, STMT case 127 — ParseWhile. WHILE cond DO body END. *)
|
|
|
+PROCEDURE ParseWhile;
|
|
|
+VAR top: CARDINAL;
|
|
|
+ fix: ADDRESS;
|
|
|
+ endMark: CARDINAL;
|
|
|
+BEGIN
|
|
|
+ top := CodeGen.MarkCodePos(13); (*{0343-0347} *)
|
|
|
+ Express.BoolCondHelper; (*{0348} *)
|
|
|
+ Express.ConstToCard(Compiler.BooleanType, 37); (*{034a-034e} *)
|
|
|
+ Scanner.ExpectSymbol(30); (*{0350-0352} DO *)
|
|
|
+ CodeGen.EmitStandardOp(16); (*{0354-0356} jump-if-false *)
|
|
|
+ CodeGen.OpenFixup(fix, TRUE); (*{0358-035b} *)
|
|
|
+ WHILE NOT ParseStatSeqLoop(BITSET{13}) DO END; (*{035d-0361} body to END *)
|
|
|
+ Scanner.GetSym; (*{0363} consume END *)
|
|
|
+ CodeGen.EmitStandardOp(15); (*{0365-0366} jump back to top *)
|
|
|
+ endMark := CodeGen.nextEmitPos; (*{0368-036a} *)
|
|
|
+ CodeGen.CloseFixup(top, TRUE); (*{036b-036d} *)
|
|
|
+ IF NOT CodeGen.InsertFixup(fix, TRUE) THEN (*{036f-0374} *)
|
|
|
+ CodeGen.AdjustFixup(endMark + 1); (*{0376-0378} *)
|
|
|
+ END;
|
|
|
+END ParseWhile;
|
|
|
+
|
|
|
+(* proc8 @037c, STMT case 126 — ParseRepeat. REPEAT body UNTIL cond. *)
|
|
|
+PROCEDURE ParseRepeat;
|
|
|
+VAR top: CARDINAL;
|
|
|
+BEGIN
|
|
|
+ top := CodeGen.MarkCodePos(12); (*{037e-0382} *)
|
|
|
+ WHILE NOT ParseStatSeqLoop(BITSET{12}) DO END; (*{0383-0387} to UNTIL *)
|
|
|
+ Scanner.GetSym; (*{0389} consume UNTIL *)
|
|
|
+ Express.BoolCondHelper; (*{038b} *)
|
|
|
+ Express.ConstToCard(Compiler.BooleanType, 12); (*{038d-0392} *)
|
|
|
+ CodeGen.EmitStandardOp(16); (*{0392-0394} jump-if-false to top *)
|
|
|
+ CodeGen.CloseFixup(top, TRUE); (*{0396-0398} *)
|
|
|
+END ParseRepeat;
|
|
|
+
|
|
|
+(* proc9 @039c, STMT case 124 — ParseIf. IF cond THEN stats
|
|
|
+ [ELSIF cond THEN stats]... [ELSE stats] END. ELSIF via recursion. *)
|
|
|
+PROCEDURE ParseIf;
|
|
|
+VAR elseFix: ADDRESS;
|
|
|
+ endFix: ADDRESS;
|
|
|
+ savedEmit: CARDINAL;
|
|
|
+ constCond: BOOLEAN;
|
|
|
+ chained: CARDINAL;
|
|
|
+ skipGen: CARDINAL;
|
|
|
+BEGIN
|
|
|
+ Express.BoolCondHelper; (*{039e} *)
|
|
|
+ Express.ConstToCard(Compiler.BooleanType, 34); (*{03a0-03a4} *)
|
|
|
+ savedEmit := ORD(CodeGen.emitEnabled); (*{03a6-03a8} FIXME: BOOLEAN pun *)
|
|
|
+ skipGen := 0; (*{03a9-03aa} *)
|
|
|
+ constCond := (Express.curDesc.raw[1] = 0); (*{03ab-03af} mode=const *)
|
|
|
+ IF constCond THEN (*{03b0-03b1} *)
|
|
|
+ CodeGen.DiscardPending; (*{03b3} *)
|
|
|
+ skipGen := 2; (*{03b5-03b6} *)
|
|
|
+ IF Express.curDesc.raw[2] = 0 THEN (*{03b7-03bb} *)
|
|
|
+ ELSE
|
|
|
+ skipGen := 1; (*{03bd-03be} *)
|
|
|
+ END;
|
|
|
+ CodeGen.emitEnabled := FALSE; (*{03bf-03c0} suppress dead arm *)
|
|
|
+ END;
|
|
|
+ Scanner.ExpectSymbol(35); (*{03c2-03c4} THEN *)
|
|
|
+ IF NOT constCond THEN (*{03c6-03c8} *)
|
|
|
+ CodeGen.EmitStandardOp(16); (*{03ca-03cc} jump-if-false *)
|
|
|
+ CodeGen.OpenFixup(elseFix, TRUE); (*{03ce-03d1} *)
|
|
|
+ END;
|
|
|
+ WHILE NOT ParseStatSeqLoop(BITSET{10,11,13}) DO END; (*{03d3-03d7} *)
|
|
|
+ IF Scanner.AcceptSymbol(13) THEN (*{03d9-03dc} END: done *)
|
|
|
+ IF NOT constCond THEN (*{03de-03e0} *)
|
|
|
+ chained := ORD(CodeGen.InsertFixup(elseFix, TRUE)); (*{03e2-03e6} FIXME pun *)
|
|
|
+ END;
|
|
|
+ END;
|
|
|
+ IF NOT constCond THEN (*{03e9-03eb} *)
|
|
|
+ CodeGen.EmitStandardOp(15); (*{03ed-03ee} jump over else *)
|
|
|
+ CodeGen.OpenFixup(endFix, TRUE); (*{03f0-03f3} *)
|
|
|
+ IF NOT CodeGen.InsertFixup(elseFix, TRUE) THEN (*{03f5-03fa} *)
|
|
|
+ INC(endFix); (*{03fc-03fe} FIXME: ADDRESS pun *)
|
|
|
+ END;
|
|
|
+ END;
|
|
|
+ CodeGen.emitEnabled := savedEmit # 0; (*{0400-0405} FIXME: exact condition TBD *)
|
|
|
+ IF Scanner.AcceptSymbol(11) THEN (*{0407-040a} ELSIF: nested IF *)
|
|
|
+ ParseIf(); (*{040c} recursion *)
|
|
|
+ ELSE
|
|
|
+ Scanner.GetSym; (*{040f} consume ELSE *)
|
|
|
+ WHILE NOT ParseStatSeqLoop(BITSET{13}) DO END; (*{0411-0415} else stats *)
|
|
|
+ Scanner.GetSym; (*{0417} consume END *)
|
|
|
+ END;
|
|
|
+ IF NOT constCond THEN (*{0419-041a} InsertFixup(endFix, TRUE), result dropped *)
|
|
|
+ END;
|
|
|
+ CodeGen.emitEnabled := savedEmit # 0; (*{0426-0427} tail *)
|
|
|
+END ParseIf;
|
|
|
+
|
|
|
+(* proc10 @042b, STMT case 121 — ParseLoop. LOOP body END with EXIT support. *)
|
|
|
+PROCEDURE ParseLoop;
|
|
|
+VAR savedExit: CARDINAL;
|
|
|
+ fix: ADDRESS;
|
|
|
+ top: CARDINAL;
|
|
|
+ endFix: CARDINAL;
|
|
|
+BEGIN
|
|
|
+ savedExit := exitDepth; (*{042d-042e} *)
|
|
|
+ INC(nestDepth); (*{042f-0431} *)
|
|
|
+ exitDepth := nestDepth; (*{0432-0433} *)
|
|
|
+ CodeGen.EmitStandardOp(21); (*{0434-0436} loop-head marker *)
|
|
|
+ CodeGen.OpenFixup(fix, FALSE); (*{0438-043b} *)
|
|
|
+ top := CodeGen.MarkCodePos(11); (*{043d-0441} *)
|
|
|
+ WHILE NOT ParseStatSeqLoop(BITSET{13}) DO END; (*{0442-0446} body to END *)
|
|
|
+ Scanner.GetSym; (*{0448} consume END *)
|
|
|
+ CodeGen.EmitStandardOp(15); (*{044a-044b} jump back *)
|
|
|
+ CodeGen.CloseFixup(top, TRUE); (*{044d-044f} *)
|
|
|
+ endFix := ORD(CodeGen.InsertFixup(fix, FALSE)); (*{0451-0455} FIXME pun *)
|
|
|
+ DEC(nestDepth); (*{0456-0458} *)
|
|
|
+ exitDepth := savedExit; (*{0459-045a} *)
|
|
|
+END ParseLoop;
|
|
|
+
|
|
|
+(* proc11 @045d, STMT case 122 — ParseExit. Unwind to enclosing LOOP. *)
|
|
|
+PROCEDURE ParseExit;
|
|
|
+VAR level: CARDINAL;
|
|
|
+BEGIN
|
|
|
+ Express.CentralError(exitDepth # 0, 26); (*{045f-0463} *)
|
|
|
+ level := nestDepth; (*{0465-0466} *)
|
|
|
+ WHILE level > exitDepth DO (*{0467-046a} *)
|
|
|
+ CodeGen.EmitStandardOp(23); (*{046c-046e} unwind one level *)
|
|
|
+ DEC(level); (*{0470-0472} *)
|
|
|
+ END;
|
|
|
+ CodeGen.EmitStandardOp(20); (*{0475-0477} jump out *)
|
|
|
+END ParseExit;
|
|
|
+
|
|
|
+(* proc12 @047b, STMT case 123 — ParseResult. RESULT expr: store value
|
|
|
+ to function result slot; no exit jump. *)
|
|
|
+PROCEDURE ParseResult;
|
|
|
+VAR size: CARDINAL;
|
|
|
+ desc: ADDRESS;
|
|
|
+BEGIN
|
|
|
+ Express.CentralError((Words(curBlockNode)^[4] = 5) AND (Express.spillFlag # 0), 27); (*{047d-0488} *)
|
|
|
+ Express.CheckAndStore(desc); (*{0491-0493} FIXME: 0-arg FORWARD *)
|
|
|
+ Express.BoolCondHelper; (*{0496} result value *)
|
|
|
+ Express.ConstToInt(desc, 33); (*{0498-049b} FIXME: ADDRESS arg *)
|
|
|
+ Express.PopExprDesc(desc); (*{049d-049e} FIXME: ADDRESS arg *)
|
|
|
+ IF withPending # 0 THEN (*{04a0-04a1} *)
|
|
|
+ Express.PushOperand(withDesc); (*{04a3-04a4} FIXME arity *)
|
|
|
+ CodeGen.EmitStandardOp(25); (*{04a6-04a8} *)
|
|
|
+ END;
|
|
|
+ size := 0; (*{04aa-04ab} *)
|
|
|
+ IF desc # NIL THEN (*{04ac-04ae} *)
|
|
|
+ size := (Words(desc)^[3] + 1) DIV 2; (*{04b0-04b5} *)
|
|
|
+ END;
|
|
|
+ CodeGen.EmitMiscOp(size, (*{04b6} staged *)
|
|
|
+ CalcMemOffset() + ORD(Express.spillFlag = 1) * 128); (*{04b7-04bf} *)
|
|
|
+END ParseResult;
|
|
|
+
|
|
|
+(* proc13 @04c3, STMT case 128 — ParseWith. WITH rec DO body END. *)
|
|
|
+PROCEDURE ParseWith;
|
|
|
+VAR saved: ADDRESS;
|
|
|
+BEGIN
|
|
|
+ Express.ParseDesignatorTail; (*{04c5} *)
|
|
|
+ saved := Express.curDesc.raw[0]; (*{04c7-04c9} FIXME: typ pun *)
|
|
|
+ Express.MatchOpClass(1024, 38); (*{04ca-04cf} *)
|
|
|
+ IF Words(saved)^[4] IN BITSET{2,3,5} THEN (*{04d1-04de} FIXME set TBD *)
|
|
|
+ Scanner.OpenScope(SymTab.currentScope, Words(saved)^[0]); (*{04d9-04dd} FIXME *)
|
|
|
+ END;
|
|
|
+ IF Words(Express.curDesc.raw[0])^[0] # Compiler.CardType THEN (*{04e0-04e8} FIXME *)
|
|
|
+ Express.PushOperand(ADR(Express.curDesc)); (*{04e0-04e2} FIXME arity *)
|
|
|
+ Express.PopExprDesc(ADR(Express.curDesc)); (*{04ea-04ec} FIXME *)
|
|
|
+ END;
|
|
|
+ MOVE(Words(SymTab.currentScope)^[2], ADR(Express.curDesc), 10); (*{04ee-04f5} FIXME *)
|
|
|
+ Scanner.ExpectSymbol(30); (*{04f6-04f8} DO *)
|
|
|
+ WHILE NOT ParseStatSeqLoop(BITSET{13}) DO END; (*{04fa-04fe} body to END *)
|
|
|
+ SymTab.currentScope := Words(SymTab.currentScope)^[0]; (*{0500-0503} FIXME pun *)
|
|
|
+ Scanner.GetSym; (*{0505} consume END *)
|
|
|
+END ParseWith;
|
|
|
+
|
|
|
+(* proc14 @0509, STMT case 129 — ParseReturn. RETURN [value]: routine
|
|
|
+ exit epilogue with optional value. *)
|
|
|
+PROCEDURE ParseReturn;
|
|
|
+VAR info: CARDINAL;
|
|
|
+BEGIN
|
|
|
+ Scanner.PushWithScope; (*{050b} *)
|
|
|
+ IF caseActive = 0 THEN (*{050d-050f} *)
|
|
|
+ Scanner.ExpectIdentKind(2); (*{0511-0512} *)
|
|
|
+ END;
|
|
|
+ IF Scanner.identKind = 2 THEN (*{0514-0518} function context *)
|
|
|
+ IF 1 IN Scanner.followSet THEN (*{051a-051e} *)
|
|
|
+ info := Words(Scanner.curNode)^[6] + 2; (*{0520-0525} *)
|
|
|
+ ELSE
|
|
|
+ info := ORD(1 IN Scanner.followSet) - ORD(6 IN Scanner.followSet); (*{0528-052e} *)
|
|
|
+ END;
|
|
|
+ CodeGen.QueueConst(Words(Scanner.curNode)^[5] + info * 256); (*{052f-0536} *)
|
|
|
+ Scanner.GetSym; (*{0538} *)
|
|
|
+ IF Scanner.AcceptSymbol(1) THEN (*{053a-053d} `,` before value *)
|
|
|
+ Express.BoolCondHelper; (*{053f} *)
|
|
|
+ Express.ParseSelector(FALSE, Compiler.charArrayDesc, NIL); (*{0541-0546} FIXME: 39 dropped *)
|
|
|
+ ELSE
|
|
|
+ CodeGen.QueueConst(0); (*{054b-054c} *)
|
|
|
+ CodeGen.QueueConst(0); (*{054e-054f} *)
|
|
|
+ END;
|
|
|
+ ELSE
|
|
|
+ CodeGen.QueueConst(0); (*{0553-0554} *)
|
|
|
+ CodeGen.QueueConst(0); (*{0556-0557} *)
|
|
|
+ CodeGen.QueueConst(0); (*{0559-055a} *)
|
|
|
+ END;
|
|
|
+ CodeGen.EmitStandardOp(14); (*{055c-055d} *)
|
|
|
+END ParseReturn;
|
|
|
+(* STATEMEN group 2 — STMT/STATSE/tails/BODY + internals *)
|
|
|
+
|
|
|
+PROCEDURE NextSymWrap;
|
|
|
+(* ~proc1: no head, no call site in statement.txt; GetSym wrapper by name *)
|
|
|
+BEGIN
|
|
|
+ Scanner.GetSym;
|
|
|
+END NextSymWrap;
|
|
|
+
|
|
|
+PROCEDURE ParseStatSeqLoop(stop: BITSET): BOOLEAN;
|
|
|
+(* ~proc4: every driver is REPEAT proc4(set) UNTIL TRUE with empty body,
|
|
|
+ so proc4 parses ONE step; 14 pre-emption for nested CASE. *)
|
|
|
+BEGIN
|
|
|
+ IF Scanner.curSymbol IN stop THEN RETURN TRUE END;
|
|
|
+ IF Scanner.curSymbol = 14 THEN (* CaseSym FIXME *)
|
|
|
+ ParseCaseTail;
|
|
|
+ ELSE
|
|
|
+ ParseStatement;
|
|
|
+ END;
|
|
|
+ RETURN Scanner.curSymbol IN stop;
|
|
|
+END ParseStatSeqLoop;
|
|
|
+
|
|
|
+PROCEDURE EmitJumpFixup;
|
|
|
+(* ~proc15: sole real site STATSE after mark-save, before THEN-expect. *)
|
|
|
+BEGIN
|
|
|
+ CodeGen.DiscardPending;
|
|
|
+END EmitJumpFixup;
|
|
|
+
|
|
|
+PROCEDURE ParseStatement; (* STMT @0566 *)
|
|
|
+VAR
|
|
|
+ kw: CARDINAL;
|
|
|
+ saveSpill: CARDINAL;
|
|
|
+ saveNest: CARDINAL;
|
|
|
+ saveLoop: CARDINAL;
|
|
|
+ saveScope: ADDRESS;
|
|
|
+BEGIN
|
|
|
+ saveSpill := Express.spillTop; (*{0568} FIXME: group wrote spillTop; word3 spill save *)
|
|
|
+ saveNest := nestDepth; (*{056b} *)
|
|
|
+ saveLoop := exitDepth; (*{056d} FIXME: group wrote loopExitMark *)
|
|
|
+ saveScope := SymTab.currentScope; (*{056f} FIXME: ADDRESS pun *)
|
|
|
+ IF Scanner.curSymbol = 0 THEN GOTO identLed END; (*{0572} *)
|
|
|
+ IF Scanner.curSymbol IN BITSET{8..14} THEN GOTO done END; (*{0577} *)
|
|
|
+ Express.CentralError((121 <= Scanner.curSymbol) AND (Scanner.curSymbol <= 130), 20); (*{0580} *)
|
|
|
+ kw := Scanner.curSymbol; (*{058c} *)
|
|
|
+ Scanner.GetSym; (*{058f} *)
|
|
|
+ CASE kw OF (*{0591-05a6} default (125) -> ParseFor *)
|
|
|
+ 121: ParseLoop
|
|
|
+ | 122: ParseExit
|
|
|
+ | 123: ParseResult
|
|
|
+ | 124: ParseIf
|
|
|
+ | 126: ParseRepeat
|
|
|
+ | 127: ParseWhile
|
|
|
+ | 128: ParseWith
|
|
|
+ | 129: ParseReturn
|
|
|
+ | 130: ParseCaseStmt
|
|
|
+ ELSE ParseFor (* 125 *)
|
|
|
+ END;
|
|
|
+ GOTO done;
|
|
|
+identLed:
|
|
|
+ Scanner.PushWithScope; (*{05c4} *)
|
|
|
+ IF Scanner.identKind = 4 THEN (*{05c6} proc call *)
|
|
|
+ Express.ParseDesignatorTail; (*{05cc} *)
|
|
|
+ IF Scanner.AcceptSymbol(43) THEN (*{05d0} '(' *)
|
|
|
+ Express.MatchOpClass(512, 43); (*{05d9} *)
|
|
|
+ Express.CentralError(Express.curDesc.raw[2] = 0, 61); (*{05db} FIXME: scratch2 TBD *)
|
|
|
+ Express.StoreOperand; (* proc19 *) (*{05e9?} *)
|
|
|
+ ELSE
|
|
|
+ Scanner.ExpectSymbol(27); (*{05e9} ':=' *)
|
|
|
+ Express.ParseAssignment; (*{05f2?} FIXME: group wrote ParseAssignRhs=proc17 *)
|
|
|
+ END;
|
|
|
+ ELSIF Scanner.identKind = 5 THEN (*{05f2} *)
|
|
|
+ Express.CentralError(Scanner.literalType = NIL, 61); (*{05f8} FIXME: pun *)
|
|
|
+ Express.LoadOperand; (* proc18 *) (*{05e9?} *)
|
|
|
+ ELSIF Scanner.identKind = 0 THEN (*{0604} *)
|
|
|
+ Errors.ReportErrorWithText(128, Scanner.tokenBuffer); (*{0609} *)
|
|
|
+ ELSE
|
|
|
+ Errors.ReportError(21); (*{0612} *)
|
|
|
+ END;
|
|
|
+done:
|
|
|
+ Express.spillTop := saveSpill; (*{0616} *)
|
|
|
+ (* 061a unwind path (exceptions only): restores exitDepth/currentScope, RAISE *)
|
|
|
+END ParseStatement;
|
|
|
+
|
|
|
+PROCEDURE GuardedStatSeq(follow: BITSET): BOOLEAN; (* STATSE @0634 *)
|
|
|
+VAR
|
|
|
+ saveOpts: BITSET;
|
|
|
+ savePos: CARDINAL;
|
|
|
+ mark: ADDRESS;
|
|
|
+ saveCode: CARDINAL;
|
|
|
+ savePool: CARDINAL;
|
|
|
+BEGIN
|
|
|
+ saveOpts := Scanner.scanOptions; (*{0636} *)
|
|
|
+ savePos := Scanner.tokenPos; (*{0639} FIXME: group wrote word25 *)
|
|
|
+ Scanner.GetStackMark(mark); (*{063d} *)
|
|
|
+ saveCode := CodeGen.nextEmitPos; (*{0641} *)
|
|
|
+ savePool := SymTab.stringPoolPtr; (*{0644} *)
|
|
|
+ EmitJumpFixup; (* ~proc15 *) (*{0647} *)
|
|
|
+ Scanner.TestSymbolInSet(follow + BITSET{9}); (*{0648} entry assert *)
|
|
|
+ IF Scanner.AcceptSymbol(9) THEN (* guarded-seq introducer *)
|
|
|
+ REPEAT UNTIL ParseStatSeqLoop(follow) END; (*{0654} *)
|
|
|
+ END;
|
|
|
+ RETURN TRUE;
|
|
|
+ (* 065b error-recovery exit: restore scanOptions/tokenPos/mark/codepos/pool,
|
|
|
+ Errors.RollbackToMark, CodeGen.OpenEmitter, RETURN FALSE *)
|
|
|
+END GuardedStatSeq;
|
|
|
+
|
|
|
+PROCEDURE ParseCaseTail; (* proc16 @0683, called only from BODY via ed *)
|
|
|
+VAR
|
|
|
+ tab, cnt: CARDINAL;
|
|
|
+ step: CARDINAL;
|
|
|
+ fix1, elseSeen: CARDINAL;
|
|
|
+ fix2: CARDINAL;
|
|
|
+ labelAddr: ADDRESS;
|
|
|
+BEGIN
|
|
|
+ caseActive := 1; (*{0685} *)
|
|
|
+ cnt := 0; (*{0687} *)
|
|
|
+ tab := 0; (*{0689} *)
|
|
|
+ IF NOT (Scanner.curSymbol IN BITSET{8,10,13}) THEN (*{068b} *)
|
|
|
+ fix1 := CodeGen.MarkCodePos(15); (*{0694} *)
|
|
|
+ Scanner.PushWithScope; (*{0699} *)
|
|
|
+ Scanner.ExpectIdentKind(2); (*{069b} *)
|
|
|
+ LOOP
|
|
|
+ Scanner.Allocate(labelAddr, 6); (*{06a0} FIXME: operand slots TBD *)
|
|
|
+ IF 1 IN Scanner.followSet THEN (* const-label class *)
|
|
|
+ step := Words(Scanner.curNode)^[0] + 2; (*{06a5?} FIXME *)
|
|
|
+ ELSE
|
|
|
+ step := 1 - ORD(6 IN Scanner.followSet);
|
|
|
+ END;
|
|
|
+ WHILE tab <> 0 DO
|
|
|
+ Express.CentralError(Words(tab)^[1] = Words(tab)^[1], 47); (*{06cd} FIXME: dup-label slots TBD *)
|
|
|
+ tab := Words(tab)^[0]; (* advance FIXME *)
|
|
|
+ END;
|
|
|
+ INC(cnt);
|
|
|
+ Scanner.GetSym;
|
|
|
+ Scanner.TestSymbolInSet(BITSET{1,2}); (*{06e0} *)
|
|
|
+ IF NOT Scanner.AcceptSymbol(1) THEN EXIT END; (*{06e3} *)
|
|
|
+ END;
|
|
|
+ Scanner.GetSym;
|
|
|
+ REPEAT UNTIL ParseStatSeqLoop(BITSET{8,10,13}) END; (*{06eb} arm seq *)
|
|
|
+ SyncToStatStart; (* ~proc3 *)
|
|
|
+ END;
|
|
|
+ IF NOT Scanner.AcceptSymbol(8) THEN GOTO noMoreArms END; (*{06f2} '|' *)
|
|
|
+ GOTO caseLoop; (* back to {068b} FIXME: restructure to LOOP *)
|
|
|
+noMoreArms:
|
|
|
+ elseSeen := ORD(Scanner.AcceptSymbol(10)); (*{06f8} ELSE FIXME pun *)
|
|
|
+ IF elseSeen # 0 THEN
|
|
|
+ INC(cnt);
|
|
|
+ fix1 := CodeGen.MarkCodePos(15);
|
|
|
+ REPEAT UNTIL ParseStatSeqLoop(BITSET{13,14}) END; (*{06fb} FIXME set TBD *)
|
|
|
+ SyncToStatStart;
|
|
|
+ END;
|
|
|
+ fix2 := CodeGen.InsertFixup(Scanner.codeSize - 2, FALSE); (*{070e} FIXME: word22 TBD *)
|
|
|
+ CodeGen.Emit1(cnt);
|
|
|
+ WHILE tab <> 0 DO
|
|
|
+ CodeGen.EmitWord(tab);
|
|
|
+ CodeGen.CloseFixup(tab, FALSE);
|
|
|
+ tab := Words(tab)^[0]; (* advance FIXME *)
|
|
|
+ END;
|
|
|
+ IF elseSeen # 0 THEN
|
|
|
+ CodeGen.EmitWord(0);
|
|
|
+ CodeGen.CloseFixup(fix1, FALSE);
|
|
|
+ END;
|
|
|
+END ParseCaseTail;
|
|
|
+
|
|
|
+PROCEDURE CloseBlockChain(VAR node: ADDRESS); (* proc17 @0738, display-call *)
|
|
|
+VAR isFirst: BOOLEAN; desc: CARDINAL;
|
|
|
+BEGIN
|
|
|
+ WHILE node # NIL DO (*{073a} *)
|
|
|
+ IF NOT (0 IN Words(node)^[3]) THEN GOTO advance END; (*{073e} FIXME pun *)
|
|
|
+ IF 5 IN Words(node)^[3] THEN (*{0745} *)
|
|
|
+ Scanner.FindIdent(SymTab.currentScope, node, 9 IN Scanner.scanOptions); (*{074b} FIXME: group wrote Proc22 6-push id-check; arity TBD *)
|
|
|
+ IF Scanner.FindIdent(SymTab.currentScope, node, 9 IN Scanner.scanOptions) = node THEN
|
|
|
+ Errors.ReportErrorWithText(128, Scanner.tokenBuffer); (*{0758} FIXME: raw (5, node, s1, 128) *)
|
|
|
+ END;
|
|
|
+ GOTO advance;
|
|
|
+ END;
|
|
|
+ IF Words(node)^[4] = 4 THEN (*{0765} *)
|
|
|
+ IF (Words(node)^[3] - BITSET{3} = BITSET{}) THEN (*{076b} FIXME: s4 > 9 conjunct TBD *)
|
|
|
+ CloseBlockChain(node); (*{077e} recurse FIXME: node^^ *)
|
|
|
+ IF Express.spillFlag <> 0 THEN (*{0780} *)
|
|
|
+ needEpilogue := 1;
|
|
|
+ desc := Express.curDesc.raw[0]; (*{079c?} FIXME *)
|
|
|
+ Express.LoadIndirect; (* proc11 *)
|
|
|
+ IF 3 IN Words(node)^[3] THEN (*{079c} *)
|
|
|
+ Express.NormalizeOperand; (* proc10 *)
|
|
|
+ IF Express.spillFlag = 1 THEN CodeGen.EmitMiscOp(5, 23)
|
|
|
+ ELSE CodeGen.EmitStandardOp(10) END;
|
|
|
+ ELSE CodeGen.EmitStandardOp(9) END;
|
|
|
+ Express.PopOperand; (* proc3 *)
|
|
|
+ END;
|
|
|
+ RETURN;
|
|
|
+ END;
|
|
|
+ GOTO advance;
|
|
|
+ END;
|
|
|
+ IF Words(node)^[4] = 6 THEN (*{07c7} *)
|
|
|
+ isFirst := NOT exitEmitted;
|
|
|
+ exitEmitted := 1;
|
|
|
+ CloseBlockChain(node); (* FIXME: node^ pun *)
|
|
|
+ IF Words(node)^[5] # NIL THEN
|
|
|
+ needEpilogue := 1;
|
|
|
+ CodeGen.EmitStandardOp(15);
|
|
|
+ CodeGen.CloseFixup(Words(node)^[2], FALSE);
|
|
|
+ IF NOT CodeGen.InsertFixup(Words(node)^[5], FALSE) THEN END;
|
|
|
+ END;
|
|
|
+ IF isFirst THEN CodeGen.EmitSystemCall(24) END;
|
|
|
+ RETURN;
|
|
|
+ END;
|
|
|
+advance:
|
|
|
+ node := Words(node)^[0]; (*{07f7} FIXME: next link via scratch; pun *)
|
|
|
+ END;
|
|
|
+ IF exitEmitted = 0 THEN CodeGen.EmitSystemCall(24) END; (*{07fc} *)
|
|
|
+END CloseBlockChain;
|
|
|
+
|
|
|
+PROCEDURE EmitNameHash(VAR name: ARRAY OF CHAR); (* proc18 @0808 FIXME: 2nd param HIGH=128 *)
|
|
|
+VAR h, m3, acc: CARDINAL; chunk, i: CARDINAL; c: CARDINAL;
|
|
|
+BEGIN
|
|
|
+ acc := 0; chunk := 0;
|
|
|
+ REPEAT
|
|
|
+ h := 0; m3 := 0; c := 0; i := 1; (*{080a-0812} *)
|
|
|
+ WHILE h <> 37 DO
|
|
|
+ c := ORD(name[chunk + m3]);
|
|
|
+ IF c = 0C THEN h := 37;
|
|
|
+ ELSIF c <= ORD("9") THEN h := c - 22C; (* FIXME: exact bounds TBD *)
|
|
|
+ ELSE h := c - ORD("A") - ORD(NOT ODD((c AND 64) DIV 2)); (* case-fold FIXME *)
|
|
|
+ END;
|
|
|
+ END;
|
|
|
+ acc := acc + h * i;
|
|
|
+ i := i * 38; INC(m3);
|
|
|
+ IF m3 <= 2 THEN (* redo *) END;
|
|
|
+ CodeGen.EmitWord(acc);
|
|
|
+ chunk := chunk + 3;
|
|
|
+ UNTIL chunk > 3;
|
|
|
+END EmitNameHash;
|
|
|
+
|
|
|
+PROCEDURE EmitComBytes; (* proc19 @0863, display-call reading BODY locals *)
|
|
|
+VAR f: CARDINAL; n: CARDINAL; saveHeap: ADDRESS;
|
|
|
+BEGIN
|
|
|
+ MARK(saveHeap);
|
|
|
+ CodeGen.EmitMiscOp(3, ORD(Express.spillFlag = 1));
|
|
|
+ Files.FindFileOnDrives(f, Scanner.tokenBuffer, "COM"); (*{0863?} FIXME: raw (addr-2, buf, 128) *)
|
|
|
+ n := 0;
|
|
|
+ REPEAT
|
|
|
+ CodeGen.Emit1(0); (* FIXME: bodyL5 byte; Files.FileProc09 TBD *)
|
|
|
+ INC(n);
|
|
|
+ UNTIL n = 0; (* FIXME: bodyL3 count TBD *)
|
|
|
+ RELEASE(saveHeap);
|
|
|
+END EmitComBytes;
|
|
|
+
|
|
|
+PROCEDURE ParseBeginBlock(tag: CARDINAL; VAR rest: CARDINAL); (* BODY @08a4 *)
|
|
|
+VAR
|
|
|
+ nonEmpty, wasVar: CARDINAL;
|
|
|
+ fix: CARDINAL;
|
|
|
+ s2, s5: CARDINAL;
|
|
|
+BEGIN
|
|
|
+ curBlockNode := tag; (*{08a6} *)
|
|
|
+ Express.spillTop := SymTab.stringPoolPtr; (*{08a8} FIXME: group wrote spillTop *)
|
|
|
+ nestDepth := 0; exitDepth := 0;
|
|
|
+ Scanner.listingEnabled := TRUE; (*{08b8?} FIXME: group wrote word23 *)
|
|
|
+ caseActive := 0; exitEmitted := 0;
|
|
|
+ Scanner.codeSize := CodeGen.nextEmitPos; (*{08b8} FIXME: group wrote word22 *)
|
|
|
+ wasVar := ORD(Scanner.identKind = 5); (*{08bd} *)
|
|
|
+ nonEmpty := ORD(Scanner.curSymbol = 23); (*{08c2} body-lead FIXME *)
|
|
|
+ IF nonEmpty # 0 THEN
|
|
|
+ Scanner.GetSym;
|
|
|
+ WHILE NOT Scanner.AcceptSymbol(9) DO Scanner.GetSym END; (*{08cd} skip past BEGIN *)
|
|
|
+ nonEmpty := ORD(Scanner.curSymbol <> 13);
|
|
|
+ END;
|
|
|
+ needEpilogue := nonEmpty; (*{08d8} *)
|
|
|
+ IF (Words(curBlockNode)^[4] = 5) AND (Express.spillFlag = 0) THEN (*{08da} *)
|
|
|
+ CodeGen.EmitExtCall3(3, curBlockNode, CalcMemOffset()); (*{08e0} FIXME: 3rd arg BYTEAt TBD *)
|
|
|
+ IF Compiler.rangeCheckEnabled THEN CodeGen.OpenFixup(fix, TRUE) END; (*{08ea} *)
|
|
|
+ IF 15 IN Scanner.scanOptions THEN CodeGen.Emit1(255) (*{08f3} *)
|
|
|
+ ELSE
|
|
|
+ EmitNameHash(Scanner.tokenBuffer); (*{08ff} FIXME: raw (g6, s1, 128) *)
|
|
|
+ CodeGen.EmitWord(0);
|
|
|
+ END;
|
|
|
+ Scanner.codeSize := CodeGen.nextEmitPos; (*{0908} FIXME *)
|
|
|
+ IF wasVar # 0 THEN
|
|
|
+ Scanner.GetSym;
|
|
|
+ Scanner.ExpectSymbol(43); (*{0912} '(' *)
|
|
|
+ Express.CentralError(Scanner.isLiteral AND (Scanner.literalType = Compiler.CharType), 33); (*{0916} *)
|
|
|
+ EmitComBytes; (* nested proc19 *)
|
|
|
+ Scanner.GetSym;
|
|
|
+ Scanner.ExpectSymbol(5); (*{0927} ')' *)
|
|
|
+ fix := ORD(Scanner.AcceptSymbol(9)); (*{092b} FIXME pun *)
|
|
|
+ ELSE
|
|
|
+ CodeGen.EmitStandardOp(22);
|
|
|
+ CodeGen.Emit1(255);
|
|
|
+ IF (Express.spillFlag <> 0) AND (withPending # 0) THEN (*{0938} FIXME: group wrote spare3 *)
|
|
|
+ Express.PushExprDesc(withDesc, Compiler.BitsetType); (*{0938?} FIXME: operand slots TBD *)
|
|
|
+ CodeGen.EmitStandardOp(24);
|
|
|
+ Express.PopOperand;
|
|
|
+ END;
|
|
|
+ CloseBlockChain(SymTab.currentScope); (*{094c} FIXME: ADDRESS pun *)
|
|
|
+ IF nonEmpty # 0 THEN REPEAT UNTIL ParseStatSeqLoop(BITSET{13,14}) END END; (*{0951} *)
|
|
|
+ SyncToStatStart;
|
|
|
+ IF Scanner.AcceptSymbol(14) THEN ParseCaseTail END; (*{095c} *)
|
|
|
+ IF Express.spillFlag <> 0 THEN (*{0962} *)
|
|
|
+ CodeGen.PokeCodeByte(SymTab.stringPoolPtr - 255, Scanner.codeSize + 1); (* FIXME *)
|
|
|
+ END;
|
|
|
+ END;
|
|
|
+ ELSE
|
|
|
+ CodeGen.EmitSystemCall(4); (*{0974} *)
|
|
|
+ IF Compiler.rangeCheckEnabled THEN CodeGen.OpenFixup(fix, FALSE) END; (*{0978} *)
|
|
|
+ Scanner.codeSize := CodeGen.nextEmitPos; (* FIXME *)
|
|
|
+ CloseBlockChain(SymTab.currentScope); (* FIXME pun *)
|
|
|
+ IF nonEmpty # 0 THEN REPEAT UNTIL ParseStatSeqLoop(BITSET{13}) END END; (*{098b} *)
|
|
|
+ IF needEpilogue # 0 THEN (*{0994} *)
|
|
|
+ CodeGen.EmitStandardOp(15);
|
|
|
+ s5 := CodeGen.nextEmitPos; CodeGen.EmitWord(0); (* FIXME *)
|
|
|
+ s2 := Scanner.codeSize; (* FIXME *)
|
|
|
+ ELSE
|
|
|
+ s5 := 0;
|
|
|
+ END;
|
|
|
+ END;
|
|
|
+ IF Compiler.rangeCheckEnabled THEN fix := ORD(CodeGen.InsertFixup(fix, FALSE)) END; (*{09ab} FIXME pun *)
|
|
|
+ Scanner.listingEnabled := FALSE; (* FIXME: group wrote word23 *)
|
|
|
+ Scanner.ExpectSymbol(13); (*{09b8} END *)
|
|
|
+ Scanner.ExpectStringLiteral(Scanner.tokenBuffer); (*{09bb} FIXME: group wrote Proc21; END-name match TBD *)
|
|
|
+ IF (Words(curBlockNode)^[4] = 5) AND (Express.spillFlag = 0) THEN (*{09c2} *)
|
|
|
+ Scanner.TestSymbolInSet(BITSET{3}); (* '.' module end *)
|
|
|
+ ELSE
|
|
|
+ Scanner.TestSymbolInSet(BITSET{9});
|
|
|
+ END;
|
|
|
+ IF (NOT Compiler.rangeCheckEnabled) AND (0 IN Scanner.scanOptions) THEN (*{09d7} *)
|
|
|
+ Texts.WriteString(3, "----- Size = "); (* FIXME: Texts.proc09 idiom *)
|
|
|
+ Texts.WriteCard(3, CodeGen.nextEmitPos - Scanner.codeSize, 0); (* FIXME: Texts.proc11 *)
|
|
|
+ END;
|
|
|
+ IF 4 IN Scanner.scanOptions THEN (*{0a02} *)
|
|
|
+ Loader.Call("PRINTCOD"); (* FIXME: +CARDINAL 7 *)
|
|
|
+ END;
|
|
|
+END ParseBeginBlock;
|
|
|
+
|
|
|
+BEGIN (* proc0 @0a25 module init *)
|
|
|
+END Statemen.
|