<> <> <> <> <<>> DIRECTORY Basics, CD, IO, IntHashTable, List, Pipal, PipalCD, PipalIO, PipalOps, PipalUI, PW, RefTab, Rope, TerminalIO; TestPipalCD: CEDAR PROGRAM IMPORTS Basics, IO, IntHashTable, List, Pipal, PipalCD, PipalIO, PipalOps, PipalUI, PW, RefTab, Rope, TerminalIO = BEGIN ConvertAndSaveDesign: PROC [design: PipalUI.Design] = { object: Pipal.Object _ PipalUI.DesignRoot[design]; directory: PipalIO.Directory _ NARROW [object]; [] _ PipalIO.SaveObject[Rope.Cat[directory.name, ".directory"], directory]; }; Draw: PUBLIC PROC [object: Pipal.Object] RETURNS [design: CD.Design] = { design _ PW.Draw[PipalCD.PToCDObject[object].cdobj]; }; InOut: PROC [in: Pipal.Object] RETURNS [out: Pipal.Object] = { [] _ PipalIO.SaveObject["TestPipalCDIO", in]; out _ PipalIO.RestoreObject["TestPipalCDIO"]; }; ObjectStat: TYPE = REF ObjectStatRec; ObjectStatRec: TYPE = RECORD [ nbChildren: INT _ -1, -- -1 means no child nbTimesSeen: INT _ 1 ]; CountObjects: PROC [root: Pipal.Object, table: RefTab.Ref] = { Each: PipalOps.EachChildProc = { stat.nbChildren _ stat.nbChildren + 1; CountObjects[child, table]; }; stat: ObjectStat _ NARROW [RefTab.Fetch[table, root].val]; IF stat#NIL THEN {stat.nbTimesSeen _ stat.nbTimesSeen+1; RETURN}; stat _ NEW [ObjectStatRec]; [] _ RefTab.Store[table, root, stat]; IF PipalOps.HasEnumerate[root] THEN { stat.nbChildren _ 0; [] _ PipalOps.Enumerate[root, Each]; }; }; ClassStat: TYPE = REF ClassStatRec; ClassStatRec: TYPE = RECORD [ class: Pipal.Class, nbChildren: INT, sigmaSeen: INT, nbObjects: INT _ 1 ]; CountClasses: PROC [table: RefTab.Ref] RETURNS [stats: LIST OF REF _ NIL] = { Each: RefTab.EachPairAction = { class: Pipal.Class = Pipal.ObjectClass[key]; ostat: ObjectStat = NARROW [val]; FOR list: LIST OF REF _ stats, list.rest WHILE list#NIL DO stat: ClassStat _ NARROW [list.first]; IF stat.class=class AND stat.nbChildren=ostat.nbChildren THEN { stat.sigmaSeen _ stat.sigmaSeen+ ostat.nbTimesSeen; stat.nbObjects _ stat.nbObjects + 1; RETURN; }; ENDLOOP; stats _ CONS [NEW [ClassStatRec _ [class: class, nbChildren: ostat.nbChildren, sigmaSeen: ostat.nbTimesSeen]], stats]; }; [] _ RefTab.Pairs[table, Each]; }; SortBySize: List.CompareProc = { stat1: ClassStat = NARROW [ref1]; stat2: ClassStat = NARROW [ref2]; RETURN [Basics.CompareInt[ABS [stat2.nbChildren]*stat2.nbObjects, ABS [stat1.nbChildren]*stat1.nbObjects]]; }; SortByClassNbChildren: List.CompareProc = { stat1: ClassStat = NARROW [ref1]; stat2: ClassStat = NARROW [ref2]; RETURN [SELECT Rope.Compare[Pipal.ClassName[stat2.class], Pipal.ClassName[stat1.class]] FROM less => less, greater => greater, ENDCASE => Basics.CompareInt[stat2.nbChildren, stat1.nbChildren] ]; }; PrintStats: PROC [stats: LIST OF REF] = { FOR list: LIST OF REF _ stats, list.rest WHILE list#NIL DO stat: ClassStat _ NARROW [list.first]; TerminalIO.PutF[ "\t%g:\t%g objects,\t%g children,\t%g daggys,\t%g in size.\n", IO.rope[Pipal.ClassName[stat.class]], IO.int[stat.nbObjects], IO.int[stat.nbChildren], IO.real[stat.sigmaSeen], IO.int[stat.nbObjects*ABS [stat.nbChildren]] ]; ENDLOOP; }; Stats: PROC [root: Pipal.Object] = { table: RefTab.Ref _ RefTab.Create[]; stats: LIST OF REF; CountObjects[root, table]; TerminalIO.PutF["\n\nNumber of different objects: %g.\n", IO.int[RefTab.GetSize[table]]]; stats _ CountClasses[table]; TerminalIO.PutF["\nSort by size:\n"]; stats _ List.Sort[stats, SortBySize]; PrintStats[stats]; TerminalIO.PutF["\nSort by class:\n"]; stats _ List.Sort[stats, SortByClassNbChildren]; PrintStats[stats]; }; FillTableFromRoot: PROC [root: Pipal.Object, table: RefTab.Ref] = { Each: PipalOps.EachChildProc = {FillTableFromRoot[child, table]}; IF RefTab.Fetch[table, root].val#NIL THEN RETURN; [] _ RefTab.Store[table, root, $Foo]; IF PipalOps.HasEnumerate[root] THEN [] _ PipalOps.Enumerate[root, Each]; }; FindEquals: PROC [root: Pipal.Object] RETURNS [equals: PipalOps.ReplaceTable] = { nbCollisions, nbReallyEqual: INT _ 0; FillHashed: RefTab.EachPairAction = { hash: INT _ LOOPHOLE [Pipal.Hash[key]]; previous: Pipal.Objects _ NARROW [IntHashTable.Fetch[hashed, hash].value]; new: Pipal.Objects _ CONS [key, previous]; [] _ IntHashTable.Store[hashed, hash, new]; IF previous=NIL THEN RETURN; nbCollisions _ nbCollisions + 1; FOR list: Pipal.Objects _ previous, list.rest WHILE list#NIL DO IF Pipal.Equal[list.first, key] THEN { [] _ RefTab.Store[equals, key, list.first]; nbReallyEqual _ nbReallyEqual+1; RETURN; }; ENDLOOP; }; PrintCollision: IntHashTable.EachPairAction = { previous: Pipal.Objects _ NARROW [value]; IF previous.rest=NIL THEN RETURN; TerminalIO.PutF["%g:\t%g.\n", IO.int[key], IO.rope[Pipal.DescribeToRope[previous, 0, 2]]]; }; table: RefTab.Ref _ RefTab.Create[]; hashed: IntHashTable.Table _ IntHashTable.Create[]; equals _ RefTab.Create[]; FillTableFromRoot[root, table]; [] _ RefTab.Pairs[table, FillHashed]; TerminalIO.PutF["\nNumber of different objects: %g.\n", IO.int[RefTab.GetSize[table]]]; TerminalIO.PutF["\nNumber of collisions: %g.\n", IO.int[nbCollisions]]; TerminalIO.PutF["\nNumber of really equal: %g.\n", IO.int[nbReallyEqual]]; TerminalIO.PutF["\nCollisions:\n"]; [] _ IntHashTable.Pairs[hashed, PrintCollision]; }; END.