RoseDeps.Mesa
Last Edited by: Spreitzer, September 12, 1984 3:27:32 pm PDT
DIRECTORY BasicTime, FS, IO, MakeDo, Rope;
RoseDeps: CEDAR PROGRAM
IMPORTS BasicTime, FS, IO, MakeDo, Rope =
BEGIN
ROPE: TYPE = Rope.ROPE;
RoseCommand: TYPE = REF RoseCommandRep; RoseCommandRep: TYPE = RECORD [
resultBase, resultShort: ROPE,
roseNode, transNode: MakeDo.Node,
earliestResultNode, lateIngredientNode: MakeDo.Node ← NIL,
earliestResultTime, lateIngredientTime: BasicTime.GMT ← BasicTime.nullGMT,
cmd: ROPENIL];
rosemaryClass: MakeDo.CommandClass ← NEW [MakeDo.CommandClassRep ← [
NotCurrent: RoseNotCurrent,
Rederive: RederiveRose,
UpdateTime: MakeDo.FileTime,
Explain: ExplainRose
]];
RoseFind: PROC [resultName: ROPE, finderData: REF ANY] RETURNS [found: BOOLEAN, sought: MakeDo.Node, makes, from, why: MakeDo.NodeList, cmd: ROPE, class: MakeDo.CommandClass, foundData: REF ANY] --MakeDo.FinderProc-- =
BEGIN
resultCP: FS.ComponentPositions;
resultFull, resultBase, resultExt, roseName: ROPE;
roseFound: BOOLEAN;
roseNode: MakeDo.Node;
rc: RoseCommand;
[resultFull, resultCP, ] ← FS.ExpandName[resultName];
resultExt ← resultFull.Substr[start: resultCP.ext.start, len: resultCP.ext.length];
roseFound ← resultExt.Equal["RoseSymbols", FALSE]
OR resultExt.Equal["roseDeps", FALSE]
OR resultExt.Equal["RoseLoad", FALSE];
found ← roseFound OR resultExt.Equal["Mesa", FALSE];
IF NOT found THEN RETURN;
resultBase ← resultFull.Substr[start: 0, len: resultCP.ext.start-1];
why ← LIST[roseNode ← MakeDo.GetNode[roseName ← resultBase.Cat[".Rose"]]];
found ← MakeDo.Exists[roseNode, MakeDo.FileTime];
IF NOT found THEN RETURN;
foundData ← rc ← NEW [RoseCommandRep ← [
resultBase: resultBase,
resultShort: resultFull.Substr[start:resultCP.base.start, len:resultCP.base.length],
roseNode: roseNode,
transNode: MakeDo.GetNode["RoseTranslator.Version"]
]];
makes ← LIST[
MakeDo.GetNode[resultBase.Cat[".RoseDeps"]],
MakeDo.GetNode[resultBase.Cat[".RoseSymbols"]],
MakeDo.GetNode[resultBase.Cat[".RoseLoad"]],
MakeDo.GetNode[resultBase.Cat[".Mesa"]]];
sought ←
IF resultExt.Equal["RoseSymbols", FALSE] THEN makes.first ELSE
IF resultExt.Equal["RoseLoad", FALSE] THEN makes.rest.first ELSE
IF resultExt.Equal["Mesa", FALSE] THEN makes.rest.rest.first ELSE
ERROR;
from ← DeriveFrom[rc];
rc.cmd ← cmd ← IO.PutFR["RoseTranslate %g", IO.rope[rc.resultShort]];
class ← rosemaryClass;
END;
DeriveFrom: PROC [rc: RoseCommand] RETURNS [from: MakeDo.NodeList] =
BEGIN
NoteModuleRef: PROC [moduleName: ROPE, type: ModuleReferenceType] = {
SELECT type FROM
Directory, Imports, Open => NULL;
Library => from ← CONS[
MakeDo.GetNode[FS.ExpandName[moduleName.Cat[".RoseSymbols"]].fullFName],
from];
ENDCASE => ERROR};
from ← LIST[rc.roseNode, rc.transNode];
[] ← EnumerateModuleReferences[fromName: rc.roseNode.Name[], to: NoteModuleRef];
END;
IDProc: IO.BreakProc = {RETURN [SELECT char FROM
IN [IO.NUL .. IO.SP] => sepr,
'; => break,
ENDCASE => other]};
RederiveRose: PROC [c: MakeDo.Command] RETURNS [from: MakeDo.NodeList, cmd: ROPE] --MakeDo.RederiveProc-- = {
rc: RoseCommand ← NARROW[c.PublicParts[].foundData];
from ← DeriveFrom[rc];
cmd ← rc.cmd};
RoseNotCurrent: PROC [c: MakeDo.Command] RETURNS [notCurrent: BOOLEAN] --MakeDo.NotCurrentProc-- =
BEGIN
fd: REF ANY;
makes, from: MakeDo.NodeList;
rc: RoseCommand;
[foundData: fd, makes: makes, from: from] ← c.PublicParts[];
rc ← NARROW[fd];
rc.earliestResultTime ← BasicTime.latestGMT;
rc.earliestResultNode ← rc.lateIngredientNode ← NIL;
FOR ml: MakeDo.NodeList ← makes, ml.rest WHILE ml # NIL DO
thisTime: BasicTime.GMT ← MakeDo.Latest[ml.first];
IF NOT MakeDo.Needed[ml.first] THEN LOOP;
IF thisTime # BasicTime.nullGMT AND thisTime.Period[rc.earliestResultTime] > 0
THEN {rc.earliestResultTime ← thisTime; rc.earliestResultNode ← ml.first};
ENDLOOP;
IF rc.earliestResultNode = NIL THEN RETURN [FALSE];
FOR fl: MakeDo.NodeList ← from, fl.rest WHILE fl # NIL DO
fromTime: BasicTime.GMT ← MakeDo.Latest[fl.first];
IF (fromTime # BasicTime.nullGMT) AND (fromTime.Period[rc.earliestResultTime] < 0) THEN {
rc.lateIngredientTime ← fromTime;
rc.lateIngredientNode ← fl.first;
RETURN [TRUE]};
ENDLOOP;
notCurrent ← FALSE;
END;
ExplainRose: PROC [c: MakeDo.Command, to: IO.STREAM] --MakeDo.ExplainProc-- =
BEGIN
rc: RoseCommand ← NARROW[c.PublicParts[].foundData];
IF rc.earliestResultNode = NIL THEN to.PutRope[" no result files existed yet.\n"]
ELSE IF rc.lateIngredientNode = NIL THEN to.PutRope[" all result files were dated later than any ingredient file.\n"]
ELSE to.PutF[" result %g of %g predated ingredient %g of %g.\n", IO.rope[rc.earliestResultNode.Name[]], IO.time[rc.earliestResultTime], IO.rope[rc.lateIngredientNode.Name[]], IO.time[rc.lateIngredientTime]];
END;
ModuleReferenceType: TYPE = {Directory, Open, Imports, Library};
MRKeywords: ARRAY ModuleReferenceType OF ROPE = ["Directory", "Open", "Imports", "Library"];
GotoSyntaxError: ERROR = CODE;
Break: IO.BreakProc = {RETURN [SELECT char FROM
IN ['a .. 'z], IN ['A .. 'Z], IN ['0 .. '9] => other,
IO.SP, IO.CR, IO.TAB, IO.LF, IO.FF => sepr,
ENDCASE => break]};
EnumerateModuleReferences: PROC [fromName: ROPE, to: PROC [moduleName: ROPE, type: ModuleReferenceType]] RETURNS [exists: BOOLEAN] =
BEGIN
NextToken: PROC RETURNS [ROPE] =
{RETURN [from.GetTokenRope[Break].token]};
ModuleReferenceKey: PROC [r: ROPE] RETURNS [is: BOOL, mrt: ModuleReferenceType] = {
FOR mrt IN ModuleReferenceType DO
IF MRKeywords[mrt].Equal[s2: r, case: FALSE] THEN RETURN [TRUE, mrt];
ENDLOOP;
is ← FALSE};
ParseRefs: PROC = {
next: ROPE;
DO
still: BOOLEAN;
mrt: ModuleReferenceType;
[still, mrt] ← ModuleReferenceKey[next ← NextToken[]];
IF NOT still THEN EXIT;
next ← EatModuleReferenceBody[mrt];
IF next.Length[] = 0 AND from.EndOf[] THEN EXIT --end of file--;
IF NOT next.Equal[";"] THEN ERROR GotoSyntaxError;
ENDLOOP;
};
EatModuleReferenceBody: PROC [mrt: ModuleReferenceType] RETURNS [next: ROPE] = {
DO
next ← NextToken[];
to[next, mrt];
next ← NextToken[];
IF next.Equal[";"] THEN RETURN;
IF NOT next.Equal[","] THEN ERROR GotoSyntaxError;
ENDLOOP};
from: IO.STREAMNIL;
from ← FS.StreamOpen[fileName: fromName, accessOptions: $read !FS.Error => {from ← NIL; CONTINUE}];
IF NOT (exists ← from # NIL) THEN RETURN;
[] ← from.GetIndex[];
ParseRefs[!GotoSyntaxError =>
BEGIN
SIGNAL MakeDo.Warning[IO.PutFR["Syntax error in %g; parse aborted at %g", IO.rope[fromName], IO.int[from.GetIndex[]]]];
CONTINUE
END];
from.Close[];
END;
MakeDo.AddFinder[[RoseFind], back];
END.