File: PrintTV.mesa
Russ Atkinson, September 1, 1982 8:00 pm
Paul Rovner, November 3, 1983 12:45 pm
DIRECTORY
AMTypes USING [TV, Class],
IO USING [STREAM],
SafeStorage USING [nullType, Type];
PrintTV: CEDAR DEFINITIONS
= BEGIN OPEN AMTypes, IO, SafeStorage;
Procedures for rendering elements of the Cedar Abstract Machine to text. Roughly speaking, the depth parameter controls the nesting depth before "..." is used, e.g. of records within records within arrays within ..., width controls the number of characters printed at each nesting level before "..." is used, and verbose TRUE causes extra information to be printed as available.
Print: PROC
[tv: TV, put: STREAM, depth: INT ← 4, width: INT ← 32, verbose: BOOLFALSE];
print the value described by tv.
PrintType: PROC
[type: Type, put: STREAM, depth: INT ← 4, width: INT ← 32, verbose: BOOLFALSE];
print the type.
PrintSignal: PROC
[signalTV, argsTV: TV, put: STREAM, depth: INT ← 4, width: INT ← 32, verbose: BOOLFALSE];
print the signal and its args.
Printing local frame arguments, results and variables
PrintArguments: PROC
[tv: TV, put: STREAM, depth: INT ← 4, width: INT ← 32,
breakBetweenItems: BOOLFALSE];
Calls Print to print the arguments to the given local frame. The depth and width args apply to each argument printed; verbose is FALSE. An error msg is printed if tv is not a local frame. breakBetweenItems causes a line break between arguments.
PrintResults: PROC
[tv: TV, put: STREAM, depth: INT ← 4, width: INT ← 32,
breakBetweenItems: BOOLFALSE];
Calls Print to print the result parameters of the given local frame. The depth and width args apply to each result parameter printed; verbose is FALSE. An error msg is printed if tv is not a local frame. breakBetweenItems causes a line break between result parameters.
PrintVariables: PROC
[tv: TV, put: STREAM, depth: INT ← 4, width: INT ← 32,
all, breakBetweenItems: BOOLTRUE];
print the variables of the given local frame. The depth and width args apply to each variable printed; verbose is FALSE. An error msg is printed if tv is not a local frame. If all = TRUE, then variables in all "enclosing bodies" of the frame are also printed. breakBetweenItems causes a line break between variables.
Procedures for registering one's own "print procs"
PrintProcs allow clients to provide custom printing for objects of specified types. There are two kinds of PrintProcs: ones used by PrintTV.Print for printing TV's and ones used by IO.Put and friends for printing REF ANY's.
PrintProcs are useful (e.g.) for printing a summary of an object's meaning. For example, a viewer is an object of type REF ViewerClasses.ViewerRec where ViewerRec is a RECORD consisting of nineteen fields! Printing this as a record would produce copious amounts of information, most of which is probably not of interest to the user who simply wants to see which viewer it is. Instead, we can define a PrintProc that prints a viewer showing just its class and name as follows:
ViewerPrintProc: RefPrintProc = {
h: REF READONLY ViewerClasses.ViewerRec ← NARROW[ref];
stream.PutF["{Viewer - class: %g, name: %g}", atom[h.class.flavor], rope[IF Rope.Length[h.name] # 0 THEN h.name ELSE "(no name)"]];
};
We register this printProc via:
RegisterRefPrintProc[
referentType: CODE[ViewerClasses.ViewerRec],
proc: ViewerPrintProc
];
After this is done, the viewer for (e.g.) the initial UserExec would print as:
{Viewer - class: Typescript, name: Work Area A: Executive}
RegisterTVPrintProc:
PROC [type: Type, proc: TVPrintProc, data: REFNIL];
Used to register a procedure to be called for printing a TV of the specified type. Replaces any previous registration of a TVPrintProc for that type. proc will be called whenever PrintTV.Print is about to print a TV of the given type. data will be supplied as an argument to proc. proc = NIL cancels the registration of a TVPrintProc for the type. BEWARE: proc will be called for remote TVs as well as local ones.
RegisterClassPrintProc:
PROC [class: Class, proc: TVPrintProc, data: REFNIL];
Used to register a procedure to be called for printing a TV with a type such that class = AMTypes.UnderClass[AMTypes.TVType[tv]]. Replaces any previous registration of a TVPrintProc for that class. proc will be called whenever PrintTV.Print is about to print such a TV AND there is no TVPrintProc registered for the type. data will be supplied as an argument to proc. proc = NIL cancels the registration of a TVPrintProc for the class. BEWARE: proc will be called for remote TVs as well as local ones.
RegisterRefPrintProc:
PROC [referentType: SafeStorage.Type, proc: RefPrintProc, data: REFNIL];
Used to register a procedure to be called for printing an object of the specified type. Replaces any previous registration of a RefPrintProc for that type. proc will be called whenever IO.Put or friends is about to print a refAny Value of the given type. data will be supplied as an argument to proc. proc = NIL cancels the registration of a RefPrintProc for the type.
TVPrintProc: TYPE =
PROC [tv: TV,
  data: REF,
  stream: STREAM,
  depth: INT ← 4,
  width: INT ← 32,
  verbose: BOOLFALSE]
RETURNS [useOld: BOOLFALSE];
the type of a TV "print proc" to be called by PrintTV.Print. tv is the thing to print. data is the same data that was given to RegisterTVPrintProc. stream is the output stream for characters. depth and width are passed through by PrintTV.Print. IF useOld is returned TRUE then Print will go on to do its normal thing.
RefPrintProc: TYPE =
PROC [ref: REF READONLY ANY,
  data: REF,
  stream: STREAM,
  depth: INT ← 4,
  width: INT ← 32,
  verbose: BOOLFALSE]
RETURNS [useOld: BOOLFALSE];
the type of a REF "print proc" to be called by IO.Put and friends for refAny Values. ref points to the object to print. data is the same data that was given to RegisterTVPrintProc. stream is the output stream for characters. depth and width are passed through by PrintTV.Print. IF useOld is returned TRUE then IO.Put and friends will go on to do their normal thing.
DisableTVPrintProcs: PROC RETURNS [wasEnabled: BOOL];
DisableClassPrintProcs: PROC RETURNS [wasEnabled: BOOL];
DisableRefPrintProc: PROC RETURNS [wasEnabled: BOOL];
These disable the use of print procs. print procs are initially enabled.
EnableTVPrintProcs: PROC RETURNS [wasEnabled: BOOL];
EnableClassPrintProcs: PROC RETURNS [wasEnabled: BOOL];
EnableRefPrintProc: PROC RETURNS [wasEnabled: BOOL];
These re-enable the use of print procs.
GetTVPrintProc: PROC[type: Type] RETURNS [proc: TVPrintProc, data: REF];
GetClassPrintProc: PROC[class: Class] RETURNS [proc: TVPrintProc, data: REF];
GetRefPrintProc: PROC[type: Type] RETURNS [proc: RefPrintProc, data: REF];
proc # NIL => a print proc is registered for the type.
NextTVPrintProc:
PROC[after: Type ← nullType] RETURNS [type: Type, proc: TVPrintProc, data: REF];
NextClassPrintProc:
PROC[after: Class ← nil] RETURNS [class: Class, proc: TVPrintProc, data: REF];
NextRefPrintProc:
PROC[after: Type ← nullType] RETURNS [type: Type, proc: RefPrintProc, data: REF];
stateless enumerators for print procs
END.