DIRECTORY
Basics USING [bytesPerWord],
BasicTime USING [FromNSTime],
BcdDefs USING [BCD, FTIndex, FTSelf, Link, MTIndex, MTNull, MTRecord, SGIndex, SGNull, SGRecord, VersionStamp],
ConvertUnsafe USING [SubString],
DefaultRemoteNames USING [Get],
FS USING [Error, OpenFileFromStream, Read, StreamOpen],
ListerUtils USING [OpCodeArray, OpCodeArrayRep, OpCodeEntry],
Literals USING [LitDescriptor, LTIndex, LTNull, LTRecord, MSTIndex, STIndex, STNull],
IO USING [Close, EndOfStream, GetChar, GetInt, GetTokenRope, Put, PutChar, PutF, PutRope, SetIndex, SkipWhitespace, STREAM, UnsafeGetBlock],
Rope USING [Concat, Fetch, Flatten, Length, ROPE],
RuntimeError USING [UNCAUGHT],
SymbolPack,
Symbols USING [BitAddress, BodyRecord, BTIndex, ContextLevel, CSEIndex, CTXIndex, CTXNull, CTXRecord, ISEIndex, ISENull, lG, lL, lZ, MDIndex, Name, nullName, RootBti, SEIndex, SENull, SERecord, TransferMode, TypeClass, typeTYPE],
SymbolTable USING [Base],
Tree USING [Index, Link, Node, NodeName, NullIndex],
VM USING [AddressForPageNumber, Allocate, Free, Interval, MakeReadOnly];
T Y P E S & C O N S T A N T S
BCD: TYPE = BcdDefs.BCD;
BitAddress: TYPE = Symbols.BitAddress;
BTIndex: TYPE = Symbols.BTIndex;
BTRecord: TYPE = Symbols.BodyRecord;
bytesPerWord: NAT = Basics.bytesPerWord;
CSEIndex:
TYPE = Symbols.CSEIndex;
typeTYPE: CSEIndex = Symbols.typeTYPE;
ContextLevel:
TYPE = Symbols.ContextLevel;
lZ: ContextLevel = Symbols.lZ;
lG: ContextLevel = Symbols.lG;
lL: ContextLevel = Symbols.lL;
CTXIndex:
TYPE = Symbols.CTXIndex;
CTXNull: CTXIndex = Symbols.CTXNull;
CTXRecord: TYPE = Symbols.CTXRecord;
FTIndex:
TYPE = BcdDefs.FTIndex;
FTSelf: FTIndex = BcdDefs.FTSelf;
ISEIndex:
TYPE = Symbols.ISEIndex;
ISENull: ISEIndex = Symbols.ISENull;
ISERecord: TYPE = SERecord.id;
LTIndex:
TYPE = Literals.LTIndex;
LTNull: LTIndex = Literals.LTNull;
LTRecord: TYPE = Literals.LTRecord;
LitDescriptor: TYPE = Literals.LitDescriptor;
MDIndex: TYPE = Symbols.MDIndex;
MSTIndex:
TYPE = Literals.MSTIndex;
MSTNull: MSTIndex = LOOPHOLE[STNull];
MTIndex:
TYPE = BcdDefs.MTIndex;
MTNull: MTIndex = BcdDefs.MTNull;
MTRecord: TYPE = BcdDefs.MTRecord;
Name:
TYPE = Symbols.Name;
nullName: Name = Symbols.nullName;
NodeName: TYPE = Tree.NodeName;
RefBCD: TYPE = REF BCD;
RefMTRecord: TYPE = REF MTRecord;
RefSGRecord: TYPE = REF SGRecord;
RootBti: BTIndex = Symbols.RootBti;
ROPE: TYPE = Rope.ROPE;
SEIndex:
TYPE = Symbols.SEIndex;
SENull: SEIndex = Symbols.SENull;
SERecord: TYPE = Symbols.SERecord;
SGIndex:
TYPE = BcdDefs.SGIndex;
SGNull: SGIndex = BcdDefs.SGNull;
SGRecord: TYPE = BcdDefs.SGRecord;
STIndex:
TYPE = Literals.STIndex;
STNull: STIndex = Literals.STNull;
STREAM: TYPE = IO.STREAM;
SubString: TYPE = ConvertUnsafe.SubString;
SymbolTableBase: TYPE = SymbolTable.Base;
TransferMode: TYPE = Symbols.TransferMode;
TypeClass: TYPE = Symbols.TypeClass;
VersionStamp: TYPE = BcdDefs.VersionStamp;
Utility procedures
Some of these routines were cloned from various places to allow stream: STREAM and stb: SymbolTableBase as arguments, so we don't have to use global variables.
PrintSE:
PUBLIC PROC [sei: ISEIndex, nBlanks:
CARDINAL, definitionsOnly:
BOOL, stream:
STREAM, stb: SymbolTableBase] = {
sep: LONG POINTER TO ISERecord = @stb.seb[sei];
typeSei: SEIndex;
Indent[stream, nBlanks];
PrintSei[sei, stream, stb];
IO.PutRope[stream, " ["];
PrintIndex[sei, stream];
IO.PutChar[stream, ']];
IF sep.public THEN IO.PutRope[stream, " [public]"];
IF sep.mark3
THEN {
val: CARDINAL = LOOPHOLE[sep.idValue];
idInfo: CARDINAL = LOOPHOLE[sep.idInfo];
IO.PutRope[stream, ", type = "];
IF sep.idType = typeTYPE
THEN {
typeSei ← sep.idInfo;
IO.PutRope[stream, "TYPE, equated to: "];
PrintType[typeSei, stream, stb];
IF stb.ctxb[sep.idCtx].level = lZ
AND stb.TypeLink[sei] # SENull
THEN IO.PutF[stream, ", tag code: %g", [cardinal[val]]];
}
ELSE {
typeSei ← sep.idType;
PrintType[typeSei, stream, stb];
SELECT
TRUE
FROM
sep.constant => IO.PutRope[stream, " [const]"];
sep.immutable => IO.PutRope[stream, " [init only]"];
ENDCASE;
IF ~sep.mark4
THEN IO.PutF[stream, ", # refs: %g", [cardinal[idInfo]]]
ELSE
SELECT
TRUE
FROM
sep.constant =>
IF ~ sep.extended
THEN {
IO.PutRope[stream, ", value: "];
SELECT stb.XferMode[typeSei]
FROM
proc, program, signal, error =>
PrintBcdLink[LOOPHOLE[val], stream];
ENDCASE =>
IF val < 1000
THEN IO.Put [stream, [cardinal[val]]]
ELSE IO.PutF[stream, "%b", [cardinal[val]]];
};
(definitionsOnly
AND stb.ctxb[sep.idCtx].level = lG) =>
IO.PutF[stream, ", index: %g", [cardinal[val]]];
ENDCASE => {
addr: BitAddress = LOOPHOLE[val];
IO.PutF[
stream, ", address: %g [%g:%g]",
[cardinal[addr.wd]], [cardinal[addr.bd]], [cardinal[idInfo]]];
IF sep.linkSpace THEN IO.PutChar[stream, '*];
};
};
PrintTypeInfo[typeSei, nBlanks+2, stream, stb];
IF sep.extended THEN PrintTree[stb.FindExtension[sei].tree, nBlanks+4, stream, stb];
};
};
PrintType:
PUBLIC PROC [sei: SEIndex, stream:
STREAM, stb: SymbolTableBase] = {
tSei: SEIndex;
IF sei = SENull
THEN IO.PutChar[stream, '?]
ELSE
WITH t: stb.seb[sei]
SELECT
FROM
cons =>
WITH t
SELECT
FROM
transfer => WriteModeName[mode, stream];
ENDCASE => WriteTypeName[t.typeTag, stream];
id =>
FOR tSei ← sei, stb.TypeLink[tSei]
UNTIL tSei = SENull
DO
WITH stb.seb[tSei]
SELECT
FROM
id => {
IF sei # tSei THEN IO.PutChar[stream, ' ];
PrintSei[LOOPHOLE[tSei, ISEIndex], stream, stb];
IF ~mark3 OR stb.ctxb[idCtx].level # lZ THEN EXIT;
};
ENDCASE;
ENDLOOP;
ENDCASE;
IO.PutRope[stream, " ["];
PrintIndex[sei, stream];
IO.PutChar[stream, ']];
};
PrintTypeInfo:
PUBLIC PROC [sei: SEIndex, nBlanks:
CARDINAL, stream:
STREAM, stb: SymbolTableBase] = {
IF sei # SENull
THEN {
sp: LONG POINTER TO SERecord = @stb.seb[sei];
WITH s: sp
SELECT
FROM
cons => {
Indent[stream, nBlanks];
IO.PutChar[stream, '[];
PrintIndex[sei, stream];
IO.PutRope[stream, "] "];
WITH s
SELECT
FROM
transfer => WriteModeName[mode, stream];
ENDCASE => WriteTypeName[s.typeTag, stream];
WITH t: s
SELECT
FROM
basic => NULL;
enumerated => {
IF t.machineDep THEN IO.PutRope[stream, " (md)"]
ELSE IF t.unpainted THEN IO.PutRope[stream, " (~painted)"];
IO.PutRope[stream, ", value ctx: "];
PrintIndex[t.valueCtx, stream];
};
record => {
IF t.machineDep THEN IO.PutRope[stream, " (md)"];
IF t.monitored THEN IO.PutRope[stream, " (monitored)"];
IF t.hints.variant THEN IO.PutRope[stream, " (variant)"];
OutCtx[", field", t.fieldCtx, stream];
WITH stb.ctxb[t.fieldCtx]
SELECT
FROM
included => IF ~complete THEN IO.PutRope[stream, " [partial]"];
imported => IO.PutRope[stream, " [partial]"];
ENDCASE;
WITH t
SELECT
FROM
linked => {
IO.PutRope[stream, ", link: "];
PrintType[linkType, stream, stb]};
ENDCASE;
};
ref => {
SELECT
TRUE
FROM
t.counted => IO.PutRope[stream, " (counted)"];
t.var => IO.PutRope[stream, " (var)"];
ENDCASE;
IF t.ordered THEN IO.PutRope[stream, " (ordered)"];
IF t.basing THEN IO.PutRope[stream, " (base)"];
IO.PutRope[stream, ", to: "];
PrintType[t.refType, stream, stb];
IF t.readOnly THEN IO.PutRope[stream, " (readonly)"];
PrintTypeInfo[t.refType, nBlanks+2, stream, stb];
};
array => {
IF t.packed THEN IO.PutRope[stream, " (packed)"];
IO.PutRope[stream, ", index type: "];
PrintType[t.indexType, stream, stb];
IO.PutRope[stream, ", component type: "];
PrintType[t.componentType, stream, stb];
PrintTypeInfo[t.indexType, nBlanks+2, stream, stb];
PrintTypeInfo[t.componentType, nBlanks+2, stream, stb];
};
arraydesc => {
IO.PutRope[stream, ", described type: "];
PrintType[t.describedType, stream, stb];
IF t.readOnly THEN IO.PutRope[stream, " (readonly)"];
PrintTypeInfo[t.describedType, nBlanks+2, stream, stb];
};
transfer => {
IF t.safe THEN IO.PutRope[stream, " (safe)"];
OutArgType[", input", t.typeIn, stream, stb];
OutArgType[", output", t.typeOut, stream, stb];
};
definition => {
IO.PutRope[stream, ", ctx: "];
PrintIndex[t.defCtx, stream];
IO.PutF[stream, ", ngfi: %g", [cardinal[t.nGfi]]];
};
union => {
IF t.overlaid THEN IO.PutRope[stream, " (overlaid)"];
IF t.controlled
THEN {
IO.PutRope[stream, ", tag: "];
PrintSei[t.tagSei, stream, stb]};
IO.PutRope[stream, ", tag type: "];
PrintType[stb.seb[t.tagSei].idType, stream, stb];
IO.PutRope[stream, ", case ctx: "];
PrintIndex[t.caseCtx, stream];
IF t.controlled THEN PrintSE[t.tagSei, nBlanks+2, FALSE, stream, stb];
};
sequence => {
IF t.packed THEN IO.PutRope[stream, " (packed)"];
IF t.controlled
THEN {
IO.PutRope[stream, ", tag: "];
PrintSei[t.tagSei, stream, stb]}
ELSE {
IO.PutRope[stream, ", index type: "];
PrintType[stb.seb[t.tagSei].idType, stream, stb]};
IO.PutRope[stream, ", component type: "];
PrintType[t.componentType, stream, stb];
IF t.controlled
THEN PrintSE[t.tagSei, nBlanks+2, FALSE, stream, stb]
ELSE PrintTypeInfo[stb.seb[t.tagSei].idType, nBlanks+2, stream, stb];
PrintTypeInfo[t.componentType, nBlanks+2, stream, stb];
};
relative => {
IO.PutRope[stream, ", base type: "];
PrintType[t.baseType, stream, stb];
IO.PutRope[stream, ", offset type: "];
PrintType[t.offsetType, stream, stb];
PrintTypeInfo[t.baseType, nBlanks+2, stream, stb];
PrintTypeInfo[t.offsetType, nBlanks+2, stream, stb];
};
opaque => {
IO.PutRope[stream, ", id: "];
PrintSei[t.id, stream, stb];
IF t.lengthKnown
THEN
IO.PutF[stream, ", size: %g", [cardinal[t.length]]];
};
zone => {
IF t.counted THEN IO.PutRope[stream, " (counted)"];
IF t.mds THEN IO.PutRope[stream, " (mds)"];
};
subrange => {
IO.PutRope[stream, " of: "];
PrintType[t.rangeType, stream, stb];
IF t.filled
THEN {
IO.PutF[stream, " origin: %g", [integer[t.origin]]];
IO.PutF[stream, ", range: %g", [cardinal[t.range]]]};
PrintTypeInfo[t.rangeType, nBlanks+2, stream, stb];
};
long, real => {
IO.PutRope[stream, " of: "];
PrintType[t.rangeType, stream, stb];
PrintTypeInfo[t.rangeType, nBlanks+2, stream, stb];
};
ENDCASE;
};
ENDCASE
};
};
PrintTree:
PUBLIC PROC [tree: Tree.Link, nBlanks:
NAT, stream:
STREAM, stb: SymbolTableBase] = {
PrintSubTree:
PROC [tree: Tree.Link] = {
Indent[stream, nBlanks];
WITH s: tree
SELECT
FROM
hash =>
PrintName[s.index, stream, stb];
symbol => {
PrintSei[s.index, stream, stb];
IO.PutChar[stream, '[];
PrintIndex[s.index, stream];
IO.PutChar[stream, ']];
};
literal =>
PrintLiteral[s, stream, stb];
subtree => {
node: Tree.Index = s.index;
SELECT node
FROM
Tree.NullIndex => IO.PutRope[stream, "<empty>"];
Tree.Index.LAST => IO.PutRope[stream, "<last>"];
ENDCASE => {
tp: LONG POINTER TO Tree.Node ← @stb.tb[node];
IO.PutRope[stream, NodeNameTable[tp.name]];
IO.PutChar[stream, '[];
PrintIndex[node, stream];
IO.PutRope[stream, "] "];
IF tp.info # 0
THEN {
IO.PutRope[stream, " info="];
PrintIndex[tp.info, stream];
};
IF tp.attr1
OR tp.attr2
OR tp.attr3
THEN {
IF tp.info = 0 THEN IO.PutChar[stream, ' ];
IO.PutChar[stream, '(];
IF tp.attr1 THEN IO.PutChar[stream, '1];
IF tp.attr2 THEN IO.PutChar[stream, '2];
IF tp.attr3 THEN IO.PutChar[stream, '3];
IO.PutChar[stream, ')];
};
nBlanks ← nBlanks + 2;
IF tp.name # thread
THEN {
EndIndex: Tree.Index = Tree.Index.LAST;
EndMark: Tree.Link = [subtree[index: EndIndex]];
n: NAT = tp.nSons;
IF tp.name = list
AND n = 0
THEN
Very long lists have end markers, not explcit lengths.
FOR i:
NAT
IN [1..
NAT.
LAST]
DO
son: Tree.Link = tp.son[i];
IF son = EndMark THEN EXIT;
PrintSubTree[tp.son[i]];
ENDLOOP
ELSE
For all other nodes, believe the given length.
FOR i:
CARDINAL
IN [1 .. n]
DO
PrintSubTree[tp.son[i]];
ENDLOOP;
}
ELSE {
IO.PutRope[stream, " link="];
PrintTreeLink[tp.son[2], stream];
IO.PutRope[stream, " to "];
PrintTreeLink[tp.son[1], stream];
};
nBlanks ← nBlanks - 2};
};
ENDCASE => ERROR;
};
PrintSubTree[tree];
};
PrintLiteral:
PUBLIC PROC [t: Tree.Link.literal, stream:
STREAM, stb: SymbolTableBase] = {
WITH t.index
SELECT
FROM
string => {
msti: MSTIndex = MasterString[stb, sti];
s: LONG STRING = @stb.ltb[msti].string;
IO.PutChar[stream, '"];
FOR i: CARDINAL IN [0..s.length) DO IO.PutChar[stream, s[i]] ENDLOOP;
IO.PutChar[stream, '"];
IF sti # msti THEN IO.PutChar[stream, 'L]};
word => {
desc: Literals.LitDescriptor = DescriptorValue[stb, lti];
v: WORD;
IF desc.length # 1 THEN IO.PutChar[stream, '[];
FOR i:
CARDINAL
IN [0 .. desc.length)
DO
IF (v ← stb.ltb[desc.offset][i]) < 1000
THEN IO.Put[stream, [cardinal[v]]]
ELSE IO.PutF[stream, "%b", [cardinal[v]]]; -- octal
IF i+1 # desc.length THEN IO.PutChar[stream, ',];
ENDLOOP;
IF desc.length # 1 THEN IO.PutChar[stream, ']]};
ENDCASE;
PrintBcdLink:
PUBLIC PROC [link: BcdDefs.Link, stream:
STREAM] = {
SELECT
TRUE
FROM
link.proc =>
IO.PutF[stream, "proc[%g,%g]", [cardinal[link.gfi]], [cardinal[link.ep]]];
link.type => {
IO.PutRope[stream, "type["]; PrintIndex[link.typeID, stream]};
ENDCASE =>
IO.PutF[stream, "var[%g,%g]", [cardinal[link.gfi]], [cardinal[link.var]]];
};
PrintTreeLink:
PUBLIC PROC [link: Tree.Link, stream:
STREAM] = {
WITH t: link
SELECT
FROM
subtree => PrintIndex[t.index, stream];
hash => {IO.PutRope[stream, "hash#"]; PrintIndex[t.index, stream]};
symbol => {IO.PutRope[stream, "symbol#"]; PrintIndex[t.index, stream]};
literal => {IO.PutRope[stream, "literal#"]; PrintIndex[t.index, stream]};
ENDCASE => ERROR;
};
PrintSei:
PUBLIC PROC [sei: ISEIndex, stream:
STREAM, stb: SymbolTableBase] = {
PrintName[stb.NameForSe[sei], stream, stb];
};
PrintName:
PUBLIC PROC [name: Name, stream:
STREAM, stb: SymbolTableBase] = {
IF name = nullName
THEN IO.PutRope[stream, "(anon)"]
ELSE {
ss: SubString = stb.SubStringForName[name];
FOR i:
NAT
IN [ss.offset..ss.offset+ss.length)
DO
IO.PutChar[stream, ss.base[i]];
ENDLOOP;
};
};
WriteNodeName:
PUBLIC PROC [n: NodeName, stream:
STREAM] = {
IO.PutRope[stream, NodeNameTable[n]];
};
WriteTypeName:
PUBLIC PROC [n: TypeClass, stream:
STREAM] = {
IO.PutRope[stream, TypeNameTable[n]];
};
WriteModeName:
PUBLIC PROC [n: TransferMode, stream:
STREAM] = {
IO.PutRope[stream, ModeNameTable[n]];
};
OutCtx:
PUBLIC PROC [message: Rope.
ROPE, ctx: CTXIndex, stream:
STREAM] = {
IO.PutRope[stream, message];
IO.PutRope[stream, " ctx: "];
IF ctx = CTXNull THEN IO.PutRope[stream, "NIL"] ELSE PrintIndex[ctx, stream];
};
OutArgType:
PUBLIC PROC [message:
ROPE, sei: CSEIndex, stream:
STREAM, stb: SymbolTableBase] = {
IF sei = SENull
THEN {IO.PutRope[stream, message]; IO.PutRope[stream, ": NIL"]}
ELSE
WITH t: stb.seb[sei]
SELECT
FROM
record => OutCtx[message, t.fieldCtx, stream];
any => {IO.PutRope[stream, message]; IO.PutRope[stream, ": ANY"]};
ENDCASE
PrintVersion:
PUBLIC PROC [stamp: VersionStamp, stream:
STREAM, useTime:
BOOL ←
FALSE] = {
str: PACKED ARRAY [0..12) OF [0..16) = LOOPHOLE[stamp];
FOR i:
NAT
IN [0..12)
DO
d: [0..16) = str[i];
IF d < 10
THEN IO.PutChar[stream, '0+d]
ELSE IO.PutChar[stream, 'a-10+d];
ENDLOOP;
IF useTime
THEN {
IF stamp.net # 0
OR stamp.host # 0
THEN IO.PutF[stream, " (%g, %g, ", [cardinal[stamp.net]], [cardinal[stamp.host]]]
ELSE IO.PutRope[stream, " ("];
This next statement is separate to deal with potential errors in time conversion.
{
ENABLE RuntimeError.
UNCAUGHT =>
GO
TO dreck;
IO.PutF[
stream, "%g)",
[time[BasicTime.FromNSTime[stamp.time]]]
];
EXITS
dreck => IO.PutRope[stream, "??)"];
};
};
};
PrintStringFromTable:
PUBLIC PROC [index:
CARDINAL, stream:
STREAM, stb: SymbolTableBase] = {
str: LONG STRING = stb.ssb;
len: CARDINAL = str[index]-0C;
FOR i:
NAT
IN [1..
MIN[64, len]]
DO
IO.PutChar[stream, str[i]];
ENDLOOP;
};
PrintString:
PUBLIC PROC [str:
LONG
STRING, stream:
STREAM] = {
IF str #
NIL
THEN
FOR i:
NAT
IN [0..str.length)
DO
IO.PutChar[stream, str[i]];
ENDLOOP;
};
PrintSubString:
PUBLIC PROC [ss: SubString, stream:
STREAM] = {
FOR i:
NAT
IN [ss.offset..ss.offset+ss.length)
DO
IO.PutChar[stream, ss.base[i]];
ENDLOOP;
};
PrintIndex:
PUBLIC PROC [index:
UNSPECIFIED, stream:
STREAM] = {
IO.Put[stream, [integer[LOOPHOLE[index, CARDINAL]]]];
};
Indent:
PUBLIC PROC [stream:
STREAM, nBlanks:
NAT] = {
IO.PutChar[stream, '\n];
THROUGH [0..nBlanks) DO IO.PutChar[stream, ' ]; ENDLOOP;
};
DescriptorValue:
PUBLIC PROC [stb: SymbolTableBase, lti: LTIndex]
RETURNS [LitDescriptor] = {
WITH entry: stb.ltb[lti]
SELECT
FROM
short => {
deltaShort: CARDINAL = LOOPHOLE[@(NIL[POINTER TO LTRecord.short]).value];
RETURN [[offset: LOOPHOLE[lti + deltaShort], length: 1]];
};
long => {
deltaLong: CARDINAL = LOOPHOLE[@(NIL[POINTER TO LTRecord.long]).value];
RETURN [[offset: LOOPHOLE[lti + deltaLong], length: entry.length]];
};
ENDCASE => ERROR;
MasterString:
PUBLIC PROC [stb: SymbolTableBase, sti: STIndex]
RETURNS [MSTIndex ← MSTNull] = {
WITH s: stb.ltb[sti]
SELECT
FROM
master => RETURN[LOOPHOLE[sti]];
copy => RETURN[s.link];
heap => RETURN[s.link];
ENDCASE;
};
ShortName:
PUBLIC PROC [rope:
ROPE]
RETURNS [
ROPE] = {
pos: INT ← Rope.Length[rope];
bang: INT ← pos;
WHILE pos > 0
DO
under: INT = pos - 1;
SELECT Rope.Fetch[rope, under]
FROM
'! => bang ← under;
'>, '/, '<, '] => RETURN [Rope.Flatten[rope, pos, bang-pos]];
ENDCASE;
pos ← under;
ENDLOOP;
RETURN [rope];
};
T A B L E S
NodeNameArray: TYPE = ARRAY NodeName OF ROPE;
NodeNameTable: PUBLIC REF NodeNameArray = NEW[NodeNameArray ←[
"list", "item", "decl", "typedecl", "basicTC", "enumeratedTC", "recordTC", "monitoredTC", "variantTC", "refTC", "pointerTC", "listTC", "arrayTC", "arraydescTC", "sequenceTC", "procTC", "processTC", "portTC", "signalTC", "errorTC", "programTC", "anyTC", "definitionTC", "unionTC", "relativeTC", "subrangeTC", "longTC", "opaqueTC", "zoneTC", "linkTC", "varTC", "implicitTC", "frameTC", "discrimTC", "paintTC", "spareTC", "unit", "diritem", "module", "body", "inline", "lambda", "block", "assign", "extract", "if", "case", "casetest", "caseswitch", "bind", "do", "forseq", "upthru", "downthru", "return", "result", "goto", "exit", "loop", "free", "resume", "reject", "continue", "retry", "catchmark", "restart", "stop", "lock", "wait", "notify", "broadcast", "unlock", "null", "label", "open", "enable", "catch", "dst", "lste", "lstf", "syscall", "checked", "lst", "spareS3", "subst", "call", "portcall", "signal", "error", "syserror", "xerror", "start", "join", "apply", "callx", "portcallx", "signalx", "errorx", "syserrorx", "startx", "fork", "joinx", "index", "dindex", "seqindex", "reloc", "construct", "union", "rowcons", "sequence", "listcons", "substx", "ifx", "casex", "bindx", "assignx", "extractx", "or", "and", "relE", "relN", "relL", "relGE", "relG", "relLE", "in", "notin", "plus", "minus", "times", "div", "mod", "dot", "cdot", "dollar", "create", "not", "uminus", "addr", "uparrow", "min", "max", "lengthen", "abs", "all", "size", "first", "last", "pred", "succ", "arraydesc", "length", "base", "loophole", "nil", "new", "void", "clit", "llit", "cast", "check", "float", "pad", "chop", "safen", "syscallx", "narrow", "istype", "openx", "mwconst", "cons", "atom", "typecode", "stringinit", "textlit", "signalinit", "procinit", "intOO", "intOC", "intCO", "intCC", "thread", "none", "exlist", "initlist", "ditem", "shorten", "self", "gcrt", "proccheck", "ord", "val", "entry", "internal", "mergecons"]];
TypeNameArray: TYPE = ARRAY TypeClass OF ROPE;
TypeNameTable: REF TypeNameArray = NEW[TypeNameArray ← [
"mode", "basic", "enumerated", "record", "ref", "array", "arraydesc", "transfer", "definition", "union", "sequence", "relative", "subrange", "long", "real", "opaque", "zone", "any", "nil"]];
ModeNameArray: TYPE = ARRAY TransferMode OF ROPE;
ModeNameTable:
PUBLIC
REF ModeNameArray =
NEW[ModeNameArray ← [
"proc", "port", "signal", "error", "process", "program", "none"]];