DIRECTORY Alloc USING [Notifier], Code USING [actenable, caseCVState, catchcount, catchoutrecord, cfsi, cfSize, CodeNotImplemented, codeptr, curctxlvl, fileLoc, framesz, inlineFileLoc, StackNotEmptyAtStatement, substenable, xtracting], CodeDefs USING [Base, Byte, CaseCVState, CodeCCIndex, codeType, FrameStateRecord, JumpType, LabelCCIndex, LabelCCNull, LabelInfoIndex, Lexeme, NullLex, OtherCCIndex, StackIndex, VarComponent, VarIndex], ComData USING [bodyIndex, switches, textIndex], FOpCodes USING [qBCAST, qBCASTL, qBNDCK, qCATCH, qDADD, qDCOMP, qDEC, qDST, qDSUB, qDUCOMP, qINC, qLL, qLST, qLSTF, qNOTIFY, qNOTIFYL, qPUSH, qRET, qSL], Log USING [Error, Warning], P5 USING [BindStmtExp, CallCatch, CaseStmtExp, CaseTest, Exp, FlowTree, GenAnonLex, GenHeapLex, GetLabelMark, LabelCreate, LabelList, LogHeapFree, MakeExitLabel, P5Error, PopFrameState, PopInVals, PurgeHeapList, PurgePendTempList, PushFrameState, PushHeapList, PushLex, PushRhs, ReleaseTempLex, SAssign, SysCall, SysError, TTAssign], P5L USING [LoadAddress, MakeComponent, VarForLex], P5S USING [Assign, Call, CatchMark, Continue, Exit, Extract, Free, GoTo, Join, Label, Lock, Loop, ProcInit, Restart, Result, Resume, Retry, Return, RetWithError, SigErr, Start, Stop, Subst, Unlock, Wait], P5U USING [CCellAlloc, ComputeFrameSize, CreateLabel, InsertLabel, LabelAlloc, Out0, Out1, OutJump, OutSource, PushLitVal, TreeLiteralValue, WordsForOperand], PrincOps USING [AllocationVectorSize, localbase], SourceMap USING [Loc, nullLoc, Down, Up], Stack USING [Clear, Decr, Depth, Incr, Mark, New, Off, On, Pop, Reset, Restore], SymbolOps USING [CtxLevel, SetCtxLevel, UnderType, TransferTypes], Symbols USING [Base, bodyType, BTIndex, BTNull, ContextLevel, CSEIndex, CSENull, CTXIndex, CTXNull, ctxType, ISEIndex, ISENull, RecordSEIndex, RecordSENull, SEIndex, seType], Tree USING [Base, Index, Link, Map, NodeName, Null, Scan, treeType], TreeOps USING [FreeTree, GetNode, GetSe, MarkShared, ReverseUpdateList, ScanList, UpdateList]; Statement: PROGRAM IMPORTS MPtr: ComData, CPtr: Code, Log, P5U, P5L, P5, P5S, SourceMap, Stack, SymbolOps, TreeOps EXPORTS CodeDefs, P5 = BEGIN OPEN FOpCodes, CodeDefs; SEIndex: TYPE = Symbols.SEIndex; ISEIndex: TYPE = Symbols.ISEIndex; ISENull: ISEIndex = Symbols.ISENull; CSEIndex: TYPE = Symbols.CSEIndex; RecordSEIndex: TYPE = Symbols.RecordSEIndex; RecordSENull: RecordSEIndex = Symbols.RecordSENull; BTIndex: TYPE = Symbols.BTIndex; BTNull: BTIndex = Symbols.BTNull; tb: Tree.Base; -- tree base (local copy) seb: Symbols.Base; -- semantic entry base (local copy) ctxb: Symbols.Base; -- context entry base (local copy) bb: Symbols.Base; -- body base (local copy) cb: CodeDefs.Base; -- code base (local copy) StatementNotify: PUBLIC Alloc.Notifier = BEGIN -- called by allocator whenever table area is repacked seb _ base[Symbols.seType]; ctxb _ base[Symbols.ctxType]; bb _ base[Symbols.bodyType]; tb _ base[Tree.treeType]; cb _ base[codeType]; END; catchEndLabel: LabelCCIndex _ LabelCCNull; recentStmt: PUBLIC Tree.Link; -- for debugging StatementTree: PUBLIC PROC [t: Tree.Link] RETURNS [Tree.Link] = BEGIN -- generates code for Mesa statements node: Tree.Index; saveHeapList: ISEIndex; saveIndex: SourceMap.Loc = MPtr.textIndex; recentStmt _ t; IF t = Tree.Null THEN RETURN [Tree.Null]; BEGIN ENABLE BEGIN P5.LogHeapFree => RESUME [TRUE, P5.GenHeapLex[]]; CPtr.CodeNotImplemented => IF ~MPtr.switches['d] THEN GO TO unimplementedConstruct; END; saveHeapList _ P5.PushHeapList[]; WITH t SELECT FROM subtree => BEGIN fIndex: SourceMap.Loc _ CPtr.inlineFileLoc; node _ index; IF fIndex = SourceMap.nullLoc THEN fIndex _ tb[node].info; IF fIndex # SourceMap.nullLoc THEN SELECT tb[node].name FROM list, block, null => NULL; -- info is not a valid file index ENDCASE => {CPtr.fileLoc _ MPtr.textIndex _ fIndex; P5U.OutSource[fIndex]}; IF ~CPtr.xtracting AND Stack.Depth[] # 0 THEN {SIGNAL CPtr.StackNotEmptyAtStatement; Stack.Clear[]}; SELECT tb[node].name FROM list => t _ TreeOps.UpdateList[t, StatementTree]; block => Block[node]; start => P5S.Start[node]; restart => P5S.Restart[node]; stop => P5S.Stop[node]; dst => DumpState[node]; lst => GO TO unimplementedConstruct; -- added in Trinity lste => LoadState[node]; lstf => LoadStateFree[node]; call, portcall => P5S.Call[node]; signal, error => P5S.SigErr[node]; syscall => SysCallStmt[node]; syserror => P5.SysError[]; label => P5S.Label[node]; assign => P5S.Assign[node]; extract => P5S.Extract[node]; if => IfStmt[node]; case => [] _ P5.CaseStmtExp[node, FALSE]; bind => [] _ P5.BindStmtExp[node, FALSE]; do => DoStmt[node]; exit => P5S.Exit[]; loop => P5S.Loop[]; retry => P5S.Retry[]; continue => P5S.Continue[]; goto => P5S.GoTo[node]; catchmark => P5S.CatchMark[node]; return => P5S.Return[node]; resume => P5S.Resume[node]; reject => Reject[]; result => P5S.Result[node]; open => Open[node]; enable => Enable[node]; checked => tb[node].son[1] _ StatementTree[tb[node].son[1]]; procinit => P5S.ProcInit[node]; wait => P5S.Wait[node]; notify => Notify[node]; broadcast => Broadcast[node]; join => P5S.Join[node]; unlock => P5S.Unlock[node]; lock => P5S.Lock[node]; subst => P5S.Subst[node]; free => P5S.Free[node]; xerror => P5S.RetWithError[node]; null => NULL; ENDCASE => GO TO unimplementedConstruct; END; ENDCASE; P5.PurgeHeapList[saveHeapList]; P5.PurgePendTempList[]; EXITS unimplementedConstruct => {Log.Error[unimplemented]; Stack.Clear[]}; END; MPtr.textIndex _ saveIndex; RETURN [TreeOps.FreeTree[t]] END; SysCallStmt: PROC [node: Tree.Index] = BEGIN Stack.Mark[]; TreeOps.ScanList[tb[node].son[2], P5.PushRhs]; P5.SysCall[P5U.TreeLiteralValue[tb[node].son[1]]]; END; Open: PROC [node: Tree.Index] = BEGIN OPEN TreeOps; OpenItem: PROC [t: Tree.Link] RETURNS [Tree.Link] = BEGIN MarkShared[t, FALSE]; RETURN [FreeTree[t]] END; tb[node].son[2] _ StatementTree[tb[node].son[2]]; tb[node].son[1] _ ReverseUpdateList[tb[node].son[1], OpenItem]; END; DumpState: PROC [node: Tree.Index] = INLINE BEGIN -- generates dumpstate DLState[node, qDST]; END; LoadState: PROC [node: Tree.Index] = INLINE BEGIN -- generates loadstate DLState[node, qLST]; P5.CallCatch[Tree.Null]; END; LoadStateFree: PROC [node: Tree.Index] = INLINE BEGIN -- generates loadstateandfree DLState[node, qLSTF]; P5U.OutJump[JumpRet, LabelCCNull]; END; DLState: PROC [node: Tree.Index, opc: Byte] = BEGIN -- does state move after checking for small currentcontext address lowBound: CARDINAL = PrincOps.localbase+2; var: VarComponent = P5L.MakeComponent[P5L.VarForLex[P5.Exp[tb[node].son[1]]]]; WITH var SELECT FROM frame => BEGIN IF level # CPtr.curctxlvl THEN {Log.Error[stateVector]; RETURN}; IF wd NOT IN [lowBound..Byte.LAST] THEN Log.Error[stateVector]; P5U.Out1[opc, wd]; END; ENDCASE => Log.Error[stateVector]; END; Block: PROC [node: Tree.Index] = BEGIN bti: BTIndex = tb[node].info; EnterBlock[bti]; tb[node].son[1] _ StatementTree[tb[node].son[1]]; tb[node].son[2] _ StatementTree[tb[node].son[2]]; ExitBlock[bti]; END; EnterBlock: PUBLIC PROC [bti: BTIndex] = BEGIN IF CPtr.inlineFileLoc = SourceMap.nullLoc THEN CPtr.fileLoc _ MPtr.textIndex _ SourceMap.Up[bb[bti].sourceIndex] ELSE bb[bti].sourceIndex _ CPtr.inlineFileLoc.Down; P5U.OutSource[SourceMap.Up[bb[bti].sourceIndex]]; P5U.CCellAlloc[other]; cb[LOOPHOLE[CPtr.codeptr, OtherCCIndex]].obody _ markbody[start: TRUE, index: bti]; END; ExitBlock: PUBLIC PROC [bti: BTIndex] = BEGIN P5U.CCellAlloc[other]; cb[LOOPHOLE[CPtr.codeptr, OtherCCIndex]].obody _ markbody[start: FALSE, index: bti]; END; IfStmt: PROC [node: Tree.Index] = BEGIN -- generates code for an IF statement eLabel: LabelCCIndex = P5U.LabelAlloc[]; P5.FlowTree[tb[node].son[1], FALSE, eLabel ! P5.LogHeapFree => RESUME [FALSE, NullLex]]; P5.PurgePendTempList[]; tb[node].son[2] _ StatementTree[tb[node].son[2]]; IF tb[node].son[3] # Tree.Null THEN BEGIN iLabel: LabelCCIndex = P5U.LabelAlloc[]; P5U.OutJump[Jump, iLabel]; P5U.InsertLabel[eLabel]; tb[node].son[3] _ StatementTree[tb[node].son[3]]; P5U.InsertLabel[iLabel]; END ELSE P5U.InsertLabel[eLabel]; END; DoStmt: PROC [rootNode: Tree.Index] = BEGIN -- generates code for all the loop statments stepLoop, tempIndex, tempEnd, upLoop, forSeqLoop, bigForSeq: BOOL _ FALSE; signed, long: BOOL _ FALSE; sSon, eSon: Tree.Link; node, subNode: Tree.Index; bti: BTIndex _ BTNull; intType: Tree.NodeName; indexLex: Lexeme.se; endLex: Lexeme; topLabel: LabelCCIndex = P5U.LabelAlloc[]; startLabel: LabelCCIndex; finLabel: LabelCCIndex = P5U.LabelAlloc[]; endLabel, loopLabel: LabelCCIndex; labelMark: LabelInfoIndex = P5.GetLabelMark[]; UpdateCV: PROC [loadLong: BOOL] = BEGIN IF long THEN BEGIN IF loadLong THEN P5.PushLex[indexLex]; P5U.PushLitVal[1]; P5U.PushLitVal[0]; P5U.Out0[IF upLoop THEN qDADD ELSE qDSUB]; P5.SAssign[indexLex.lexsei]; END ELSE P5U.Out0[IF upLoop THEN qINC ELSE qDEC]; END; [exit: endLabel, loop: loopLabel] _ P5.MakeExitLabel[]; TreeOps.ScanList[tb[rootNode].son[5], P5.LabelCreate]; IF tb[rootNode].son[1] = Tree.Null THEN P5U.InsertLabel[topLabel] ELSE BEGIN node _ TreeOps.GetNode[tb[rootNode].son[1]]; bti _ tb[node].info; IF bti # BTNull THEN EnterBlock[bti]; SELECT tb[node].name FROM forseq => BEGIN t1: Tree.Link = tb[node].son[1]; t2: Tree.Link = tb[node].son[2]; indexLex _ [se[TreeOps.GetSe[t1]]]; forSeqLoop _ TRUE; bigForSeq _ P5U.WordsForOperand[t1] > 2; IF bigForSeq THEN {P5.TTAssign[t1, t2]; P5U.InsertLabel[topLabel]} ELSE {P5.PushRhs[t2]; P5U.InsertLabel[topLabel]; P5.SAssign[indexLex.lexsei]}; P5.PurgeHeapList[ISENull]; END; upthru, downthru => BEGIN ENABLE P5.LogHeapFree => RESUME [FALSE, NullLex]; cvBound: Tree.Link = tb[node].son[3]; nonempty: BOOL = tb[node].attr1; stepLoop _ TRUE; upLoop _ tb[node].name = upthru; subNode _ TreeOps.GetNode[tb[node].son[2]]; intType _ tb[subNode].name; IF tb[subNode].attr1 THEN SIGNAL CPtr.CodeNotImplemented; long _ tb[subNode].attr2; signed _ tb[subNode].attr3; WITH tb[node].son[1] SELECT FROM subtree => -- son1 is empty {indexLex _ P5.GenAnonLex[IF long THEN 2 ELSE 1]; tempIndex _ TRUE}; symbol => indexLex _ Lexeme[se[index]]; ENDCASE; IF upLoop THEN {sSon _ tb[subNode].son[1]; eSon _ tb[subNode].son[2]} ELSE BEGIN SELECT intType FROM intCO => intType _ intOC; intOC => intType _ intCO; ENDCASE; sSon _ tb[subNode].son[2]; eSon _ tb[subNode].son[1]; END; WITH e: eSon SELECT FROM literal => WITH e.index SELECT FROM word => endLex _ Lexeme[literal[word[lti]]]; ENDCASE => P5.P5Error[769]; symbol => IF seb[e.index].immutable THEN endLex _ Lexeme[se[e.index]] ELSE BEGIN endLex _ P5.GenAnonLex[IF long THEN 2 ELSE 1]; P5.PushRhs[e]; tempEnd _ TRUE; WITH endLex SELECT FROM se => P5.SAssign[lexsei]; ENDCASE; END; ENDCASE => BEGIN endLex _ P5.GenAnonLex[IF long THEN 2 ELSE 1]; P5.PushRhs[e]; tempEnd _ TRUE; WITH endLex SELECT FROM se => P5.SAssign[lexsei]; ENDCASE; END; startLabel _ P5U.LabelAlloc[]; P5.PushRhs[sSon]; IF long THEN P5.SAssign[indexLex.lexsei]; IF (intType = intCC OR intType = intOO) AND ~nonempty THEN BEGIN -- earlier passes check for empty intervals TopTest: ARRAY BOOL OF ARRAY BOOL OF ARRAY BOOL OF JumpType = [ [[UJumpL,UJumpLE], -- unsigned, down, closed/open [UJumpG,UJumpGE]], -- unsigned, up, closed/open [[JumpL,JumpLE], -- signed, down, closed/open [JumpG,JumpGE]]]; -- signed, up, closed/open IF long THEN {P5U.Out0[qPUSH]; P5U.Out0[qPUSH]}; P5.PushLex[endLex]; IF long THEN {P5U.Out0[IF signed THEN qDCOMP ELSE qDUCOMP]; P5U.PushLitVal[0]}; P5U.OutJump[TopTest[long OR signed][upLoop][intType = intOO], finLabel]; IF ~long THEN P5U.Out0[qPUSH]; END; IF ~long THEN Stack.Decr[1]; P5U.OutJump[Jump, startLabel]; P5U.InsertLabel[topLabel]; IF ~long THEN P5U.Out0[qPUSH]; SELECT intType FROM intCC => {UpdateCV[TRUE]; P5U.InsertLabel[startLabel]}; intOC => UpdateCV[TRUE]; intCO, intOO => NULL; ENDCASE; IF ~long THEN BEGIN IF cvBound # Tree.Null THEN {P5.PushRhs[cvBound]; P5U.Out0[FOpCodes.qBNDCK]}; P5.SAssign[indexLex.lexsei]; END; END; ENDCASE; END; IF tb[rootNode].son[2] # Tree.Null THEN P5.FlowTree[tb[rootNode].son[2], FALSE, finLabel ! P5.LogHeapFree => RESUME [FALSE, NullLex]]; tb[rootNode].son[4] _ StatementTree[tb[rootNode].son[4]]; P5U.InsertLabel[loopLabel]; IF stepLoop THEN BEGIN IF long AND (intType = intOC OR intType = intOO) THEN P5U.InsertLabel[startLabel]; P5.PushLex[indexLex]; SELECT intType FROM intCC => NULL; intCO => {UpdateCV[FALSE]; P5U.InsertLabel[startLabel]}; intOC => IF ~long THEN P5U.InsertLabel[startLabel]; intOO => {IF ~long THEN P5U.InsertLabel[startLabel]; UpdateCV[FALSE]}; ENDCASE; IF long THEN SELECT intType FROM intCO, intOO => {P5U.Out0[qPUSH]; P5U.Out0[qPUSH]}; ENDCASE; P5.PushLex[endLex]; IF long THEN {P5U.Out0[IF signed THEN qDCOMP ELSE qDUCOMP]; P5U.PushLitVal[0]}; P5U.OutJump[ IF ~long AND ~signed THEN IF upLoop THEN UJumpL ELSE UJumpG ELSE IF upLoop THEN JumpL ELSE JumpG, topLabel]; P5U.OutJump[Jump, finLabel]; IF tempEnd THEN P5.ReleaseTempLex[LOOPHOLE[endLex, Lexeme.se]]; IF tempIndex THEN P5.ReleaseTempLex[indexLex]; END ELSE BEGIN IF forSeqLoop THEN BEGIN IF bigForSeq THEN P5.TTAssign[[symbol[indexLex.lexsei]], tb[node].son[3]] ELSE P5.PushRhs[tb[node].son[3]]; P5.PurgeHeapList[ISENull]; END; P5U.OutJump[Jump, topLabel]; END; Stack.Reset[]; P5.PurgePendTempList[]; P5.LabelList[tb[rootNode].son[5], endLabel, labelMark]; P5U.InsertLabel[finLabel]; tb[rootNode].son[6] _ StatementTree[tb[rootNode].son[6]]; IF bti # BTNull THEN ExitBlock[bti]; P5U.InsertLabel[endLabel]; END; CatchPhrase: PUBLIC PROC [node: Tree.Index] = BEGIN -- process a catchphrase at procedure call aroundLabel: LabelCCIndex = P5U.LabelAlloc[]; saveCfSize: CARDINAL = CPtr.cfSize; saveCfsi: CARDINAL = CPtr.cfsi; r: CodeCCIndex; CPtr.catchcount _ CPtr.catchcount + 1; P5U.Out1[qCATCH, 0]; r _ LOOPHOLE[CPtr.codeptr, CodeCCIndex]; P5U.OutJump[JumpA, aroundLabel]; SCatchPhrase[node]; cb[r].parameters[1] _ CPtr.cfsi; P5U.InsertLabel[aroundLabel]; CPtr.catchcount _ CPtr.catchcount - 1; CPtr.cfSize _ saveCfSize; CPtr.cfsi _ saveCfsi; END; Enable: PROC [node: Tree.Index] = BEGIN -- generate code for an ENABLE aroundLabel: LabelCCIndex = P5U.LabelAlloc[]; enableLabel: LabelCCIndex; saveActEnable: LabelCCIndex = CPtr.actenable; saveSubstEnable: LabelCCIndex = CPtr.substenable; saveCfSize: CARDINAL = CPtr.cfSize; saveCfsi: CARDINAL = CPtr.cfsi; CPtr.catchcount _ CPtr.catchcount + 1; P5U.OutJump[JumpA, aroundLabel]; enableLabel _ P5U.CreateLabel[]; SCatchPhrase[TreeOps.GetNode[tb[node].son[1]]]; P5U.InsertLabel[aroundLabel]; CPtr.actenable _ enableLabel; IF tb[node].attr3 THEN CPtr.substenable _ enableLabel; CPtr.catchcount _ CPtr.catchcount - 1; tb[node].son[2] _ StatementTree[tb[node].son[2]]; CPtr.actenable _ saveActEnable; CPtr.substenable _ saveSubstEnable; CPtr.cfSize _ saveCfSize; CPtr.cfsi _ saveCfsi; END; SCatchPhrase: PUBLIC PROC [node: Tree.Index] = BEGIN -- main subr for catchphrases and ENABLEs saveCaseCVState: CaseCVState = CPtr.caseCVState; saveEndLabel: LabelCCIndex = catchEndLabel; oldStkPtr: StackIndex = Stack.New[]; oldCfSize: CARDINAL = CPtr.cfSize; msgTemp, sigTemp: Lexeme.se; saveActEnable: LabelCCIndex = CPtr.actenable; tempState: FrameStateRecord; CatchScan: PROC [t: Tree.Link] = BEGIN fail: LabelCCIndex = P5U.LabelAlloc[]; [] _ CatchItem[node:TreeOps.GetNode[t], failLabel: fail]; P5U.OutJump[Jump, catchEndLabel]; P5U.InsertLabel[fail]; END; catchEndLabel _ P5U.LabelAlloc[]; CPtr.curctxlvl _ CPtr.curctxlvl + 1; P5.PushFrameState[@tempState, tb[node].info]; CPtr.cfSize _ 0; Stack.Incr[1]; -- signal code is on stack IF CPtr.actenable # LabelCCNull THEN BEGIN sigTemp _ P5.GenAnonLex[1]; msgTemp _ P5.GenAnonLex[1]; P5U.Out1[qLL,PrincOps.localbase+1]; P5.SAssign[msgTemp.lexsei]; P5.SAssign[sigTemp.lexsei]; P5.PushLex[sigTemp]; END; CPtr.caseCVState _ singleLoaded; CPtr.actenable _ LabelCCNull; TreeOps.ScanList[tb[node].son[1], CatchScan]; IF tb[node].son[1] = Tree.Null THEN Stack.Pop[]; IF tb[node].son[2] # Tree.Null THEN tb[node].son[2] _ StatementTree[tb[node].son[2]]; CPtr.actenable _ saveActEnable; P5U.InsertLabel[catchEndLabel]; Stack.Off[]; IF CPtr.actenable # LabelCCNull THEN BEGIN P5.PushLex[sigTemp]; P5.PushLex[msgTemp]; P5U.Out1[qSL,PrincOps.localbase+1]; P5U.OutJump[Jump, CPtr.actenable]; P5.ReleaseTempLex[msgTemp]; P5.ReleaseTempLex[sigTemp]; END ELSE BEGIN P5U.PushLitVal[0]; P5U.Out0[qRET]; P5U.OutJump[JumpRet,LabelCCNull]; END; Stack.On[]; CPtr.curctxlvl _ CPtr.curctxlvl-1; CPtr.caseCVState _ saveCaseCVState; catchEndLabel _ saveEndLabel; CPtr.cfSize _ MAX[oldCfSize, CPtr.framesz]; P5.PopFrameState[@tempState]; CPtr.cfsi _ P5U.ComputeFrameSize[CPtr.cfSize]; IF bb[MPtr.bodyIndex].resident THEN CPtr.cfsi _ CPtr.cfsi + PrincOps.AllocationVectorSize; Stack.Restore[oldStkPtr]; END; CatchItem: PROC [node: Tree.Index, failLabel: LabelCCIndex] = BEGIN -- generate code for a CATCH item saveCatchOutRecord: RecordSEIndex = CPtr.catchoutrecord; inRecord: RecordSEIndex; tSei: CSEIndex = SymbolOps.UnderType[tb[node].info]; saveInCtxLevel, saveOutCtxLevel: Symbols.ContextLevel; inCtx, outCtx: Symbols.CTXIndex _ Symbols.CTXNull; P5.CaseTest[tb[node].son[1], failLabel]; IF tSei = Symbols.CSENull THEN inRecord _ CPtr.catchoutrecord _ RecordSENull ELSE BEGIN [inRecord, CPtr.catchoutrecord] _ SymbolOps.TransferTypes[tSei]; IF inRecord # RecordSENull THEN BEGIN inCtx _ seb[inRecord].fieldCtx; saveInCtxLevel _ SymbolOps.CtxLevel[inCtx]; SymbolOps.SetCtxLevel[inCtx, CPtr.curctxlvl]; END; IF CPtr.catchoutrecord # RecordSENull THEN BEGIN outCtx _ seb[CPtr.catchoutrecord].fieldCtx; saveOutCtxLevel _ SymbolOps.CtxLevel[outCtx]; SymbolOps.SetCtxLevel[outCtx, CPtr.curctxlvl]; END; END; P5.PopInVals[inRecord, TRUE]; tb[node].son[2] _ StatementTree[tb[node].son[2]]; IF inCtx # Symbols.CTXNull THEN SymbolOps.SetCtxLevel[inCtx, saveInCtxLevel]; IF outCtx # Symbols.CTXNull THEN SymbolOps.SetCtxLevel[outCtx, saveOutCtxLevel]; CPtr.catchoutrecord _ saveCatchOutRecord; END; Reject: PROC = INLINE BEGIN P5U.OutJump[Jump,catchEndLabel]; END; Notify: PROC [node: Tree.Index] = BEGIN r: VarIndex = P5L.VarForLex[P5.Exp[tb[node].son[1]]]; P5U.Out0[IF P5L.LoadAddress[r].long THEN qNOTIFYL ELSE qNOTIFY]; END; Broadcast: PROC [node: Tree.Index] = BEGIN r: VarIndex = P5L.VarForLex[P5.Exp[tb[node].son[1]]]; P5U.Out0[IF P5L.LoadAddress[r].long THEN qBCASTL ELSE qBCAST]; END; END. ÞStatement.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Sweet, September 12, 1980 9:11 AM Satterthwaite, April 16, 1986 3:49:52 pm PST Donahue, 10-Dec-81 9:39:18 Russ Atkinson (RRA) March 6, 1985 11:27:09 pm PST imported definitions set up for EXIT clause handle initialization node now the pre-body test ignore the opens (tb[rootNode].son3) now the body now (update and) test the control variable now the labelled EXITs finally the FINISHED clause Ê’˜codešœ™Kšœ Ïmœ1™Kšžœ˜K˜—Kšžœ˜K˜——…—GŒZü