CoreOpsImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Barth, January 30, 1986 9:38:27 am PST
Spreitzer, April 8, 1986 4:34:16 pm PST
Bertrand Serlet May 29, 1986 7:37:33 pm PDT
Louis Monier May 1, 1986 4:44:41 pm PDT
Pradeep Sindhu February 24, 1986 6:48:20 pm PST
DIRECTORY CedarProcess, Commander, Core, CoreOps, CoreProperties, HashTable, IO, ProcessProps, Rope, RopeList;
CoreOpsImpl: CEDAR PROGRAM
IMPORTS CedarProcess, CoreProperties, HashTable, IO, ProcessProps, Rope, RopeList
EXPORTS CoreOps =
BEGIN OPEN Core, CoreOps;
Property
nameProp: PUBLIC ATOM ← CoreProperties.RegisterProperty[$CoreName, CoreProperties.Props[[CoreProperties.propCopy, CoreProperties.PropDoCopy], [CoreProperties.propPrint, CoreProperties.PropDontPrint]]];
Cell Classes
printClassProcProp: ATOM ← CoreProperties.RegisterProperty[$CorePrintClassProc];
SetClassPrintProc: PUBLIC PROC [class: CellClass, proc: PrintClassProc] RETURNS [sameClass: CellClass] = {
CoreProperties.PutCellClassProp[on: class, prop: printClassProcProp, value: NEW[PrintClassProc ← proc]];
sameClass ← class;
};
Cell Types
CreateCellType: PUBLIC PROC [class: CellClass, public: Wire, data: REF ANYNIL, name: ROPENIL, props: Properties ← NIL] RETURNS [cellType: CellType] = {
cellType ← NEW [CellTypeRec ← [class: class, public: public, data: data, properties: props]];
IF name#NIL THEN cellType ← SetCellTypeName[cellType, name];
};
SetCellTypeName: PUBLIC PROC [cellType: CellType, name: ROPE] RETURNS [sameCellType: CellType] = {
CoreProperties.PutCellTypeProp[cellType, nameProp, name];
sameCellType ← cellType;
};
GetCellTypeName: PUBLIC PROC [cellType: CellType] RETURNS [name: ROPENIL] = {
name ← NARROW [CoreProperties.GetCellTypeProp[cellType, nameProp]];
};
recastCacheProp: ATOM ← CoreProperties.RegisterProperty[$CoreRecastCache];
Recast: PUBLIC RecastProc = {
value: REF ← CoreProperties.GetCellTypeProp[me, recastCacheProp];
IF value#NIL THEN RETURN [NARROW[value]];
new ← me.class.recast[me];
CoreProperties.PutCellTypeProp[me, recastCacheProp, new];
};
ToBasic: PUBLIC PROC [cellType: Core.CellType] RETURNS [basic: Core.CellType] = {
FOR basic ← cellType, Recast[basic] UNTIL basic.class.recast = NIL DO NULL ENDLOOP;
};
PrintCellType: PUBLIC PROC [cellType: CellType, out: STREAMNIL, indent: NAT ← 0, level: NAT ← 2] = {
classProc: REF PrintClassProc;
IF out=NIL THEN out ← NARROW[ProcessProps.GetProp[$CommanderHandle], Commander.Handle].out;
IO.PutF[out,
"\n\n%g: %g Cell Type",
[rope[GetCellTypeName[cellType]]],
[rope[cellType.class.name]]
];
IO.PutRope[out, "\nPublic wire:"];
PrintWire[cellType.public, out, indent+1, level];
IF (classProc ← NARROW [CoreProperties.GetProp[from: cellType.class.properties, prop: printClassProcProp]]) # NIL THEN classProc[cellType.data, out, indent, level];
CoreProperties.PrintProperties[props: cellType.properties, out: out, indent: indent, level: level];
};
PrintIndent: PUBLIC PROC [indent: NAT, out: STREAM, cr: BOOLTRUE] = {
IF cr
THEN {
IO.PutChar[out, IO.CR];
FOR i: NAT IN [0..indent) DO IO.PutRope[out, " "] ENDLOOP
}
ELSE IO.PutRope[out, ", "]
};
Wire Creation
CreateWire: PUBLIC PROC [elements: Wires ← NIL, name: ROPENIL, props: Properties ← NIL] RETURNS [wire: Wire] = {
size: NAT ← 0;
FOR c: Wires ← elements, c.rest UNTIL c=NIL DO
size ← size + 1;
ENDLOOP;
wire ← CreateWires[size, name, props];
size ← 0;
FOR c: Wires ← elements, c.rest UNTIL c=NIL DO
wire[size] ← c.first;
size ← size + 1;
ENDLOOP;
};
CreateWires: PUBLIC PROC [size: NAT, name: ROPENIL, props: Properties ← NIL] RETURNS [wire: Wire] = {
wire ← NEW[WireRec[size]];
wire.properties ← props;
IF name#NIL THEN CoreProperties.PutWireProp[wire, nameProp, name];
};
SubrangeWire: PUBLIC PROC [wire: Wire, start, size: NAT, name: ROPENIL, props: Properties ← NIL] RETURNS [sub: Wire] = {
sub ← CreateWires[size, name, props];
FOR i: NAT IN [0 .. size) DO
sub[i] ← wire[start+i];
ENDLOOP;
};
CopyWire: PUBLIC PROC [wire: Wire] RETURNS [new: Wire] = {
Copy: PROC [wire: Wire] RETURNS [new: Wire] = {
IF (new ← NARROW[HashTable.Fetch[table: visitTab, key: wire].value])=NIL THEN {
new ← CreateWires[size: wire.size, props: CoreProperties.CopyProps[propList: wire.properties]];
IF NOT HashTable.Insert[table: visitTab, key: wire, value: new] THEN ERROR;
FOR i: NAT IN [0 .. wire.size) DO
new[i] ← Copy[wire[i]];
ENDLOOP;
};
};
visitTab: HashTable.Table ← HashTable.Create[]; -- Wire to Wire
new ← IF wire=NIL THEN NIL ELSE Copy[wire];
};
UnionWire: PUBLIC PROC [wire1, wire2: Wire, name: ROPENIL, props: Properties ← NIL] RETURNS [union: Wire] = {
IF wire1 = NIL THEN RETURN [wire2]; -- BS thinks we should get rid of this test one day
IF wire2 = NIL THEN RETURN [wire1]; -- BS thinks we should get rid of this test one day
union ← CreateWires[size: wire1.size+wire2.size, name: name, props: props];
FOR i: NAT IN [0 .. wire1.size) DO union[i] ← wire1[i] ENDLOOP;
FOR i: NAT IN [0 .. wire2.size) DO union[wire1.size+i] ← wire2[i] ENDLOOP;
};
Wire Enumeration
VisitWire: PUBLIC PROC [wire: Wire, eachWire: EachWireProc] RETURNS [quit: BOOL] = {
subWires: BOOL;
[subWires, quit] ← eachWire[wire];
IF quit OR NOT subWires THEN RETURN;
FOR i: NAT IN [0 .. wire.size) DO
IF VisitWire[wire[i], eachWire] THEN RETURN [TRUE];
ENDLOOP;
quit ← FALSE;
};
VisitAtomicWires: PUBLIC PROC [wire: Wire, eachWire: PROC [Wire]] = {
IF wire.size=0
THEN eachWire[wire]
ELSE FOR i: NAT IN [0 .. wire.size) DO VisitAtomicWires[wire[i], eachWire] ENDLOOP;
};
VisitBinding: PUBLIC PROC [actual, public: Wire, eachWirePair: EachWirePairProc] RETURNS [quit: BOOL] = {
subWires: BOOL;
IF actual.size#public.size THEN RETURN [TRUE]; -- wires do not conform
[subWires, quit] ← eachWirePair[actual, public];
IF quit OR NOT subWires THEN RETURN;
FOR i: NAT IN [0 .. actual.size) DO
IF VisitBinding[actual[i], public[i], eachWirePair] THEN RETURN [TRUE];
ENDLOOP;
quit ← FALSE;
};
Conform: PUBLIC PROC [actual, public: Wire] RETURNS [BOOL] = {
EachWirePair: EachWirePairProc = {};
RETURN [NOT VisitBinding[actual, public, EachWirePair]];
};
WireBits: PUBLIC PROC [wire: Wire] RETURNS [bits: NAT] = {
visitTab: HashTable.Table ← HashTable.Create[]; -- Wire to ATOM
CountBits: PROC [wire: Wire] RETURNS [bits: NAT ← 0] = {
IF NOT HashTable.Fetch[table: visitTab, key: wire].found THEN {
IF wire.size=0 THEN bits ← 1
ELSE FOR sub: NAT IN [0..wire.size) DO
bits ← bits + CountBits[wire[sub]];
ENDLOOP;
IF NOT HashTable.Insert[table: visitTab, key: wire, value: $Counted] THEN ERROR;
};
};
bits ← CountBits[wire];
};
Wire Naming
GetShortWireName: PUBLIC PROC [wire: Wire] RETURNS [name: ROPENIL] = {
name ← IF wire=NIL THEN NIL ELSE NARROW [CoreProperties.GetWireProp[wire, nameProp]];
};
SetShortWireName: PUBLIC PROC [wire: Wire, name: ROPE] RETURNS [sameWire: Wire] = {
IF wire#NIL THEN CoreProperties.PutWireProp[wire, nameProp, name];
sameWire ← wire;
};
GetWireIndex: PUBLIC PROC [wire: Wire, name: ROPE] RETURNS [n: INT ← -1] ~ {
IF wire#NIL THEN FOR i: NAT IN [0..wire.size) DO
IF Rope.Equal[name, GetShortWireName[wire[i]]] THEN RETURN [i];
ENDLOOP;
};
wireToNamesCacheProp: ATOM ← CoreProperties.RegisterProperty[$CoreWireToNamesCache, CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]];
Association wire -> list of full names
nameToWireCacheProp: ATOM ← CoreProperties.RegisterProperty[$CoreNameToWireCache, CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]];
Association full name -> wire
FullWireNames: PRIVATE PROC [root: Wire] RETURNS [wireToNames, nameToWire: HashTable.Table] = {
SetName: PUBLIC PROC [wire: Wire, name: ROPE] = {
names: LIST OF ROPENARROW [HashTable.Fetch[wireToNames, wire].value];
previousWire: Wire ← NARROW [HashTable.Fetch[nameToWire, name].value];
IF name#NIL AND NOT RopeList.Memb[names, name] THEN {
names ← CONS [name, names];
[] ← HashTable.Store[wireToNames, wire, names];
};
IF name#NIL AND ~HashTable.Insert[nameToWire, name, wire] AND previousWire#wire THEN ERROR; -- two different wires have the same name relative to this root
FOR i: NAT IN [0 .. wire.size) DO
short: ROPE ← GetShortWireName[wire[i]];
SetName[wire[i], SELECT TRUE FROM
short=NIL => Rope.Cat[name, "[", IO.PutR1[IO.int[i]], "]"],
name=NIL => short,
ENDCASE => Rope.Cat[name, ".", short]];
ENDLOOP;
};
wireToNames ← NARROW [CoreProperties.GetWireProp[root, wireToNamesCacheProp]];
nameToWire ← NARROW [CoreProperties.GetWireProp[root, nameToWireCacheProp]];
IF wireToNames#NIL AND nameToWire#NIL THEN RETURN;
wireToNames ← HashTable.Create[WireBits[root]];
nameToWire ← HashTable.Create[WireBits[root], HashTable.RopeEqual, HashTable.HashRope];
SetName has GetShortWireName[wire] instead of NIL to make full names also work for wires in their own context, as in Sisyph.
SetName[root, GetShortWireName[root]];
CoreProperties.PutWireProp[root, wireToNamesCacheProp, wireToNames];
CoreProperties.PutWireProp[root, nameToWireCacheProp, nameToWire];
};
GetFullWireNames: PUBLIC PROC [root, wire: Wire] RETURNS [names: LIST OF ROPE ] = {
names ← NARROW [HashTable.Fetch[FullWireNames[root].wireToNames, wire].value];
};
GetFullWireName: PUBLIC PROC [root, wire: Wire] RETURNS [name: ROPE ] = {
names: LIST OF ROPE ← GetFullWireNames[root, wire];
IF names=NIL OR names.rest#NIL THEN ERROR; -- one full name only for this wire, please
name ← names.first;
};
IsFullWireName: PUBLIC PROC [root, wire: Wire, name: ROPE] RETURNS [BOOL] = {
RETURN [RopeList.Memb[GetFullWireNames[root, wire], name]]
};
FindWire: PUBLIC PROC [root: Wire, name: ROPE] RETURNS [wire: Wire ← NIL] = {
wire ← NARROW [HashTable.Fetch[FullWireNames[root].nameToWire, name].value];
};
ParseWireName: PUBLIC PROC [name: ROPE] RETURNS [base: ROPE, components: LIST OF ROPENIL] = {
endBase: INTMIN [Rope.Index[name, 0, "."], Rope.Index[name, 0, "["]];
base ← Rope.Substr[name, 0, endBase];
name ← Rope.Substr[name, endBase];
WHILE Rope.Length[name]#0 DO
SELECT Rope.Fetch[name] FROM
'[  => {
endBracket: INT ← Rope.Find[name, "]"];
IF endBracket=-1 THEN ERROR; -- malformed name
components ← CONS [Rope.Substr[name, 1, endBracket-1], components];
name ← Rope.Substr[name, endBracket+1];
};
'.  => {
endField: INTMIN [Rope.Index[name, 1, "."], Rope.Index[name, 1, "["]];
components ← CONS [Rope.Substr[name, 1, endField-1], components];
name ← Rope.Substr[name, endField];
};
ENDCASE => ERROR; -- malformed name
ENDLOOP;
components ← RopeList.Reverse[components];
};
PrintWire: PUBLIC PROC [wire: Wire, out: STREAMNIL, indent: NAT ← 0, level: NAT ← 2] = {
name: ROPE ← GetShortWireName[wire];
PrintAWire: PROC [wire: Wire, indent: NAT, level: NAT, name: ROPE, cr, firstWire: BOOL] = {
CedarProcess.CheckAbort[];
PrintIndent[indent, out, cr OR firstWire];
IO.PutRope[out, name];
IF wire.size#0 THEN IO.PutF[out, ", %g elements", IO.int[wire.size]];
CoreProperties.PrintProperties[props: wire.properties, out: out, indent: indent+1, cr: cr, level: level];
IF level=0 AND wire.size#0 THEN IO.PutRope[out, " [...] "] ELSE FOR i: NAT IN [0 .. wire.size) DO
subName: ROPE ← GetShortWireName[wire[i]];
IF subName=NIL THEN subName ← IO.PutFR["[%g]", IO.int[i]];
PrintAWire[wire[i], indent+1, level-1, subName, cr AND wire.size<=32, cr AND i=0];
ENDLOOP;
};
IF out=NIL THEN out ← NARROW[ProcessProps.GetProp[$CommanderHandle], Commander.Handle].out;
PrintAWire[wire, indent, level, IF name#NIL THEN name ELSE "<no name>", TRUE, TRUE];
};
FlushNameCaches: PUBLIC PROC [root: Wire] = {
CoreProperties.PutWireProp[root, wireToNamesCacheProp, NIL];
CoreProperties.PutWireProp[root, nameToWireCacheProp, NIL];
};
Wire List Operations
Reverse: PUBLIC PROC [wires: Wires] RETURNS [revWires: Wires ← NIL] = {
WHILE wires#NIL DO revWires ← CONS [wires.first, revWires]; wires ← wires.rest ENDLOOP;
};
Delete: PUBLIC PROC [wires: Wires, wire: Wire] RETURNS [newWires: Wires ← NIL] = {
WHILE wires#NIL DO
IF wires.first#wire THEN newWires ← CONS [wires.first, newWires];
wires ← wires.rest;
ENDLOOP;
};
Member: PUBLIC PROC [wires: Wires, wire: Wire] RETURNS [BOOL] = {
WHILE wires#NIL DO IF wires.first=wire THEN RETURN [TRUE]; wires ← wires.rest ENDLOOP;
RETURN [FALSE];
};
RecursiveMember: PUBLIC PROC [wire, candidate: Wire] RETURNS [BOOL] = {
FindActual: EachWireProc = {quit ← wire=candidate};
RETURN [VisitWire[wire, FindActual]];
};
Miscellaneous
FixStupidRef: PUBLIC PROC [ref: REF ANY] RETURNS [rope: ROPE] = {
rope ← WITH ref SELECT FROM
r: REF TEXT => Rope.FromRefText[r],
r: ROPE => r,
ENDCASE => ERROR;
};
Print: PUBLIC PROC [ref: REF, out: STREAMNIL, indent: NAT ← 0, level: NAT ← 2] = {
WITH ref SELECT FROM
wire: Wire  => PrintWire[wire, out, indent, level];
cellType: CellType => PrintCellType[cellType, out, indent, level];
ENDCASE  => {
IF out=NIL THEN out ← NARROW [ProcessProps.GetProp[$CommanderHandle], Commander.Handle].out;
IO.PutRope[out, "*** CoreOps.Print Does not know how to print argument"];
};
};
END.