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: ROPE ← NIL];
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.STREAM ← NIL;
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.