MakeDoBasic3Impl.Mesa
Copyright Ó 1989 by Xerox Corporation. All rights reserved.
Bill Jackson (bj) January 16, 1989 1:36:32 pm PST
Last tweaked by Mike Spreitzer on October 5, 1992 11:53 am PDT
DIRECTORY
CedarProcess USING [CheckAbort],
Commander USING [],
IO USING [PutFR],
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};
GetInfo: PUBLIC --ENTRY-- PROC [n: Node] RETURNS [created: Time ← notExistTime, length: INTFIRST[INT]] = {
GCWork: --INTERNAL-- PROC = {created ← n.created; length ← n.length};
DoIn[GCWork];
RETURN};
GetCreated: PUBLIC --ENTRY-- PROC [n: Node] RETURNS [t: Time ← notExistTime] = {
GCWork: --INTERNAL-- PROC = {t ← n.created};
DoIn[GCWork];
RETURN};
InnerGetInfo: PUBLIC --INTERNAL-- PROC [n: Node] RETURNS [created: Time, length: INT]
= {RETURN [n.created, n.length]};
InnerGetCreated: PUBLIC --INTERNAL-- PROC [n: Node] RETURNS [t: Time] = {
t ← n.created};
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: BOOLFALSE]] = StatelessEnumerateRefTable;
StatelessEnumerateRefTable: PUBLIC PROC [table: RefTable, EachNode: PROC [REF ANY] RETURNS [stop: BOOLFALSE]] = {
PassPair: PROC [key, val: REF ANY] RETURNS [stop: BOOLFALSE]
~ {RETURN EachNode[key]};
[] ← table.Pairs[PassPair];
RETURN};
EnumerateNodes: PUBLIC PROC [table: RefTable, EachNode: PROC [Node]] = {
PassPair: PROC [key, val: REF ANY] RETURNS [stop: BOOLFALSE] ~ {
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: BOOLFALSE] --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: BOOLFALSE] --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: BOOLFALSE] = {
a: Action ← NIL;
subDo: BOOLFALSE;
sourceMissing, sourcePresent, sourceNonCurrent, sourceBroken: BOOLFALSE;
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: BOOLFALSE;
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.PutFR["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.