Constructor:
PROGRAM
IMPORTS MPtr: ComData, CPtr: Code, CodeDefs, P5, P5U, PrincOpsUtils, SymbolOps, TreeOps
EXPORTS CodeDefs, P5 = BEGIN OPEN CodeDefs, SymbolOps;
imported definitions
WordSize: CARDINAL = CodeDefs.WordSize;
charlength: CARDINAL = Basics.bitsPerChar;
ArraySEIndex: TYPE = Symbols.ArraySEIndex;
BitAddress: TYPE = Symbols.BitAddress;
BitCount: TYPE = Symbols.BitCount;
ContextLevel: TYPE = Symbols.ContextLevel;
CSEIndex: TYPE = Symbols.CSEIndex;
CTXIndex: TYPE = Symbols.CTXIndex;
ISEIndex: TYPE = Symbols.ISEIndex;
ISENull: ISEIndex = Symbols.ISENull;
lZ: ContextLevel = Symbols.lZ;
lG: ContextLevel = Symbols.lG;
RecordSEIndex: TYPE = Symbols.RecordSEIndex;
SEIndex: TYPE = Symbols.SEIndex;
typeANY: CSEIndex = Symbols.typeANY; -- don't-care type for ConsAssign
tb: Tree.Base; -- tree base (local copy)
seb: Symbols.Base; -- semantic entry base (local copy)
cb: CodeDefs.Base; -- code base (local copy)
stb: Literals.Base; -- string base (local copy)
ConstructorNotify:
PUBLIC Alloc.Notifier =
BEGIN -- called by allocator whenever table area is repacked
seb ← base[Symbols.seType];
stb ← base[Literals.stType];
tb ← base[Tree.treeType];
cb ← base[codeType];
END;
state data and common code for construction
ConstructionError: SIGNAL = CODE;
cd: PUBLIC ConsDestination;
SetConsDest:
PROC [t: Tree.Link, cl: CodeList] =
BEGIN
n: Node;
tv: Var;
cd.cl ← cl;
WITH tt: t
SELECT
FROM
symbol => {
ctx: CTXIndex ← seb[tt.index].idCtx;
level: ContextLevel ← SymbolOps.CtxLevel[ctx];
SELECT level
FROM
lG, CPtr.curctxlvl => {
cd.destNode ← P5.Exp[t];
RETURN};
ENDCASE => NULL;
};
ENDCASE => NULL;
n ← P5.Exp[t];
tv ← P5U.MakeTemp[cl: cl, bits: PtrSize, init: P5U.ApplyOp[oper: P5U.MesaOpNode[addr], args: P5U.MakeNodeList[n], bits: PtrSize]].var;
cd.destNode ← P5U.Deref[tv, n.bits];
END;
CountedAssign:
PROC [type: CSEIndex, const:
BOOL]
RETURNS [
BOOL] =
INLINE
BEGIN
RETURN [cd.options.counted AND RCType[type]#none AND ~(const AND cd.options.init)]
END;
AssureSize:
PROC [n: Node, size: IntCodeDefs.Count]
RETURNS [Node] = {
SELECT size
FROM
> n.bits => RETURN[P5U.ZeroExtend[n: n, to: size]];
< n.bits => RETURN[P5U.TakeField[n: n, vl: [disp: 0, size: size]]];
ENDCASE => RETURN[n]};
ConsAssign:
PROC [type: CSEIndex, offset: VLoc, n: Node] =
BEGIN
field: Var ← P5U.TakeField[n: cd.destNode, vl: offset];
P5U.DoAssign[cl: cd.cl, lhs: field, rhs: AssureSize[n, offset.size]];
END;
VanillaCons:
PROC [t: Tree.Link]
RETURNS [vanilla:
BOOL ←
TRUE] =
BEGIN
CheckItem: Tree.Scan =
BEGIN
SELECT TreeOps.OpName[t]
FROM
rowcons, construct, all, union => vanilla ← FALSE;
cast, pad => CheckItem[TreeOps.NthSon[t, 1]];
ENDCASE => NULL;
END;
TreeOps.ScanList[t, CheckItem]; RETURN
END;
main drivers
MainConstruct:
PROC [
maint: Tree.Link,
rSei: CSEIndex,
fa: PROC [ISEIndex] RETURNS [BitAddress, CARDINAL],
total: VLoc,
fieldSei: ISEIndex ← ISENull] =
BEGIN -- workhorse subroutine for construction in memory
tOffset: VLoc = total;
totalBits: CARDINAL = total.size;
rcSei: RecordSEIndex;
AssignField:
PROC [root: Tree.Link] =
BEGIN
offset: VLoc;
rep: BitAddress;
res: BitCount;
fieldType: CSEIndex = UnderType[seb[fieldSei].idType];
IF root # Tree.Null
THEN
BEGIN
[rep, res] ← fa[fieldSei];
offset ← P5U.TakeVField[vl: tOffset, disp: P5U.Bits[rep], size: res];
IF fa # FnField
AND totalBits <= WordSize
THEN
offset ← P5U.AdjustLoc[vl: offset, rSei: rcSei, fSei: fieldSei, tBits: totalBits];
DO
-- until we get to something interesting
SELECT TreeOps.OpName[root]
FROM
pad =>
BEGIN
root ← TreeOps.NthSon[root, 1];
offset.size ← P5U.WordsForOperand[root]*WordSize;
END;
cast => root ← TreeOps.NthSon[root, 1];
ENDCASE => EXIT;
ENDLOOP;
SELECT TreeOps.OpName[root]
FROM
construct =>
MainConstruct[TreeOps.NthSon[root, 2], P5U.OperandType[root], RecField, offset];
union => UnionConstruct[TreeOps.GetNode[root], rcSei, tOffset];
rowcons => Row[TreeOps.GetNode[root], offset];
all => [] ← AllConstruct[TreeOps.GetNode[root], offset];
ENDCASE => {ConsAssign[fieldType, offset, P5.Exp[root]]};
END; -- IF root # Tree.Null
fieldSei ← P5U.NextVar[NextSe[fieldSei]];
END; -- of AssignField
IF fieldSei = ISENull
THEN
WITH seb[rSei]
SELECT
FROM
record =>
BEGIN
rcSei ← RecordRoot[LOOPHOLE[rSei]];
fieldSei ← P5U.NextVar[FirstCtxSe[seb[rcSei].fieldCtx]];
END;
ENDCASE => P5.P5Error[589]
ELSE rcSei ← LOOPHOLE[rSei];
TreeOps.ScanList[maint, AssignField];
END; -- of MainConstruct
Row:
PROC [node: Tree.Index, total: VLoc] =
BEGIN -- handles ARRAY construction
aSei: ArraySEIndex = LOOPHOLE[SymbolOps.UnderType[tb[node].info]];
offset: VLoc ← total;
eSize: BitCount;
cSei: CSEIndex = UnderType[seb[aSei].componentType];
AssignElement:
PROC [t: Tree.Link] =
BEGIN
DO
-- until we get to something interesting
SELECT TreeOps.OpName[t]
FROM
pad =>
BEGIN
t ← TreeOps.NthSon[t, 1];
offset.size ← P5U.WordsForOperand[t]*WordSize;
END;
cast => t ← TreeOps.NthSon[t, 1];
ENDCASE => EXIT;
ENDLOOP;
SELECT TreeOps.OpName[t]
FROM
rowcons => Row[TreeOps.GetNode[t], offset];
construct =>
MainConstruct[TreeOps.NthSon[t, 2], P5U.OperandType[t], RecField, offset];
all =>
-- convert this later
[] ← AllConstruct[TreeOps.GetNode[t], offset];
ENDCASE => IF t # Tree.Null THEN ConsAssign[cSei, offset, P5.Exp[t]];
offset ← P5U.TakeVField[vl: offset, disp: eSize, size: eSize];
END; -- of AssignElement
totalBits: BitCount = total.size;
grain: BitCount = BitsPerElement[seb[aSei].componentType, seb[aSei].packed];
packed: BOOL;
fillBits: CARDINAL;
IF seb[aSei].typeTag # array THEN P5.P5Error[580];
IF grain >= WordSize
THEN
BEGIN
packed ← FALSE; fillBits ← 0;
eSize ← BitsForType[seb[aSei].componentType];
END
ELSE
BEGIN
packed ← TRUE;
fillBits ← totalBits - Cardinality[UnderType[seb[aSei].indexType]]*grain;
eSize ← grain;
END;
IF fillBits # 0
AND totalBits <= WordSize
THEN
BEGIN
offset.size ← eSize + fillBits;
fillBits ← 0;
END
ELSE offset.size ← eSize;
TreeOps.ScanList[tb[node].son[2], AssignElement];
IF fillBits # 0
THEN
BEGIN
offset.size ← fillBits;
ConsAssign[typeANY, offset, CPtr.nC0];
END;
END;
UnionConstruct:
PROC [node: Tree.Index, rootSei: RecordSEIndex, total: VLoc] =
BEGIN -- construct a union part, total is offset of beginning of record
tOffset: VLoc = total;
offset: VLoc ← total;
fieldSei: ISEIndex;
vCtx: CTXIndex;
uSei: CSEIndex = SymbolOps.UnderType[tb[node].info];
rcSei: RecordSEIndex;
tSei: ISEIndex;
tagged: BOOL;
tagValue: CARDINAL;
tBits: CARDINAL = tOffset.size;
WITH u: seb[uSei]
SELECT
FROM
union =>
BEGIN
tagged ← u.controlled;
IF tagged
THEN
BEGIN
tagAddr: BitAddress = seb[u.tagSei].idValue;
tagSize: BitCount = LONG[LOOPHOLE[seb[u.tagSei].idInfo, CARDINAL]];
offset ← P5U.TakeVField[vl: offset, disp: P5U.Bits[tagAddr], size: tagSize];
IF tBits <= WordSize
THEN
offset ← P5U.AdjustLoc[vl: offset, rSei: rootSei, fSei: u.tagSei, tBits: tBits];
END;
END;
ENDCASE => ERROR;
tSei ← TreeOps.GetSe[tb[node].son[1]];
tagValue ← seb[tSei].idValue;
rcSei ← LOOPHOLE[UnderType[tSei], RecordSEIndex];
vCtx ← seb[rcSei].fieldCtx;
fieldSei ← P5U.NextVar[FirstCtxSe[vCtx]];
IF tagged
THEN
BEGIN
IF fieldSei # ISENull
AND seb[fieldSei].idCtx # vCtx
THEN
BEGIN -- a dummy fill field
fillSize: CARDINAL = seb[fieldSei].idInfo;
tagValue ← PrincOpsUtils.BITSHIFT[tagValue, fillSize];
offset.size ← offset.size + fillSize;
fieldSei ← P5U.NextVar[NextSe[fieldSei]];
END;
ConsAssign[typeANY, offset, P5U.MakeNodeLiteral[tagValue]];
END
ELSE
IF fieldSei # ISENull
AND seb[fieldSei].idCtx # vCtx
THEN
BEGIN -- no tag, but a fill field anyway
fillSize: [0..WordSize) = seb[fieldSei].idInfo;
fillAddr: BitAddress = seb[fieldSei].idValue; -- can't be full word
offset ← P5U.TakeVField[ vl: offset, disp: P5U.Bits[fillAddr], size: fillSize];
IF tBits <= WordSize
THEN
offset ← P5U.AdjustLoc[vl: offset, rSei: rootSei, fSei: fieldSei, tBits: tBits];
ConsAssign[typeANY, offset, CPtr.nC0];
fieldSei ← P5U.NextVar[NextSe[fieldSei]];
END;
IF fieldSei # ISENull THEN MainConstruct[tb[node].son[2], rootSei, RecField, total, fieldSei];
END;
AllConstruct:
PROC [node: Tree.Index, total: VLoc] =
BEGIN
aSei: ArraySEIndex = LOOPHOLE[SymbolOps.UnderType[tb[node].info]];
tOffset: VLoc = total;
offset: VLoc;
val: Node;
csei: CSEIndex = UnderType[seb[aSei].componentType];
eSize: BitCount;
t1: Tree.Link ← tb[node].son[1];
totalBits: BitCount = tOffset.size;
aBits: BitCount;
grain: BitCount = BitsPerElement[seb[aSei].componentType, seb[aSei].packed];
packed: BOOL;
fillBits, eCount: CARDINAL;
IF grain >= WordSize
THEN
BEGIN
packed ← FALSE; fillBits ← 0;
eSize ← BitsForType[seb[aSei].componentType];
aBits ← totalBits;
END
ELSE
BEGIN
packed ← TRUE;
eCount ← Cardinality[UnderType[seb[aSei].indexType]];
aBits ← eCount*CARDINAL[grain];
fillBits ← totalBits - aBits;
eSize ← grain;
END;
offset ← P5U.TakeVField[vl: tOffset, disp: 0, size: aBits];
IF fillBits # 0
AND totalBits <= WordSize
THEN
BEGIN
offset.size ← eSize + fillBits;
fillBits ← 0;
END;
val ← AssureSize[P5.Exp[t1], grain];
ConsAssign[aSei, offset, z.NEW [NodeRep.all ← [bits: aBits, details: all[count: P5U.MakeNodeLiteral[eCount], value: val]]]];
IF fillBits # 0
THEN {
offset ← P5U.TakeVField[vl: offset, disp: aBits, size: fillBits];
ConsAssign[typeANY, offset, CPtr.nC0]};
RETURN
END;
public entries
All:
PUBLIC
PROC [t: Tree.Link, node: Tree.Index, options: StoreOptions]
RETURNS [l: Node] =
BEGIN -- generate code for constructor expression
aSei: Symbols.ArraySEIndex = LOOPHOLE[SymbolOps.UnderType[tb[node].info]];
cl: CodeList ← P5U.NewCodeList[];
aBits: BitCount = BitsForType[aSei];
saveCd: ConsDestination = cd;
IF t = Tree.Null
THEN {
var: Var;
sei: ISEIndex;
[var: var, sei: sei] ← P5U.MakeTemp[cl: cl, bits: aBits];
t ← [symbol[sei]]; options.init ← TRUE; options.expr ← TRUE};
cd ← [options: options, ignoreSafen: t = Tree.Null OR t.tag = symbol]; -- + many defaults
tb[node].son[1] ← P5U.ProcessSafens[cl, tb[node].son[1], cd.ignoreSafen];
SetConsDest[t, cl];
AllConstruct[node, [disp: 0, size: cd.destNode.bits]];
IF options.expr THEN P5U.MoreCode[cl, cd.destNode];
l ← P5U.MakeBlock[cl];
IF options.expr THEN l.bits ← aBits;
cd ← saveCd;
END;
Construct:
PUBLIC
PROC [t: Tree.Link, node: Tree.Index, options: StoreOptions]
RETURNS [l: Node] =
BEGIN -- generate code for constructor expression
tsei: RecordSEIndex = LOOPHOLE[SymbolOps.UnderType[tb[node].info]];
cl: CodeList ← P5U.NewCodeList[];
nbits: BitCount = BitsForType[tsei];
saveCd: ConsDestination = cd;
IF t = Tree.Null
THEN {
var: Var;
sei: ISEIndex;
[var: var, sei: sei] ← P5U.MakeTemp[cl: cl, bits: nbits];
t ← [symbol[sei]]; options.init ← TRUE; options.expr ← TRUE};
cd ← [options: options, ignoreSafen: t = Tree.Null OR t.tag = symbol]; -- + many defaults
tb[node].son[2] ← P5U.ProcessSafens[cl, tb[node].son[2], cd.ignoreSafen];
SetConsDest[t, cl];
MainConstruct[
tb[node].son[2], tsei, IF seb[tsei].argument THEN FnField ELSE RecField, [disp: 0, size: cd.destNode.bits]];
IF options.expr THEN P5U.MoreCode[cl, cd.destNode];
l ← P5U.MakeBlock[cl];
IF options.expr THEN l.bits ← cd.destNode.bits;
cd ← saveCd;
END;
ListCons:
PUBLIC
PROC[node: Tree.Index]
RETURNS[Node ←
NIL] = {
pSei: CSEIndex = SymbolOps.UnderType[tb[node].info];
rSei: CSEIndex = SymbolOps.ReferentType[pSei];
long: BOOL = tb[node].attr2;
counted: BOOL = tb[node].attr3;
pLength: CARDINAL = WordsForType[pSei];
zoneTree: Tree.Link;
zoneVar: Lexeme.se;
nwords: CARDINAL = WordsForType[rSei];
k: CARDINAL ← TreeOps.ListLength[tb[node].son[2]];
destVar: Lexeme.se ← P5.GenTempLex[pLength];
restVar: Lexeme.se ← (IF k > 1 THEN P5.GenTempLex[pLength] ELSE NullLex);
rest: Tree.Link ← P5U.NilTree[pSei];
PushSize: PROC = {P5U.PushLitVal[nwords]};
ConsItem: Tree.Map = {
r: VarIndex;
saveCd: ConsDestination = cd;
saveTempList: TempStateRecord = P5.PushTempState[];
list: Tree.Link;
listNode: Tree.Index;
offset: VarComponent.frame;
cd ← [options: [init: TRUE, counted: counted], ignoreSafen: FALSE]; -- + many defaults
TreeOps.PushTree[t]; TreeOps.PushTree[rest];
list ← TreeOps.UpdateList[TreeOps.MakeList[2], CountDups];
listNode ← NARROW[list, Tree.Link.subtree].index;
IF counted THEN
Counting.Allocate[zone: zoneTree, type: rSei, catch: Tree.Null, pushSize: NIL]
ELSE {
P5.ZoneOp[zone: zoneTree, index: 0, pushArg: PushSize, catch: Tree.Null, long: long];
Stack.Incr[pLength]};
P5.SAssign[destVar.lexsei];
offset ← [wSize: nwords, space: frame[wd: 0]];
r ← P5L.GenVarItem[bo];
cb[r] ← [body: bo[base: P5L.ComponentForLex[destVar], offset: offset]];
[] ← SetConsDest[r, FALSE];
MainConstruct[list, rSei, RecField, @offset];
IF (k ← k-1) # 0 THEN {
sTemp: Lexeme.se = destVar;
rest ← [symbol[destVar.lexsei]];
destVar ← restVar; restVar ← sTemp};
v ← tb[listNode].son[1];
tb[listNode].son[1] ← Tree.Null; [] ← TreeOps.FreeTree[list];
cd ← saveCd; P5.PopTempState[saveTempList]};
Stack.Dump[];
IF tb[node].son[1] = Tree.Null THEN {
zoneVar ← P5.GenTempLex[pLength];
Counting.LoadSystemZone[]; P5.SAssign[zoneVar.lexsei];
zoneTree ← [symbol[zoneVar.lexsei]]}
ELSE zoneTree ← tb[node].son[1];
tb[node].son[2] ← TreeOps.ReverseUpdateList[tb[node].son[2], ConsItem];
RETURN [destVar];
};
RowCons:
PUBLIC
PROC [t: Tree.Link, node: Tree.Index, options: StoreOptions]
RETURNS [l: Node] =
BEGIN -- array (expression) construction
aSei: Symbols.ArraySEIndex = LOOPHOLE[SymbolOps.UnderType[tb[node].info]];
cl: CodeList ← P5U.NewCodeList[];
aBits: BitCount = BitsForType[aSei];
saveCd: ConsDestination = cd;
IF t = Tree.Null
THEN {
var: Var;
sei: ISEIndex;
[var: var, sei: sei] ← P5U.MakeTemp[cl: cl, bits: aBits];
t ← [symbol[sei]]; options.init ← TRUE; options.expr ← TRUE};
cd ← [options: options, ignoreSafen: t = Tree.Null OR t.tag = symbol]; -- + many defaults
tb[node].son[1] ← P5U.ProcessSafens[cl, tb[node].son[1], cd.ignoreSafen];
SetConsDest[t, cl];
Row[node, [disp: 0, size: cd.destNode.bits]];
IF options.expr THEN P5U.MoreCode[cl, cd.destNode];
l ← P5U.MakeBlock[cl];
IF options.expr THEN l.bits ← aBits;
cd ← saveCd;
END;
VariantConstruct:
PUBLIC
PROC [t1, t2: Tree.Link, options: StoreOptions]
RETURNS [l: Node] =
BEGIN -- array (expression) construction
rootSei: RecordSEIndex;
cl: CodeList ← P5U.NewCodeList[];
saveCd: ConsDestination = cd;
offset: VLoc;
t1 ← TreeOps.NthSon[t1, 1];
SetConsDest[t1, cl];
cd ← [options: options, ignoreSafen: t1.tag = symbol]; -- + many defaults
t2 ← P5U.ProcessSafens[cl, t2, cd.ignoreSafen];
rootSei ← RecordRoot[LOOPHOLE[P5U.OperandType[t1]]];
offset ← [disp: 0, size: cd.destNode.bits];
UnionConstruct[TreeOps.GetNode[t2], rootSei, offset];
l ← P5U.MakeBlock[cl];
cd ← saveCd;
END;
New:
PUBLIC
PROC [node: Tree.Index]
RETURNS [Node ← NIL] =
BEGIN
long: BOOL = tb[node].attr2;
counted: BOOL = tb[node].attr3;
pLength: CARDINAL = WordsForType[tb[node].info];
typeTree: Tree.Link = tb[node].son[2];
overType: SEIndex = P5U.TypeForTree[typeTree];
type: CSEIndex = UnderType[overType];
catchTree: Tree.Link = IF tb[node].nSons = 4 THEN tb[node].son[4] ELSE Tree.Null;
tag: ISEIndex ← ISENull;
seqLength: VarComponent;
computedType: BOOL = (TreeOps.OpName[typeTree] = apply);
sizePusher: PROC = IF computedType THEN PushNewSize ELSE NIL;
PushNewSize: PROC =
BEGIN
nw: CARDINAL = WordsForType[type];
IF computedType THEN
BEGIN
subNode: Tree.Index = TreeOps.GetNode[typeTree];
vSei: ISEIndex = VariantField[type];
bitsPerItem, n: CARDINAL;
IF vSei # ISENull THEN
BEGIN
vType: CSEIndex = UnderType[seb[vSei].idType];
WITH v: seb[vType] SELECT FROM
sequence =>
BEGIN
tag ← IF v.controlled THEN v.tagSei ELSE ISENull;
bitsPerItem ← BitsPerElement[v.componentType, v.packed];
END;
ENDCASE => ERROR;
END
ELSE
BEGIN -- must be StringBody, fudge it
tag ← NextSe[FirstCtxSe[seb[LOOPHOLE[type, RecordSEIndex]].fieldCtx]];
bitsPerItem ← charlength;
END;
seqLength ← P5L.ComponentForLex[P5.Exp[tb[subNode].son[2]]];
IF tag # ISENull THEN seqLength ← P5L.EasilyLoadable[seqLength, load];
IF bitsPerItem >= wordlength THEN
BEGIN
n ← bitsPerItem/wordlength;
WITH s: seqLength SELECT FROM
const => P5U.PushLitVal[nw + n*s.d1];
ENDCASE =>
BEGIN
P5L.LoadComponent[seqLength];
IF n # 1 THEN {P5U.PushLitVal[n]; P5U.Out0[FOpCodes.qMUL]};
P5U.PushLitVal[nw]; P5U.Out0[FOpCodes.qADD];
END;
END
ELSE
BEGIN
n ← wordlength/bitsPerItem;
WITH s: seqLength SELECT FROM
const => P5U.PushLitVal[nw + ((s.d1+(n-1))/n)];
ENDCASE =>
BEGIN
P5L.LoadComponent[seqLength];
P5U.PushLitVal[n-1]; P5U.Out0[FOpCodes.qADD];
P5U.PushLitVal[SELECT n FROM 2 => -1, 4 => -2, 8 => -3, ENDCASE => -4];
P5U.Out0[FOpCodes.qSHIFT];
P5U.PushLitVal[nw]; P5U.Out0[FOpCodes.qADD];
END;
END;
END
ELSE P5U.PushLitVal[nw];
END;
zoneTree: Tree.Link = tb[node].son[1];
initTree: Tree.Link;
saveCd: ConsDestination = cd;
cd ← [options: [init: TRUE, counted: counted], ignoreSafen: FALSE]; -- + defaults
cd.remaining ← 1;
tb[node].son[3] ← CountDups[tb[node].son[3]];
IF counted THEN
Counting.Allocate[zone: zoneTree, type: overType, catch: catchTree, pushSize: sizePusher]
ELSE
BEGIN
P5.ZoneOp[zone: zoneTree, index: 0, pushArg: PushNewSize, catch: catchTree, long: long];
Stack.Incr[pLength];
END;
IF tag # ISENull OR tb[node].son[3] # Tree.Null THEN
BEGIN
ptrVar: VarIndex;
ptrVar ← P5L.TOSAddrLex[size: WordsForType[type], long: long].lexbdoi;
[] ← SetConsDest[ptrVar];
IF tag # ISENull THEN
BEGIN
offset: VarComponent ← P5L.ComponentForSE[tag];
WITH o: offset SELECT FROM
frame => ConsAssign[typeANY, @o, Tree.Null, [bdo[P5L.OVarItem[seqLength]]]];
ENDCASE => ERROR;
END;
IF tb[node].son[3] # Tree.Null THEN
BEGIN
offset: VarComponent.frame ← [wSize: cd.wSize, bSize: cd.bSize, space: frame[]];
initTree ← tb[node].son[3];
DO
SELECT TreeOps.OpName[initTree] FROM
pad =>
BEGIN
initTree ← TreeOps.NthSon[initTree, 1];
offset.wSize ← P5U.WordsForOperand[initTree]; offset.bSize ← 0;
END;
cast => initTree ← TreeOps.NthSon[initTree, 1];
ENDCASE => EXIT;
ENDLOOP;
SELECT TreeOps.OpName[initTree] FROM
construct =>
MainConstruct[TreeOps.NthSon[initTree, 2], P5U.OperandType[initTree],
RecField, @offset];
rowcons => Row[TreeOps.GetNode[initTree], @offset];
all => [] ← AllConstruct[TreeOps.GetNode[initTree], @offset];
mwconst => ConstantFill[type, @offset, initTree];
ENDCASE => {ConstructCountDown[]; ConsAssign[type, @offset, initTree]};
END;
IF cd.remaining # 1 THEN SIGNAL ConstructionError;
[] ← LoadPointer[0];
END;
cd ← saveCd;
RETURN [P5L.TOSLex[pLength]]
END;