Index:
PUBLIC
PROC [node: Tree.Index]
RETURNS [Lexeme] =
BEGIN -- generates code for array indexing
arrayType: CSEIndex = P5U.OperandType[tb[node].son[1]];
grain, tBits: BitCount;
packed: BOOL;
elementWords: OpWordCount;
indexRange: LONG CARDINAL;
owd: CARDINAL;
delta: INTEGER;
t2: Tree.Link;
base, index, offset: VarComponent;
er: IndVarIndex;
bar: BoVarIndex ← P5L.MakeBo[P5L.VarForLex[P5.Exp[tb[node].son[1]]]];
IF bar = VarNull
THEN
SIGNAL CPtr.CodeNotImplemented; -- no packed arrays of arrays
base ← cb[bar].base; offset ← cb[bar].offset;
WITH a: seb[arrayType]
SELECT
FROM
array =>
BEGIN
grain ← SymbolOps.BitsPerElement[a.componentType, a.packed];
packed ← grain < wordLength;
elementWords ← IF packed THEN 1 ELSE OpWordCount[grain/wordLength];
indexRange ← SymbolOps.Cardinality[a.indexType];
END;
ENDCASE => ERROR;
IF packed
AND (tBits ← indexRange*grain)
IN (0..wordLength)
THEN
BEGIN
fieldSize: CARDINAL = offset.wSize*wordLength + offset.bSize;
IF tBits < fieldSize
THEN
P5L.ModComponent[var: @offset, wd: 0, bd: fieldSize-tBits];
END;
WITH oo: offset
SELECT
FROM
frame =>
BEGIN
IF oo.level # Symbols.lZ THEN ERROR;
IF packed
THEN
BEGIN
ScaleComponent[@offset, PackedBitCount[grain]];
offset.wSize ← 0; offset.bSize ← grain;
END
ELSE
BEGIN
IF oo.bd # 0
OR offset.bSize # 0
THEN
ERROR; -- arrays start on word boundaries and are words long
offset.wSize ← elementWords;
END;
owd ← oo.wd;
END;
code =>
BEGIN -- this gets cross jumped
IF packed
THEN
BEGIN
ScaleComponent[@offset, PackedBitCount[grain]];
offset.wSize ← 0; offset.bSize ← grain;
END
ELSE
BEGIN
IF oo.bd # 0
OR offset.bSize # 0
THEN
ERROR; -- arrays start on word boundaries and are words long
offset.wSize ← elementWords;
END;
owd ← oo.wd;
END;
ENDCASE => ERROR;
[t2, delta] ← CheckAdditivity[tb[node].son[2], elementWords, owd];
P5L.ModComponent[var: @offset, wd: INTEGER[elementWords] * delta];
index ← P5L.ComponentForLex[P5.Exp[t2]];
WITH ii: index
SELECT
FROM
const =>
BEGIN
co: LONG CARDINAL = LongMult[elementWords, ii.d1];
IF co + owd.LONG > OpWordCount.LAST THEN GO TO tooBig;
P5L.ModComponent[var: @offset, wd: co];
IF packed THEN UnscaleComponent[@offset, PackedBitCount[grain]];
cb[bar].offset ← offset;
RETURN [[bdo[bar]]]
END;
ENDCASE;
P5L.ReleaseVarItem[bar];
er ← LOOPHOLE[P5L.GenVarItem[ind]];
cb[er] ← [body: ind[base: base, index: index, offset: offset,
simple: TRASH, packinfo: TRASH]];
IF packed
THEN
BEGIN
cb[er].simple ← indexRange # 0 AND grain*(owd+indexRange) <= 4096;
cb[er].packinfo ← packed[grain: PackedBitCount[grain]];
END
ELSE
BEGIN
cb[er].simple ←
(P5L.Words[base.wSize, base.bSize] = 1)
OR
(indexRange # 0 AND elementWords*indexRange <= OpWordCount.LAST.LONG+1);
cb[er].packinfo ← notPacked[elementWords];
END;
RETURN [[bdo[er]]]
END;
DIndex:
PUBLIC
PROC [node: Tree.Index]
RETURNS [Lexeme] =
BEGIN -- generates code for indexing from an array descriptor
arrayDType: CSEIndex = SymbolOps.NormalType[P5U.OperandType[tb[node].son[1]]];
arrayType: CSEIndex =
WITH seb[arrayDType]
SELECT
FROM
arraydesc => SymbolOps.UnderType[describedType],
ENDCASE => ERROR;
grain: BitCount;
packed: BOOL;
elementWords: OpWordCount;
nilck: BOOL = tb[node].attr1;
long: BOOL = tb[node].attr2;
pLength: CARDINAL = IF long THEN 2 ELSE 1;
bndck: BOOL = tb[node].attr3;
owd: CARDINAL;
delta: CARDINAL ← 0;
t2: Tree.Link;
rBase, rBound: VarIndex;
base, bound, index: VarComponent;
offset: frame VarComponent;
er: IndVarIndex;
WITH a:seb[arrayType]
SELECT
FROM
array =>
BEGIN
grain ← SymbolOps.BitsPerElement[a.componentType, a.packed];
packed ← grain < wordLength;
elementWords ← IF packed THEN 1 ELSE OpWordCount[grain/wordLength];
END
ENDCASE => ERROR;
IF packed THEN offset ← [bSize: grain, space: frame[wd: 0]]
ELSE offset ← [wSize: elementWords, space: frame[wd: 0]];
rBase ← P5L.VarForLex[P5.Exp[tb[node].son[1]]];
IF bndck
THEN
BEGIN
IF nilck THEN [first: rBase, next: rBound] ← P5L.ReusableCopies[rBase, load, TRUE]
ELSE [first: rBound, next: rBase] ← P5L.ReusableCopies[rBase, load, TRUE];
P5L.FieldOfVar[r: rBound, wd: pLength, wSize: 1];
P5L.FieldOfVar[r: rBase, wSize: pLength];
END
ELSE P5L.FieldOfVarOnly[r: rBase, wSize: pLength];
base ← P5L.MakeComponent[rBase];
IF nilck
THEN
BEGIN
P5L.LoadComponent[base];
P5U.Out0[IF long THEN FOpCodes.qNILCKL ELSE FOpCodes.qNILCK];
base ← P5L.TOSComponent[pLength];
END;
IF bndck THEN t2 ← tb[node].son[2]
ELSE [t2, delta] ← CheckAdditivity[tb[node].son[2], elementWords, 0];
offset.wd ← owd ← elementWords*delta; -- elementWords = 1 if packed
index ← P5L.ComponentForLex[P5.Exp[t2]];
IF bndck
THEN
BEGIN
bound ← P5L.MakeComponent[rBound];
P5L.LoadBoth[@index, @bound, FALSE];
P5U.Out0[FOpCodes.qBNDCK];
index ← P5L.TOSComponent[1];
END
ELSE
WITH ii: index
SELECT
FROM
const =>
BEGIN
bar: VarIndex;
co: LONG CARDINAL = LongMult[elementWords, ii.d1];
IF co + owd.LONG > OpWordCount.LAST THEN GO TO tooBig;
P5L.ModComponent[var: @offset, wd: co];
IF packed THEN UnscaleComponent[@offset, PackedBitCount[grain]];
bar ← P5L.GenVarItem[bo];
cb[bar] ← [body: bo[base: base, offset: offset]];
RETURN [[bdo[bar]]]
END;
ENDCASE;
er ← LOOPHOLE[P5L.GenVarItem[ind]];
cb[er] ← [body: ind[base: base, index: index, offset: offset,
simple: TRASH, packinfo: TRASH]];
IF packed
THEN {cb[er].simple ← FALSE; cb[er].packinfo ← packed[grain: PackedBitCount[grain]]}
ELSE {cb[er].simple ← ~long; cb[er].packinfo ← notPacked[elementWords]};
RETURN [[bdo[er]]]
END;
SeqIndex:
PUBLIC
PROC [node: Tree.Index]
RETURNS [Lexeme] =
BEGIN
seqType: CSEIndex = P5U.OperandType[tb[node].son[1]];
isString: BOOL ← FALSE;
grain: BitCount;
packed: BOOL;
elementWords: OpWordCount;
indexRange: LONG CARDINAL;
long: BOOL = tb[node].attr2;
bndck: BOOL = tb[node].attr3;
owd: CARDINAL;
rBound, bor: BoVarIndex;
base, offset, index: VarComponent;
er: IndVarIndex;
WITH ss: seb[seqType]
SELECT
FROM
array =>
BEGIN
isString ← packed ← TRUE; grain ← Symbols.ByteLength;
elementWords ← 1;
indexRange ← SymbolOps.Cardinality[ss.indexType];
END;
sequence =>
BEGIN
grain ← SymbolOps.BitsPerElement[ss.componentType, ss.packed];
packed ← grain < wordLength;
elementWords ← IF packed THEN 1 ELSE OpWordCount[grain/wordLength];
indexRange ← SymbolOps.Cardinality[seb[ss.tagSei].idType];
IF bndck THEN P5.AdjustNilCheck[tb[node].son[1], WordOffset[ss.tagSei]];
END;
ENDCASE => ERROR;
bor ← P5L.MakeBo[P5L.VarForLex[P5.Exp[tb[node].son[1]]]];
IF bor = VarNull
THEN
SIGNAL CPtr.CodeNotImplemented; -- no packed arrays of sequences
IF bndck
THEN
BEGIN
[first:
LOOPHOLE[bor, VarIndex], next:
LOOPHOLE[rBound, VarIndex]] ←
P5L.ReusableCopies[bor, load, FALSE];
P5L.LoadComponent[cb[bor].base];
cb[bor].base ← P5L.TOSComponent[IF long THEN 2 ELSE 1];
END;
IF isString
THEN
BEGIN
IF bndck
THEN
WITH vv: cb[rBound].offset
SELECT
FROM
frame => {vv.wd ← vv.wd - 1; vv.wSize ← 1}; -- maxlength precedes text
ENDCASE => ERROR;
END
ELSE P5L.FieldOfVar[
r: bor, wd: cb[bor].offset.wSize, bd: cb[bor].offset.bSize]; -- skip tag
base ← cb[bor].base; offset ← cb[bor].offset;
IF packed THEN {offset.bSize ← grain; offset.wSize ← 0}
ELSE {offset.wSize ← elementWords; offset.bSize ← 0};
WITH vv: offset
SELECT
FROM
frame =>
BEGIN
IF packed THEN ScaleComponent[@offset, PackedBitCount[grain]];
owd ← vv.wd;
END;
ENDCASE => ERROR;
IF bndck
THEN
BEGIN
P5.PushRhs[tb[node].son[2]];
P5L.LoadVar[rBound];
P5U.Out0[FOpCodes.qBNDCK];
index ← P5L.TOSComponent[1];
END
ELSE
BEGIN
t2: Tree.Link;
delta: INTEGER;
[t2, delta] ← CheckAdditivity[tb[node].son[2], elementWords, owd];
P5L.ModComponent[var: @offset, wd: INTEGER[elementWords] * delta];
index ← P5L.ComponentForLex[P5.Exp[t2]];
END;
WITH ii: index
SELECT
FROM
const =>
BEGIN
co: LONG CARDINAL = LongMult[elementWords, ii.d1];
IF co + owd.LONG > OpWordCount.LAST THEN GO TO tooBig;
P5L.ModComponent[var: @offset, wd: co];
IF packed THEN UnscaleComponent[@offset, PackedBitCount[grain]];
cb[bor].offset ← offset;
RETURN [[bdo[bor]]]
END;
ENDCASE;
P5L.ReleaseVarItem[bor];
er ← LOOPHOLE[P5L.GenVarItem[ind]];
cb[er] ← [body: ind[base: base, index: index, offset: offset,
simple: TRASH, packinfo: TRASH]];
IF packed
THEN
BEGIN
cb[er].simple ← indexRange # 0 AND grain*(owd+indexRange) <= 4096;
cb[er].packinfo ← packed[grain: PackedBitCount[grain]];
END
ELSE
BEGIN
cb[er].simple ←
(P5L.Words[base.wSize, base.bSize] = 1)
OR
(indexRange # 0 AND elementWords*indexRange <= OpWordCount.LAST.LONG+1);
cb[er].packinfo ← notPacked[elementWords];
END;
RETURN [[bdo[er]]]
END;