<> <> <> DIRECTORY Ascii, Basics, BasicTime, Convert, FS, IO, OrderedSymbolTableRef, Rope, RoseTranslateTypes, RoseTranslateInsides, TiogaFileOps, TiogaStreams; RoseTranslateWrite: CEDAR PROGRAM IMPORTS Ascii, BasicTime, Convert, FS, IO, OSTR: OrderedSymbolTableRef, Rope, TiogaFileOps, TS: TiogaStreams, RoseTranslateTypes, RoseTranslateInsides EXPORTS RoseTranslateInsides = BEGIN OPEN RoseTranslateTypes, RoseTranslateInsides; WriteInterfaceDecls: PROC [job: Job, name: ROPE, di: DigestedInterface] RETURNS [iCount: CARDINAL] = BEGIN interface: InterfaceEltList _ di.asList; toIO, toDrive, toPortFile, portConsts: IO.STREAM; firstWord: CARDINAL _ 0; dest: TiogaFileOps.Ref; portFileName: ROPE _ job.rootName.Cat[".", name, ".rosePorts"]; iCount _ 0; toPortFile _ FS.StreamOpen[portFileName, create]; TS.EndNode[job.to]; job.to.PutF["Create%gPorts: PROC = {%gPorts _ RoseCreate.PortsFromFile[\"%q\"]};", IO.rope[name], IO.rope[name], IO.rope[portFileName]]; TS.EndNode[job.to]; TS.EndNode[job.to]; toPortFile.PutF["%g", IO.int[di.asTable.Size[]]]; job.to.PutF["%gIORef: TYPE = REF %gIORec;", IO.rope[name], 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"]; 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["%gDrive: TYPE = MACHINE DEPENDENT RECORD [", IO.rope[name]]; TS.EndNode[job.to]; dest _ TS.CurOutNode[job.to]; TS.EndNode[job.to]; toDrive _ 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, special: BOOLEAN _ FALSE; 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; 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]]; Finish[toIO]; toDrive.PutF["fill%g(%g:0..14): [0 .. 32768),", IO.card[iCount], IO.card[iCount]]; TS.EndNode[toDrive]; toDrive.PutF["%g(%g:15..15): BOOLEAN", IO.rope[iename], IO.card[iCount]]; Finish[toDrive]; FOR rl: RopeList _ ie.switches, rl.rest WHILE rl # NIL DO IF rl.first.Equal["X"] THEN xPhobic _ TRUE ELSE IF rl.first.Equal["S"] THEN special _ TRUE ELSE Whimper[job, "Unkown switch %g to port %g of %g", IO.rope[rl.first], IO.rope[iename], IO.rope[name]]; ENDLOOP; toPortFile.PutF[" %g %g %g ", IO.card[firstWord], IO.card[wordWidth], IO.rope[Convert.RopeFromRope[iename]]]; WriteInvocation[toPortFile, ie.sti.invocation]; toPortFile.PutF["!! %g", 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)]]; IF NOT ie.sti.st.simple 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[]; toDrive.PutRope["];"]; toDrive.Close[]; toPortFile.Close[]; 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]]}; TranslatePiece: PROC [job: Job, asAny: REF ANY] = BEGIN IF asAny # error THEN WITH asAny SELECT FROM b: Binding => TranslateCellDef[b, job]; cs: CedarSource => InjectCedar[job, cs]; ENDCASE => [] _ Complain[job, "Got %g when expecting CEDAR or a CELL", IO.refAny[asAny]]; 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[]; 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; TiogaFileOps.Store[job.outRoot, destName _ job.rootName.Concat[".Mesa"]]; --DoMesaFormatting[destName];-- --UserExecExtras.DoIt[job.exec, Rope.Cat["compile ", job.rootName]];-- TiogaFileOps.Store[job.symbolsRoot, job.rootName.Concat[".RoseSymbols"]]; WriteDeps[job]; END; END; TranslateCellDef: PROC [b: Binding, job: Job] = BEGIN name: ROPE _ b.name; cellDef: CellDef _ NARROW[b.value]; IF b.initial # NIL THEN [] _ Complain[job, "Cell Class %g given initial value --- that's nonsense", IO.rope[name]]; RationalizeInitData[job, name, cellDef]; AddInterfaceNodes[job, cellDef]; WriteInterfaceSpec[job, name, cellDef]; WriteRegistration[job, name, cellDef]; IF cellDef.interface.asList # NIL THEN cellDef.portCount _ WriteInterfaceDecls[job, name, cellDef.interface]; IF cellDef.initDataGiven THEN WriteInitData[job, name, cellDef.initDataSource]; IF cellDef.defaultInitDataGiven THEN WriteDefaultInitData[job, name, cellDef.defaultInitDataSource]; IF cellDef.stateGiven THEN WriteState[job, name, cellDef.stateSource]; IF cellDef.expandGiven THEN WriteExpand[job, name, cellDef.expandCode.statements, cellDef]; IF cellDef.interface.asList # NIL THEN WriteIOCreator[job, name, cellDef]; IF cellDef.stateGiven OR cellDef.initializerGiven THEN WriteInitializer[job, name, cellDef.initializerSource, cellDef]; FOR et: EvalType IN EvalType DO IF cellDef.evalsGiven[et] THEN WriteEval[job, name, et, cellDef.evalSources[et], cellDef]; ENDLOOP; IF cellDef.bbTestGiven THEN WriteTest[job, name, FALSE, cellDef.bbTestSource, cellDef]; IF cellDef.stTestGiven THEN WriteTest[job, name, TRUE, cellDef.stTestSource, cellDef]; WritePorts[job, name, cellDef.portCount]; RemoveNodes[job]; AddCellClass[job, NEW [SymbolTableEntryRep[cellClass] _ [name: name, value: cellClass[definedIn: job.rootName, cd: cellDef]]]]; END; RationalizeInitData: PROC [job: Job, className: ROPE, cellDef: CellDef] = BEGIN IF cellDef.defaultInitDataGiven AND cellDef.defaultInitExprGiven THEN Whimper[job, "%g's default init data expression given both implicitly and explicitly", IO.rope[className]] ELSE IF cellDef.defaultInitDataGiven THEN BEGIN cellDef.defaultInitExprGiven _ TRUE; cellDef.defaultInitExpr _ IO.PutFR["%g.default%gInitRef", IO.rope[job.rootName], IO.rope[className]]; END; END; RemoveNodes: PROC [job: Job] = BEGIN DeleteNode: PROC [asAny: REF ANY] RETURNS [stop: BOOLEAN] = BEGIN ste: SymbolTableEntry _ NARROW[asAny]; IF ste.type = node THEN [] _ job.things.Delete[ste]; stop _ FALSE; END; job.things.EnumerateIncreasing[DeleteNode]; END; AddInterfaceNodes: PROC [job: Job, cellDef: CellDef] = BEGIN FOR iel: InterfaceEltList _ cellDef.interface.asList, iel.rest WHILE iel # NIL DO ne: nodeEntry _ NEW [SymbolTableEntryRep[node] _ [name: iel.first.name, value: node[iel.first.sti.st]]]; job.things.Insert[ne]; ENDLOOP; END; WriteInterfaceSpec: PROC [job: Job, name: ROPE, cellDef: CellDef] = BEGIN job.symbolsStream.PutF["%g %g %g %g ", IO.rope[name], IO.rope[job.rootName], IO.card[(IF cellDef.defaultInitExprGiven THEN 1 ELSE 0) + (IF cellDef.initializerGiven THEN 2 ELSE 0) + (IF cellDef.initDataGiven THEN 4 ELSE 0)], IO.refAny[cellDef.defaultInitExpr]]; IF cellDef.interface.asList # NIL THEN WriteInterface[job.symbolsStream, cellDef.interface] ELSE job.symbolsStream.PutRope["NULL"]; job.symbolsStream.PutRope[" !!\n"]; TS.EndNode[job.symbolsStream]; END; WriteInterface: PROC [to: IO.STREAM, interface: DigestedInterface] = BEGIN first: BOOLEAN _ TRUE; to.PutRope["["]; FOR iel: InterfaceEltList _ interface.asList, iel.rest WHILE iel # NIL DO IF first THEN first _ FALSE ELSE to.PutRope[", "]; to.PutF["%g%g", IO.rope[iel.first.name], IO.rope[ways[iel.first.input][iel.first.output]]]; WriteInvocation[to, iel.first.sti.invocation]; ENDLOOP; to.PutRope["]"]; END; ways: ARRAY BOOLEAN OF ARRAY BOOLEAN OF ROPE _ [["??", ">"], ["<", "="]]; WriteInvocation: PROC [to: IO.STREAM, i: Invocation] = BEGIN to.PutRope[i.name]; IF i.parms # NIL THEN BEGIN to.PutRope["["]; WITH i.parms SELECT FROM bl: BindingList => WriteBindingList[to, bl]; a: Args => WriteArgs[to, a]; ENDCASE => ERROR; to.PutRope["]"]; END; END; WriteBindingList: PROC [to: IO.STREAM, bl: BindingList] = BEGIN first: BOOLEAN _ TRUE; FOR bl _ bl, bl.rest WHILE bl # NIL DO IF first THEN first _ FALSE ELSE to.PutRope[", "]; to.PutF["%g:", IO.rope[bl.first.name]]; WriteValue[to, bl.first.value]; ENDLOOP; END; WriteArgs: PROC [to: IO.STREAM, args: Args] = BEGIN first: BOOLEAN _ TRUE; FOR l: LIST OF Arg _ args.args, l.rest WHILE l # NIL DO IF first THEN first _ FALSE ELSE to.PutRope[", "]; WriteValue[to, l.first]; ENDLOOP; END; WriteValue: PROC [to: IO.STREAM, value: REF ANY] = BEGIN WITH value SELECT FROM r: ROPE => to.Put[IO.rope[r]]; q: Quoted => to.Put[IO.rope[Convert.RopeFromRope[q.rope]]]; ri: REF INT => to.Put[IO.int[ri^]]; ENDCASE => ERROR; END; uppers: ARRAY [1..15] OF CARDINAL _ [1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767]; <> <> <> <> <> <> <> <> <> <> <> <<>> <> <> <> < BEGIN>> <> <> <> <> <> <> < BEGIN>> <> <> <> <> <> < ERROR;>> <> <<>> <> <> <> < to.PutF["%q", IO.rope[rope]];>> < to.PutF["%q", IO.rope[Convert.RopeFromRope[quoted.rope]]];>> < to.Put[IO.int[ri^]];>> < ERROR;>> <> WriteInitData: PROC [job: Job, name: ROPE, cs: CedarSource] = BEGIN dest: TiogaFileOps.Ref; TS.EndNode[job.to]; job.to.PutF["%gInitRef: TYPE = REF %gInitRec;", IO.rope[name], IO.rope[name]]; TS.EndNode[job.to]; job.to.PutF["%gInitRec: PUBLIC TYPE = RECORD [", IO.rope[name]]; dest _ TS.CurOutNode[job.to]; TS.ChangeDepth[job.to, 1]; job.to.PutF["];"]; TS.ChangeDepth[job.to, -1]; TS.CopyChildren[from: cs.parent, to: dest]; END; WriteDefaultInitData: PROC [job: Job, name: ROPE, cs: CedarSource] = BEGIN dest: TiogaFileOps.Ref; TS.EndNode[job.to]; job.to.PutF["default%gInitRef: PUBLIC %gInitRef _ NEW [%gInitRec _ [", IO.rope[name], IO.rope[name], IO.rope[name]]; dest _ TS.CurOutNode[job.to]; TS.ChangeDepth[job.to, 1]; job.to.PutF["]];"]; TS.ChangeDepth[job.to, -1]; TS.CopyChildren[from: cs.parent, to: dest]; END; WriteState: PROC [job: Job, name: ROPE, cs: CedarSource] = BEGIN dest: TiogaFileOps.Ref; TS.EndNode[job.to]; job.to.PutF["%gStateRef: TYPE = REF %gStateRec;", IO.rope[name], IO.rope[name]]; TS.EndNode[job.to]; job.to.PutF["%gStateRec: TYPE = RECORD [", IO.rope[name]]; dest _ TS.CurOutNode[job.to]; TS.ChangeDepth[job.to, 1]; job.to.PutF["];"]; TS.ChangeDepth[job.to, -1]; TS.CopyChildren[from: cs.parent, to: dest]; END; WriteIOCreator: PROC [job: Job, name: ROPE, cellDef: CellDef] = BEGIN TS.EndNode[job.to]; job.to.PutF["Create%gIO: IOCreator = {", IO.rope[name]]; TS.ChangeDepth[job.to, 1]; IF cellDef.interface.hasSwitchElt THEN { job.to.PutF["cell.realCellStuff.switchIO _ NEW [%gIORec];", IO.rope[name]]; TS.EndNode[job.to]; }; job.to.PutF["cell.realCellStuff.newIO _ NEW [%gIORec];", IO.rope[name]]; TS.EndNode[job.to]; job.to.PutF["cell.realCellStuff.oldIO _ NEW [%gIORec];", IO.rope[name]]; TS.EndNode[job.to]; job.to.PutRope["};"]; TS.ChangeDepth[job.to, -1]; END; WriteInitializer: PROC [job: Job, name: ROPE, cs: CedarSource, 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.initializerGiven THEN BEGIN job.to.PutF["ioRec: %gIORef _ NARROW[cell.realCellStuff.newIO];", IO.rope[name]]; TS.EndNode[job.to]; opend _ opend.Cat["ioRec"]; IF cellDef.initDataGiven THEN BEGIN job.to.PutF["narrowedInitData: %gInitRef _ NARROW[initData];", IO.rope[name]]; TS.EndNode[job.to]; opend _ opend.Cat[", narrowedInitData"]; END; IF cellDef.stateGiven THEN opend _ opend.Cat[", state"]; END; IF cellDef.stateGiven THEN BEGIN job.to.PutF["state: %gStateRef _ NEW [%gStateRec", IO.rope[name], IO.rope[name]]; IF cellDef.stateInittable THEN job.to.PutRope[" _ []"]; job.to.PutRope["];"]; TS.EndNode[job.to]; job.to.PutRope["cell.realCellStuff.state _ state;"]; TS.EndNode[job.to]; END; IF cellDef.initializerGiven 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: cs.parent, to: dest]; END; job.to.PutRope["END;"]; TS.ChangeDepth[job.to, -1]; job.to.PutRope["};"]; TS.ChangeDepth[job.to, -1]; END; WriteEval: PROC [job: Job, name: ROPE, et: EvalType, cs: CedarSource, cellDef: CellDef] = BEGIN opend: ROPE _ NIL; AddOpen: PROC [o: ROPE] = { opend _ IF opend = NIL THEN o ELSE (opend.Cat[", ", o])}; dest: TiogaFileOps.Ref; 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, index: CARDINAL]" 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 => { AddOpen["sw"]; IF NOT cellDef.interface.hasSwitchElt THEN Whimper[job, "Cell class %g has a %g, but no switch-level interface elements!", IO.rope[name], IO.rope[etNames[et]]]; }; EvalSimple => AddOpen["newIO"]; ENDCASE => ERROR; IF cellDef.interface.hasSwitchElt THEN { job.to.PutF["sw: %gIORef _ NARROW[cell.realCellStuff.switchIO];", IO.rope[name]]; TS.EndNode[job.to]; }; job.to.PutF["newIO: %gIORef _ NARROW[cell.realCellStuff.newIO];", IO.rope[name]]; IF cellDef.stateGiven THEN BEGIN TS.EndNode[job.to]; job.to.PutF["state: %gStateRef _ NARROW[cell.realCellStuff.state];", IO.rope[name]]; 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: cs.parent, to: dest]; job.to.PutRope["END;"]; TS.ChangeDepth[job.to, -1]; END; WriteTest: PROC [job: Job, name: ROPE, stateToo: BOOL, cs: CedarSource, cellDef: CellDef] = BEGIN dest: TiogaFileOps.Ref; TS.EndNode[job.to]; job.to.PutF["%g%gTest: CellTestProc =", IO.rope[name], IO.rope[IF stateToo THEN "ST" ELSE "BB"]]; TS.ChangeDepth[job.to, 1]; job.to.PutRope["BEGIN"]; TS.EndNode[job.to]; job.to.PutF["instructions: %gIORef _ NARROW[io];", IO.rope[name]]; TS.EndNode[job.to]; IF stateToo THEN { job.to.PutF["state: %gStateRef _ NARROW[stateAsAny];", IO.rope[name]]; TS.EndNode[job.to]}; job.to.PutF["drive: REF %gDrive _ NARROW[driveAsAny];", IO.rope[name]]; IF cellDef.initDataGiven THEN BEGIN TS.EndNode[job.to]; job.to.PutF["initRef: %gInitRef _ NARROW[initData];", IO.rope[name]]; END; TS.ChangeDepth[job.to, 1]; job.to.PutRope["BEGIN OPEN "]; IF cellDef.initDataGiven THEN job.to.PutRope["initRef, "]; IF stateToo THEN job.to.PutRope["state, "]; job.to.PutRope["instructions;"]; dest _ TS.CurOutNode[job.to]; TS.EndNode[job.to]; job.to.PutRope["END;"]; TS.ChangeDepth[job.to, -1]; TS.CopyChildren[from: cs.parent, to: dest]; job.to.PutRope["END;"]; TS.ChangeDepth[job.to, -1]; END; WriteExpand: PROC [job: Job, name: ROPE, ec: LORA, cellDef: CellDef] = BEGIN TS.EndNode[job.to]; job.to.PutF["%gExpand: ExpandProc = {", IO.rope[name]]; TS.ChangeDepth[job.to, 1]; IF cellDef.initDataGiven THEN BEGIN job.to.PutF["initRef: %gInitRef _ NARROW[initData];", IO.rope[name]]; TS.ChangeDepth[job.to, 1]; job.to.PutRope["BEGIN OPEN initRef;"]; TS.EndNode[job.to]; END; IF cellDef.interface.asList # NIL THEN { job.to.PutRope["PrivateLookupNode: PROC [name: ROPE] RETURNS [node: Node] = {node _ RoseCreate.LookupNode[from: thisCell, path: LIST[name]]};"]; TS.EndNode[job.to]; }; FOR iel: InterfaceEltList _ cellDef.interface.asList, iel.rest WHILE iel # NIL DO job.to.PutF[ "%g: Node _ PrivateLookupNode[\"%g\"];", IO.rope[iel.first.name], IO.rope[iel.first.name]]; TS.EndNode[job.to]; ENDLOOP; job.nodeCreateHacks _ OSTR.CreateTable[CompareNCHs]; job.nchCount _ 0; job.previewing _ TRUE; FOR lora: LORA _ ec, lora.rest WHILE lora # NIL DO WriteBinding: PROC [b: Binding] = BEGIN WITH b.value SELECT FROM sti: SignalTypeInvocation => WriteNodeInstance[job, b.name, sti.st, b.initial]; a: Application => WriteCellInstance[job, b.name, a]; r: ROPE => WriteWhateverInstance[job, b.name, r, b.initial]; ENDCASE => ERROR; END; WITH lora.first SELECT FROM cs: CedarSource => NULL; bl: BindingList => FOR bl _ bl, bl.rest WHILE bl # NIL DO WriteBinding[bl.first] ENDLOOP; b: Binding => WriteBinding[b]; ENDCASE => ERROR; ENDLOOP; job.previewing _ FALSE; FOR lora: LORA _ ec, lora.rest WHILE lora # NIL DO WriteBinding: PROC [b: Binding] = BEGIN WITH b.value SELECT FROM sti: SignalTypeInvocation => WriteNodeInstance[job, b.name, sti.st, b.initial]; a: Application => WriteCellInstance[job, b.name, a]; r: ROPE => WriteWhateverInstance[job, b.name, r, b.initial]; ENDCASE => ERROR; END; WITH lora.first SELECT FROM cs: CedarSource => InjectCedar[job, cs]; bl: BindingList => FOR bl _ bl, bl.rest WHILE bl # NIL DO WriteBinding[bl.first] ENDLOOP; b: Binding => WriteBinding[b]; ENDCASE => ERROR; ENDLOOP; IF cellDef.initDataGiven THEN BEGIN job.to.PutRope["END;"]; TS.ChangeDepth[job.to, -1]; END; job.to.PutRope["};"]; TS.ChangeDepth[job.to, -1]; END; InjectCedar: PROC [job: Job, cs: CedarSource] = BEGIN where: TiogaFileOps.Ref; TS.EndNode[job.to]; job.to.PutRope["--explicitly requested CEDAR:"]; TS.EndNode[job.to]; where _ TS.CurOutNode[job.to]; TS.EndNode[job.to]; TS.CopyChildren[from: cs.parent, to: where]; END; NodeCreateHack: TYPE = REF NodeCreateHackRep; NodeCreateHackRep: TYPE = RECORD [ key, name: ROPE, callCount: CARDINAL]; CompareNCHs: PROC [r1, r2: REF ANY] RETURNS [c: Basics.Comparison] = BEGIN Key: PROC [r: REF ANY] RETURNS [k: ROPE] = {k _ WITH r SELECT FROM x: ROPE => x, nch: NodeCreateHack => nch.key, ENDCASE => ERROR}; c _ Key[r1].Compare[Key[r2]]; END; WriteNodeInstance: PROC [job: Job, name: ROPE, st: NodeType, initialValue: ROPE] = BEGIN IF job.previewing THEN BEGIN roseType: Mesa _ st.procs.MesaDescription[st]; key: ROPE _ IO.PutFR["\"%q\" _ %g", IO.rope[roseType.mesa], IO.refAny[initialValue]]; nch: NodeCreateHack _ NARROW[job.nodeCreateHacks.Lookup[key]]; IF nch = NIL THEN job.nodeCreateHacks.Insert[nch _ NEW [NodeCreateHackRep _ [ key: key, name: NIL, callCount: 0]]]; nch.callCount _ nch.callCount + 1; END ELSE BEGIN roseType: Mesa _ st.procs.MesaDescription[st]; key: ROPE _ IO.PutFR["\"%q\" _ %g", IO.rope[roseType.mesa], IO.refAny[initialValue]]; nch: NodeCreateHack _ NARROW[job.nodeCreateHacks.Lookup[key]]; ne: nodeEntry _ NEW [SymbolTableEntryRep[node] _ [name: name, value: node[st]]]; IF job.things.Lookup[name] = NIL THEN job.things.Insert[ne] ELSE Whimper[job, "node %g multiply defined", IO.rope[name]]; AddMesa[job, roseType]; IF nch.callCount >= nodeCreateHackThreshold THEN BEGIN IF nch.name = NIL THEN BEGIN nch.name _ IO.PutFR["NodeCreateHack%g", IO.card[job.nchCount _ job.nchCount + 1]]; job.to.PutF["%g: PROC [name: ROPE] RETURNS [node: Node] = {node _ RoseCreate.CreateNode[within: thisCell, name: name, type: %g", IO.rope[nch.name], IO.rope[roseType.mesa]]; IF initialValue # NIL THEN job.to.PutF[", initialValue: \"%q\"", IO.rope[initialValue]]; job.to.PutRope["]};"]; TS.EndNode[job.to]; END; job.to.PutF["%g: Node _ %g[\"%g\"", IO.rope[name], IO.rope[nch.name], IO.rope[name]]; END ELSE BEGIN job.to.PutF["%g: Node _ RoseCreate.CreateNode[within: thisCell, name: \"%g\", type: %g", IO.rope[name], IO.rope[name], IO.rope[roseType.mesa]]; IF initialValue # NIL THEN job.to.PutF[", initialValue: \"%q\"", IO.rope[initialValue]]; END; job.to.PutRope["];"]; TS.EndNode[job.to]; END; END; nodeCreateHackThreshold: CARDINAL _ 3; 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; WriteCellInstance: PROC [job: Job, instanceName: ROPE, a: Application] = BEGIN ste: SymbolTableEntry _ NARROW[job.things.Lookup[a.fn]]; cd: CellDef; definedIn: ROPE; fromSelf: BOOLEAN; IF job.previewing THEN RETURN; IF ste = NIL THEN BEGIN [] _ Complain[job, "Cell Class %g undefined!", IO.rope[a.fn]]; cd _ NEW [CellDefRep _ []]; definedIn _ NIL; IF a.fn # NIL THEN AddCellClass[job, NEW [SymbolTableEntryRep[cellClass] _ [name: a.fn, value: cellClass[definedIn: definedIn, cd: cd]]]]; END ELSE WITH ste SELECT FROM cce: ccEntry => {definedIn _ cce.definedIn; cd _ cce.cd}; ENDCASE => BEGIN [] _ Complain[job, "Can't instantiate %g like a Cell Class", IO.refAny[ste]]; definedIn _ NIL; cd _ NEW [CellDefRep _ []]; END; fromSelf _ definedIn.Equal[job.rootName, FALSE]; job.to.PutF["[] _ RoseCreate.CreateCell[within: thisCell, instanceName: \"%g\", className: \"%g\", interfaceNodes: ", IO.rope[instanceName], IO.rope[a.fn]]; IF definedIn # NIL THEN TypeCheck[job, a.args, cd.interface, instanceName]; IF a.args # NIL THEN BEGIN job.to.PutRope["\""]; WITH a.args SELECT FROM bl: BindingList => WriteBindingList[job.to, bl]; a: Args => WriteArgs[job.to, a]; ENDCASE => ERROR; job.to.PutRope["\""]; END ELSE job.to.PutRope["NIL"]; IF a.initData # NIL THEN job.to.PutF[", initData: %g", IO.rope[a.initData]] ELSE IF cd.initDataGiven AND cd.initializerGiven THEN BEGIN IF cd.defaultInitExprGiven THEN BEGIN job.to.PutF[", initData: %g", IO.rope[cd.defaultInitExpr]]; END ELSE Whimper[job, "%g must be given init data", IO.rope[instanceName]]; END; job.to.PutRope["];"]; TS.EndNode[job.to]; IF definedIn # NIL AND NOT fromSelf THEN AddImport[job, definedIn]; END; WriteWhateverInstance: PROC [job: Job, name, class, initialValue: ROPE] = BEGIN sti: SignalTypeInvocation _ InstantiateSignalType[job, class, NIL]; IF sti # NIL THEN WriteNodeInstance[job, name, sti.st, initialValue]; END; WritePorts: PROC [job: Job, name: ROPE, count: CARDINAL] = BEGIN TS.EndNode[job.to]; job.to.PutF["%gPorts: Ports _ NEW [PortsRep[%g]];", IO.rope[name], IO.card[count]]; TS.EndNode[job.to]; END; WriteRegistration: PROC [job: Job, name: ROPE, cellDef: CellDef] = BEGIN evalGiven: BOOLEAN _ FALSE; IF cellDef.interface.asList # NIL THEN BEGIN job.regStream.PutF["Create%gPorts[];", IO.rope[name]]; TS.EndNode[job.regStream]; END; job.regStream.PutF["[] _ RoseCreate.RegisterCellClass[className: \"%g\",", IO.rope[name]]; TS.ChangeDepth[job.regStream, 1]; IF cellDef.expandGiven THEN job.regStream.PutF["expandProc: %gExpand,", IO.rope[name]] ELSE job.regStream.PutRope["expandProc: NIL,"]; TS.EndNode[job.regStream]; IF cellDef.interface.asList # NIL THEN job.regStream.PutF["ioCreator: Create%gIO, ", IO.rope[name]] ELSE job.regStream.PutRope["ioCreator: NIL, "]; IF cellDef.stateGiven OR cellDef.initializerGiven THEN job.regStream.PutF["initializer: Initialize%g,", IO.rope[name]] ELSE job.regStream.PutRope["initializer: NIL,"]; TS.EndNode[job.regStream]; job.regStream.PutRope["evals: ["]; FOR et: EvalType IN EvalType DO IF cellDef.evalsGiven[et] THEN { IF evalGiven THEN job.regStream.PutRope[", "] ELSE evalGiven _ TRUE; job.regStream.PutF["%g: %g%g", IO.rope[etNames[et]], IO.rope[name], IO.rope[etNames[et]]]}; ENDLOOP; job.regStream.PutRope["],"]; TS.EndNode[job.regStream]; IF cellDef.bbTestGiven THEN job.regStream.PutF["blackBox: %gBBTest, ", IO.rope[name]] ELSE job.regStream.PutRope["blackBox: NIL, "]; IF cellDef.stTestGiven THEN job.regStream.PutF["stateToo: %gSTTest,", IO.rope[name]] ELSE job.regStream.PutRope["stateToo: NIL,"]; TS.EndNode[job.regStream]; job.regStream.PutF["ports: %gPorts,", IO.rope[name]]; TS.EndNode[job.regStream]; IF cellDef.interface.asList # NIL THEN job.regStream.PutF["drivePrototype: NEW [%gDrive]];", IO.rope[name]] ELSE job.regStream.PutRope["drivePrototype: NIL];"]; TS.ChangeDepth[job.regStream, -1]; END; etNames: ARRAY EvalType OF ROPE = ["ValsChanged", "InitQ", "PropQ", "InitUD", "PropUD", "FinalUD", "EvalSimple", "FindVicinity"]; 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; END.