CoreIOImpl.mesa
Copyright Ó 1985, 1987 by Xerox Corporation. All rights reserved.
Barth, April 16, 1987 4:03:41 pm PDT
Bertrand Serlet May 5, 1988 3:29:57 pm PDT
Mike Spreitzer February 27, 1987 2:54:07 pm PST
Louis Monier September 24, 1987 2:51:06 pm PDT
DIRECTORY
Ascii, Atom, BrineIO, CedarProcess,
Core, CoreClasses, CoreDirectory, CoreIO, CoreOps, CoreProperties,
FS, GList, IO, ProcessProps, RefTab, RefTabExtras, Rope, SymTab;
CoreIOImpl: CEDAR PROGRAM
IMPORTS Atom, BrineIO, CedarProcess, CoreClasses, CoreOps, CoreProperties, FS, GList, IO, ProcessProps, RefTab, RefTabExtras, Rope, SymTab
EXPORTS CoreIO
= BEGIN OPEN CoreIO, BrineIO;
Prerequisites
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
coreWriteProcProp: ATOM = $CoreWriteProc;
coreReadProcProp: ATOM = $CoreReadProc;
calledFromDir: Core.ROPENIL;
classRegistry: RefTab.Ref ← RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.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 => {
IF NOT GList.Member[propKey, props] THEN props ← CONS [propKey, props];
RESUME;
};
UnknownCellClass => {
IF NOT GList.Member[class, classes] THEN classes ← CONS [class, classes];
RESUME;
}];
};
SaveCellType: PUBLIC PROC [cellType: Core.CellType, fileName: ROPENIL] = {
stream: STREAM;
IF fileName=NIL THEN fileName ← Rope.Cat[CoreOps.GetCellTypeName[cellType], ".core"];
stream ← FS.StreamOpen[fileName, $create];
WriteCellType[stream, cellType];
IO.Close[stream];
};
importCellClass: PUBLIC Core.CellClass ← CoreOps.SetClassPrintProc[NEW [Core.CellClassRec ← [name: "Import", recast: RecastImport, layersProps: TRUE]], PrintImport];
ReadFile: PROC [name: Core.ROPE] RETURNS [s: STREAMNIL] ~ {
s ← FS.StreamOpen[fileName: name ! FS.Error => CONTINUE];
IF s=NIL THEN s ← FS.StreamOpen[fileName: name, wDir: calledFromDir];
};
RestoreCellType: PUBLIC PROC [cellName: ROPENIL, fileName: ROPENIL] RETURNS [cellType: Core.CellType] = {
stream: STREAM;
wireIDTable: RefTab.Ref;
IF fileName=NIL AND cellName=NIL THEN ERROR;
IF fileName=NIL THEN fileName ← Rope.Cat[cellName, ".core"];
stream ← ReadFile[fileName];
stream.propList ← Atom.PutPropOnList[stream.propList, $CoreIOFileName, fileName];
[cellType, wireIDTable] ← ReadCellTypePublic[stream];
stream.propList ← Atom.PutPropOnList[stream.propList, $CoreIOWireTable, wireIDTable];
cellType.class ← importCellClass; cellType.data ← stream;
};
RecastImport: Core.RecastProc = {
stream: STREAMNARROW [me.data];
wireIDTable: RefTab.Ref ← GetRefTab[stream, $CoreIOWireTable];
me.data ← NIL;
ReadCellTypeRest[stream, me, wireIDTable];
new ← me;
};
PrintImport: CoreOps.PrintClassProc = {
stream: STREAMNARROW [data];
CoreOps.PrintIndent[indent, out];
IO.PutF[out, "Import of : %g", IO.rope[NARROW [Atom.GetPropFromList[stream.propList, $CoreIOFileName]]]];
};
Library IO
SaveLibrary: PUBLIC PROC [library: CoreDirectory.Library, fileName: ROPE] = {
EachLibraryItem: SymTab.EachPairAction = {
WriteRope[stream, key];
WriteCellType[stream, NARROW [val]
! UnknownProperty => RESUME; UnknownCellClass => RESUME];
};
stream: STREAM;
fileName ← Rope.Cat[fileName, ".corelib"];
stream ← FS.StreamOpen[fileName, $create];
WriteInt[stream, SymTab.GetSize[library]];
[] ← SymTab.Pairs[library, EachLibraryItem];
IO.Close[stream];
};
RestoreLibrary: PUBLIC PROC [fileName: ROPE] RETURNS [library: CoreDirectory.Library] = {
stream: STREAM;
size: INT;
fileName ← Rope.Cat[fileName, ".corelib"];
stream ← ReadFile[fileName];
stream.propList ← Atom.PutPropOnList[stream.propList, $CoreIOFileName, fileName];
size ← ReadInt[stream];
library ← SymTab.Create[(size/2)*2+1];
THROUGH [0 .. size) DO
key: ROPE ← ReadRope[stream];
cellType: Core.CellType ← ReadCellType[stream];
[] ← SymTab.Store[library, key, cellType];
ENDLOOP;
IO.Close[stream];
};
IO Registration
RegisterClass: PUBLIC PROC [class: Core.CellClass, write: ClassWriteProc, read: ClassReadProc] RETURNS [sameClass: Core.CellClass] = {
sameClass ← class;
CoreProperties.PutCellClassProp[class, coreWriteProcProp, NEW[ClassWriteProc ← write]];
CoreProperties.PutCellClassProp[class, coreReadProcProp, NEW[ClassReadProc ← read]];
[] ← RefTab.Store[classRegistry, class.name, class];
};
RegisterProperty: PUBLIC PROC [prop: ATOM, write: PropWriteProc, read: PropReadProc] 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;
};
IO Utilities
WriteCellType: PUBLIC PROC [stream: STREAM, cellType: Core.CellType] = {
cellTypeIDTable: RefTab.Ref ← GetRefTab[stream, $CoreIOCellTypeTable];
cellTypeID: ROPENARROW [RefTab.Fetch[cellTypeIDTable, cellType].val];
IF cellTypeID=NIL THEN {
wireIDTable: RefTab.Ref ← RefTab.Create[];
classWrite: REF ClassWriteProc ← NARROW[CoreProperties.GetCellClassProp[from: cellType.class, prop: coreWriteProcProp]];
IF classWrite=NIL THEN {
SIGNAL UnknownCellClass[cellType.class];
cellType ← CoreOps.Recast[cellType];
IF cellType=NIL THEN ERROR;
WriteCellType[stream, cellType];
RETURN;
};
cellTypeID ← MakeID["C", RefTab.GetSize[cellTypeIDTable]];
IF NOT RefTab.Insert[cellTypeIDTable, cellType, cellTypeID] THEN ERROR;
WriteID[stream, cellTypeID];
WriteWire[stream, wireIDTable, cellType.public];
WriteProperties[stream, cellType.properties];
WriteRope[stream, cellType.class.name];
classWrite^[stream, cellType, wireIDTable];
}
ELSE WriteID[stream, cellTypeID];
};
ReadCellType: PUBLIC PROC [stream: STREAM] RETURNS [cellType: Core.CellType] = {
wireIDTable: RefTab.Ref ← NIL;
[cellType, wireIDTable] ← ReadCellTypePublic[stream];
IF wireIDTable#NIL THEN ReadCellTypeRest[stream, cellType, wireIDTable];
};
ReadCellTypePublic: PUBLIC PROC [stream: STREAM] RETURNS [cellType: Core.CellType, wireIDTable: RefTab.Ref] = {
cellTypeIDTable: RefTab.Ref ← GetRefTab[stream, $CoreIOCellTypeTable, RefTabExtras.EqualRope, RefTabExtras.HashRope];
cellTypeID: ROPE ← ReadID[stream];
IF Rope.Fetch[cellTypeID]#'C THEN ERROR;
cellType ← NARROW[RefTab.Fetch[cellTypeIDTable, cellTypeID].val];
IF cellType=NIL THEN {
cellType ← NEW[Core.CellTypeRec];
IF NOT RefTab.Insert[cellTypeIDTable, cellTypeID, cellType] THEN ERROR;
wireIDTable ← RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope];
cellType.public ← ReadWire[stream, wireIDTable];
cellType.properties ← ReadProperties[stream];
};
};
ReadCellTypeRest: PUBLIC PROC [stream: STREAM, cellType: Core.CellType, wireIDTable: RefTab.Ref] = {
className: ROPE ← ReadRope[stream];
classRead: REF ClassReadProc ← NIL;
cellType.class ← NARROW[RefTab.Fetch[classRegistry, className].val];
classRead ← NARROW[CoreProperties.GetCellClassProp[from: cellType.class, prop: coreReadProcProp]];
classRead^[stream, cellType, wireIDTable];
};
WriteWire: PUBLIC PROC [stream: STREAM, wireIDTable: RefTab.Ref, wire: Core.Wire] = {
wireID: ROPENARROW[RefTab.Fetch[wireIDTable, wire].val];
IF wireID=NIL THEN {
wireID ← MakeID["W", RefTab.GetSize[wireIDTable]];
IF NOT RefTab.Insert[wireIDTable, wire, wireID] THEN ERROR;
WriteID[stream, wireID];
WriteInt[stream, wire.size];
WriteProperties[stream, wire.properties];
FOR w: NAT IN [0 .. wire.size) DO
WriteWire[stream, wireIDTable, wire[w]];
ENDLOOP;
}
ELSE WriteID[stream, wireID];
};
ReadWire: PUBLIC PROC [stream: STREAM, wireIDTable: RefTab.Ref] RETURNS [wire: Core.Wire] = {
wireID: ROPE ← ReadID[stream];
IF Rope.Fetch[wireID]#'W THEN ERROR;
wire ← NARROW[RefTab.Fetch[wireIDTable, wireID].val];
IF wire=NIL THEN {
wireSize: NAT ← ReadInt[stream];
wire ← NEW[Core.WireRec[wireSize]];
IF NOT RefTab.Insert[wireIDTable, wireID, wire] THEN ERROR;
wire.properties ← ReadProperties[stream];
FOR w: NAT IN [0 .. wire.size) DO
wire[w] ← ReadWire[stream, wireIDTable];
ENDLOOP;
};
};
WriteProperties: PUBLIC PROC [stream: STREAM, properties: Core.Properties] = {
propCount: INT ← 0;
CedarProcess.CheckAbort[];
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] OR ISTYPE[propVal, REF REAL] OR ISTYPE[propVal, REF BOOL] THEN propCount ← propCount + 1;
ENDLOOP;
WriteInt[stream, propCount];
FOR props: Core.Properties ← properties, props.rest UNTIL props=NIL DO
StartProp: PROC [type: ROPE] = {
WriteAtom[stream, propKey];
IF type#NIL THEN WriteID[stream, 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[stream, r]};
lor: LIST OF ROPE => {StartProp["lor"]; WriteRopes[stream, lor]};
i: REF INT => {StartProp["i"]; WriteInt[stream, i^]};
n: REF NAT => {StartProp["n"]; WriteInt[stream, n^]};
a: ATOM => {StartProp["a"]; WriteAtom[stream, a]};
real: REF REAL => {StartProp["real"]; WriteReal[stream, real^]};
rb: REF BOOL => {StartProp["rb"]; WriteBool[stream, rb^]};
ENDCASE => SIGNAL UnknownProperty[propKey]
ELSE {StartProp[NIL]; propWrite^[stream, propKey, props.first.val]};
ENDLOOP;
};
ReadProperties: PUBLIC PROC [stream: STREAM] RETURNS [properties: Core.Properties ← NIL] = {
propCount: INT ← ReadInt[stream];
CedarProcess.CheckAbort[];
FOR c: INT IN [0..propCount) DO
key: ATOM ← ReadAtom[stream];
val: REF ANY;
propRead: REF PropReadProc ← NARROW[CoreProperties.GetProp[from: CoreProperties.FetchProperties[key], prop: coreReadProcProp]];
IF propRead=NIL THEN {
type: ROPE ← ReadID[stream];
val ← SELECT TRUE FROM
Rope.Equal["r", type] => ReadRope[stream],
Rope.Equal["lor", type] => ReadRopes[stream],
Rope.Equal["i", type] => NEW[INT ← ReadInt[stream]],
Rope.Equal["n", type] => NEW[NAT ← ReadInt[stream]],
Rope.Equal["a", type] => ReadAtom[stream],
Rope.Equal["real", type] => NEW[REAL ← ReadReal[stream]],
Rope.Equal["rb", type] => NEW[BOOL ← ReadBool[stream]],
ENDCASE => ERROR UnknownProperty[Atom.MakeAtom[type]];
}
ELSE val ← propRead^[stream, key];
properties ← CONS [[key, val], properties];
ENDLOOP;
};
Cell Class IO
WriteRecordCell: ClassWriteProc = {
rct: CoreClasses.RecordCellType ← NARROW[cellType.data];
WriteInt[stream, rct.size];
WriteWire[stream, wireIDTable, rct.internal];
FOR in: NAT IN [0..rct.size) DO
instance: CoreClasses.CellInstance ← rct[in];
WriteWire[stream, wireIDTable, instance.actual];
WriteProperties[stream, instance.properties];
WriteCellType[stream, instance.type];
ENDLOOP;
};
ReadRecordCell: ClassReadProc = {
rct: CoreClasses.RecordCellType ← NEW[CoreClasses.RecordCellTypeRec[ReadInt[stream]]];
rct.internal ← ReadWire[stream, wireIDTable];
FOR in: NAT IN [0..rct.size) DO
instance: CoreClasses.CellInstance ← NEW[CoreClasses.CellInstanceRec];
rct[in] ← instance;
instance.actual ← ReadWire[stream, wireIDTable];
instance.properties ← ReadProperties[stream];
instance.type ← ReadCellType[stream];
ENDLOOP;
cellType.data ← rct;
};
WriteTransistor: ClassWriteProc = {
tran: CoreClasses.Transistor ← NARROW[cellType.data];
WriteID[stream, CoreClasses.transistorTypeNames[tran.type]];
};
ReadTransistor: ClassReadProc = {
tran: CoreClasses.Transistor ← NEW[CoreClasses.TransistorRec];
type: ROPE ← ReadID[stream];
FOR t: CoreClasses.TransistorType IN CoreClasses.TransistorType DO
IF Rope.Equal[CoreClasses.transistorTypeNames[t], type] THEN {
tran.type ← t;
EXIT;
};
REPEAT FINISHED => ERROR;
ENDLOOP;
cellType.data ← tran;
};
WriteUnspecified: ClassWriteProc = {};
ReadUnspecified: ClassReadProc = {cellType.data ← NIL};
WriteSequence: ClassWriteProc = {
WriteSequenceSet: PROC [set: CoreClasses.SequenceSet] = {
IF set=NIL THEN WriteInt[stream, -1]
ELSE {
WriteInt[stream, set.length];
FOR i: NAT IN [0..set.length) DO
WriteInt[stream, set[i]];
ENDLOOP;
};
};
seq: CoreClasses.SequenceCellType ← NARROW[cellType.data];
WriteCellType[stream, seq.base];
WriteInt[stream, seq.count];
WriteSequenceSet[seq.sequence];
WriteSequenceSet[seq.flatSequence];
};
ReadSequence: ClassReadProc = {
ReadSequenceSet: PROC RETURNS [set: CoreClasses.SequenceSet ← NIL] = {
length: INT ← ReadInt[stream];
IF length >= 0 THEN {
set ← NEW[CoreClasses.SequenceSetRec[length]];
FOR i: NAT IN [0..set.length) DO
set[i] ← ReadInt[stream];
ENDLOOP;
};
};
seq: CoreClasses.SequenceCellType ← NEW[CoreClasses.SequenceCellTypeRec];
seq.base ← ReadCellType[stream];
seq.count ← ReadInt[stream];
seq.sequence ← ReadSequenceSet[];
seq.flatSequence ← ReadSequenceSet[];
cellType.data ← seq;
};
Initialization
[] ← RegisterClass[CoreClasses.recordCellClass, WriteRecordCell, ReadRecordCell];
[] ← RegisterClass[CoreClasses.transistorCellClass, WriteTransistor, ReadTransistor];
[] ← RegisterClass[CoreClasses.unspecifiedCellClass, WriteUnspecified, ReadUnspecified];
[] ← RegisterClass[CoreClasses.sequenceCellClass, WriteSequence, ReadSequence];
calledFromDir ← NARROW[ProcessProps.GetProp[$WorkingDirectory]];
END.