DIRECTORY A3: TYPE USING [LhsMode, CanonicalType, DefaultInit, IdentifiedType, OperandLhs, TargetType, Voidable], Alloc: TYPE USING [Notifier], ComData: TYPE USING [bodyIndex, idANY, idBOOL, monitored, ownSymbols, textIndex], Log: TYPE USING [Error, ErrorSei, ErrorTree, ErrorTreeOp, ErrorType, Warning, WarningTree], Pass3: TYPE USING [checkedANY, lockNode], P3: TYPE USING [Attr, NPUse, Safety, phraseNP, BoundNP, SequenceNP, voidAttr, And, Apply, Assignment, BumpCount, CheckDisjoint, CloseBase, ClearRefStack, CopyLock, DeclList, Discrimination, EnterComposite, EnterType, Exp, Extract, FieldDefault, FindLockParams, FirstId, LockVar, MatchFields, MiscStmt, OpenBase, PopCtx, PushCtx, Range, RAttr, RecordMention, Rhs, RPop, RPush, RType, SealRefStack, UnsealRefStack, UpdateTreeAttr, UType, InsertCatchLabel], P3S: TYPE USING [BodyData, ImplicitInfo, implicit], SourceMap: TYPE USING [Loc, Up], SymLiteralOps: TYPE USING [DescribeRefLits], Symbols: TYPE USING [Base, ContextLevel, ISEIndex, Type, RecordSEIndex, CTXIndex, BTIndex, CBTIndex, HTNull, ISENull, CSENull, RecordSENull, CTXNull, BTNull, lG, RootBti, typeANY, seType, ctxType, mdType, bodyType], SymbolOps: TYPE USING [CopyBasicType, CtxLevel, FirstCtxSe, NextSe, RCType, SetCtxLevel, TransferTypes, TypeForm, UnderType], Tree: TYPE USING [Base, Index, Link, Map, Null, Scan, NullId, NullIndex, treeType], TreeOps: TYPE USING [FreeNode, GetHash, GetNode, MakeList, OpName, NthSon, PopTree, PushTree, PushNode, ReverseScanList, ScanList, SetAttr, SetInfo, UpdateList], Types: TYPE USING [Assignable]; Pass3S: PROGRAM IMPORTS A3, Log, P3, P3S, SourceMap, SymLiteralOps, SymbolOps, TreeOps, Types, dataPtr: ComData, passPtr: Pass3 EXPORTS P3, P3S = { OPEN SymbolOps, Symbols, A3, P3, TreeOps; tb: Tree.Base; -- tree base address (local copy) seb: Symbols.Base; -- se table base address (local copy) ctxb: Symbols.Base; -- context table base (local copy) mdb: Symbols.Base; -- module table base (local copy) bb: Symbols.Base; -- body table base (local copy) StmtNotify: PUBLIC Alloc.Notifier = { tb _ base[Tree.treeType]; seb _ base[seType]; ctxb _ base[ctxType]; mdb _ base[mdType]; bb _ base[bodyType]}; pathNP: PUBLIC NPUse _ none; currentBody: PUBLIC P3S.BodyData; current: POINTER TO P3S.BodyData = @currentBody; currentScope: PUBLIC BTIndex; safety: PUBLIC Safety _ none; exits: BOOL; BodyList: PUBLIC PROC[firstBti: BTIndex] = { bti: BTIndex _ firstBti; IF bti # BTNull THEN DO WITH bb[bti] SELECT FROM Callable => IF nesting # Catch THEN Body[LOOPHOLE[bti, CBTIndex]]; ENDCASE => NULL; IF bb[bti].link.which = parent THEN EXIT; bti _ bb[bti].link.index; ENDLOOP }; Body: PROC[bti: CBTIndex] = { saved: P3S.BodyData = current^; saveIndex: SourceMap.Loc = dataPtr.textIndex; saveBodyIndex: CBTIndex = dataPtr.bodyIndex; saveScope: BTIndex = currentScope; saveSafety: Safety = safety; node: Tree.Index; lockVar: ISEIndex; lockBit: BOOL; inRecord, outRecord: RecordSEIndex; argLevel: ContextLevel; dataPtr.bodyIndex _ currentScope _ bti; dataPtr.textIndex _ SourceMap.Up[bb[bti].sourceIndex]; current.bodyNode _ node _ WITH bb[bti].info SELECT FROM Internal => bodyTree, ENDCASE => ERROR; current.level _ bb[bti].level; current.entry _ bb[bti].entry; SetSafety[SafetyAttr[node]]; bb[bti].resident _ FALSE; current.lockHeld _ bb[bti].entry OR bb[bti].internal; argLevel _ IF bti = RootBti THEN lG ELSE current.level; IF bb[bti].ioType # typeANY THEN seb[bb[bti].ioType].mark4 _ FALSE; [inRecord, outRecord] _ TransferTypes[bb[bti].ioType]; IF inRecord = RecordSENull THEN current.argCtx _ CTXNull ELSE { current.argCtx _ seb[inRecord].fieldCtx; SetCtxLevel[current.argCtx, argLevel]; IF argLevel = lG THEN EnterTypes[current.argCtx]}; IF outRecord # RecordSENull THEN { SetCtxLevel[seb[outRecord].fieldCtx, argLevel]; IF argLevel = lG THEN EnterTypes[seb[outRecord].fieldCtx]}; PushArgCtx[current.inputRecord _ inRecord]; SetArgRefs[inRecord, 1]; PushArgCtx[current.returnRecord _ outRecord]; SetArgRefs[outRecord, 0]; ClearRefStack[]; current.labelList _ Tree.Null; current.loopDepth _ 0; current.catchDepth _ 0; current.unwindEnabled _ FALSE; current.resumeRecord _ RecordSENull; current.resumeFlag _ FALSE; IF ~current.entry THEN pathNP _ none ELSE { IF (lockVar _ FindLockParams[].actual) # ISENull THEN { lockBit _ seb[lockVar].immutable; seb[lockVar].immutable _ TRUE}; tb[node].son[4] _ CopyLock[]; pathNP _ phraseNP}; BEGIN ENABLE InsertCatchLabel => {Log.Error[catchLabel]; RESUME}; outInit: Tree.Link _ Tree.Null; ScanList[tb[node].son[1], OpenItem]; current.noXfers _ TRUE; IF inRecord # RecordSENull THEN CheckDisjoint[current.argCtx, bb[bti].localCtx]; IF outRecord # RecordSENull THEN { CheckDisjoint[seb[outRecord].fieldCtx, bb[bti].localCtx]; outInit _ AssignDefaults[seb[outRecord].fieldCtx, bb[bti].inline]}; PushCtx[bb[bti].localCtx]; IF bti = RootBti AND dataPtr.monitored THEN { PushCtx[tb[passPtr.lockNode].info]; DeclList[tb[passPtr.lockNode].son[1]]; IF (lockVar _ FirstCtxSe[tb[passPtr.lockNode].info]) # ISENull THEN BumpCount[lockVar]; tb[passPtr.lockNode].son[2] _ LockVar[tb[passPtr.lockNode].son[2]]; PopCtx[]; ClearRefStack[]}; DeclList[tb[node].son[2]]; IF outInit # Tree.Null THEN { PushTree[outInit]; PushTree[tb[node].son[2]]; PushNode[initlist, 2]; SetInfo[dataPtr.textIndex]; tb[node].son[2] _ PopTree[]}; END; IF bb[bti].type # RecordSENull THEN { IF bti = RootBti THEN { EnterTypes[seb[bb[bti].type].fieldCtx]; SetBodyAttrs[bb[bti].type]}; seb[bb[bti].type].mark3 _ TRUE}; current.reachable _ TRUE; tb[node].son[3] _ UpdateList[tb[node].son[3], Stmt ! InsertCatchLabel => {IF ~catchSeen THEN Log.Error[catchLabel]; RESUME}]; IF current.reachable THEN tb[node].son[3] _ ImpliedReturn[tb[node].son[3]]; BodyList[bb[bti].firstSon]; PopCtx[]; ReverseScanList[tb[node].son[1], CloseItem]; bb[bti].noXfers _ current.noXfers; bb[bti].hints _ [ safe: pathNP <= ref, argUpdated: inRecord # RecordSENull AND ctxb[seb[inRecord].fieldCtx].varUpdated, nameSafe: pathNP # unsafe, noStrings: ]; PopArgCtx[outRecord]; PopArgCtx[inRecord]; IF bti = RootBti AND SymLiteralOps.DescribeRefLits[].length # 0 THEN { rSei: RecordSEIndex = bb[bti].type; seb[rSei].hints.refField _ TRUE; EnterType[rSei]}; IF current.entry AND lockVar # ISENull THEN seb[lockVar].immutable _ lockBit; current^ _ saved; currentScope _ saveScope; SetSafety[saveSafety]; dataPtr.bodyIndex _ saveBodyIndex; dataPtr.textIndex _ saveIndex}; Scope: PUBLIC PROC[node: Tree.Index, body: Tree.Map] = { bti: BTIndex = tb[node].info; saveIndex: SourceMap.Loc = dataPtr.textIndex; saveScope: BTIndex = currentScope; dataPtr.textIndex _ SourceMap.Up[bb[bti].sourceIndex]; currentScope _ bti; PushCtx[bb[bti].localCtx]; DeclList[tb[node].son[1] ! InsertCatchLabel => {Log.Error[catchLabel]; RESUME}]; IF bb[bti].type # RecordSENull THEN seb[bb[bti].type].mark3 _ TRUE; tb[node].son[2] _ body[tb[node].son[2]]; BodyList[bb[bti].firstSon]; PopCtx[]; currentScope _ saveScope; dataPtr.textIndex _ saveIndex}; PushArgCtx: PROC[rSei: RecordSEIndex] = { IF rSei # RecordSENull THEN PushCtx[seb[rSei].fieldCtx]}; PopArgCtx: PROC[rSei: RecordSEIndex] = {IF rSei # RecordSENull THEN PopCtx[]}; SetArgRefs: PROC[rSei: RecordSEIndex, nRefs: CARDINAL] = { IF rSei # RecordSENull THEN { seb[rSei].mark4 _ FALSE; FOR sei: ISEIndex _ FirstCtxSe[seb[rSei].fieldCtx], NextSe[sei] UNTIL sei = ISENull DO IF seb[sei].mark4 THEN {seb[sei].idValue _ Tree.NullIndex; seb[sei].mark4 _ FALSE}; seb[sei].idInfo _ nRefs; ENDLOOP} }; EnterTypes: PROC[ctx: CTXIndex] = { FOR sei: ISEIndex _ FirstCtxSe[ctx], NextSe[sei] UNTIL sei = ISENull DO IF RCType[UnderType[seb[sei].idType]] = composite THEN EnterType[UnderType[seb[sei].idType]]; ENDLOOP }; AssignDefault: PROC[sei: ISEIndex] RETURNS[v: Tree.Link] = { IF seb[sei].hash = Symbols.HTNull AND ~seb[sei].extended THEN v _ Tree.Null ELSE { t: Tree.Link = IF seb[sei].extended THEN FieldDefault[sei] ELSE DefaultInit[seb[sei].idType]; IF t = Tree.Null THEN { IF ~Voidable[seb[sei].idType] THEN Log.ErrorSei[missingInit, sei]; v _ Tree.Null} ELSE { lhs: Tree.Link = [symbol[sei]]; mode: LhsMode; RecordMention[sei]; mode _ OperandLhs[lhs]; PushTree[lhs]; PushTree[t]; PushNode[assign, 2]; SetInfo[dataPtr.textIndex]; SetAttr[1, TRUE]; IF mode # counted THEN SetAttr[2, FALSE] ELSE { type: Type = seb[sei].idType; SELECT RCType[type] FROM simple => {SetAttr[2, OpName[t] # nil]; SetAttr[3, FALSE]}; composite => { SetAttr[2, TRUE]; SetAttr[3, TRUE]; EnterComposite[type, t, TRUE]}; ENDCASE => SetAttr[2, FALSE]}; v _ PopTree[]}; RPop[]}; RETURN}; AssignDefaults: PROC[ctx: CTXIndex, copyable: BOOL] RETURNS[Tree.Link] = { n: INTEGER _ 0; FOR sei: ISEIndex _ FirstCtxSe[ctx], NextSe[sei] UNTIL sei = ISENull DO IF seb[sei].hash # HTNull OR seb[sei].extended THEN { t: Tree.Link = AssignDefault[sei]; IF t # Tree.Null THEN { IF seb[sei].hash = HTNull AND copyable THEN Log.ErrorSei[defaultForm, sei]; PushTree[t]; n _ n+1; pathNP _ SequenceNP[pathNP][phraseNP]; ClearRefStack[]}}; ENDLOOP; RETURN[MakeList[n]]}; SetBodyAttrs: PROC[rSei: RecordSEIndex] = { FOR sei: ISEIndex _ FirstCtxSe[seb[rSei].fieldCtx], NextSe[sei] UNTIL sei = ISENull DO IF ~seb[sei].constant AND RCType[UnderType[seb[sei].idType]] # none THEN { seb[rSei].hints.refField _ TRUE; EnterType[rSei]; EXIT} ENDLOOP }; SafetyAttr: PUBLIC PROC[node: Tree.Index] RETURNS[Safety] = { RETURN[SELECT TRUE FROM tb[node].attr1 => checked, tb[node].attr2 => asserted, ENDCASE => none] }; SetSafety: PUBLIC PROC[new: Safety] = { IF safety # new THEN { SELECT new FROM checked => { IF passPtr.checkedANY = CSENull THEN passPtr.checkedANY _ CopyBasicType[typeANY]; seb[dataPtr.idANY].idInfo _ passPtr.checkedANY}; ENDCASE => seb[dataPtr.idANY].idInfo _ typeANY; safety _ new} }; continued: PUBLIC BOOL; markCatch: PUBLIC BOOL; Stmt: PUBLIC PROC[stmt: Tree.Link] RETURNS[val: Tree.Link] = { node: Tree.Index; saveIndex: SourceMap.Loc = dataPtr.textIndex; saveMark: BOOL = markCatch; saveContinued: BOOL = continued; IF stmt = Tree.Null THEN RETURN[Tree.Null]; WITH stmt SELECT FROM subtree => { node _ index; dataPtr.textIndex _ tb[node].info; IF ~current.reachable AND tb[node].name # list THEN { Log.Warning[unreachable]; current.reachable _ TRUE}; val _ stmt; -- the default markCatch _ continued _ FALSE; SELECT tb[node].name FROM assign => { Assignment[node]; RPop[]; pathNP _ SequenceNP[pathNP][phraseNP]}; extract => { Extract[node]; RPop[]; pathNP _ SequenceNP[pathNP][phraseNP]}; apply => { node _ Apply[node, typeANY, TRUE]; val _ [subtree[node]]; SELECT tb[node].name FROM wait => Log.ErrorTree[typeClash, tb[node].son[1]]; error => current.reachable _ FALSE; ENDCASE; SELECT RType[] FROM CSENull, typeANY => NULL; ENDCASE => Log.Error[nonVoidStmt]; RPop[]; pathNP _ SequenceNP[pathNP][phraseNP]}; block => { saveSafety: Safety = safety; SetSafety[SafetyAttr[node]]; IF saveSafety = checked AND safety = none THEN Log.Error[unsafeBlock]; Scope[node, Stmt]; SetSafety[SafetyAttr[node]]}; if => { saveReachable: BOOL; entryNP, saveNP: NPUse; tb[node].son[1] _ Rhs[tb[node].son[1], dataPtr.idBOOL]; RPop[]; pathNP _ entryNP _ SequenceNP[pathNP][phraseNP]; ClearRefStack[]; tb[node].son[2] _ UpdateList[tb[node].son[2], Stmt]; saveReachable _ current.reachable; saveNP _ pathNP; current.reachable _ TRUE; pathNP _ entryNP; tb[node].son[3] _ UpdateList[tb[node].son[3], Stmt]; IF saveReachable THEN current.reachable _ TRUE; pathNP _ BoundNP[saveNP][pathNP]}; case => SelectStmt[node, Case]; bind => SelectStmt[node, Discrimination]; do => DoStmt[node]; label => { InsertLabels[tb[node].son[2]]; tb[node].son[1] _ UpdateList[tb[node].son[1], Stmt]; DeleteLabels[tb[node].son[2]]; LabelList[tb[node].son[2]]}; goto => {ValidateLabel[tb[node].son[1]]; current.reachable _ FALSE}; return => Return[node]; exit, loop => { IF tb[node].name = exit THEN exits _ TRUE; IF current.loopDepth = 0 THEN Log.Error[exit]; current.reachable _ FALSE}; null => NULL; syserror => current.reachable _ FALSE; open => { ScanList[tb[node].son[1], OpenItem]; tb[node].son[2] _ UpdateList[tb[node].son[2], Stmt]; ReverseScanList[tb[node].son[1], CloseItem]}; checked => { saveSafety: Safety = safety; SetSafety[SafetyAttr[node]]; IF saveSafety = checked AND safety = none THEN Log.Error[unsafeBlock]; tb[node].son[1] _ Stmt[tb[node].son[1]]; SetSafety[saveSafety]}; list => val _ UpdateList[val, Stmt]; ENDCASE => val _ MiscStmt[node]}; ENDCASE => ERROR; IF markCatch THEN { PushTree[val]; PushNode[catchmark,1]; SetInfo[dataPtr.textIndex]; val _ PopTree[]; IF continued THEN current.reachable _ TRUE; pathNP _ unsafe}; markCatch _ saveMark; continued _ saveContinued; ClearRefStack[]; dataPtr.textIndex _ saveIndex; RETURN}; Case: PUBLIC PROC[node: Tree.Index, selection: Tree.Map] = { OPEN tb[node]; saveImplicit: P3S.ImplicitInfo = P3S.implicit; entryNP: NPUse; attr: Attr; eqTests: BOOL; CaseItem: Tree.Scan = { switchable: BOOL; saveIndex: SourceMap.Loc = dataPtr.textIndex; CaseTest: Tree.Map = { node: Tree.Index = GetNode[t]; BEGIN OPEN tb[node]; SELECT name FROM relE => { type: Type; son[2] _ Rhs[son[2], TargetType[P3S.implicit.type]]; type _ RType[]; info _ dataPtr.idBOOL; SELECT TypeForm[type] FROM $long => {attr1 _ FALSE; attr2 _ TRUE}; $real => {attr1 _ TRUE; attr2 _ FALSE}; ENDCASE => { IF OpName[son[2]] = shorten THEN Log.ErrorTree[typeClash, NthSon[son[2], 1]]; attr1 _ attr2 _ FALSE}; switchable _ switchable AND RAttr[].const; v _ t}; ENDCASE => { v _ Rhs[t, dataPtr.idBOOL]; eqTests _ switchable _ FALSE}; attr _ And[RAttr[], attr]; RPop[]; entryNP _ SequenceNP[entryNP][phraseNP]; END; RETURN}; node: Tree.Index = GetNode[t]; IF OpName[tb[node].son[1]] = decl THEN { bti: BTIndex = tb[node].info; Item: Tree.Map = {phraseNP _ entryNP; v _ selection[t]}; dataPtr.textIndex _ SourceMap.Up[bb[bti].sourceIndex]; Log.Error[discrimForm]; switchable _ FALSE; Scope[node, Item]} ELSE { dataPtr.textIndex _ tb[node].info; switchable _ TRUE; tb[node].son[1] _ UpdateList[tb[node].son[1], CaseTest]; tb[node].attr1 _ switchable; phraseNP _ entryNP; tb[node].son[2] _ selection[tb[node].son[2]]}; dataPtr.textIndex _ saveIndex}; SealRefStack[]; son[1] _ Exp[son[1], typeANY]; P3S.implicit.type _ CanonicalType[RType[]]; P3S.implicit.attr _ attr _ RAttr[]; RPop[]; entryNP _ phraseNP; IF ~IdentifiedType[P3S.implicit.type] THEN Log.ErrorTreeOp[missingOp, son[1], relE]; P3S.implicit.tree _ son[1]; eqTests _ TRUE; UnsealRefStack[]; ScanList[son[2], CaseItem]; attr1 _ eqTests; attr2 _ attr.const; phraseNP _ entryNP; son[3] _ selection[son[3]]; RPush[CSENull, attr]; P3S.implicit _ saveImplicit}; SelectStmt: PROC[node: Tree.Index, driver: PROC[Tree.Index, Tree.Map]] = { newReachable: BOOL; newNP: NPUse; saveNP: NPUse = pathNP; Selection: Tree.Map = { current.reachable _ TRUE; pathNP _ SequenceNP[saveNP][phraseNP]; v _ Stmt[t]; IF current.reachable THEN newReachable _ TRUE; newNP _ BoundNP[newNP][pathNP]}; newReachable _ FALSE; newNP _ none; driver[node, Selection]; RPop[]; current.reachable _ newReachable; pathNP _ newNP}; DoStmt: PROC[node: Tree.Index] = { OPEN tb[node]; forNode: Tree.Index; cvType: Type; controlled, block, cvUpdate, newReachable, saveExits: BOOL; saveNP, exitNP: NPUse; saveScope: BTIndex = currentScope; newReachable _ controlled _ block _ cvUpdate _ FALSE; IF son[1] # Tree.Null THEN { sei: ISEIndex; mode: LhsMode; forNode _ GetNode[son[1]]; IF tb[forNode].son[1] = Tree.Null THEN { sei _ ISENull; mode _ uncounted; cvType _ typeANY} ELSE { IF OpName[tb[forNode].son[1]] # decl THEN { tb[forNode].son[1] _ Exp[tb[forNode].son[1], typeANY]; IF (mode _ OperandLhs[tb[forNode].son[1]]) = none THEN Log.ErrorTree[nonLHS, tb[forNode].son[1]]; sei _ WITH tb[forNode].son[1] SELECT FROM symbol => index, ENDCASE => ISENull} ELSE { bti: BTIndex = tb[forNode].info; declNode: Tree.Index = GetNode[tb[forNode].son[1]]; block _ TRUE; currentScope _ bti; PushCtx[bb[bti].localCtx]; DeclList[tb[forNode].son[1]]; sei _ FirstId[declNode]; seb[sei].immutable _ TRUE; RPush[seb[sei].idType, voidAttr]; mode _ IF CtxLevel[seb[sei].idCtx] = lG THEN counted ELSE uncounted}; IF sei # ISENull THEN {BumpCount[sei]; BumpCount[sei]} -- account for implicit refs ELSE Log.ErrorTree[controlId, tb[forNode].son[1]]; cvType _ TargetType[RType[]]; RPop[]}; SELECT mode FROM counted => SELECT RCType[cvType] FROM simple => {tb[forNode].attr2 _ TRUE; tb[forNode].attr3 _ FALSE}; composite => tb[forNode].attr2 _ tb[forNode].attr3 _ TRUE; ENDCASE => tb[forNode].attr2 _ FALSE; ENDCASE => tb[forNode].attr2 _ FALSE; SELECT tb[forNode].name FROM forseq => { OPEN seq: tb[forNode]; seq.son[2] _ Rhs[seq.son[2], cvType]; RPop[]; IF seq.attr2 AND seq.attr3 THEN EnterComposite[cvType, seq.son[2], OpName[seq.son[1]] = decl]; cvUpdate _ TRUE}; upthru, downthru => { controlled _ TRUE; tb[forNode].son[2] _ Range[tb[forNode].son[2], cvType]; IF ~Types.Assignable[ [dataPtr.ownSymbols, UnderType[cvType]], [dataPtr.ownSymbols, UType[]]] THEN Log.ErrorType[typeClash, tb[forNode].son[2], [dataPtr.ownSymbols, cvType]]; RPop[]}; ENDCASE => ERROR; pathNP _ SequenceNP[pathNP][phraseNP]; ClearRefStack[]}; saveNP _ pathNP; pathNP _ none; IF son[2] # Tree.Null THEN { controlled _ TRUE; son[2] _ Rhs[son[2], dataPtr.idBOOL]; RPop[]; pathNP _ SequenceNP[pathNP][phraseNP]; ClearRefStack[]}; ScanList[son[3], OpenItem]; InsertLabels[son[5]]; current.loopDepth _ current.loopDepth + 1; saveExits _ exits; exits _ FALSE; son[4] _ UpdateList[son[4], Stmt]; IF exits THEN newReachable _ TRUE; exits _ saveExits; DeleteLabels[son[5]]; current.loopDepth _ current.loopDepth - 1; IF cvUpdate THEN { OPEN seq: tb[forNode]; seq.son[3] _ Rhs[seq.son[3], cvType]; RPop[]; IF seq.attr2 AND seq.attr3 THEN EnterComposite[cvType, seq.son[3], FALSE]; pathNP _ SequenceNP[pathNP][phraseNP]; ClearRefStack[]}; IF pathNP = refset THEN pathNP _ unsafe; saveNP _ pathNP _ SequenceNP[saveNP][pathNP]; IF son[5] # Tree.Null THEN { current.reachable _ FALSE; LabelList[son[5]]; IF current.reachable THEN newReachable _ TRUE}; exitNP _ pathNP; IF son[6] # Tree.Null THEN { current.reachable _ controlled; pathNP _ saveNP; son[6] _ UpdateList[son[6], Stmt]; IF current.reachable THEN newReachable _ TRUE; exitNP _ BoundNP[exitNP][pathNP]} ELSE IF controlled THEN newReachable _ TRUE; ReverseScanList[son[3], CloseItem]; current.reachable _ newReachable; pathNP _ exitNP; IF block THEN PopCtx[]; currentScope _ saveScope}; LabelList: PROC[t: Tree.Link] = { newReachable: BOOL; saveNP, newNP: NPUse; LabelItem: PROC[item: Tree.Link] = { node: Tree.Index = GetNode[item]; current.reachable _ tb[node].attr1; pathNP _ saveNP; tb[node].son[2] _ UpdateList[tb[node].son[2], Stmt]; IF current.reachable THEN newReachable _ TRUE; newNP _ BoundNP[newNP][pathNP]}; newReachable _ current.reachable; saveNP _ pathNP; newNP _ none; ScanList[t, LabelItem]; current.reachable _ newReachable; pathNP _ newNP}; InsertLabels: PROC[t: Tree.Link] = { labelMark: Tree.Link = current.labelList; InsertLabel: PROC[labeled: Tree.Link] = { node: Tree.Index = GetNode[labeled]; saveIndex: SourceMap.Loc = dataPtr.textIndex; dataPtr.textIndex _ tb[node].info; ScanList[tb[node].son[1], StackLabel]; dataPtr.textIndex _ saveIndex}; StackLabel: PROC[id: Tree.Link] = { node: Tree.Index; FOR t: Tree.Link _ current.labelList, tb[node].son[2] UNTIL t = labelMark DO node _ GetNode[t]; IF tb[node].son[1] = id AND id # Tree.NullId THEN Log.ErrorTree[duplicateLabel, id]; ENDLOOP; PushTree[id]; PushTree[current.labelList]; PushNode[item, 2]; SetAttr[1, FALSE]; current.labelList _ PopTree[]}; ScanList[t, InsertLabel]}; ValidateLabel: PROC[id: Tree.Link] = { node: Tree.Index; FOR t: Tree.Link _ current.labelList, tb[node].son[2] UNTIL t = Tree.Null DO node _ GetNode[t]; IF tb[node].son[1] = id THEN {tb[node].attr1 _ TRUE; RETURN}; ENDLOOP; Log.ErrorTree[unknownLabel, id]}; DeleteLabels: PROC[t: Tree.Link] = { anyReachable: BOOL; DeleteLabel: PROC[labeled: Tree.Link] = { node: Tree.Index = GetNode[labeled]; saveIndex: SourceMap.Loc = dataPtr.textIndex; dataPtr.textIndex _ tb[node].info; anyReachable _ FALSE; ReverseScanList[tb[node].son[1], UnstackLabel]; tb[node].attr1 _ anyReachable; dataPtr.textIndex _ saveIndex}; UnstackLabel: PROC[id: Tree.Link] = { node: Tree.Index; node _ GetNode[current.labelList]; IF tb[node].attr1 THEN anyReachable _ TRUE ELSE Log.WarningTree[unusedId, tb[node].son[1]]; current.labelList _ tb[node].son[2]; tb[node].son[2] _ Tree.Null; FreeNode[node]}; ReverseScanList[t, DeleteLabel]}; BumpArgRefs: PUBLIC PROC[record: RecordSEIndex, write: BOOL] = { IF record # RecordSENull THEN FOR sei: ISEIndex _ FirstCtxSe[seb[record].fieldCtx], NextSe[sei] UNTIL sei = ISENull DO IF write THEN BumpCount[sei] ELSE RecordMention[sei]; ENDLOOP}; CheckLocals: PUBLIC PROC[t: Tree.Link] RETURNS[localsOnly: BOOL] = { level: ContextLevel = bb[dataPtr.bodyIndex].level; CheckElement: Tree.Scan = { WITH t SELECT FROM literal => NULL; symbol => { sei: ISEIndex = index; IF ~seb[sei].constant AND CtxLevel[seb[sei].idCtx] # level THEN localsOnly _ FALSE}; ENDCASE => localsOnly _ FALSE}; localsOnly _ TRUE; ScanList[t, CheckElement]; RETURN}; Return: PROC[node: Tree.Index] = { OPEN tb[node]; rSei: RecordSEIndex = current.returnRecord; IF current.catchDepth # 0 OR (dataPtr.bodyIndex = RootBti AND rSei = RecordSENull) THEN Log.Error[misplacedReturn]; IF rSei # RecordSENull AND son[1] = Tree.Null THEN { BumpArgRefs[rSei, FALSE]; FOR sei: ISEIndex _ FirstCtxSe[seb[rSei].fieldCtx], NextSe[sei] UNTIL sei = ISENull DO IF seb[sei].hash = HTNull AND ~seb[sei].extended THEN { Log.Error[illDefinedReturn]; EXIT}; ENDLOOP; attr2 _ TRUE} ELSE { son[1] _ IF attr3 AND rSei # RecordSENull THEN Rhs[son[1], rSei] ELSE MatchFields[rSei, son[1]]; RPop[]; pathNP _ SequenceNP[pathNP][phraseNP]; IF current.entry THEN attr2 _ CheckLocals[son[1]]}; IF (attr1 _ current.entry) THEN { [] _ UpdateTreeAttr[tb[current.bodyNode].son[4]]; pathNP _ SequenceNP[pathNP][phraseNP]}; current.reachable _ FALSE}; ImpliedReturn: Tree.Map = { IF current.returnRecord # RecordSENull OR current.entry THEN { PushTree[Tree.Null]; PushNode[return, 1]; SetInfo[dataPtr.textIndex]; SetAttr[3, FALSE]; PushTree[Stmt[PopTree[]]]; PushTree[t]; v _ MakeList[-2]} ELSE v _ t; RETURN}; OpenItem: Tree.Scan = { node: Tree.Index = GetNode[t]; saveIndex: SourceMap.Loc = dataPtr.textIndex; dataPtr.textIndex _ tb[node].info; tb[node].son[2] _ OpenBase[tb[node].son[2], GetHash[tb[node].son[1]] ! InsertCatchLabel => {Log.Error[catchLabel]; RESUME}]; ClearRefStack[]; dataPtr.textIndex _ saveIndex}; CloseItem: Tree.Scan = { node: Tree.Index = GetNode[t]; CloseBase[tb[node].son[2], GetHash[tb[node].son[1]]]}; }. ŠPass3S.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Satterthwaite, April 8, 1986 5:36:37 pm PST Donahue, 10-Dec-81 11:28:15 Russ Atkinson (RRA) March 6, 1985 10:44:06 pm PST called by allocator whenever table area is repacked parameter usage bodies and blocks initialize computed attributes statements case driver selection iteration labels control transfers basing Κ“˜codešœ ™ Kšœ Οmœ1™˜QKšœžœžœL˜[Kšœžœžœ˜)KšœžœžœΈ˜ΖKšœžœžœ$˜3Kšœ žœžœ ˜ Kšœžœžœ˜,Kšœ žœžœΕ˜ΨKšœ žœžœh˜}KšœžœžœC˜SKšœ žœžœŽ˜‘Kšœžœžœ˜K˜—šœž˜šž˜KšœF˜FKšœ ˜ —Kšžœ ˜Kšžœ%˜)K˜KšœΟc!˜0KšœŸ%˜8KšœŸ"˜6KšœŸ!˜4KšœŸ˜1K˜šœ žœ˜%Kšœ3™3K˜K˜?K˜K˜K˜——Kšœ™˜Kšœžœ˜K˜—Kšœ™˜Kšœ žœ˜!Kšœ žœžœ˜0K˜Kšœžœ ˜Kšœžœ˜Kšœžœ˜ K˜šΟnœžœžœ˜,K˜šžœž˜šž˜šžœ žœž˜Kšœ žœžœžœ˜BKšžœžœ˜—Kšžœžœžœ˜)K˜Kšž˜——šœ˜K˜——š œžœ˜K˜Kšœ-˜-K˜,K˜"K˜K˜K˜Kšœ žœ˜K˜#K˜K˜'K˜6šœžœžœž˜7K˜Kšžœžœ˜—K˜>K˜Kšœžœ˜Kšœ!žœ˜5Kšœ žœžœžœ˜7Kšžœžœžœ˜CK˜6Kšžœžœ˜8šžœ˜K˜(K˜&Kšžœžœ˜2—šžœžœ˜"Kšœ/˜/Kšœ;˜;—K˜EK˜HK˜šœ™K˜6Kšœ1žœ˜7Kšœ;žœ˜A—Kšžœžœ˜$šžœ˜šžœ/žœ˜7Kšœ;žœ˜A—K˜2K˜—Kšž˜šž˜Kšœ,žœ˜4—K˜K˜$Kšœžœ˜Kšžœžœ1˜Pšžœžœ˜"K˜9K˜C—K˜šžœžœžœ˜-K˜#K˜&Kšžœ=žœ˜WK˜CK˜—K˜šžœžœ˜K˜.K˜3K˜—Kšžœ˜K˜šžœžœ˜%šžœžœ˜Kšœ'˜'Kšœ˜—Kšœžœ˜ —Kšœžœ˜˜2Kšœžœ žœžœ˜J—Kšžœžœ2˜KK˜K˜ K˜,K˜"˜K˜Kšœ$žœ)˜PK˜K˜ —K˜+šžœžœ,žœ˜FK˜#Kšœžœ˜2—Kšžœžœžœ"˜MK˜,K˜K˜CK˜—š œžœžœ&˜8K˜Kšœ-˜-K˜"K˜6K˜K˜KšœGžœ˜PKšžœžœžœ˜CK˜(K˜K˜ K˜:K˜K˜—š  œžœ˜)Kšžœžœ˜9K˜—Kš  œžœžœžœ ˜NK˜š  œžœžœ˜:šžœžœ˜Kšœžœ˜šžœ=žœž˜VKšžœžœ6žœ˜SK˜Kšžœ˜——šœ˜K˜——š  œžœ˜#šžœ.žœž˜Gšžœ0ž˜6K˜&—Kšž˜—šœ˜K˜——š  œžœžœ˜K˜Kšœ-˜-Kšœ žœ ˜Kšœžœ ˜ Kšžœžœžœ ˜+šžœžœž˜˜ K˜ K˜"šžœžœžœ˜5Kšœ.žœ˜4—Kšœ Ÿ˜Kšœžœ˜Kšžœž˜˜˜ K˜CK˜—˜ K˜@K˜—˜ Kšœžœ˜:šžœž˜K˜2Kšœžœ˜#Kšžœ˜—šžœ ž˜Kšœžœ˜Kšžœ˜"—K˜1K˜—˜ K˜K˜Kšžœžœžœ˜FK˜K˜K˜—˜Kšœžœ˜K˜K˜AK˜BK˜4K˜4Kšœžœ˜,K˜4Kšžœžœžœ˜/K˜"K˜—K˜K˜)K˜K˜˜ K˜K˜4K˜K˜K˜—Kšœ=žœ˜DK˜K˜˜Kšžœžœ žœ˜*Kšžœžœ˜.Kšœžœ˜K˜—Kšœžœ˜ Kšœ žœ˜&K˜˜ K˜$K˜4K˜-K˜—˜ K˜K˜Kšžœžœžœ˜FK˜(K˜K˜—K˜$Kšžœ˜!K˜——Kšžœžœ˜—šžœ žœ˜K˜&K˜-Kšžœ žœžœ˜+K˜—K˜1K˜Kšœ žœ˜(K˜K˜——Kšœ ™ ˜š œžœžœ+˜—Kšœ žœ˜—˜Kšœ žœ˜K˜7šžœ˜KšœJž˜NK˜K—K˜—Kšžœžœ˜—K˜9—K˜ šžœžœ˜Kšœ žœ/˜@K˜9—K˜K˜K˜*Kšœžœ˜$K˜"Kšžœžœžœ˜6K˜K˜*šžœ žœ˜Kšžœ˜K˜.Kšžœ žœ žœ$žœ˜JK˜9—Kšžœžœ˜(K˜-šžœžœ˜Kšœžœ˜Kšœžœžœžœ˜C—K˜šžœžœ˜K˜1K˜"Kšžœžœžœ˜.K˜!—Kšžœžœ žœžœ˜,K˜#K˜3Kšžœžœ ˜K˜K˜K˜——Kšœ™˜š  œžœ˜!Kšœžœ˜K˜K˜š  œžœ˜$K˜!K˜5K˜4Kšžœžœžœ˜.K˜ K˜—K˜BK˜K˜3K˜K˜—š  œžœ˜$K˜)K˜š  œžœ˜)K˜$Kšœ-˜-K˜"K˜&K˜K˜—š  œžœ˜#K˜šžœ3žœž˜LK˜Kšžœžœžœ#˜TKšžœ˜—K˜+Kšœžœ#˜GK˜—K˜K˜K˜—š  œžœ˜&K˜šžœ3žœž˜LK˜Kšžœžœžœžœ˜=Kšžœ˜—K˜!K˜K˜—š  œžœ˜$Kšœžœ˜K˜š  œžœ˜)K˜$Kšœ-˜-Kšœ3žœ˜9K˜/K˜K˜K˜—š  œžœ˜%K˜K˜"Kšžœžœž˜*Kšžœ,˜0K˜$K˜.K˜—K˜!K˜K˜——Kšœ™˜š  œžœžœžœ˜@šžœž˜šžœ?žœž˜XKšžœžœžœ˜5Kšžœ˜ K˜———š   œžœžœžœ žœ˜DK˜2K˜˜šžœžœž˜Kšœ žœ˜˜ K˜Kšžœžœ"žœžœ˜T—Kšžœžœ˜K˜——Kšœ žœžœ˜8K˜K˜—š œžœ˜"Kšžœ ˜K˜+šžœžœžœž˜WK˜—šžœžœžœ˜4Kšœžœ˜šžœ=žœž˜Všžœžœžœ˜7Kšœžœ˜#—Kšžœ˜—Kšœžœ˜ —šžœ˜šœ žœžœ˜)Kšžœ˜Kšžœ˜—K˜K˜&Kšžœžœ˜3—šžœžœ˜!K˜1K˜'—Kšœžœ˜K˜—˜šžœ%žœžœ˜>K˜)Kšœ)žœ˜0K˜K˜—Kšžœ˜ Kšžœ˜K˜K˜——Kšœ™˜˜K˜Kšœ-˜-K˜"˜DKšœ.žœ˜7—K˜K˜K˜—˜K˜K˜6K˜—K˜K˜——…—XΘnε