<> <> <> <> <<>> <<>> DIRECTORY Basics, RedBlackTree, Schedule; ScheduleImpl: CEDAR PROGRAM IMPORTS RedBlackTree EXPORTS Schedule ~ BEGIN OPEN Schedule; <> <<>> CreateHistory: PUBLIC PROC [t: ps, v: REAL] RETURNS [newHistory: History] ~ { newHistory _ LIST[[t, v]]; }; KillHistory: PUBLIC PROC [history: History] ~ { h: History; UNTIL history=NIL DO h _ history; history _ history.rest; h.rest _ NIL; ENDLOOP; }; AddToHistory: PUBLIC PROC [oldHistory: History, t: ps, v: REAL] RETURNS [newHistory: History] ~ { last, prev: History; historyPt: HistoryPt _ [t, v]; IF oldHistory=NIL THEN RETURN[LIST[historyPt]]; newHistory _ oldHistory; FOR ih: History _ oldHistory, ih.rest UNTIL ih=NIL DO IF ih.first.t>=t THEN { --if t occurs before the end of the current history then ih.first _ historyPt; -- change the present and delete the "old future". ih.rest _ NIL; IF prev#NIL THEN IF prev.first.v=last.first.v AND prev.first.v=v THEN prev.rest _ last.rest; RETURN; }; prev _ last; last _ ih; ENDLOOP; last.rest _ LIST[historyPt]; IF prev#NIL THEN IF prev.first.v=last.first.v AND prev.first.v=v THEN prev.rest _ last.rest; }; ForgetBeginings: PUBLIC PROC [oldHistory: History, t: ps] RETURNS [newHistory: History] ~ { newHistory _ oldHistory; FOR ih: History _ oldHistory, ih.rest UNTIL ih.rest=NIL DO IF ih.rest.first.t>t THEN { newHistory _ ih; RETURN; }; ENDLOOP; }; <> <> <> <> <t THEN {>> <> <> <> <> <<};>> <> <<};>> <<>> FirstTimeOfHistory: PUBLIC PROC [history: History] RETURNS [t: ps] ~ { t _ history.first.t }; NextTimeOfHistory: PUBLIC PROC [history: History, t: ps] RETURNS [tnext: ps _ -1e30] ~ { FOR ih: History _ history, ih.rest UNTIL ih=NIL DO IF ih.first.t>t THEN RETURN[ih.first.t]; ENDLOOP; }; LastTimeOfHistory: PUBLIC PROC [history: History] RETURNS [t: ps] ~ { FOR ih: History _ history, ih.rest UNTIL ih.rest=NIL DO REPEAT FINISHED => t _ ih.first.t; ENDLOOP; }; LastValueOfHistory: PUBLIC PROC [history: History] RETURNS [v: REAL] ~ { FOR ih: History _ history, ih.rest UNTIL ih.rest=NIL DO REPEAT FINISHED => v _ ih.first.v; ENDLOOP; }; VFromHistory: PUBLIC PROC [history: History, t: ps] RETURNS [v: REAL] ~ { t0: ps; v0: REAL; IF t < history.first.t THEN ERROR; -- Why should you return to the past ? IF t=history.first.t THEN RETURN[history.first.v]; FOR ih: History _ history, ih.rest UNTIL ih=NIL DO IF t<=ih.first.t THEN { v _ v0 + (ih.first.v - v0)*(t-t0) /(ih.first.t - t0); RETURN; }; v0 _ ih.first.v; t0 _ ih.first.t; REPEAT FINISHED => v _ v0; ENDLOOP; }; EnumerateHistory: PUBLIC PROC [history: History, from, to: ps, action: HistoryProc] RETURNS [invalidEnumeration: BOOL _ FALSE] ~ { quit: BOOLEAN _ FALSE; FOR ih: History _ history, ih.rest UNTIL ih=NIL OR quit OR ih.first.t>to DO IF ih.first.t>=from THEN IF action[ih.first.t, ih.first.v] THEN RETURN[TRUE]; ENDLOOP; }; Schedule: PUBLIC PROC [hList: LIST OF History] RETURNS [lt: LIST OF ps] ~ { t: ps; h: LIST OF History; endlt: LIST OF ps; finished: BOOLEAN _ FALSE; endlt _ lt _ LIST[-1e30]; UNTIL finished DO finished _ TRUE; t _ 1e30; FOR ih: LIST OF History _ hList, ih.rest UNTIL ih=NIL DO IF ih.first#NIL THEN { finished _ FALSE; IF t>=ih.first.first.t THEN { t _ ih.first.first.t; h _ ih; }; }; ENDLOOP; IF ~finished THEN { IF endlt.first#t THEN { endlt.rest _ LIST[t]; endlt _ endlt.rest; }; h.first _ h.first.rest; }; ENDLOOP; lt _ lt.rest; }; <> CreateAgenda: PUBLIC PROC [execute: ExecuteProc, data: REF ANY] RETURNS [newAgenda: Agenda] ~ { newAgenda _ NEW[AgendaRec _ [ execute: execute, table: RedBlackTree.Create[GetKey, Compare], data: data ]]; }; KillAgenda: PUBLIC PROC [agenda: Agenda] ~ { RedBlackTree.DestroyTable[agenda.table]; agenda.data _ NIL; }; InsertInAgenda: PUBLIC PROC [agenda: Agenda, ref: REF ANY, t: ps] ~ { event: Event _ [t, ref]; list: LIST OF Event _ LIST[event]; n: RedBlackTree.Node _ RedBlackTree.LookupNode[agenda.table, list]; IF n=NIL THEN RedBlackTree.Insert[agenda.table, list, list] ELSE { list.rest _ NARROW[n.data]; n.data _ list; }; agenda.nbOfEvents _ agenda.nbOfEvents+1; }; ExecuteAgenda: PUBLIC PROC [agenda: Agenda] RETURNS [lastTime: ps] ~ { WHILE RedBlackTree.Size[agenda.table]#0 DO list: LIST OF Event _ NARROW[RedBlackTree.LookupSmallest[agenda.table]]; [] _ RedBlackTree.Delete[agenda.table, list]; lastTime _ list.first.t; WHILE list#NIL DO agenda.execute[list.first.ref, list.first.t, agenda.data]; agenda.nbOfEvents _ agenda.nbOfEvents-1; list _ list.rest; ENDLOOP; ENDLOOP; IF agenda.nbOfEvents#0 THEN ERROR; }; GetKey: PROC [data: RedBlackTree.UserData] RETURNS [RedBlackTree.Key] ~ { <> RETURN[data] }; Compare: PROC [k: RedBlackTree.Key, data: RedBlackTree.UserData] RETURNS [Basics.Comparison] ~ { <> t1: ps _ NARROW[k, LIST OF Event].first.t; t2: ps _ NARROW[data, LIST OF Event].first.t; RETURN[SELECT TRUE FROM t1>t2 => greater, t1 less, ENDCASE => equal]; }; END.