MnemonicsImpl.Mesa
Last Edited by: Spreitzer, March 10, 1984 1:27:35 pm PST
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 ROPENIL;
count, newCount, bits: CARDINAL ← 0;
file: IO.STREAM;
md: MnemData;
saturated: BOOLEANFALSE;
fileTime: BasicTime.GMT;
fileSinceEpoch: LONG CARDINAL;
fileExists: BOOLEANTRUE;
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 CARDINALNARROW[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 CARDINALNARROW[testData];
md: MnemData ← NARROW[nodeType.typeData];
TRUSTED {passes ← rc^ = Basics.BITAND[where^, masks[md.bits]]};
END;
SignalTypeRegistration.RegisterNodeTypeConstructor["Mnemonic", ConstructMnemonic];
END.