<<>> <> <> <> <> <<>> 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 <> <<(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: INT _ FIRST[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: 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.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.