Scheme>SchemeCells.Mesa
Last Edited by: Spreitzer, February 23, 1984 10:49 pm
DIRECTORY BiScrollers, IO, OrderedSymbolTableRef, Rope, SchemeRep, SchemeEditing, ViewerClasses, ViewerTools, ViewRec;
SchemeCells: CEDAR PROGRAM
IMPORTS BiScrollers, IO, OrderedSymbolTableRef, Rope, SchemeEditing, ViewerTools, ViewRec
EXPORTS SchemeEditing =
BEGIN OPEN SchemeRep, SchemeEditing;
CreateCellType: PUBLIC PROC [session: Session, name: ROPE] =
BEGIN
session.ctlRV.DisplayMessage[ViewRec.clearMessagePlace];
IF session.typesTable.Lookup[name] # NIL THEN {session.ctlRV.DisplayMessage["Already exists"]; RETURN};
[] ← NewCellType[session, name, FALSE];
END;
CreateIcon: PUBLIC PROC [session: Session, cellTypeName, iconName: ROPE] =
BEGIN
cellType: CellType ← NARROW[session.typesTable.Lookup[cellTypeName]];
picName: ROPE ← cellTypeName.Cat["[", iconName, "]"];
pic: PictureDef;
session.ctlRV.DisplayMessage[ViewRec.clearMessagePlace];
IF cellType = NIL THEN {session.ctlRV.DisplayMessage["No such CellType"]; RETURN};
pic ← NARROW[cellType.icons.Lookup[iconName]];
IF pic # NIL THEN {session.ctlRV.DisplayMessage["Icon name taken"]; RETURN};
pic ← NewPicture[session, picName];
cellType.icons.Insert[pic];
END;
EditType: PUBLIC PROC [session: Session, cellTypeName, iconName: ROPE, part: SubjectClass] =
BEGIN
picName: ROPE ← cellTypeName.Cat["[", iconName, "]"];
cellType: CellType;
editor: Editor;
session.ctlRV.DisplayMessage[ViewRec.clearMessagePlace];
cellType ← NARROW[session.typesTable.Lookup[cellTypeName]];
IF cellType = NIL THEN {session.ctlRV.DisplayMessage["No such type"]; RETURN};
editor ← NEW [EditorRep ← [
session: session,
bs: NIL,
v: NIL,
subjectPic: SELECT part FROM
icon => NARROW[IF cellType.icons.Size[] = 1
THEN cellType.icons.LookupSmallest[]
ELSE cellType.icons.Lookup[picName]],
expansion => cellType.expansion,
ENDCASE => ERROR,
subjectCell: cellType,
subjectClass: part,
primary: NIL, secondary: NIL]];
IF editor.subjectPic = NIL THEN {session.ctlRV.DisplayMessage["No such icon"]; RETURN};
IF editor.subjectPic.editor # NIL THEN {session.ctlRV.DisplayMessage["Already being edited"]; RETURN};
editor.subjectPic.editor ← editor;
session.editors ← CONS[editor, session.editors];
editor.primary ← NEW [PointBackRep ← [primary: TRUE]];
editor.secondary ← NEW [PointBackRep ← [primary: FALSE]];
editor.bs ← BiScrollers.CreateBiScroller[class: editorClasses[part], info: [name: IO.PutFR["%g.%g", IO.rope[session.name], IO.rope[editor.subjectPic.name]], data: editor, iconic: FALSE]];
editor.v ← editor.bs.QuaViewer[];
END;
DestroyEditor: PUBLIC ViewerClasses.DestroyProc --PROC [self: Viewer]-- =
BEGIN
editor: Editor ← NARROW[BiScrollers.QuaBiScroller[self].ClientDataOf[]];
last: LIST OF Editor ← NIL;
IF editor.subjectPic.editor # editor THEN ERROR;
editor.subjectPic.editor ← NIL;
IF editor.session.mostRecentEditor = editor THEN editor.session.mostRecentEditor ← NIL;
FOR l: LIST OF Editor ← editor.session.editors, l.rest WHILE l # NIL DO
IF l.first = editor THEN {
IF last = NIL THEN editor.session.editors ← l.rest ELSE last.rest ← l.rest;
EXIT};
last ← l;
ENDLOOP;
editor.session ← NIL;
END;
NewCellType: PUBLIC PROC [session: Session, name: ROPE, skeletal: BOOLEAN] RETURNS [cellType: CellType] =
BEGIN
picName: ROPE ← name.Cat["[expansion]"];
cellType ← NEW [CellTypeRep ← [
name: name,
icons: OrderedSymbolTableRef.CreateTable[CompareNames],
expansion: NIL,
ports: OrderedSymbolTableRef.CreateTable[CompareNames],
nets: OrderedSymbolTableRef.CreateTable[CompareNames],
components: OrderedSymbolTableRef.CreateTable[CompareNames]]];
IF NOT skeletal THEN cellType.expansion ← NewPicture[session, picName];
session.typesTable.Insert[cellType];
ViewerTools.SetContents[session.typesMenu, ViewerTools.GetContents[session.typesMenu].Cat[" ", name]];
END;
NewComponent: PUBLIC PROC [editor: Editor] =
BEGIN
cellType: CellType ← NARROW[editor.session.typesTable.Lookup[editor.session.ctlPanel.cellType]];
icon: PictureDef;
comp: Component;
inst: PictureInstance;
IF cellType = NIL THEN {Complain[editor, "No such cell type"]; RETURN};
icon ← NARROW[IF cellType.icons.Size[] = 1 THEN cellType.icons.LookupSmallest[] ELSE cellType.icons.Lookup[editor.session.ctlPanel.icon]];
IF icon = NIL THEN {Complain[editor, "No such icon"]; RETURN};
IF editor.subjectCell.components.Lookup[editor.session.ctlPanel.name] # NIL
THEN {Complain[editor, "Instance name taken"]; RETURN};
inst ← CreateInstance[in: editor.subjectPic, of: icon, org: editor.primary.point];
comp ← CreateComponent[editor.subjectCell, cellType, editor.session.ctlPanel.name, inst];
END;
DeleteComponent: PUBLIC PROC [editor: Editor] =
BEGIN
Check: PROC [any: REF ANY] RETURNS [stop: BOOLEAN] =
{cp: ComponentPort ← NARROW[any]; stop ← FALSE;
IF NOT DeleteableNet[cp.point.net, cp.point] THEN {ok ← FALSE; Complain[editor, IO.PutFR[" port %g used by net %g", IO.rope[cp.port.name], IO.rope[cp.point.net.name]]]}};
Delete: PROC [any: REF ANY] RETURNS [stop: BOOLEAN] =
{cp: ComponentPort ← NARROW[any]; stop ← FALSE;
DeleteNet[from, cp.point.net];
DeletePoint[from.expansion, cp.point]};
org: Point ← editor.primary.point;
inst: PictureInstance ← FindPI[org];
comp: Component;
from: CellType ← editor.subjectCell;
ok: BOOLEANTRUE;
IF inst = NIL THEN RETURN;
IF inst.asComponent = NIL THEN RETURN;
comp ← inst.asComponent;
comp.ports.EnumerateIncreasing[Check];
IF NOT ok THEN RETURN;
comp.ports.EnumerateIncreasing[Delete];
IF comp.label # NIL THEN DeleteText[from.expansion, NIL, comp.label];
DeleteInstance[from.expansion, NIL, comp.inst];
IF org.dependents = NIL THEN DeletePoint[from.expansion, org];
[] ← from.components.Delete[comp];
END;
DeleteableNet: PROC [net: Net, pt: Point] RETURNS [deleteable: BOOLEAN] =
{deleteable ← TRUE;
IF net = NIL THEN RETURN;
FOR l: LORA ← net.stuff, l.rest WHILE l # NIL DO
WITH l.first SELECT FROM
p: Point => IF p # pt THEN deleteable ← FALSE;
l2: Line => deleteable ← FALSE;
t: Text => NULL;
ENDCASE => ERROR;
ENDLOOP};
DeleteNet: PROC [from: CellType, net: Net] =
BEGIN
IF net = NIL THEN RETURN;
FOR l: LORA ← net.stuff, l.rest WHILE l # NIL DO
WITH l.first SELECT FROM
p: Point => p.net ← NIL;
l2: Line => ERROR;
t: Text => {t.labelOf ← NIL; DeleteText[from.expansion, NIL, t]};
ENDCASE => ERROR;
ENDLOOP;
net.stuff ← NIL;
[] ← from.nets.Delete[net];
END;
DeletePoint: PUBLIC PROC [from: PictureDef, point: Point] =
BEGIN
IF point.dependents # NIL THEN ERROR;
[] ← from.points.Delete[point];
point.deleted ← TRUE;
point.c[X].dependents ← Filter[point.c[X].dependents, point];
point.c[Y].dependents ← Filter[point.c[Y].dependents, point];
IF Scavengeable[point.c[X]] THEN DeleteCoord[point.c[X]];
IF Scavengeable[point.c[Y]] THEN DeleteCoord[point.c[Y]];
END;
Scavengeable: PUBLIC PROC [coord: Coord] RETURNS [s: BOOLEAN] =
{s ← coord.dependents = NIL AND (coord.parent = NIL OR ISTYPE[coord.parent, Coord])};
DeleteCoord: PUBLIC PROC [coord: Coord] =
BEGIN
IF coord.dependents # NIL THEN ERROR;
IF coord.parent = NIL THEN NULL
ELSE WITH coord.parent SELECT FROM
c: Coord => c.dependents ← Filter[c.dependents, coord];
pi: PictureInstance => NULL--I hope--;
ENDCASE => ERROR;
END;
NewPort: PUBLIC PROC [editor: Editor] =
BEGIN
port: Port ← NARROW[editor.subjectCell.ports.Lookup[editor.session.ctlPanel.name]];
IF port # NIL THEN {Complain[editor, "Name taken"]; RETURN};
[] ← CreatePort[editor.subjectCell, editor.session.ctlPanel.name, editor.primary.point];
END;
DeletePort: PUBLIC PROC [editor: Editor] =
BEGIN
port: Port ← editor.primary.point.toPort;
from: CellType ← editor.subjectCell;
IF port = NIL THEN RETURN;
IF port.label # NIL THEN DeleteText[from.expansion, NIL, port.label];
IF DeleteableNet[port.pt.net, port.pt] THEN DeleteNet[from, port.pt.net];
IF port.pt.dependents = NIL THEN DeletePoint[from.expansion, port.pt];
[] ← from.ports.Delete[port];
END;
DeleteStrand: PUBLIC PROC [editor: Editor] =
BEGIN
strand: Line ← FindLine[editor.secondary.point, editor.primary.point];
newName: ROPE ← editor.session.ctlPanel.name;
from: CellType ← editor.subjectCell;
changes: LORA;
IF strand = NIL THEN RETURN;
IF from.nets.Lookup[newName] # NIL THEN {Complain[editor, "net name taken"]; RETURN};
strand.net.stuff ← Filter[strand.net.stuff, strand];
strand.net ← NIL;
changes ← BreakNet[from, editor.secondary.point, newName];
DeleteLine[from.expansion, NIL, NIL, strand];
END;
BreakNet: PROC [in: CellType, start: Point, name: ROPE] RETURNS [changes: LORA] =
BEGIN
Explore: PROC [from: Point] =
BEGIN
new.stuff ← CONS[from, new.stuff];
from.net ← new;
old.stuff ← Filter[old.stuff, from];
FOR la: LORA ← from.dependents, la.rest WHILE la # NIL DO
WITH la.first SELECT FROM
t: Text => ERROR;
l: Line => IF l.net = new THEN NULL
ELSE IF l.net = old THEN {
new.stuff ← CONS[l, new.stuff];
l.net ← new;
old.stuff ← Filter[old.stuff, l];
IF l.a = from THEN Explore[l.b] ELSE IF l.b = from THEN Explore[l.a] ELSE ERROR}
ELSE IF l.net # NIL THEN ERROR;
pi: PictureInstance => NULL;
ENDCASE => ERROR;
ENDLOOP;
END;
old: Net ← start.net;
new: Net ← NEW [NetRep ← [name: name]];
changes ← NIL;
Explore[start];
in.nets.Insert[new];
END;
NewStrand: PUBLIC PROC [editor: Editor, final: BOOLEAN] =
BEGIN
cellType: CellType ← editor.subjectCell;
strand: Line;
net: Net ← NIL;
changed: LORANIL;
a, b: Point;
IF final AND editor.strandGoal # NIL
THEN {a ← editor.primary.point; b ← editor.strandGoal}
ELSE {a ← editor.secondary.point; b ← editor.primary.point};
IF a.net = b.net AND a.net # NIL THEN
{Complain[editor, "Already connected"]; RETURN};
strand ← NewLine[editor.subjectPic, a, b];
IF strand = NIL THEN RETURN;
IF strand.a.net # NIL THEN net ← strand.a.net ELSE StartNet[cellType, strand.a];
IF strand.b.net # NIL THEN net ← strand.b.net ELSE StartNet[cellType, strand.b];
IF net = NIL THEN net ← strand.a.net;
strand.net ← net; net.stuff ← CONS[strand, net.stuff];
IF strand.a.net # net THEN changed ← JoinNet[cellType, strand.a.net, net];
IF strand.b.net # net THEN changed ← JoinNet[cellType, strand.b.net, net];
IF changed # NIL THEN NotifyLabels[changed, editor];
IF final THEN editor.strandGoal ← NIL;
END;
StartNet: PROC [cellType: CellType, point: Point] =
{point.net ← NEW [NetRep ← [name: NewName[cellType.nets], otherProps: NIL, stuff: LIST[point]]];
cellType.nets.Insert[point.net]};
JoinNet: PROC [in: CellType, from, to: Net] RETURNS [changed: LORA] =
BEGIN
FOR l: LORA ← from.stuff, l.rest WHILE l # NIL DO
WITH l.first SELECT FROM
point: Point => IF point.net # to THEN
{to.stuff ← CONS[point, to.stuff]; point.net ← to};
line: Line => IF line.net # to THEN
{to.stuff ← CONS[line, to.stuff]; line.net ← to};
label: Text => IF label.labelOf = from THEN
{to.stuff ← CONS[label, to.stuff]; label.labelOf ← to;
label.rope ← to.name; changed ← CONS[label, changed]};
ENDCASE => ERROR;
ENDLOOP;
from.stuff ← NIL;
from.eatenBy ← to;
[] ← in.nets.Delete[from];
END;
BreakWire: PUBLIC PROC [editor: Editor, input: LORA] RETURNS [output: LORA] =
BEGIN
new: Line;
strand: Line ← FindLine[editor.secondary.point, editor.primary.point];
cellType: CellType ← editor.subjectCell;
pic: PictureDef ← cellType.expansion;
mv: Vertex;
mp: Point;
output ← input.rest;
IF strand = NIL THEN {Complain[editor, "No strand between primary & secondary"]; RETURN};
mv[X] ← NewCoord[axis: X, at: (strand.a.c[X].z + strand.b.c[X].z)/2, pic: pic];
mv[Y] ← NewCoord[axis: Y, at: (strand.a.c[Y].z + strand.b.c[Y].z)/2, pic: pic];
mp ← MakePoint[pic: pic, vertex: mv];
mp.net ← strand.net;
mp.net.stuff ← CONS[mp, mp.net.stuff];
new ← NewLine[pic, strand.a, mp];
new.net ← strand.net;
new.net.stuff ← CONS[new, new.net.stuff];
SetBackToPoint[editor, editor.primary, mp];
strand.a ← mp;
NotifyCoord[mp.c[X], editor];
NotifyCoord[mp.c[Y], editor];
END;
JoinWire: PUBLIC PROC [editor: Editor, input: LORA] RETURNS [output: LORA] =
BEGIN
l1, l2: Line ← NIL;
tooMany: BOOLEAN;
mp: Point ← editor.primary.point;
l1p: Point;
cellType: CellType ← editor.subjectCell;
pic: PictureDef ← cellType.expansion;
output ← input.rest;
IF mp = NIL THEN {Complain[editor, "primary empty"]; RETURN};
IF mp.deleted THEN ERROR;
FOR la: LORA ← mp.dependents, la.rest WHILE la # NIL DO
WITH la.first SELECT FROM
t: Text => NULL;
l: Line => IF l1 = NIL THEN l1 ← l ELSE IF l2 = NIL THEN l2 ← l ELSE {tooMany ← TRUE; EXIT};
pi: PictureInstance => NULL;
ENDCASE => ERROR;
ENDLOOP;
IF tooMany THEN {Complain[editor, "Too many lines attached"]; RETURN};
l1p ← IF l1.a = mp THEN l1.b ELSE l1.a;
l1.net.stuff ← Filter[l1.net.stuff, l1];
l1.net ← NIL;
mp.net.stuff ← Filter[mp.net.stuff, mp];
mp.net ← NIL;
DeletePoint[from: pic, point: mp];
DeleteLine[pic: pic, a: NIL, b: NIL, line: l1];
IF l2.a = mp THEN l2.a ← l1p ELSE l2.b ← l1p;
NotifyCoord[mp.c[X], editor];
NotifyCoord[mp.c[Y], editor];
END;
CreatePort: PUBLIC PROC [cellType: CellType, name: ROPE, point: Point] RETURNS [port: Port] =
BEGIN
port ← NEW [PortRep ← [name: name, pt: point]];
cellType.ports.Insert[port];
END;
CreateComponent: PUBLIC PROC [in, of: CellType, name: ROPE, inst: PictureInstance] RETURNS [comp: Component] =
BEGIN
CreateComponentPort: PROC [any: REF ANY] RETURNS [stop: BOOLEAN] =
{port: Port ← NARROW[any];
cp: ComponentPort ← NEW [ComponentPortRep ← [component: comp, port: port]];
cp.point ← NARROW[in.expansion.points.Lookup[
PIPointName[comp.inst.name, port.name]]];
stop ← FALSE;
comp.ports.Insert[cp];
cp.point.fromCP ← cp};
comp ← NEW [ComponentRep ← [name: name, type: of, inst: inst]];
comp.inst.asComponent ← comp;
in.components.Insert[comp];
comp.type.ports.EnumerateIncreasing[CreateComponentPort];
END;
END.