-- file Pass2.mesa -- last modified by Satterthwaite, February 22, 1983 10:29 am -- last modified by Donahue, 9-Dec-81 12:03:59 DIRECTORY Alloc: TYPE USING [Notifier, AddNotify, Bounds, DropNotify, Words], ComData: TYPE USING [ bodyIndex, defBodyLimit, idLOCK, importCtx, interface, mainCtx, moduleCtx, monitored, nBodies, nInnerBodies, nSigCodes, table, textIndex], CompilerUtil: TYPE USING [], Log: TYPE USING [Error, ErrorHti], Symbols: TYPE USING [ Base, BodyLink, BodyRecord, ContextLevel, SERecord, TransferMode, Name, Type, CSEIndex, ISEIndex, RecordSEIndex, CTXIndex, BTIndex, CBTIndex, nullName, nullType, CSENull, ISENull, RecordSENull, CTXNull, BTNull, CBTNull, lG, lL, lZ, RootBti, typeANY, typeTYPE, seType, ctxType, bodyType], SymbolOps: TYPE USING [ BlockLevel, FillCtxSe, FirstCtxSe, NewCtx, MakeNonCtxSe, MakeSeChain, NameClash, NextLevel, NextSe, SetMainCtx, StaticNestError], Tree: TYPE USING [ Base, Index, Link, Map, NodeName, Null, NullIndex, Scan, treeType], TreeOps: TYPE USING [ FreeNode, GetInfo, GetNode, ListHead, ListLength, NthSon, OpName, PutInfo, ScanList, UpdateList]; Pass2: PROGRAM IMPORTS Alloc, Log, SymbolOps, TreeOps, dataPtr: ComData EXPORTS CompilerUtil = { OPEN TreeOps, SymbolOps, Symbols; tb: Tree.Base; -- tree base (private copy) seb: Symbols.Base; -- se table base (private copy) ctxb: Symbols.Base; -- context table base (private copy) bb: Symbols.Base; -- body table base (private copy) Notify: Alloc.Notifier = { -- called by allocator whenever tables are repacked tb ← base[Tree.treeType]; seb ← base[seType]; ctxb ← base[ctxType]; bb ← base[bodyType]}; ContextInfo: TYPE = RECORD [ ctx: CTXIndex, staticLevel: ContextLevel, seChain: ISEIndex]; current: ContextInfo; NewContext: PROC [level: ContextLevel, entries: NAT, unique: BOOL] = { OPEN c: current; c.staticLevel ← level; IF entries = 0 AND ~unique THEN {c.ctx ← CTXNull; c.seChain ← ISENull} ELSE { c.ctx ← NewCtx[level]; ctxb[c.ctx].seList ← c.seChain ← MakeSeChain[c.ctx, entries, level=lG]}}; -- main driver P2Unit: PUBLIC PROC [t: Tree.Link] RETURNS [Tree.Link] = { node: Tree.Index; (dataPtr.table).AddNotify[Notify]; anySei ← CSENull; node ← GetNode[t]; BEGIN ENABLE { -- default error reporting NameClash => {Log.ErrorHti[duplicateId, name]; RESUME}; StaticNestError => {Log.Error[staticNesting]; RESUME}}; dataPtr.textIndex ← tb[node].info; dataPtr.bodyIndex ← CBTNull; dataPtr.nBodies ← dataPtr.nInnerBodies ← dataPtr.nSigCodes ← 0; btLink ← [which:parent, index:BTNull]; NewContext[ level: lZ, entries: ListLength[tb[node].son[1]] + CountIds[tb[node].son[6]], unique: FALSE]; dataPtr.moduleCtx ← current.ctx; ScanList[tb[node].son[1], IdItem]; ImportList[tb[node].son[2]]; -- process LOCKS clause dataPtr.monitored ← tb[node].son[5] # Tree.Null; lockLambda ← Lambda[tb[node].son[5], lL]; MainBody[tb[node].son[6]]; dataPtr.defBodyLimit ← (dataPtr.table).Bounds[bodyType].size; END; (dataPtr.table).DropNotify[Notify]; RETURN [t]}; ImportList: PROC [t: Tree.Link] = { saved: ContextInfo = current; NewContext[lG, ListLength[t], FALSE]; dataPtr.importCtx ← current.ctx; ScanList[t, IdItem]; current ← saved}; MainBody: PROC [t: Tree.Link] = INLINE { dataPtr.interface ← (OpName[NthSon[t, 2]] = definitionTC); DeclList[t]; BodyList[RootBti]}; -- monitor lock processing lockLambda: Tree.Index; Lambda: PROC [item: Tree.Link, level: ContextLevel] RETURNS [node: Tree.Index] = { node ← GetNode[item]; IF node # Tree.NullIndex THEN { saved: ContextInfo = current; NewContext[level, CountIds[tb[node].son[1]], FALSE]; tb[node].info ← current.ctx; DeclList[tb[node].son[1]]; Exp[tb[node].son[2]]; current ← saved}; RETURN}; ImplicitLock: PROC = { sei: ISEIndex = current.seChain; tb[lockLambda].son[2] ← Ids[ list: tb[lockLambda].son[2], public: tb[lockLambda].attr2, link: Tree.NullIndex]; seb[sei].idType ← dataPtr.idLOCK; seb[sei].idInfo ← 1; seb[sei].mark3 ← TRUE}; -- body processing btLink: BodyLink; AllocateBody: PROC [node: Tree.Index, id: ISEIndex] RETURNS [bti: CBTIndex] = { -- queue body for later processing -- force nesting message here SELECT NextLevel[current.staticLevel] FROM lG, lL => { bti ← (dataPtr.table).Words[bodyType, BodyRecord.Callable.Outer.SIZE]; bb[bti] ← [,,,,,,, Callable[,,,,,,,,,,Outer[]]]}; ENDCASE => { bti ← (dataPtr.table).Words[bodyType, BodyRecord.Callable.Inner.SIZE]; bb[bti] ← [,,,,,,, Callable[,,,,,,,,,, Inner[frameOffset: ]]]}; bb[bti].firstSon ← BTNull; bb[bti].sourceIndex ← dataPtr.textIndex; bb[bti].info ← [Internal[bodyTree:node, thread:Tree.NullIndex, frameSize: ]]; bb[bti].id ← id; bb[bti].entry ← bb[bti].internal ← FALSE; -- conservative initial approximations bb[bti].ioType ← typeANY; bb[bti].noXfers ← FALSE; bb[bti].hints ← [safe:FALSE, argUpdated:TRUE, nameSafe:FALSE, noStrings:FALSE]; LinkBody[bti]; RETURN}; LinkBody: PROC [bti: BTIndex] = { IF btLink.which = parent THEN { bb[bti].link ← btLink; IF btLink.index # BTNull THEN bb[btLink.index].firstSon ← bti ELSE IF bti # RootBti THEN ERROR} ELSE { bb[bti].link ← bb[btLink.index].link; bb[btLink.index].link ← [which:sibling, index: bti]}}; SetEntryAttr: PROC [t: Tree.Link, attr: Tree.NodeName] = { IF OpName[t] # body OR ~dataPtr.monitored THEN Log.Error[misplacedEntry] ELSE { -- see AllocateBody bti: CBTIndex = GetInfo[t]; SELECT attr FROM entry => bb[bti].entry ← TRUE; internal => bb[bti].internal ← TRUE; ENDCASE}}; BodyList: PROC [firstBti: BTIndex] = { FOR bti: BTIndex ← firstBti, bb[bti].link.index UNTIL bti = BTNull DO WITH bb[bti] SELECT FROM Callable => Body[LOOPHOLE[bti, CBTIndex]]; ENDCASE => NULL; IF bb[bti].link.which = parent THEN EXIT; ENDLOOP}; Body: PROC [bti: CBTIndex] = { node: Tree.Index = WITH bb[bti].info SELECT FROM Internal => bodyTree, ENDCASE => ERROR; level: ContextLevel; nLocks: [0..1]; oldBodyIndex: CBTIndex = dataPtr.bodyIndex; oldBtLink: BodyLink = btLink; saved: ContextInfo = current; dataPtr.bodyIndex ← bti; btLink ← [which:parent, index:bti]; level ← NextLevel[saved.staticLevel ! StaticNestError => {RESUME}]; nLocks ← IF level = lG AND dataPtr.monitored AND tb[lockLambda].attr1 THEN 1 ELSE 0; NewContext[ level: level, entries: nLocks + CountIds[tb[node].son[2]], unique: level = lG]; bb[bti].localCtx ← current.ctx; bb[bti].level ← BlockLevel[level]; bb[bti].monitored ← nLocks # 0; bb[bti].inline ← tb[node].attr3; bb[bti].type ← IF current.ctx = CTXNull OR bb[bti].inline THEN RecordSENull ELSE BodyType[current.ctx, bb[bti].monitored]; IF level = lG THEN { IF bti # RootBti THEN ERROR; dataPtr.mainCtx ← current.ctx; SetMainCtx[current.ctx]}; ExpList[tb[node].son[1]]; IF nLocks # 0 THEN ImplicitLock[]; DeclList[tb[node].son[2]]; StmtList[tb[node].son[3]]; BodyList[bb[bti].firstSon]; current ← saved; dataPtr.bodyIndex ← oldBodyIndex; btLink ← oldBtLink}; NewScope: PROC [node: Tree.Index, decls: Tree.Link] RETURNS [bti: BTIndex] = { level: ContextLevel = BlockLevel[current.staticLevel]; NewContext[level:level, entries:CountIds[decls], unique:FALSE]; bti ← (dataPtr.table).Words[bodyType, BodyRecord.Other.SIZE]; bb[bti] ← [ link: , firstSon: BTNull, type: IF bb[dataPtr.bodyIndex].inline THEN RecordSENull ELSE BodyType[current.ctx, FALSE], localCtx: current.ctx, level: level, sourceIndex: tb[node].info, info: [Internal[bodyTree:node, thread:Tree.NullIndex, frameSize: ]], extension: Other[relOffset: ]]; LinkBody[bti]; btLink ← [which:parent, index:bti]; DeclList[decls]}; BodyType: PROC [ctx: CTXIndex, monitored: BOOL] RETURNS [rSei: RecordSEIndex] = { rSei ← LOOPHOLE[MakeNonCtxSe[SERecord.cons.record.notLinked.SIZE]]; seb[rSei].typeInfo ← record[ machineDep: FALSE, painted: TRUE, argument: FALSE, hints: [ unifield: FALSE, variant: FALSE, assignable: FALSE, comparable: FALSE, privateFields: TRUE, refField: FALSE, default: FALSE, voidable: FALSE], length: 0, fieldCtx: ctx, monitored: monitored, linkPart: notLinked[]]; RETURN}; CodeBody: PROC [node: Tree.Index] = { InlineOp: Tree.Scan = {ExpList[t]}; ScanList[tb[node].son[1], InlineOp]}; -- declarations DeclList: PROC [t: Tree.Link, linkId: Type←nullType] = { DeclItem: Tree.Scan = { node: Tree.Index = GetNode[t]; saveIndex: CARDINAL = dataPtr.textIndex; dataPtr.textIndex ← tb[node].info; tb[node].son[1] ← Ids[ list: tb[node].son[1], type: (tb[node].name = typedecl), public: tb[node].attr2, link: node]; tb[node].attr2 ← tb[node].attr3 ← FALSE; SELECT tb[node].name FROM typedecl => { TypeExp[t:tb[node].son[2], typeId:FirstId[tb[node].son[1]], linkId:linkId]; ExpList[tb[node].son[3]]}; decl => { TypeExp[t:tb[node].son[2], linkId:linkId]; tb[node].son[3] ← InitialValue[ tb[node].son[3], IF tb[node].attr1 THEN FirstId[tb[node].son[1]] ELSE ISENull]}; ENDCASE => Log.Error[unimplemented]; dataPtr.textIndex ← saveIndex}; ScanList[t, DeclItem]}; CountIds: PROC [declList: Tree.Link] RETURNS [n: NAT←0] = { NIds: Tree.Scan = {n ← n + ListLength[NthSon[t, 1]]}; ScanList[declList, NIds]; RETURN}; InitialValue: PROC [t: Tree.Link, id: ISEIndex] RETURNS [v: Tree.Link] = { v ← t; -- the default IF t # Tree.Null THEN WITH t SELECT FROM subtree => { node: Tree.Index = index; SELECT tb[node].name FROM body => { bti: CBTIndex = AllocateBody[node, id]; tb[node].info ← bti; IF ~tb[node].attr3 THEN { dataPtr.nBodies ← dataPtr.nBodies+1; IF current.staticLevel >= lL THEN dataPtr.nInnerBodies ← dataPtr.nInnerBodies + 1}; btLink ← [which:sibling, index:bti]}; entry, internal => { v ← InitialValue[tb[node].son[1], id]; SetEntryAttr[v, tb[node].name]; tb[node].son[1] ← Tree.Null; FreeNode[node]}; signalinit => { tb[node].info ← dataPtr.nSigCodes; dataPtr.nSigCodes ← dataPtr.nSigCodes+1}; inline => CodeBody[node]; ENDCASE => ExpList[t]}; ENDCASE => ExpList[t]}; IdItem: Tree.Scan = { node: Tree.Index = GetNode[t]; saveIndex: CARDINAL = dataPtr.textIndex; dataPtr.textIndex ← tb[node].info; tb[node].son[1] ← Ids[list: tb[node].son[1], public: FALSE, link: node]; dataPtr.textIndex ← saveIndex}; -- id list manipulation Ids: PROC [ list: Tree.Link, public: BOOL, type: BOOL ← FALSE, link: Tree.Index] RETURNS [Tree.Link] = { Id: Tree.Map = { WITH t SELECT FROM hash, symbol => { name: Name = (WITH t SELECT FROM hash => index, symbol => seb[index].hash, ENDCASE => ERROR); sei: ISEIndex = current.seChain; current.seChain ← NextSe[current.seChain]; FillCtxSe[sei, name, public]; seb[sei].idType ← IF type THEN typeTYPE ELSE typeANY; seb[sei].public ← public; seb[sei].immutable ← seb[sei].constant ← FALSE; seb[sei].idValue ← link; seb[sei].idInfo ← 0; seb[sei].extended ← seb[sei].linkSpace ← FALSE; v ← [symbol[index: sei]]}; subtree => { node: Tree.Index = index; tb[node].son[1] ← Id[tb[node].son[1]]; Position[tb[node].son[2]]; v ← t}; ENDCASE => ERROR; RETURN}; RETURN [UpdateList[list, Id]]}; FirstId: PROC [t: Tree.Link] RETURNS [ISEIndex] = { head: Tree.Link = ListHead[t]; RETURN [WITH head SELECT FROM symbol => index, subtree => FirstId[tb[index].son[1]], ENDCASE => ERROR]}; -- type manipulation TypeExp: PROC [t: Tree.Link, typeId, linkId: Type←nullType] = { sei: CSEIndex; WITH t SELECT FROM subtree => { node: Tree.Index = index; SELECT tb[node].name FROM enumeratedTC => { sei ← MakeNonCtxSe[SERecord.cons.enumerated.SIZE]; seb[sei].typeInfo ← enumerated[ ordered: TRUE, sparse: FALSE, machineDep: tb[node].attr2, unpainted: ~(tb[node].attr2 OR dataPtr.interface), valueCtx: Enumeration[node], empty: , nValues: ]; AssignValues[sei, IF typeId # nullType THEN typeId ELSE sei]}; recordTC, monitoredTC => { tCtx: CTXIndex; nFields: NAT; sei ← MakeNonCtxSe[SERecord.cons.record.notLinked.SIZE]; [tCtx, nFields] ← FieldList[ t: tb[node].son[1], level: lZ, typeId: IF typeId # nullType THEN typeId ELSE sei]; seb[sei].typeInfo ← record[ machineDep: tb[node].attr1, painted: tb[node].attr1 OR (dataPtr.interface AND tb[node].attr3), argument: FALSE, hints: [ unifield: nFields = 1 AND ~tb[node].attr2, variant: tb[node].attr2, assignable: TRUE, comparable: FALSE, privateFields: FALSE, refField: FALSE, default: FALSE, voidable: TRUE], length: , fieldCtx: tCtx, monitored: tb[node].name = monitoredTC, linkPart: notLinked[]]; IF tb[node].name = monitoredTC AND tb[node].attr1 THEN Log.Error[attrClash]}; variantTC => { sei ← MakeNonCtxSe[SERecord.cons.record.linked.SIZE]; seb[sei].typeInfo ← record[ machineDep: tb[node].attr1, painted: tb[node].attr3, argument: FALSE, hints: [ unifield: FALSE, variant: tb[node].attr2, assignable: TRUE, comparable: FALSE, privateFields: FALSE, refField: FALSE, default: FALSE, voidable: TRUE], length: , fieldCtx: FieldList[t:tb[node].son[1], level:lZ, typeId:typeId].ctx, monitored: FALSE, linkPart: linked[linkId]]}; refTC, listTC, pointerTC, varTC => { sei ← MakeNonCtxSe[SERecord.cons.ref.SIZE]; seb[sei].typeInfo ← ref[ counted: tb[node].name = refTC OR tb[node].name = listTC, var: tb[node].name = varTC, ordered: tb[node].attr1, basing: tb[node].attr2, list: tb[node].name = listTC, readOnly: tb[node].attr3, refType: ]; TypeExp[tb[node].son[1]]}; arrayTC => { sei ← MakeNonCtxSe[SERecord.cons.array.SIZE]; seb[sei].typeInfo ← array[ packed: tb[node].attr3, indexType: , componentType: ]; OptTypeExp[tb[node].son[1]]; TypeExp[tb[node].son[2]]}; arraydescTC => { sei ← MakeNonCtxSe[SERecord.cons.arraydesc.SIZE]; seb[sei].typeInfo ← arraydesc[ readOnly: tb[node].attr3, var: FALSE, describedType: ]; TypeExp[tb[node].son[1]]}; procTC, processTC, portTC, signalTC, errorTC, programTC => { modeMap: ARRAY Tree.NodeName[procTC..programTC] OF TransferMode = [ procTC: proc, processTC: process, portTC: port, signalTC: signal, errorTC: error, programTC: program]; sei ← MakeNonCtxSe[SERecord.cons.transfer.SIZE]; seb[sei].typeInfo ← transfer[ mode: modeMap[tb[node].name], safe: tb[node].attr3, typeIn: ArgList[tb[node].son[1]], typeOut: ArgList[tb[node].son[2]]]}; anyTC => sei ← TypeAny[]; definitionTC => { sei ← MakeNonCtxSe[SERecord.cons.definition.SIZE]; seb[sei].typeInfo ← definition[nGfi: 1, named: FALSE, defCtx: ]}; unionTC => sei ← Union[node, linkId]; sequenceTC => sei ← Sequence[node]; relativeTC => { sei ← MakeNonCtxSe[SERecord.cons.relative.SIZE]; seb[sei].typeInfo ← relative[baseType: , offsetType: , resultType: ]; TypeExp[tb[node].son[1]]; TypeExp[tb[node].son[2]]}; subrangeTC => { sei ← MakeNonCtxSe[SERecord.cons.subrange.SIZE]; seb[sei].typeInfo ← subrange[ filled: FALSE, empty: FALSE, rangeType: , origin: , range: ]; TypeExp[tb[node].son[1]]; Exp[tb[node].son[2]]}; longTC => { sei ← MakeNonCtxSe[SERecord.cons.long.SIZE]; seb[sei].typeInfo ← long[rangeType: ]; TypeExp[tb[node].son[1]]}; opaqueTC => { sei ← MakeNonCtxSe[SERecord.cons.opaque.SIZE]; seb[sei].typeInfo ← opaque[ lengthKnown: tb[node].son[1] # Tree.Null, length: 0, id: WITH seb[typeId] SELECT FROM id => LOOPHOLE[typeId], ENDCASE => ISENull]; Exp[tb[node].son[1]]}; zoneTC => { sei ← MakeNonCtxSe[SERecord.cons.zone.SIZE]; seb[sei].typeInfo ← zone[counted: ~tb[node].attr1, mds: tb[node].attr2]}; paintTC => { sei ← CSENull; TypeExp[tb[node].son[1]]; TypeExp[tb[node].son[2]]}; implicitTC, linkTC, frameTC => sei ← CSENull; dot, discrimTC => {TypeExp[tb[node].son[1]]; sei ← CSENull}; apply => {TypeExp[tb[node].son[1]]; Exp[tb[node].son[2]]; sei ← CSENull}; ENDCASE => {sei ← CSENull; Log.Error[nonTypeCons]}; tb[node].info ← sei}; ENDCASE => NULL}; OptTypeExp: PROC [t: Tree.Link] = {IF t # Tree.Null THEN TypeExp[t]}; Enumeration: PROC [node: Tree.Index] RETURNS [ctx: CTXIndex] = { saved: ContextInfo = current; NewContext[lZ, ListLength[tb[node].son[1]], TRUE]; ctx ← current.ctx; tb[node].son[1] ← Ids[ list: tb[node].son[1], public: tb[node].attr1, link: Tree.NullIndex]; current ← saved; RETURN}; AssignValues: PROC [type: CSEIndex, valueType: Type] = { WITH t: seb[type] SELECT FROM enumerated => { i: CARDINAL ← 0; FOR sei: ISEIndex ← FirstCtxSe[t.valueCtx], NextSe[sei] UNTIL sei = ISENull DO seb[sei].idType ← valueType; seb[sei].idInfo ← 0; seb[sei].idValue ← i; i ← i+1; seb[sei].immutable ← seb[sei].constant ← TRUE; seb[sei].mark3 ← seb[sei].mark4 ← TRUE; ENDLOOP; t.empty ← (i=0); t.nValues ← i}; ENDCASE => ERROR}; FieldList: PROC [t: Tree.Link, level: ContextLevel, typeId: Type] RETURNS [ctx: CTXIndex, nFields: NAT] = { saved: ContextInfo = current; nFields ← CountIds[t]; NewContext[level, nFields, TRUE]; ctx ← current.ctx; DeclList[t, typeId]; current ← saved; RETURN}; ArgList: PROC [t: Tree.Link] RETURNS [sei: CSEIndex] = { IF t = Tree.Null THEN sei ← RecordSENull ELSE IF OpName[t] = anyTC THEN sei ← TypeAny[] ELSE { tCtx: CTXIndex; nFields: NAT; sei ← MakeNonCtxSe[SERecord.cons.record.notLinked.SIZE]; [tCtx, nFields] ← FieldList[t, lZ, sei]; seb[sei].typeInfo ← record[ machineDep: FALSE, painted: FALSE, argument: TRUE, hints: [ unifield: nFields = 1, variant: FALSE, assignable: TRUE, comparable: FALSE, privateFields: FALSE, refField: FALSE, default: FALSE, voidable: TRUE], length: , fieldCtx: tCtx, monitored: FALSE, linkPart: notLinked[]]}; RETURN}; anySei: CSEIndex; TypeAny: PROC RETURNS [CSEIndex] = { IF anySei = CSENull THEN { anySei ← MakeNonCtxSe[SERecord.cons.any.SIZE]; seb[anySei] ← [mark3: TRUE, mark4: TRUE, body: cons[any[]]]}; RETURN [anySei]}; TagField: PROC [t: Tree.Link, MakeTagType: PROC RETURNS [CSEIndex]] RETURNS [tagId: ISEIndex] = { saved: ContextInfo = current; node: Tree.Index; current.ctx ← CTXNull; current.seChain ← MakeSeChain[CTXNull, 1, FALSE]; DeclList[t]; node ← GetNode[t]; tagId ← FirstId[tb[node].son[1]]; IF OpName[tb[node].son[2]] = implicitTC THEN { subNode: Tree.Index = GetNode[tb[node].son[2]]; IF MakeTagType # NIL THEN tb[subNode].info ← MakeTagType[] ELSE {Log.Error[attrClash]; tb[subNode].info ← typeANY}}; current ← saved; RETURN}; Union: PROC [node: Tree.Index, linkId: Type] RETURNS [sei: CSEIndex] = { saved: ContextInfo = current; MakeTagType: PROC RETURNS [type: CSEIndex] = { saved: ContextInfo = current; CollectTags: Tree.Scan = { node: Tree.Index = GetNode[t]; tb[node].son[1] ← Ids[ list: tb[node].son[1], public: tb[node].attr2, link: Tree.NullIndex ! NameClash => {RESUME}]}; NewContext[lZ, CountIds[tb[node].son[2]], TRUE]; type ← MakeNonCtxSe[SERecord.cons.enumerated.SIZE]; seb[type].typeInfo ← enumerated[ ordered: FALSE, sparse: FALSE, machineDep: FALSE, unpainted: ~dataPtr.interface, valueCtx: current.ctx, empty: , nValues: ]; ScanList[tb[node].son[2], CollectTags]; AssignValues[type, type]; current ← saved; RETURN}; tagId: ISEIndex = TagField[tb[node].son[1], MakeTagType]; NewContext[lZ, CountIds[tb[node].son[2]], TRUE]; DeclList[tb[node].son[2], linkId ! NameClash => {Log.ErrorHti[duplicateTag, name]; RESUME}]; sei ← MakeNonCtxSe[SERecord.cons.union.SIZE]; seb[sei].typeInfo ← union[ caseCtx: current.ctx, machineDep: tb[node].attr1, overlaid: tb[node].attr2, controlled: seb[tagId].hash # nullName, tagSei: tagId, hints: [ equalLengths: FALSE, refField: FALSE, default: FALSE, voidable: TRUE]]; current ← saved; RETURN}; Sequence: PROC [node: Tree.Index] RETURNS [sei: CSEIndex] = { tagId: ISEIndex = TagField[tb[node].son[1], NIL]; IF tb[node].attr2 THEN Log.Error[attrClash]; TypeExp[tb[node].son[2]]; sei ← MakeNonCtxSe[SERecord.cons.sequence.SIZE]; seb[sei].typeInfo ← sequence[ packed: tb[node].attr3, controlled: seb[tagId].hash # nullName, machineDep: tb[node].attr1, tagSei: tagId, componentType: ]; RETURN}; -- statements Stmt: PROC [stmt: Tree.Link] = { node: Tree.Index; saveIndex: CARDINAL = dataPtr.textIndex; IF stmt = Tree.Null THEN RETURN; WITH stmt SELECT FROM subtree => { node ← index; dataPtr.textIndex ← tb[node].info; SELECT tb[node].name FROM assign => {Exp[tb[node].son[1]]; Exp[tb[node].son[2]]}; extract => {ExpList[tb[node].son[1]]; Exp[tb[node].son[2]]}; apply => { Exp[tb[node].son[1]]; ExpList[tb[node].son[2]]; IF tb[node].nSons > 2 THEN CatchPhrase[tb[node].son[3]]}; block => Block[node]; if => { Exp[tb[node].son[1]]; StmtList[tb[node].son[2]]; StmtList[tb[node].son[3]]}; case => { Exp[tb[node].son[1]]; SelectionList[tb[node].son[2], Stmt]; Stmt[tb[node].son[3]]}; bind => { Exp[tb[node].son[1]]; Exp[tb[node].son[2]]; SelectionList[tb[node].son[3], Stmt]; Stmt[tb[node].son[4]]}; do => DoStmt[node]; return, resume => ExpList[tb[node].son[1]]; label => {StmtList[tb[node].son[1]]; StmtList[tb[node].son[2]]}; goto, exit, loop, reject, continue, retry, syserror, stop, null => NULL; free => { Exp[tb[node].son[1]]; Exp[tb[node].son[2]]; IF tb[node].nSons > 3 THEN CatchPhrase[tb[node].son[4]]}; signal, error, xerror, start, restart, join, wait, notify, broadcast, dst, lst, lste, lstf => Exp[tb[node].son[1]]; open => {ExpList[tb[node].son[1]]; StmtList[tb[node].son[2]]}; enable => {CatchPhrase[tb[node].son[1]]; StmtList[tb[node].son[2]]}; checked => Stmt[tb[node].son[1]]; list => ScanList[stmt, Stmt]; item => Stmt[tb[node].son[2]]; ENDCASE => Log.Error[unimplemented]}; ENDCASE => NULL; dataPtr.textIndex ← saveIndex}; StmtList: PROC [list: Tree.Link] = Stmt; Block: PROC [node: Tree.Index] = { saved: ContextInfo = current; bti: BTIndex = NewScope[node, tb[node].son[1]]; tb[node].info ← bti; StmtList[tb[node].son[2]]; BodyList[bb[bti].firstSon]; current ← saved; btLink ← [which:sibling, index:bti]}; SelectionList: PROC [t: Tree.Link, selection: Tree.Scan] = { Item: Tree.Scan = { node: Tree.Index = GetNode[t]; saveIndex: CARDINAL = dataPtr.textIndex; dataPtr.textIndex ← tb[node].info; IF OpName[tb[node].son[1]] # decl THEN { ExpList[tb[node].son[1]]; selection[tb[node].son[2]]} ELSE { saved: ContextInfo = current; bti: BTIndex = NewScope[node, tb[node].son[1]]; tb[node].name ← ditem; tb[node].info ← bti; tb[node].attr3 ← FALSE; selection[tb[node].son[2]]; current ← saved; btLink ← [which:sibling, index:bti]}; dataPtr.textIndex ← saveIndex}; ScanList[t, Item]}; DoStmt: PROC [node: Tree.Index] = { OPEN tb[node]; saved: ContextInfo = current; forTree: Tree.Link = tb[node].son[1]; bti: BTIndex ← BTNull; IF forTree # Tree.Null THEN { subTree: Tree.Link = NthSon[forTree, 1]; IF OpName[subTree] # decl THEN Exp[subTree] ELSE bti ← NewScope[node, subTree]; PutInfo[forTree, bti]; SELECT OpName[forTree] FROM forseq => {Exp[NthSon[forTree, 2]]; Exp[NthSon[forTree, 3]]}; upthru, downthru => Range[NthSon[forTree, 2]]; ENDCASE => ERROR}; Exp[tb[node].son[2]]; ExpList[tb[node].son[3]]; StmtList[tb[node].son[4]]; StmtList[tb[node].son[5]]; StmtList[tb[node].son[6]]; current ← saved; IF bti # BTNull THEN btLink ← [which:sibling, index:bti]}; CatchPhrase: PROC [t: Tree.Link] = { node: Tree.Index = GetNode[t]; saved: ContextInfo = current; NewContext[ level: NextLevel[saved.staticLevel], entries: 0, unique: FALSE]; SelectionList[tb[node].son[1], Stmt]; Stmt[tb[node].son[2]]; current ← saved}; -- expressions Exp: PROC [exp: Tree.Link] = { IF exp = Tree.Null THEN RETURN; WITH exp SELECT FROM subtree => { node: Tree.Index = index; SELECT tb[node].name FROM apply => { Exp[tb[node].son[1]]; ExpList[tb[node].son[2]]; IF tb[node].nSons > 2 THEN CatchPhrase[tb[node].son[3]]}; signalx, errorx, startx, fork, joinx, dot, uparrow, uminus, not, addr, create, cast => Exp[tb[node].son[1]]; plus, minus, times, div, mod, relE, relN, relL, relGE, relG, relLE, intOO, intOC, intCO, intCC, or, and, assignx => { Exp[tb[node].son[1]]; Exp[tb[node].son[2]]}; in, notin => {Exp[tb[node].son[1]]; Range[tb[node].son[2]]}; ifx => {Exp[tb[node].son[1]]; Exp[tb[node].son[2]]; Exp[tb[node].son[3]]}; casex => { Exp[tb[node].son[1]]; SelectionList[tb[node].son[2], Exp]; Exp[tb[node].son[3]]}; bindx => { Exp[tb[node].son[1]]; Exp[tb[node].son[2]]; SelectionList[tb[node].son[3], Exp]; Exp[tb[node].son[4]]}; extractx => {ExpList[tb[node].son[1]]; Exp[tb[node].son[2]]}; pred, succ, ord, lengthen, float, abs, min, max, base, length, all, val => ExpList[tb[node].son[1]]; arraydesc => { SELECT ListLength[tb[node].son[1]] FROM 1 => Exp[tb[node].son[1]]; 3 => { subNode: Tree.Index = GetNode[tb[node].son[1]]; Exp[tb[subNode].son[1]]; Exp[tb[subNode].son[2]]; OptTypeExp[tb[subNode].son[3]]}; ENDCASE => ERROR}; void, clit, llit, atom, mwconst, syserrorx => NULL; loophole => {Exp[tb[node].son[1]]; OptTypeExp[tb[node].son[2]]}; narrow, istype => { Exp[tb[node].son[1]]; OptTypeExp[tb[node].son[2]]; IF tb[node].nSons > 2 THEN CatchPhrase[tb[node].son[3]]}; new => { Exp[tb[node].son[1]]; TypeExp[tb[node].son[2]]; tb[node].son[3] ← InitialValue[tb[node].son[3], ISENull]; IF tb[node].nSons > 3 THEN CatchPhrase[tb[node].son[4]]}; cons, listcons => { Exp[tb[node].son[1]]; ExpList[tb[node].son[2]]; IF tb[node].nSons > 2 THEN CatchPhrase[tb[node].son[3]]}; first, last, typecode => TypeExp[tb[node].son[1]]; size => {TypeExp[tb[node].son[1]]; Exp[tb[node].son[2]]}; nil => OptTypeExp[tb[node].son[1]]; item => Exp[tb[node].son[2]]; ENDCASE => Log.Error[unimplemented]}; ENDCASE => NULL}; ExpList: PROC [list: Tree.Link] = INLINE {ScanList[list, Exp]}; Position: PROC [t: Tree.Link] = { IF OpName[t] = item THEN { node: Tree.Index = GetNode[t]; Exp[tb[node].son[1]]; Exp[tb[node].son[2]]} ELSE Exp[t]}; Range: PROC [t: Tree.Link] = { node: Tree.Index; WITH t SELECT FROM subtree => { node ← index; SELECT tb[node].name FROM subrangeTC => {TypeExp[tb[node].son[1]]; Exp[tb[node].son[2]]}; IN [intOO .. intCC] => Exp[t]; ENDCASE => TypeExp[t]}; ENDCASE => TypeExp[t]}; }.