<> <> DIRECTORY Cucumber, FileIO, IO, Rope, OrderedSymbolTableRef, Rosemary, RoseStateIO, SafeStorage; RoseStateIOImpl: PROGRAM IMPORTS Cucumber, FileIO, IO, OrderedSymbolTableRef, Rope, Rosemary, SS: SafeStorage EXPORTS RoseStateIO = BEGIN ROPE: TYPE = Rope.ROPE; Cell: TYPE = Rosemary.Cell; Dir: TYPE = Cucumber.Direction; Save: PUBLIC PROC [cell: Cell, fileName: ROPE] RETURNS [errMsg: ROPE] = BEGIN file: IO.STREAM _ FileIO.Open[fileName: fileName, accessOptions: overwrite]; errMsg _ NIL; Cucumber.Transfer[what: cell, where: file, direction: out !Cucumber.Error => {errMsg _ msg; CONTINUE}]; file.Close[]; END; Restore: PUBLIC PROC [cell: Cell, fileName: ROPE] RETURNS [errMsg: ROPE] = BEGIN file: IO.STREAM _ FileIO.Open[fileName: fileName, accessOptions: read]; errMsg _ NIL; Cucumber.Transfer[what: cell, where: file, direction: in !Cucumber.Error => {errMsg _ msg; CONTINUE}]; 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 $class => NULL; $nextInstance => NULL; $parent => NULL; $leftChild => NULL; $rightSibling => NULL; $firstInternalNode => NULL; $internalNodes => NULL; $components => TransferComponents[cell, where, direction]; $interfaceNodes => NULL; $other => NULL; $type => NULL; $realCellStuff => IF cell.type = Real THEN TransferRealCellStuff[cell, where, direction]; ENDCASE => ERROR; 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.rope[component.name]]; Cucumber.Transfer[component, where, out]; stop _ FALSE; END; SELECT direction FROM in => DO name: ROPE _ where.GetToken[IO.IDProc]; component: Cell; IF name.Equal["!"] 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["! "]; END; ENDCASE => ERROR; END; TransferRealCellStuff: PROC [cell: Cell, where: IO.STREAM, direction: Dir] = BEGIN ReadIO: Rosemary.ModifyProc = TRUSTED BEGIN FOR i: CARDINAL IN [0 .. cell.class.ioWordCount) DO card: CARDINAL _ where.GetCard[!SS.NarrowRefFault => ERROR Cucumber.Error["Not a CARDINAL"]]; (cell.realCellStuff.newIOAsWP + i)^ _ card; ENDLOOP; END; SELECT direction FROM in => BEGIN hasState: BOOLEAN; scheduled: BOOLEAN _ where.GetBool[!SS.NarrowRefFault => ERROR Cucumber.Error["Not a BOOLEAN"]]; IF cell.parent # NIL THEN cell.AllowToModify[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 # Rosemary.notInSchedule]]; FOR i: CARDINAL IN [0 .. cell.class.ioWordCount) DO where.PutF["%g ", IO.card[(cell.realCellStuff.newIOAsWP + i)^]]; ENDLOOP; where.PutF["%g ", IO.bool[hasState]]; IF hasState THEN Cucumber.Transfer[cell.realCellStuff.state, where, out]; END; ENDCASE => ERROR; END; TransferStructure: Cucumber.PartTransferProc = { str: Rosemary.Structure _ NARROW[whole]; SELECT part.first FROM $container, $schedFirst, $schedLast, $insideNodes => NULL; $mirror => Cucumber.Transfer[what: str.mirror, where: where, direction: direction]; ENDCASE => ERROR Cucumber.Error[IO.PutFR["Unexpected part %g of Structure", IO.refAny[part]]] }; Setup: PROC = BEGIN cellHandler.Register[CODE[Rosemary.CellRep]]; strHandler.Register[CODE[Rosemary.StructureRep]]; END; Setup[]; END.