DIRECTORY A3: TYPE USING [ AssignableType, Default, DefaultInit, IndexType, NewableType, OrderedType, TargetType, TypeForTree, Voidable, VoidItem], Alloc: TYPE USING [Notifier], ComData: TYPE USING [ idANY, idCARDINAL, interface, mainCtx, moduleCtx, seAnon, textIndex, typeINT, 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], Symbols: TYPE USING [ Base, SERecord, HTIndex, SEIndex, ISEIndex, CSEIndex, RecordSEIndex, RefSEIndex, CTXIndex, CBTIndex, SENull, ISENull, CTXNull, codeANY, codeINT, lG, lZ, typeANY, typeTYPE, seType, ctxType, mdType, bodyType], SymbolOps: TYPE USING [ ArgCtx, CopyXferType, EnterExtension, LinkMode, MakeNonCtxSe, NormalType, RCType, ReferentType, TypeForm, TypeLink, UnderType, XferMode], Tree: TYPE USING [Base, Index, Link, Map, Null, NullIndex, Scan, treeType], TreeOps: TYPE USING [ FreeTree, GetHash, GetNode, GetSe, IdentityMap, ListHead, ListLength, NthSon, OpName, ScanList, 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 = { tb _ base[Tree.treeType]; seb _ base[seType]; ctxb _ base[ctxType]; mdb _ base[mdType]; bb _ base[bodyType]}; CheckTypeLoop: SIGNAL [loopNode: Tree.Index] RETURNS [BOOL] = CODE; LogTypeLoop: SIGNAL [loopNode: Tree.Index] = CODE; ItemId: PUBLIC PROC [t: Tree.Link] RETURNS [ISEIndex] = { RETURN [WITH t SELECT 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: SEIndex; saveIndex: CARDINAL = dataPtr.textIndex; IF tb[node].attr3 = P3.mark THEN RETURN; -- already processed tb[node].attr3 _ P3.mark; dataPtr.textIndex _ 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: CARDINAL = dataPtr.textIndex; IF tb[node].attr2 = P3.mark THEN RETURN; -- already processed tb[node].attr2 _ P3.mark; dataPtr.textIndex _ tb[node].info; TypeAttr[typeExp: tb[node].son[2], varOK: varOK]; SELECT tb[node].name FROM typedecl => NULL; decl => { type: SEIndex = TypeForTree[tb[node].son[2]]; IF ~NewableType[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: CARDINAL = dataPtr.textIndex; IF tb[node].attr2 = P3.mark THEN RETURN; -- already processed tb[node].attr2 _ P3.mark; dataPtr.textIndex _ 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: SEIndex; constFlag, extFlag: BOOL; ctx: CTXIndex = TopCtx[]; TypeAttr[typeExp: tb[node].son[2], varOK: InterfaceContext[ctx]]; type _ TypeForTree[tb[node].son[2]]; IF ~NewableType[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[UnderType[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: SEIndex, ids: Tree.Link] RETURNS [v: Tree.Link] = { subType: CSEIndex = TargetType[UnderType[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: SEIndex] RETURNS [v: Tree.Link, extended: BOOL] = { subType: CSEIndex = UnderType[type]; v _ t; extended _ FALSE; phraseNP _ none; SELECT OpName[t] FROM body => { expNode: Tree.Index = GetNode[t]; bti: CBTIndex = 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[subType, 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[attrClash]; tb[expNode].son[1] _ UpdateList[tb[expNode].son[1], CodeBody]; RPush[subType, fullAttr]; extended _ TRUE; CheckBodyType[subType, expNode]}; apply => { expNode: Tree.Index = GetNode[t]; IF tb[expNode].son[1] = Tree.Null AND ReferentType[subType] = dataPtr.typeStringBody AND ListLength[tb[expNode].son[2]] = 1 THEN tb[expNode].name _ stringinit; v _ Rhs[t, TargetType[subType]]}; signalinit => RPush[subType, voidAttr]; void => {v _ FreeTree[t]; RPush[subType, voidAttr]}; ENDCASE => v _ Rhs[t, TargetType[subType]]; RETURN}; RecordField: PROC [ctx: CTXIndex] RETURNS [BOOL] = INLINE { RETURN [ctx = CTXNull OR (ctxb[ctx].level = lZ AND ctx # dataPtr.moduleCtx)]}; GlobalContext: PROC [ctx: CTXIndex] RETURNS [BOOL] = INLINE { RETURN [~dataPtr.interface AND ctxb[ctx].level = 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: SEIndex] = { first: BOOL _ TRUE; UpdateSe: Tree.Scan = { sei: ISEIndex = ItemId[t]; seb[sei].idType _ typeTYPE; seb[sei].idInfo _ 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: SEIndex, 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}; ResolveType: PUBLIC PROC [sei: ISEIndex] = { currentCtx: CTXIndex = TopCtx[]; IF seb[sei].idCtx # currentCtx THEN {PopCtx[]; ResolveType[sei]; PushCtx[currentCtx]} ELSE {SealRefStack[]; DeclA[[subtree[index: seb[sei].idValue]]]; UnsealRefStack[]}}; ResolveValue: PUBLIC PROC [sei: ISEIndex] = { currentCtx: CTXIndex = TopCtx[]; IF seb[sei].idCtx # currentCtx THEN {PopCtx[]; ResolveValue[sei]; PushCtx[currentCtx]} ELSE { SealRefStack[]; IF RecordField[currentCtx] THEN DeclBDefault[[subtree[index: seb[sei].idValue]]] ELSE DeclBInit[[subtree[index: seb[sei].idValue]]]; UnsealRefStack[]}}; CheckTypeId: PROC [sei: ISEIndex] RETURNS [BOOL] = { SELECT TRUE FROM (sei = ISENull) => RETURN [FALSE]; seb[sei].mark3 => RETURN [seb[sei].idType = typeTYPE]; ENDCASE => { node: Tree.Index = seb[sei].idValue; RETURN [node = Tree.NullIndex OR tb[node].name = typedecl]}}; TypeSymbol: PROC [sei: ISEIndex] RETURNS [val: Tree.Link] = { entryIndex: CARDINAL = dataPtr.textIndex; circular: BOOL _ FALSE; IF ~seb[sei].mark3 THEN { ENABLE LogTypeLoop => { saveIndex: CARDINAL = dataPtr.textIndex; dataPtr.textIndex _ entryIndex; Log.ErrorSei[circularType, sei]; circular _ TRUE; dataPtr.textIndex _ saveIndex}; declNode: Tree.Index = seb[sei].idValue; IF tb[declNode].attr3 # P3.mark THEN ResolveType[sei] ELSE IF SIGNAL CheckTypeLoop[declNode] THEN SIGNAL LogTypeLoop[declNode]}; IF CheckTypeId[sei] AND ~circular THEN val _ [symbol[index: sei]] ELSE { IF ~circular AND sei # dataPtr.seAnon THEN Log.ErrorSei[nonTypeId, sei]; val _ [symbol[index: dataPtr.idANY]]}; RETURN}; PushArgCtx: PROC [sei: CSEIndex] = { ctx: CTXIndex = ArgCtx[sei]; IF ctx # CTXNull THEN PushCtx[ctx]}; PopArgCtx: PROC [sei: CSEIndex] = { IF ArgCtx[sei] # CTXNull THEN PopCtx[]}; TypeExp: PUBLIC PROC [typeExp: Tree.Link] RETURNS [val: Tree.Link] = { val _ TypeLink[typeExp]; TypeAttr[val]; RETURN}; TypeAppl: PUBLIC PROC [typeExp: Tree.Link] RETURNS [val: Tree.Link] = { attr: Attr; IF OpName[typeExp] = apply THEN { node: Tree.Index = GetNode[typeExp]; rType: SEIndex; tb[node].son[1] _ TypeExp[tb[node].son[1]]; tb[node].info _ rType _ TypeForTree[tb[node].son[1]]; SELECT TRUE FROM (UnderType[rType] = dataPtr.typeStringBody), (TypeForm[VariantUnionType[rType]] = sequence) => { tb[node].son[2] _ Rhs[tb[node].son[2], dataPtr.typeINT]; attr _ RAttr[]; RPop[]}; (TypeForm[VariantUnionType[rType]] = union) => { TypeDiscrim[rType, node]; phraseNP _ none; attr _ fullAttr}; ENDCASE => { Log.ErrorTree[typeClash, tb[node].son[1]]; tb[node].son[2] _ Exp[tb[node].son[2], typeANY]; attr _ RAttr[]; RPop[]}; val _ typeExp} ELSE {val _ TypeExp[typeExp]; phraseNP _ none; attr _ fullAttr}; RPush[typeTYPE, attr]}; ClusterExp: PROC [t: Tree.Link] RETURNS [val: Tree.Link] = { WITH t SELECT FROM hash => { sei: ISEIndex = FindSe[index].symbol; IF ~CheckTypeId[sei] THEN -- prevent duplicate error messages val _ Exp[IF sei = dataPtr.seAnon THEN [symbol[sei]] ELSE t, typeANY] ELSE {val _ TypeSymbol[sei]; RPush[typeTYPE, fullAttr]}}; symbol => { sei: ISEIndex = index; IF ~CheckTypeId[sei] THEN val _ Exp[t, typeANY] ELSE {val _ TypeSymbol[sei]; RPush[typeTYPE, fullAttr]}}; ENDCASE => {val _ TypeLink[t]; RPush[typeTYPE, fullAttr]}; RETURN}; TypeDot: PROC [rType: SEIndex, node: Tree.Index] = TypeDiscrim; TypeDiscrim: PROC [rType: SEIndex, node: Tree.Index] = { t2: Tree.Link = tb[node].son[2]; WITH h: t2 SELECT FROM hash => { iSei: ISEIndex = SelectVariantType[rType, h.index]; IF iSei # ISENull THEN { tb[node].info _ iSei; tb[node].son[2] _ [symbol[index: iSei]]; tb[node].name _ discrimTC} ELSE { IF rType # typeANY THEN Log.ErrorTree[unknownVariant, t2]; tb[node].info _ dataPtr.idANY}}; ENDCASE => { Log.ErrorTree[unknownVariant, t2]; tb[node].son[2] _ VoidExp[t2]}}; FindLinkType: SIGNAL RETURNS [CSEIndex] = CODE; -- to find list link type TypeLink: PROC [typeExp: Tree.Link] RETURNS [val: Tree.Link] = { WITH typeExp SELECT FROM hash => { sei: ISEIndex = FindSe[index].symbol; IF sei # SENull THEN val _ TypeSymbol[sei] ELSE {Log.ErrorHti[nonTypeId, index]; val _ [symbol[dataPtr.idANY]]}}; symbol => val _ TypeSymbol[index]; subtree => { node: Tree.Index = index; iSei: ISEIndex; SELECT tb[node].name FROM discrimTC => { tb[node].son[1] _ TypeLink[tb[node].son[1]]; TypeDiscrim[TypeForTree[tb[node].son[1]], node]}; apply => { rType: SEIndex; tb[node].son[1] _ TypeLink[tb[node].son[1]]; tb[node].info _ rType _ TypeForTree[tb[node].son[1]]; IF TypeForm[VariantUnionType[rType]] = union THEN TypeDiscrim[rType, node] ELSE Log.ErrorTree[noApplication, tb[node].son[1]]}; dot => { hti: HTIndex = GetHash[tb[node].son[2]]; nDerefs: CARDINAL _ 0; found: BOOL; next: SEIndex; ctx: CTXIndex _ CTXNull; tb[node].son[1] _ ClusterExp[tb[node].son[1]]; FOR subType: CSEIndex _ RType[], UnderType[next] DO WITH t: seb[subType] SELECT FROM mode => GOTO type; definition, transfer => { ctx _ InterfaceCtx[subType, tb[node].son[1]]; GO TO cluster}; record => {ctx _ t.fieldCtx; GO TO cluster}; ref => {IF (nDerefs _ nDerefs+1) > 63 THEN GO TO cluster; next _ t.refType}; long => next _ t.rangeType; subrange => next _ t.rangeType; ENDCASE => GO TO cluster; REPEAT type => TypeDot[TypeForTree[tb[node].son[1]], node]; cluster => { [found, iSei] _ SearchCtxList[hti, ctx]; IF ~found THEN {iSei _ dataPtr.idANY; Log.ErrorHti[unknownField, hti]}; tb[node].name _ cdot; tb[node].info _ iSei; tb[node].son[2] _ TypeSymbol[iSei]}; ENDLOOP; RPop[]}; paintTC => { tb[node].son[1] _ TypeLink[tb[node].son[1]]; tb[node].son[2] _ TypeLink[tb[node].son[2]]; tb[node].info _ TypeForTree[tb[node].son[2]]}; linkTC => tb[node].info _ SIGNAL FindLinkType[]; implicitTC => NULL; frameTC => { tb[node].son[1] _ Exp[tb[node].son[1], typeANY]; RPop[]; tb[node].info _ MakeFrameRecord[tb[node].son[1]]}; ENDCASE => { OPEN tb[node]; type: CSEIndex = info; WITH t: seb[type] SELECT FROM enumerated => NULL; record => {PushCtx[t.fieldCtx]; ScanList[son[1], DeclA]; PopCtx[]}; ref => { son[1] _ TypeLink[son[1] ! CheckTypeLoop => {RESUME [FALSE]}]; t.refType _ TypeForTree[son[1]]}; array => { IF son[1] = Tree.Null THEN t.indexType _ dataPtr.idCARDINAL ELSE {son[1] _ TypeLink[son[1]]; t.indexType _ TypeForTree[son[1]]}; son[2] _ TypeLink[son[2]]; t.componentType _ TypeForTree[son[2]]}; arraydesc => { son[1] _ TypeLink[son[1] ! CheckTypeLoop => {RESUME [FALSE]}]; t.describedType _ TypeForTree[son[1]]}; transfer => { ENABLE CheckTypeLoop => {RESUME [FALSE]}; CheckDisjoint[ArgCtx[t.typeIn], ArgCtx[t.typeOut]]; PushArgCtx[t.typeIn]; IF OpName[son[1]] # anyTC THEN ScanList[son[1], DeclA]; PushArgCtx[t.typeOut]; IF OpName[son[2]] # anyTC THEN ScanList[son[2], DeclA]; PopArgCtx[t.typeOut]; PopArgCtx[t.typeIn]}; definition => t.defCtx _ dataPtr.mainCtx; union => {DeclA[son[1]]; ScanList[son[2], DeclA]}; sequence => { DeclA[son[1]]; son[2] _ TypeLink[son[2]]; t.componentType _ TypeForTree[son[2]]}; relative => { son[1] _ TypeLink[son[1] ! CheckTypeLoop => {RESUME [FALSE]}]; t.baseType _ TypeForTree[son[1]]; son[2] _ TypeLink[son[2]]; t.resultType _ t.offsetType _ TypeForTree[son[2]]}; opaque => IF t.id = SENull OR ~InterfaceSe[t.id] THEN Log.Error[misplacedType]; zone => NULL; subrange => { t.range _ LOOPHOLE[node]; -- to allow symbolic evaluation son[1] _ TypeLink[son[1]]; t.rangeType _ TypeForTree[son[1]]}; long => { son[1] _ TypeLink[son[1] ! FindLinkType => {RESUME [type]}]; t.rangeType _ TypeForTree[son[1]]}; any => NULL; ENDCASE => ERROR; seb[type].mark3 _ TRUE}; val _ typeExp}; ENDCASE => ERROR; RETURN}; TypeAttr: PROC [typeExp: Tree.Link, indirect, varOK: BOOL _ FALSE] = { WITH typeExp SELECT FROM symbol => IF ~indirect THEN { sei: ISEIndex = index; IF seb[sei].mark3 AND ~seb[sei].mark4 THEN { declNode: Tree.Index = seb[sei].idValue; IF tb[declNode].attr2 # P3.mark THEN ResolveValue[sei]}}; subtree => { node: Tree.Index = index; SELECT tb[node].name FROM discrimTC => TypeAttr[tb[node].son[1], indirect]; cdot => TypeAttr[tb[node].son[2], indirect]; paintTC => { TypeAttr[tb[node].son[1]]; TypeAttr[tb[node].son[2], indirect]; Log.Error[unimplemented]}; implicitTC, linkTC => NULL; frameTC => NULL; apply => tb[node].son[2] _ VoidExp[tb[node].son[2]]; dot => NULL; ENDCASE => { OPEN tb[node]; type: CSEIndex = info; subType: CSEIndex; WITH t: seb[type] SELECT FROM enumerated => IF AssignedEnumeration[son[1]] AND ~t.machineDep THEN Log.Error[machDep]; record => { saveNP: NPUse = pathNP; PushCtx[t.fieldCtx]; pathNP _ none; ScanList[son[1], DeclBField]; WITH s: t SELECT FROM linked => CheckDisjointPrefix[t.fieldCtx, s.linkType]; notLinked => { attrs: FieldAttrs = CollectAttrs[ son[1], FieldAttrs[positionValid: t.machineDep]]; UpdateHints[LOOPHOLE[type], attrs]; attr1 _ AssignedPositions[attrs]}; ENDCASE => ERROR; PopCtx[]; pathNP _ saveNP}; ref => { IF t.var AND ~varOK THEN Log.Error[var]; TypeAttr[son[1], TRUE]}; array => { IF son[1] # Tree.Null THEN TypeAttr[son[1]]; SELECT TRUE FROM ~IndexType[t.indexType] => { t.indexType _ typeANY; Log.Error[nonOrderedType]}; (TypeForm[t.indexType]=long) => Log.Error[subrangeNesting]; ENDCASE; TypeAttr[son[2], indirect]; IF ~NewableType[t.componentType] THEN Log.ErrorTree[typeLength, son[2]]}; arraydesc => { TypeAttr[son[1], TRUE]; IF TypeForm[t.describedType] # array THEN Log.Error[descriptor]}; transfer => { saveNP: NPUse = pathNP; IF t.mode = error THEN t.safe _ FALSE; PushArgCtx[t.typeIn]; ArgAttr[t.typeIn, son[1], t.mode = proc OR t.mode = signal]; PushArgCtx[t.typeOut]; ArgAttr[t.typeOut, son[2], FALSE]; PopArgCtx[t.typeOut]; PopArgCtx[t.typeIn]; pathNP _ saveNP}; definition => NULL; union => { tagType: CSEIndex; DeclBDefault[son[1]]; seb[t.tagSei].immutable _ TRUE; tagType _ TargetType[UnderType[seb[t.tagSei].idType]]; IF seb[tagType].typeTag # enumerated THEN { Log.ErrorSei[nonTagType, t.tagSei]; tagType _ typeANY}; VariantList[son[2], tagType]}; sequence => { DeclBDefault[son[1]]; seb[t.tagSei].immutable _ TRUE; SELECT TRUE FROM ~IndexType[seb[t.tagSei].idType] => Log.ErrorSei[nonTagType, t.tagSei]; (TypeForm[seb[t.tagSei].idType]=long) => Log.Error[unimplemented]; ENDCASE; TypeAttr[son[2], indirect]}; relative => { vType: CSEIndex; TypeAttr[son[1], TRUE]; IF seb[NormalType[UnderType[t.baseType]]].typeTag # ref THEN Log.Error[relative]; TypeAttr[son[2]]; vType _ UnderType[t.offsetType]; subType _ NormalType[vType]; SELECT seb[subType].typeTag FROM ref, arraydesc => NULL; ENDCASE => {Log.Error[relative]; subType _ typeANY}; IF seb[UnderType[t.baseType]].typeTag = long OR seb[vType].typeTag = long THEN subType _ MakeLongType[subType, vType]; t.resultType _ subType}; zone => NULL; opaque => IF son[1] # Tree.Null THEN { son[1] _ Rhs[son[1], dataPtr.typeINT]; IF ~RAttr[].const THEN Log.ErrorTree[nonConstant, son[1]]; RPop[]}; subrange => { target: CSEIndex; subNode: Tree.Index = GetNode[son[2]]; TypeAttr[son[1], indirect]; subType _ UnderType[t.rangeType]; SELECT TRUE FROM (TypeForm[subType] = ref) => target _ dataPtr.typeINT; OrderedType[subType] => { WITH s: seb[subType] SELECT FROM long => { t.rangeType _ s.rangeType; subType _ UnderType[s.rangeType]}; real => Log.Error[subrangeNesting]; ENDCASE; target _ TargetType[subType]}; ENDCASE => {Log.Error[nonOrderedType]; target _ typeANY}; tb[subNode].son[1] _ EndPoint[tb[subNode].son[1], target]; tb[subNode].son[2] _ EndPoint[tb[subNode].son[2], target]}; long => { TypeAttr[son[1], indirect, varOK]; subType _ UnderType[t.rangeType]; WITH s: seb[subType] SELECT FROM basic => SELECT s.code FROM codeINT, codeANY => NULL; ENDCASE => Log.Error[long]; ref, arraydesc => NULL; subrange => IF t.rangeType # dataPtr.idCARDINAL THEN Log.Error[long]; ENDCASE => Log.Error[long]}; any => NULL; ENDCASE => ERROR}}; ENDCASE => ERROR}; EndPoint: PROC [t: Tree.Link, target: CSEIndex] RETURNS [v: Tree.Link] = { v _ Rhs[t, target]; IF ~RAttr[].const THEN Log.ErrorTree[nonConstant, v]; RPop[]}; FieldAttrs: TYPE = RECORD [ positionValid: BOOL _ FALSE, noAssign: BOOL _ FALSE, refField, unVoidable, default: BOOL _ FALSE, positions: PACKED ARRAY {implicit, explicit} OF BOOL _ [FALSE, FALSE]]; MergeAttrs: PROC [attr1, attr2: FieldAttrs] RETURNS [FieldAttrs] = LOOPHOLE[PrincOpsUtils.BITOR]; UpdateHints: PROC [rSei: RecordSEIndex, attrs: FieldAttrs] = { seb[rSei].hints.assignable _ ~attrs.noAssign; seb[rSei].hints.refField _ attrs.refField; seb[rSei].hints.voidable _ ~attrs.unVoidable; seb[rSei].hints.default _ attrs.default}; AssignedPositions: PROC [attrs: FieldAttrs] RETURNS [assigned: BOOL] = { IF attrs.positionValid THEN { IF attrs.positions = [TRUE, TRUE] THEN Log.Error[mixedPositions]; assigned _ attrs.positions[explicit]} ELSE assigned _ FALSE; RETURN}; CollectAttrs: PROC [t: Tree.Link, attrs: FieldAttrs] RETURNS [FieldAttrs] = { ProcessField: Tree.Scan = { node: Tree.Index = GetNode[t]; type: SEIndex = TypeForTree[tb[node].son[2]]; subType: CSEIndex = UnderType[type]; attrs _ CheckPositions[tb[node].son[1], attrs]; IF (IF tb[node].son[3] = Tree.Null THEN Default[type] = nonVoid ELSE ProcessDefault[node]) THEN attrs.default _ TRUE; WITH t: seb[subType] SELECT FROM union => { subNode: Tree.Index = GetNode[tb[node].son[2]]; IF t.controlled THEN ProcessField[tb[subNode].son[1]]; attrs _ MergeVariantAttrs[tb[subNode].son[2], attrs]; t.hints.refField _ attrs.refField; t.hints.voidable _ ~attrs.unVoidable; t.hints.default _ attrs.default; tb[subNode].attr1 _ attrs.positions[explicit]}; sequence => { subNode: Tree.Index = GetNode[tb[node].son[2]]; IF t.controlled THEN ProcessField[tb[subNode].son[1]]; IF RCType[UnderType[t.componentType]] # none THEN { IF ~t.controlled THEN Log.Error[attrClash]; attrs.refField _ --attrs.unVoidable _-- TRUE}; attrs.noAssign _ TRUE; tb[subNode].attr1 _ attrs.positions[explicit]}; ENDCASE => { IF ~attrs.refField AND RCType[subType] # none THEN attrs.refField _ attrs.unVoidable _ TRUE; IF ~attrs.unVoidable AND ~Voidable[type] THEN attrs.unVoidable _ TRUE; IF ~AssignableType[subType, FALSE] THEN attrs.noAssign _ TRUE}}; ScanList[t, ProcessField]; RETURN [attrs]}; ArgAttr: PROC [rSei: CSEIndex, t: Tree.Link, varOK: BOOL] = { IF rSei # SENull THEN WITH seb[rSei] SELECT FROM record => { ScanList[t, IF varOK THEN DeclBVarField ELSE DeclBField]; UpdateHints[LOOPHOLE[rSei], CollectAttrs[t, FieldAttrs[]]]}; ENDCASE}; NumericConst: Tree.Map = {v _ Rhs[t, dataPtr.typeINT]; RPop[]; RETURN}; AssignedEnumeration: PROC [t: Tree.Link] RETURNS [assigned: BOOL] = { AssignElement: Tree.Scan = { WITH t SELECT FROM subtree => { node: Tree.Index = index; tb[node].son[2] _ NumericConst[tb[node].son[2]]; assigned _ TRUE}; ENDCASE => NULL; RETURN}; assigned _ FALSE; ScanList[t, AssignElement]; RETURN}; CheckPositions: PROC [t: Tree.Link, attrs: FieldAttrs] RETURNS [FieldAttrs] = { CheckPosition: Tree.Scan = { WITH t SELECT FROM subtree => { node: Tree.Index = GetNode[tb[index].son[2]]; IF ~attrs.positionValid THEN Log.ErrorSei[position, ItemId[tb[index].son[1]]]; tb[node].son[1] _ NumericConst[tb[node].son[1]]; IF tb[node].son[2] # Tree.Null THEN { subNode: Tree.Index = GetNode[tb[node].son[2]]; tb[subNode].son[1] _ NumericConst[tb[subNode].son[1]]; tb[subNode].son[2] _ NumericConst[tb[subNode].son[2]]}; attrs.positions[explicit] _ TRUE}; ENDCASE => attrs.positions[implicit] _ TRUE}; ScanList[t, CheckPosition]; RETURN [attrs]}; CheckDisjointPrefix: PROC [ctx: CTXIndex, link: SEIndex] = { FOR sei: SEIndex _ link, SymbolOps.TypeLink[sei] UNTIL sei = SENull DO type: CSEIndex = UnderType[sei]; WITH t: seb[type] SELECT FROM record => CheckDisjoint[ctx, t.fieldCtx]; ENDCASE; ENDLOOP}; VariantList: PROC [t: Tree.Link, tagType: CSEIndex] = { DefineTag: Tree.Scan = { sei: ISEIndex = GetSe[t]; seb[sei].idValue _ TagValue[seb[sei].hash, tagType]}; VariantItem: Tree.Scan = { node: Tree.Index = GetNode[t]; saveIndex: CARDINAL = dataPtr.textIndex; dataPtr.textIndex _ tb[node].info; ScanList[tb[node].son[1], DefineTag]; DeclBDefault[t]; dataPtr.textIndex _ saveIndex}; ScanList[t, VariantItem]}; TagValue: PROC [tag: HTIndex, tagType: CSEIndex] RETURNS [CARDINAL] = { matched: BOOL; sei: ISEIndex; WITH seb[tagType] SELECT FROM enumerated => { [matched, sei] _ SearchCtxList[tag, valueCtx]; IF matched THEN RETURN [seb[sei].idValue]}; ENDCASE; Log.ErrorHti[unknownTag, tag]; RETURN [0]}; MergeVariantAttrs: PROC [list: Tree.Link, prefixAttrs: FieldAttrs] RETURNS [mergedAttrs: FieldAttrs] = { ProcessVariant: Tree.Scan = { node: Tree.Index = GetNode[t]; ProcessLabel: Tree.Scan = { sei: ISEIndex = GetSe[t]; type: SEIndex = seb[sei].idInfo; WITH v: seb[type] SELECT FROM cons => WITH r: v SELECT FROM record => { subNode: Tree.Index = GetNode[tb[node].son[2]]; attrs: FieldAttrs = CollectAttrs[tb[subNode].son[1], prefixAttrs]; UpdateHints[LOOPHOLE[type], attrs]; r.hints.default _ TRUE; tb[subNode].attr1 _ attrs.positions[explicit]; mergedAttrs _ MergeAttrs[mergedAttrs, attrs]}; ENDCASE; id => NULL; ENDCASE}; ScanList[tb[node].son[1], ProcessLabel]}; mergedAttrs _ prefixAttrs; ScanList[list, ProcessVariant]; mergedAttrs.default _ prefixAttrs.default; RETURN}; MakeLongType: PUBLIC PROC [rType: SEIndex, hint: CSEIndex] RETURNS [type: CSEIndex] = { subType: CSEIndex = UnderType[rType]; WITH t: seb[hint] SELECT FROM long => IF TargetType[UnderType[t.rangeType]] = TargetType[subType] THEN RETURN [hint]; ENDCASE; WITH t: seb[subType] SELECT FROM relative => { oType: CSEIndex = MakeLongType[UnderType[t.offsetType], UnderType[t.resultType]]; type _ MakeNonCtxSe[SERecord.cons.relative.SIZE]; seb[type] _ [mark3: TRUE, mark4: TRUE, body: cons[relative[ baseType: t.baseType, offsetType: oType, resultType: oType]]]}; ENDCASE => { type _ MakeNonCtxSe[SERecord.cons.long.SIZE]; seb[type] _ [mark3: TRUE, mark4: TRUE, body: cons[long[rangeType: rType]]]}; RETURN}; MakeRefType: PUBLIC PROC [ cType: SEIndex, hint: CSEIndex, readOnly, counted, var: BOOL] RETURNS [type: RefSEIndex] = { WITH t: seb[hint] SELECT FROM ref => IF ~t.ordered AND t.readOnly = readOnly AND t.counted = counted AND t.var = var AND UnderType[t.refType] = UnderType[cType] THEN RETURN [LOOPHOLE[hint]]; ENDCASE; type _ LOOPHOLE[MakeNonCtxSe[SERecord.cons.ref.SIZE]]; seb[type] _ [mark3: TRUE, mark4: TRUE, body: cons[ref[ counted: counted, var: var, readOnly: readOnly, ordered: FALSE, list: FALSE, basing: FALSE, refType: cType]]]; RETURN}; }. èfile Pass3D.mesa last modified by Satterthwaite, May 6, 1983 9:17 am last modified by Donahue, 10-Dec-81 10:22:58 Last Edited by: Maxwell, August 1, 1983 3:42 pm called by allocator whenever table area is repacked signals for type loop detection declaration processing defer processing of bodies (see Body) forward reference resolution type expressions for now, should do other possible cluster items record attribute collection machine dependent layout variants type construction Ê`˜Jšœ™Jšœ3™3Jšœ,™,J™/J˜šÏk ˜ šœœœ˜J˜JJ˜-—Jšœœœ ˜šœ œœ˜J˜DJ˜—Jšœœœ(˜7šœœœ˜J˜,J˜J˜DJ˜AJ˜AJ˜KJ˜ —Jšœœœœ˜"šœ œœ˜J˜5J˜.J˜FJ˜#—šœ œœ˜J˜IJ˜?—Jšœœœ;˜Kšœ œœ˜J˜EJ˜&J˜——šœ˜š˜J˜/J˜—Jšœ˜Jšœ%˜)J˜JšœÏc!˜0Jšœž%˜8Jšœž*˜>Jšœž)˜Jšœ&˜,J˜J˜—Jšœ œ:˜JJ˜˜J˜J˜Jšœ œ˜(Jšœœœž˜=J˜J˜"˜*š œœœœœ˜;Jšœœœœ˜1——J˜$šœ˜J˜0J˜œ˜DJšœœ˜——Jšœœ˜—J˜+—Jšœœ˜—J˜J˜J˜J˜—˜J˜?J˜J˜—šŸ œœ/œ˜YJ˜0J˜šŸœœœ˜9Jšœ!œ˜)J˜—J˜Jšœ œœ(˜OJšœ˜J˜—šŸ œœœ˜5Jšœœ˜*J˜$Jšœœ˜+šœ ˜˜ Jšœ%™%J˜!J˜!J˜šœ˜Jšœœ˜šœ˜ Jšœœœ˜M——šœœ˜,J˜Jšœ'˜.—Jšœ6ž ˜?J˜!—˜ J˜!J˜Jšœœ ˜Jšœ&œ˜+J˜!—˜ J˜!šœ˜!Jšœ/˜2šœ$˜+J˜——J˜!—J˜'J˜5Jšœ$˜+—Jšœ˜J˜J˜J˜—š Ÿ œœœœœ˜;Jšœœœ˜NJ˜—š Ÿ œœœœœ˜=Jšœœ˜6J˜—š Ÿœœœœœ˜@Jšœœ˜6J˜—š Ÿ œœœœœ˜;Jšœ%˜+J˜J˜—šŸ œœ'˜:šœœ˜˜ šœœ˜=J˜—Jšœœœ˜C—Jšœ˜ J˜J˜——šŸ œœ"˜4Jšœœœ˜J˜˜J˜J˜4Jšœ)œ˜.Jšœœœ˜*Jšœœ˜J˜—J˜J˜—JšŸ œœ&œ˜A˜˜J˜Jšœ-œ˜3Jšœœ)œ˜IJšœ˜ Jšœœ˜J˜—J˜J˜—JšŸ œœœ˜3˜˜J˜J˜Jšœœœœ˜LJ˜—J˜J˜J˜—šŸœœœ œ˜CJšœœ˜ J˜J˜˜Jšœ#œœ œ˜DJšœœ˜ J˜—šœ ˜J˜7˜ šœ#˜)J˜)——Jšœœ˜Jšœœ˜—Jšœœ,˜8J˜J˜J˜—Jšœ™˜šŸ œœœ˜,J˜ Jšœœ2˜UJšœP˜TJ˜—šŸ œœœ˜-J˜ Jšœœ3˜Všœ˜J˜Jšœœ1˜PJšœ0˜4J˜J˜J˜———Jšœ™˜šŸ œœœœ˜4šœœ˜Jšœœœ˜"Jšœœ˜6šœ˜ J˜$Jšœœ˜=J˜———šŸ œœœ˜=Jšœ œ˜)Jšœ œœ˜šœœ˜š˜˜Jšœ œ˜(J˜Jšœ-œ˜2J˜——J˜(Jšœœ˜5Jš œœœœœ˜J—Jšœœ œ˜Ašœ˜Jšœ œœ˜HJ˜&—Jšœ˜J˜J˜—šŸ œœ˜$J˜Jšœœ˜$J˜—šŸ œœ˜#Jšœœ ˜(J˜J˜—šŸœœœœ˜FJšœ(œ˜0J˜—šŸœœœœ˜GJ˜ šœœ˜!J˜$J˜J˜+J˜5šœœ˜J˜,˜3J˜Q—˜0J˜=—šœ˜ J˜*J˜I——J˜—Jšœ<˜@J˜J˜J˜—šŸ œœœ˜<šœœ˜˜ J˜%šœœž#˜>Jšœ œœœ ˜E—Jšœ5˜9—˜ J˜Jšœœ˜/Jšœ5˜9—Jšœ3˜:—Jšœ˜J˜—šŸœœ2˜?Jšœ/™/J˜—šŸ œœ'˜8J˜ šœœ˜˜ J˜3šœœ˜J˜?J˜—šœ˜Jšœœ#˜:J˜ ——šœ˜ J˜CJ˜J˜———Jšœœœœž˜IJ˜šŸœœœ˜@šœ œ˜˜ J˜%Jšœœ˜*JšœB˜F—J˜"˜ J˜J˜šœ˜˜J˜,J˜1—˜ J˜J˜,J˜5Jšœ+œ˜JJšœ0˜4—˜J˜(Jšœ œ˜Jšœœ˜ J˜J˜J˜.šœ.˜3šœœ˜ Jšœœ˜˜Jšœ.œœ ˜=—Jšœœœ ˜,Jš œœœœœ˜LJ˜J˜Jšœœœ ˜—š˜J˜4˜ J˜(Jšœœ9˜GJ˜J˜;——Jšœ˜—J˜—˜ J˜,J˜,J˜.—Jšœœ˜0Jšœœ˜˜ J˜9J˜2—šœ˜ Jšœ ˜J˜šœœ˜Jšœœ˜J˜C˜Jšœ-œœ˜>J˜!—˜ Jšœœ!˜;Jšœ@˜DJ˜C—˜Jšœ-œœ˜>J˜'—˜ Jšœœœ˜*J˜3J˜Jšœœ˜7J˜Jšœœ˜7J˜,—J˜)J˜2˜ J˜J˜C—˜ Jšœ-œœ˜>J˜!J˜J˜3—Jšœ œœœ˜OJšœœ˜ ˜ Jšœ œ ž˜—˜ Jšœ,œ ˜šœ˜ Jšœœ˜Jšœ-˜4—šœ+œ˜NJ˜'—J˜—Jšœœ˜ ˜ šœœ˜J˜&Jšœœ$˜:J˜——˜ J˜J˜&J˜>šœœ˜J˜6˜šœœ˜ ˜ J˜J˜"—J˜#Jšœ˜—J˜—Jšœ2˜9—J˜:J˜;—˜ J˜"J˜!šœœ˜ ˜šœ˜Jšœœ˜Jšœ˜——Jšœœ˜Jšœ œ"œ˜EJšœ˜——Jšœœ˜ Jšœœ˜————Jšœœ˜J˜šŸœœ"œ˜JJ˜Jšœœ˜5J˜J˜J˜————Jšœ™˜šœ œœ˜Jšœœœ˜Jšœ œœ˜Jšœœœ˜,Jš œ œœœœœœ˜GJ˜—šŸ œœœ˜BJšœœ˜J˜—šŸ œœ-˜>J˜-J˜*J˜-J˜)J˜—šŸœœœ œ˜Hšœœ˜Jšœœœœ˜AJ˜%—Jšœ œ˜Jšœ˜J˜—JšŸ œœ#œ˜M˜˜J˜J˜-J˜$J˜/šœœ˜"Jšœ˜Jšœœœ˜5—šœœ˜ ˜ J˜/Jšœœ"˜6J˜5J˜HJ˜ J˜/—˜ J˜/Jšœœ"˜6šœ+œ˜3Jšœœ˜+Jšœžœœ˜.—Jšœœ˜J˜/—šœ˜ šœœ˜2Jšœ$œ˜)—Jšœœœœ˜FJšœœœœ˜@J˜———J˜Jšœ ˜J˜—šŸœœ'œ˜=šœ˜šœ œ˜˜ Jšœ œœœ ˜9Jšœ œ(˜<—Jšœ˜ J˜J˜————Jšœ™˜JšœAœ˜IJ˜JšŸœœœ œ˜E˜˜šœœ˜˜ J˜Jšœ=œ˜C—Jšœœ˜—Jšœ˜J˜—Jšœ œ œ˜8J˜—JšŸœœ#œ˜O˜˜šœœ˜˜ J˜-Jšœœ2˜NJ˜0šœœ˜%J˜/J˜6J˜7—Jšœœ˜"—Jšœ œ˜-J˜——Jšœœ ˜,J˜J˜——Jšœ™˜šŸœœ#˜<šœ.œ˜FJ˜ šœœ˜J˜)Jšœ˜—Jšœ˜ J˜J˜——JšŸ œœ&˜7˜˜J˜J˜5J˜—˜J˜Jšœ œ˜(J˜"J˜%J˜J˜J˜—J˜J˜—šŸœœ#œœ˜GJšœ œ˜J˜šœœ˜˜J˜.Jšœ œœ˜+—Jšœ˜—Jšœ œ˜,J˜—šŸœœ+˜BJšœ˜%J˜˜J˜J˜˜J˜J˜ šœœ˜˜šœœ˜˜ J˜/J˜BJšœ œ˜#Jšœœ˜J˜.J˜.—Jšœ˜——Jšœœ˜ Jšœ˜ J˜——J˜)J˜—J˜J˜KJšœ˜J˜——Jšœ™˜šŸ œœœ"œ˜WJ˜%šœœ˜˜Jšœ:œœ˜O—Jšœ˜—šœœ˜ ˜ J˜QJšœ+œ˜1šœœ œ˜&˜J˜?———šœ˜ Jšœ'œ˜-Jšœœ œ'˜L——Jšœ˜J˜—šŸ œœœ˜Jšœ8œ˜=Jšœ˜šœœ˜˜šœ ˜ Jšœœœ ˜AJšœ)œœœ˜I——Jšœ˜—Jšœœ œ˜6šœœ œ˜&˜J˜J˜ Jšœœœ œ˜?J˜——Jšœ˜J˜—J˜J˜———…—lâ‰*