RoseTranslateSymbols.Mesa
Last Edited by: Spreitzer, July 9, 1983 5:29 pm
DIRECTORY
Atom, CIFS, ConvertUnsafe, Directory, FileIO, IO, Juniper, OrderedSymbolTableRef, PutGet, Rope, RoseTranslateTypes, RoseTranslateInsides, ShowTime, System, TextNode, TiogaFileOps, TiogaOps, UserExec, ViewerClasses, ViewerOps, Volume;
RoseTranslateSymbols: CEDAR PROGRAM
IMPORTS Atom, CIFS, ConvertUnsafe, Directory, FileIO, IO, Juniper, OSTR: OrderedSymbolTableRef, Rope, System, RoseTranslateInsides, UserExec, Volume
EXPORTS RoseTranslateInsides =
BEGIN OPEN RoseTranslateTypes, RoseTranslateInsides;
AddSymbols: PUBLIC PROC [job: Job, rootName: ROPE] =
BEGIN
error: BOOLEANFALSE;
IF job.libbed.Lookup[rootName] # NIL THEN RETURN;
job.libbed.Insert[rootName];
IF job.type = UpdateJob THEN error ← Update[job.exec, rootName, job.path].error;
IF NOT error THEN [] ← DigestSymbols[job, rootName];
END;
Update: PROC [exec: UserExec.ExecHandle, rootName: ROPE, pathIn: LIST OF ROPE] RETURNS [error, changed: BOOLEAN] =
BEGIN
DirtyDown: PROC = CHECKED
BEGIN
check ← Atom.MakeAtom[rootName];
IF Atom.GetProp[atom: check, prop: $roseTranslateCheck] # NIL THEN
BEGIN
viewerLog.PutF["Circularity detected at %g", IO.refAny[path]];
ERROR Circularity;
END;
Atom.PutProp[atom: check, prop: $roseTranslateCheck, val: check];
END;
check: ATOM;
CleanUp: PROC = CHECKED
{Atom.PutProp[atom: check, prop: $roseTranslateCheck, val: NIL]};
sourceName: ROPE ← rootName.Concat[".Rose"];
depsName: ROPE ← rootName.Concat[".RoseDeps"];
symbolsName: ROPE ← rootName.Concat[".RoseSymbols"];
mesaName: ROPE ← rootName.Concat[".Mesa"];
sourceOK, depsOK, symbolsOK, mesaExists, autoOK: BOOLEANTRUE;
path: LIST OF ROPECONS[rootName, pathIn];
dSource, dMesa, dSymbols, dDeps: LONG CARDINAL;
newer: BOOLEANFALSE;
imps: RopeList ← NIL;
[sourceOK, dSource] ← GetTime[sourceName];
[depsOK, dDeps] ← GetTime[depsName];
[symbolsOK, dSymbols] ← GetTime[symbolsName];
[mesaExists, dMesa] ← GetTime[mesaName];
autoOK ← depsOK AND symbolsOK AND mesaExists;
newer ← (dSource > dDeps) OR (dSource > dSymbols) OR (dSource > dMesa);
DirtyDown[];
BEGIN ENABLE UNWIND => CleanUp[];
IF sourceOK AND (IF autoOK THEN newer ELSE TRUE) THEN
BEGIN
error ← Translate[exec, rootName, pathIn, UpdateJob] > 0;
changed ← TRUE;
END
ELSE IF depsOK THEN
BEGIN
[error, changed] ← News[exec, rootName, path];
IF (changed OR NOT symbolsOK) AND sourceOK AND NOT error THEN
error ← Translate[exec, rootName, pathIn, TranslateJob] > 0;
END
ELSE BEGIN
viewerLog.PutF["no source or dependancies for %g!\n", IO.rope[rootName]];
error ← FALSE;
changed ← FALSE;
END;
END;
CleanUp[];
IF NOT error THEN
BEGIN
bcdName: ROPE ← rootName.Concat[".bcd"];
bcdExists, want: BOOLEANFALSE;
dBCD: LONG CARDINAL;
[mesaExists, dMesa] ← GetTime[mesaName];
[bcdExists, dBCD] ← GetTime[bcdName];
IF NOT mesaExists THEN want ← FALSE
ELSE IF NOT bcdExists THEN want ← TRUE
ELSE IF dMesa > dBCD THEN want ← TRUE
ELSE BEGIN
mc: BOOLEAN;
[error, mc, want] ← MesaNews[rootName, dBCD];
END;
IF want THEN UserExec.DoIt[Rope.Cat["compile ", rootName], exec];
END;
END;
RopeList: TYPE = LIST OF ROPE;
MesaNews: PROC [rootName: ROPE, dParent: LONG CARDINAL] RETURNS [error, missingChild, news: BOOLEAN] =
BEGIN
depFile: IO.STREAM;
depList: RopeList ← NIL;
storing: BOOLEANFALSE;
error ← missingChild ← news ← FALSE;
depFile ← FileIO.Open[rootName.Concat[".RoseDeps"] !FileIO.OpenFailed, Juniper.Error, CIFS.Error, Volume.InsufficientSpace =>
BEGIN
error ← TRUE;
CONTINUE;
END];
IF error THEN RETURN;
depFile.SkipOver[IO.WhiteSpace];
WHILE NOT depFile.EndOf[] DO
name: ROPE ← depFile.GetToken[MyBreak];
IF storing THEN depList ← CONS[name, depList]
ELSE IF name.Equal[";"] THEN storing ← TRUE;
depFile.SkipOver[IO.WhiteSpace];
ENDLOOP;
depFile.Close[];
WHILE depList # NIL DO
childExists: BOOLEAN;
dChild: LONG CARDINAL;
[childExists, dChild] ← GetTime[depList.first.Concat[".bcd"]];
IF NOT childExists THEN missingChild ← TRUE
ELSE IF dChild > dParent THEN news ← TRUE;
depList ← depList.rest;
ENDLOOP;
END;
News: PROC [exec: UserExec.ExecHandle, rootName: ROPE, path: LIST OF ROPE] RETURNS [error, news: BOOLEAN] =
BEGIN
depFile: IO.STREAM ← FileIO.Open[rootName.Concat[".RoseDeps"]];
depList: RopeList ← NIL;
depFile.SkipOver[IO.WhiteSpace];
WHILE NOT depFile.EndOf[] DO
name: ROPE ← depFile.GetToken[MyBreak];
IF name.Equal[";"] THEN EXIT;
depList ← CONS[name, depList];
depFile.SkipOver[IO.WhiteSpace];
ENDLOOP;
depFile.Close[];
error ← news ← FALSE;
WHILE depList # NIL DO
e, n: BOOLEAN;
[e, n] ← Update[exec, depList.first, path];
IF n THEN news ← TRUE;
IF e THEN RETURN [TRUE, news];
depList ← depList.rest;
ENDLOOP;
END;
GetTime: PROC [fileName: ROPE] RETURNS [exists: BOOLEAN, sinceEpoch: LONG CARDINAL] = TRUSTED
BEGIN
s: LONG STRING ← [256];
temp: LONG STRING ← [256];
t: System.GreenwichMeanTime;
exists ← TRUE;
ConvertUnsafe.AppendRope[s, fileName];
t ← Directory.GetProps[Directory.Lookup[s !Directory.Error => {exists ← FALSE; CONTINUE}], temp].createDate;
IF exists THEN sinceEpoch ← System.SecondsSinceEpoch[t];
END;
DigestSymbols: PROC [parent: Job, rootName: ROPE] RETURNS [error: BOOLEAN] =
BEGIN
job: Job ← NEW [JobRep ← [
exec: parent.exec,
rootName: rootName,
from: NIL,
things: parent.things,
type: TranslateJob,
log: parent.log]];
job.from ← FileIO.Open[rootName.Concat[".RoseSymbols"] !FileIO.OpenFailed, Juniper.Error, CIFS.Error, Volume.InsufficientSpace =>
BEGIN
Whimper[parent, "Unable to open %g.RoseSymbols", IO.rope[rootName]];
job.from ← NIL;
CONTINUE;
END];
IF job.from = NIL THEN RETURN [TRUE];
job.log.PutF["Reading symbols from %g.RoseSymbols...\n", IO.rope[rootName]];
job.from.SkipOver[IO.WhiteSpace];
WHILE NOT job.from.EndOf[] DO
className: ROPE ← job.from.GetToken[MyBreak];
definer: ROPE ← job.from.GetToken[MyBreak];
bits: CARDINAL ← job.from.GetInt[];
defaultInitExpr: ROPENARROW[job.from.GetRefAny[]];
asAny: REF ANY;
stoppedOn: ROPE;
cce: ccEntry ← NEW [SymbolTableEntryRep[cellClass] ← [name: className, value: cellClass[definedIn: rootName, cd: NEW [CellDefRep ← [defaultInitExprGiven: (bits MOD 2) > 0, initializerGiven: (bits MOD 4) > 1, initDataGiven: (bits MOD 8) > 3, defaultInitExpr: defaultInitExpr]] ]]];
iel: InterfaceEltList;
[asAny, stoppedOn] ← ParseExpression[job, TRUE];
IF NOT stoppedOn.Equal["!!"] THEN
BEGIN
[] ← Complain[job, "Not terminated properly"];
job.log.PutRope["Done reading symbols\n"];
RETURN [TRUE];
END;
IF asAny = NIL THEN iel ← NIL
ELSE WITH asAny SELECT FROM
sb: SquareBracketed => iel ← sb.iel;
ENDCASE => BEGIN
[] ← Complain[job, "Bad interface: %g", IO.refAny[asAny]];
job.log.PutRope["Done reading symbols\n"];
RETURN [TRUE];
END;
IF (cce.cd.interface ← DigestInterface[job, iel]) = NIL THEN
BEGIN
job.log.PutRope["Done reading symbols\n"];
RETURN [TRUE];
END;
AddCellClass[job, cce];
job.from.SkipOver[IO.WhiteSpace];
ENDLOOP;
job.log.PutRope["Done reading symbols\n"];
END;
AddCellClass: PUBLIC PROC [job: Job, cce: ccEntry] =
BEGIN
ste: SymbolTableEntry ← NARROW[job.things.Lookup[cce.name]];
complain: BOOLEAN ← ste # NIL;
IF complain THEN WITH ste SELECT FROM
oldCCE: ccEntry => IF oldCCE.definedIn = NIL AND cce.definedIn # NIL THEN
BEGIN
oldCCE.definedIn ← cce.definedIn;
oldCCE.cd ← cce.cd;
RETURN;
END;
ENDCASE;
IF complain THEN
BEGIN
Whimper[job, "Multiple definition of cell class %g", IO.rope[cce.name]];
END
ELSE job.things.Insert[cce];
END;
DigestInterface: PUBLIC PROC [context: REF ANY, iel: InterfaceEltList] RETURNS [di: DigestedInterface] =
BEGIN
di ← NEW [DigestedInterfaceRep ← [
asTable: OSTR.CreateTable[CompareInterfaceElts],
asList: iel]];
FOR iel ← iel, iel.rest WHILE iel # NIL DO
IF di.asTable.Lookup[iel.first.name] # NIL THEN
BEGIN
[] ← Complain[context, "Multiple def of %g in interface %g", IO.rope[iel.first.name], IO.refAny[di]];
RETURN [NIL];
END;
di.asTable.Insert[iel.first];
ENDLOOP;
END;
CompareInterfaceElts: OSTR.CompareProc =
BEGIN
s1, s2: ROPE;
s1 ← WITH r1 SELECT FROM
r: ROPE => r,
ie: InterfaceElt => ie.name,
ENDCASE => ERROR;
s2 ← WITH r2 SELECT FROM
r: ROPE => r,
ie: InterfaceElt => ie.name,
ENDCASE => ERROR;
RETURN [s1.Compare[s2, FALSE]];
END;
UpdateCmd: UserExec.CommandProc =
BEGIN
event.commandLineStream.SkipOver[IO.WhiteSpace];
WHILE NOT event.commandLineStream.EndOf[] DO
name: ROPE ← event.commandLineStream.GetToken[IO.IDProc];
error: BOOLEANTRUE;
error ← NOT Update[exec, name, NIL !Circularity => CONTINUE].error;
IF error THEN ok ← FALSE;
event.commandLineStream.SkipOver[IO.WhiteSpace];
ENDLOOP;
END;
UserExec.RegisterCommand["RoseUpdate", UpdateCmd, "Ensures Rosemary translations are up to date", "Syntax: \"RoseUpdate <rootName>*\". Recursively called on what each root depends on"];
END.