IntTypesImpl.Mesa, from [Ivy]<Spreitzer>Simulation>NewRose>Rosemary.DF
Last Edited by: Spreitzer, June 14, 1983 10:26 pm
DIRECTORY
Inline, IntTypes, Rope, Rosemary, VFonts;
IntTypesImpl: CEDAR PROGRAM
IMPORTS Inline, Rope, VFonts
EXPORTS IntTypes =
BEGIN OPEN IntTypes;
ROPE: TYPE = Rope.ROPE;
WordPtr: TYPE = Rosemary.WordPtr;
SignalType: TYPE = Rosemary.SignalType;
SignalTypeRep: TYPE = Rosemary.SignalTypeRep;
SignalTypeList: TYPE = LIST OF SignalType;
WordPair: TYPE = ARRAY [0..1] OF CARDINAL;
MaskedValue: TYPE = REF MaskedValueRep;
MaskedValueRep: TYPE = RECORD [m, v: Value];
IntData: TYPE = REF IntDataRep;
IntDataRep: TYPE = RECORD [bits: CARDINAL];
Bit: PUBLIC SignalType;
intTypes: SignalTypeList ← NIL;
decode: ARRAY CHARACTER OF [0..16] ← ALL[16];
encode: ARRAY [0..16) OF ROPEALL[NIL];
lowMask, highMask: ARRAY [1..32] OF CARDINAL;
verboten: ARRAY [0..16) OF CARDINAL ← [0, 65535-1, 65535-3, 65535-7, 65535-15, 65535-31, 65535-63, 65535-127, 65535-255, 65535-511, 65535-1023, 65535-2047, 65535-4095, 65535-8191, 65535-16383, 32768];
IntNot: PUBLIC PROC [bitWidth: [1..32], bits: LONG CARDINAL] RETURNS [inverted: LONG CARDINAL] =
BEGIN
LOOPHOLE[inverted, WordPair][0] ← Inline.BITAND[Inline.BITNOT[LOOPHOLE[bits, WordPair][0]], lowMask[bitWidth]];
LOOPHOLE[inverted, WordPair][1] ← Inline.BITAND[Inline.BITNOT[LOOPHOLE[bits, WordPair][1]], highMask[bitWidth]];
END;
IntType: PUBLIC PROC [bitWidth: CARDINAL] RETURNS [st: SignalType] =
BEGIN
FOR it: SignalTypeList ← intTypes, it.rest WHILE it # NIL DO
id: IntData ← NARROW[it.first.typeData];
IF id.bits = bitWidth THEN RETURN [it.first];
ENDLOOP;
intTypes ← CONS[st ← MakeIntOfWidth[bitWidth], intTypes];
END;
MakeIntOfWidth: PROC [bitWidth: CARDINAL] RETURNS [st: SignalType] =
BEGIN
st ← NEW [SignalTypeRep ← [
toRope: IntToRope,
fromRope: IntFromRope,
init: NIL,
maxWidth: MaxWidthOfInt,
parseTest: TestFromRope,
unParseTest: TestToRope,
typeData: NEW [IntDataRep ← [bitWidth]] ]];
END;
MaxWidthOfInt: Rosemary.MaxWidthProc = TRUSTED
BEGIN
id: IntData ← NARROW[typeData];
RETURN [
--MAX[--
--VFonts.StringWidth["0"]*id.bits + VFonts.StringWidth["B"],--
(VFonts.StringWidth["F", font]*(id.bits+3))/4 + VFonts.StringWidth["H"]
--]--
];
END;
TestFromRope: Rosemary.TestParseProc =
BEGIN
id: IntData ← NARROW[typeData];
wordWidth: CARDINAL ← (id.bits + 15)/16;
base, test: CARDINAL;
dl, sign: INTEGER ← 1;
v: Value ← NEW [ValueRec[0]];
m: Value ← NEW [ValueRec[0]];
IF rope.Length[] < 1 THEN RETURN [FALSE, NIL, NIL]
ELSE BEGIN
SELECT rope.Fetch[rope.Length[] - 1] FROM
'b, 'B => {base ← 2; dl ← 1};
'o, 'O => {base ← 8; dl ← 1};
'd, 'D => {base ← 10; dl ← 1};
'h, 'H => {base ← 16; dl ← 1};
IN ['2..'9] => {base ← 10; dl ← 0};
'A, 'a, 'c, 'C, 'e, 'E, 'f, 'F => {base ← 16; dl ← 0};
ENDCASE => {base ← 2; dl ← 0};
FOR i: CARDINAL IN [0 .. rope.Length[] - dl) DO
c: CHARACTER ← rope.Fetch[i];
v ← Multiply[v, base];
m ← Multiply[m, base];
IF c = 'x OR c = 'X THEN
BEGIN
m ← Add[m, base-1];
END
ELSE BEGIN
d: [0..16] ← decode[c];
IF d > base THEN RETURN [FALSE, NIL, NIL];
v ← Add[v, d];
END;
ENDLOOP;
END;
IF MAX[v.length, m.length] > wordWidth THEN RETURN [FALSE, NIL, NIL];
IF wordWidth < 1 THEN RETURN [FALSE, NIL, NIL];
v ← Truncate[v, wordWidth];
m ← Truncate[m, wordWidth];
test ← Inline.BITAND[v[0], verboten[id.bits MOD 16]];
IF 0 # test THEN RETURN [FALSE, NIL, NIL];
test ← Inline.BITAND[m[0], verboten[id.bits MOD 16]];
IF 0 # test THEN RETURN [FALSE, NIL, NIL];
testData ← NEW [MaskedValueRep ← [m: m, v: v]];
success ← TRUE;
testProc ← TestInt;
END;
TestToRope: Rosemary.TestUnParseProc =
BEGIN
id: IntData ← NARROW[typeData];
mv: MaskedValue ← NARROW[testData];
IF mv = NIL THEN rope ← "??"
ELSE rope ← EncodeMV[mv.m, mv.v, 16, id.bits !CantEncode => {rope ← EncodeMV[mv.m, mv.v, 2, id.bits]; CONTINUE}];
IF subject # NIL THEN rope ← Rope.Cat[subject, "=", rope];
END;
CantEncode: ERROR = CODE;
EncodeMV: PROC [m, v: Value, base: [2..16], bits: CARDINAL] RETURNS [rope: ROPE] =
BEGIN
digits: CARDINAL ← (bits + base - 1)/base;
rope ← IF base = 16 THEN "H" ELSE IF base = 2 THEN "B" ELSE ERROR;
FOR i: CARDINAL IN [1 .. digits] DO
vRem, mRem: CARDINAL;
[v, vRem] ← DivMod[v, base];
[m, mRem] ← DivMod[m, base];
IF mRem = 0 THEN rope ← encode[vRem].Concat[rope]
ELSE IF mRem+1 = base THEN rope ← Rope.Concat["X", rope]
ELSE ERROR CantEncode[];
ENDLOOP;
END;
IntFromRope: Rosemary.FromRopeProc =
BEGIN
id: IntData ← NARROW[typeData];
wordWidth: CARDINAL ← (id.bits + 15)/16;
base, test: CARDINAL;
dl, sign: INTEGER ← 1;
v: Value ← NEW [ValueRec[0]];
IF rope.Length[] < 1 THEN RETURN [FALSE]
ELSE BEGIN
SELECT rope.Fetch[rope.Length[] - 1] FROM
'b, 'B => {base ← 2; dl ← 1};
'o, 'O => {base ← 8; dl ← 1};
'd, 'D => {base ← 10; dl ← 1};
'h, 'H => {base ← 16; dl ← 1};
ENDCASE => {base ← 10; dl ← 0};
FOR i: CARDINAL IN [0 .. rope.Length[] - dl) DO
c: CHARACTER ← rope.Fetch[i];
IF c = '- THEN sign ← -sign
ELSE BEGIN
d: [0..16] ← decode[c];
IF d > base THEN RETURN [FALSE];
v ← Add[Multiply[v, base], d];
END;
ENDLOOP;
END;
IF v.length > wordWidth THEN RETURN [FALSE];
IF wordWidth < 1 THEN RETURN [TRUE];
v ← Truncate[v, wordWidth];
test ← Inline.BITAND[v[0], verboten[id.bits MOD 16]];
IF 0 # test THEN RETURN [FALSE];
ValueToWP[v, where, wordWidth];
success ← TRUE;
END;
IntToRope: Rosemary.ToRopeProc =
BEGIN
id: IntData ← NARROW[typeData];
wordWidth: CARDINAL ← (id.bits + 15)/16;
digits: CARDINAL ← (id.bits + 3)/4;
v: Value ← ValueFromWP[where, wordWidth];
rope ← "H";
FOR i: CARDINAL IN [1 .. digits] DO
rem: CARDINAL;
[v, rem] ← DivMod[v, 16];
rope ← encode[rem].Concat[rope];
ENDLOOP;
END;
TestInt: Rosemary.TestProc = TRUSTED
BEGIN
id: IntData ← NARROW[typeData];
mv: MaskedValue ← NARROW[testData];
other: CARDINAL ← verboten[id.bits MOD 16];
wordCount: CARDINAL ← (id.bits+15)/16;
wmo: CARDINAL ← wordCount - 1;
IF wordCount < 1 THEN ERROR;
IF wordCount # mv.v.length THEN RETURN [FALSE];
IF wordCount # mv.m.length THEN RETURN [FALSE];
FOR i: CARDINAL IN [0..wordCount) DO
diff: CARDINAL ← Inline.BITXOR[mv.v[wmo - i], (where+i)^];
diff ← Inline.BITAND[diff, Inline.BITNOT[Inline.BITOR[other, mv.m[i]]]];
IF diff # 0 THEN RETURN [FALSE];
other ← 0;
ENDLOOP;
passes ← TRUE;
END;
ValueToWP: PROC [v: Value, wp: WordPtr, words: CARDINAL] = TRUSTED
BEGIN
wmo: CARDINAL ← words - 1;
IF words < 1 THEN ERROR;
FOR i: CARDINAL IN [0..words) DO (wp+i)^ ← v[wmo - i] ENDLOOP;
END;
ValueFromWP: PROC [wp: WordPtr, words: CARDINAL] RETURNS [v: Value] = TRUSTED
BEGIN
wmo: CARDINAL ← words - 1;
IF words < 1 THEN ERROR;
v ← NEW [ValueRec[words]];
FOR i: CARDINAL IN [0..words) DO v[wmo - i] ← (wp+i)^ ENDLOOP;
END;
Value: TYPE = REF ValueRec;
ValueRec: TYPE = RECORD [chunks: SEQUENCE length: CARDINAL OF CARDINAL];
increasing index <=> decreasing significance
Multiply: PROC [v: Value, f: CARDINAL] RETURNS [p: Value] =
BEGIN
prod: LONG CARDINAL ← 0;
p ← NEW [ValueRec[v.length + 1]];
FOR i: CARDINAL DECREASING IN [0..p.length) DO
IF i > 0 THEN prod ← prod + LONG[v[i-1]] * f;
p[i] ← prod MOD 65536;
prod ← prod / 65536;
ENDLOOP;
p ← Truncate[p, Significance[p]];
END;
DivMod: PROC [v: Value, d: CARDINAL] RETURNS [q: Value, rem: CARDINAL] =
BEGIN
r: LONG CARDINAL ← 0;
q ← NEW[ValueRec[v.length]];
FOR i: CARDINAL IN [0..v.length) DO
prod: LONG CARDINAL ← d;
r ← r * 65536 + v[i];
q[i] ← r/d;
r ← r - prod * q[i];
ENDLOOP;
rem ← r;
q ← Truncate[q, Significance[q]];
END;
Add: PROC [v: Value, s: CARDINAL] RETURNS [w: Value] =
BEGIN
carry: LONG CARDINAL ← s;
w ← NEW[ValueRec[v.length + 1]];
FOR i: CARDINAL DECREASING IN [0..w.length) DO
IF i > 0 THEN carry ← carry + v[i-1];
w[i] ← carry MOD 65536;
carry ← carry / 65536;
ENDLOOP;
w ← Truncate[w, Significance[w]];
END;
Significance: PROC [v: Value] RETURNS [s: CARDINAL] =
BEGIN
FOR s IN [0..v.length) DO
IF v[s] # 0 THEN RETURN [v.length - s];
ENDLOOP;
s ← 0;
END;
Truncate: PROC [v: Value, len: CARDINAL] RETURNS [w: Value] =
BEGIN
w ← NEW [ValueRec[len]];
FOR i: CARDINAL IN (0..len] DO
w[len - i] ← IF i <= v.length THEN v[v.length - i] ELSE 0;
ENDLOOP;
END;
Setup: PROC =
BEGIN
n: CARDINAL ← 1;
lowMask ← ALL[65535];
highMask ← ALL[0];
FOR i: CARDINAL IN [1 .. 16] DO
highMask[16+i] ← lowMask[i] ← n;
n ← n + n + 1;
ENDLOOP;
FOR c: CARDINAL IN [0..9] DO
decode['0 + c] ← c;
ENDLOOP;
FOR c: CARDINAL IN [0..5] DO
decode['A + c] ← 10 + c;
decode['a + c] ← 10 + c;
ENDLOOP;
encode ← ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];
Bit ← IntType[1];
END;
Setup[];
END.