<> <> 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["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.