CoreIOImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Barth, May 23, 1986 9:20:31 am PDT
Bertrand Serlet May 23, 1986 0:17:02 am PDT
DIRECTORY Atom, Convert, Core, CoreClasses, CoreIO, CoreOps, CoreProperties, FS, HashTable, IO, Rope;
CoreIOImpl: CEDAR PROGRAM
IMPORTS Atom, Convert, CoreClasses, CoreOps, CoreProperties, FS, HashTable, IO, Rope
EXPORTS CoreIO
SHARES Core
= BEGIN OPEN CoreIO;
CoreWriteProcProp: ATOM = $CoreWriteProc;
CoreReadProcProp: ATOM = $CoreReadProc;
CoreIOInitProcProp: ATOM = $CoreIOInitProc;
classRegistry: HashTable.Table ← HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope];
Cell Type IO
UnknownProperty: PUBLIC SIGNAL [propKey: ATOM] = CODE;
UnknownCellClass: PUBLIC SIGNAL [class: Core.CellClass] = CODE;
ReportSaveCellType: PUBLIC PROC [cellType: Core.CellType, fileName: ROPENIL] RETURNS [props: LIST OF ATOMNIL, classes: LIST OF Core.CellClass ← NIL] = {
SaveCellType[cellType, fileName !
UnknownProperty => {
FOR pl: LIST OF ATOM ← props, pl.rest UNTIL pl=NIL DO
IF pl.first=propKey THEN EXIT;
REPEAT FINISHED => props ← CONS[propKey, props];
ENDLOOP;
RESUME;
};
UnknownCellClass => {
FOR cl: LIST OF Core.CellClass ← classes, cl.rest UNTIL cl=NIL DO
IF cl.first=class THEN EXIT;
REPEAT FINISHED => classes ← CONS[class, classes];
ENDLOOP;
RESUME;
}];
};
SaveCellType: PUBLIC PROC [cellType: Core.CellType, fileName: ROPENIL] = {
h: Handle ← NEW[HandleRec];
IF fileName=NIL THEN fileName ← Rope.Cat[CoreOps.GetCellTypeName[cellType], ".core"];
h.stream ← FS.StreamOpen[fileName, $create];
h.cellTypeIDTab ← HashTable.Create[];
h.ropeIDTab ← HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope];
h.atomIDTab ← HashTable.Create[];
WriteCellType[h, cellType];
IO.Close[h.stream];
};
RestoreCellType: PUBLIC PROC [cellName: ROPENIL, fileName: ROPENIL] RETURNS [cellType: Core.CellType] = {
h: Handle ← NEW[HandleRec];
IF fileName=NIL AND cellName=NIL THEN ERROR;
IF fileName=NIL THEN fileName ← Rope.Cat[cellName, ".core"];
h.stream ← FS.StreamOpen[fileName];
h.cellTypeIDTab ← HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope];
h.ropeIDTab ← HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope];
h.atomIDTab ← HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope];
cellType ← ReadCellType[h];
IO.Close[h.stream];
};
IO Registration
RegisterClass: PUBLIC PROC [class: Core.CellClass, write: ClassWriteProc, read: ClassReadProc, init: IOInitProc ← NIL] RETURNS [sameClass: Core.CellClass] = {
sameClass ← class;
CoreProperties.PutCellClassProp[class, CoreWriteProcProp, NEW[ClassWriteProc ← write]];
CoreProperties.PutCellClassProp[class, CoreReadProcProp, NEW[ClassReadProc ← read]];
[] ← HashTable.Store[classRegistry, class.name, class];
IF init#NIL THEN ERROR; -- not implemented
};
RegisterProperty: PUBLIC PROC [prop: ATOM, write: PropWriteProc, read: PropReadProc, init: IOInitProc ← NIL] RETURNS [sameProp: ATOM] = {
props: Core.Properties ← CoreProperties.FetchProperties[prop];
props ← CoreProperties.PutProp[props, CoreWriteProcProp, NEW[PropWriteProc ← write]];
props ← CoreProperties.PutProp[props, CoreReadProcProp, NEW[PropReadProc ← read]];
CoreProperties.StoreProperties[prop, props];
sameProp ← prop;
IF init#NIL THEN ERROR; -- not implemented
};
IO Utilities
WriteCellType: PUBLIC PROC [h: Handle, cellType: Core.CellType] = {
cellTypeID: ROPENARROW[HashTable.Fetch[h.cellTypeIDTab, cellType].value];
IF cellTypeID=NIL THEN {
wireIDTab: HashTable.Table ← HashTable.Create[];
classWrite: REF ClassWriteProc ← NARROW[CoreProperties.GetCellClassProp[from: cellType.class, prop: CoreWriteProcProp]];
cellTypeID ← Rope.Cat["C", Convert.RopeFromInt[from: HashTable.GetSize[h.cellTypeIDTab], base: 16, showRadix: FALSE]];
IF NOT HashTable.Insert[h.cellTypeIDTab, cellType, cellTypeID] THEN ERROR;
IF classWrite=NIL THEN {
SIGNAL UnknownCellClass[cellType.class];
cellType ← CoreOps.ToBasic[cellType];
classWrite ← NARROW[CoreProperties.GetCellClassProp[from: cellType.class, prop: CoreWriteProcProp]];
IF classWrite=NIL THEN ERROR;
};
WriteID[h, cellTypeID];
WriteWire[h, wireIDTab, cellType.public];
WriteProperties[h, cellType.properties];
WriteRope[h, cellType.class.name];
classWrite^[h, cellType, wireIDTab];
}
ELSE WriteID[h, cellTypeID];
};
ReadCellType: PUBLIC PROC [h: Handle] RETURNS [cellType: Core.CellType] = {
cellTypeID: ROPE ← ReadID[h];
IF Rope.Fetch[cellTypeID]#'C THEN ERROR;
cellType ← NARROW[HashTable.Fetch[h.cellTypeIDTab, cellTypeID].value];
IF cellType=NIL THEN {
wireIDTab: HashTable.Table ← HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope];
className: ROPE;
classRead: REF ClassReadProc;
cellType ← NEW[Core.CellTypeRec];
IF NOT HashTable.Insert[h.cellTypeIDTab, cellTypeID, cellType] THEN ERROR;
cellType.public ← ReadWire[h, wireIDTab];
cellType.properties ← ReadProperties[h];
className ← ReadRope[h];
cellType.class ← NARROW[HashTable.Fetch[classRegistry, className].value];
classRead ← NARROW[CoreProperties.GetCellClassProp[from: cellType.class, prop: CoreReadProcProp]];
classRead^[h, cellType, wireIDTab];
};
};
WriteWire: PUBLIC PROC [h: Handle, wireIDTab: HashTable.Table, wire: Core.Wire] = {
wireID: ROPENARROW[HashTable.Fetch[wireIDTab, wire].value];
IF wireID=NIL THEN {
wireID ← Rope.Cat["W", Convert.RopeFromInt[from: HashTable.GetSize[wireIDTab], base: 16, showRadix: FALSE]];
IF NOT HashTable.Insert[wireIDTab, wire, wireID] THEN ERROR;
WriteID[h, wireID];
WriteInt[h, wire.size];
WriteProperties[h, wire.properties];
FOR w: NAT IN [0..wire.size) DO
WriteWire[h, wireIDTab, wire[w]];
ENDLOOP;
}
ELSE WriteID[h, wireID];
};
ReadWire: PUBLIC PROC [h: Handle, wireIDTab: HashTable.Table] RETURNS [wire: Core.Wire] = {
wireID: ROPE ← ReadID[h];
IF Rope.Fetch[wireID]#'W THEN ERROR;
wire ← NARROW[HashTable.Fetch[wireIDTab, wireID].value];
IF wire=NIL THEN {
wireSize: NAT ← ReadInt[h];
wire ← NEW[Core.WireRec[wireSize]];
IF NOT HashTable.Insert[wireIDTab, wireID, wire] THEN ERROR;
wire.properties ← ReadProperties[h];
FOR w: NAT IN [0..wire.size) DO
wire[w] ← ReadWire[h, wireIDTab];
ENDLOOP;
};
};
WriteProperties: PUBLIC PROC [h: Handle, properties: Core.Properties] = {
propCount: INT ← 0;
FOR props: Core.Properties ← properties, props.rest UNTIL props=NIL DO
propKey: ATOMNARROW[props.first.key];
propVal: REF ANY ← props.first.val;
propWrite: REF PropWriteProc ← NARROW[CoreProperties.GetProp[from: CoreProperties.FetchProperties[propKey], prop: CoreWriteProcProp]];
IF propWrite#NIL OR ISTYPE[propVal, ROPE] OR ISTYPE[propVal, LIST OF ROPE] OR ISTYPE[propVal, REF INT] OR ISTYPE[propVal, REF NAT] OR ISTYPE[propVal, ATOM] THEN propCount ← propCount + 1;
ENDLOOP;
WriteInt[h, propCount];
FOR props: Core.Properties ← properties, props.rest UNTIL props=NIL DO
StartProp: PROC [type: ROPE] = {
WriteAtom[h, propKey];
IF type#NIL THEN WriteID[h, type];
};
propKey: ATOMNARROW[props.first.key];
propWrite: REF PropWriteProc ← NARROW[CoreProperties.GetProp[from: CoreProperties.FetchProperties[propKey], prop: CoreWriteProcProp]];
IF propWrite=NIL THEN WITH props.first.val SELECT FROM
r: ROPE => {StartProp["r"]; WriteRope[h, r]};
lor: LIST OF ROPE => {StartProp["lor"]; WriteListOfRope[h, lor]};
i: REF INT => {StartProp["i"]; IO.PutF[h.stream, "%g ", IO.int[i^]]};
n: REF NAT => {StartProp["n"]; IO.PutF[h.stream, "%g ", IO.int[n^]]};
a: ATOM => {StartProp["a"]; WriteAtom[h, a]};
ENDCASE => SIGNAL UnknownProperty[propKey]
ELSE {StartProp[NIL]; propWrite^[h, propKey, props.first.val]};
ENDLOOP;
};
ReadProperties: PUBLIC PROC [h: Handle] RETURNS [properties: Core.Properties ← NIL] = {
propCount: INT ← ReadInt[h];
FOR c: INT IN [0..propCount) DO
key: ATOM ← ReadAtom[h];
val: REF ANY;
propRead: REF PropReadProc ← NARROW[CoreProperties.GetProp[from: CoreProperties.FetchProperties[key], prop: CoreReadProcProp]];
IF propRead=NIL THEN {
type: ROPE ← ReadID[h];
val ← SELECT TRUE FROM
Rope.Equal["r", type] => ReadRope[h],
Rope.Equal["lor", type] => ReadListOfRope[h],
Rope.Equal["i", type] => NEW[INTIO.GetInt[h.stream]],
Rope.Equal["n", type] => NEW[NATIO.GetInt[h.stream]],
Rope.Equal["a", type] => ReadAtom[h],
ENDCASE => ERROR UnknownProperty[Atom.MakeAtom[type]];
}
ELSE val ← propRead^[h, key];
properties ← CONS[[key, val], properties];
ENDLOOP;
};
WriteID: PUBLIC PROC [h: Handle, id: ROPE] = {
IO.PutRope[h.stream, id];
IO.PutRope[h.stream, " "];
};
ReadID: PUBLIC PROC [h: Handle] RETURNS [id: ROPE] = {
id ← IO.GetID[h.stream];
};
WriteAtom: PUBLIC PROC [h: Handle, atom: ATOM] = {
atomID: ROPENARROW[HashTable.Fetch[h.atomIDTab, atom].value];
IF atomID=NIL THEN {
atomID ← Rope.Cat["A", Convert.RopeFromInt[from: HashTable.GetSize[h.atomIDTab], base: 16, showRadix: FALSE]];
IF NOT HashTable.Insert[h.atomIDTab, atom, atomID] THEN ERROR;
WriteID[h, atomID];
IO.PutF[h.stream, "%g ", IO.atom[atom]];
}
ELSE WriteID[h, atomID];
};
ReadAtom: PUBLIC PROC [h: Handle] RETURNS [atom: ATOM] = {
atomID: ROPE ← ReadID[h];
IF Rope.Fetch[atomID]#'A THEN ERROR;
atom ← NARROW[HashTable.Fetch[h.atomIDTab, atomID].value];
IF atom=NIL THEN {
atom ← IO.GetAtom[h.stream];
IF NOT HashTable.Insert[h.atomIDTab, atomID, atom] THEN ERROR;
};
};
WriteRope: PUBLIC PROC [h: Handle, rope: ROPE] = {
ropeID: ROPENARROW[HashTable.Fetch[h.ropeIDTab, rope].value];
IF ropeID=NIL THEN {
ropeID ← Rope.Cat["R", Convert.RopeFromInt[from: HashTable.GetSize[h.ropeIDTab], base: 16, showRadix: FALSE]];
IF NOT HashTable.Insert[h.ropeIDTab, rope, ropeID] THEN ERROR;
WriteID[h, ropeID];
IO.PutRope[h.stream, "\""];
IO.PutRope[h.stream, rope]; -- cannot use IO.PutF that truncates long ropes! (BS)
IO.PutRope[h.stream, "\" "];
}
ELSE WriteID[h, ropeID];
};
ReadRope: PUBLIC PROC [h: Handle] RETURNS [rope: ROPE] = {
ropeID: ROPE ← ReadID[h];
IF Rope.Fetch[ropeID]#'R THEN ERROR;
rope ← NARROW[HashTable.Fetch[h.ropeIDTab, ropeID].value];
IF rope=NIL THEN {
rope ← IO.GetRopeLiteral[h.stream];
IF NOT HashTable.Insert[h.ropeIDTab, ropeID, rope] THEN ERROR;
};
};
WriteListOfRope: PUBLIC PROC [h: Handle, ropes: LIST OF ROPE] = {
count: INT ← 0;
FOR rl: LIST OF ROPE ← ropes, rl.rest UNTIL rl=NIL DO
count ← count + 1;
ENDLOOP;
WriteInt[h, count];
FOR rl: LIST OF ROPE ← ropes, rl.rest UNTIL rl=NIL DO
WriteRope[h, rl.first];
ENDLOOP;
};
ReadListOfRope: PUBLIC PROC [h: Handle] RETURNS [ropes: LIST OF ROPE] = {
count: INT ← ReadInt[h];
lor: LIST OF ROPENIL;
FOR c: INT IN [0..count) DO
lor ← CONS[ReadRope[h], lor];
ENDLOOP;
FOR rl: LIST OF ROPE ← lor, rl.rest UNTIL rl=NIL DO
ropes ← CONS[rl.first, ropes];
ENDLOOP;
};
WriteInt: PUBLIC PROC [h: Handle, val: INT] = {
IO.PutF[h.stream, "%g ", IO.int[val]];
};
ReadInt: PUBLIC PROC [h: Handle] RETURNS [int: INT] = {
int ← IO.GetInt[h.stream];
};
Cell Class IO
WriteRecordCell: ClassWriteProc = {
rct: CoreClasses.RecordCellType ← NARROW[cellType.data];
WriteInt[h, rct.size];
WriteWire[h, wireIDTab, rct.internal];
FOR in: NAT IN [0..rct.size) DO
instance: CoreClasses.CellInstance ← rct[in];
WriteWire[h, wireIDTab, instance.actual];
WriteProperties[h, instance.properties];
WriteCellType[h, instance.type];
ENDLOOP;
};
ReadRecordCell: ClassReadProc = {
rct: CoreClasses.RecordCellType ← NEW[CoreClasses.RecordCellTypeRec[ReadInt[h]]];
rct.internal ← ReadWire[h, wireIDTab];
FOR in: NAT IN [0..rct.size) DO
instance: CoreClasses.CellInstance ← NEW[CoreClasses.CellInstanceRec];
rct[in] ← instance;
instance.actual ← ReadWire[h, wireIDTab];
instance.properties ← ReadProperties[h];
instance.type ← ReadCellType[h];
ENDLOOP;
cellType.data ← rct;
};
WriteTransistor: ClassWriteProc = {
tran: CoreClasses.Transistor ← NARROW[cellType.data];
WriteID[h, CoreClasses.transistorTypeNames[tran.type]];
WriteInt[h, tran.length];
WriteInt[h, tran.width];
};
ReadTransistor: ClassReadProc = {
tran: CoreClasses.Transistor ← NEW[CoreClasses.TransistorRec];
type: ROPE ← ReadID[h];
FOR t: CoreClasses.TransistorType IN CoreClasses.TransistorType DO
IF Rope.Equal[CoreClasses.transistorTypeNames[t], type] THEN {
tran.type ← t;
EXIT;
};
REPEAT FINISHED => ERROR;
ENDLOOP;
tran.length ← ReadInt[h];
tran.width ← ReadInt[h];
cellType.data ← tran;
};
[] ← RegisterClass[CoreClasses.recordCellClass, WriteRecordCell, ReadRecordCell];
[] ← RegisterClass[CoreClasses.transistorCellClass, WriteTransistor, ReadTransistor];
END.