SaffronContextShowImpl.Mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Sturgis, July 15, 1987 12:56:40 pm PDT
Bill Jackson (bj) August 12, 1987 5:17:21 pm PDT
Lucy Hederman August 14, 1987 4:47:52 pm PDT
DIRECTORY
IO USING [ int, PutF, PutRope, rope, STREAM ],
Rope USING [ Cat, ROPE ],
SaffronBaseDef USING [ ],
SaffronGenericDef USING [ IdNode ],
SaffronContext USING [ ],
SaffronContextPrivateTypes USING[AccessValNode, ArrayTGN, BaseTypeTGN, BoundsValNode, ContextRibNode, ContextTreeNodeBody, CTCell, DefaultExpNode, DescriptorTGN, EnumElementCell, EnumTGN, EnvironmentNodeBody, ExpPTreeNode, FrozenFieldListNode, FrozenUnionList, GenRopeNames, GenVisibleNames, InterfaceTGN, InterfaceValNode, LinkTGN, ListTGN, LocalContextNodeBody, LongTGN, NamedTGN, OpaqueTGN, PaintNode, PointerTGN, PositionValNode, RecordTGN, ReferentTGN, RefTGN, RelativeTGN, SequenceTGN, SpecialTGN, SpecianatedTGN, SubrangeTGN, TransferTGN, TypeGraphNodeNode, VariantFlavorNode, VariantFlavorNodeBody, VariantPartTGN, VarTGN, VisibleNames, ZoneTGN];
SaffronContextShowImpl: CEDAR PROGRAM
IMPORTS IO, Rope, SaffronContextPrivateTypes
EXPORTS SaffronBaseDef, SaffronContext ~ {
OPEN SaffronBaseDef, SaffronContextPrivateTypes, SaffronGenericDef;
Environment Operations
EnvironmentNode: TYPE ~ REF EnvironmentNodeBody;
EnvironmentNodeBody: PUBLIC TYPE ~ SaffronContextPrivateTypes.EnvironmentNodeBody;
ShowEnvironment: PUBLIC PROC [on: IO.STREAM, nest: INT, env: EnvironmentNode] =
BEGIN
OneInterface: PROC[name: Rope.ROPE, raif: REF ANY] =
BEGIN
IO.PutF[on, "%g interface\N", IO.rope[name]];
ShowNested[on, nest];
ShowInterface[on, nest, NARROW[raif]];
END;
IO.PutRope[on, "\n\n"];
ShowNested[on, nest]; IO.PutF[on, "Environment\N"];
SaffronContextPrivateTypes.GenRopeNames[env.interfaces, OneInterface];
END;
Interface Operations
ShowInterface: PROC [on: IO.STREAM, nest: INT, if: InterfaceValNode] =
BEGIN
IO.PutRope[on, "\n\n"];
ShowNested[on, nest]; IO.PutF[on, "Interface\N"];
ShowNested[on, nest];
ShowContextTree[on, nest, if.ct];
IO.PutRope[on, "\n\n"];
ShowNested[on, nest]; IO.PutF[on, "types visible in interface\N"];
ShowNested[on, nest];
ShowLocallyVisibleTypes[on, nest, if.entries];
END;
Context Operations
RealShowLocalContext: PROC [on: IO.STREAM, nest: INT, lc: LocalContextNode] ~ {
FOR tgn: TypeGraphNodeNode ← lc.tgNodes, tgn.next WHILE ( tgn # NIL ) DO
tgn.shown ← FALSE;
ENDLOOP;
FOR fl: FrozenFieldListNode ← lc.fieldLists, fl.next WHILE ( fl # NIL ) DO
fl.shown ← FALSE;
ENDLOOP;
IO.PutRope[on, "\n\n"]; ShowNested[on, nest];
IO.PutRope[on, "locally visible types\n"]; ShowNested[on, nest+2];
ShowLocallyVisibleTypes[on, nest+2, lc.lvtn];
IO.PutRope[on, "\n\n"]; ShowNested[on, nest]; IO.PutRope[on, "other nodes"];
FOR tgn: TypeGraphNodeNode ← lc.tgNodes, tgn.next WHILE ( tgn # NIL ) DO
IF NOT tgn.shown THEN {
IO.PutRope[on, "\n\n"]; ShowNested[on, nest+2];
ShowTGN[on, nest+2, tgn];
}
ENDLOOP;
IO.PutRope[on, "\n\n"];
};
none of the internal nodes are visible from outside, so just trees
ShowLocallyVisibleTypes: PROC [ on: IO.STREAM, nest: INT, lvtn: VisibleNames ] ~ {
first: BOOLEANTRUE;
ShowOneLVTGN: PROC [ name: IdNode, access: AccessValNode, value: REF ANY ] ~ {
IF NOT first THEN { IO.PutRope[on, "\n\n"]; ShowNested[on, nest] };
first ← FALSE;
IO.PutRope[on, RopeForId[name]];
ShowAVN[on, nest, access];
IO.PutRope[on, "\n"]; ShowNested[on, nest+2];
ShowNamedTGNTree[on, nest+4, NARROW[value]];
};
IO.PutRope[on, "\n"]; ShowNested[on, nest];
GenVisibleNames[lvtn, ShowOneLVTGN];
};
Idea is that this routine will print out address of node on current line, and allow called routine to put more info on that line, or on subsequent lines.
Nodes will be marked to show that they have been printed, so we do not progress any deaper on previously printed nodes.
We do not proceed passed a named node in any case. (ShowNamedTGNTree will do that)
We assume that we have been positioned on current line, and that the caller will supply the final carriage return.
ShowTGN: PROC [on: IO.STREAM, nest: INT, tgn: TypeGraphNodeNode, short: BOOLEAN ← FALSE] ~ {
IO.PutF[on, "[%g](%g): ", IO.int[tgn.index], IO.int[LOOPHOLE[tgn, INT]]];
IF NOT short THEN
BEGIN
IF tgn.shown THEN
WITH tgn.body SELECT FROM
ntgn: NamedTGN => ShowNamedTGN[on, nest, ntgn, TRUE];
ENDCASE => NULL
ELSE {
tgn.shown ← TRUE;
WITH tgn.body SELECT FROM
ntgn: NamedTGN => ShowNamedTGN[on, nest, ntgn, TRUE];
spctgn: SpecialTGN => ShowSpecialTGN[on, nest, spctgn];
srtgn: SubrangeTGN => ShowSubrangeTGN[on, nest, srtgn];
rn: RecordTGN => ShowRecordTGN[on, nest, rn];
ptgn: PointerTGN => ShowPointerTGN[on, nest, ptgn];
rtgn: RefTGN => ShowRefTGN[on, nest, rtgn];
vtgn: VarTGN => ShowVarTGN[on, nest, vtgn];
rtgn: RelativeTGN => ShowRelativeTGN[on, nest, rtgn];
refenttgn: ReferentTGN => ShowReferentTGN[on, nest, refenttgn];
ltgn: ListTGN => ShowListTGN[on, nest, ltgn];
etgn: EnumTGN => ShowEnumTypeTGN[on, nest, etgn];
vptgn: VariantPartTGN => ShowVariantPartTGN[on, nest, vptgn];
stgn: SequenceTGN => ShowSequenceTGN[on, nest, stgn];
atgn: ArrayTGN => ShowArrayTGN[on, nest, atgn];
dtgn: DescriptorTGN => ShowDescriptorTGN[on, nest, dtgn];
ttgn: TransferTGN => ShowTransferTGN[on, nest, ttgn];
ztgn: ZoneTGN => ShowZoneTGN[on, nest, ztgn];
ltgn: LongTGN => ShowLongTGN[on, nest, ltgn];
itgn: InterfaceTGN => ShowInterfaceTGN[on, nest, itgn];
linktgn: LinkTGN => ShowLinkTGN[on, nest, linktgn];
otgn: OpaqueTGN => ShowOpaqueTGN[on, nest, otgn];
stgn: SpecianatedTGN => ShowSpecianatedTGN[on, nest, stgn];
bttgn: BaseTypeTGN => ShowBaseTypeTGN[on, nest, bttgn];
ENDCASE => ERROR;
}
END;
};
ShowNamedTGNTree: PROC [ on: IO.STREAM, nest: INT, tgn: TypeGraphNodeNode ] ~ {
ntgn: NamedTGN ← NARROW[tgn.body];
ShowNamedTGN[on, nest, ntgn, FALSE];
tgn.shown ← TRUE;
};
ShowTGNAsNamedSubstructure: PROC [ on: IO.STREAM, nest: INT, name: Rope.ROPE,
tgn: TypeGraphNodeNode ] ~ {
IO.PutF[on, "\n"]; ShowNested[on, nest+2]; IO.PutF[on, "%g ", IO.rope[name]];
ShowTGN[on, nest+2, tgn];
};
Now for the assorted body types
BaseTypes
ShowBaseTypeTGN: PROC [ on: IO.STREAM, nest: INT, bttgn: BaseTypeTGN ] ~ {
IO.PutRope[on, bttgn.typeName];
};
Top and Bottom
ShowSpecialTGN: PROC [ on: IO.STREAM, nest: INT, spctgn: SpecialTGN ] ~ {
IO.PutF[on, "%g", IO.rope[SELECT spctgn.kind FROM
bottom => "bottom",
top => "top",
ENDCASE => ERROR]];
};
Named nodes (i.e., locally visible)
ShowNamedTGN: PROC [ on: IO.STREAM, nest: INT, ntgn: NamedTGN, shown: BOOLEAN ] ~ {
IO.PutF[on, "%g ", IO.rope[RopeForId[ntgn.name]]];
ShowAVN[on, nest, ntgn.access];
ShowDEN[on, nest, ntgn.default];
IF NOT shown THEN ShowTGN[on, nest+2, ntgn.type];
};
SubRange Nodes
ShowSubrangeTGN: PROC [ on: IO.STREAM, nest: INT, srtgn: SubrangeTGN ] ~ {
IO.PutF[on, " sub range of\n"]; ShowNested[on, nest+2];
ShowTGN[on, nest+2, srtgn.subrangeOf];
IO.PutF[on, "\n"]; ShowNested[on, nest+2];
ShowBVN[on, nest+2, srtgn.bounds];
};
Record nodes
ShowRecordTGN: PROC [ on: IO.STREAM, nest: INT, rn: RecordTGN ] ~ {
IO.PutF[on, " RECORD"];
ShowPaint[on, nest, rn.paint];
IF rn.machineDependent THEN IO.PutF[on, " (machineDependent)"];
IF rn.monitoredRecord THEN IO.PutF[on, " (monitoredRecord)"];
ShowFrozenFieldList[on, nest+2, rn.ffl];
};
pointer type nodes
ShowPointerTGN: PROC [ on: IO.STREAM, nest: INT, ptgn: PointerTGN ] ~ {
IO.PutF[on, "%g Pointer %g %g\n",
IO.rope[IF ptgn.ordered THEN "(ordered)" ELSE ""],
IO.rope[IF ptgn.base THEN "(base)" ELSE ""],
IO.rope[IF ptgn.readOnly THEN "(readOnly)" ELSE ""]];
ShowNested[on, nest+1];
ShowBVN[on, nest+1, ptgn.bounds];
IO.PutF[on, "\n"]; ShowNested[on, nest+1]; IO.PutF[on, "target type = "];
ShowTGN[on, nest+2, ptgn.target];
};
ShowRefTGN: PROC [ on: IO.STREAM, nest: INT, rtgn: RefTGN ] ~ {
IO.PutF[on, "Ref %g\n", IO.rope[IF rtgn.machineDependent THEN "(machine dependent)" ELSE ""]];
ShowTGNAsNamedSubstructure[on, nest+2, "target type = ", rtgn.target];
};
ShowVarTGN: PROC [ on: IO.STREAM, nest: INT, vtgn: VarTGN ] ~ {
IO.PutF[on, "var\n"];
ShowTGNAsNamedSubstructure[on, nest+2, "target type = ", vtgn.target];
};
ShowRelativeTGN: PROC [ on: IO.STREAM, nest: INT, rtgn: RelativeTGN ] ~ {
IO.PutF[on, "relative\n"];
ShowTGNAsNamedSubstructure[on, nest+2, "base type = ", rtgn.base];
ShowTGNAsNamedSubstructure[on, nest+2, "pointer type = ", rtgn.pointer];
};
ShowReferentTGN: PROC [ on: IO.STREAM, nest: INT, refenttgn: ReferentTGN ] ~ {
IO.PutF[on, "REFERENT\n"];
ShowTGNAsNamedSubstructure[on, nest+2, "contents type = ", refenttgn.contents];
};
List nodes
ShowListTGN: PROC [ on: IO.STREAM, nest: INT, ltgn: ListTGN ] ~ {
IO.PutF[on, "LIST %Gof \n", IO.rope[IF ltgn.readOnly THEN "(readOnly)" ELSE ""]];
ShowNested[on, nest+1]; IO.PutF[on, "item type = "];
ShowTGN[on, nest+2, ltgn.first];
};
EnumeratedType Nodes
ShowEnumTypeTGN: PROC [ on: IO.STREAM, nest: INT, etgn: EnumTGN ] ~ {
IO.PutF[on, "Enumerated Type %g {", IO.rope[IF etgn.machineDependent THEN "(MachineDependent)" ELSE ""]];
ShowPaint[on, nest, etgn.paint];
FOR cell: EnumElementCell ← etgn.firstElement, cell.next WHILE ( cell # NIL ) DO
IO.PutF[on, " %g %g", IF cell.id # NIL THEN IO.rope[RopeForId[cell.id]] ELSE IO.rope[""], IF cell.rep # NIL THEN IO.rope[Rope.Cat["(", TextForExpPTree[cell.rep], ")"]] ELSE IO.rope[""]];
IF cell = etgn.lastElement THEN EXIT;
ENDLOOP;
IO.PutF[on, " }"];
};
Field lists and frozen field lists
ShowFrozenFieldList: PROC [ on: IO.STREAM, nest: INT, ffl: FrozenFieldListNode ] ~ {
IO.PutF[on, "ffl (%g) %g", IO.int[LOOPHOLE[ffl, INT]], IO.rope[IF ffl.any THEN "ANY" ELSE ""]];
IF NOT ffl.shown THEN {
ffl.shown ← TRUE;
FOR x: CARDINAL IN [0..ffl.nSlots) DO
IO.PutRope[on, "\n"]; ShowNested[on, nest];
SELECT ffl.fields[x].case FROM
field => {
IF ffl.fields[x].name = NIL
THEN { -- assume unnamed field
IO.PutF[on, "<>: "]
}
ELSE { -- assume named field
IO.PutF[on, "%g: ", IO.rope[RopeForId[ffl.fields[x].name]]];
ShowPVN[on, nest, ffl.fields[x].pvn];
ShowAVN[on, nest, ffl.fields[x].avn];
};
ShowTGN[on, nest+2, ffl.fields[x].tgn];
ShowDEN[on, nest+2, ffl.fields[x].default]
};
ffl => ShowFrozenFieldList[on, nest+2, ffl.fields[x].ffl];
ENDCASE => ERROR;
ENDLOOP;
};
};
VariantPart TGN and Union List
ShowVariantPartTGN: PROC [ on: IO.STREAM, nest: INT, vptgn: VariantPartTGN ] ~ {
IO.PutF[on, "variant\n"]; ShowNested[on, nest+2];
ShowVariantFlavor[on, nest+2, vptgn.flavor];
IO.PutF[on, "tagType\n"]; ShowNested[on, nest+2];
ShowTGN[on, nest+2, vptgn.tagType];
IO.PutF[on, "\n"];
ShowNested[on, nest+2]; IO.PutF[on, "variations\n"]; ShowNested[on, nest+2];
ShowFrozenUnionList[on, nest+2, vptgn.types];
};
ShowFrozenUnionList: PROC [ on: IO.STREAM, nest: INT, ful: FrozenUnionList ] ~ {
first: BOOLEANFALSE;
FOR I: CARDINAL IN [0..ful.nTypes) DO
IF NOT first THEN { IO.PutF[on, "\n"]; ShowNested[on, nest] };
IO.PutF[on, "%g => ", IO.rope[RopeForId[ful[I].id]]];
ShowFrozenFieldList[on, nest+2, ful[I].ffl];
ENDLOOP;
};
Variant Flavors
ShowVariantFlavor: PROC [ on: IO.STREAM, nest: INT, vf: VariantFlavorNode ] ~ {
WITH vf SELECT FROM
o: REF VariantFlavorNodeBody.overlaid =>
IO.PutF[on, "Overlaid"];
c: REF VariantFlavorNodeBody.computed =>
IO.PutF[on, "Computed"];
v: REF VariantFlavorNodeBody.vanilla => {
IO.PutF[on, "Vanilla %g", IO.rope[RopeForId[v.id]]];
ShowPVN[on, nest, v.position];
ShowAVN[on, nest, v.access];
};
ENDCASE => ERROR;
};
Sequence TGNs
ShowSequenceTGN: PROC [ on: IO.STREAM, nest: INT, stgn: SequenceTGN ] ~ {
IO.PutF[on, "%gsequence\n", IO.rope[IF stgn.packed THEN "packed " ELSE ""]]; ShowNested[on, nest+2];
IO.PutF[on, "%g", IO.rope[RopeForId[stgn.id]]];
ShowPVN[on, nest, stgn.position];
ShowAVN[on, nest, stgn.access];
ShowTGNAsNamedSubstructure[on, nest+2, "tagType", stgn.tagType];
ShowTGNAsNamedSubstructure[on, nest+2, "type", stgn.type];
IO.PutF[on, "\n"]; ShowNested[on, nest+2]; IO.PutF[on, "tagType "];
};
Array TGN
ShowArrayTGN: PROC [on: IO.STREAM, nest: INT, atgn: ArrayTGN] ~ {
IO.PutF[on, "%array\n", IO.rope[IF atgn.packed THEN "packed " ELSE ""]];
ShowTGNAsNamedSubstructure[on, nest+2, "indexType", atgn.indexType];
ShowTGNAsNamedSubstructure[on, nest+2, "itemType", atgn.itemType];
};
Descriptor TGN
ShowDescriptorTGN: PROC [ on: IO.STREAM, nest: INT, dtgn: DescriptorTGN ] ~ {
IO.PutF[on, "%descriptor\n", IO.rope[IF dtgn.readonly THEN "ReadOnly " ELSE ""]];
ShowTGNAsNamedSubstructure[on, nest+2, "itemType", dtgn.itemType];
};
Transfer TGN
ShowTransferTGN: PROC [ on: IO.STREAM, nest: INT, ttgn: TransferTGN ] ~ {
modeName: Rope.ROPESELECT ttgn.mode FROM
proc => "proc",
port => "port",
signal => "signal",
error => "error",
process => "process",
program => "program",
ENDCASE => ERROR;
IO.PutF[on, "%g transfer\n", IO.rope[modeName]];
ShowNested[on, nest+2];
ShowFrozenFieldList[on, nest+2, ttgn.arguments];
IO.PutF[on, "\n"]; ShowNested[on, nest+2];
ShowFrozenFieldList[on, nest+2, ttgn.results];
};
Zone TGN
ShowZoneTGN: PROC [ on: IO.STREAM, nest: INT, ztgn: ZoneTGN ] ~ {
IO.PutF[on, "% zone ", IO.rope[IF ztgn.uncounted THEN "uncounted" ELSE "counted"]];
};
Long TGN
ShowLongTGN: PROC [ on: IO.STREAM, nest: INT, ltgn: LongTGN ] ~ {
IO.PutF[on, " long "];
ShowTGN[on, nest+2, ltgn.underlyingType];
};
Interface TGN
ShowInterfaceTGN: PROC [ on: IO.STREAM, nest: INT, itgn: InterfaceTGN ] =
BEGIN
first: BOOLEANTRUE;
ShowOneInterfaceItem: PROC[name: IdNode, access: AccessValNode, value: REF ANY] =
BEGIN
IF NOT first THEN { IO.PutRope[on, "\n\n"]; ShowNested[on, nest] };
first ← FALSE;
IO.PutRope[on, RopeForId[name]];
ShowAVN[on, nest, access];
IO.PutRope[on, "\n"]; ShowNested[on, nest+2];
ShowNamedTGNTree[on, nest+4, NARROW[value]];
END;
IO.PutF[on, " interfaceTGN %g ", IO.rope[IF itgn.sharedAccess THEN "sharedAccess" ELSE "unSharedAccess"]];
GenVisibleNames[itgn.typeNames, ShowOneInterfaceItem];
END;
Link TGN
ShowLinkTGN: PROC [ on: IO.STREAM, nest: INT, linktgn: LinkTGN ] =
BEGIN
IO.PutF[on, "link to external module \N", ];
ShowNested[on, nest+2];
IO.PutF[on, "interface to external module\N"];
ShowNested[on, nest+2];
IO.PutF[on, "external type name: %g\N", IO.rope[RopeForId[linktgn.itemName]]];
ShowTGN[on, nest+2, linktgn.tgn, TRUE];
END;
Frame TGN
Specianated TGN
ShowSpecianatedTGN: PROC [ on: IO.STREAM, nest: INT, stgn: SpecianatedTGN ] ~ {
IO.PutF[on, "%g specianated ", IF ( stgn.expParam # NIL )
THEN IO.rope[TextForExpPTree[stgn.expParam]]
ELSE IO.rope[RopeForId[stgn.idParam]]
];
ShowTGN[on, nest+2, stgn.underlyingType];
};
Opaque TGNs
ShowOpaqueTGN: PROC[on: IO.STREAM, nest: INT, otgn: OpaqueTGN] =
BEGIN
IO.PutF[on, " Opaque"];
ShowPaint[on, nest, otgn.paint];
IO.PutF[on, " %g", IO.rope[TextForExpPTree[otgn.optSize]]];
END;
Paint nodes
ShowPaint: PROC [ on: IO.STREAM, nest: INT, paint: PaintNode ] ~ {
IO.PutF[on, " (paint = %g) ", IO.int[paint.index]];
};
Locally Visible Names
General purpose show routines
ShowNested: PROC [ on: IO.STREAM, nest: INT ] ~ {
FOR i: INT IN [0..nest) DO
IO.PutRope[on, " "];
ENDLOOP
};
RopeForId: PROC [ id: IdNode ] RETURNS [ Rope.ROPE ] ~ {
RETURN[IF ( id # NIL ) THEN id.text ELSE ""];
};
Context Ribs
RealShowRib: PROC [ on: IO.STREAM, nest: INT, rib: ContextRibNode ] ~ {
IO.PutF[on, "Context Rib %g:", IO.int[LOOPHOLE[rib, INT]]];
IO.PutRope[on, "\n"]; ShowNested[on, nest+2];
RealShowLocalContext[on, nest+2, rib.lc];
};
Context Trees
RealShowTree: PROC [ on: IO.STREAM, nest: INT, ct: ContextTreeNode ] ~ {
IO.PutF[on, "Context Tree %g:", IO.int[LOOPHOLE[ct, INT]]];
IO.PutRope[on, "\n"]; ShowNested[on, nest+2];
RealShowRib[on, nest+2, ct.rib];
IO.PutRope[on, "\n\n"]; ShowNested[on, nest+4];
FOR cell: CTCell ← ct.subTrees, cell.next WHILE ( cell # NIL ) DO
RealShowTree[on, nest+4, cell.ctn];
IF cell = ct.lastSubTree THEN EXIT;
ENDLOOP;
};
Default Exp Nodes
ShowDEN: PROC [ on: IO.STREAM, nest: INT, den: DefaultExpNode ] ~ {
t1: Rope.ROPE ← IF den = NIL THEN "" ELSE SELECT den.case FROM
c1 => "",
c2 => "← ",
c3 => "𡤎 ",
c4 => "←TRASH ",
c5 => "𡤎|TRASH ",
ENDCASE => ERROR;
t2: Rope.ROPE ← IF den = NIL THEN "" ELSE TextForExpPTree[den.exp];
IO.PutF[on, "<%g%g>", IO.rope[t1], IO.rope[t2]];
};
position val nodes
ShowPVN: PROC [ on: IO.STREAM, nest: INT, pvn: PositionValNode ] ~ {
IF ( pvn # NIL ) THEN {
IO.PutF[on, "( %g ", IO.rope[TextForExpPTree[pvn.index]]];
ShowBVN[on, nest, pvn.bounds];
IO.PutF[on, " )"];
};
};
bounds val nodes
The colon is not needed for some uses, but I have to go back and figure out all of the uses, and see which ones need the colon.
ShowBVN: PROC [ on: IO.STREAM, nest: INT, bvn: BoundsValNode ] ~ {
IF bvn # NIL THEN {
left: Rope.ROPESELECT bvn.left FROM
open => "(",
closed => "[",
ENDCASE => ERROR;
right: Rope.ROPESELECT bvn.right FROM
open => ")",
closed => "]",
ENDCASE => ERROR;
IO.PutF[on, ": %g%g..%g%g ", IO.rope[left], IO.rope[TextForExpPTree[bvn.first]], IO.rope[TextForExpPTree[bvn.last]], IO.rope[right]];
};
};
access val nodes
ShowAVN: PROC [ on: IO.STREAM, nest: INT, avn: AccessValNode ] ~ {
IF avn # NIL THEN IO.PutF[on, " %g", IO.rope[SELECT avn^ FROM
empty => "empty",
private => "private",
public => "public",
ENDCASE => ERROR]];
};
ExpPTree
TextForExpPTree: PROC [ exp: ExpPTreeNode ] RETURNS [ Rope.ROPE ] ~ { RETURN[IF (exp # NIL) THEN "exp" ELSE ""] };
ScopePTree
misc stuff
following are exported to SaffronContext
ShowContextRib: PROC [ on: IO.STREAM, nest: INT, rib: ContextRibNode ] ~ {
RealShowRib[on, nest, rib];
};
LocalContextNode: TYPE ~ REF LocalContextNodeBody;
LocalContextNodeBody: PUBLIC TYPE ~ SaffronContextPrivateTypes.LocalContextNodeBody;
ShowLocalContext: PUBLIC PROC [ on: IO.STREAM, nest: INT, lc: LocalContextNode ] ~ {
RealShowLocalContext[on, nest, lc];
};
ContextTreeNode: TYPE ~ REF ContextTreeNodeBody;
ContextTreeNodeBody: PUBLIC TYPE ~ SaffronContextPrivateTypes.ContextTreeNodeBody;
ShowContextTree: PUBLIC PROC [ on: IO.STREAM, nest: INT, ct: ContextTreeNode ] ~ {
RealShowTree[on, nest, ct];
};
}.