MakeDoDownNodes.Mesa
Last Edited by: Spreitzer, September 4, 1985 11:03:35 pm PDT
Carl Hauser, April 11, 1985 3:43:34 pm PST
DIRECTORY Basics, BasicTime, CedarProcess, FS, IO, MakeDo, MakeDoPrivate, RedBlackTree, Rope;
MakeDoDownNodes: CEDAR MONITOR
LOCKS n.down USING n: Node
IMPORTS CedarProcess, IO, MakeDo, MakeDoPrivate, Rope
EXPORTS MakeDo, MakeDoPrivate
=
BEGIN OPEN MakeDo, MakeDoPrivate;
NodeRep: PUBLIC TYPE = MakeDoPrivate.NodeRep;
CommandRep: PUBLIC TYPE = MakeDoPrivate.CommandRep;
Enter: ENTRY PROC [n: Node] = {
ENABLE UNWIND => {};
WHILE n.down.locked DO WAIT n.down.change ENDLOOP;
n.down.locked ← TRUE;
};
MayEnterDownNode: PUBLIC ENTRY PROC [n: Node] RETURNS [in: BOOL] = {
ENABLE UNWIND => {};
in ← NOT n.down.locked;
IF in THEN n.down.locked ← TRUE;
};
ExitDownNode: PUBLIC ENTRY PROC [n: Node] = {
ENABLE UNWIND => {};
n.down.locked ← FALSE;
BROADCAST n.down.change;
};
DoIn: PROC [n: Node, p: --INTERNAL-- PROC [Node]] = {
Enter[n];
{ENABLE UNWIND => ExitDownNode[n];
p[n];
};
ExitDownNode[n];
};
SuspectProducer: PUBLIC --ENTRY-- PROC [n: Node, stack: Table] = {
Inner: --INTERNAL-- PROC [n: Node] = {
prod: Command = IF n.producer # NIL AND n.producer.c # leaf THEN n.producer.c ELSE NIL;
IF prod # NIL THEN {
CmdMayNeedRemaking[prod, cmd, stack];
CmdMayNeedRemaking[prod, data, stack];
}
ELSE NodeMayNeedRemaking[n, stack];
};
DoIn[n, Inner];
};
PublicPartsOfNode: PUBLIC PROC [n: Node] RETURNS [name: ROPE, class: NodeClass] = {
name ← n.name;
class ← n.class;
};
GetProducer: PUBLIC --ENTRY-- PROC [n: Node] RETURNS [producer: Command] = {
Inner: INTERNAL PROC [n: Node] = {
producer ← IF n.producer # NIL AND n.producer.c # leaf THEN n.producer.c ELSE NIL;
};
DoIn[n, Inner];
};
GetLeaf: PUBLIC PROC [name: ROPE, class: NodeClass] RETURNS [node: Node] = {
node ← GetNode[name, class];
VolunteerLeaf[node];
};
VolunteerLeaf: --ENTRY-- PROC [n: Node] = {
DoIn[n, InnerVolunteerLeaf];
};
InnerVolunteerLeaf: --INTERNAL-- PROC [n: Node] = {
IF n.producer = NIL THEN n.producer ← NEW [EdgeRep ← [
c: leaf,
n: n,
cNext: NIL, cPrev: NIL, nNext: NIL, nPrev: NIL,
optional: FALSE
]]
ELSE IF n.producer.c = NIL THEN ERROR;
};
EnsureNodeProduced: --INTERNAL-- PROC [n: Node] =
BEGIN
n2: Node;
IF n.producer # NIL THEN RETURN;
n2 ← TryToProduce[n.name, n.class];
IF n # n2 THEN Warning[IO.PutFR["Disagreement on cannonical name for %g or %g", IO.rope[n.name], IO.rope[n2.name]]];
InnerVolunteerLeaf[n];
END;
FindNode: PUBLIC PROC [someName: ROPE, class: NodeClass] RETURNS [node: Node] = {
node ← TryToProduce[someName, class];
VolunteerLeaf[node];
};
RetryToProduce: PUBLIC --ENTRY-- PROC [n: Node] = {
Inner: --INTERNAL-- PROC [n: Node] = {
n2: Node;
IF n.producer # NIL AND n.producer.c # leaf THEN RETURN;
IF n.producer # NIL AND n.producer.c = leaf THEN {
e: Edge = n.producer;
IF e.cNext # NIL OR e.cPrev # NIL THEN ERROR;
IF e.nNext # NIL OR e.nPrev # NIL THEN ERROR;
n.producer.c ← NIL;
n.producer ← NIL;
};
n2 ← TryToProduce[n.name, n.class];
IF n # n2 THEN Warning[IO.PutFR["Disagreement on cannonical name for %g or %g", IO.rope[n.name], IO.rope[n2.name]]];
InnerVolunteerLeaf[n];
};
DoIn[n, Inner];
};
Found: ERROR = CODE;
TryToProduce: PROC [resultName: ROPE, class: NodeClass] RETURNS [sought: Node] =
BEGIN
PerFinder: PROC [f: Finder] = {
found: BOOLEAN;
makes: NodeList;
from, cmdFrom: From;
cmd: ROPE;
class: CommandClass;
foundData: REF ANY;
CedarProcess.CheckAbort[];
[found, sought, makes, from, cmdFrom, cmd, class, foundData] ← f.finderProc[resultName: resultName, finderData: f.finderData];
IF found THEN {
c: Command;
first: BOOLEANTRUE;
soughtIn: BOOLFALSE;
already: Command ← NIL;
FOR ml: NodeList ← makes, ml.rest WHILE ml # NIL DO
this: Command ← IF ml.first.producer = NIL THEN NIL ELSE ml.first.producer.c;
soughtIn ← soughtIn OR (sought = ml.first);
IF first
THEN {already ← this; first ← FALSE}
ELSE {IF this # already
THEN Warning[IO.PutFR[
"Command %g doesn't precisely cover command %g (e.g., at %g)",
IO.refAny[cmd],
IO.refAny[IF already # NIL THEN already.cmd ELSE NIL],
IO.rope[ml.first.name]]]};
ENDLOOP;
IF soughtIn
THEN {
IF already # NIL THEN ERROR Found;
c ← NEW [CommandRep ← [cmd: cmd, class: class, foundData: foundData, down: NewMonitorLock[]]];
FOR nl: NodeList ← makes, nl.rest WHILE nl # NIL DO
n: Node ← nl.first;
peh: EdgeRingHead ← emptyHead;
IF n.producer # NIL THEN ERROR;
[c.makes, peh] ← Link[c, c.makes, n, peh, FALSE, TRUE];
n.producer ← peh.first;
ENDLOOP;
AddConsumption[c, cmdFrom.mustHave, cmd, FALSE];
AddConsumption[c, cmdFrom.optional, cmd, TRUE];
AddConsumption[c, from.mustHave, data, FALSE];
AddConsumption[c, from.optional, data, TRUE];
ERROR Found
}
ELSE {
Warning[Rope.Cat["Finder (", f.name, ") blew it"]];
sought ← NIL;
};
}
ELSE sought ← NIL;
};
sought ← NIL;
EnumerateFinders[PerFinder !Found => CONTINUE];
IF sought=NIL THEN sought ← GetNode[resultName, class];
END;
NodeWork: PUBLIC --INTERNAL-- PROC [nWork: NWork] RETURNS [Subgoal] = {
OPEN nWork;
sg: Subgoal;
isLeaf: BOOL;
IF debugging THEN Log[depth, "EWn -> %g", IO.rope[goal.name]];
IF job.boundaryKnown AND NOT NodeInTable[goal, job.modifiable] THEN isLeaf ← TRUE
ELSE {
EnsureNodeProduced[goal];
isLeaf ← goal.producer = NIL OR goal.producer.c = leaf;
};
IF isLeaf THEN {PostAmble[nWork, "leaf out"]; RETURN[NIL]};
IF NOT ShouldRemakeNode[goal, job.do] THEN {PostAmble[nWork, "not suspect"]; RETURN[NIL]};
{
c: Command = goal.producer.c;
cWork: CWork ← NEW [WorkRec[cmd] ← [
job: job,
depth: depth,
subject: cmd[c, goal]
]];
sg ← NEW [SubgoalRep ← [
job: job,
toDo: NewWorkTable[],
parent: nWork,
AllDone: FinishNodeWork
]];
InsertWork[sg.toDo, cWork];
RETURN[sg];
};
};
FinishNodeWork: PROC [parent: WorkRef] RETURNS [Subgoal] = {
nWork: NWork = NARROW[parent];
{OPEN nWork;
PostAmble[nWork, "end"];
RETURN [NIL];
};
};
PostAmble: PROC [nWork: NWork, msg: ROPE] = {
OPEN nWork;
IF debugging THEN Log[depth, "EWn <- %g %g", IO.rope[goal.name], IO.rope[msg]];
};
END.