MnemonicsImpl.Mesa
Last Edited by: Spreitzer, March 18, 1983 1:07 pm
DIRECTORY
Atom, FileIO, Inline, IO, Mnemonics, Rope, Rosemary, VFonts;
MnemonicsImpl: CEDAR PROGRAM
IMPORTS Atom, FileIO, Inline, IO, Rope, VFonts
EXPORTS Mnemonics =
BEGIN
ROPE: TYPE = Rope.ROPE;
WordPtr: TYPE = Rosemary.WordPtr;
SignalType: TYPE = Rosemary.SignalType;
SignalTypeRep: TYPE = Rosemary.SignalTypeRep;
MnemData: TYPE = REF MnemDataRep;
MnemDataRep: TYPE = RECORD [
bits: CARDINAL,
members: SEQUENCE length: CARDINAL OF ROPE
];
Mnemonic: PUBLIC PROC [mnemName: ROPE] RETURNS [st: SignalType] =
BEGIN
fileName: ROPE;
atom: ATOM;
memList: LIST OF ROPENIL;
count, newCount, bits: CARDINAL ← 0;
file: IO.STREAM;
md: MnemData;
saturated: BOOLEANFALSE;
atom ← Atom.MakeAtom[fileName ← mnemName.Concat[".mnemonics"]];
st ← NARROW[Atom.GetProp[atom: atom, prop: $mnemonicRoseImpl]];
IF st # NIL THEN RETURN;
file ← FileIO.Open[fileName];
file.SkipOver[IO.WhiteSpace];
WHILE NOT file.EndOf[] DO
mem: ROPE ← file.GetToken[IO.IDProc];
newCount: CARDINAL ← count + 1;
overlap: CARDINAL ← Inline.BITAND[count, newCount];
IF saturated THEN bits ← bits + 1;
saturated ← overlap = 0;
count ← newCount;
memList ← CONS[mem, memList];
file.SkipOver[IO.WhiteSpace];
ENDLOOP;
file.Close[];
md ← NEW [MnemDataRep[count]];
md.bits ← bits;
FOR i: CARDINAL DECREASING IN [0 .. md.length) DO
md[i] ← memList.first;
memList ← memList.rest;
ENDLOOP;
st ← NEW [Rosemary.SignalTypeRep ← [
toRope: ToRope,
fromRope: FromRope,
init: NIL,
maxWidth: MaxWidth,
parseTest: TestParse,
unParseTest: TestUnParse,
typeData: md]];
Atom.PutProp[atom: atom, prop: $mnemonicRoseImpl, val: st];
END;
ToRope: PROC [where: WordPtr, typeData: REF ANY] RETURNS [rope: ROPE] = TRUSTED
BEGIN
md: MnemData ← NARROW[typeData];
index: CARDINAL ← Inline.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];
FromRope: PROC [rope: ROPE, where: WordPtr, typeData: REF ANY] RETURNS [success: BOOLEAN] = TRUSTED
BEGIN
md: MnemData ← NARROW[typeData];
i: CARDINAL;
[i, success] ← Lookup[md, rope];
IF success THEN 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;
MaxWidth: PROC [typeData: REF ANY, font: VFonts.Font] RETURNS [INTEGER] = TRUSTED
BEGIN
md: MnemData ← NARROW[typeData];
mw: INTEGER ← 0;
FOR i: CARDINAL IN [0 .. md.length) DO
mw ← MAX[mw, VFonts.StringWidth[md[i], font]];
ENDLOOP;
RETURN [mw];
END;
TestParse: Rosemary.TestParseProc =
BEGIN
md: MnemData ← NARROW[typeData];
i: CARDINAL;
[i, success] ← Lookup[md, rope];
IF success THEN testData ← NEW [CARDINAL ← i] ELSE testData ← NIL;
testProc ← TestMnemonic;
END;
TestUnParse: Rosemary.TestUnParseProc =
BEGIN
md: MnemData ← NARROW[typeData];
rc: REF CARDINALNARROW[testData];
rope ← IF rc = NIL THEN "??" ELSE md[rc^];
IF subject # NIL THEN rope ← subject.Cat["=", rope];
END;
TestMnemonic: Rosemary.TestProc = TRUSTED
BEGIN
rc: REF CARDINALNARROW[testData];
passes ← rc^ = where^;
END;
END.