<> <> DIRECTORY AMBridge, AMTypes, Ascii, Asserting, AssertingIO, Atom, Basics, BasicTime, BitTwiddling, 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, RoseTypes, 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]; partsAssertionsExtension: ROPE _ ".partsAssertions"; 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; AddExport: PUBLIC PROC [job: Job, name: ROPE] = BEGIN IF job.exports.Lookup[name] # NIL THEN RETURN; job.exports.Insert[name]; IF NOT job.emptyExports THEN job.exportsStream.PutRope[", "]; job.exportsStream.PutRope[name]; job.emptyExports _ 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; 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.Close[]; job.exportsStream.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], exports: 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[partsAssertionsExtension], 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", IO.rope[versionString]]; TS.EndNode[job.to]; job.to.PutF["--created from %g of %g", 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 "]; job.exportsStream _ TS.CreateOutput[TS.CurOutNode[job.to], "code"]; job.exportsStream.PutRope["EXPORTS "]; 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[partsAssertionsExtension]]]; 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 NOT RoseTypes.Conforming[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.MesaRepAux # NIL THEN st.procs.MesaRepAux[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, SwitchIO, Val] AND AuxKnown[name, cellDef, SimpleIO, Val] THEN to.PutF["ioCreator: Create%gIO, ", IO.rope[name]]; IF AuxKnown[name, cellDef, Drive, Val] THEN to.PutF["driveCreator: Create%gDrive, ", IO.rope[name]]; IF AuxKnown[name, cellDef, State, Val] OR cellDef.initializerSource # NIL THEN to.PutF["initializer: Initialize%g,", IO.rope[name]]; 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 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", "EnumerateVicinity"]; auxClassNames: PUBLIC ARRAY AuxClass OF ROPE _ [SwitchIO: "SwitchIO", SimpleIO: "SimpleIO", State: "State", Drive: "Drive"]; auxValNames: PUBLIC ARRAY AuxVal OF ROPE _ [Ref: "Ref", Rec: "Rec", Val: "Val"]; WriteInterfaceDecls: PUBLIC PROC [job: Job, name, switchIORefTypeName, simpleIORefTypeName: ROPE, cellDef: CellDef, function: BOOL] RETURNS [iCount: CARDINAL] = BEGIN di: DigestedInterface _ cellDef.interfaceLiteral; interface: InterfaceEltList _ di.asList; toSwitchIO, toSimpleIO, toPortType, toPortFile, portConsts: IO.STREAM; firstSimpleBit, firstSwitchBit: CARDINAL _ 0; hasASwitchPort, someSimple, someSwitch: 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 %gSwitchIORec;", IO.rope[switchIORefTypeName], IO.rope[name]]; TS.EndNode[job.to]; job.to.PutF["%gSwitchIORec: TYPE = RECORD [", IO.rope[name]]; TS.EndNode[job.to]; dest _ TS.CurOutNode[job.to]; TS.EndNode[job.to]; toSwitchIO _ TS.CreateOutput[dest, "code"]; job.to.PutF["%g: TYPE = REF %gSimpleIORec;", IO.rope[simpleIORefTypeName], IO.rope[name]]; TS.EndNode[job.to]; job.to.PutF["%gSimpleIORec: TYPE = RECORD [", IO.rope[name]]; TS.EndNode[job.to]; dest _ TS.CurOutNode[job.to]; TS.EndNode[job.to]; toSimpleIO _ TS.CreateOutput[dest, "code"]; IF hasASwitchPort AND cellDef.evals[EnumerateVicinity] # 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 [driveRecordInitialPadding: DriveTagType, drive: PACKED ARRAY %gPort OF DriveLevel];", IO.rope[name], IO.rope[name]]; TS.EndNode[job.to]; job.to.PutF["%gPort: TYPE = {", 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 ie: InterfaceElt _ interface.first; iename: ROPE _ ie.name; simpleBitWidth, switchBitWidth: CARDINAL _ 0; mesaType: Mesa; simpleType, switchType: NodeType; xPhobic: BOOL _ TRUE; instructionsSimple: BOOL _ TRUE; portTypeStream: IO.STREAM _ IO.ROS[]; otherAssertions: Asserting.Assertions _ NIL; toPortFile.PutRope["\n "]; [simpleType, switchType] _ RoseTypes.BothTypes[ie.sti.st]; IF simpleType # NIL THEN { padBits: NAT _ 0; UseSignalType[job, simpleType]; simpleBitWidth _ simpleType.procs.Bits[simpleType].container; mesaType _ simpleType.procs.MesaRepresentation[simpleType]; AddMesa[job, mesaType]; [firstSimpleBit, padBits] _ Layout[firstSimpleBit, simpleBitWidth]; IF someSimple THEN toSimpleIO.PutRope[","] ELSE someSimple _ TRUE; IF padBits # 0 THEN { toSimpleIO.PutF[ "fill%g: [0 .. %g],", IO.int[iCount], IO.int[BitTwiddling.oneLessThanTwoToThe[padBits]]]; TS.EndNode[toSimpleIO]; }; toSimpleIO.PutF["%g: %g", IO.rope[iename], IO.rope[mesaType.mesa]]; TS.EndNode[toSimpleIO]; toPortFile.PutF["%g %g ", IO.card[firstSimpleBit], IO.card[simpleBitWidth]]; } ELSE toPortFile.PutRope["65535 65535 "]; IF switchType # NIL THEN { padBits: NAT _ 0; UseSignalType[job, switchType]; switchBitWidth _ switchType.procs.Bits[switchType].container; mesaType _ switchType.procs.MesaRepresentation[switchType]; AddMesa[job, mesaType]; [firstSwitchBit, padBits] _ Layout[firstSwitchBit, switchBitWidth]; IF someSwitch THEN toSwitchIO.PutRope[","] ELSE someSwitch _ TRUE; IF padBits # 0 THEN { toSwitchIO.PutF[ "fill%g: [0 .. %g],", IO.int[iCount], IO.int[BitTwiddling.oneLessThanTwoToThe[padBits]]]; TS.EndNode[toSwitchIO]; }; toSwitchIO.PutF["%g: %g", IO.rope[iename], IO.rope[mesaType.mesa]]; TS.EndNode[toSwitchIO]; toPortFile.PutF["%g %g ", IO.card[firstSwitchBit], IO.card[switchBitWidth]]; } ELSE toPortFile.PutRope["65535 65535 "]; toPortFile.PutF["%g ", 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 instructionsSimple THEN 8 ELSE 0)]]; 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; $SimpleInstructions => instructionsSimple _ TRUE; $SwitchInstructions => instructionsSimple _ FALSE; $Special, $General => Whimper[ie.sr, job, "Found old assertion (Special or General)"]; ENDCASE => otherAssertions _ CONS[ll.first, otherAssertions]; ENDLOOP; AssertingIO.Write[to: toPortFile, assertions: otherAssertions]; IF iCount > 0 THEN toPortType.PutRope[", "]; toPortType.PutRope[iename]; IF (NOT ie.sti.st.simple) AND (cellDef.evals[EnumerateVicinity] # NIL) THEN { portConsts.PutF["%g%gPortIndex: CARDINAL = %g;", IO.rope[name], IO.rope[InitialCap[iename]], IO.card[iCount]]; TS.EndNode[portConsts]}; firstSimpleBit _ firstSimpleBit + simpleBitWidth; firstSwitchBit _ firstSwitchBit + switchBitWidth; iCount _ iCount + 1; ENDLOOP; toSimpleIO.PutRope["];"]; toSimpleIO.Close[]; toSwitchIO.PutRope["];"]; toSwitchIO.Close[]; FOR n: NAT _ iCount, n+1 WHILE (n MOD DriveLevelsPerWord) # 0 DO toPortType.PutF[", %gPortTypePad%g", IO.rope[name], IO.int[n]]; ENDLOOP; toPortType.PutRope["};"]; toPortType.Close[]; SS.CloseThrough[toPortFile]; END; bpw: NAT = Basics.bitsPerWord; Layout: PROC [firstAvail, width: NAT] RETURNS [firstUsed, padBits: NAT] = { rem: NAT _ (firstAvail+width) MOD bpw; IF firstAvail MOD bpw # 0 THEN ERROR; padBits _ IF rem # 0 THEN bpw-rem ELSE 0; firstUsed _ firstAvail + padBits; }; 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.