Pass3B.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Satterthwaite, April 4, 1986 9:18:48 am PST
Maxwell, August 2, 1983 3:17 pm
Paul Rovner, September 7, 1983 4:14 pm
Russ Atkinson (RRA) March 6, 1985 10:39:44 pm PST
DIRECTORY
Alloc: TYPE USING [Notifier, AddNotify, DropNotify, Words],
ComData: TYPE USING [importCtx, interface, moduleCtx, objectStamp, outerCtx, table, textIndex],
ConvertUnsafe: TYPE USING [ToRope],
Copier: TYPE USING [CreateFileTable, EnterFile, FileVersionMix, FillModule, SearchFileCtx, UnknownModule],
LiteralOps: TYPE USING [StringIndex, StringValue],
Log: TYPE USING [ErrorHti, ErrorSei, ErrorTree],
OSMiscOps: TYPE USING [MergeStamps, TimeToStamp],
P3: TYPE USING [mark, EnterIdList, Exp, MakeIdTable, MakeFrameRecord, MakeRefType, PopCtx, PushCtx, RAttr, RPop, Shared, UType],
Rope: TYPE USING [ROPE],
SourceMap: TYPE USING [Loc],
Symbols: TYPE USING [Base, SERecord, CTXRecord, Name, ISEIndex, CSEIndex, CTXIndex, IncludedCTXIndex, MDIndex, CBTIndex, nullName, ISENull, CTXNull, RootBti, BTNull, lG, OwnMdi, typeANY, seType, ctxType, mdType, bodyType],
SymbolOps: TYPE USING [FillCtxSe, FirstCtxSe, LinkMode, MakeCtxSe, MakeNonCtxSe, NameClash, NewCtx, NextSe, SearchContext, UnderType],
Tree: TYPE USING [Base, Index, Link, Map, Scan, Test, Null, NullIndex, treeType],
TreeOps: TYPE USING [GetHash, GetNode, ListLength, ScanList, SearchList, UpdateList];
Pass3B: PROGRAM
IMPORTS Alloc, ConvertUnsafe, Copier, LiteralOps, Log, OSMiscOps, P3, SymbolOps, TreeOps, dataPtr: ComData
EXPORTS P3 = {
OPEN TreeOps, SymbolOps, Symbols, 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)
BCDNotify: 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]};
GetSe: PROC[t: Tree.Link] RETURNS[ISEIndex] = {
RETURN[WITH t SELECT FROM
symbol => index,
subtree => GetSe[tb[index].son[1]],
ENDCASE => ERROR]
};
ItemLabel: PROC[node: Tree.Index] RETURNS[ISEIndex] = INLINE {
RETURN[GetSe[tb[node].son[1]]]};
MemberId: PROC[id: Name, list: Tree.Link] RETURNS[found: BOOLFALSE] = {
TestItem: Tree.Test = {
RETURN[WITH t SELECT FROM
hash => IF index = id THEN (found ← TRUE) ELSE FALSE,
subtree => TestItem[tb[index].son[1]],
ENDCASE => FALSE]
};
SearchList[list, TestItem];
RETURN};
module header
HashTest: TYPE = PROC[id: Name] RETURNS[BOOL];
Header: PUBLIC PROC[node: Tree.Index] = {
TestShared: HashTest = {
RETURN[MemberId[id, tb[node].son[3]] OR MemberId[id, tb[node].son[4]]]};
(dataPtr.table).AddNotify[BCDNotify];
Directory[directory: tb[node].son[1], shared: TestShared];
ScanList[tb[node].son[4], Sharing];
PushCtx[dataPtr.outerCtx]; PushCtx[dataPtr.moduleCtx];
Interfaces[imports: tb[node].son[2], exports: tb[node].son[3]];
PopCtx[]; PopCtx[];
(dataPtr.table).DropNotify[BCDNotify]};
directory processing
Directory: PROC[directory: Tree.Link, shared: HashTest] = {
nIdLists: CARDINAL;
mdb[OwnMdi].moduleId ← seb[bb[RootBti].id].hash;
nIdLists ← DirectoryScan[directory];
MakeIdTable[nIdLists];
DirectoryDecls[directory, shared]};
MdiMap: TYPE = RECORD[SEQUENCE length: CARDINAL OF MDIndex];
mdiMap: REF MdiMap;
DirectoryScan: PROC[t: Tree.Link] RETURNS[nLists: CARDINAL ← 0] = {
i: CARDINAL ← 0;
FileEntry: Tree.Scan = {
node: Tree.Index = GetNode[t];
formalId: Name = seb[ItemLabel[node]].hash;
typeId: Name = WITH tb[node].son[2] SELECT FROM
hash => index,
ENDCASE => formalId;
mdiMap[i] ← Copier.EnterFile[formalId, typeId, TreeStringValue[tb[node].son[2]]
! Copier.FileVersionMix => {IF hti = typeId THEN RESUME ELSE REJECT}];
i ← i + 1;
IF tb[node].son[3] # Tree.Null THEN nLists ← nLists+1};
n: CARDINAL = ListLength[t];
Copier.CreateFileTable[n];
mdiMap ← NEW[MdiMap[n]];
ScanList[t, FileEntry];
RETURN};
TreeStringValue: PROC[t: Tree.Link] RETURNS[Rope.ROPE] = {
RETURN[WITH t SELECT FROM
s: Tree.Link.literal =>
ConvertUnsafe.ToRope[LiteralOps.StringValue[LiteralOps.StringIndex[s.index]]],
ENDCASE => NIL]
};
DirectoryDecls: PROC[directory: Tree.Link, shared: HashTest] = {
i: CARDINAL ← 0;
DirectoryItem: Tree.Scan = {
node: Tree.Index = GetNode[t];
sei: ISEIndex = ItemLabel[node];
key: Name = WITH tb[node].son[2] SELECT FROM
hash => index,
ENDCASE => seb[sei].hash;
type: CSEIndex;
ctx: CTXIndex;
bti: CBTIndex;
saveIndex: SourceMap.Loc = dataPtr.textIndex;
dataPtr.textIndex ← tb[node].info;
tb[node].attr2 ← tb[node].attr3 ← P3.mark;
Copier.FillModule[sei, key, mdiMap[i]
! Copier.UnknownModule => {Log.ErrorHti[moduleId, hti]; RESUME}];
type ← UnderType[seb[sei].idType];
ctx ← WITH t: seb[type] SELECT FROM
definition => t.defCtx,
transfer => IF (bti←seb[sei].idInfo) # BTNull THEN bb[bti].localCtx ELSE CTXNull,
ENDCASE => CTXNull;
IF ctx # CTXNull THEN {
WITH c: ctxb[ctx] SELECT FROM
included => {
dataPtr.objectStamp ← OSMiscOps.MergeStamps[
dataPtr.objectStamp, OSMiscOps.TimeToStamp[mdb[c.module].stamp]];
mdb[c.module].shared ← shared[seb[sei].hash]};
ENDCASE;
tb[node].son[3] ← IncludedIds[ctx, tb[node].son[3]
! Copier.FileVersionMix => {IF hti=key THEN RESUME ELSE REJECT}]
};
i ← i + 1;
dataPtr.textIndex ← saveIndex};
ScanList[directory, DirectoryItem];
mdiMap ← NIL};
IncludedIds: PROC[ctx: CTXIndex, list: Tree.Link] RETURNS[val: Tree.Link] = {
includedCtx: IncludedCTXIndex;
IncludedId: Tree.Map = {
WITH t SELECT FROM
hash => {
id: Name = index;
sei: ISEIndex;
found, duplicate, update: BOOL;
CheckDuplicate: Tree.Test = {
RETURN[WITH t SELECT FROM
symbol => IF index = sei THEN (duplicate ← TRUE) ELSE FALSE,
ENDCASE => TRUE]};
sei ← SearchContext[id, ctx];
IF sei = ISENull THEN {
[found, sei] ← Copier.SearchFileCtx[id, includedCtx]; update ← found}
ELSE {
found ← TRUE; update ← LinkMode[sei] = manifest;
duplicate ← FALSE; SearchList[list, CheckDuplicate];
IF duplicate THEN Log.ErrorHti[duplicateId, id]};
IF found THEN {
IF ~seb[sei].public AND ~Shared[includedCtx] THEN {
Log.ErrorSei[privateId, sei]; seb[sei].public ← TRUE};
IF update THEN seb[sei].idCtx ← CTXNull;
v ← [symbol[index: sei]]}
ELSE {Log.ErrorHti[unknownId, id]; v ← t}};
ENDCASE => ERROR;
RETURN};
WITH c: ctxb[ctx] SELECT FROM
included =>
IF list # Tree.Null THEN {
includedCtx ← LOOPHOLE[ctx];
c.restricted ← TRUE;
val ← UpdateList[list, IncludedId];
EnterIdList[includedCtx, val]}
ELSE val ← Tree.Null;
ENDCASE => ERROR;
RETURN};
Sharing: Tree.Scan = {
id: Name = GetHash[t];
sei: ISEIndex = SearchContext[id, dataPtr.moduleCtx];
IF sei = ISENull THEN Log.ErrorHti[unknownId, id]
ELSE {
type: CSEIndex = UnderType[seb[sei].idType];
ctx: CTXIndex ← CTXNull;
WITH t: seb[type] SELECT FROM
definition => ctx ← t.defCtx;
transfer =>
IF seb[sei].mark4 AND seb[sei].constant AND t.mode = program THEN
ctx ← bb[LOOPHOLE[seb[sei].idInfo, CBTIndex]].localCtx;
ENDCASE;
IF ctx = CTXNull AND type # typeANY THEN Log.ErrorTree[nonInterface, t]}
};
ImportType: PROC[mdi: MDIndex] RETURNS[CSEIndex] = {
sei: ISEIndex;
type: CSEIndex;
FOR sei ← FirstCtxSe[dataPtr.moduleCtx], NextSe[sei] UNTIL sei = ISENull DO
type ← UnderType[seb[sei].idType];
WITH t: seb[type] SELECT FROM
definition =>
WITH c: ctxb[t.defCtx] SELECT FROM
imported => IF ctxb[c.includeLink].module = mdi THEN GO TO Found;
ENDCASE;
ENDCASE;
REPEAT
Found => NULL;
FINISHED => {
sei ← MakeCtxSe[mdb[mdi].moduleId, CTXNull];
Copier.FillModule[sei, seb[sei].hash, mdi]};
ENDLOOP;
RETURN[UnderType[seb[sei].idType]]};
import/export processing
Interfaces: PROC[imports, exports: Tree.Link] = INLINE {
ScanList[imports, ImportItem];
ScanList[exports, ExportItem]};
ImportItem: Tree.Scan = {
node: Tree.Index = GetNode[t];
sei: ISEIndex = ItemLabel[node];
type, vType: CSEIndex;
const: BOOL;
saveIndex: SourceMap.Loc = dataPtr.textIndex;
dataPtr.textIndex ← tb[node].info;
tb[node].attr2 ← tb[node].attr3 ← P3.mark;
tb[node].son[2] ← Exp[tb[node].son[2], typeANY];
vType ← UType[]; const ← RAttr[].const; RPop[];
WITH v: seb[vType] SELECT FROM
definition =>
SELECT ctxb[v.defCtx].ctxType FROM
included => {
type ← ImportInstance[iType: vType, named: tb[node].attr1];
IF tb[node].attr1 AND dataPtr.interface THEN Log.ErrorSei[nonDefinition, sei]};
ENDCASE => {type ← typeANY; Log.ErrorTree[notPortable, tb[node].son[2]]};
transfer => {
IF v.mode # program OR dataPtr.interface THEN
Log.ErrorTree[notPortable, tb[node].son[2]];
seb[sei].immutable ← TRUE;
type ← MakeRefType[MakeFrameRecord[tb[node].son[2]], typeANY];
const ← FALSE};
ENDCASE => {
IF vType # typeANY THEN Log.ErrorTree[nonInterface, tb[node].son[2]];
type ← typeANY};
seb[sei].idType ← type;
seb[sei].immutable ← TRUE; seb[sei].constant ← const; seb[sei].idInfo ← 1;
seb[sei].mark3 ← TRUE;
dataPtr.textIndex ← saveIndex};
ImportInstance: PROC[iType: CSEIndex, named: BOOL] RETURNS[type: CSEIndex] = {
WITH t: seb[iType] SELECT FROM
definition =>
WITH c: ctxb[t.defCtx] SELECT FROM
included => {
ctx: CTXIndex = NewImportedCtx[LOOPHOLE[t.defCtx]];
type ← MakeNonCtxSe[SERecord.cons.definition.SIZE];
seb[type] ← SERecord[mark3: TRUE, mark4: TRUE,
body: cons[definition[
nDummyGfi: t.nDummyGfi, named: named, defCtx: ctx]]];
IF ~named THEN mdb[c.module].defaultImport ← ctx};
ENDCASE => ERROR;
ENDCASE => type ← typeANY;
RETURN};
NewImportedCtx: PROC[link: IncludedCTXIndex] RETURNS[ctx: CTXIndex] = {
ctx ← (dataPtr.table).Words[ctxType, CTXRecord.imported.SIZE];
ctxb[ctx] ← CTXRecord[
levelOrigin: ctxb[link].levelOrigin, levelOffset: ctxb[link].levelOffset,
seList: ISENull, varUpdated: FALSE,
extension: imported[includeLink: link]];
RETURN};
ExportItem: Tree.Scan = {
node: Tree.Index = GetNode[t];
type: CSEIndex;
saveIndex: SourceMap.Loc = dataPtr.textIndex;
dataPtr.textIndex ← tb[node].info;
tb[node].son[2] ← Exp[tb[node].son[2], typeANY]; type ← UType[]; RPop[];
WITH d: seb[type] SELECT FROM
definition => {
WITH c: ctxb[d.defCtx] SELECT FROM
included => mdb[c.module].exported ← TRUE;
ENDCASE => Log.ErrorTree[notPortable, tb[node].son[2]]};
ENDCASE => IF type # typeANY THEN Log.ErrorTree[nonInterface, tb[node].son[2]];
dataPtr.textIndex ← saveIndex};
SetDefaultImport: PUBLIC PROC[iCtx: IncludedCTXIndex, implicitOK: BOOL] = {
mdi: MDIndex;
(dataPtr.table).AddNotify[BCDNotify];
mdi ← ctxb[iCtx].module;
IF mdb[mdi].defaultImport = CTXNull THEN {
sei: ISEIndex;
type: CSEIndex;
n: CARDINAL ← 0;
IF dataPtr.importCtx = CTXNull THEN dataPtr.importCtx ← NewCtx[lG];
FOR sei ← FirstCtxSe[dataPtr.importCtx], NextSe[sei] UNTIL sei = ISENull DO
type ← UnderType[seb[sei].idType];
WITH t: seb[type] SELECT FROM
definition =>
WITH c: ctxb[t.defCtx] SELECT FROM
imported =>
IF ctxb[c.includeLink].module = mdi THEN {
mdb[mdi].defaultImport ← t.defCtx; n ← n+1};
ENDCASE;
ENDCASE;
ENDLOOP;
SELECT n FROM
0 => {
IF ~implicitOK THEN Log.ErrorHti[missingImport, mdb[mdi].moduleId];
sei ← MakeCtxSe[nullName, dataPtr.importCtx];
FillCtxSe[sei, mdb[mdi].moduleId, FALSE
! NameClash => {Log.ErrorHti[missingImport, name]; RESUME}];
seb[sei].immutable ← seb[sei].constant ← TRUE;
seb[sei].linkSpace ← seb[sei].extended ← FALSE;
seb[sei].idType ← ImportInstance[iType: ImportType[mdi], named:FALSE];
seb[sei].idInfo ← 1; seb[sei].idValue ← Tree.NullIndex;
seb[sei].mark3 ← TRUE; seb[sei].mark4 ← FALSE};
1 => NULL;
ENDCASE => Log.ErrorHti[missingImport, mdb[mdi].moduleId];
IF mdb[mdi].defaultImport = CTXNull THEN mdb[mdi].defaultImport ← NewImportedCtx[iCtx]};
(dataPtr.table).DropNotify[BCDNotify]};
}.