RosemaryRun.mesa
last changed by Barth, June 9, 1983 11:14 am
Last Edited by: Spreitzer, July 14, 1983 11:24 am
DIRECTORY IO, List, OrderedSymbolTableRef, Rope, Rosemary, RosemaryInsides;
RosemaryRun:
CEDAR
MONITOR
IMPORTS IO, List, OSTR: OrderedSymbolTableRef, Rope, Rosemary
EXPORTS Rosemary, RosemaryInsides =
BEGIN OPEN Rosemary, RosemaryInsides;
EvalStructure:
PUBLIC EvalProc =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
FOR c:
CARDINAL
IN [0 .. cell.class.ioWordCount)
DO
TRUSTED
BEGIN
(str.mirror.realCellStuff.newIOAsWP+c)^ ← (cell.realCellStuff.oldIOAsWP+c)^ ← (cell.realCellStuff.newIOAsWP+c)^;
END;
ENDLOOP;
FOR portIndex:
CARDINAL
IN [0 .. cell.class.ports.length)
DO
port: Port ← cell.class.ports[portIndex];
IF
NOT port.input
THEN
LOOP;
TRUSTED BEGIN
Distribute[
cell.realCellStuff.newIOAsWP + port.firstWord,
port.wordCount,
str.insideNodes[portIndex],
NIL,
str];
END;
ENDLOOP;
Run[str];
FOR c:
CARDINAL
IN [0 .. cell.class.ioWordCount)
DO
TRUSTED
BEGIN
(cell.realCellStuff.newIOAsWP+c)^ ← (str.mirror.realCellStuff.newIOAsWP+c)^;
END;
ENDLOOP;
END;
Distribute:
PROC [base: WordPtr, count:
CARDINAL, fromNode: Node, fromCell: Cell, str: Structure] =
BEGIN
abort: BOOLEAN ← FALSE;
FOR dests: SocketList ← fromNode.readers, dests.rest
WHILE dests #
NIL
DO
target: Cell ← dests.first.cell;
targPort: Port ← target.class.ports[dests.first.index];
sourceWP: WordPtr ← base;
destWP: WordPtr;
TRUSTED BEGIN
destWP ← target.realCellStuff.newIOAsWP + targPort.firstWord;
END;
FOR j:
CARDINAL
IN [0 .. targPort.wordCount)
DO
TRUSTED
BEGIN
destWP^ ← sourceWP^;
sourceWP ← sourceWP + 1;
destWP ← destWP + 1;
END;
ENDLOOP;
IF target # fromCell THEN Schedule[target, str];
ENDLOOP;
FOR watchers: NodeWatcherList ← fromNode.watchers[1], watchers.rest
WHILE watchers #
NIL
DO
watchers.first.notify[node: fromNode, clientData: watchers.first.clientData !ABORTED => {abort ← TRUE; CONTINUE}];
ENDLOOP;
IF abort THEN ERROR ABORTED;
FOR watchers: NodeWatcherList ← fromNode.watchers[0], watchers.rest
WHILE watchers #
NIL
DO
watchers.first.notify[node: fromNode, clientData: watchers.first.clientData !ABORTED => {abort ← TRUE; CONTINUE}];
ENDLOOP;
IF abort THEN ERROR ABORTED;
END;
Operations:
GetStrLock:
ENTRY
PROC [str: Structure] =
BEGIN ENABLE UNWIND => NULL;
IF str.locked THEN ERROR Error["Structure in use"];
str.locked ← TRUE;
END;
ReleaseStrLock: PROC [str: Structure] = {str.locked ← FALSE};
notInSchedule: PUBLIC Cell ← NEW [CellRep];
ScheduleCell:
PUBLIC
PROC [cell: Cell] =
BEGIN
WHILE cell.parent #
NIL
DO
str: Structure ← CellToStr[cell.parent];
Schedule[cell, str];
cell ← str.container;
ENDLOOP;
END;
CellToStr:
PUBLIC
PROC [cell: Cell]
RETURNS [str: Structure] =
BEGIN
WHILE (IF cell.realCellStuff = NIL THEN TRUE ELSE IF cell.realCellStuff.state = NIL THEN TRUE ELSE NOT ISTYPE[cell.realCellStuff.state, Structure]) DO cell ← cell.parent ENDLOOP;
RETURN [NARROW[cell.realCellStuff.state]];
END;
NotifyCellEval:
PROC [cell: Cell] =
BEGIN
abort: BOOLEAN ← FALSE;
FOR wl: CellWatcherList ← cell.realCellStuff.evalWatchers, wl.rest
WHILE wl #
NIL
DO
wl.first.notify[cell: cell, clientData: wl.first.clientData !ABORTED => {abort ← TRUE; CONTINUE}];
ENDLOOP;
IF abort THEN ERROR ABORTED;
END;
SingleStep:
PUBLIC
PROC [str: Structure] =
BEGIN
GetStrLock[str];
BEGIN ENABLE UNWIND => ReleaseStrLock[str];
IF stop THEN SIGNAL Stop[msg: "Stopped", data: str];
IF str.schedFirst #
NIL
THEN
BEGIN
cell: Cell ← PickFromSchedule[str];
IF cell.realCellStuff.eval #
NIL
THEN
BEGIN
errorAbort: BOOLEAN ← FALSE;
cell.realCellStuff.eval[cell !UNWIND => [] ← ReallyCleanUpAfterModify[cell, str, TRUE, FALSE]];
[] ← ReallyCleanUpAfterModify[cell, str, TRUE, FALSE];
NotifyCellEval[cell];
END;
END;
END;
ReleaseStrLock[str];
END;
stop: PUBLIC BOOLEAN ← FALSE;
Run:
PUBLIC
PROC [str: Structure] =
BEGIN
GetStrLock[str];
BEGIN ENABLE UNWIND => ReleaseStrLock[str];
WHILE str.schedFirst #
NIL
DO
cell: Cell;
IF stop THEN SIGNAL Stop[msg: "Stopped", data: str];
cell ← PickFromSchedule[str];
IF cell.realCellStuff.eval #
NIL
THEN
BEGIN
errorAbort: BOOLEAN ← FALSE;
cell.realCellStuff.eval[cell !UNWIND => [] ← ReallyCleanUpAfterModify[cell, str, TRUE, FALSE]];
[] ← ReallyCleanUpAfterModify[cell, str, TRUE, FALSE];
NotifyCellEval[cell];
END;
ENDLOOP;
END;
ReleaseStrLock[str];
END;
PickFromSchedule:
PROC [str: Structure]
RETURNS [cell: Cell] =
BEGIN
abort: BOOLEAN ← FALSE;
cell ← str.schedFirst;
IF (str.schedFirst ← cell.realCellStuff.schedNext) = NIL THEN str.schedLast ← NIL;
cell.realCellStuff.schedNext ← notInSchedule;
FOR cw: CellWatcherList ← cell.realCellStuff.schedWatchers, cw.rest
WHILE cw #
NIL
DO
cw.first.notify[cell: cell, clientData: cw.first.clientData !ABORTED => {abort ← TRUE; CONTINUE}];
ENDLOOP;
IF abort THEN ERROR ABORTED;
IF str.schedFirst = NIL THEN RETURN;
FOR cw: CellWatcherList ← str.schedFirst.realCellStuff.schedWatchers, cw.rest
WHILE cw #
NIL
DO
cw.first.notify[cell: str.schedFirst, clientData: cw.first.clientData !ABORTED => {abort ← TRUE; CONTINUE}];
ENDLOOP;
IF abort THEN ERROR ABORTED;
END;
AllowToModify:
PUBLIC
PROC [cell: Cell, modifier: ModifyProc, blindly:
BOOLEAN ←
FALSE] =
BEGIN
ReallyAllowToModify: ModifyProc =
BEGIN
GetStrLock[str];
IF
NOT blindly
THEN
FOR c:
CARDINAL
IN [0 .. theCell.class.ioWordCount)
DO
TRUSTED
BEGIN
(theCell.realCellStuff.oldIOAsWP+c)^ ← (theCell.realCellStuff.newIOAsWP+c)^;
END;
ENDLOOP;
subtle ← modifier[theCell !
UNWIND =>
BEGIN
subtle ← ReallyCleanUpAfterModify[theCell, str, FALSE, blindly];
ReleaseStrLock[str];
END];
IF subtle THEN Schedule[theCell, str];
subtle ← subtle OR ReallyCleanUpAfterModify[theCell, str, FALSE, blindly];
ReleaseStrLock[str];
END;
theCell: Cell ← cell;
str: Structure ← NIL;
IF cell.parent = NIL THEN [] ← modifier[theCell]
ELSE IF (str ← CellToStr[cell.parent]).container.parent = NIL THEN [] ← ReallyAllowToModify[NIL]
ELSE AllowToModify[str.container, ReallyAllowToModify, FALSE];
END;
CleanUpAfterModify:
PUBLIC
PROC [cell: Cell] =
BEGIN
[] ← ReallyCleanUpAfterModify[cell, CellToStr[cell.parent], FALSE, FALSE];
END;
ReallyCleanUpAfterModify:
PROC [cell: Cell, str: Structure, strict, blindly:
BOOLEAN]
RETURNS [anyDiff:
BOOLEAN] =
BEGIN
anyDiff ← FALSE;
FOR outPortIndex:
CARDINAL
IN [0 .. cell.class.ports.length)
DO
port: Port ← cell.class.ports[outPortIndex];
diff: BOOLEAN ← FALSE;
newWP: WordPtr;
oldWP: WordPtr;
IF strict AND NOT port.output THEN LOOP;
TRUSTED
BEGIN
newWP ← cell.realCellStuff.newIOAsWP + port.firstWord;
oldWP ← cell.realCellStuff.oldIOAsWP + port.firstWord;
END;
IF blindly THEN diff ← TRUE
ELSE
FOR i:
CARDINAL
IN [0 .. port.wordCount)
DO
TRUSTED
BEGIN
IF newWP^ # oldWP^ THEN {diff ← TRUE; EXIT};
newWP ← newWP + 1;
oldWP ← oldWP + 1;
END;
ENDLOOP;
IF diff
THEN
TRUSTED BEGIN
anyDiff ← TRUE;
cell.interfaceNodes[outPortIndex].visible ← [cell, outPortIndex];
Distribute[
cell.realCellStuff.newIOAsWP + port.firstWord,
port.wordCount,
cell.interfaceNodes[outPortIndex],
cell,
str];
END;
ENDLOOP;
END;
Test:
PUBLIC
PROC [subject: Cell, parms: TestParms] =
BEGIN
ReallyTest: ModifyProc =
BEGIN
subject.class.test[subject];
subtle ← TRUE;
END;
IF subject.type # Real THEN ERROR Error["Attempt to test a Shadow Cell", subject];
subject.other ← List.PutAssoc[key: $TestParms, val: parms, aList: subject.other];
AllowToModify[subject, ReallyTest];
END;
Eval:
PUBLIC
PROC [cell: Cell] =
BEGIN
parms: TestParms ← NARROW[List.Assoc[key: $TestParms, aList: cell.other]];
str: Structure ← NIL;
IF cell.parent #
NIL
THEN
BEGIN
str ← CellToStr[cell.parent];
IF ReallyCleanUpAfterModify[cell, str, FALSE, FALSE] THEN Schedule[cell, str];
END;
NotifyCellEval[cell];
IF parms.stopBefore THEN SIGNAL Stop["About to eval", cell];
cell.realCellStuff.eval[cell];
IF cell.parent #
NIL
THEN
BEGIN
IF ReallyCleanUpAfterModify[cell, str, FALSE, FALSE] THEN Schedule[cell, str];
END;
NotifyCellEval[cell];
IF parms.stopAfter THEN SIGNAL Stop["Just eval'ed", cell];
IF cell.parent #
NIL
THEN
BEGIN
FOR c:
CARDINAL
IN [0 .. cell.class.ioWordCount)
DO
TRUSTED
BEGIN
(cell.realCellStuff.oldIOAsWP+c)^ ← (cell.realCellStuff.newIOAsWP+c)^;
END;
ENDLOOP;
END;
END;
UpToReal:
PUBLIC
PROC [cell: Cell]
RETURNS [realCell: Cell] =
BEGIN
FOR realCell ← cell, realCell.parent WHILE realCell.type # Real DO NULL ENDLOOP;
END;
Schedule:
PROC [cell: Cell, str: Structure] =
BEGIN
abort: BOOLEAN ← FALSE;
IF cell.realCellStuff.schedNext # notInSchedule THEN RETURN;
cell.realCellStuff.schedNext ← NIL;
IF str.schedLast = NIL THEN str.schedFirst ← cell ELSE str.schedLast.realCellStuff.schedNext ← cell;
str.schedLast ← cell;
FOR cw: CellWatcherList ← cell.realCellStuff.schedWatchers, cw.rest
WHILE cw #
NIL
DO
cw.first.notify[cell: cell, clientData: cw.first.clientData !ABORTED => {abort ← TRUE; CONTINUE}];
ENDLOOP;
IF abort THEN ERROR ABORTED;
END;
SocketToWP:
PUBLIC
PROC [s: Socket]
RETURNS [wp: WordPtr] =
TRUSTED BEGIN
wp ← s.cell.realCellStuff.newIOAsWP + s.cell.class.ports[s.index].firstWord;
END;
UnScheduleCell:
PUBLIC
PROC [cell: Cell] =
BEGIN
str: Structure ← CellToStr[cell.parent];
prev, cur: Cell ← NIL;
abort: BOOLEAN ← FALSE;
FOR cur ← str.schedFirst, cur.realCellStuff.schedNext
WHILE cur #
NIL
DO
IF cur = cell THEN EXIT;
ENDLOOP;
IF cur = NIL THEN RETURN;
IF prev = NIL THEN str.schedFirst ← cur.realCellStuff.schedNext ELSE prev.realCellStuff.schedNext ← cur.realCellStuff.schedNext;
IF str.schedLast = cur THEN str.schedLast ← prev;
cur.realCellStuff.schedNext ← notInSchedule;
FOR cw: CellWatcherList ← cell.realCellStuff.schedWatchers, cw.rest
WHILE cw #
NIL
DO
cw.first.notify[cell: cell, clientData: cw.first.clientData !ABORTED => {abort ← TRUE; CONTINUE}];
ENDLOOP;
IF abort THEN ERROR ABORTED;
IF str.schedFirst = NIL THEN RETURN;
FOR cw: CellWatcherList ← str.schedFirst.realCellStuff.schedWatchers, cw.rest
WHILE cw #
NIL
DO
cw.first.notify[cell: str.schedFirst, clientData: cw.first.clientData !ABORTED => {abort ← TRUE; CONTINUE}];
ENDLOOP;
IF abort THEN ERROR ABORTED;
END;
LongCellName:
PUBLIC
PROC [cell: Cell]
RETURNS [ln:
ROPE] =
BEGIN
ln ← cell.name;
FOR cell ← cell.parent, cell.parent
WHILE cell #
NIL
DO
ln ← cell.name.Cat[".", ln];
ENDLOOP;
END;
LookupCell:
PUBLIC
PROC [path:
LIST
OF
ROPE, from: Cell ←
NIL]
RETURNS [cell: Cell] =
BEGIN
sofar: LIST OF ROPE ← NIL;
cell ← from;
WHILE path #
NIL
DO
next: Cell ← NARROW[(IF cell = NIL THEN roots ELSE cell.components). Lookup[path.first]];
IF next =
NIL
THEN
{SIGNAL Warning[IO.PutFR["Not found: %g %g %g", IO.refAny[sofar], IO.refAny[path.first], IO.refAny[path.rest]]]; RETURN [NIL]};
sofar ← CONS[path.first, sofar];
path ← path.rest;
cell ← next;
ENDLOOP;
END;
RootStructure:
PUBLIC
PROC [cell: Cell]
RETURNS [str: Structure] =
BEGIN
FOR str ← CellToStr[cell], CellToStr[str.container.parent] WHILE str.container.parent # NIL DO NULL ENDLOOP;
END;
END.