RoseDeps.Mesa
Last Edited by: Spreitzer, September 23, 1985 12:01:23 pm PDT
DIRECTORY BasicTime, FS, IO, IOClasses, MakeDo, Rope, RoseTranslateInsides;
RoseDeps: CEDAR PROGRAM
IMPORTS BasicTime, FS, IO, IOClasses, MakeDo, Rope, RoseTranslateInsides =
BEGIN
ROPE: TYPE = Rope.ROPE;
RoseAction: TYPE = REF RoseActionRep; RoseActionRep: TYPE = RECORD [
resultBase, resultShort: ROPE,
roseNode, transNode: MakeDo.Node,
cmd: ROPENIL];
rosemaryClass: MakeDo.ActionClass ← NEW [MakeDo.ActionClassRep ← [
CheckConsistency: CheckRoseConsistency,
Rederive: RederiveRose
]];
transName: ROPE = "Rosemary Translator";
transClass: MakeDo.NodeClass ← MakeDo.DeclareNodeClass[
name: transName,
CanonizeName: CanonizeTranslatorName,
GetTime: GetTranslatorTime
];
implTail: ROPE = "Impl";
implTailLength: INT = implTail.Length[];
CanonizeTranslatorName: PROC [raw: ROPE] RETURNS [cooked: ROPE] =
{cooked ← raw};
GetTranslatorTime: PROC [n: MakeDo.Node] RETURNS [created: MakeDo.Time] = {
IF NOT n.PublicPartsOfNode[].name.Equal[transName] THEN ERROR;
created ← RoseTranslateInsides.commandDate;
};
RoseFind: PROC [resultName: ROPE, finderData: REF ANY] RETURNS [found: BOOLEAN, sought: MakeDo.Node, makes, cmdFrom: MakeDo.NodeList, from: MakeDo.From, cmd: ROPE, class: MakeDo.ActionClass, foundData: REF ANY] --MakeDo.FinderProc-- =
BEGIN
resultCP: FS.ComponentPositions;
resultFull, resultBase, resultShort, resultExt, roseName: ROPE;
roseFound, hasImpl: BOOLEAN;
roseNode: MakeDo.Node;
rc: RoseAction;
shortLength, shortTrim: INT ← 0;
found ← TRUE;
[resultFull, resultCP, ] ← FS.ExpandName[resultName !FS.Error => {found ← FALSE; CONTINUE}];
IF NOT found THEN RETURN;
resultExt ← resultFull.Substr[start: resultCP.ext.start, len: resultCP.ext.length];
roseFound ← resultExt.Equal["RoseSymbols", FALSE]
OR resultExt.Equal["partsAssertions", 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.base.start + resultCP.base.length];
resultShort ← resultFull.Substr[start: resultCP.base.start, len: resultCP.base.length];
shortLength ← resultShort.Length[];
IF (hasImpl ← (shortLength > 4 AND resultShort.Substr[shortLength-4].Equal[implTail, FALSE])) THEN {
shortTrim ← -implTailLength;
resultBase ← resultBase.Substr[len: resultBase.Length[]+shortTrim];
resultShort ← resultShort.Substr[len: shortLength+shortTrim];
shortLength ← resultShort.Length[];
};
roseName ← resultBase.Cat[".Rose"];
roseNode ← MakeDo.GetNode[roseName, MakeDo.fileClass];
cmdFrom ← LIST[roseNode];
found ← MakeDo.InnerExists[roseNode];
IF NOT found THEN RETURN;
foundData ← rc ← NEW [RoseActionRep ← [
resultBase: resultBase,
resultShort: resultShort,
roseNode: roseNode,
transNode: MakeDo.GetNode[transName, transClass]
]];
makes ← LIST[
MakeDo.GetNode[resultBase.Cat[".RoseSymbols"], MakeDo.fileClass],
MakeDo.GetNode[resultBase.Cat[".partsAssertions"], MakeDo.fileClass],
MakeDo.GetNode[resultBase.Cat[".RoseLoad"], MakeDo.fileClass],
MakeDo.GetNode[resultBase.Cat["Impl.Mesa"], MakeDo.fileClass],
MakeDo.GetNode[resultBase.Cat[".Mesa"], MakeDo.fileClass]];
sought ←
IF resultExt.Equal["RoseSymbols", FALSE] THEN makes.first ELSE
IF resultExt.Equal["partsAssertions", FALSE] THEN makes.rest.first ELSE
IF resultExt.Equal["RoseLoad", FALSE] THEN makes.rest.rest.first ELSE
IF resultExt.Equal["Mesa", FALSE] THEN
IF hasImpl THEN makes.rest.rest.rest.first ELSE makes.rest.rest.rest.rest.first
ELSE
ERROR;
from ← DeriveFrom[rc];
rc.cmd ← cmd ← IO.PutFR["%g %g", [rope[RoseTranslateInsides.translateCommandName]], IO.rope[rc.resultShort]];
class ← rosemaryClass;
END;
DeriveFrom: PROC [rc: RoseAction] RETURNS [from: MakeDo.From] =
BEGIN
NoteModuleRef: PROC [moduleName: ROPE, type: ModuleReferenceType] = {
SELECT type FROM
Directory, Imports, Open => NULL;
Library => from.mustHave ← CONS[
MakeDo.GetNode[moduleName.Cat[".RoseSymbols"], MakeDo.fileClass],
MakeDo.GetNode[moduleName.Cat["Impl.BCD"], MakeDo.fileClass],
from.mustHave];
TranslationNeeds => from.mustHave ← CONS[
MakeDo.GetNode[moduleName.Cat[".BCD"], MakeDo.fileClass],
from.mustHave];
ENDCASE => ERROR};
from ← [mustHave: LIST[rc.roseNode, rc.transNode], optional: NIL];
[] ← EnumerateModuleReferences[fromName: rc.roseNode.PublicPartsOfNode[].name, to: NoteModuleRef];
END;
IDProc: IO.BreakProc = {RETURN [SELECT char FROM
IN [IO.NUL .. IO.SP] => sepr,
'; => break,
ENDCASE => other]};
RederiveRose: PROC [a: MakeDo.Action] RETURNS [from: MakeDo.From, cmd: ROPE] --MakeDo.RederiveProc-- = {
rc: RoseAction ← NARROW[a.PublicPartsOfAction[].foundData];
from ← DeriveFrom[rc];
cmd ← rc.cmd};
CheckRoseConsistency: PROC [a: MakeDo.Action, result: MakeDo.Node] RETURNS [consistent: BOOL, reason: ROPE] --MakeDo.NotCurrentProc-- =
BEGIN
rc: RoseAction = NARROW[a.PublicPartsOfAction[].foundData];
resultTime: BasicTime.GMT = MakeDo.InnerGetCreated[result];
resultName: ROPE = result.PublicPartsOfNode[].name;
missingIngredientNode, latestIngredientNode: MakeDo.Node ← NIL;
latestIngredientTime: BasicTime.GMT ← BasicTime.nullGMT;
PerSource: PROC [n: MakeDo.Node, which: MakeDo.ActionDep, optional: BOOL] = {
fromTime: BasicTime.GMT ← MakeDo.InnerGetCreated[n];
IF fromTime = MakeDo.notExistTime THEN {IF NOT optional THEN missingIngredientNode ← n}
ELSE IF fromTime.Period[latestIngredientTime] < 0 THEN {
latestIngredientTime ← fromTime;
latestIngredientNode ← n;
};
};
latestIngredientTime ← BasicTime.earliestGMT;
missingIngredientNode ← latestIngredientNode ← NIL;
MakeDo.InnerEnumerateSources[a, data, PerSource];
IF missingIngredientNode#NIL THEN RETURN [
TRUE,
IO.PutFR[
"ingredient %g missing",
[rope[missingIngredientNode.PublicPartsOfNode[].name]]
]];
IF latestIngredientNode = NIL THEN ERROR;
IF resultTime = MakeDo.notExistTime THEN RETURN [
FALSE,
IO.PutFR[
"result %g doesn't exist",
[rope[resultName]]
]];
IF latestIngredientTime.Period[resultTime] > 0 THEN RETURN [
TRUE,
"result dated later than any ingredient"];
reason ← IO.PutFR[
"result %g of %g predates ingredient %g of %g",
[rope[resultName]],
[time[resultTime]],
[rope[latestIngredientNode.PublicPartsOfNode[].name]],
[time[latestIngredientTime]]];
consistent ← FALSE;
END;
ModuleReferenceType: TYPE = {Directory, Open, Imports, Exports, Library, TranslationNeeds};
MRKeywords: ARRAY ModuleReferenceType OF ROPE = ["Directory", "Open", "Imports", "Exports", "Library", "TranslationNeeds"];
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] = {
[] ← from.SkipWhitespace[];
IF from.PeekChar[] = '$ THEN {
IF from.GetChar[] # '$ THEN ERROR;
RETURN [IF from.PeekChar[] # '" THEN "$" ELSE from.GetRopeLiteral];
};
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 ← IOClasses.CreateCommentFilterStream[from];
[] ← 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[["Rosemary", RoseFind], back];
END.