DIRECTORY
A3: TYPE USING [AssignableType, ComponentType, Default, DefaultInit, IndexType, OrderedType, TargetType, TypeForTree, Voidable, VoidItem],
Alloc: TYPE USING [Notifier],
ComData: TYPE USING [idANY, idCARDINAL, idINTEGER, interface, mainCtx, moduleCtx, seAnon, textIndex, typeStringBody],
Log: TYPE USING [Error, ErrorHti, ErrorSei, ErrorTree],
P3: TYPE USING [Attr, NPUse, SequenceNP, fullAttr, voidAttr, mark, pathNP, phraseNP, CheckDisjoint, ClearRefStack, CopyTree, EnterComposite, Exp, FindSe, InterfaceCtx, MakeFrameRecord, PopCtx, PushCtx, RAttr, RecordLhs, RecordMention, Rhs, RPop, RPush, RType, SafetyAttr, SealRefStack, SearchCtxList, SelectVariantType, TopCtx, UnsealRefStack, VariantUnionType, VoidExp],
PrincOpsUtils: TYPE USING [BITOR],
SourceMap: TYPE USING [Loc],
Symbols: TYPE USING [Base, SERecord, Name, Type, ISEIndex, CSEIndex, RecordSEIndex, RefSEIndex, CTXIndex, CBTIndex, nullType, ISENull, CSENull, CTXNull, codeANY, codeINT, lG, lZ, typeANY, typeTYPE, seType, ctxType, mdType, bodyType],
SymbolOps: TYPE USING [ArgCtx, CopyXferType, CtxLevel, DecodeCard, DecodeTreeIndex, DecodeType, EncodeCard, EncodeType, EnterExtension, EqTypes, FromType, LinkMode, MakeNonCtxSe, NormalType, RCType, ReferentType, ToBti, ToType, TypeForm, TypeLink, UnderType, XferMode],
Tree: TYPE USING [Base, Index, Link, Map, Null, nullIndex, Scan, treeType],
TreeOps:
TYPE
USING [FreeTree, GetHash, GetNode, GetSe, GetTag, IdentityMap, ListHead, ListLength, NthSon, OpName, ScanList, ToLoc, UpdateList];
Pass3D:
PROGRAM
IMPORTS A3, Log, P3, PrincOpsUtils, SymbolOps, TreeOps, dataPtr: ComData
EXPORTS P3 = {
OPEN TreeOps, SymbolOps, Symbols, A3, P3;
tb: Tree.Base; -- tree base address (local copy)
seb: Symbols.Base; -- se table base address (local copy)
ctxb: Symbols.Base; -- context table base address (local copy)
mdb: Symbols.Base; -- module table base address (local copy)
bb: Symbols.Base; -- body table base address (local copy)
DeclNotify:
PUBLIC Alloc.Notifier = {
called by allocator whenever table area is repacked
tb ← base[Tree.treeType];
seb ← base[seType]; ctxb ← base[ctxType]; mdb ← base[mdType];
bb ← base[bodyType]};
ItemId:
PUBLIC
PROC[t: Tree.Link]
RETURNS[ISEIndex] = {
RETURN[
WITH t
SELECT GetTag[t]
FROM
symbol => index,
subtree => ItemId[tb[index].son[1]],
ENDCASE => ERROR]
FirstId:
PUBLIC
PROC[node: Tree.Index]
RETURNS[ISEIndex] = {
RETURN[ItemId[ListHead[tb[node].son[1]]]]};
DeclList: PUBLIC Tree.Scan = {ScanList[t, DeclA]; ScanList[t, DeclBInit]};
DeclA: Tree.Scan = {
node: Tree.Index = GetNode[t];
type: Type;
saveIndex: SourceMap.Loc = dataPtr.textIndex;
IF tb[node].attr3 = P3.mark THEN RETURN; -- already processed
tb[node].attr3 ← P3.mark;
dataPtr.textIndex ← ToLoc[tb[node].info];
tb[node].son[2] ← TypeLink[tb[node].son[2]
! CheckTypeLoop => {
IF loopNode = node
THEN
RESUME [
TRUE]};
LogTypeLoop => {IF loopNode = node THEN RESUME}];
type ← TypeForTree[tb[node].son[2]];
SELECT tb[node].name
FROM
typedecl => DefineTypeSe[tb[node].son[1], type];
decl => DefineSeType[tb[node].son[1], type, tb[node].attr1];
ENDCASE => ERROR;
ClearRefStack[];
dataPtr.textIndex ← saveIndex};
DeclBField: Tree.Scan = {DeclBDefault[t, FALSE]};
DeclBVarField: Tree.Scan = {DeclBDefault[t, TRUE]};
DeclBDefault:
PROC[t: Tree.Link, varOK:
BOOL←
FALSE] = {
node: Tree.Index = GetNode[t];
saveIndex: SourceMap.Loc = dataPtr.textIndex;
IF tb[node].attr2 = P3.mark THEN RETURN; -- already processed
tb[node].attr2 ← P3.mark;
dataPtr.textIndex ← ToLoc[tb[node].info];
TypeAttr[typeExp: tb[node].son[2], varOK: varOK];
SELECT tb[node].name
FROM
typedecl => NULL;
decl => {
type: Type = TypeForTree[tb[node].son[2]];
IF ~ComponentType[type] THEN Log.ErrorTree[typeLength, tb[node].son[2]];
IF tb[node].son[3] # Tree.Null
THEN {
ScanList[tb[node].son[1], RecordDeclInit];
tb[node].son[3] ← DefaultExp[t:tb[node].son[3], type:type, ids:tb[node].son[1]]};
DefineSeValue[tb[node].son[1], FALSE]};
ENDCASE => ERROR;
ClearRefStack[];
dataPtr.textIndex ← saveIndex};
DeclBInit: Tree.Scan = {
node: Tree.Index = GetNode[t];
saveIndex: SourceMap.Loc = dataPtr.textIndex;
IF tb[node].attr2 = P3.mark THEN RETURN; -- already processed
tb[node].attr2 ← P3.mark;
dataPtr.textIndex ← ToLoc[tb[node].info];
[] ← CheckPositions[tb[node].son[1], FieldAttrs[]];
SELECT tb[node].name
FROM
typedecl => {
TypeAttr[tb[node].son[2]];
IF tb[node].son[3] # Tree.Null
THEN {
tb[node].son[3] ← DefaultExp[
t:tb[node].son[3], type:TypeForTree[tb[node].son[2]], ids:tb[node].son[1]];
[] ← ProcessDefault[node]}
};
decl => {
type: Type;
constFlag, extFlag: BOOL;
ctx: CTXIndex = TopCtx[];
TypeAttr[typeExp: tb[node].son[2], varOK: InterfaceContext[ctx]];
type ← TypeForTree[tb[node].son[2]];
IF ~ComponentType[type] THEN Log.ErrorTree[typeLength, tb[node].son[2]];
IF tb[node].son[3] = Tree.Null
THEN {
IF ~InterfaceContext[ctx]
AND ~tb[node].attr1
THEN {
tb[node].son[3] ← DefaultInit[type];
pathNP ← SequenceNP[pathNP][phraseNP]; RPop[]};
constFlag ← FALSE}
ELSE {
[tb[node].son[3], extFlag] ← InitialExp[tb[node].son[3], type];
IF extFlag AND ~tb[node].attr1 THEN Log.ErrorTree[misusedInline, tb[node].son[3]];
pathNP ← SequenceNP[pathNP][phraseNP];
constFlag ← tb[node].attr1 AND RAttr[].const; RPop[];
IF tb[node].son[3] # Tree.Null THEN ScanList[tb[node].son[1], RecordDeclInit]};
SELECT
TRUE
FROM
(tb[node].son[3] = Tree.Null) =>
IF ~InterfaceContext[ctx]
AND ~Voidable[type]
THEN
Log.ErrorSei[missingInit, FirstId[node]];
GlobalContext[ctx] =>
SELECT RCType[type]
FROM
composite => EnterComposite[UnderType[type], tb[node].son[3], TRUE];
ENDCASE => NULL;
ENDCASE => NULL;
DefineSeValue[tb[node].son[1], constFlag]};
ENDCASE => ERROR;
ClearRefStack[];
dataPtr.textIndex ← saveIndex};
RecordDeclInit: Tree.Scan = {
sei: ISEIndex = ItemId[t]; RecordMention[sei]; RecordLhs[sei]};
DefaultExp:
PROC[t: Tree.Link, type: Type, ids: Tree.Link]
RETURNS[v: Tree.Link] = {
subType: Type = TargetType[type];
ExpInit:
PROC[t: Tree.Link]
RETURNS[val: Tree.Link] = {
val ← Rhs[t, subType]; RPop[]; RETURN};
v ← UpdateList[t, ExpInit];
IF VoidItem[v] AND ~Voidable[type] THEN Log.ErrorSei[defaultForm, ItemId[ids]];
RETURN};
InitialExp:
PUBLIC
PROC[t: Tree.Link, type: Type]
RETURNS[v: Tree.Link, extended:
BOOL] = {
v ← t; extended ← FALSE; phraseNP ← none;
SELECT OpName[t]
FROM
body => {
defer processing of bodies (see Body)
subType: CSEIndex = UnderType[type];
expNode: Tree.Index = GetNode[t];
bti: CBTIndex = LOOPHOLE[ToBti[tb[expNode].info]];
attr: Attr ← voidAttr;
SELECT XferMode[type]
FROM
proc, program => NULL;
ENDCASE =>
IF TypeForm[type] = $definition THEN attr ← fullAttr ELSE Log.Error[bodyType];
bb[bti].ioType ←
SELECT seb[type].seTag
FROM
cons => subType,
ENDCASE => CopyXferType[subType, IdentityMap];
RPush[type, attr]; extended ← tb[expNode].attr3; -- inline
CheckBodyType[subType, expNode]};
inline => {
expNode: Tree.Index = GetNode[t];
CodeBody: Tree.Map = {RETURN[UpdateList[t, NumericConst]]};
IF XferMode[type] # proc THEN Log.Error[inlineType];
IF tb[expNode].attr1 THEN Log.Error[inlineChecked];
tb[expNode].son[1] ← UpdateList[tb[expNode].son[1], CodeBody];
RPush[type, fullAttr]; extended ← TRUE;
CheckBodyType[UnderType[type], expNode]};
apply => {
expNode: Tree.Index = GetNode[t];
IF tb[expNode].son[1] = Tree.Null
AND EqTypes[ReferentType[type], dataPtr.typeStringBody]
AND ListLength[tb[expNode].son[2]] = 1
THEN
tb[expNode].name ← stringinit;
v ← Rhs[t, TargetType[type]]};
signalinit => RPush[type, voidAttr];
void => {v ← FreeTree[t]; RPush[type, voidAttr]};
ENDCASE => v ← Rhs[t, TargetType[type]];
RETURN};
RecordField:
PROC[ctx: CTXIndex]
RETURNS[
BOOL] =
INLINE {
RETURN[ctx = CTXNull OR (CtxLevel[ctx] = lZ AND ctx # dataPtr.moduleCtx)]};
GlobalContext:
PROC[ctx: CTXIndex]
RETURNS[
BOOL] =
INLINE {
RETURN[~dataPtr.interface AND CtxLevel[ctx] = lG]};
InterfaceContext:
PROC[ctx: CTXIndex]
RETURNS[
BOOL] =
INLINE {
RETURN[dataPtr.interface AND ctx = dataPtr.mainCtx]};
InterfaceSe:
PROC[sei: ISEIndex]
RETURNS[
BOOL] =
INLINE {
RETURN[InterfaceContext[seb[sei].idCtx]]};
CheckBodyType:
PROC[type: CSEIndex, node: Tree.Index] = {
WITH t: seb[type]
SELECT
FROM
transfer => {
IF TypeForm[t.typeIn] = $any
OR TypeForm[t.typeOut] = $any
THEN
Log.Error[bodyType];
IF t.safe AND SafetyAttr[node] = none THEN Log.Error[unsafeBlock]};
ENDCASE
DefineTypeSe:
PROC[t: Tree.Link, info: Type] = {
first: BOOL ← TRUE;
UpdateSe: Tree.Scan = {
sei: ISEIndex = ItemId[t];
seb[sei].idType ← typeTYPE; seb[sei].idInfo ← EncodeType[info];
seb[sei].immutable ← seb[sei].constant ← TRUE;
IF first THEN {info ← sei; first ← FALSE};
seb[sei].mark3 ← TRUE};
ScanList[t, UpdateSe]};
DefineSeType: PROC[t: Tree.Link, type: Type, fixed: BOOL] = {
UpdateSe: Tree.Scan = {
sei: ISEIndex = ItemId[t];
seb[sei].idType ← type; seb[sei].constant ← FALSE;
IF InterfaceSe[sei] THEN seb[sei].immutable ← seb[sei].immutable OR fixed
ELSE seb[sei].immutable ← fixed;
seb[sei].mark3 ← TRUE};
ScanList[t, UpdateSe]};
DefineSeValue: PROC[t: Tree.Link, const: BOOL] = {
UpdateSe: Tree.Scan = {
sei: ISEIndex = ItemId[t];
seb[sei].constant ← const;
IF InterfaceSe[sei] AND LinkMode[sei] = val THEN seb[sei].immutable ← TRUE};
ScanList[t, UpdateSe]};
ProcessDefault:
PROC[node: Tree.Index]
RETURNS[nonVoid:
BOOL] = {
copy: BOOL;
v: Tree.Link = tb[node].son[3];
DefineDefault: Tree.Scan = {
EnterExtension[ItemId[t], default, IF copy THEN CopyTree[v] ELSE v];
copy ← TRUE};
SELECT OpName[v]
FROM
stringinit => Log.ErrorSei[defaultForm, FirstId[node]];
lengthen =>
IF OpName[NthSon[v, 1]] = stringinit
THEN
Log.ErrorSei[defaultForm, FirstId[node]];
void => nonVoid ← FALSE;
ENDCASE => nonVoid ← TRUE;
copy ← FALSE; ScanList[tb[node].son[1], DefineDefault];
tb[node].son[3] ← Tree.Null};