[Indigo]<Rosemary>®>Rosemary.df=>RoseStateIOImpl.Mesa
Last Edited by: Spreitzer, October 17, 1985 5:07:26 pm PDT
DIRECTORY Asserting, Cucumber, FS, IO, Rope, RedBlackTree, RoseDisplayInsides, RoseTypes, RoseRun, RoseStateIO, SafeStorage;
RoseStateIOImpl: PROGRAM
IMPORTS Asserting, Cucumber, FS, IO, RedBlackTree, RoseDisplayInsides, RoseRun, RoseTypes, SS: SafeStorage
EXPORTS RoseStateIO =
BEGIN
ROPE: TYPE = Rope.ROPE;
Cell: TYPE = RoseTypes.Cell;
Dir: TYPE = Cucumber.Direction;
Save: PUBLIC PROC [cell: Cell, fileName: ROPE] RETURNS [errMsg: ROPE] =
BEGIN
file: IO.STREAM ← FS.StreamOpen[fileName: fileName, accessOptions: create];
errMsg ← NIL;
Cucumber.Transfer[what: cell, where: file, direction: out !
Cucumber.Error => {errMsg ← msg; CONTINUE};
UNWIND => {file.Close[]}
];
file.Close[];
END;
Restore: PUBLIC PROC [cell: Cell, fileName: ROPE] RETURNS [errMsg: ROPE] =
BEGIN
file: IO.STREAMFS.StreamOpen[fileName: fileName, accessOptions: read];
errMsg ← NIL;
Cucumber.Transfer[what: cell, where: file, direction: in !
Cucumber.Error => {errMsg ← msg; CONTINUE};
UNWIND => file.Close[]
];
IF errMsg # NIL THEN errMsg ← IO.PutFR["at %g: %g", IO.int[file.GetIndex[]], IO.rope[errMsg]];
file.Close[];
END;
cellHandler: Cucumber.Handler ← NEW [Cucumber.HandlerRep ← [
PartTransfer: TransferCell]];
strHandler: Cucumber.Handler ← NEW [Cucumber.HandlerRep ← [
PartTransfer: TransferStructure]];
TransferCell: Cucumber.PartTransferProc =
BEGIN
cell: Cell ← NARROW[whole];
SELECT part.first FROM
$type => NULL;
$nextInstance => NULL;
$sim => NULL;
$parent => NULL;
$leftChild => NULL;
$rightSibling => NULL;
$firstInternalNode => NULL;
$internalNodes => NULL;
$components => TransferComponents[cell, where, direction];
$interfaceNodes => NULL;
$other => IF direction = out THEN CheckCellProps[cell];
$realCellStuff => IF cell.substantiality = Real THEN TransferRealCellStuff[cell, where, direction];
ENDCASE => ERROR;
END;
CheckCellProps: PROC [cell: Cell] =
BEGIN
FOR al: RoseTypes.Assertions ← cell.other, al.rest WHILE al # NIL DO
key: Asserting.Term ← Asserting.RelnOf[al.first];
rest: Asserting.Terms ← Asserting.TermsOf[al.first];
IF key # NIL THEN WITH key SELECT FROM
x: RoseDisplayInsides.Display => LOOP;
ENDCASE;
SELECT key FROM
$ExpandDeciderClosure, RoseDisplayInsides.cellStateDisplayProp => LOOP;
ENDCASE;
IF rest # NIL AND rest.first # NIL THEN ERROR Cucumber.Error[IO.PutFR["%g has a %g relation, and I don't know what to do with it", IO.rope[cell.name], IO.refAny[key]]];
ENDLOOP;
END;
TransferComponents: PROC [cell: Cell, where: IO.STREAM, direction: Dir] =
BEGIN
WriteCell: SAFE PROC [asAny: REF ANY] RETURNS [stop: BOOLEAN] = TRUSTED
BEGIN
component: Cell ← NARROW[asAny];
where.PutF["%g ", IO.refAny[component.name]];
Cucumber.Transfer[component, where, out];
stop ← FALSE;
END;
SELECT direction FROM
in => DO
name: ROPENARROW[where.GetRefAny[]];
component: Cell;
IF name = NIL THEN EXIT;
component ← NARROW[cell.components.Lookup[name]];
IF component = NIL THEN ERROR Cucumber.Error[IO.PutFR["component %g not found", IO.rope[name]]];
Cucumber.Transfer[component, where, direction];
ENDLOOP;
out => BEGIN
IF cell.components # NIL THEN cell.components.EnumerateIncreasing[WriteCell];
where.PutRope["NIL "];
END;
ENDCASE => ERROR;
END;
TransferWords: PUBLIC PROC [wp: RoseTypes.WordPtr, wordCount: CARDINAL, stream: IO.STREAM, direction: Cucumber.Direction] =
BEGIN
SELECT direction FROM
in => {
FOR i: CARDINAL IN [0 .. wordCount) DO
card: CARDINAL ← stream.GetCard[!SS.NarrowRefFault => ERROR Cucumber.Error["Not a CARDINAL"]];
TRUSTED {(wp + i)^ ← card};
ENDLOOP;
};
out => {
FOR i: CARDINAL IN [0 .. wordCount) DO
TRUSTED {stream.PutF["%g ", IO.card[(wp + i)^]]};
ENDLOOP;
};
ENDCASE => ERROR;
END;
TransferRealCellStuff: PROC [cell: Cell, where: IO.STREAM, direction: Dir] =
BEGIN
SELECT direction FROM
in => BEGIN
ReadIO: SAFE PROC [cell: Cell] --RoseTypes.CellProc-- = TRUSTED
{TransferWords[cell.realCellStuff.newIOAsWP, cell.type.simpleWordCount, where, in]};
hasState: BOOLEAN;
scheduled: BOOLEAN ← where.GetBool[!SS.NarrowRefFault => ERROR Cucumber.Error["Not a BOOLEAN"]];
IF cell.parent # NIL THEN RoseRun.AllowToModify[cell, ReadIO] ELSE [] ← ReadIO[cell];
hasState ← where.GetBool[!SS.NarrowRefFault => ERROR Cucumber.Error["Not a BOOLEAN"]];
IF hasState # (cell.realCellStuff.state # NIL) THEN ERROR Cucumber.Error[IO.PutFR["disagreement on emptiness of state of %g", IO.rope[cell.name]]];
IF hasState THEN Cucumber.Transfer[cell.realCellStuff.state, where, in];
END;
out => BEGIN
hasState: BOOLEAN ← cell.realCellStuff.state # NIL;
where.PutF["%g ", IO.bool[cell.realCellStuff.schedNext # RoseTypes.notInCellList]];
TransferWords[cell.realCellStuff.newIOAsWP, cell.type.simpleWordCount, where, out];
where.PutF["%g ", IO.bool[hasState]];
IF hasState THEN Cucumber.Transfer[cell.realCellStuff.state, where, out];
END;
ENDCASE => ERROR;
END;
TransferStructure: PROC [whole: REF ANY, part: Cucumber.Path, where: IO.STREAM, direction: Cucumber.Direction, data: REF ANY] --Cucumber.PartTransferProc-- = {
str: RoseTypes.Structure ← NARROW[whole];
SELECT part.first FROM
$sim, $schedFirst, $schedLast, $firstNeeded, $firstPerturbed, $firstAffected => NULL;
ENDCASE => ERROR Cucumber.Error[IO.PutFR["Unexpected part %g of Structure", IO.refAny[part]]]
};
Setup: PROC =
BEGIN
cellHandler.Register[CODE[RoseTypes.CellRep]];
strHandler.Register[CODE[RoseTypes.StructureRep]];
END;
Setup[];
END.