MakeDoBasic3Impl.Mesa
Copyright Ó 1989, 1991 by Xerox Corporation. All rights reserved.
Bill Jackson (bj) January 16, 1989 1:36:32 pm PST
Last tweaked by Mike Spreitzer on October 6, 1992 11:17 am PDT
Michael Plass, November 27, 1991 10:30 am PST
DIRECTORY
CedarProcess USING [CheckAbort],
Commander USING [],
IO,
MakeDo,
MakeDoBasics,
MakeDoPrivate,
RefTab,
Rope USING [];
MakeDoBasic3Impl: CEDAR MONITOR
IMPORTS CedarProcess, IO, MakeDo, MakeDoBasics, MakeDoPrivate, RefTab
EXPORTS MakeDo, MakeDoBasics, MakeDoPrivate
Extension of MakeDoBasicImpl.mesa
(it does not fit into a single module)
~ BEGIN OPEN MakeDo, MakeDoPrivate, MakeDoBasics;
RefTable: TYPE = MakeDo.RefTable;
NodeRep: PUBLIC TYPE = MakeDoPrivate.NodeRep;
ActionRep: PUBLIC TYPE = MakeDoPrivate.ActionRep;
NodeClassRep: PUBLIC TYPE = MakeDoPrivate.NodeClassRep;
Abandon: ERROR = CODE;
GetForkParms: PUBLIC --ENTRY-- PROC RETURNS [forkParms: ForkParms] = {
SPAWork: --INTERNAL-- PROC = {
forkParms ¬ InnerGetForkParms[];
RETURN};
DoIn[SPAWork];
RETURN};
GetCreated: PUBLIC --ENTRY-- PROC [n: Node] RETURNS [t: Time ¬ notExistTime] = {
GCWork: --INTERNAL-- PROC = {t ¬ n.created};
DoIn[GCWork];
RETURN};
GetInfo: PUBLIC --ENTRY-- PROC [n: Node] RETURNS [created: Time ¬ notExistTime, length: INT ¬ INT.FIRST] = {
GCWork: --INTERNAL-- PROC = {created ¬ n.created; length ¬ n.length};
DoIn[GCWork];
RETURN};
InnerGetCreated: PUBLIC --INTERNAL-- PROC [n: Node] RETURNS [t: Time] = {
t ¬ n.created};
InnerGetInfo: PUBLIC --INTERNAL-- PROC [n: Node] RETURNS [created: Time, length: INT]
= {created ¬ n.created; length ¬ n.length};
InnerLeaf: PUBLIC --INTERNAL-- PROC [n: Node] RETURNS [isLeaf: BOOL] = {
SELECT n.modifiability FROM
no => RETURN [TRUE];
yes, guess => NULL;
uninitialized => ERROR;
ENDCASE => ERROR;
isLeaf ¬ n.producer = NIL OR n.producer.a = leaf;
};
StartTime: PUBLIC PROC [n: Node] = {
[n.created, n.length] ¬ n.class.GetInfo[n]};
ScanRefTable: PUBLIC PROC [table: RefTable, EachNode: PROC [REF ANY] RETURNS [stop: BOOL ¬ FALSE]] = StatelessEnumerateRefTable;
StatelessEnumerateRefTable: PUBLIC PROC [table: RefTable, EachNode: PROC [REF ANY] RETURNS [stop: BOOL ¬ FALSE]] = {
PassPair: PROC [key, val: REF ANY] RETURNS [stop: BOOL ¬ FALSE]
~ {RETURN EachNode[key]};
[] ¬ table.Pairs[PassPair];
RETURN};
EnumerateNodes: PUBLIC PROC [table: RefTable, EachNode: PROC [Node]] = {
PassPair: PROC [key, val: REF ANY] RETURNS [stop: BOOL ¬ FALSE] ~ {
n: Node ~ NARROW[key];
EachNode[n];
RETURN [FALSE]};
IF table.Pairs[PassPair] THEN ERROR;
RETURN};
GetActions: PUBLIC PROC [goals: RefTable, modifiabilitySpec: ModifiabilitySpec, report: ReportSpec, neededLeaves, optionalLeaves, determiningLeaves, brokenGoals: RefTable ¬ NIL] RETURNS [actions: ActionList] = {
nodesSeen  : RefTable = MakeRefTable[];
stackedActions: RefTable = MakeRefTable[];
actionsSeen: RefTable = MakeRefTable[];
WorkOnGoal: PROC [data: REF ANY] RETURNS [stop: BOOL ¬ FALSE] --RedBlackTree.EachNode-- = {
goal: Node = NARROW[data];
WOG: --INTERNAL-- PROC = {
InnerSetModifiability[goal, goals, modifiabilitySpec];
[] ¬ WorkOn[goal, needed];
};
DoIn[WOG];
};
FinishGoal: PROC [data: REF ANY] RETURNS [stop: BOOL ¬ FALSE] --RedBlackTree.EachNode-- = {
goal: Node = NARROW[data];
FG: --INTERNAL-- PROC ~ {IF goal.current#true OR goal.broken THEN EnsureRefInTable[goal, brokenGoals]};
DoIn[FG];
};
WorkOn: --INTERNAL-- PROC [subj: Node, kind: {needed, optional, determiner}] RETURNS [do: BOOL ¬ FALSE] = {
a: Action ¬ NIL;
subDo: BOOL ¬ FALSE;
sourceMissing, sourcePresent, sourceNonCurrent, sourceBroken: BOOL ¬ FALSE;
missedList: NodeList ¬ NIL;
Finish: --INTERNAL-- PROC [current: ExpensiveBool] = {
SetCurrency[subj, current];
[] ¬ nodesSeen.Insert[subj, $T];
do ¬ do OR subDo;
IF a # NIL THEN {
[] ¬ stackedActions.Delete[a];
IF
(SELECT report FROM
none => FALSE,
all => TRUE,
toBeDone => do,
ENDCASE => ERROR) AND
actionsSeen.Insert[a, $T]
THEN actions ¬ CONS[a, actions];
};
};
CheckSource: --INTERNAL-- PROC [n: Node, which: ActionDep, optional: BOOL] = {
CedarProcess.CheckAbort[];
InnerSetModifiability[n, goals, modifiabilitySpec];
subDo ¬ WorkOn[n, IF which=cmd THEN determiner ELSE IF optional THEN optional ELSE needed] OR subDo;
IF n.created # notExistTime THEN sourcePresent ¬ TRUE
ELSE IF NOT optional THEN {
sourceMissing ¬ TRUE;
IF subj.modifiability=yes THEN missedList ¬ CONS[n, missedList];
};
SELECT n.current FROM
true => {IF n.broken THEN SetBroken[subj, sourceBroken ¬ TRUE]};
false => sourceNonCurrent ¬ TRUE;
notComputed => ERROR;
ENDCASE => ERROR;
};
detTrue, detFalse: BOOL ¬ FALSE;
IF subj.producer = NIL THEN InnerGetProduced[subj];
IF InnerLeaf[subj] THEN {
table: RefTable ~ SELECT kind FROM
needed => neededLeaves,
optional => optionalLeaves,
determiner => determiningLeaves,
ENDCASE => ERROR;
IF table#NIL THEN [] ¬ table.Insert[subj, $T];
IF (NOT nodesSeen.Fetch[subj].found) OR subj.current=notComputed THEN Finish[true];
RETURN};
a ¬ subj.producer.a;
IF nodesSeen.Fetch[subj].found THEN {
IF subj.current#notComputed THEN {
do ¬ actionsSeen.Fetch[a].found;
RETURN;
}
ELSE a ¬ a;
};
IF NOT stackedActions.Insert[a, $T] THEN {
Warning[IO.PutFR1["Found cycle containing %g --- you lose", [rope[a.cmd]]]];
Abandon[]};
SetBroken[subj, subj.modifiability=yes AND subj.created=notExistTime];
InnerEnumerateSources[a, cmd, CheckSource];
IF sourceNonCurrent THEN detFalse ¬ TRUE ELSE IF sourceBroken THEN detTrue ¬ TRUE;
SELECT a.derivedFromCurrentDeterminers FROM
TRUE => NULL;
FALSE => {
InnerRederive[a];
a.derivedFromCurrentDeterminers ¬ TRUE;
};
ENDCASE => ERROR;
sourceNonCurrent ¬ sourceBroken ¬ sourceMissing ¬ FALSE;
missedList ¬ NIL;
InnerEnumerateSources[a, data, CheckSource];
IF detFalse THEN {Finish[false]; RETURN};
IF detTrue THEN {Finish[true]; RETURN};
IF sourceNonCurrent THEN {Finish[false]; RETURN};
IF sourceBroken THEN {Finish[true]; RETURN};
IF sourceMissing AND subj.modifiability=yes THEN {el: ROPE; ec: CARDINAL;
[el, ec] ¬ EnglishList[missedList];
Warning[IO.PutFR["Can't %g because %g %g exist", [rope[a.cmd]], [rope[el]], [rope[IF ec=1 THEN "doesn't" ELSE "don't"]] ]];
SetBroken[subj, TRUE]; Finish[true]; RETURN};
IF NOT subj.consistencyAsked THEN {
[subj.consistent, subj.consistencyReason] ¬ a.class.CheckConsistency[a, subj];
subj.consistencyAsked ¬ TRUE;
};
IF subj.consistent THEN {InnerUnknowFails[a]; Finish[true]; RETURN};
IF sourceMissing THEN {el: ROPE; ec: CARDINAL;
[el, ec] ¬ EnglishList[missedList];
Warning[IO.PutFR["Can't %g because %g %g exist", [rope[a.cmd]], [rope[el]], [rope[IF ec=1 THEN "doesn't" ELSE "don't"]] ]];
SetBroken[subj, TRUE]; Finish[true]; RETURN};
IF a.fails = true THEN {Finish[true]; RETURN};
do ¬ TRUE;
Finish[false];
};
actions ¬ NIL;
{StatelessEnumerateRefTable[goals, WorkOnGoal !Abandon => GOTO Dun];
IF brokenGoals#NIL THEN StatelessEnumerateRefTable[goals, FinishGoal];
EXITS Dun => actions ¬ actions};
nodesSeen.Erase[];
actionsSeen.Erase[];
stackedActions.Erase[];
};
END.