SECTION 20 PRINTSTRUCTURE, INTERSCOPE, AND HELPSYS 1 20.1 Printstructure In trying to work with large programs, a user can lose track of the hierarchy which defines his program structure; it is often convenient to have a map to show which functions are called by each of the functions in a system. If fn is the name of the top level function called in your system, then typing in printstructure[fn] will cause a tree printout of the function-call structure of fn. To illustrate this in more detail, we use the printstructure program itself as an example. ------------------------------------------------------------------------ 1 A preliminary version of printstructure was written by D. G. Bobrow. The current form of printstructure was written by W. Teitelman. 20.1 PRINTSTRUCTURE PRGETD PROGSTRUC PRGETD PRGSTRC NOTFN PRGETD PROGSTRUC PRGSTRC1 PRNCONC PRGSTRC1 PRGSTRC PRNCONC PRGSTRC CALLS1 MAKELIST NOTFN CALLS2 CALLS1 PRGETD TREEPRINT TREEPRINT1 TREEPRINT VARPRINT VARPRINT1 TREEPRINT1 VARPRINT2 ALLCALLS ALLCALLS1 ALLCALLS1 TREEPRINT1 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ PRINTSTRUCTURE [X,FILE: DONELST,N,TREELST,TREEFNS,LSTEM,X,Y,Z, FN,TREE;PRDEPTH,LAST-PRINTSTRUCTURE] CALLED BY: PRGETD [X,FLG; ; ] CALLED BY: PRINTSTRUCTURE,PROGSTRUC,NOTFN,CALLS2 PROGSTRUC [FN,DEF; N,Y,Z,CALLSFLG,VARSFLG,VARS1,VARS2,D,X; N,DONELST] CALLED BY: PRINSTRUCTURE,PRGSTRC PRGSTRC [X,HEAD,FLG; Y,TEM,X; VARSFLG,D,NOFNS,CALLSFLG,N,DONELST, TREEFNS,NOTRACEFNS,FN,VARS1,QUOTEFNS] CALLED BY: PROGSTRUC,PRGSTRC1,PRGSTRC NOTFN [FN; DEF; NOFNS,YESFNS,FIRSTLOC,LASTLOC] CALLED BY: PRGSTRC,CALLS1 PRGSTRC1 [L,HEAD,FLG; A,B; VARS1,VARS2] CALLED BY: PRGSTRC,PRGSTRC1 PRNCONC [X,Y; ; CALLSFLG] CALLED BY: PRGSTRC1,PRGSTRC CALLS1 [ADR,GENFLG,D; LIT,END,V1,V2,LEFT,OPD,X,X; VARS1,VARS2, VARSFLG] CALLED BY: PROGSTRUC,CALLS2 MAKELIST [N,ADR; L; ] CALLED BY: CALLS1 Figure 20-1 20.2 The upper portion of this printout is the usual horizontal version of a tree. This tree is straighforwardly derived from the definitions of the functions: printstructure calls prgetd, progstruc, treeprint, and varprint. progstruc in turn calls prgetd, prgstrc and calls1. prgstrc calls notfn, progstruc, prgstrc1, prnconc, and itself. prgstrc1 calls prnconc, itself, and prgstrc. Note that a function whose substructure has already been shown is not expanded in its second occurrence in the tree. The lower portion of the printout contains, for each function, information about the variables it uses, and a list of the functions that call it. For example, printstructure is a function of two arguments, x and file. It binds eleven variables internally: donelst, 2 n, ... tree, and uses prdepth and last-printstructure as free variables. It is not called by any of the functions in the tree. prgetd is a function of two arguments, x and flg, binds no variables internally, uses no free variables, and is called by printstructure, progstruc, notfn and calls2. printstructure calls many other low-level functions such as getd, car, list, nconc, etc. in addition to the four functions appearing in the above output. The reason these do not appear in the output is that they were defined "uninteresting" by the user for the purposes of his analysis. Two functions, firstfn and lastfn, and two variables, yesfns and nofns are used for this purpose. Any function that appears on the list nofns is not of interest, any function appearing on yesfns is of interest. yesfns=T effectively puts all functions on yesfns. As for functions appearing on neither nofns or yesfns, all interpreted functions are deemed interesting, but only those compiled functions whose code lies in that portion of bpspace between the two limits established by firstfn and lastfn. For example, the above analysis was performed following firstfn[PRINTSTRUCTURE] and lastfn[ALLCALLS1]. Two other variables, notracefns and prdepth, also affect the action of printstructure. Functions that appear on the list notracefns will appear in the tree, assuming they are "interesting" functions as defined above, but their definitions will not be analyzed. prdepth is a cutoff depth for analysis. It is initially set to 7. printstructure assumes that all functions whose argtypes are 1 or 3, i.e. all NLAMBDAs, do not evaluate their arguments. For example, if the function prinq were defined as (NLAMBDA (X) (MAPC X (FUNCTION PRIN1))), and the form (PRINQ (NOW IS THE TIME)) appeared in a function being analyzed, IS, THE, and TIME would not be reported as free variables, and NOW as an undefined function. The user can inform printstructure (and other system packages which require this information) that an nlambda function does evaluate its arguments by putting on its property list the property INFO value EVAL. For example, the functions and, ersetq, progn, etc., are all initialized in this fashion. ------------------------------------------------------------------------ 2 Variables are bound internally by either PROGs LAMBDA-expressions. 20.3 If printstructure encounters a form beginning with two left parentheses in the course of analyzing an interpreted function (other than a COND clause or open lambda expression) it notes the presence of a possible parentheses error by the abbreviation P.P.E., followed by the function in which the form appears, and the form itself, as in the example below. Note also that since printstructure detects functions that are not defined, (i.e., atoms appearing as CAR of a form), printstructure is a useful tool for debugging. 20.4 _PP FOO (FOO [LAMBDA (X) (COND ((CAR X) (FOO1 X)) (T ((CONS X (CAR X]) FOO _PRINTSTRUCTURE(FOO) FOO FOO1 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ FOO [X; ; ] CALLED BY: FOO1 IS NOT DEFINED. P.P.E. IN FOO - ((CONS X (CAR X))) Figure 20-2 OTHER OPTIONS printstructure is a function of three arguments, x, exprflg, and file. printstructure analyzes x, sets the free variable last-printstructure to the results of its analysis, prints the result (in the format shown earlier) to file (which is opened if necessary and closed afterwards), and returns x as its value. Thus if the user did not want to see any 3 output, he could call printstructure with file=NIL:, and then process the result himself by using last-printstructure. printstructure always checks for EXPR properties on the property list of functions that are not defined. However, if exprflg=T, printstructure will prefer to analyze EXPR definitions whenever possible, i.e. if the function definition call contains a compiled definition, and there is also an EXPR property, the latter will be analyzed. x can be NIL, a list, a function, or an atom that evaluates to a list. If x is NIL, printstructure does not perform any analysis, but simply prints the result of the last analysis, i.e., that stored on last-printstructure. Thus the user can effectively redirect the output that is going to the terminal to a disc file by aborting the printout, and then performing printstructure[NIL;file]. ------------------------------------------------------------------------ 3 NIL: is a TENEX output device that acts like a 'bottomless pit'. Note that file=NIL (not NIL:) means print the tree to primary output file. 20.5 If x is a list, printstructure analyzes the first function on x, and then analyzes the second function, unless it was already analyzed, then the third, etc., producing however many trees required. Thus, if the user wishes to analyze a collection of functions, e.g., breakfns, he can simply perform (PRINTSTRUCTURE BREAKFNS). If x is not a list, but is the name of a function, printstructure[x] is the same as printstructure[(x)]. Finally, if the value of x is a list of functions, printstructure will process that list as described above. Note that in the case that x is a list, or evaluates to a list, subsequent functions are not separately analyzed if they have been encountered in the analysis of a function appearing earlier on the list. Thus, the ordering of x can be important. For example, if both FOO and FIE call FUM, printstructure[(FOO FIE FUM)], will produce a tree for FOO containing embedded in it the tree for FUM. FUM will not be expanded in the tree for FIE, nor will it have a tree of its own. (Of course, if FOO also calls FIE, then FIE will not have a tree either.) The convention of listing FUM can be used to force printstructure to give FUM a tree of its own. Thus printstructure[(FOO FIE (FUM))] will produce three trees, and neither of the calls to FUM from FOO or FIE will be expanded in their respective trees. Of course, in this example, the same effect could have been achieved by reordering, i.e., printstructure[(FUM FOO FIE)]. However, if FOO, FIE, and FUM, all called each other, and yet the user wanted to see three separate trees, no ordering would suffice. Instead, the user would have to do printstructure[((FOO) (FIE) (FUM))]. The result of the analysis of printstructure is in two parts: donelst, a list summarizing the argument/variable information for each function appearing in the tree(s), and treelst, a list of the trees. last-printstructure is set to cons[donelst;treelst]. donelst is a list consisting, in alternation, of the functions appearing in any tree, and a variable list for that function. car of the variable list is a list of variables bound in the function, and cdr is a list of those variables used freely in the function. Thus the form of donelst for the earlier example would be: (PRINTSTRUCTURE ((X FILE DONELST N TREELST TREEFNS L TEM X Y Z FN TREE) PRDEPTH LAST-PRINTSTRUCTURE) PRGETD ((X FLG)) PROGSTRUC (( FN DEF N Y Z CALLSFLG VARSFLG VARS1 VARS2 D X) N DONELST) ... ALLCALLS1 ((FN TR A B))) Possible parentheses errors are indicated on donelst by a non-atomic form appearing where a function would normally occur, i.e., in an odd position. The non-atomic form is followed by the name of the function in which the P.P.E. occurred. PRINTSTRUCTURE FUNCTIONS printstructure[x;exprflg;file] analyzes x, saves result on last-printstructure, outputs trees and variable information to file, and returns x as its value. 20.6 If exprflg=T, printstructure will prefer to analyze expr's. See page 20.5. treeprint[x;n] prints a tree in the horizontal fashion shown in the examples above. i.e., printstructure performs (MAPC TREELST (FUNCTION TREEPRINT)). varprint[donelst;treelst] prints the "lower half" of the printstructure output. allcalls[fn;treelst] uses treelst to produce a list of the functions that call fn. firstfn[fn] If fn=T, lower boundary is set to 0, i.e., all subrs and all compiled functions will pass this test. If fn=NIL, lower boundary set at end of bpspace, i.e., no compiled functions will pass this test. Otherwise fn is the name of a compiled function and the boundary is set at fn, i.e., all compiled functions defined earlier than fn are rejected. lastfn[fn] if fn=NIL, upper boundary set at end of bpspace, i.e., all compiled functions will pass this test. Otherwise boundary set at fn, i.e., all compiled functions defined later than fn are rejected. Thus to accept all compiled functions, perform firstfn[T] and lastfn[NIL]: to reject all compiled functions, perform firstfn[]. calls[fn;exprflg;varsflg] is a fast 'one-level' printstructure, i.e., it indicates what functions fn calls, but does not go further and analyze any of them. calls does not print a tree, but reports its findings by returning as its value a list of three elements: a list of all functions called by fn, a list of variables bound in fn, and a list of variables used freely in fn, e.g., calls[progstruc] = ((PRGETD EXPRP PRGSTRC CCODEP CALLS1 ATTACH) (FN DEF N Y Z CALLSFLG VARSFLG VARS1 VARS2 D X) (N DONELST)) fn can be a function name, a definition, or a form. Calls first does firstfn(T), lastfn() so that all subrs and compiled 20.7 functions appear, except those on nofns. If varsflg is T, calls ignores functions and only looks at the variables (and therefore runs much faster). vars[fn;exprflg] cdr[calls[fn;exprflg;T]] freevars[fn;exprflg] cadr[vars[fn;exprflg]] 4 20.2 Interscope While printstructure is a convenient tool for giving the user an overview of the structure of his programs, it is not well suited for determining the answer to particular questions the user may have about his programs. For example, if FOO uses X freely, and the user wants to know where X is bound 'above' FOO, he has to visually trace back up the tree that is output by printstructure, and, at each point, look down at the lower portion of the printout and find whether the corresponding function binds X. For large systems, such a procedure can be quite tedious. Furthermore, printstructure does not even compute certain certain important types of information. For example, printstructure does not distinguish between functions that use a variable freely and those that set it (or smash it). Interscope is an extension of printstructure designed to resolve these shortcomings. Like printstructure, interscope analyses programs (functions), although it extracts considerably more information and relationships than does printstructure. However, instead of presenting the information it obtains in a predetermined format, interscope allows the user to ask it questions about the programs it has analysed, i.e. to interrogate its data base. These questions can be input in English, and contain conjunctions, disjunctions, and negations of the many relationships between functions and variables that interscope knows about. The questions can be closed questions, e.g. "DOES FOO CALL FIE?", or open questions, "WHAT FUNCTIONS CALL FIE?". The answers to some questions are obtainable directly from the data base, e.g. "WHAT VARIABLES DOES FOO SET?" Other questions cause interscope to search its data base, e.g. "WHAT FUNCTIONS BIND VARIABLES THAT FOO SETS?". Figure 20-3 contains a sample session with interscope. ------------------------------------------------------------------------ 4 Interscope was originally written by P. C. Jackson, and substantially revised and improved by L. M. Masinter. 20.8 _INTERSCOPE] Hello, shall I analyze a system? [1] &_WTFIXFNS AND CLISPFNS. This may take a few minutes. GC: 8 1233, 10431 FREE WORDS Shall I analyze another system? &_NO [2] Ok, what would you like to know? &WHO CALLS RETDWIM? (WTFIX FIX89TYPEIN FIXAPPLY FIXATOM FIXCONTINUE CLISPATOM FIXT) &HOW IS CLISPATOM CALLED? I didn't understand that. [3] &WHAT FUNCTIONS CALL CLISPATOM? [4] (WTFIX FIXAPPLY FIXATOM) &WHAT FREE VARIABLES DOES CLISPATOM USE? (ONLYSPELLFLG CLISPCHANGES CLISPFLG TYPE-IN? CLISPSTATS INFIXSTATS LST FAULTXX CHCONLST FAULTX DWIMIFYFLG 89CHANGE FAULTPOS) &WHO BINDS TAIL? (WTFIX RETDWIM1 RETDWIM2 RETDWIM3 CLISPFUNCTION? CLISPATOM0 CLISPATOM1 CLISPATOM1A CLISPATOM2A DWIMIFY1A DWIMIFY2 DWIMIFY2A CLISPRESPELL) &WHO BINDS TAIL AND CALLS CLISPATOM SOMEHOW? (WTFIX DWIMIFY2) &WHAT VARS DOES HELPFIX CHANGE? (FORM LASTPOS NOCHANGEFLG HELPFIXTAIL FN TEM BRKEXP) &WHAT FUNCTIONS CHANGE THE VARIABLE TENTATIVE? (CLISPATOM1 CLISPATOM2 CLISPATOM2C CLISPATOM2A CLISPATOM1A) &WHO CHANGES TAIL? (FIXATOM HELPFIX1 CLISPATOM1 CLISPATOM2 DWIMIFY2) &WHAT FNS USE TEM AS AN INTERANL VAR AND ...ARE CALLED BY CLISPATOM INDIRECTLY? INTERANL=INTERNAL ? Yes (RETDWIM RETDWIM1 FIX89TYPEIN) &HOW DOES CLIAPTOM CALL LISTP? CLIAPTOM=CLISPATOM ? Yes ((CLISPATOM LISTP) (CLISPATOM *** RETDWIM *** LISTP) (CLISPATOM [5] FIX89 FIX89A LISTP)) &SHOW ME THE PATHS FROM CLISPATOM TO LISTP. CLISPATOM LISTP RETDWIM LISTP [6] RETDWIM1 LISTP FIX89TYPEIN RETDWIM ... FIX89 FIX89A LISTP &DOES GETVARS SMASH ANY VARIABLES? (L) &SHOW ME HOW GETVARS SMASHES L. (NCONC L (AND (LISTP X) (MAPCAR & &))) &GOODBYE. Goodbye. Figure 20-3 20.9 In order to answer questions about programs, interscope must analyze them and build its data-base. When interscope is first called, it will ask the user what functions he wants analyzed. The user can respond to this question by giving interscope either: 1) the name of the top level function called in his system, or 2) the name of a variable that evaluates to a list of top level functions, or 3) the list itself. All of the functions below each top level function will be analyzed, except those which are declared to be "uninteresting," as described below. 5 Note that after interscope goes into question-answering mode, the user can instruct interscope to analyze additional functions, either in English input, e.g. "ANALYZE FOOFNS." or by calling the function lookat directly (page 20.13). The structure of interscope may be divided into three major subsystems: a top-level monitor function, an English preprocessor, and the functions which build and search the data base. The monitor function is implemented via userexec (see Section 22), so that the features of the 6 programmer's assistant are available from within interscope. For example, the user can REDO or FIX interscope questions, interrogate the 7 history list for his session, or run programs from within interscope. ------------------------------------------------------------------------ 5 When interscope is first called, and it has not previously analyzed any functions, it is in analysis mode, as indicated by its greeting and prompt character (&_ instead of &) (see [1] in Figure 20-3). Interscope goes into question-answering mode when the user answers NO to the question "Shall I analyse a (another) system?" ([2] in Figure 20-3). The only difference between analysis mode and question-answering mode is that in analysis mode, interscope treats forms as indicating a list of functions to be analysed, whereas in question-answering mode, interscope simply passes forms back to lispx for evaluation. 6 interscope assumes that any input line terminated by a punctuation mark is intended for it to process. interscope will also attempt to process other input lines, i.e. those not ending in punctuation. However, if it is not able to make sense of the input, interscope will assume that it was intended to be handled by lispx, and pass it back for evaluation. For example, if the user types "HAS THOU SLAIN THE JABBERWOCK?", interscope will respond "I didn't understand that", but if the user omits the '?', the line will be given to lispx for evaluation and (probably) cause a U.D.F. HAS error. 7 Since the data base that interscope constructs is global (stored on property lists), the user can also exit from interscope, either by typing OK or GOODBYE, or via control-D, and then reenter interscope at some later point and continue asking questions, without having to reanalyze his functions. 20.10 8 The English preprocessor translates English questions, statements, and commands into INTERLISP forms appropriate for searching and building the interscope data base. Although this preprocessor is fairly flexible and robust (e.g. includes spelling correction), it translates only a limited subset of English sentences, and replies "I didn't understand that." to 9 anything outside this subset ([3] in Figure 20-3). When this happens, usually a simple rephrasing of the question will suffice to allow interscope to handle it ([4] in Figure 20-3). The interscope data-base can be accessed directly by the user via the functions described below. It should be noted that interscope actually creates two data bases, the first containing information about the elementary relations between the functions and variables in the user's system, and the second containing information derived from the first, i.e. the paths by which one function calls another. The first data base is created when interscope analyzes a system (via the function lookat). The second data base is developed incrementally (by the function paths), depending on the questions asked by the user. Both data bases are stored on the property lists of the functions and variables which are analyzed. Interscope "understands" a wide variety of the elementary relations that exist between functions and variables, e.g. which functions bind, use, change, test, or smash a given variable, which functions may cause a 10 given function to be called, either directly or indirectly, which variables are used as global or local free variables, either by a given function or by a group of functions, etc. Information about the function-call paths from one program to another is "generalized" when it is stored; e.g. at [5] in Figure 20-3, one of the paths by which CLISPATOM calls LISTP is given as (CLISPATOM *** RETDWIM *** LISTP), which means that there is more than one path from CLISPATOM to RETDWIM, and more than one path from RETDWIM to LISTP. The conventions used by interscope for recognizing functions that are "uninteresting" are the same as those used by printstructure (page 20.3), i.e. yesfns, nofns firstfn, and lastfn all have the same effect as for printstructure. ------------------------------------------------------------------------ 8 The translation of the most recent input is always stored in the function definition cell of the atom MEANING. 9 Where possible, interscope will try to inform the user what part of the sentence it did not understand. 10 e.g. if FOO calls FIE, and FIE calls FUM, then FOO calls FUM indirectly. 'SOMEHOW' means directly or indirectly, e.g. "WHAT FUNCTIONS CALL FOO SOMEHOW?" 20.11 INTERSCOPE FUNCTIONS paths[x;y;type;must;avoid;only] Value is a list of paths from x to y, where each path is an ordered list of functions. *** is used to indicate multiple paths. For example, if FOO calls FIE, and FIE calls FUM directly as well as calling FIE1 which calls FUM, then paths[FOO;FUM] returns ((FOO FIE *** FUM)). type, must, avoid, and only are optional. type can be either CALLS or CALLEDBY (NIL is equivalent to CALLS), e.g. in the above example, paths[FUM;FOO;CALLEDBY] would return the same set of paths as paths[FOO;FUM], except each path would be in the reverse order. must, avoid, and only are used to select out certain types of paths. Each can be specified by an atom which evaluates to a list of functions, or a form which evaluates to such a list. If (the value of) must is non-NIL, each path is required to go through at least one of the members of must. If avoid is non-NIL, no path can go through any member of avoid. If only is non-NIL, no path can go through any function which is not a member of only, i.e. each path can only go through 11 functions on only. treepaths[x;y;type;must;avoid;only] Like paths, except prints paths as a tree structure, as shown at [6] in Figure 20-3. type, must, avoid, and only have the same 12 meaning as with paths. ------------------------------------------------------------------------ 11 paths is called for English inputs of the form: "WHAT ARE THE PATHS FROM x TO y?". Such questions can be modified with subordinate clauses to indicate values for must, avoid, and/or only, e.g. "WHAT ARE THE PATHS FROM FOO TO FIE WHICH ONLY GO THROUGH FOOFNS AND AVOID FIEFNS?" 12 treepaths is called for English inputs of the form "SHOW ME HOW x CALLS y", "DISPLAY THE PATHS FROM x TO y", etc. 20.12 lookat[x] Builds the initial data base describing the system x, where x is either the name of a function, the name of a variable which evaluates to a list of functions, or the list of functions itself. clumpget[object;relation;universe] Value is a list of objects (functions or variables) which have the indicated relation with respect to object, e.g. clumpget[FOO;CALLERS] returns a list of functions that call FOO, clumpget[X;SMASHERS] a list of functions that smash the variable X, etc. A complete list of the possible values for relation is 13 given below. object can be a list of objects (or a variable which evaluates to a list of objects), in which case the value returned by clumpget is the list of all objects which have the indicated relation to any of the members of object. Similarly, universe can be a list of objects (or a variable which evaluates to a list of objects), in which case the value returned by clumpget is the list of all objects in universe which have the indicated relation to object (or any of the members of object), e.g. clumpget[X;SMASHERS;FOOFNS]. Finally,, universe can be a relation, which is equivalent to supplying clumpget[object;universe] in place of object, i.e. the value returned is the list of all objects which have the indicated relation to any of the members of the {set of all objects which bear the relationship universe to object}. For example, clumpget[FOO;CALLERS;CALLEDFNS] is a list of all functions that call any of the functions (CALLERS) that are directly called by FOO (CALLEDFNS). clumpget[FOO;FREEUSERS;LOCALVARS] is a list of functions that use freely any of the variables that are bound locally by FOO. ------------------------------------------------------------------------ 13 If clumpget is given a value for relation that it does not recognize, it will attempt spelling correction, and if that fails, generate an error. If given a value for object that it has not seen before, it will type "I don't know anything about object, shall I analyse a system?" and go into analysis mode. 20.13 Currently, the following relations are implemented: CALLERS list of functions that directly call object. CALLEDFNS list of functions directly called by object. CALLCAUSERS list of functions that call object, perhaps indirectly. In English: "WHO CALLS FOO SOMEHOW?". CALLSCAUSED list of functions called by object, perhaps indirectly. In English: "WHO DOES FOO CALL SOMEHOW?" ABOVE union of object with CALLCAUSERS. BELOW union of object with CALLSCAUSED. ARGS arguments of object. ARGBINDERS list of functions that have object as an argument. LOCALVARS list of variables that are locally bound in object, e.g. PROG vars. LOCALBINDERS list of functions that bind object as a local variable. FREEVARS list of variables used freely by object. FREEUSERS list of functions that use object freely. LOCALFREEVARS list of variables that are used freely in object, but are bound in object before they are used, e.g. clumpget[FOO;LOCALFREEVARS;BELOW] gives a list of those variables used freely below FOO, but are bound above the place that 20.14 14 they are used. In English: "WHAT ARE THE LOCAL FREE VARS (VARIABLES) BELOW FOO?" GLOBALFREEVARS list of variables used freely in object without previously being bound in object. ENTRYFNS list of each function in object which is not called by any function in object other than itself, e.g. clumpget[FOOFNS;ENTRYFNS]. SELFRECURSIVE list of functions in object which call themselves directly. CAUSESELFCALL list of functions in object which could call themselves, perhaps indirectly. CAUSERECURSION list of functions in object which cause some function to call itself, perhaps indirectly. CHANGEVARS list of variables that are changed by object, where 'changed' means any flavor of assignment, i.e. via SETQ, SETQQ, RPAQ, SETN, or even an expression of the form (RPLACA (QUOTE atom) value) (or FRPLACA, 15 /RPLACA, SAVESET, etc.) CHANGERS list of functions that change object. Note: 'set' in English input means any flavor of assignment, and translates the same as 'change'. SMASHVARS list of variables whose value are smashed by object, where 'smash' means the variable appears ------------------------------------------------------------------------ 14 Note that if object is the name of a function and universe is NIL, LOCALFREEVARS will always be NIL, and GLOBALFREEVARS the same as FREEVARS. It is only in connection with collections of functions that LOCALFREEVARS and GLOBALFREEVARS become interesting. 15 clumpget will accept as relations SETQVARS, SETQERS, SETVARS, SETTERS, SETQQERS, SETQQVARS, etc., in case the user wants to distinguish between the various flavors of assignments. In English, "WHAT ARE THE SETQERS OF X?", etc. 20.15 as the first argument to one of the list of 16 functions on smasherslst. SMASHERS list of functions that smash object. TESTVARS list of variables that are tested by object, where 'tested' means they appear as the first argument to one of the list of functions on testerslst, initially (ATOM LISTP NUMBERP NLISTP STRINGP EQ EQP EQUAL NULL), or anywhere in an AND or OR, or as the predicate in a COND clause, or as the first argument to SELECTQ, etc. TESTERS list of functions that test object. USEVARS list of variables that are used in object, where 'used' means actually appear in the body of the function, i.e. if a variable is simply bound, but not actually used anywhere, it will not be included in the value of USEVARS. CHANGEVARS and TESTVARS are subsets of USEVARS. USERS list of functions that use object. ------------------------------------------------------------------------ 16 Initially (RPLACA RPLACD FRPLACA FRPLACD /RPLACA /RPLACD NCONC NCONC1 /NCONC /NCONC1 ATTACH /ATTACH RPLNODE /RPLNODE RPLNODE2 /RPLNODE2). As with assignments, clumpget will accept as relations RPLACAERS, RPLACAVARS, RPLACDERS, RPLACDVARS, etc., in case the user wants to distinguish the different types of smashing. 20.16 17 20.3 Helpsys Helpsys provides yet another form of on-line assistance to the user, namely in the area of documentation of INTERLISP. Helpsys uses the INTERLISP Reference Manual as a data base, and answers simple questions about INTERLISP by presenting the appropriate passages from the manual. Inquiries are made in the form of simple sentences, void of punctuation, terminated with a carriage-return. The following sample session illustrates the use of Helpsys. User inputs are underlined. _HELPSYS] Type ??? for assistance !TELL ME ABOUT WHILE ... WHILE as a CLISP iterative statement operator from section 23 WHILE pred provides a way of terminating the i.s. WHILE pred evaluates pred before each iteration, and if the value is NIL, exits. !TELL ME ABOUT EVAL Do you want to see the function ? No Do you want to see the break command ? Yes EVAL Same as GO or OK except that the break is maintained after the evaluation. The user can then interrogate the value of the break which is bound on the variable !value, and continue with the break. More? Yes Typing GO or OK following EVAL will not cause reevaluation but another EVAL will. EVAL is a useful command when the user is not sure whether or not the break will produce the correct value and wishes to be able to do something about it if it is wrong. !TELL ME ABOUT UB ... UB as a break command from section 15 UB unbreaks brkfn, e.g. (FOO BROKEN) :UB FOO : and FOO is now unbroken !REDO EVAL Do you want to see the function ? ...yes eval[x] eval evaluates the expression x and returns this value i.e. eval provides a way of calling the interpreter. Footnote [7] now? Yes ---------- {*7*} eval is a subr so that the 'name' x does not actually appear ------------------------------------------------------------------------ 17 Helpsys was written by R. L. Walker II. 20.17 on the stack. ---------- Note that eval is itself a lambda type function, so its argument 18 is the first evaluated, e.g., {user aborts output by typing control-E} !WHAT ARE THE ARGS FOR BREAK1 Valid arguments for BREAK1 are: [BRKEXP;BRKWHEN;BRKFN;BRKCOMS;BRKTYPE] !TELL ME AOUT THE THIRD ARG FOR BREAK1 =ABOUT ... BREAK1 as a function from section 15 break1[brkexp;brkwhen;brkfn;brkcoms;brktype] is an nlambda. brktype is NIL for user breaks, INTERRUPT for control-H breaks, and ERRORX for error breaks. !TELL ME ABOUT ERROR IN ARRAYSIZE ... ARRAYSIZE as a function from section 10 Generates an error, ARG NOT ARRAY, if a is not an array. !TELL ME ABOUT THE LAST ARUGNEMT OF CHANGEPROP =ARGUMENT ... CHANGEPROP as a function from section 7 changeprop[x;prop1;prop2] Changes name of property prop1 to prop2 on property list of x, (but does not affect the value of the property). !USE 2ND FOR LAST ... CHANGEPROP as a function from section 7 changeprop[x;prop1;prop2] Changes name of property prop1 to prop2 on property list of x, (but does not affect the value of the property). Value is x, (but does not affect the value of the property). !WHAT IS THE VALUE OF MAPC ... MAPC as a function from section 11 The value of mapc is NIL. !OK NIL ------------------------------------------------------------------------ 18 The user could also interrupt the output by striking the 'del' key, which simply causes helpsys to skip over what it was currently typing, e.g. footnote, paragraph, etc., and continue with the same subject further on. 20.18