RoseDeps.Mesa
Last Edited by: Spreitzer, September 12, 1984 3:59: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: ROPE ← NIL];
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.STREAM ← NIL;
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.