TestPipalCD.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reversed.
Created by Bertrand Serlet, June 4, 1987 2:34:25 pm PDT
Bertrand Serlet, May 26, 1988 6:37:02 pm PDT
DIRECTORY
Basics, CardTab, CD, IO, List,
Pipal, PipalCD, PipalIO, PipalOps, PipalUI,
PW, RefTab, Rope, TerminalIO;
TestPipalCD: CEDAR PROGRAM
IMPORTS Basics, CardTab, IO, 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 REFNIL] = {
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, onlyOne: BOOLFALSE] RETURNS [equals: PipalOps.ReplaceTable] = {
nbCollisions, nbReallyEqual: INT ← 0;
FillHashed: RefTab.EachPairAction = {
hash: CARD ← Pipal.Hash[key];
previous: Pipal.Objects ← NARROW [CardTab.Fetch[hashed, hash].val];
new: Pipal.Objects ← CONS [key, previous];
[] ← CardTab.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;
quit ← onlyOne;
RETURN;
};
ENDLOOP;
};
PrintCollision: CardTab.EachPairAction = {
previous: Pipal.Objects ← NARROW [val];
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: CardTab.Ref ← CardTab.Create[];
equals ← RefTab.Create[];
FillTableFromRoot[root, table];
IF RefTab.Pairs[table, FillHashed] THEN RETURN;
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"];
[] ← CardTab.Pairs[hashed, PrintCollision];
};
END.