DIRECTORY C2CBasics, C2CDefs, C2CEnables, C2CNames, C2CIntCodeUtils, IntCodeDefs, IntCodeUtils, IntToIntTab; C2CEnablesImpl: CEDAR PROGRAM IMPORTS C2CBasics, C2CNames, C2CIntCodeUtils, IntCodeUtils, IntToIntTab EXPORTS C2CEnables = BEGIN OPEN IntCodeDefs, C2CEnables, C2CBasics, C2CDefs; IdList: TYPE = LIST OF LogicalId; ConsId: PROC [idList: IdList, id: LogicalId] RETURNS [l: IdList] = { FOR list: IdList ¬ idList, list.rest WHILE list#NIL DO IF list.first=id THEN RETURN [idList]; ENDLOOP; RETURN [CONS[id, idList]]; }; globalPerModuleEnables: IntCodeUtils.IdTab; ResetGlobalPerModuleEnables: PROC [] = { globalPerModuleEnables ¬ IntCodeUtils.NewIdTab[] }; InitIdToLambdaInf: PROC [] = { tab: IntCodeUtils.IdTab ¬ globalPerModuleEnables ¬ IntCodeUtils.NewIdTab[]; BEGIN VisitNIncludeLambda: IntCodeUtils.Visitor = { WITH node SELECT FROM labelNode: LabelNode => { WITH labelNode.label.node SELECT FROM lambdaNode: LambdaNode => { old: REF ¬ IntCodeUtils.Fetch[tab, labelNode.label.id]; WITH old SELECT FROM inf: LabelUsage => IF inf.lambda=lambdaNode THEN RETURN [node] --same id for same lambda ELSE ERROR; --multiply defined id ENDCASE => {}; [] ¬ IntCodeUtils.Store[tab, labelNode.label.id, NEW[LabelUsageRec ¬ [lambda: lambdaNode, purposeOfLambda: unknown, definedLabels: IntToIntTab.Create[]]]]; RETURN [node]; --dont recurse down; lambdas are not nested }; ENDCASE => {}; }; lambdaNode: LambdaNode => RETURN [node]; --dont recurse: lambdas are not nested ENDCASE => {}; IntCodeUtils.MapNode[node, VisitNIncludeLambda]; RETURN [node]; }; [] ¬ VisitNIncludeLambda[C2CBasics.rootNode] END; BEGIN SetPurpose: PROC [id: IntCodeDefs.LogicalId, purposeOfLambda: Purpose] = { inf: LabelUsage ¬ LambdaLabelUsage[id]; SELECT TRUE FROM inf=NIL => CantHappen; --lambda not found in previous pass inf.purposeOfLambda=unknown => {inf.purposeOfLambda ¬ purposeOfLambda; [] ¬ C2CNames.LabName[id, "Enable"]; --place nice name }; inf.purposeOfLambda#purposeOfLambda => CantHappen; --inconsistent usage ENDCASE => {}; }; VisitLambdaInIdTab: IntCodeUtils.IdTabVisitor = { VisitNode: IntCodeUtils.Visitor = { WITH node SELECT FROM lambdaNode: LambdaNode => RETURN [node]; --stop recursion applyNode: ApplyNode => { IF applyNode.handler#NIL AND applyNode.handler.proc#NIL THEN WITH applyNode.handler.proc SELECT FROM gotoNode: GotoNode => SetPurpose[gotoNode.dest.id, enableHandler]; ENDCASE => ERROR; WITH applyNode.proc SELECT FROM operNode: OperNode => WITH operNode.oper SELECT FROM codeOper: CodeOper => SetPurpose[codeOper.label.id, proc]; ENDCASE => {}; ENDCASE => {}; }; enableNode: EnableNode => { IF enableNode.handle#NIL AND enableNode.handle.proc#NIL THEN WITH enableNode.handle.proc SELECT FROM gotoNode: GotoNode => SetPurpose[gotoNode.dest.id, enableHandler]; ENDCASE => ERROR CantHappenCedar; }; labelNode: LabelNode => { [] ¬ IntToIntTab.Store[lambdaInf.definedLabels, labelNode.label.id, 0]; }; ENDCASE => NULL; IntCodeUtils.MapNode[node, VisitNode]; RETURN [node]; }; lambdaInf: LabelUsage ¬ NARROW[value]; IF lambdaInf.lambda=NIL THEN ERROR CantHappenCedar; IntCodeUtils.MapNode[lambdaInf.lambda, VisitNode]; }; IntCodeUtils.Enumerate[tab, VisitLambdaInIdTab]; END; BEGIN VisitLambdaInIdTab: IntCodeUtils.IdTabVisitor = { lambdaInf: LabelUsage ¬ NARROW[value]; IF lambdaInf.purposeOfLambda=enableHandler THEN { RegisterCall: PROC [callee: LogicalId] = { calleeInf: LabelUsage ¬ LambdaLabelUsage[callee]; IF calleeInf.purposeOfLambda#enableHandler THEN CantHappen; calleeInf.callers ¬ ConsId[calleeInf.callers, id]; }; VisitUpLabels: IntCodeUtils.Visitor = { WITH node SELECT FROM oper: OperNode => { WITH oper.oper SELECT FROM code: CodeOper => { WITH code.label.node SELECT FROM lambda: LambdaNode => {--procedure call; NOT uplevel goto--} ENDCASE => { IF ~IntToIntTab.Fetch[lambdaInf.definedLabels, code.label.id].found THEN { key: INT; IF code.offset#0 THEN SIGNAL NotYetImpl; key ¬ IntToIntTab.Fetch[lambdaInf.upLabels, code.label.id].val; IF key<1 THEN { key ¬ IntToIntTab.GetSize[lambdaInf.upLabels]+1; [] ¬ IntToIntTab.Store[lambdaInf.upLabels, code.label.id, key]; }; RETURN [C2CIntCodeUtils.GenConst[key]]; }; }; }; ENDCASE => {}; }; applyNode: ApplyNode => { IF applyNode.handler#NIL AND applyNode.handler.proc#NIL THEN WITH applyNode.handler.proc SELECT FROM gotoNode: GotoNode => RegisterCall[callee: gotoNode.dest.id]; ENDCASE => CantHappen; }; enableNode: EnableNode => { IF enableNode.handle#NIL AND enableNode.handle.proc#NIL THEN WITH enableNode.handle.proc SELECT FROM gotoNode: GotoNode => RegisterCall[callee: gotoNode.dest.id]; ENDCASE => CantHappenCedar; }; lambdaNode: LambdaNode => RETURN [node]; --stop recursion ENDCASE => {}; IntCodeUtils.MapNode[node, VisitUpLabels]; RETURN [node]; }; lambdaInf.upLabels ¬ IntToIntTab.Create[3]; IntCodeUtils.MapNode[lambdaInf.lambda, VisitUpLabels]; } }; IntCodeUtils.Enumerate[tab, VisitLambdaInIdTab]; END; BEGIN VisitHandler: PROC [handlerId: LogicalId, lambdaInf: LabelUsage] = { recurse: IdList ¬ NIL; EachUpLabel: IntToIntTab.EachPairAction = { labId: LogicalId ¬ key; FOR list: IdList ¬ lambdaInf.callers, list.rest WHILE list#NIL DO callerInf: LabelUsage ¬ LambdaLabelUsage[list.first]; key: INT; IF IntToIntTab.Fetch[callerInf.definedLabels, labId].found THEN LOOP; key ¬ IntToIntTab.Fetch[callerInf.upLabels, labId].val; IF key<1 THEN { key ¬ IntToIntTab.GetSize[callerInf.upLabels]+1; [] ¬ IntToIntTab.Store[callerInf.upLabels, labId, key]; recurse ¬ ConsId[recurse, list.first]; }; ENDLOOP; }; IF lambdaInf=NIL THEN lambdaInf ¬ LambdaLabelUsage[handlerId]; IF lambdaInf.purposeOfLambda#enableHandler THEN CantHappen; IF lambdaInf.callers=NIL THEN RETURN; --not used by handlers... [] ¬ IntToIntTab.Pairs[lambdaInf.upLabels, EachUpLabel]; FOR list: IdList ¬ recurse, list.rest WHILE list#NIL DO VisitHandler[list.first, NIL]; ENDLOOP; }; VisitLambdaInIdTab: IntCodeUtils.IdTabVisitor = { lambdaInf: LabelUsage ¬ NARROW[value]; IF lambdaInf.purposeOfLambda=enableHandler THEN { VisitHandler[id, lambdaInf]; } }; IntCodeUtils.Enumerate[tab, VisitLambdaInIdTab]; END; }; LambdaLabelUsage: PUBLIC PROC [id: IntCodeDefs.LogicalId] RETURNS [LabelUsage] = { tab: IntCodeUtils.IdTab ¬ globalPerModuleEnables; IF tab#NIL THEN { WITH IntCodeUtils.Fetch[tab, id] SELECT FROM lambdaInf: LabelUsage => RETURN [lambdaInf]; ENDCASE => ERROR CantHappen; }; InitIdToLambdaInf[]; RETURN [LambdaLabelUsage[id]]; }; ProcNesting: TYPE = REF ProcNestingRec; ProcNestingRec: TYPE = RECORD [nest: INT ¬ 0, procLabel: IntCodeDefs.LabelNode ¬ NIL, labTab: IntToIntTab.Table ¬ NIL]; globalProcNesting: ProcNesting ¬ NIL; ResetGlobalPerModuleNesting: PROC [] = { globalProcNesting ¬ NIL }; NestingInfo: PROC [] RETURNS [ProcNesting] = { IF globalProcNesting=NIL THEN globalProcNesting ¬ NEW[ProcNestingRec]; RETURN [globalProcNesting] }; IncEnableNesting: PUBLIC PROC [] = { pNesting: ProcNesting ¬ NestingInfo[]; pNesting.nest ¬ pNesting.nest+1; }; DecEnableNesting: PUBLIC PROC [] = { pNesting: ProcNesting ¬ NestingInfo[]; pNesting.nest ¬ pNesting.nest-1; IF pNesting.nest<0 THEN C2CBasics.CantHappen; }; InitializeNestingsCurrentLambda: PROC [pNesting: ProcNesting, procLabel: IntCodeDefs.LabelNode] = { nest: INT ¬ 0; Visit: IntCodeUtils.Visitor = { WITH node SELECT FROM var: Var => WITH var.location SELECT FROM locLoc: LocalVarLocation => RETURN [node];--don't find label ENDCASE => {}; operNode: OperNode => WITH operNode.oper SELECT FROM code: CodeOper => RETURN [node];--don't find label ENDCASE => {}; enableNode: EnableNode => { IntCodeUtils.MapNode[enableNode.handle.proc, Visit]; nest ¬ nest+1; IntCodeUtils.MapNodeList[enableNode.scope, Visit]; nest ¬ nest-1; RETURN [enableNode]; }; labelNode: IntCodeDefs.LabelNode => { IF labelNode.label.id#nullLogicalId THEN IF ~IntToIntTab.Insert[pNesting.labTab, labelNode.label.id, nest] THEN CantHappen; --label multiple defined }; gotoNode: IntCodeDefs.GotoNode => RETURN [node]; --don't find label lambdaNode: LambdaNode => RETURN [node]; --stop recursion, and, don't find label ENDCASE => NULL; IntCodeUtils.MapNode[node, Visit]; RETURN [node]; }; pNesting.procLabel ¬ procLabel; pNesting.labTab ¬ IntToIntTab.Create[]; IF procLabel.label.node=NIL THEN CantHappen; IntCodeUtils.MapNode[procLabel.label.node, Visit]; }; FindNest: PROC [pNesting: ProcNesting, id: IntCodeDefs.LogicalId] RETURNS [nest: INT] = { IF C2CBasics.labelWithLambda=NIL THEN ERROR CantHappen; IF pNesting.procLabel#C2CBasics.labelWithLambda THEN { InitializeNestingsCurrentLambda[pNesting, C2CBasics.labelWithLambda]; }; nest ¬ IntToIntTab.Fetch[pNesting.labTab, id].val; IF nest<0 THEN CantHappen; --label is not found in this proc }; PopsForJump: PUBLIC PROC [id: IntCodeDefs.LogicalId] RETURNS [pops: INT] = { pNesting: ProcNesting ¬ NestingInfo[]; pops ¬ pNesting.nest-FindNest[pNesting, id]; IF pops<0 THEN CantHappen; }; PopsForReturns: PUBLIC PROC [] RETURNS [pops: INT] = { pNesting: ProcNesting ¬ NestingInfo[]; pops ¬ pNesting.nest; IF pops<0 THEN CantHappen; }; C2CBasics.CallbackWhenC2CIsCalled[ResetGlobalPerModuleNesting]; C2CBasics.CallbackWhenC2CIsCalled[ResetGlobalPerModuleEnables]; END. Θ C2CEnablesImpl.mesa Copyright Σ 1987, 1988, 1989, 1990, 1991 by Xerox Corporation. All rights reserved. Christian Jacobi, 1987 Christian Jacobi, October 5, 1990 10:55:35 am PDT --finds all uplevel goto's of handlers and replaces the goto's with returning an appropriate constant. --find all lambdas and include them into the table --set purposes of lambdas: go through all lambdas in table; for each lambda recurse down checking whether sub node usage tells about beeing handlers or procedures --also: finds all declared labels --frame extensions won't cause uplevel gotos... --go through all handlers to find all direct uplevel gotos and replace them --also find out what other handlers are called, to build call graph --an uplevel goto is found --finally replace up level goto with key-- --go through all the handlers and -- go through all uplevel gotos; -- check whether upLevelness needs to propagate; recurse --entered a new procedure; compute labTab Κ «–(cedarcode) style•NewlineDelimiter ™codešœ™Kšœ ΟeœI™TKšœ™Kšœ1™1K˜šΟk ˜ Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ ˜ Kšœ ˜ K˜——šΟnœžœž˜Kšžœ@˜GKšžœ˜—šž˜Kšžœ-˜1—K˜Kšœžœžœžœ ˜!šŸœžœ!žœ˜Dšžœ"žœžœž˜6Kšžœžœžœ ˜&Kšžœ˜—Kšžœžœ˜K˜—K˜šœ+˜+šŸœžœ˜(Kšœ0˜0Kšœ˜K˜——šŸœžœ˜K™gKšœK˜KKšΟc2™2šžœ ˜šŸœ˜-šžœžœž˜šœ˜šžœžœž˜%šœ˜Kšœžœ/˜7šžœžœž˜šœžœ˜,Kšžœžœ ˜,Kšžœžœ ˜!—Kšžœ˜—Kšœ1žœg˜›Kšžœ ,˜:K˜—Kšžœ˜—Kšœ˜—Kšœžœ  &˜OKšžœ˜—Kšœ0˜0Kšžœ˜K˜—Kšœ,˜,Kšžœ˜—Kš ’™’K™!šžœ˜šŸ œžœ:˜JKšœ'˜'šžœžœž˜Kšœžœ #˜:šœF˜FKšœ% ˜6Kšœ˜—Kšœ3 ˜GKšžœ˜—K˜—šŸœ˜1šŸ œ˜#šžœžœž˜Kšœžœ  ˜9šœ˜š žœžœžœžœžœ˜=šžœžœž˜'KšœB˜BKšžœžœ˜——šžœžœž˜šœ˜šžœžœž˜Kšœ:˜:Kšžœ˜——Kšžœ˜—K˜—šœ˜š žœžœžœžœž˜<šžœžœž˜'KšœB˜BKšžœžœ˜!Kšœ/™/——K˜—šœ˜KšœG˜GK˜—Kšžœžœ˜—Kšœ&˜&Kšžœ˜K˜—Kšœžœ˜&Kšžœžœžœžœ˜3Kšœ2˜2Kšœ˜—Kšœ0˜0Kšžœ˜—Kš K™KKš C™Cšžœ˜šŸœ˜1Kšœžœ˜&šžœ)žœ˜1šŸ œžœ˜*Kšœ1˜1Kšžœ)žœ ˜;Kšœ2˜2K˜—šŸ œ˜'šžœžœž˜˜šžœ žœž˜šœ˜šžœžœž˜ Kšœ $œ˜<šžœ˜ šžœBžœ˜JKš ™Kšœžœ˜ Kšžœžœžœ ˜(Kšœ?˜?šžœžœ˜Kšœ0˜0Kšœ?˜?Kšœ˜—Kš *™*Kšžœ!˜'Kšœ˜—K˜——Kšœ˜—Kšžœ˜—K˜—šœ˜š žœžœžœžœžœ˜=šžœžœž˜'Kšœ=˜=Kšžœ˜——K˜—šœ˜š žœžœžœžœž˜<šžœžœž˜'Kšœ=˜=Kšžœ˜——K˜—Kšœžœ  ˜9Kšžœ˜—Kšœ*˜*Kšžœ˜K˜—Kšœ+˜+Kšœ6˜6K˜—K˜—Kšœ0˜0Kšžœ˜—K™"K™!K™9šžœ˜šŸ œžœ2˜DKšœžœ˜šŸ œ ˜+Kšœ˜šžœ-žœžœž˜AKšœ5˜5Kšœžœ˜ Kšžœ9žœžœ˜EKšœ7˜7šžœžœ˜Kšœ0˜0Kšœ7˜7Kšœ&˜&Kšœ˜—Kšžœ˜—Kšœ˜—Kšžœ žœžœ)˜>Kšžœ)žœ ˜;Kš žœžœžœžœ ˜?Kšœ8˜8šžœ#žœžœž˜7Kšœžœ˜Kšžœ˜—K˜—šŸœ˜1Kšœžœ˜&šžœ)žœ˜1Kšœ˜K˜—K˜—Kšœ0˜0Kšžœ˜—Kšœ˜—K˜šŸœžœžœžœ˜RKšœ1˜1šžœžœžœ˜šžœžœž˜,Kšœžœ˜-Kšžœžœ ˜—K˜—Kšœ˜Kšžœ˜Kšœ˜—K˜K˜Kšœ žœžœ˜'Kš œžœžœžœ)žœžœ˜wK˜šœ!žœ˜%šŸœžœ˜(Kšœž˜Kšœ˜K˜——šŸ œžœžœ˜.Kšžœžœžœžœ˜FKšžœ˜K˜—K˜šŸœžœžœ˜$Kšœ&˜&Kšœ ˜ K˜—K˜šŸœžœžœ˜$Kšœ&˜&Kšœ ˜ Kšžœžœ˜-K˜K˜—šŸœžœ>˜cKšœžœ˜šŸœ˜šžœžœž˜šœ ˜ šžœžœž˜Kšœžœ ˜=Kšžœ˜——šœ˜šžœžœž˜Kšœžœ ˜2Kšžœ˜——šœ˜Kšœ4˜4Kšœ˜Kšœ2˜2Kšœ˜Kšžœ˜K˜—šœ%˜%šžœ"ž˜(šžœ@˜BKšžœ  ˜)——Kšœ˜—Kšœ"žœ  ˜CKšœžœ  '˜PKšžœžœ˜—Kšœ"˜"Kšžœ˜K˜—Kšœ˜Kšœ'˜'Kšžœžœžœ ˜,Kšœ2˜2K˜—K˜šŸœžœ4žœžœ˜YKšžœžœžœžœ ˜7šžœ.žœ˜6Kš )™)KšœF˜FK˜—Kšœ2˜2Kšžœžœ  !˜