RoseTranslateRandoms.Mesa
Last Edited by: Spreitzer, February 12, 1985 6:32:42 pm PST
DIRECTORY AMBridge, AMTypes, Ascii, Asserting, AssertingIO, Atom, BasicTime, Commander, Convert, FS, IO, IOClasses, OrderedSymbolTableRef, PrintTV, PutGet, Rope, RoseTranslateTypes, RoseTranslateInsides, RoseTypes, RuntimeError, SignalTypeRegistration, StructuredStreams, TEditMesaOps, TextNode, TiogaFileOps, TiogaOps, TiogaStreams, UndoEvent, UserCredentials, ViewerClasses, ViewerIO, ViewerOps, ViewerTools;
RoseTranslateRandoms:
CEDAR
PROGRAM
IMPORTS AMBridge, Ascii, Asserting, AssertingIO, BasicTime, Commander, Convert, FS, IO, IOClasses, OSTR: OrderedSymbolTableRef, PrintTV, PutGet, Rope, RoseTranslateInsides, RuntimeError, SignalTypeRegistration, SS: StructuredStreams, TEditMesaOps, TextNode, TFO: TiogaFileOps, TS: TiogaStreams, UserCredentials, ViewerIO
EXPORTS RoseTranslateTypes, RoseTranslateInsides =
BEGIN OPEN RoseTranslateTypes, RoseTranslateInsides;
TypeConstructionError: PUBLIC ERROR [msg: ROPE] = CODE;
Circularity: PUBLIC ERROR = CODE;
viewerLog: PUBLIC IO.STREAM ← ViewerIO.CreateViewerStreams["RoseTranslate.Log"].out;
versionString: PUBLIC ROPE;
omitted: PUBLIC REF ANY ← NEW [ROPE ← "omitted"];
error: PUBLIC REF ANY ← NEW [ROPE ← "error"];
noDefault: PUBLIC REF ANY ← NEW [ROPE ← "no default"];
DriveLevelsPerWord: NAT = 480/SIZE[PACKED ARRAY [0 .. 480) OF RoseTypes.DriveLevel];
AddOpen:
PUBLIC
PROC [job: Job, name:
ROPE] =
BEGIN
IF job.opened.Lookup[name] # NIL THEN RETURN;
job.opened.Insert[name];
IF NOT job.emptyOpen THEN job.openStream.PutRope[", "];
job.openStream.PutRope[name]; job.emptyOpen ← FALSE;
AddDirectory[job, name];
END;
AddImport:
PUBLIC
PROC [job: Job, name:
ROPE] =
BEGIN
IF job.imports.Lookup[name] # NIL THEN RETURN;
job.imports.Insert[name];
IF NOT job.emptyImports THEN job.importsStream.PutRope[", "];
job.importsStream.PutRope[name]; job.emptyImports ← FALSE;
AddDirectory[job, name];
END;
AddDirectory:
PUBLIC
PROC [job: Job, name:
ROPE] =
BEGIN
IF job.directory.Lookup[name] # NIL THEN RETURN;
job.directory.Insert[name];
IF NOT job.emptyDirectory THEN job.directoryStream.PutRope[", "];
job.directoryStream.PutRope[name]; job.emptyDirectory ← FALSE;
END;
AddMesa:
PUBLIC
PROC [job: Job, m: Mesa] = {rl: RopeList;
FOR rl ← m.directory, rl.rest WHILE rl # NIL DO AddDirectory[job, rl.first] ENDLOOP;
FOR rl ← m.imports, rl.rest WHILE rl # NIL DO AddImport[job, rl.first] ENDLOOP;
};
GetParm:
PUBLIC
PROC [n: [1..
LAST[
INTEGER]], name:
ROPE, parms:
REF
ANY, default:
REF
ANY ← noDefault]
RETURNS [it:
REF
ANY] =
BEGIN
IF parms =
NIL
THEN
BEGIN
IF default # noDefault THEN it ← default
ELSE ERROR TypeConstructionError[IO.PutFR["parm %g not found", IO.rope[name]]];
END
ELSE
WITH parms
SELECT
FROM
bl: BindingList =>
BEGIN
FOR bl ← bl, bl.rest
WHILE bl #
NIL
DO
IF bl.first.name.Equal[name, FALSE] THEN RETURN [bl.first.value];
ENDLOOP;
IF default # noDefault THEN it ← default
ELSE ERROR TypeConstructionError[IO.PutFR["parm %g not found", IO.rope[name]]];
END;
a: Args =>
BEGIN
i: INT ← n;
FOR l:
LIST
OF Arg ← a.args, l.rest
WHILE l #
NIL
DO
IF i = 1 THEN RETURN [l.first];
i ← i - 1;
ENDLOOP;
IF default # noDefault THEN it ← default
ELSE ERROR TypeConstructionError[IO.PutFR["no %g'th parm", IO.int[i]]];
END;
ENDCASE => ERROR;
END;
ForceMesaType:
PUBLIC
PROC [mesaType:
ROPE, on: NodeType]
RETURNS [forced: NodeType] =
BEGIN
ERROR; --no longer supported
END;
Close:
PUBLIC
PROC [job: Job] =
BEGIN
IF job.errCount < 1
THEN
BEGIN
WITH job.parseTree
SELECT
FROM
s: Statements => FOR l: LORA ← s.statements, l.rest WHILE l # NIL DO TranslatePiece[job, l.first] ENDLOOP;
ENDCASE => TranslatePiece[job, job.parseTree];
END
ELSE job.log.PutRope["Translation aborted due to errors\n"];
job.log.PutF["%g error%g, %g warning%g", IO.card[job.errCount], IO.rope[IF job.errCount = 1 THEN "" ELSE "s"], IO.card[job.warnCount], IO.rope[IF job.warnCount = 1 THEN "" ELSE "s"]];
job.log.PutF["; source tokens: %g, time: %g\n", IO.card[job.tokenCount], IO.real[BasicTime.PulsesToSeconds[BasicTime.GetClockPulses[] - job.start]]];
job.directoryStream.PutRope[";"];
job.directoryStream.Close[];
job.importsStream.PutRope[" ="];
job.importsStream.Close[];
job.openStream.PutRope[";"];
job.openStream.Close[];
job.regStream.PutRope["END;"];
job.regStream.Close[];
job.typeStream.Close[];
job.partsAssertionsStream.Close[];
TS.EndNode[job.to];
job.to.PutRope["RegisterCells[];"];
TS.EndNode[job.to];
TS.EndNode[job.to];
job.to.PutRope["END."];
job.to.Close[];
IF job.errCount < 1
THEN
TRUSTED
BEGIN
destName: ROPE;
DoMesaFormatting[job.outRoot];
TFO.Store[job.outRoot, destName ← job.rootName.Concat[".Mesa"]];
--DoMesaFormatting[destName];--
--UserExecExtras.DoIt[job.exec, Rope.Cat["compile ", job.rootName]];--
TFO.Store[job.symbolsRoot, job.rootName.Concat[".RoseSymbols"]];
WriteDeps[job];
END;
END;
WriteDeps:
PROC [job: Job] =
BEGIN
WriteLoad:
PROC [asAny:
REF
ANY]
RETURNS [stop:
BOOLEAN] =
BEGIN
depName: ROPE ← NARROW[asAny];
cmFile.PutF["@%g.roseLoad\n", IO.rope[depName]];
stop ← FALSE;
END;
cmFile: IO.STREAM ← FS.StreamOpen[fileName: job.rootName.Concat[".roseLoad"], accessOptions: create];
job.libbed.EnumerateIncreasing[WriteLoad];
cmFile.PutF["Run %g\n", IO.rope[job.rootName]];
cmFile.Close[];
END;
TranslateCmd: Commander.CommandProc
--PROC [cmd: Handle] RETURNS [result: REF ← NIL, msg: Rope.ROPE ← NIL]-- =
BEGIN
commandLineStream: IO.STREAM ← IO.RIS[cmd.commandLine];
[] ← commandLineStream.SkipWhitespace[flushComments: FALSE];
WHILE
NOT commandLineStream.EndOf[]
DO
name: ROPE ← commandLineStream.GetTokenRope[IO.IDProc].token;
errs: CARDINAL ← 1;
errs ← Translate[cmd, name, NIL, TranslateJob !Circularity => CONTINUE];
IF errs > 0 THEN RETURN [$Failure];
[] ← commandLineStream.SkipWhitespace[flushComments: FALSE];
ENDLOOP;
END;
Translate:
PUBLIC
PROC [exec: Commander.Handle, rootName:
ROPE, pathIn:
LIST
OF
ROPE, type: JobType]
RETURNS [errCount:
CARDINAL] =
TRUSTED
BEGIN
inRoot: TextNode.Ref ← NIL;
job: Job ←
NEW [JobRep ← [
exec: exec,
rootName: rootName,
path: CONS[rootName, pathIn],
outRoot: TFO.CreateRoot[],
symbolsRoot: TFO.CreateRoot[],
directory: OSTR.CreateTable[CompareRopes],
imports: OSTR.CreateTable[CompareRopes],
opened: OSTR.CreateTable[CompareRopes],
libbed: OSTR.CreateTable[CompareRopes],
things: OSTR.CreateTable[SignalTypeRegistration.CompareSymbolTableEntries],
used: OSTR.CreateTable[CompareRefAnies],
type: type,
start: BasicTime.GetClockPulses[]]];
logFile: IO.STREAM;
sourceName, logName: ROPE;
inRoot ← PutGet.FromFile[sourceName ← rootName.Concat[".Rose"] !FS.Error =>
BEGIN
viewerLog.PutF["\nOpen failed on %g\n", IO.rope[sourceName]];
inRoot ← NIL;
CONTINUE;
END];
IF inRoot = NIL THEN RETURN [1];
job.from ← TS.CreateInput[inRoot];
job.to ← TS.CreateOutput[job.outRoot, "code"];
job.symbolsStream ← TS.CreateOutput[job.symbolsRoot];
job.partsAssertionsStream ← SS.Create[FS.StreamOpen[rootName.Cat[".pass"], create], 55];
logFile ← FS.StreamOpen[fileName: logName ← rootName.Concat[".log"], accessOptions: create];
job.log ← IOClasses.CreateDribbleOutputStream[logFile, viewerLog];
Open[job, sourceName];
job.parseTree ← ParseExpression[job];
Close[job];
logFile.Close[];
viewerLog.PutRope["Done.\n\n"];
errCount ← job.errCount;
END;
Open:
PROC [job: Job, sourceName:
ROPE] =
TRUSTED
BEGIN
job.log.PutF["\nTranslating %g into %g.Mesa, log on %g.Log\n", IO.rope[sourceName], IO.rope[job.rootName], IO.rope[job.rootName]];
job.to.PutF["--%g.Mesa", IO.rope[job.rootName]]; TS.EndNode[job.to];
job.to.PutF["--created by RoseTranslate %g from %g of %g", IO.rope[versionString], IO.rope[sourceName], IO.time[FS.FileInfo[sourceName].created]];
TS.EndNode[job.to];
job.to.PutF["--created for %g", IO.rope[UserCredentials.Get[].name]];
TS.EndNode[job.to];
job.to.PutF["--created at %g", IO.time[]];
TS.EndNode[job.to];
TS.EndNode[job.to];
TS.EndNode[job.to];
job.to.PutRope["DIRECTORY"];
job.directoryStream ← TS.CreateOutput[TS.CurOutNode[job.to], "code"];
TS.EndNode[job.to];
TS.EndNode[job.to];
job.to.PutF["%l%g%l: CEDAR PROGRAM", IO.rope["lb"], IO.rope[job.rootName], IO.rope["LB"]];
job.importsStream ← TS.CreateOutput[TS.CurOutNode[job.to], "code"];
job.importsStream.PutRope["IMPORTS "];
TS.EndNode[job.to];
TS.EndNode[job.to];
job.to.PutRope["BEGIN OPEN"];
job.openStream ← TS.CreateOutput[TS.CurOutNode[job.to], "code"];
TS.EndNode[job.to];
TS.EndNode[job.to];
job.to.PutRope["--Signal Type decls"];
job.typeStream ← TS.CreateOutput[TS.CurOutNode[job.to], "code"];
TS.EndNode[job.to];
TS.EndNode[job.to];
job.to.PutRope["RegisterCells: PROC ="];
job.regStream ← TS.CreateOutput[TS.CurOutNode[job.to], "code"];
TS.EndNode[job.to];
job.regStream.PutRope["BEGIN"]; TS.EndNode[job.regStream];
job.to.PutF["otherss: SymbolTable ← RoseCreate.GetOtherss[%g];", IO.refAny[job.rootName.Cat[".pass"]]];
TS.EndNode[job.to];
AddOpen[job, "RoseTypes"];
AddImport[job, "RoseCreate"];
END;
TypeCheck:
PUBLIC
PROC [job: Job, defName:
ROPE, args:
REF
ANY, interface: DigestedInterface, instanceName:
ROPE] =
BEGIN
cName: ROPE ← defName.Cat[".", instanceName];
Check:
PROC [sr: SourceRange, keyword:
ROPE, match: InterfaceElt, value:
REF
ANY] =
BEGIN
Descr:
PROC
RETURNS [r:
ROPE] = {
r ←
IF keyword =
NIL
THEN IO.PutFR["%g#%g", IO.rope[cName], IO.card[index]]
ELSE IO.PutFR["%g.%g", IO.rope[cName], IO.rope[keyword]]};
ste: SymbolTableEntry;
valName: ROPE;
valNode: nodeEntry;
IF match =
NIL
AND keyword #
NIL
THEN
BEGIN
match ← NARROW[interface.asTable.Lookup[keyword]];
IF match = NIL THEN Whimper[sr, job, "%g not a valid port on cell %g", IO.rope[keyword], IO.rope[cName]];
END;
WITH value
SELECT
FROM
id: ID => {valName ← id.rope; IF sr = nullSR THEN sr ← id.sr};
ENDCASE => {Whimper[sr, job, "%g should be bound to an ID, not %g", IO.rope[Descr[]], IO.refAny[value]]; RETURN};
ste ← NARROW[job.things.Lookup[valName]];
WITH ste
SELECT
FROM
ne: nodeEntry => valNode ← ne;
ENDCASE => {Whimper[sr, job, "%g was bound to %g, which should have been a node, rather than %g", IO.rope[Descr[]], IO.rope[valName], IO.refAny[ste]]; RETURN};
IF match = NIL THEN RETURN;
IF match.spare THEN Whimper[sr, job, "%g.%g specified twice", IO.rope[cName], IO.rope[match.name]]
ELSE match.spare ← TRUE;
IF match.sti.st # valNode.nodeType
THEN
BEGIN
Whimper[sr, job,
"Type mismatch for %g: got %g when expecting %g",
IO.rope[Descr[]],
IO.rope[valNode.nodeType.procs.UserDescription[valNode.nodeType]],
IO.rope[match.sti.st.procs.UserDescription[match.sti.st]]];
END;
END;
toMatch: InterfaceEltList ← interface.asList;
index: CARDINAL ← 0;
FOR iel: InterfaceEltList ← interface.asList, iel.rest
WHILE iel #
NIL
DO
iel.first.spare ← FALSE;
ENDLOOP;
WITH args
SELECT
FROM
bl: BindingList =>
FOR bl ← bl, bl.rest
WHILE bl #
NIL
DO
index ← index + 1;
Check[bl.first.sr, bl.first.name, NIL, bl.first.value];
ENDLOOP;
a: Args =>
BEGIN
l: LIST OF Arg;
FOR l ← a.args, l.rest
WHILE l #
NIL
AND toMatch #
NIL
DO
index ← index + 1;
Check[nullSR, NIL, toMatch.first, l.first];
toMatch ← toMatch.rest;
ENDLOOP;
IF l # NIL --OR toMatch # NIL-- THEN Whimper[a.sr, job, "too many parameters to %g", IO.rope[cName]];
END;
ENDCASE => ERROR;
index ← 0;
FOR iel: InterfaceEltList ← interface.asList, iel.rest
WHILE iel #
NIL
DO
index ← index + 1;
IF
NOT iel.first.spare
THEN
--old: Whimper[job, "%g.%g never specified", IO.rope[cName], IO.rope[iel.first.name]];--
--new:-- Check[nullSR, iel.first.name, iel.first, NEW [IDRep ← [nullSR, iel.first.name]] ];
ENDLOOP;
END;
DoMesaFormatting:
PROC [tfor: TiogaFileOps.Ref] =
BEGIN
tnr: TextNode.Ref;
TRUSTED {tnr ← LOOPHOLE[tfor]};
[] ← TEditMesaOps.SetSpanMesaLooks[
span: [[tnr, 0], TextNode.LastLocWithin[tnr]],
event: NIL
];
END;
Complain:
PUBLIC
PROC [sr: SourceRange, context:
REF
ANY, complaint:
ROPE, v1, v2, v3, v4, v5:
IO.Value ← [null[]]]
RETURNS [reduced:
REF
ANY] =
BEGIN
job: Job ← NARROW[context];
IF sr # nullSR THEN job.log.PutF["At [%g..%g]: ", IO.int[sr.first], IO.int[sr.last]]
ELSE IF NOT job.from.EndOf[] THEN job.log.PutF["Somewhere before %g: ", IO.int[job.from.GetIndex[]]];
job.log.PutF[complaint.Concat["\n"], v1, v2, v3, v4, v5];
job.errCount ← job.errCount + 1;
reduced ← error;
END;
Whimper:
PUBLIC
PROC [sr: SourceRange, context:
REF
ANY, complaint:
ROPE, v1, v2, v3, v4, v5:
IO.Value ← [null[]]] =
BEGIN
job: Job ← NARROW[context];
IF sr # nullSR THEN job.log.PutF["At [%g..%g]: ", IO.int[sr.first], IO.int[sr.last]]
ELSE IF NOT job.from.EndOf[] THEN job.log.PutF["Somewhere before %g: ", IO.int[job.from.GetIndex[]]];
job.log.PutF[complaint.Concat["\n"], v1, v2, v3, v4, v5];
job.warnCount ← job.warnCount + 1;
END;
CompareRopes: OSTR.CompareProc = {RETURN [Rope.Compare[NARROW[r1], NARROW[r2]]]};
CompareRefAnies:
OSTR.CompareProc =
BEGIN
c1: LONG CARDINAL ← LOOPHOLE[r1];
c2: LONG CARDINAL ← LOOPHOLE[r2];
RETURN [IF c1 < c2 THEN less ELSE IF c1 > c2 THEN greater ELSE equal];
END;
InitialCap:
PROC [r:
ROPE]
RETURNS [
R:
ROPE] = {
l: INT = r.Length[];
IF l = 0 THEN RETURN [r];
R ← Rope.FromChar[Ascii.Upper[r.Fetch[0]]].Concat[r.Substr[start: 1, len: l-1]]};
uppers: ARRAY [1..15] OF CARDINAL ← [1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767];
UseSignalType:
PROC [job: Job, st: NodeType] =
BEGIN
c: REF ANY ← st;
ce: REF ANY ← NARROW[job.used.Lookup[c]];
IF ce =
NIL
THEN
BEGIN
m: Mesa ← IF st.procs.MesaDefinition # NIL THEN st.procs.MesaDefinition[st] ELSE [NIL];
job.used.Insert[c];
IF m # [
NIL]
THEN
{job.typeStream.PutRope[m.mesa];
job.typeStream.PutRope[";"];
TS.EndNode[job.typeStream];
AddMesa[job, m];};
END;
END;
WriteRegistration:
PUBLIC
PROC [to:
IO.
STREAM, result, name:
ROPE, cellDef: CellDef] =
BEGIN
evalGiven: BOOLEAN ← FALSE;
to.PutRope[result];
to.PutRope[" ← RoseCreate.RegisterCellType[name: "];
IF cellDef.nameIsLiteral
THEN to.PutF["\"%g\",", IO.rope[cellDef.literalName]]
ELSE to.PutF["%gName[%g],", IO.rope[name], IO.rope[IF cellDef.forFn # NIL THEN "args" ELSE ""]];
TS.ChangeDepth[to, 1];
IF cellDef.expandCode # NIL THEN to.PutF["expandProc: %gExpand,", IO.rope[name]] ELSE to.PutRope["expandProc: NIL,"];
TS.EndNode[to];
IF AuxKnown[name, cellDef, IO, Val] THEN to.PutF["ioCreator: Create%gIO, ", IO.rope[name]] ELSE to.PutRope["ioCreator: NIL, "];
IF AuxKnown[name, cellDef, State, Val] OR cellDef.initializerSource # NIL THEN to.PutF["initializer: Initialize%g,", IO.rope[name]] ELSE to.PutRope["initializer: NIL,"];
TS.EndNode[to];
to.PutRope["evals: ["];
FOR et: EvalType
IN EvalType
DO
IF cellDef.evals[et] #
NIL
THEN {
IF evalGiven THEN to.PutRope[", "] ELSE evalGiven ← TRUE;
to.PutF["%g: %g%g", IO.rope[etNames[et]], IO.rope[name], IO.rope[etNames[et]]]};
ENDLOOP;
to.PutRope["],"];
TS.EndNode[to];
to.PutRope["tests: LIST["];
FOR tl: TestList ← cellDef.tests, tl.rest
WHILE tl #
NIL
DO
to.PutF[
"[name: %g, proc: %g, stateToo: %g]",
IO.refAny[tl.first.name],
IO.rope[TestName[name, tl.first, cellDef]],
IO.bool[tl.first.stateToo]];
IF tl.rest # NIL THEN to.PutRope[", "];
ENDLOOP;
to.PutRope["],"];
TS.EndNode[to];
to.PutRope["ports: "];
IF cellDef.interfaceLiteral #
NIL
AND cellDef.interfaceLiteral.asList =
NIL
THEN to.PutRope["NEW [PortsRep[0]],"]
ELSE to.PutF["Create%gPorts[%g],", IO.rope[name], IO.rope[IF cellDef.forFn # NIL THEN "args" ELSE ""]];
TS.EndNode[to];
IF AuxKnown[name, cellDef, Drive, Val]
THEN to.PutF["driveCreator: Create%gDrive", IO.rope[name]]
ELSE to.PutRope["driveCreator: NIL"];
IF cellDef.forFn #
NIL
THEN {
to.PutRope[","];
TS.EndNode[to];
to.PutF["typeData: NEW [%gArgs ← args]", IO.rope[name]]};
IF cellDef.initCTPropsSource #
NIL
OR (cellDef.assertions #
NIL)
THEN {
to.PutRope[","];
TS.EndNode[to];
to.PutF["other: Initial%gProps[%g]", IO.rope[name], IO.rope[IF cellDef.forFn # NIL THEN "args" ELSE ""]]};
to.PutRope["];"];
TS.ChangeDepth[to, -1];
END;
etNames: PUBLIC ARRAY EvalType OF ROPE ← ["ValsChanged", "InitQ", "PropQ", "InitUD", "PropUD", "FinalUD", "EvalSimple", "FindVicinity"];
auxClassNames: PUBLIC ARRAY AuxClass OF ROPE ← [IO: "IO", State: "State", Drive: "Drive"];
auxValNames: PUBLIC ARRAY AuxVal OF ROPE ← [Ref: "Ref", Rec: "Rec", Val: "Val"];
WriteInterfaceDecls:
PUBLIC
PROC [job: Job, name, ioRefTypeName:
ROPE, cellDef: CellDef, function:
BOOL]
RETURNS [iCount:
CARDINAL] =
BEGIN
di: DigestedInterface ← cellDef.interfaceLiteral;
interface: InterfaceEltList ← di.asList;
toIO, toPortType, toPortFile, portConsts: IO.STREAM;
firstWord: CARDINAL ← 0;
hasASwitchPort: BOOL ← FALSE;
dest: TFO.Ref;
portFileName: ROPE ← job.rootName.Cat[".", name, ".rosePorts"];
FOR iel: InterfaceEltList ← interface, iel.rest
WHILE iel #
NIL
DO
IF NOT iel.first.sti.st.simple THEN {hasASwitchPort ← TRUE; EXIT};
ENDLOOP;
iCount ← 0;
toPortFile ← SS.Create[FS.StreamOpen[portFileName, create]];
TS.EndNode[job.to];
job.to.PutF["Create%gPorts: PROC ", IO.rope[name]];
IF function THEN job.to.PutF["[args: %gArgs] ", IO.rope[name]];
job.to.PutF["RETURNS [ports: Ports] = {ports ← RoseCreate.PortsFromFile[\"%q\"]};", IO.rope[portFileName]];
TS.EndNode[job.to];
TS.EndNode[job.to];
toPortFile.PutF["%g", IO.int[di.asTable.Size[]]];
job.to.PutF["%g: TYPE = REF %gIORec;", IO.rope[ioRefTypeName], IO.rope[name]];
TS.EndNode[job.to];
job.to.PutF["%gIORec: TYPE = MACHINE DEPENDENT RECORD [", IO.rope[name]];
TS.EndNode[job.to];
dest ← TS.CurOutNode[job.to];
TS.EndNode[job.to];
toIO ← TS.CreateOutput[dest, "code"];
IF hasASwitchPort
AND cellDef.evals[FindVicinity] #
NIL
THEN {
job.to.PutRope["-- port indices:"];
TS.EndNode[job.to];
dest ← TS.CurOutNode[job.to];
TS.EndNode[job.to];
portConsts ← TS.CreateOutput[dest, "code"];
};
job.to.PutF["%gDriveRef: TYPE = REF %gDriveRec;", IO.rope[name], IO.rope[name]];
TS.EndNode[job.to];
job.to.PutF["%gDriveRec: TYPE = RECORD [tag: DriveTagType, s: PACKED ARRAY %gPort OF DriveLevel];", IO.rope[name], IO.rope[name]];
TS.EndNode[job.to];
job.to.PutF["%gPort: TYPE = MACHINE DEPENDENT {", IO.rope[name]];
dest ← TS.CurOutNode[job.to];
TS.EndNode[job.to];
toPortType ← TS.CreateOutput[dest, "code"];
FOR interface ← interface, interface.rest
WHILE interface #
NIL
DO
Finish:
PROC [s:
IO.
STREAM] =
{IF interface.rest # NIL THEN {s.PutRope[","]; TS.EndNode[s]}};
ie: InterfaceElt ← interface.first;
iename: ROPE ← ie.name;
bitWidth, wordWidth, bitRem: CARDINAL;
mesaType: Mesa;
xPhobic: BOOL ← NOT ie.sti.st.simple;
special: BOOLEAN ← FALSE;
portTypeStream: IO.STREAM ← IO.ROS[];
otherAssertions: Asserting.Assertions ← NIL;
UseSignalType[job, ie.sti.st];
bitWidth ← ie.sti.st.procs.Bits[ie.sti.st];
mesaType ← ie.sti.st.procs.MesaUse[ie.sti.st];
AddMesa[job, mesaType];
wordWidth ← (bitWidth + 15)/16;
bitRem ← bitWidth MOD 16;
Very explicit, but not necessary:
IF bitRem # 0 THEN
BEGIN
toIO.PutF["fill%g(%g:0..%g): [0..%g],", IO.card[iCount], IO.card[firstWord], IO.int[15 - bitRem], IO.card[uppers[16 - bitRem]]];
TS.EndNode[toIO];
END;
toIO.PutF["%g(%g:%g..%g): %g", IO.rope[iename], IO.card[firstWord], IO.card[(16-bitRem) MOD 16], IO.card[16*wordWidth - 1], IO.rope[mesaType.mesa]];
More concisely, but equivalent in terms of where the interesting stuff goes (or so a little experimentation says):
toIO.PutF["%g(%g): %g", IO.rope[iename], IO.card[firstWord], IO.rope[mesaType.mesa]];
Finish[toIO];
IF iCount > 0 THEN toPortType.PutRope[", "];
toPortType.PutRope[iename];
FOR ll: Asserting.Assertions ← ie.assertions, ll.rest
WHILE ll #
NIL
DO
key: ATOM ← NARROW[Asserting.RelnOf[ll.first]];
SELECT key
FROM
$XPhobic => xPhobic ← TRUE;
$XPhillic => xPhobic ← FALSE;
$Special => special ← TRUE;
$General => special ← FALSE;
ENDCASE => otherAssertions ← CONS[ll.first, otherAssertions];
ENDLOOP;
toPortFile.PutF["\n %g %g %g ", IO.card[firstWord], IO.card[wordWidth], IO.rope[Convert.RopeFromRope[iename]]];
WriteInvocation[portTypeStream, ie.sti.invocation];
toPortFile.PutF["\"%q\" %g ",
IO.rope[IO.RopeFromROS[portTypeStream]],
IO.card[(IF ie.input THEN 1 ELSE 0) + (IF ie.output THEN 2 ELSE 0) + (IF xPhobic THEN 4 ELSE 0) + (IF special THEN 8 ELSE 0)]];
AssertingIO.Write[to: toPortFile, assertions: otherAssertions];
IF (
NOT ie.sti.st.simple)
AND (cellDef.evals[FindVicinity] #
NIL)
THEN {
portConsts.PutF["%g%gPortIndex: CARDINAL = %g;", IO.rope[name], IO.rope[InitialCap[iename]], IO.card[iCount]];
TS.EndNode[portConsts]};
firstWord ← firstWord + wordWidth;
iCount ← iCount + 1;
ENDLOOP;
toIO.PutRope["];"]; toIO.Close[];
IF (iCount MOD DriveLevelsPerWord) # 0 THEN toPortType.PutF[", (%g)", IO.int[((iCount + DriveLevelsPerWord - 1) / DriveLevelsPerWord) * DriveLevelsPerWord - 1]];
toPortType.PutRope["};"]; toPortType.Close[];
SS.CloseThrough[toPortFile];
END;
WriteInitializer:
PUBLIC
PROC [job: Job, name:
ROPE, cc: CedarChildren, cellDef: CellDef] =
BEGIN
dest: TiogaFileOps.Ref;
opend: ROPE ← "";
TS.EndNode[job.to];
job.to.PutF["Initialize%g: Initializer = {", IO.rope[name]];
TS.ChangeDepth[job.to, 1];
job.to.PutRope["IF leafily THEN"];
TS.ChangeDepth[job.to, 1];
job.to.PutRope["BEGIN"];
TS.EndNode[job.to];
IF cellDef.forFn #
NIL
THEN {
job.to.PutF["args: REF %gArgs ← NARROW [cell.type.typeData];", IO.rope[name]];
TS.ChangeDepth[job.to, 1];
job.to.PutRope["{OPEN args;"];
TS.EndNode[job.to];
};
IF cellDef.initializerSource #
NIL
AND AuxKnown[name, cellDef,
IO, Ref]
THEN
BEGIN
job.to.PutF["ioRec: %g ← NARROW[cell.realCellStuff.newIO];", IO.rope[GetAux[name, cellDef, IO, Ref]]];
TS.EndNode[job.to];
opend ← "ioRec";
IF AuxKnown[name, cellDef, State, Ref] THEN opend ← opend.Cat[", state"];
END;
IF AuxKnown[name, cellDef, State, Ref]
AND AuxKnown[name, cellDef, State, Val]
THEN
BEGIN
job.to.PutF["state: %g ← %g;",
IO.rope[GetAux[name, cellDef, State, Ref]],
IO.rope[GetAux[name, cellDef, State, Val]]];
TS.EndNode[job.to];
job.to.PutRope["cell.realCellStuff.state ← state;"];
TS.EndNode[job.to];
END;
IF cellDef.initializerSource #
NIL
THEN
BEGIN
job.to.PutF["BEGIN OPEN %g;", IO.rope[opend]];
dest ← TS.CurOutNode[job.to];
TS.ChangeDepth[job.to, 1];
job.to.PutRope["END;"];
TS.ChangeDepth[job.to, -1];
TS.CopyChildren[from: cc.parent, to: dest];
END;
IF cellDef.forFn #
NIL
THEN {
job.to.PutRope["};"];
TS.ChangeDepth[job.to, -1];
};
job.to.PutRope["END;"];
TS.ChangeDepth[job.to, -1];
job.to.PutRope["};"];
TS.ChangeDepth[job.to, -1];
END;
WriteEval:
PUBLIC
PROC [job: Job, name:
ROPE, et: EvalType, cc: CedarChildren, cellDef: CellDef] =
BEGIN
opend: ROPE ← NIL;
AddOpen:
PROC [o:
ROPE] = {
opend ← IF opend = NIL THEN o ELSE (opend.Cat[", ", o])};
dest: TiogaFileOps.Ref;
hasIO: BOOL ← AuxKnown[name, cellDef, IO, Ref];
doSW: BOOL ← FALSE;
TS.EndNode[job.to];
job.to.PutF["%g%g: %g =",
IO.rope[name],
IO.rope[etNames[et]],
IO.rope[
IF et = FindVicinity
THEN "PROC [cell: Cell, portIndex: CARDINAL, evenIfInput: BOOL ← FALSE]"
ELSE "CellProc"]];
TS.ChangeDepth[job.to, 1];
job.to.PutRope["BEGIN"]; TS.EndNode[job.to];
SELECT et
FROM
FindVicinity => NULL;
InitQ, PropQ, InitUD, PropUD, FinalUD, ValsChanged => {
IF hasIO THEN {AddOpen["sw"]; doSW ← TRUE};
IF cellDef.interfaceLiteral # NIL AND NOT cellDef.interfaceLiteral.hasSwitchElt THEN Whimper[cellDef.sr, job, "Cell class %g has a %g, but no switch-level interface elements!", IO.rope[name], IO.rope[etNames[et]]];
};
EvalSimple => IF hasIO THEN AddOpen["newIO"];
ENDCASE => ERROR;
IF doSW
OR (cellDef.interfaceLiteral #
NIL
AND cellDef.interfaceLiteral.hasSwitchElt)
THEN {
job.to.PutF["sw: %g ← NARROW[cell.realCellStuff.switchIO];", IO.rope[GetAux[name, cellDef, IO, Ref]]];
TS.EndNode[job.to];
};
IF cellDef.forFn #
NIL
THEN {
job.to.PutF["args: REF %gArgs ← NARROW[cell.type.typeData];", IO.rope[name]];
TS.EndNode[job.to];
AddOpen["args"];
};
IF hasIO THEN job.to.PutF["newIO: %g ← NARROW[cell.realCellStuff.newIO];", IO.rope[GetAux[name, cellDef, IO, Ref]] ];
IF AuxKnown[name, cellDef, State, Ref]
THEN
BEGIN
TS.EndNode[job.to];
job.to.PutF["state: %g ← NARROW[cell.realCellStuff.state];", IO.rope[GetAux[name, cellDef, State, Ref]]];
AddOpen["state"];
END;
TS.ChangeDepth[job.to, 1];
job.to.PutRope["BEGIN"];
IF opend # NIL THEN job.to.PutF[" OPEN %g;", IO.rope[opend]];
dest ← TS.CurOutNode[job.to];
TS.EndNode[job.to];
job.to.PutRope["END;"];
TS.ChangeDepth[job.to, -1];
TS.CopyChildren[from: cc.parent, to: dest];
job.to.PutRope["END;"];
TS.ChangeDepth[job.to, -1];
END;
InstantiateSignalType:
PUBLIC
PROC [context:
REF
ANY, name:
ROPE, parms:
REF
ANY]
RETURNS [sti: SignalTypeInvocation] =
BEGIN
job: Job ← NARROW[context];
stce: stcEntry ← NARROW[SignalTypeRegistration.signalTypes.Lookup[name]];
IF stce = NIL THEN {[] ← Complain[nullSR, context, "Signal Type %g Undefined", IO.rope[name]]; RETURN [NIL]};
sti ← NEW [SignalTypeInvocationRep ← [nullSR, NIL, [nullSR, name, parms]]];
sti.st ← stce.stc[parms !
TypeConstructionError =>
BEGIN
[] ← Complain[nullSR, context, msg];
sti ← NIL;
CONTINUE;
END;
RuntimeError.
UNCAUGHT =>
BEGIN
msg: IO.STREAM ← IO.ROS[];
stv: AMTypes.TV;
TRUSTED {stv ← AMBridge.TVForSignal[signal]};
PrintTV.Print[tv: stv, put: msg, verbose: TRUE];
[] ← Complain[nullSR, context,
"Signal Type construction %g[%g] died horribly (uncaught signal or error: %g)",
IO.rope[name],
IO.refAny[parms],
IO.rope[IO.RopeFromROS[msg]]];
sti ← NIL;
CONTINUE;
END];
END;
Setup:
PROC =
BEGIN
versionStream: IO.STREAM ← FS.StreamOpen["RoseTranslator.Version"];
[] ← versionStream.SkipWhitespace[];
versionString ← versionStream.GetLineRope[];
versionStream.Close[];
Commander.Register["RoseTranslate", TranslateCmd, "Translates rosemary sources (.Rose) into Mesa files"];
END;
Setup[];
END.