RoseRunImpl.mesa
Last Edited by: Spreitzer, July 13, 1984 11:20:59 pm PDT PDT
Last Edited by: Barth, July 23, 1984 11:43:40 am PDT
DIRECTORY IO, List, OrderedSymbolTableRef, Rope, RoseEvents, RoseIOHacks, RoseRun, RoseTypes;
RoseRunImpl: CEDAR PROGRAM
IMPORTS RoseEvents, RoseIOHacks, RoseTypes
EXPORTS RoseRun, RoseTypes =
BEGIN OPEN RoseTypes;
stop: PUBLIC BOOLEANFALSE;
notInStrList: PUBLIC Structure ← NEW [StructureRep];
notInCellList: PUBLIC Cell ← NEW [CellRep];
notInNodeList: PUBLIC Node ← NEW [NodeRep];
StrEvals: PUBLIC EvalProcs ← [
InitQ: StrInitQ,
PropQ: StrPropQ,
InitUD: StrInitUD,
PropUD: StrPropUD,
FinalUD: StrFinalUD,
EvalSimple: StrSimple,
FindVicinity: StrFindVicinity
];
StrMirrorEvals: PUBLIC EvalProcs ← [
InitQ: StrInitQ,
PropQ: StrMirrorPropQ,
InitUD: StrInitUD,
PropUD: StrMirrorPropUD,
FinalUD: StrFinalUD,
EvalSimple: StrMirrorSimple,
FindVicinity: StrMirrorFindVicinity
];
SocketToWP: PUBLIC PROC [s: Socket, useBryant: BOOLFALSE] RETURNS [wp: WordPtr] =
TRUSTED BEGIN
wp ← (IF useBryant THEN s.cell.realCellStuff.switchIOAsWP ELSE s.cell.realCellStuff.newIOAsWP) + s.cell.class.ports[s.index].firstWord;
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;
Run: PUBLIC PROC [sim: Simulation] =
BEGIN
ran: BOOLEANFALSE;
WHILE StepSim[sim] # noStep DO ran ← TRUE ENDLOOP;
IF ran THEN RoseEvents.Notify[event: $EndOfRun, watched: sim, handleAborted: TRUE];
END;
Next: PUBLIC PROC [sim: Simulation] RETURNS [stepType: RoseRun.StepType] =
BEGIN
topStr: Structure;
topStr ← NARROW[sim.root.realCellStuff.state];
IF sim.switched AND topStr.schedFirst # NIL THEN RETURN [otherStep];
IF sim.firstPerturbedStr # NIL THEN RETURN [switchStep];
IF topStr.schedFirst # NIL THEN RETURN [otherStep];
stepType ← noStep;
END;
StepSim: PUBLIC PROC [sim: Simulation] RETURNS [stepType: RoseRun.StepType] =
BEGIN
SELECT stepType ← Next[sim] FROM
noStep => NULL;
switchStep => SwitchStepSim[sim];
otherStep => {sim.root.realCellStuff.evals.EvalSimple[sim.root]; sim.switched ← FALSE};
ENDCASE => ERROR;
END;
SwitchStepSim: PROC [sim: Simulation] =
BEGIN
str: Structure;
sim.firstWasPerturbedStr ← sim.firstPerturbedStr;
sim.firstPerturbedStr ← NIL;
FOR str ← sim.firstWasPerturbedStr, str.nextWasPerturbed WHILE str # NIL DO
IF str = notInStrList THEN ERROR;
IF str.nextPerturbed = notInStrList THEN ERROR;
str.nextWasPerturbed ← str.nextPerturbed;
str.nextPerturbed ← notInStrList;
ENDLOOP;
FOR str ← sim.firstWasPerturbedStr, str.nextWasPerturbed WHILE str # NIL DO
IF str.container.realCellStuff.evals # StrEvals THEN ERROR;
StrFindVicinity[str.container, noPort];
ENDLOOP;
FOR str ← sim.firstWasPerturbedStr, str.nextWasPerturbed WHILE str # NIL DO
IF NOT str.container.realCellStuff.initQed THEN {
str.container.realCellStuff.initQed ← TRUE;
StrInitQ[str.container]}
ENDLOOP;
FOR str ← sim.firstWasPerturbedStr, str.nextWasPerturbed WHILE str # NIL DO
IF NOT str.container.realCellStuff.propQed THEN {
str.container.realCellStuff.propQed ← TRUE;
StrPropQWork[str, IF str.mirror = NIL THEN str.container ELSE str.mirror, str.insideNodes, TRUE]}
ENDLOOP;
FOR str ← sim.firstWasPerturbedStr, str.nextWasPerturbed WHILE str # NIL DO
IF NOT str.container.realCellStuff.initUDed THEN {
str.container.realCellStuff.initUDed ← TRUE;
StrInitUD[str.container]}
ENDLOOP;
FOR str ← sim.firstWasPerturbedStr, str.nextWasPerturbed WHILE str # NIL DO
IF NOT str.container.realCellStuff.propUDed THEN {
str.container.realCellStuff.propUDed ← TRUE;
StrPropUDWork[str, IF str.mirror = NIL THEN str.container ELSE str.mirror, str.insideNodes, TRUE]}
ENDLOOP;
FOR str ← sim.firstWasPerturbedStr, str.nextWasPerturbed WHILE str # NIL DO
StrFinalUD[str.container];
str.container.realCellStuff.initQed ← str.container.realCellStuff.propQed ← str.container.realCellStuff.initUDed ← str.container.realCellStuff.propUDed ← FALSE;
ENDLOOP;
sim.switched ← TRUE;
END;
PerturbNode: PUBLIC PROC [node: Node, within: Cell] =
{ReallyPerturb[node, CellToStr[within], within.sim]};
PerturbPort: PUBLIC PROC [cell: Cell, index: CARDINAL] =
{ReallyPerturb[cell.interfaceNodes[index], ContainingStr[cell], cell.sim]};
ReallyPerturb: PROC [node: Node, str: Structure, sim: Simulation] =
BEGIN
IF node.type.simple THEN ERROR;
IF node.nextPerturbed = notInNodeList THEN {
IF str.firstPerturbed = notInNodeList THEN ERROR;
node.nextPerturbed ← str.firstPerturbed;
str.firstPerturbed ← node;
IF str.nextPerturbed = notInStrList THEN {
IF sim.firstPerturbedStr = notInStrList THEN ERROR;
str.nextPerturbed ← sim.firstPerturbedStr;
sim.firstPerturbedStr ← str;
};
};
END;
FindExteriorVicinity: PUBLIC PROC [cell: Cell, index: CARDINAL] =
BEGIN
ReallyFindVicinity[ContainingStr[cell], cell.interfaceNodes[index]];
END;
ReallyFindVicinity: PROC [str: Structure, n: Node] =
BEGIN
IF n.found THEN RETURN;
n.found ← TRUE;
IF str.firstAffected = notInNodeList THEN ERROR;
n.nextAffected ← str.firstAffected;
str.firstAffected ← n;
FOR sl: SocketList ← n.readers, sl.rest WHILE sl # NIL DO
IF sl.first.cell.realCellStuff.evals.FindVicinity # NIL THEN sl.first.cell.realCellStuff.evals.FindVicinity[sl.first.cell, sl.first.index];
sl.first.cell.realCellStuff.affectedFlags[read][Specialty[sl.first]] ← TRUE;
ENDLOOP;
FOR sl: SocketList ← n.bidirs, sl.rest WHILE sl # NIL DO
IF sl.first.cell.realCellStuff.evals.FindVicinity # NIL THEN sl.first.cell.realCellStuff.evals.FindVicinity[sl.first.cell, sl.first.index];
sl.first.cell.realCellStuff.affectedFlags[read][Specialty[sl.first]] ← TRUE;
sl.first.cell.realCellStuff.affectedFlags[write][Specialty[sl.first]] ← TRUE;
ENDLOOP;
FOR sl: SocketList ← n.writers, sl.rest WHILE sl # NIL DO
sl.first.cell.realCellStuff.affectedFlags[write][Specialty[sl.first]] ← TRUE;
ENDLOOP;
END;
Specialty: PROC [st: Socket] RETURNS [sy: Speciality] =
{sy ← IF st.cell.class.ports[st.index].special AND NotAgg[st.cell] THEN special ELSE general};
StrFindVicinity: PROC [cell: Cell, index: CARDINAL] =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
this: Node;
IF index # noPort THEN ReallyFindVicinity[str, str.insideNodes[index]];
WHILE str.firstPerturbed # NIL DO
IF str.firstPerturbed = notInNodeList THEN ERROR;
this ← str.firstPerturbed;
str.firstPerturbed ← this.nextPerturbed;
this.nextPerturbed ← notInNodeList;
ReallyFindVicinity[str, this];
ENDLOOP;
END;
StrMirrorFindVicinity: PROC [cell: Cell, index: CARDINAL] =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
unmirrored: Cell← cell.parent;
this: Node;
IF index # noPort THEN ReallyFindVicinity[str, unmirrored.interfaceNodes[index]];
WHILE str.firstPerturbed # NIL DO
IF str.firstPerturbed = notInNodeList THEN ERROR;
this ← str.firstPerturbed;
str.firstPerturbed ← this.nextPerturbed;
this.nextPerturbed ← notInNodeList;
ReallyFindVicinity[str, this];
ENDLOOP;
END;
Need1: PROC [str: Structure, n: Node, also: CellProc] =
BEGIN
FOR sl: SocketList ← n.writers, sl.rest WHILE sl # NIL DO
IF sl.first.cell.realCellStuff.nextNeeded = notInCellList THEN
BEGIN
IF str.firstNeeded = notInCellList THEN ERROR;
sl.first.cell.realCellStuff.nextNeeded ← str.firstNeeded;
str.firstNeeded ← sl.first.cell;
IF also # NIL THEN also[sl.first.cell];
END;
ENDLOOP;
FOR sl: SocketList ← n.bidirs, sl.rest WHILE sl # NIL DO
IF sl.first.cell.realCellStuff.nextNeeded = notInCellList THEN
BEGIN
IF str.firstNeeded = notInCellList THEN ERROR;
sl.first.cell.realCellStuff.nextNeeded ← str.firstNeeded;
str.firstNeeded ← sl.first.cell;
IF also # NIL THEN also[sl.first.cell];
END;
ENDLOOP;
FOR sl: SocketList ← n.readers, sl.rest WHILE sl # NIL DO
IF sl.first.cell.realCellStuff.nextNeeded = notInCellList THEN
BEGIN
IF str.firstNeeded = notInCellList THEN ERROR;
sl.first.cell.realCellStuff.nextNeeded ← str.firstNeeded;
str.firstNeeded ← sl.first.cell;
IF also # NIL THEN also[sl.first.cell];
END;
ENDLOOP;
END;
Need2: PROC [str: Structure, n: Node, except: Cell] =
BEGIN
FOR sl: SocketList ← n.readers, sl.rest WHILE sl # NIL DO
IF sl.first.cell.realCellStuff.nextNeeded = notInCellList AND sl.first.cell # except AND (sl.first.cell.realCellStuff.affectedFlags[write][special] OR sl.first.cell.realCellStuff.affectedFlags[write][general]) THEN
BEGIN
IF str.firstNeeded = notInCellList THEN ERROR;
sl.first.cell.realCellStuff.nextNeeded ← str.firstNeeded;
str.firstNeeded ← sl.first.cell;
END;
ENDLOOP;
FOR sl: SocketList ← n.bidirs, sl.rest WHILE sl # NIL DO
IF sl.first.cell.realCellStuff.nextNeeded = notInCellList AND sl.first.cell # except THEN
BEGIN
IF str.firstNeeded = notInCellList THEN ERROR;
sl.first.cell.realCellStuff.nextNeeded ← str.firstNeeded;
str.firstNeeded ← sl.first.cell;
END;
ENDLOOP;
END;
InitQ: CellProc--PROC [cell: Cell]-- = {
IF NOT cell.realCellStuff.initQed THEN {
cell.realCellStuff.initQed ← TRUE;
IF cell.realCellStuff.evals.InitQ # NIL THEN cell.realCellStuff.evals.InitQ[cell]}};
StrInitQ: CellProc--PROC [cell: Cell]-- =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
FOR n: Node ← str.firstAffected, n.nextAffected WHILE n # NIL DO
IF n = notInNodeList THEN ERROR;
IF n.type.procs.InitQ # NIL THEN n.type.procs.InitQ[n];
Need1[str, n, InitQ];
ENDLOOP;
END;
StrPropQ: CellProc--PROC [cell: Cell]-- =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
StrPropQWork[str, IF str.mirror = NIL THEN cell ELSE str.mirror, str.insideNodes, FALSE];
END;
StrMirrorPropQ: CellProc--PROC [cell: Cell]-- =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
StrPropQWork[str, cell.parent, cell.parent.interfaceNodes, FALSE];
END;
StrPropQWork: PROC [str: Structure, innerBorder: Cell, borderNodes: NodeS, top: BOOLEAN] =
BEGIN
IF NOT top THEN
FOR index: CARDINAL IN [0 .. innerBorder.class.ports.length) DO
inside: Node ← borderNodes[index];
IF inside.type.procs.NewQ = NIL THEN LOOP;
IF inside.type.procs.NewQ[inside, SocketToWP[[innerBorder, index], TRUE]] THEN Need2[str, inside, innerBorder];
ENDLOOP;
WHILE str.firstNeeded # NIL DO
needed: Cell ← str.firstNeeded;
IF needed = notInCellList THEN ERROR;
str.firstNeeded ← needed.realCellStuff.nextNeeded;
needed.realCellStuff.nextNeeded ← notInCellList;
needed.realCellStuff.initQed ← FALSE;
IF (needed.realCellStuff.evals.PropQ = NIL) AND (NOT (needed.class.hasASpecialPort AND NotAgg[needed])) THEN LOOP;
FOR index: CARDINAL IN [0 .. needed.class.ports.length) DO
IF needed.class.ports[index].type.procs.QFromNode # NIL THEN needed.class.ports[index].type.procs.QFromNode[needed.interfaceNodes[index], SocketToWP[[needed, index], TRUE]];
ENDLOOP;
PropInner[needed, needed.realCellStuff.evals.PropQ];
FOR index: CARDINAL IN [0 .. needed.class.ports.length) DO
inside: Node ← needed.interfaceNodes[index];
IF inside.type.procs.NewQ = NIL OR NOT needed.class.ports[index].output THEN LOOP;
IF inside.nextAffected = notInNodeList THEN ERROR;
IF inside.type.procs.NewQ[inside, SocketToWP[[needed, index], TRUE]] THEN Need2[str, inside, needed];
ENDLOOP;
ENDLOOP;
IF NOT top THEN
FOR index: CARDINAL IN [0 .. innerBorder.class.ports.length) DO
inside: Node ← borderNodes[index];
IF inside.type.procs.QFromNode = NIL THEN LOOP;
inside.type.procs.QFromNode[inside, SocketToWP[[innerBorder, index], TRUE]];
ENDLOOP;
END;
PropInner: PROC [cell: Cell, prop: CellProc] =
BEGIN
IF cell.class.hasASpecialPort AND NotAgg[cell] THEN RoseIOHacks.CopyIO[
from: cell.realCellStuff.newIOAsWP,
to: cell.realCellStuff.switchIOAsWP,
by: cell.class.ports,
what: [inputs: none, outputs: forward, bidirs: forward],
specials: TRUE, generals: FALSE, simples: FALSE, drive: NIL];
IF prop # NIL THEN prop[cell];
END;
InitUD: CellProc--PROC [cell: Cell]-- = {
IF NOT cell.realCellStuff.initUDed THEN {
cell.realCellStuff.initUDed ← TRUE;
IF cell.realCellStuff.evals.InitUD # NIL THEN cell.realCellStuff.evals.InitUD[cell]}};
StrInitUD: CellProc--PROC [cell: Cell]-- =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
FOR n: Node ← str.firstAffected, n.nextAffected WHILE n # NIL DO
IF n = notInNodeList THEN ERROR;
IF n.type.procs.InitUD # NIL THEN n.type.procs.InitUD[n];
Need1[str, n, InitUD];
RoseEvents.Notify[event: $NewNodeUD, watched: n, handleAborted: TRUE, arg: NIL];
ENDLOOP;
END;
StrPropUD: CellProc--PROC [cell: Cell]-- =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
StrPropUDWork[str, IF str.mirror = NIL THEN cell ELSE str.mirror, str.insideNodes, FALSE];
END;
StrMirrorPropUD: CellProc--PROC [cell: Cell]-- =
BEGIN
StrPropUDWork[NARROW[cell.realCellStuff.state], cell.parent, cell.parent.interfaceNodes, FALSE];
END;
NotAgg: PROC [cell: Cell] RETURNS [notAgg: BOOL] = INLINE {
notAgg ← cell.expansion = Leaf AND CellToStr[cell.parent].mirror # cell};
StrPropUDWork: PROC [str: Structure, innerBorder: Cell, borderNodes: NodeS, top: BOOLEAN] =
BEGIN
IF NOT top THEN
FOR index: CARDINAL IN [0 .. innerBorder.class.ports.length) DO
inside: Node ← borderNodes[index];
IF inside.type.procs.NewUD = NIL THEN LOOP;
IF inside.type.procs.NewUD[inside, SocketToWP[[innerBorder, index], TRUE]] THEN {
Need2[str, inside, innerBorder];
RoseEvents.Notify[event: $NewNodeUD, watched: inside, handleAborted: TRUE, arg: innerBorder]}
ENDLOOP;
WHILE str.firstNeeded # NIL DO
needed: Cell ← str.firstNeeded;
IF needed = notInCellList THEN ERROR;
str.firstNeeded ← needed.realCellStuff.nextNeeded;
needed.realCellStuff.nextNeeded ← notInCellList;
needed.realCellStuff.initUDed ← FALSE;
IF (needed.realCellStuff.evals.PropUD = NIL) AND (NOT (needed.class.hasASpecialPort AND NotAgg[needed])) THEN LOOP;
FOR index: CARDINAL IN [0 .. needed.class.ports.length) DO
IF needed.class.ports[index].type.procs.UDFromNode # NIL THEN needed.class.ports[index].type.procs.UDFromNode[needed.interfaceNodes[index], SocketToWP[[needed, index], TRUE]];
ENDLOOP;
PropInner[needed, needed.realCellStuff.evals.PropUD];
FOR index: CARDINAL IN [0 .. needed.class.ports.length) DO
inside: Node ← needed.interfaceNodes[index];
IF inside.type.procs.NewUD = NIL OR NOT needed.class.ports[index].output THEN LOOP;
IF inside.nextAffected = notInNodeList THEN ERROR;
IF inside.type.procs.NewUD[inside, SocketToWP[[needed, index], TRUE]] THEN {
Need2[str, inside, needed];
RoseEvents.Notify[event: $NewNodeUD, watched: inside, handleAborted: TRUE, arg: needed]};
ENDLOOP;
ENDLOOP;
IF NOT top THEN
FOR index: CARDINAL IN [0 .. innerBorder.class.ports.length) DO
inside: Node ← borderNodes[index];
IF inside.type.procs.UDFromNode = NIL THEN LOOP;
inside.type.procs.UDFromNode[inside, SocketToWP[[innerBorder, index], TRUE]];
ENDLOOP;
END;
StrFinalUD: CellProc--PROC [cell: Cell]-- =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
firstNoted, next: Cell ← NIL;
FOR n: Node ← str.firstAffected, n.nextAffected WHILE n # NIL DO
IF n = notInNodeList THEN ERROR;
n.found ← FALSE;
IF n.type.procs.NewVal # NIL THEN n.type.procs.NewVal[n];
RoseEvents.Notify[event: $ChangeEarly, watched: n, handleAborted: TRUE];
RoseEvents.Notify[event: $ChangeLate, watched: n, handleAborted: TRUE];
FOR sl: SocketList ← n.readers, sl.rest WHILE sl # NIL DO
IF sl.first.cell.realCellStuff.nextNoted = notInCellList THEN
{sl.first.cell.realCellStuff.nextNoted ← firstNoted; firstNoted ← sl.first.cell};
ENDLOOP;
FOR sl: SocketList ← n.bidirs, sl.rest WHILE sl # NIL DO
IF sl.first.cell.realCellStuff.nextNoted = notInCellList THEN
{sl.first.cell.realCellStuff.nextNoted ← firstNoted; firstNoted ← sl.first.cell};
ENDLOOP;
FOR sl: SocketList ← n.writers, sl.rest WHILE sl # NIL DO
IF sl.first.cell.realCellStuff.nextNoted = notInCellList THEN
{sl.first.cell.realCellStuff.nextNoted ← firstNoted; firstNoted ← sl.first.cell};
ENDLOOP;
ENDLOOP;
str.firstAffected ← NIL;
FOR firstNoted ← firstNoted, next WHILE firstNoted # NIL DO
IF firstNoted = notInCellList THEN ERROR;
next ← firstNoted.realCellStuff.nextNoted;
firstNoted.realCellStuff.nextNoted ← notInCellList;
FOR index: CARDINAL IN [0 .. firstNoted.class.ports.length) DO
ntp: NodeProcs ← firstNoted.class.ports[index].type.procs;
IF ntp.ValFromNode # NIL
THEN ntp.ValFromNode[
firstNoted.interfaceNodes[index],
SocketToWP[[firstNoted, index], TRUE]];
IF SocketIsSpecial[[firstNoted, index]] AND ntp.UDFromNode # NIL
THEN ntp.UDFromNode[
firstNoted.interfaceNodes[index],
SocketToWP[[firstNoted, index], TRUE]];
ENDLOOP;
IF firstNoted.realCellStuff.evals.FinalUD # NIL THEN firstNoted.realCellStuff.evals.FinalUD[firstNoted];
IF firstNoted.realCellStuff.affectedFlags[read][special]
THEN ScheduleCell[firstNoted];
IF (firstNoted.realCellStuff.affectedFlags[read][general] OR firstNoted.realCellStuff.affectedFlags[read][special]) AND firstNoted.realCellStuff.evals.ValsChanged # NIL
THEN ValsChanged[firstNoted, str];
firstNoted.realCellStuff.affectedFlags ← ALL[ALL[FALSE]];
ENDLOOP;
END;
ValsChanged: PROC [cell: Cell, str: Structure] =
BEGIN
NewToOld[cell];
cell.realCellStuff.evals.ValsChanged[cell
!UNWIND => [] ← ReallyCleanUpAfterModify[cell: cell, str: str, outputsOnly: TRUE, blindly: FALSE, mayRescheduleSelf: TRUE, simples: TRUE, generals: FALSE, specials: TRUE]];
[] ← ReallyCleanUpAfterModify[cell: cell, str: str, outputsOnly: TRUE, blindly: FALSE, mayRescheduleSelf: TRUE, simples: TRUE, generals: FALSE, specials: TRUE];
END;
StrSimple: CellProc--PROC [cell: Cell]-- =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
IF str.running THEN ERROR ELSE str.running ← TRUE;
BEGIN ENABLE UNWIND => {str.running ← FALSE};
FOR portIndex: CARDINAL IN [0 .. cell.class.ports.length) DO
port: Port ← cell.class.ports[portIndex];
IF NOT port.type.simple THEN LOOP;
TRUSTED BEGIN
Distribute[
cell.realCellStuff.newIOAsWP + port.firstWord,
str.insideNodes[portIndex],
NIL,
str];
END;
ENDLOOP;
RunStr[str];
END;
str.running ← FALSE;
END;
StrMirrorSimple: CellProc--PROC [cell: Cell]-- =
{ERROR Error["Attempt to evaluate mirror's other", cell]};
ValueChanged: PUBLIC PROC [node: Node] =
BEGIN
IF node.type.simple THEN ERROR;
PerturbNode[node, node.cellIn];
RoseEvents.Notify[event: $ChangeEarly, watched: node, handleAborted: TRUE];
RoseEvents.Notify[event: $ChangeLate, watched: node, handleAborted: TRUE];
END;
Distribute: PROC [base: WordPtr, fromNode: Node, fromCell: Cell, str: Structure] =
BEGIN
DoDest: PROC [dest: Socket] =
BEGIN
target: Cell ← dest.cell;
targPort: Port ← target.class.ports[dest.index];
sourceWP: WordPtr ← base;
destWP: WordPtr;
IF target = NIL THEN ERROR;
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 NULL
ELSE IF target = str.mirror THEN {
IF NOT str.running THEN {
parentCell: Cell ← str.container;
parentStr: Structure ← ContainingStr[parentCell];
Distribute[base: SocketToWP[[parentCell, dest.index]], fromNode: parentCell.interfaceNodes[dest.index], fromCell: parentCell, str: parentStr];
ScheduleAllup[parentCell, parentStr];
};
}
ELSE ScheduleAllup[target, str];
END;
abort: BOOLEANFALSE;
IF fromNode.type.procs.SetNode # NIL THEN fromNode.type.procs.SetNode[fromNode, base];
FOR dests: SocketList ← fromNode.readers, dests.rest WHILE dests # NIL DO
DoDest[dests.first] ENDLOOP;
FOR dests: SocketList ← fromNode.bidirs, dests.rest WHILE dests # NIL DO
DoDest[dests.first] ENDLOOP;
FOR dests: SocketList ← fromNode.writers, dests.rest WHILE dests # NIL DO
DoDest[dests.first] ENDLOOP;
RoseEvents.Notify[event: $ChangeEarly, watched: fromNode, handleAborted: TRUE];
RoseEvents.Notify[event: $ChangeLate, watched: fromNode, handleAborted: TRUE];
END;
ScheduleStep: PROC [cell: Cell, str: Structure] =
BEGIN
IF cell.realCellStuff.schedNext # notInCellList THEN RETURN;
cell.realCellStuff.schedNext ← NIL;
IF str.schedLast = NIL THEN str.schedFirst ← cell ELSE str.schedLast.realCellStuff.schedNext ← cell;
str.schedLast ← cell;
RoseEvents.Notify[event: $Schedule, watched: cell, handleAborted: TRUE];
END;
ScheduleAllup: PROC [cell: Cell, str: Structure] =
BEGIN
IF cell.parent # NIL THEN DO
IF cell.realCellStuff.schedNext # notInCellList THEN RETURN;
cell.realCellStuff.schedNext ← NIL;
IF str.schedLast = NIL THEN str.schedFirst ← cell ELSE str.schedLast.realCellStuff.schedNext ← cell;
str.schedLast ← cell;
RoseEvents.Notify[event: $Schedule, watched: cell, handleAborted: TRUE];
IF str.running THEN RETURN;
IF (cell ← str.container).parent = NIL THEN RETURN;
str ← ContainingStr[cell];
ENDLOOP;
END;
NewToOld: PUBLIC PROC [cell: Cell] = TRUSTED
BEGIN
n: WordPtr ← cell.realCellStuff.newIOAsWP;
o: WordPtr ← cell.realCellStuff.oldIOAsWP;
FOR i: CARDINAL IN [0 .. cell.class.ioWordCount) DO
(o+i)^ ← (n+i)^;
ENDLOOP;
END;
PreSimple: PUBLIC PROC [cell: Cell] = TRUSTED
BEGIN
n: WordPtr ← cell.realCellStuff.newIOAsWP;
o: WordPtr ← cell.realCellStuff.oldIOAsWP;
FOR i: CARDINAL IN [0 .. cell.class.ioWordCount) DO
(o+i)^ ← (n+i)^;
ENDLOOP;
IF cell.class.hasASpecialPort AND NotAgg[cell]
THEN FOR portIndex: CARDINAL IN [0 .. cell.class.ports.length) DO
port: Port ← cell.class.ports[portIndex];
IF port.special THEN {
n: WordPtr ← cell.realCellStuff.newIOAsWP + port.firstWord;
s: WordPtr ← cell.realCellStuff.switchIOAsWP + port.firstWord;
FOR i: CARDINAL IN [0 .. port.wordCount) DO
(n+i)^ ← (s+i)^;
ENDLOOP;
};
ENDLOOP;
END;
RunStr: PROC [str: Structure] =
BEGIN
WHILE str.schedFirst # NIL DO
cell: Cell;
IF str.schedFirst = notInCellList THEN ERROR;
IF stop THEN SIGNAL Stop[msg: "Stopped", data: str];
cell ← PickFromSchedule[str];
IF cell.realCellStuff.evals.EvalSimple # NIL THEN
BEGIN
PreSimple[cell];
cell.realCellStuff.evals.EvalSimple[cell !UNWIND => {
[] ← ReallyCleanUpAfterModify[cell, str, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE];
ScheduleAllup[cell, str];
}];
[] ← ReallyCleanUpAfterModify[cell, str, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE];
RoseEvents.Notify[event: $Eval, watched: cell, handleAborted: TRUE];
END;
ENDLOOP;
END;
PickFromSchedule: PROC [str: Structure] RETURNS [cell: Cell] =
BEGIN
abort: BOOLEANFALSE;
cell ← str.schedFirst;
IF (str.schedFirst ← cell.realCellStuff.schedNext) = NIL THEN str.schedLast ← NIL;
cell.realCellStuff.schedNext ← notInCellList;
RoseEvents.Notify[event: $Schedule, watched: cell, handleAborted: TRUE];
IF str.schedFirst = NIL THEN RETURN;
RoseEvents.Notify[event: $Schedule, watched: str.schedFirst, handleAborted: TRUE];
END;
ReallyCleanUpAfterModify: PROC [cell: Cell, str: Structure, outputsOnly, blindly, mayRescheduleSelf, simples, generals, specials: BOOLEAN] RETURNS [anyDiff: BOOLEAN] =
BEGIN
notAgg: BOOL = NotAgg[cell];
anyDiff ← FALSE;
FOR portIndex: CARDINAL IN [0 .. cell.class.ports.length) DO
port: Port ← cell.class.ports[portIndex];
node: Node ← cell.interfaceNodes[portIndex];
diff: BOOLEANFALSE;
newWP: WordPtr;
oldWP: WordPtr;
IF (outputsOnly AND NOT port.output) THEN LOOP;
IF NOT (IF port.type.simple THEN simples ELSE IF notAgg AND port.special THEN specials ELSE generals) THEN LOOP;
TRUSTED BEGIN
newWP ← cell.realCellStuff.newIOAsWP + port.firstWord;
oldWP ← cell.realCellStuff.oldIOAsWP + port.firstWord;
END;
IF blindly THEN diff ← TRUE
ELSE BEGIN
IF port.special AND (NOT port.type.simple) AND NotAgg[cell] AND (port.type.procs.ComputeQ # NIL) THEN port.type.procs.ComputeQ[node, newWP];
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;
END;
IF diff THEN
TRUSTED BEGIN
anyDiff ← TRUE;
theActivityReport.node ← node;
theActivityReport.socket ← node.visible ← [cell, portIndex];
IF port.type.simple
THEN {
Distribute[
cell.realCellStuff.newIOAsWP + port.firstWord,
node,
IF NOT mayRescheduleSelf THEN cell ELSE NIL,
str];
RoseEvents.Notify[event: $SimpleChanged, watched: NIL, handleAborted: TRUE, arg: theActivityReport];
}
ELSE {
ReallyPerturb[node: node, str: str, sim: cell.sim];
RoseEvents.Notify[event: $NewSpecialSwitchInstructions, watched: NIL, handleAborted: TRUE, arg: theActivityReport];
};
END;
ENDLOOP;
END;
theActivityReport: RoseRun.ActivityReport ← NEW [RoseRun.ActivityReportRep];
ScheduleCell: PUBLIC PROC [cell: Cell] =
{ScheduleAllup[cell, ContainingStr[cell]]};
AllowToModify: PUBLIC PROC [cell: Cell, modifier: RoseRun.ModifyProc, blindly, mayRescheduleSelf: BOOLEANFALSE] =
BEGIN
str: Structure ← ContainingStr[cell];
subtle: BOOLFALSE;
IF NOT blindly THEN NewToOld[cell];
subtle ← modifier[cell !UNWIND =>
BEGIN
[] ← ReallyCleanUpAfterModify[cell, str, FALSE, blindly, mayRescheduleSelf, TRUE, TRUE, TRUE];
END];
[] ← ReallyCleanUpAfterModify[cell, str, FALSE, blindly, mayRescheduleSelf, TRUE, TRUE, TRUE];
IF subtle THEN ScheduleAllup[cell, str];
END;
AllowToModify: PUBLIC PROC [cell: Cell, modifier: RoseRun.ModifyProc, blindly, mayRescheduleSelf: BOOLEANFALSE] =
BEGIN
ReallyAllowToModify: RoseRun.ModifyProc--PROC [cell: Cell] RETURNS [subtle: BOOLEAN ← FALSE]-- =
BEGIN
--GetStrLock[str];--
IF NOT blindly THEN NewToOld[theCell];
subtle ← modifier[theCell !UNWIND =>
BEGIN
subtle ← ReallyCleanUpAfterModify[theCell, str, FALSE, blindly, mayRescheduleSelf, TRUE, TRUE, TRUE];
--ReleaseStrLock[str];--
END];
IF subtle THEN ScheduleStep[theCell, str];
subtle ← subtle OR ReallyCleanUpAfterModify[theCell, str, FALSE, blindly, mayRescheduleSelf, TRUE, TRUE, TRUE];
--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;
notInCellList.name ← "notInCellList";
notInNodeList.name ← "notInNodeList";
END.