<> <> DIRECTORY Atom, FS, Basics, BasicTime, IO, Mnemonics, Rope, RoseTranslateTypes, RoseTypes, SignalTypeRegistration, VFonts; MnemonicsImpl: CEDAR PROGRAM IMPORTS Atom, FS, Basics, BasicTime, IO, Rope, RoseTranslateTypes, SignalTypeRegistration, VFonts EXPORTS Mnemonics = BEGIN ROPE: TYPE = Rope.ROPE; WordPtr: TYPE = RoseTypes.WordPtr; NodeType: TYPE = RoseTypes.NodeType; NodeTypeRep: TYPE = RoseTypes.NodeTypeRep; Format: TYPE = RoseTypes.Format; Node: TYPE = RoseTypes.Node; NodeTestProc: TYPE = RoseTypes.NodeTestProc; NodeTestData: TYPE = RoseTypes.NodeTestData; MnemData: TYPE = REF MnemDataRep; MnemDataRep: TYPE = RECORD [ fileSinceEpoch: LONG CARDINAL, bits: CARDINAL, name, mesaType, mesaTypeDecl: ROPE, members: SEQUENCE length: CARDINAL OF ROPE ]; mnemonicProcs: RoseTypes.NodeProcs _ NEW [RoseTypes.NodeProcsRep _ [ Bits: MnemonicBits, MesaUse: MnemonicMesaUse, MesaDefinition: MnemonicMesaDefinition, UserDescription: MnemonicUserDescription, MesaDescription: MnemonicMesaDescription, ListFormats: MnemonicListFormats, GetFormat: MnemonicGetFormat]]; ConstructMnemonic: RoseTranslateTypes.NodeTypeConstructor--PROC [parms: REF ANY - -UNION [BindingList, Args]- -] RETURNS [type: NodeType]-- = BEGIN name: RoseTranslateTypes.Quoted _ NARROW[RoseTranslateTypes.GetParm[n: 1, name: "name", parms: parms]]; type _ Mnemonic[name.rope]; END; Mnemonic: PUBLIC PROC [mnemName: ROPE] RETURNS [nt: NodeType] = BEGIN fileName: ROPE; atom: ATOM; memList: LIST OF ROPE _ NIL; count, newCount, bits: CARDINAL _ 0; file: IO.STREAM; md: MnemData; saturated: BOOLEAN _ FALSE; fileTime: BasicTime.GMT; fileSinceEpoch: LONG CARDINAL; fileExists: BOOLEAN _ TRUE; atom _ Atom.MakeAtom[fileName _ mnemName.Concat[".mnemonics"]]; nt _ NARROW[Atom.GetProp[atom: atom, prop: $mnemonicRoseImpl]]; fileTime _ FS.FileInfo[fileName !FS.Error => {fileExists _ FALSE; CONTINUE}].created; IF NOT fileExists THEN ERROR; fileSinceEpoch _ BasicTime.Period[from: BasicTime.earliestGMT, to: fileTime]; IF nt # NIL THEN BEGIN mnem: MnemData _ NARROW[nt.typeData]; IF fileSinceEpoch = mnem.fileSinceEpoch THEN RETURN; END; file _ FS.StreamOpen[fileName]; [] _ file.SkipWhitespace[flushComments: FALSE]; WHILE NOT file.EndOf[] DO mem: ROPE _ file.GetTokenRope[IO.IDProc].token; newCount: CARDINAL _ count + 1; overlap: CARDINAL _ Basics.BITAND[count, newCount]; IF saturated THEN bits _ bits + 1; saturated _ overlap = 0; count _ newCount; memList _ CONS[mem, memList]; [] _ file.SkipWhitespace[flushComments: FALSE]; ENDLOOP; file.Close[]; md _ NEW [MnemDataRep[count]]; md.fileSinceEpoch _ fileSinceEpoch; md.name _ mnemName; md.bits _ bits; md.mesaType _ mnemName; md.mesaTypeDecl _ "}"; FOR i: CARDINAL DECREASING IN [0 .. md.length) DO md[i] _ memList.first; IF i+1 = md.length THEN md.mesaTypeDecl _ memList.first.Cat[md.mesaTypeDecl] ELSE md.mesaTypeDecl _ memList.first.Cat[", ", md.mesaTypeDecl]; memList _ memList.rest; ENDLOOP; md.mesaTypeDecl _ mnemName.Cat[": TYPE = {", md.mesaTypeDecl]; nt _ NEW [NodeTypeRep _ [ procs: mnemonicProcs, typeData: md, structure: atom[] ]]; Atom.PutProp[atom: atom, prop: $mnemonicRoseImpl, val: nt]; END; MnemonicBits: PROC [nt: NodeType] RETURNS [bits: INTEGER] = {md: MnemData _ NARROW[nt.typeData]; bits _ md.bits}; MnemonicMesaUse: PROC [nt: NodeType] RETURNS [m: RoseTypes.Mesa] = {md: MnemData _ NARROW[nt.typeData]; m _ [md.mesaType]}; MnemonicMesaDefinition: PROC [nt: NodeType] RETURNS [m: RoseTypes.Mesa] = {md: MnemData _ NARROW[nt.typeData]; m _ [md.mesaTypeDecl]}; MnemonicUserDescription: PROC [nt: NodeType] RETURNS [ud: ROPE] = {md: MnemData _ NARROW[nt.typeData]; ud _ Rope.Cat["Mnemonic[\"", md.name, "\"]"]}; MnemonicMesaDescription: PROC [nt: NodeType] RETURNS [m: RoseTypes.Mesa] = {md: MnemData _ NARROW[nt.typeData]; m _ [ mesa: Rope.Cat["Mnemonics.Mnemonic[\"", md.name, "\"]"], imports: LIST["Mnemonics"]]}; MnemonicListFormats: PROC [NodeType] RETURNS [rl: RoseTypes.RopeList] = {rl _ LIST["mnem"]}; MnemonicGetFormat: PROC [NodeType, ROPE] RETURNS [Format] = {RETURN [mnemonicFormat]}; mnemonicFormat: RoseTypes.Format _ NEW [RoseTypes.FormatRep _ [ FormatValue: MnemonicFormatValue, ParseValue: MnemonicParseValue, FormatTest: MnemonicFormatTest, ParseTest: MnemonicParseTest, MaxWidth: MnemonicMaxWidth, formatData: NIL, key: "mnem"]]; MnemonicFormatValue: PROC [node: Node, format: Format, where: WordPtr] RETURNS [rope: ROPE] = BEGIN md: MnemData _ NARROW[node.type.typeData]; index: CARDINAL; TRUSTED {index _ Basics.BITAND[where^, masks[md.bits]]}; RETURN [IF index >= md.length THEN "??" ELSE md[index]]; END; masks: ARRAY [0..16] OF CARDINAL = [0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535]; MnemonicParseValue: PROC [node: Node, format: Format, where: WordPtr, from: IO.STREAM] RETURNS [success: BOOLEAN] = BEGIN md: MnemData _ NARROW[node.type.typeData]; i: CARDINAL; rope: ROPE _ from.GetTokenRope[].token; [i, success] _ Lookup[md, rope]; IF success THEN TRUSTED {where^ _ i}; END; Lookup: PROC [md: MnemData, rope: ROPE] RETURNS [index: CARDINAL, success: BOOLEAN] = BEGIN FOR i: CARDINAL IN [0 .. md.length) DO IF rope.Equal[md[i]] THEN RETURN [i, TRUE]; ENDLOOP; success _ FALSE; index _ 0; END; MnemonicMaxWidth: PROC [nodeType: NodeType, format: Format, font: VFonts.Font] RETURNS [INT] = BEGIN md: MnemData _ NARROW[nodeType.typeData]; mw: INT _ 0; FOR i: CARDINAL IN [0 .. md.length) DO mw _ MAX[mw, VFonts.StringWidth[md[i], font]]; ENDLOOP; RETURN [mw]; END; MnemonicParseTest: PROC [nodeType: NodeType, format: Format, from: IO.STREAM] RETURNS [success: BOOLEAN, testProc: NodeTestProc, testData: NodeTestData] = BEGIN md: MnemData _ NARROW[nodeType.typeData]; i: CARDINAL; rope: ROPE _ from.GetTokenRope[].token; [i, success] _ Lookup[md, rope]; IF success THEN testData _ NEW [CARDINAL _ i] ELSE testData _ NIL; testProc _ TestMnemonic; END; MnemonicFormatTest: PROC [nodeType: NodeType, format: Format, testProc: NodeTestProc, testData: NodeTestData] RETURNS [rope: ROPE] = BEGIN md: MnemData _ NARROW[nodeType.typeData]; rc: REF CARDINAL _ NARROW[testData]; rope _ IF rc = NIL THEN "??" ELSE md[rc^]; END; TestMnemonic: RoseTypes.NodeTestProc--PROC [where: WordPtr, testData: NodeTestData, nodeType: NodeType] RETURNS [passes: BOOLEAN]-- = BEGIN rc: REF CARDINAL _ NARROW[testData]; md: MnemData _ NARROW[nodeType.typeData]; TRUSTED {passes _ rc^ = Basics.BITAND[where^, masks[md.bits]]}; END; SignalTypeRegistration.RegisterNodeTypeConstructor["Mnemonic", ConstructMnemonic]; END.