-- File: DisjointColapse.mesa
-- routines to remove small symbols
-- Written by Martin Newell/Dan Fitzpatrick June 1981
-- Last edited: June 25, 1981 10:30 PM

DIRECTORY


DisjointTypes: FROM "DisjointTypes" USING [Instance, Symbol, Geometry, PropID, PropList],
DisjointAllocDefs: FROM "DisjointAllocDefs" USING [EnumerateSymbols,
AllocateGeometry, AllocateInstance, FreeGeometry, FreeInstance, FreeSymbol],
DisjointColapseDefs: FROM "DisjointColapseDefs",
DisjointPropDefs: FROM "DisjointPropDefs" USING [AllocPropID, PutProp, GetProp, RemoveProp],
IODefs: FROM "IODefs" USING [WriteLine],
MiscDefs: FROM "MiscDefs" USING [CallDebugger];

DisjointColapse: PROGRAM
IMPORTS DisjointAllocDefs, DisjointPropDefs, IODefs, MiscDefs
EXPORTS DisjointColapseDefs =
BEGIN
OPEN DisjointAllocDefs, DisjointPropDefs, DisjointTypes, IODefs, MiscDefs;

SetColapseSize: PUBLIC PROCEDURE [n:INTEGER] =
BEGIN
IF n < 0 THEN WriteLine["can’t call SetColapseSize with negative value"]
ELSE ColapseSize ← n;
END;

Colapse: PUBLIC PROCEDURE[symb: Symbol] =
BEGIN

Mark: PROC[symb: Symbol] RETURNS[BOOLEAN] =
BEGIN
PutProp[@symb.prop,markID,1];
RETURN[FALSE];
END; -- Proc Mark

Remove: PROC[symb: Symbol] RETURNS[BOOLEAN] =
BEGIN
n: INTEGER ← GetProp[symb.prop,markID];
IF n = 2 THEN ReleaseSymbol[symb];-- throw away, too small
RemoveProp[symb.prop,markID];
RETURN[FALSE];
END; -- Proc Remove

markID ← AllocPropID[];
[] ← EnumerateSymbols[Mark];
DoColapse[symb];
PutProp[@symb.prop,markID,3];-- be careful not to throw away
[] ← EnumerateSymbols[Remove];
END;

DoColapse: PROCEDURE[symb: Symbol] =
BEGIN
n: INTEGER;
next: Instance ← symb.insts;
symb.insts ← NIL;
FOR in:Instance ← next,next UNTIL in = NIL DO
next ← in.next;
n ← GetProp[in.symbol.prop,markID];
IF n = 1 THEN {-- never seen before
DoColapse[in.symbol];
n ← GetProp[in.symbol.prop,markID];
};
SELECT n FROM
2 => Combine[symb,in];-- throw away, too small
3 => {in.next ← symb.insts; symb.insts ← in};-- do nothing
ENDCASE => CallDebugger["bad mark value in Colapse"];-- bug
ENDLOOP;
-- count instances and geoms
n ← 0;
FOR in:Instance ← symb.insts,in.next UNTIL in = NIL DO
n ← n + 1;
ENDLOOP;
FOR g:Geometry ← symb.geom,g.next UNTIL g = NIL DO
n ← n + 1;
ENDLOOP;
IF n > ColapseSize THEN PutProp[@symb.prop,markID,3]
ELSE PutProp[@symb.prop,markID,2];
END;

Combine: PROCEDURE[symb: Symbol, inst:Instance] =
BEGIN
osymb: Symbol ← inst.symbol;
-- copy instances and geom of osymb onto symb
FOR in:Instance ← osymb.insts,in.next UNTIL in = NIL DO
new: Instance ← AllocateInstance[];
new↑ ← [
next: symb.insts,
symbol: in.symbol,
xOffset: in.xOffset,
yOffset: in.yOffset
];
symb.insts ← new;
ENDLOOP;
FOR g:Geometry ← osymb.geom,g.next UNTIL g = NIL DO
new: Geometry ← AllocateGeometry[];
new↑ ← [
next: symb.geom,
layer: g.layer,
l: g.l,
b: g.b,
r: g.r,
t: g.t
];
symb.geom ← new;
ENDLOOP;
-- now free inst
FreeInstance[inst];
END;

ReleaseSymbol: PROCEDURE[symb: Symbol] =
BEGIN
nexti: Instance;
nextg: Geometry;
-- delete instances and geom of symb
FOR in:Instance ← symb.insts,nexti UNTIL in = NIL DO
nexti ← in.next;
FreeInstance[in];
ENDLOOP;
FOR g:Geometry ← symb.geom,nextg UNTIL g = NIL DO
nextg ← g.next;
FreeGeometry[g];
ENDLOOP;
-- now free symb
FreeSymbol[symb];
END;

markID: PropID;
ColapseSize: INTEGER ← 0;

END.