RUTGERS/UCI LISP MANUAL Rick LeFaivre Computer Science Department Rutgers University October 8, 1977 RUTGERS/UCI LISP MANUAL Page 2 CONTENTS ←←←←←←←← I. INTRODUCTION . . . . . . . . . . . . . . . . . . . . . 4 Documentation Conventions . . . . . . . . . . . . . . 4 II. USER INTERACTION . . . . . . . . . . . . . . . . . . . 5 Terminal Interrupts . . . . . . . . . . . . . . . . . 5 Terminal Input . . . . . . . . . . . . . . . . . . . 6 Lower-Case Characters . . . . . . . . . . . . . . . . 7 Defining New Functions . . . . . . . . . . . . . . . 7 Default Function Names . . . . . . . . . . . . . . . 7 Expansion of Core . . . . . . . . . . . . . . . . . . 8 Exiting from LISP . . . . . . . . . . . . . . . . . . 8 System-Monitoring Functions . . . . . . . . . . . . . 9 III. NEW LANGUAGE FACILITIES . . . . . . . . . . . . . . . . 10 The New NIL . . . . . . . . . . . . . . . . . . . . . 10 ATOM, CONSP, and PATOM . . . . . . . . . . . . . . . 10 Funargs and SPDL Pointers . . . . . . . . . . . . . . 10 Functions for Controlling Evaluation . . . . . . . . 10 Functions for Manipulating Property Lists . . . . . . 12 New Mapping Functions . . . . . . . . . . . . . . . . 13 New List-Manipulation Functions . . . . . . . . . . . 14 New Functions on Strings . . . . . . . . . . . . . . 16 IV. NEW I/O FACILITIES . . . . . . . . . . . . . . . . . . 17 The Octal Point "Q" . . . . . . . . . . . . . . . . . 17 36-Bit Integers . . . . . . . . . . . . . . . . . . . 17 String Input . . . . . . . . . . . . . . . . . . . . 17 Changes to DSKIN/DSKOUT . . . . . . . . . . . . . . . 18 Additions to MODCHR . . . . . . . . . . . . . . . . . 18 New File-Accessing Functions . . . . . . . . . . . . 18 New Output Functions . . . . . . . . . . . . . . . . 20 New Input Functions . . . . . . . . . . . . . . . . . 22 V. NEW DEBUGGING FACILITIES . . . . . . . . . . . . . . . 23 Additions to the Editor . . . . . . . . . . . . . . . 23 Additions to the Break Package . . . . . . . . . . . 23 VI. THE LISP PRETTYPRINTER . . . . . . . . . . . . . . . . 25 Basic Functions . . . . . . . . . . . . . . . . . . . 25 PRETTYPROPS . . . . . . . . . . . . . . . . . . . . . 26 Prettyprint Commands . . . . . . . . . . . . . . . . 26 Printmacros . . . . . . . . . . . . . . . . . . . . . 27 Comments . . . . . . . . . . . . . . . . . . . . . . 29 RUTGERS/UCI LISP MANUAL Page 3 VII. THE COMPILER AND LAP . . . . . . . . . . . . . . . . . 31 Declarations . . . . . . . . . . . . . . . . . . . . 31 Extensions to NOCALL . . . . . . . . . . . . . . . . 32 In-Line Code . . . . . . . . . . . . . . . . . . . . 33 Other Extensions . . . . . . . . . . . . . . . . . . 34 VIII. INFORMATION FOR THE SYSTEM BUILDER . . . . . . . . . . 35 User Error Handling . . . . . . . . . . . . . . . . . 35 Creating One's Own System . . . . . . . . . . . . . . 35 Building ILISP . . . . . . . . . . . . . . . . . . . 36 INDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 RUTGERS/UCI LISP MANUAL Page 4 I. INTRODUCTION ←←←←←←←←←←←←←←← This manual describes ILISP, an extended version of UCI LISP, which is itself an extended version of Stanford LISP 1.6. The existing documentation for ILISP is spread over three documents, reflecting the various stages in the development of the system: (1) SAILSP.MAN Describes the basic LISP 1.6 upon which UCI LISP is based. (2) UCILSP.MAN Describes the modifications and additions contained in the UCI LISP system as available from UC-Irvine. (3) ILISP.MAN (This document). Describes the modifications and additions contained in the ILISP system as available from Rutgers. We assume here that the reader is familiar with the UCI LISP system as described in (1) and (2) above - this document describes only the Rutgers modifications and additions. Note that there are numerous minor modifications and corrections to UCI LISP which have no direct user impact, and thus are not described in this manual. The interested LISP maintainer is referred to the various source listings for detailed information. Document Conventions ←←←←←←←←←←←←←←←←←←←← In this manual arguments to functions are represented as meta-linguistic variables of the form <variable>. Each function is presented as a template, with arguments which will be evaluated indicated by preceding them with "@". For example, (SETQ <atom> @<value>) indicates that <atom> is not evaluated and <value> is. Arguments which are optional are indicated by enclosing them in braces, e.g., {<x>}, and an unlimited number of arguments is indicated by ellipses (. . .). RUTGERS/UCI LISP MANUAL Page 5 II. USER INTERACTION ←←←←←←←←←←←←←←←←←←←← The ILISP system is started by typing .R ILISP at monitor level. The compiler is called ILISPC, and may be run via .R ILISPC (see section VII for details on the compiler). The system also comes with ILISP versions of the AI languages MICRO-PLANNER (.R PLNR), CONNIVER (.R CNVR), and FUZZY (.R FUZZY). Terminal Interrupts ←←←←←←←←←←←←←←←←←←← One of the major advantages of ILISP over UCI LISP and LISP 1.6 is the presence of a terminal interrupt-handling facility. The interrupt routine is entered by striking a single ↑C (Control-C) if awaiting terminal input, or two consecutive ↑C's if computing. The interrupt routine types: Interrupt (Help=?): and awaits an interrupt character from the user. Typing "?" will produce the following list of choices: CR = Continue (Ignore ↑C) ↑D = Return to Top Level ↑X = Exit to Monitor via (%$EXIT NIL) ↑H = Break Next Fn Call ↑B = Back Up and Break Last Fn Call ↑G = (ERR @ERRORX) ↑E = (ERR NIL) ↑R = Restore System OBLIST Typing a carriage return causes ILISP to continue doing whatever it was doing when the ↑C was typed. ↑H, ↑B, ↑G, ↑E, and ↑R are as described in the UCI LISP manual under the ↑C REENTER procedure (which is now obsolete). ↑D causes an immediate return to the top level of LISP, and ↑X causes an exit to the monitor (see EXIT). A subsequent CONTINUE at monitor level will cause ILISP to continue where it left off, while START or REENTER will cause it to restart at the top level (like ↑D). Any other character is ignored by the interrupt routine. The system is fully protected against a ↑C interrupt occuring at the wrong time; for example, if ↑C is typed during a garbage collection the garbage collection is completed before the interrupt is recognized (however, if several interrupts occur during a single garbage collection, it will be aborted). If the LOADER is in core when ↑C is struck, the LOAD will be aborted and ILISP will be restored to its state before the LOAD was invoked. RUTGERS/UCI LISP MANUAL Page 6 Note that a START or REENTER at monitor level will restart ILISP at the top level only if the system was exited normally (via ↑C ↑X or EXIT). If ILISP was somehow exited without going through the normal exit procedure, START or REENTER will cause the ↑C interrupt routine to be entered. Terminal Input ←←←←←←←←←←←←←← In addition to the above interrupt characters, which are recognized after a ↑C interrupt, there are three special control characters which are active during terminal input. As before, ↑G causes an (ERR @ERRORX) to occur, returning either to an (ERRSET <x> ERRORX) if present or to the top level. Recall that this character may be changed via (ERRCH @<char>) where <char> is the ASCII value of the new character. ERRCH returns the ASCII value of the old error character. Two new control characters affect the handling of errors during terminal input. If the error is in the current line, the system line-editing features may of course be used (RUBOUT/DELETE or ↑H to delete a character, ↑U to delete the line, ↑R to retype the line). In standard UCI LISP, if an error was noticed after carriage return was struck, the user was forced to abort the entire procedure via ↑G. ILISP now provides a "reread character" ↑Z which causes READ to ignore what was typed previously and start over. The reread character may be changed via (REREADCH @<char>) which is similar to ERRCH in its operation. Occasionally an error is not discovered until a good deal of typing has taken place. Rather than starting over, an "edit character" ↑F (for "fix") is also provided which causes the LISP editor to be called when the expression is completely entered (↑F may be typed at any point within the expression). The user may then correct the expression, returning the edited version as the value of the READ when OK is typed. The edit character may be changed via (EDITCH @<char>) which is similar to ERRCH and REREADCH. RUTGERS/UCI LISP MANUAL Page 7 Lower-Case Characters ←←←←←←←←←←←←←←←←←←←←← ILISP normally considers lower-case letters to be distinct from their upper-case counterparts. Thus, for example, nil and NIL represent different atomic symbols. If this is undesirable, the new RAISE function may be used to modify the handling of lower-case letters. (RAISE @<flag>) instructs READ to convert lower-case letters to upper case (<flag>=T) or pass them through unchanged (<flag>=NIL, the default setting). Note that (RAISE T) applies only to non-string atomic symbols read via READ; lower-case letters in strings, and those read via READCH or TYI, will not be converted to upper case. Note also that since character echoing is performed at the monitor level, all lower-case letters will be echoed as lower case independant of the RAISE function. RAISE returns the previous value of <flag>. Defining New Functions ←←←←←←←←←←←←←←←←←←←←←← The name of each function defined via DE, DF, or DM, or edited via EDITF, is now kept on the list ALLFNS. This list may be consulted after a long terminal session to see what functions have been created or modified and must therefore be saved before exiting. If an existing function is redefined via DE, DF, or DM, the old definition is now saved on the property list of the function name under the property UNSAVE. The old definition may be restored via (UNSAVE <name>) if desired. The saving of old definitions may be disabled by setting UNSAVE to NIL (it is initially T). Default Function Names ←←←←←←←←←←←←←←←←←←←←←← DE, DF, and DM now set LASTWORD to the name of the function just defined. The value of LASTWORD is used as a default name by the editor, the prettyprinter, and the break package when no function name is given explicitly. DE, DF, DM, EDITF, EDITV, EDITP, PP, BREAK, and TRACE all set LASTWORD, and all but DE, DF, and DM use it when no argument is given. A newly-defined function may thus be prettyprinted via (PP), broken or traced via (BREAK) or (TRACE), and edited via (EDITF), all without retyping the function name. RUTGERS/UCI LISP MANUAL Page 8 Expansion of Core ←←←←←←←←←←←←←←←←← If ILISP is started with its low segment expanded beyond its normal limit, the initial allocation procedure is entered as before. However, it is recommended that one of the following new functions be used to expand core without leaving LISP: (REALLOC @<fws> @<bps> @<rpdl> @<spdl> @<fs>) REALLOC's arguments specify increments (in words) to be added to each of the five major allocation areas: fullword space, binary program space, the regular pushdown list, the special pushdown list, and free storage (i.e., list space). After expanding core as necessary and reallocating storage, REALLOC returns control directly to the top level of LISP. In order to retain control, the user must set up an INITFN which will be called after REALLOC returns. (EXPFWS @<fws>) For those of us who can't remember the order of the arguments to REALLOC, EXPFWS is equivalent to: (REALLOC @<fws> 0 0 0 0) (EXPBPS @<bps>) Equivalent to (REALLOC 0 @<bps> 0 0 0). (EXPFS @<fs>) Equivalent to (REALLOC 0 0 0 0 @<fs>). Exiting from LISP ←←←←←←←←←←←←←←←←← (EXIT @<flag>) ILISP may be exited via the EXIT function. <flag> specifies whether ILISP's sharable high segment should be deleted (<flag>=NIL) or retained (<flag>=T) before exiting. There is normally no reason to retain the high segment, as it is automatically loaded when ILISP is STARTed or CONTinued. By deleting the high segment, EXIT allows the user to exit from LISP and save the low segment as a runnable SAV file - when the file is later RUN, ILISP's sharable high segment will be loaded automatically. (Note that an EXCISE or SYSCLR should be performed before exiting if the low segment is to be saved - see section VIII for more details). (EXIT T) is necessary only after SETSYS has been used to create a new sharable system, when both the low and high segments must be saved. At the top level, (EXIT) (and ↑C ↑X) are equivalent to (EXIT NIL). RUTGERS/UCI LISP MANUAL Page 9 System-Monitoring Functions ←←←←←←←←←←←←←←←←←←←←←←←←←←← (FSCNT) Returns the length of the free storage list, i.e., the number of available cons cells. (FWCNT) Returns the length of the fullword list. (DTIME) Returns the time of day in milliseconds past midnight. (DATE) Returns the current date as a list of the form: (<month> <day> <year-1900>) (TIMER {<expr1>} {<expr2>} . . .) TIMER serves as either an evaluation timer or an incremental timer. If any arguments are present they are evaluated, the execution time, portion of that time spent garbage collecting, elapsed clock time, and number of conses are printed, and the value of the last expression is returned. For example, (TIMER (GC) (GC)) times two garbage collections, printing the message: 627. msec CPU (627. msec GC), 1300. msec clock, 0. conses If TIMER is called with no arguments (i.e., (TIMER)), the execution time, etc., since the last evaluation of (TIMER) are printed and a value of NIL is returned. The intent here is that TIMER will be called once to initialize it, a number of expressions will be evaluated, and then TIMER will be called again to check the incremental statistics. Note that TIMER performs a TALK before printing these statistics, so they will appear on the terminal even if a ↑O has been struck. RUTGERS/UCI LISP MANUAL Page 10 III. NEW LANGUAGE FACILITIES ←←←←←←←←←←←←←←←←←←←←←←←←←←←← The New NIL ←←←←←←←←←←← In keeping with its character as both an atom and the representation of the empty list, the atom NIL has been modified so that its CAR and CDR are both NIL. One can now, for example, pick up the arguments to an FEXPR via a sequence of CAR/CDR combinations, with missing arguments automatically set to NIL. Note that NIL now has a usable property list, although it is not stored as the CDR of NIL as with other atoms (GET, PUTPROP, etc. are all aware of its actual location). ATOM, CONSP, and PATOM ←←←←←←←←←←←←←←←←←←←←←← ATOM has been fixed to return T only for a true LISP atom (i.e., an atomic symbol or a number). It will no longer be true if its argument is a pointer to some other location which happens to have -1 in its CAR field. Similarly, CONSP is true only if its argument is a true LISP consed cell. It is now the case that (ATOM X), (CONSP X), and (AND (PATOM X) (NOT (ATOM X))) define three disjoint classes. Funargs and SPDL Pointers ←←←←←←←←←←←←←←←←←←←←←←←←← For those of you who use funargs, it should be noted that this mechanism has now been integrated with UCI LISP SPDL pointers. A funarg binding context pointer can now be used with the various stack-accessing functions, and stack pointers may be used for the optional funarg argument to EVAL and APPLY. Note in particular that a pointer of zero always refers to the top level, so that (EVAL @<expr> 0) may always be used to evaluate <expr> using the top-level values of all variables. Functions for Controlling Evaluation ←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←← (CATCH <expr> {<label>}) (CATCH <expr> {(<l1> <e11> . . .)} {(<l2> <e21> . . .)} . . .) (THROW @<value> {<label>}) CATCH and THROW provide a more convenient method of programming transfers to a higher level in the control hierarchy than ERRSET/ERR, which (as the names imply) were originally designed for error handling rather than planned (programmed) transfers. CATCH simply evaluates RUTGERS/UCI LISP MANUAL Page 11 <expr>, and if no THROWs are executed during that evaluation, returns the value of <expr>. If a THROW is evaluated and the CATCH has no <label> then the CATCH is immediately exited with <value> as its value (regardless of whether the THROW had a <label> or not). An unlabeled CATCH will thus catch a value thrown by any THROW. If the CATCH has a <label>, it will catch values thrown only by a THROW with the same label; other THROWs are passed on in search of a higher-level CATCH with a matching label. Finally, a single CATCH can catch a variety of different THROWs via a SELECTQ-like mechanism as shown above. Each <l> is either a <label> or a list of <label>s; if a THROW <lable> matches an <l> or a member of an <l>, the corresponding <e>s are evaluated and the value of the last one is returned as the value of the CATCH. If no labels match, the THROW is passed on in search of a higher level CATCH. Note that a missing THROW <label> is equivalent to a <label> of NIL, and may be caught as such. CATCH and THROW are compiled in-line. (RPTQ @<n> <expr>) RPTQ evaluates <expr> <n> times, returning the value of the <n>th evaluation. If <n> is less than one, no evaluation is done and NIL is returned. Note that the special variable RPTN is initialized to one, and is incremented after each evaluation; it may be referenced within <expr> if desired. For example, the following prints the squares of the integers from 1 to 20: (RPTQ 20. (PRINT (*TIMES RPTN RPTN))) RPTQ is compiled in-line. (*APPLY @<fn> @<arglist>) *APPLY has the same relation to APPLY as *EVAL has to EVAL, i.e., it is a SUBR instead of an LSUBR, and it does not take the optional funarg argument. APPLYs without the funarg argument are compiled as *APPLYs. (DO <e1> {<e2>} . . .) DO is equivalent to PROGN. (BOUNDP @<var>) Returns T if the atomic symbol <var> is currently bound, NIL otherwise. Note that <var> must have been assigned a value in the interpreter or as a special variable in compiled code. Bindings of local variables in compiled code will not be noticed by BOUNDP. RUTGERS/UCI LISP MANUAL Page 12 Functions for Manipulating Property Lists ←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←← (DEFLIST <l> {<defval>} <prop>) DEFLIST is useful for placing a property on a number of atomic symbols. <l> should be a list of items, each of which is either an atomic symbol <a> or a two-element list (<a> <val>). Each <a> will have a <prop> property placed on its property list, with a value of <val> if present, or <defval> if only the atomic symbol was given. <defval> is optional, with a default value of T assumed. As an example of the use of DEFLIST, the following will give TOM and BOB ages of 15, and SAM an age of 20 (i.e., the 20 overrides the default value of 15): (DEFLIST (TOM BOB (SAM 20)) 15 AGE) (DEFP <at1> <at2> <props>) DEFP is used to place one of <at2>'s properties onto <at1>. <props> may be either a single property name or a list of property names (in which case the first property in the list found on <at2> is used. For example, (DEFP DO PROGN FSUBR) defines DO as an alternative to PROGN. If it is not known whether PROGN is compiled or not, (DEFP DO PROGN (FSUBR FEXPR)) may be used instead. DEFP returns <at1> if the property was found, NIL otherwise. (DEFV <atom> <value>) Equivalent to (SETQ <atom> @<value>), except that <value> is not evaluated and the value returned is <atom> instead of <value>. DEFV is used by the prettyprinter to print VALUE properties. (ADDPROP @<atom> @<value> @<prop>) ADDPROP is used to collect a number of values under a single property. If <atom> has no <prop> property, (LIST @<value>) is placed onto the property list of <atom>. If <value> is already a member of the <prop> property of <atom> (which is assumed to be a list), no action is taken. Otherwise <value> is CONSed onto the front of the list and it is placed back on the property list of <atom>. The (modified) list is returned as the value of ADDPROP. Note that ADDPROP uses ENTER to enter <value> on the property list, so MEMBFN may be used to indicate whether MEMB or MEMBER checks should be performed. RUTGERS/UCI LISP MANUAL Page 13 (PUTLIST @<l> @<value> @<prop>) Places <value> as the <prop> property of each element of <l> (which should be a list of atomic symbols). PUTLIST returns NIL. (REMLIST @<l> @<prop>) Removes the <prop> property from each element of <l> (which should be a list of atomic symbols). REMLIST returns NIL. (REMPROPS @<atom> @<l>) Treats each element of <l> (a list of atomic symbols) as a property, removing that property from <atom>. For example, (REMPROPS @FUNC @(EXPR FEXPR MACRO)) insures that FUNC is not an uncompiled function. REMPROPS returns NIL. (PUT @<atom> @<value> @<prop>) PUT is equivalent to PUTPROP. New Mapping Functions ←←←←←←←←←←←←←←←←←←←←← (MAPATOMS @<fn>) Applies <fn> (a function of one argument) to every atomic symbol on the OBLIST and returns NIL. MAPATOMS is compiled in-line. (EVERY @<fn> @<l>) Returns T if <fn> (a function of one argument) is non-NIL for each element of the list <l>. In other words, <fn> ←←←← is applied to each element of <l> in turn until either <fn> returns NIL (in which case EVERY returns NIL), or <l> is exhausted (with EVERY returning T). For example, the following checks whether L is a list of atoms: (EVERY @ATOM L) EVERY is compiled in-line. (SOME @<fn> @<l>) Returns a non-NIL value if <fn> (a function of one argument) is non-NIL for some element of the list <l>. ←←←← The value returned is the tail of <l> starting with that element. SOME is compiled in-line. RUTGERS/UCI LISP MANUAL Page 14 (NOTEVERY @<fn> @<l>) Equivalent to (NOT (EVERY @<fn> @<l>)). (NOTANY @<fn> @<l>) Equivalent to (NOT (SOME @<fn> @<l>)). (SUBSET @<fn> @<l>) Applies <fn> (a function of one argument) to each element of the list <l>, returning a list consisting of each element of <l> which causes <fn> to return a non-NIL value. For example, the following finds all atoms in L: (SUBSET @ATOM L) SUBSET is compiled in-line. New List-Manipulation Functions ←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←← (*INSERT @<x> @<l> @<comparefn> @<nodups>) (The insert, merge, and sort functions were copied with minor modifications from the Carnegie-Mellon University LISPX package). *INSERT destructively inserts <x> into the sorted list <l> in the proper slot using <comparefn> as a binary comparison function. (<comparefn> @<x> @<y>) should return a non-NIL value if <x> either precedes <y> in sorted order or <x> and <y> are equal, and NIL if <y> precedes <x>. If <comparefn> is NIL, LEXORDER will be used; if <comparefn> is T, LEXORDERCAR (see below) will be used. <nodups> controls the handling of duplicate values: if <nodups> is non-NIL, <x> will not be inserted into <l> if an element equal to <x> is already present in <l>. *INSERT performs a binary search to determine where to insert the new element. The value of *INSERT is the list <l> with <x> inserted. (INSERT @<x> @<l>) Equivalent to (*INSERT @<x> @<l> NIL NIL). (*MERGE @<l1> @<l2> @<comparefn> @<nodups>) *MERGE returns a new list which is the merge of the sorted lists <l1> and <l2>. <comparefn> and <nodups> are as described under *INSERT, i.e., <comparefn> is the binary comparison function, and <nodups> controls whether duplicate elements will be allowed or not. RUTGERS/UCI LISP MANUAL Page 15 (MERGE @<l1> @<l2>) Equivalent to (*MERGE @<l1> @<l2> NIL NIL). (*SORT @<l> @<comparefn> @<nodups>) *SORT returns a new list which is the sort of the list <l>, using a binary insertion sort. <comparefn> and <nodups> are as described under *INSERT, i.e., <comparefn> is the binary comparison function, and <nodups> controls whether duplicate elements will be removed or not. (SORT @<l>) Equivalent to (*SORT @<l> NIL NIL). (LEXORDERCAR @<x> @<y>) LEXORDERCAR returns the result of applying LEXORDER to the CARs of <x> and <y>, i.e., it is a binary comparison function used for sorting expressions in ascending lexical order of the CARs of the expressions. (UNION @<l1> @<l2>) Returns a list which is the union of the two lists <l1> and <l2>. If <l1> and <l2> are of unequal length, UNION is more efficient if <l2> is the longer list. Note that membership tests are made using MEMBER (and hence EQUAL). If MEMB (EQ) checks are desired instead, change the value of MEMBFN from MEMBER to MEMB. (INTERSECTION @<l1> @<l2>) Returns a list which is the intersection of <l1> and <l2>. See comments for UNION concerning efficiency and MEMBFN. (ENTER @<value> @<list>) Returns <list> if <value> is already a member of <list>, otherwise returns <list> with <value> CONSed onto the front. As with UNION and INTERSECTION, MEMBFN is used to indicate whether MEMB or MEMBER checks should be performed. (*NCONC @<l1> @<l2>) *NCONC has the same relation to NCONC as *APPEND has to APPEND, i.e., it is a SUBR instead of an LSUBR. NCONCs are compiled as a series of *NCONCs. RUTGERS/UCI LISP MANUAL Page 16 (NCONC1 @<list> @<value>) NCONC1 destructively adds <value> to the end of <list>. Equivalent to (NCONC @<list> (LIST @<value>)) (ATTACH @<x> @<l>) ATTACH destructively attachs <x> to the beginning of list <l>. For example, after (SETQ L @(A)) (ATTACH @B L) L has value (B A). If <l> is NIL, ATTACH is equivalent to CONS. (MCONS @<x1> @<x2> . . .) MCONS (Multiple CONS) is a MACRO which expands to ← ←←←← (CONS @<x1> (CONS @<x2> . . . (CONS @<xn-1> @<xn>))) It is useful for consing several items onto the list <xn>. New Functions on Strings ←←←←←←←←←←←←←←←←←←←←←←←← (EQSTR @<at1> @<at2>) Compares the PNAMEs of <at1> and <at2>, returning T if they are identical and NIL if they differ. Useful for use with any uninterned atomic symbols (including, of course, strings). (SUBSTRING @<str> @<m> @<n>) Returns a new string consisting of characters <m> through <n> of <str>. <m> and <n> may be positive integers (count from left) or negative integers (count from right). If <m> is non-numeric a value of 1 (first character) is assumed, and if <n> is non-numeric -1 (last character) is assumed. Although <str> will typically be a string, SUBSTRING will actually work with any argument; ←←← the indicated characters are simply extracted from the PRINC character string of <str> and formed into a string. RUTGERS/UCI LISP MANUAL Page 17 IV. NEW I/O FACILITIES ←←←←←←←←←←←←←←←←←←←←←← The Octal Point "Q" ←←←←←←←←←←←←←←←←←←← In order to correct the long-standing LISP 1.6/UCI LISP problem of reading a file which contains numbers which were printed using a different BASE than the current IBASE, an "octal point" Q is now printed following numbers when BASE=8. Like the decimal point (.), the octal point may be turned off by setting *NOPOINT to T. To summarize the numeric I/O conventions: on input, any number followed by a "Q" will be interpreted as octal, any number followed by a "." will be interpreted as decimal, and all other integers are interpreted according to the current setting of IBASE; on output, integers will be printed according to the current value of BASE, with a "Q" (BASE=8) or "." (BASE=10) appended unless *NOPOINT=T. In order to allow the user to disable the printing of octal or decimal points when interacting from the terminal but still have points printed when dumping to a file (so integers will be read in correctly), DSKOUT maintains its own copy of *NOPOINT, called *NOPOINTDSK. Both *NOPOINT and *NOPOINTDSK are initially NIL (i.e., print points), but either or both may be changed to T if desired. It should be noted that the lower-case letters "q" and "e" are now considered equivalent to their upper-case counterparts when used in numeric input. 10Q and 10q, or 12E and 12e, are now identical. 36-Bit Integers ←←←←←←←←←←←←←←← Integers may now be input and output as either signed 35-bit or unsigned 36-bit numbers. On input, the last 36 bits are retained (there is no overflow). For example, -1Q and 777777777777Q input as the same quantity. On output, the decision to print as 36 bits or sign plus 35 bits is under the control of the variable BASE. If BASE is positive, negative integers will be printed in standard form (i.e., with a sign). If BASE is negative, integers will be printed as positive 36-bit quantities. String Input ←←←←←←←←←←←← Recall that strings are normally not interned by the read routine so that they will be garbage collected when no longer referenced. If this feature is not desirable, the READ routine can now be told to intern all strings by setting the special variable INTERNSTR to T (it is initially NIL). This feature is used by LAP to uniquely store strings which are referenced from compiled code. RUTGERS/UCI LISP MANUAL Page 18 Changes to DSKIN/DSKOUT ←←←←←←←←←←←←←←←←←←←←←←← If the value of the symbol DSKIN is T (its default value) then DSKIN prints the value of each non-NIL expression loaded, attempting to place as many atoms as possible on each line. If the value of DSKIN is PRINT, the values are printed one per line. If DSKIN is set to NIL, no printing is done. Similarly, if the value of DSKOUT is T (its default value), the name of each function prettyprinted during the DSKOUT is printed on the terminal so that the user may follow the progress of the dump. If DSKOUT is set to NIL, no terminal printing is performed. The maximum line length used by DSKOUT is stored in DSKLENGTH, and may be changed if desired (it is initially 80). The variable LPTLENGTH is equivalent to DSKLENGTH - they may be used interchangeably. FILBAK (the file extension used by DSKOUT to back up a file) has been changed from LBK to QSP to maintain compatability with the SOS convention of starting backup files with Q (lets one do things like .DEL *.Q??). Additions to MODCHR ←←←←←←←←←←←←←←←←←←← MODCHR now notices when either the "slashifier" (currently "/") or the comment character (↑Y) is changed and fixes things so the new characters are used by PRINT. In other words, PRINT will use the slashifier and comment character most recently defined via MODCHR. Other special characters (e.g., '.' as the decimal point) are considered sacred by PRINT, although equivalent characters may still be defined for READ via MODCHR. New File-Accessing Functions ←←←←←←←←←←←←←←←←←←←←←←←←←←←← (GETDEF {<device/directory>} <file> <at1> {<at2>} . . .) GETDEF is similar to DSKIN, but only one file is accessed and only selected expressions from that file are read. In particular, all definitions of each <at> are loaded, including expressions starting with DEFPROP, DE, DF, DM, LAP, DEFP, and DEFV (the list of expression types to be examined is stored as the value of the atom GETDEF, and may be changed if desired). As usual, <device/directory> may be omitted, with DSK: assumed. As an example of the use of GETDEF, (GETDEF (FUNCS.LSP) FN1 FN2 FN3) loads any definitions for FN1, FN2, and FN3 found in the file FUNCS.LSP. The value of each expression loaded is printed on the terminal for feedback purposes. Note that RUTGERS/UCI LISP MANUAL Page 19 GETDEF does not intern any new atomic symbols unless necessary (i.e., unless contained in an expression to be loaded). Free storage is thus not clogged up with unused atomic symbols when scanning a large file for definitions. (DIRF {<directory>} {<filespec>}) Unlike the function DIR, which returns a list of all the files in a given directory, DIRF prints the name of each file in the directory which "matches" <filespec> (it is thus quite similar in operation to the DIRECT monitor command). <filespec> may be a dotted pair (<file>.<ext>), where either <file> and/or <ext> may be * (match anything), or simply <file>, with (<file>.*) assumed. Either <directory> or <filespec> or both may be missing, with the default directory and (*.*) assumed. As an example of the use of DIRF, (DIRF (*.LSP)) prints the names of all LSP files in the users directory. (TYPE {<device/directory>} <file1> {<file2>} . . .) This function types each <file> on the currently selected output device. Its principle use is to type a text file on the terminal without leaving LISP, for example, (TYPE LSP: (ILISP.MAN)) As usual, <device/directory> may be omitted, with DSK: assumed. Note that if more than one <file> is given they are simply concatenated together. Thus TYPE could be used to create a new file which is the concatenation of FILE1 and FILE2 by doing the following: (PROGN (OUTC (OUTPUT T NEWFILE)) (TYPE FILE1 FILE2) (OUTC NIL)) (%DEVP @<x>) Returns T if <x> is either a device name (i.e., an atomic symbol which ends in ":"), or a programmer project number (i.e, a list whose CDR is not an atomic symbol). Used by INPUT, OUTPUT, DSKIN, etc. RUTGERS/UCI LISP MANUAL Page 20 New Output Functions ←←←←←←←←←←←←←←←←←←←← (MSG <i1> {<i2>} . . .) MSG provides a general message-printing facility for ILISP. Each <i> is an instruction which provides a specific formatting capability: "<string>" Print <string> using PRINAC +<number> Space <number> spaces (T @<n>) Tab to position <n> T Move to new line -<number> Print <number> blank lines (E <expr>) Evaluate <expr> other Eval and print using PRINA As an example of the use of MSG, consider the following: (MSG T "Value of X is:" 5 X T) which is equivalent to: (PROGN (TERPRI) (PRINAC @"Value of X is:") (SPACES 5) (PRINA X) (TERPRI)) Note that MSG prints the desired message on the currently selected output device. MSG returns NIL, and is compiled in-line. (TTYOUT <e1> {<e2>} . . .) TTYOUT may be used to direct output to the terminal instead of the currently selected output device. The current channel is deselected, the TTY is selected, and the <e>s are evaluated (hopefully doing some printing). The previous channel is then reselected, and the value of <en> is returned as the value of the TTYOUT. TTYOUT is compiled in-line. (TTYMSG <i1> {<i2>} . . .) Equivalent to (TTYOUT (TALK) (MSG <i1> <i2> . . .)) That is, TTYMSG is identical to MSG, except printed output is directed to the terminal instead of the currently selected output device. To insure that the message will appear on the terminal even if ↑O has been struck, a TALK is performed before printing. TTYMSG is compiled in-line. RUTGERS/UCI LISP MANUAL Page 21 (PRINA @<x> {@<pos>}) Like PRIN1, except if an atom won't fit on the line, a tab to position <pos> on the next line is performed before printing resumes. <pos> is optional, with a value of 1 assumed if omitted. (PRINAC @<x> {@<pos>}) Identical to PRINA, except PRINC is used to print atoms instead of PRIN1. (SPACES @<n>) Prints <n> spaces. If <n> spaces won't fit on the current line, SPACES performs a TERPRI instead. (LINES @<n>) Prints <n> blank lines. Note that the next print position will always be at the start of a line, so (LINES 0) may be used as a "conditional TERPRI" which outputs a carriage return if not already at the start of a line. (PRINL @<l>) Prints the list <l> without the outermost parentheses, i.e., prints the elements of <l> separated by spaces. Each element is printed using PRINA, with a <pos> of 1. (PRINLC @<l>) Identical to PRINL, except uses PRINAC instead of PRINA to print the list elements. (PRINTC @<x>) Identical to PRINT, except uses PRINC instead of PRIN1. (DPRINT @<x>) Prints <x> with BASE set to 10 (decimal). (TALK) Undoes the effect of a previous ↑O. May be used to insure that a message will appear on the terminal (see TTYMSG). Note that a TALK is automatically performed by the system whenever an error condition is encountered or a prompt character is output. RUTGERS/UCI LISP MANUAL Page 22 (OUTCH) Returns the name of the currently selected output channel (NIL if the TTY). New Input Functions ←←←←←←←←←←←←←←←←←←← (TTYIN <e1> {<e2>} . . .) TTYIN may be used to request input from the terminal instead of the currently selected input device. The current channel is deselected, the TTY is selected and the <e>s are evaluated (hopefully doing some input). The previous channel is then reselected, and the value of <en> is returned as the value of the TTYIN. TTYIN is compiled in-line. (READL) Identical to (LINEREAD). READL is (in some sense) the inverse of PRINL. (PEEKC) Returns the ASCII code of the next character in the input stream without reading the character. Equivalent to (UNTYI (TYI)). (DELIM @<char>) Returns T if the character whose ASCII code is <char> is a delimiter (i.e., will stop the formation of an atomic symbol), and NIL if it isn't. For example, (DELIM (PEEKC)) checks if the next character in the input stream will be a delimiter. (CURRCOL) Returns the number of the next available print position. (INCH) Returns the name of the currently selected input channel (NIL if the TTY). RUTGERS/UCI LISP MANUAL Page 23 V. NEW DEBUGGING FACILITIES ←←←←←←←←←←←←←←←←←←←←←←←←←←← Additions to the Editor ←←←←←←←←←←←←←←←←←←←←←←← LASTWORD LASTWORD is the variable used by EDITF, EDITV, and EDITP to obtain a name when none is given explicitly. It should be noted that in addition to the editor, this variable is now set and referenced by other program development modules, including the functions DE, DF, DM, PP, BREAK, and TRACE. Thus (EDITF) will edit the function last referenced by any of these functions. ←←← (EDITEXPR @<expr>) If <expr> is an atom EDITEXPR simply returns <expr>; otherwise the editor is called with <expr> as the object to be edited. PP* Command Prettyprints the current edit expression with COMMENTFLG set to T. F, BF Commands The F and BF commands now save their arguments from one call to the next; if used without an argument the previous F or BF pattern is used. Note also that strings may now be found (or replaced) if desired. FP, BFP Commands FP and BFP are equivalent to F and BF followed by a P (Print). They also save their find patterns from one call to the next. Additions to the Break Package ←←←←←←←←←←←←←←←←←←←←←←←←←←←←←← LASTWORD As mentioned above, (BREAK) and (TRACE) may be used to break or trace the function last defined, edited, or prettyprinted (or broken or traced, if a subsequent UNBREAK or UNTRACE was performed). Note that BREAK and TRACE set LASTWORD only for "simple" breaks or traces - complex conditional breaks, breaks inside of other functions, etc., do not change LASTWORD. RUTGERS/UCI LISP MANUAL Page 24 BREAK and TRACE of Compiled Functions When breaking or tracing compiled functions, the argument lists supplied by the user are now saved from one call to the next, so they need only be supplied once for each function. The argument list is stored on the property list of the function name under the property ARGS. A function which wishes to break a compiled function under program control without user interaction can thus specify an argument list by placing it under the ARGS property. (TRACEV <var1> {<var2>} . . .) TRACEV provides a value-tracing facility for uncompiled ILISP code. Each time one of the <var>s has its value changed via SET or SETQ a message showing the new value is printed. Note that initial variable bindings in LAMBDA expressions and PROGs, and variables bound within compiled functions, will not be traced. (UNTRACEV {<var1>} {<var2>} . . .) Each variable <var> will have its value tracing turned off. Like UNBREAK and UNTRACE, (UNTRACEV T) may be used to untrace the most recently-traced variable, and (UNTRACEV) turns off all value tracing. RUTGERS/UCI LISP MANUAL Page 25 VI. THE LISP PRETTYPRINTER ←←←←←←←←←←←←←←←←←←←←←←←←←← The ILISP prettyprint package provides a powerful facility for printing functions in readable form and creating formatted symbolic files. New capabilities include a "printmacro" mechanism, three levels of user commenting, and a "prettyprint command" facility for controlling the printing process. Basic Functions ←←←←←←←←←←←←←←← (PP {<a1>} {<a2>} . . .) (PP replaces the old GRINDEF). If <a> is atomic, each property of <a> which appears on the list PRETTYPROPS is printed in readable format. (If no such properties appear a message to that effect is printed - this message may be suppressed by setting NOPRETTYPROPS to NIL). Each non-atomic <a> is simply printed via SPRINT unless its CAR is defined as a "prettyprint command", in which case the expression is evaluated (prettyprint commands are explained further below). <a> may also be a list consisting of a LAP expression followed by a sequence of LAP code; such a list will be printed in standard LAP format. If no <a>s are present, the value of LASTWORD is used. LASTWORD is also set to the name of the last function printed. Note that if the value of the atomic symbol PP is non-NIL and output is being directed to a device other than the terminal, PP will print the name of each function printed on the terminal. This feature is used by DSKOUT to provide feedback about the dump (i.e., PP is set to the value of DSKOUT before the prettyprinter is invoked). (PPL <var1> {<var2>} . . .) (PPL replaces the old GRINL). Each <var> should be an atomic symbol which is bound to a prettyprint list to be passed on to PP. This prettyprint list may contain atomic symbols whose properties are to be printed, prettyprint command expressions, and other expressions which are to be SPRINTed. Each <var> (except ALLFNS) which is not already a member of its prettyprint list will be printed so that if dumping to a file its value will be restored when the file is subsequently loaded. The prettyprint list will disappear when the file is compiled, however (i.e., it will not appear in the LAP file). (SPRINT @<expr> @<col>) SPRINT is the workhorse of the prettyprint package - it is used by PP and PPL to print <expr>s in pretty form starting in column <col>. The prettyprinting RUTGERS/UCI LISP MANUAL Page 26 capabilities of SPRINT may be suppressed by setting the special variable PRETTYFLG to NIL. In this mode, the prettyprint package may be used to produce fast, compact (though not very readable) symbolic dumps. PRETTYPROPS ←←←←←←←←←←← (PRETTYPROPS replaces the old GRINPROPS). In its simplest form, PRETTYPROPS is a list of atomic symbols which gives the properties which PP is to print. Each atomic argument to PP which has a property on PRETTYPROPS will be printed as a DEFPROP expression. Occasionally, however, it is desirable to print certain properties in something other than DEFPROP format. This may be accomplished by putting a consed pair of the form (<prop> . <fn>) onto PRETTYPROPS; when an atom with a <prop> property is encountered, PP simply prints a carriage return and calls <fn>. <fn> will be passed three arguments: the atom currently being PPed, the value stored under the property <prop>, and the atom <prop> itself. The function can then print anything it wishes before returning to PP, at which time another carriage return will be printed. For example, the functions PP-VALUE and PP-RMACS are provided by the prettyprint package to print VALUE and READMACRO properties in special form. PRETTYPROPS is initialized to (SPECIAL EXPR FEXPR MACRO (VALUE . PP-VALUE) PRINTMACRO (READMACRO . PP-RMACS)). Prettyprint Commands ←←←←←←←←←←←←←←←←←←←← Prettyprint commands may be used as arguments to PP or in PPL prettyprint lists to perform a variety of special formatting tasks. A prettyprint command is simply an expression whose CAR is a function name with a non-NIL PPCOM property. Such expressions are evaluated when encountered by PP, thus providing a mechanism for "grabbing control" during the prettyprint process. The user may define his own prettyprint commands, or may use the following functions supplied by the system. Note that in addition to appearing as prettyprint commands in PPL lists, these expressions may be used in other contexts as well. (*PG*) Outputs a page eject; may be used to place various sections of a large symbolic file on different pages. (F: <fn1> {<fn2>} . . .) Prettyprints any functional attributes of each <fn>, ignoring all other properties. Actually, F: simply sets PRETTYPROPS to (EXPR FEXPR MACRO) and passes its arguments on to PP, so each <fn> may be anything which can normally be used as an argument to PP. PRETTYPROPS is restored after printing is completed. RUTGERS/UCI LISP MANUAL Page 27 (P: <props> <x1> {<x2>} . . .) PRETTYPROPS is set to <props>, the <x>s are passed on to PP, and PRETTYPROPS is restored. For example, F: could be defined as (P: (EXPR FEXPR MACRO) <fn1> <fn2> . . .) (V: <x1> {<x2>} . . .) Useful for printing values. Each <x> may be either an atomic symbol <var> or a list of the form (<var> <val>). Each <var> will be printed as a DEFV expression, with a value of <val> if given, or the current value of the variable if only the variable name was given (unbound variables are printed with a value of NIL). (MBD: <fn> <x1> {<x2>} . . .) Passes the <x>s on to PP in such a way that they will be prettyprinted inside of an expression starting with <fn>. For example, to prettyprint F1 and F2 inside of a PROGN expression (perhaps so they will not be compiled) one could do: (MBD: PROGN F1 F2) (FORMS: <x1> {<x2>} . . .) Each <x> is passed directly to SPRINT - may be used to print atoms and prettyprint command expressions which would normally be handled specially by PP. (E: <e1> {<e2>} . . .) The <e>s are simply evaluated. For example, the inclusion of the following in a prettyprint list could be used to change the base in the middle of a print: (E: (SETQ BASE 10.)) Printmacros ←←←←←←←←←←← SPRINT normally operates by formatting the expression being printed using indentation to produce "pretty" output. It is occasionally desirable to have certain subexpressions printed in some special format for increased readability. Such a capability is provided via the use of printmacros. Any function may be ←←←←←←←←←←← flagged as a printmacro by placing the macro definition on the property list of the atom under the indicator PRINTMACRO. Whenever an atom with such a property appears as the first element in a list being prettyprinted, SPRINT takes special action, such action depending on the value of the PRINTMACRO property: RUTGERS/UCI LISP MANUAL Page 28 (1) If the value is a string the string is simply PRINCed and the CADR of the original expression is SPRINTed. This serves as an inverse for READMACROs of the @<e> -> (QUOTE <e>) type. For example, (DEFPROP QUOTE "@" PRINTMACRO) (DEFPROP THV "$?" PRINTMACRO) (the QUOTE printmacro is in fact already present in ILISP). (2) If the value is the special atomic symbol BRACKETS then the expression is printed by SPRINT in the normal way, except that each top-level non-atomic argument will be printed with brackets [...] instead of the usual parentheses (...). This gives the user one more method of producing more readable output. COND, SELECTQ, AND, OR, and CATCH are initialized as printmacros of this type. To disable the use of brackets for these functions simply REMPROP the PRINTMACRO property from their property lists. (3) If the value of the PRINTMACRO property is neither a string nor the atomic symbol BRACKETS it is assumed to be a true printmacro function (or, more typically, the name of a function). This function will be passed the expression being printed as its only argument, and may print it in any format it wishes (calling SPRINT recursively if desired). If the printmacro function decides that the expression should be printed in normal form by SPRINT (i.e., it is a "conditional" printmacro), it may simply print nothing and return the atomic symbol SPRINT. SPRINT will then print the expression as if no printmacro property were present (note that this special case is necessitated by the fact that a recursive call on SPRINT with the original expression would cause the printmacro function to be reinvoked). If the printmacro function returns anything else, SPRINT assumes that it has printed the entire expression, and simply proceeds. As an example of a printmacro function, one might do the following in lieu of defining QUOTE as a string printmacro: (DEFPROP QUOTE (LAMBDA (E) (COND [(AND [CONSP (CDR E)] [NULL (CDDR E)]) (PRINC @"@") (SPRINT (CADR E) (CURRCOL))] [T @SPRINT])) PRINTMACRO) This is in fact what is already done for string printmacros - the expression is checked to insure that it has only one argument and, if not, is printed as a normal list. RUTGERS/UCI LISP MANUAL Page 29 To make the writing of printmacro functions easier several auxiliary formatting functions are provided: (PP-FORMAT @<e> @<n> @<flag>) Prints the expression <e> with the first <n>+1 elements (the function name and <n> arguments) printed on one line. <flag> specifies how the remaining arguments are to be printed: if <flag>=NIL (standard format), all remaining arguments are printed under the first argument; if <flag>=MISER, the remaining arguments are placed under the function name; if <flag>=LABELS, all non-atomic arguments are printed under the first argument, with atoms placed to the left as labels. Note, however, that if the entire expression will fit on one line, and is less than PP-FORMAT characters long (initially 40), it will be printed on one line. (PP-MISER @<e>) Equivalent to: (PP-FORMAT @<e> 1 @MISER) This is the system printmacro function used for LAMBDA and DEFPROP. (PP-MISER0 @<e>) Equivalent to: (PP-FORMAT @<e> 0 @MISER) This is the system printmacro function used for FUNCTION and *FUNCTION. (PP-LABELS @<e>) Equivalent to: (PP-FORMAT @<e> 1 @LABELS) This is the system printmacro function used for PROG. Comments ←←←←←←←← One of the major disadvantages of many LISP systems is the lack of a usable commenting facility. This has been remedied in ILISP by the addition of three levels of comments: *, **, and ***. These atoms are defined as macros which expand to NIL; expressions starting with *, **, or *** may be placed in function definitions anywhere a NIL could be placed without harm, e.g., at the top level of LAMBDAs and PROGs (when the function is subsequently compiled, these expressions will disappear). *, **, RUTGERS/UCI LISP MANUAL Page 30 and *** are also defined as printmacros which cause the expression to be printed in block form as a comment. * comments are intended to be used for detailed descriptions of code - they are printed starting in column 40. ** comments are intended to serve as top-level descriptions of functions - they are printed starting in column 10. *** comments are intended to be used in prettyprint lists to describe major sections of a symbolic file (perhaps following a (*PG*) prettyprint command) - they are printed starting in column 1. Recall that the E: prettyprint command may be used to cause expressions to be evaluated before printing a certain function. It is also possible to cause an expression to be evaluated while ←←←←← a function is being prettyprinted. This is done by placing the atomic symbol E as the second element of a comment, and the expression to be evaluated as the third element. For example, the comment (* E (SETQ BASE 10.) Changing base) changes the base at prettyprint time. Comment atoms are flagged by placing the function name PP-COMMENT on the property list of the atom under the PRINTMACRO property, and putting the desired starting print column on the property list under the property COMMENT. The user may thus disable *, **, and/or *** as comment atoms by removing these two properties, or may change the starting column or add new comment atoms if desired. Note that comments are intended primarily to comment symbolic files - when printing to the terminal all comments appear simply as *COMMENT* unless the special variable COMMENTFLG is non-NIL. The functions PP* and PPL*, and the edit command PP*, may be used to print function definitions with comments on the terminal (i.e., they first set COMMENTFLG to T). Note also that comments are treated by LISP as normal list structures, and hence must obey all LISP syntax rules. In particular, this means that periods may not be used and commas will disappear. It is suggested that ";" be used instead of period as a terminator as it is not a LISP punctuation mark and thus simply becomes part of an atomic symbol. RUTGERS/UCI LISP MANUAL Page 31 VII. THE COMPILER AND LAP ←←←←←←←←←←←←←←←←←←←←←←←←← The ILISP compiler (ILISPC) is an extended (and debugged) version of the Stanford LISP 1.6 compiler. As before, a file of LISP functions is compiled via the function COMPL, which takes a file specification (like DSKIN) and creates a LAP file which can subsequently be loaded via DSKIN. Declarations ←←←←←←←←←←←← Although the use of the compiler is quite straightforward, there are several declarations which can (and sometimes must) be made to give the compiler additional information about your code. These declarations should appear at the beginning of the file inside a DECLARE expression: (DECLARE <d1> {<d2>} . . .) Each <d> is a compiler declaration expression - such declarations are ignored when the file containing the DECLARE is loaded, but are evaluated when the file is compiled. Available declarations are given below. (SPECIAL <var1> {<var2>} . . .) Declares each <var> as a special variable, i.e., a variable which appears free in a function. Note that free variables in in-line LAMBDA expressions and LAMBDA expressions used as arguments to most system functions (e.g., the MAP functions) need not be declared SPECIAL, as such functions are compiled in-line. In addition ERRSETs are now compiled in-line, so variables in ERRSET expressions no longer have to be declared SPECIAL. All undeclared free variables in a file may be found by compiling the file and examining the error messages; for convenience, the compiler places all newly-discovered special variables on the list SPECIALS. (UNSPECIAL <var1> {<var2>} . . .) This declaration may be used to inform the compiler that certain variables are no longer considered special, and should be compiled as normal local variables in subsequent functions. (NOCALL <a1> {<a2>} . . .) Each <a> should be either the name of a function to be compiled or a special variable. These functions and variables are assumed to be local to the file being compiled and will thus never be traced, called or referenced from functions not in this file, or used as entry points or top-level values. The compiler can RUTGERS/UCI LISP MANUAL Page 32 compile references to such functions as direct jumps, and the atoms may be REMOBed when the file is loaded (see DUMPATOMS below). It is also possible to cause all ←←← function references to be changed to direct jumps when a LAP file is loaded (see below). (CALL <fn1> {<fn2>} . . .) Specifies that each <fn> should always be called via the ←←←←←← function-calling mechanism and not changed to direct jumps. Necessary in rare cases when the new NOCALL=T feature is being used (see below for further explanation). (GLOBALMACRO <mac1> {<mac2>} . . .) Macro definitions are normally assumed to be used only by functions in the file in which they appear, and hence are not necessary after the file is compiled. Occassionally, however, it is desirable to keep the macro definitions after compilation by having them copied into the LAP file (PLUS is such a macro for example). The GLOBALMACRO declaration specifies that each <mac> is such a global macro and should be saved. (*SUBR/*FSUBR/*LSUBR <fn1> {<fn2>} . . .) FSUBRs and LSUBRs which are referenced before they are compiled must be declared (via *FSUBR and *LSUBR) so that the compiler can compile function references correctly. *SUBR declarations may also be made, although they are normally not necessary since all undefined functions are assumed to be SUBRs. The only exception is when a function name is also used as a variable - it then must be declared if it is referenced before it is compiled. *EXPR, *FEXPR, and *LEXPR may be used in place of *SUBR, *FSUBR, and *LSUBR if desired. Extensions to NOCALL ←←←←←←←←←←←←←←←←←←←← As stated above, NOCALL declarations are intended to flag atomic symbols (both functions and, in the Rutgers ILISP system, special variables) which are not necessary after a LAP file is loaded and may thus be REMOBed (only the special cell of a variable is actually referenced by compiled code). In order to make this process reversible, the following function is now provided: (DUMPATOMS {<file>}) After loading a set of files which contain NOCALL declarations, DUMPATOMS may be called to REMOB all NOCALL atoms after first creating a file <file> which, when subsequently loaded, will restore the SUBR, FSUBR, LSUBR, RUTGERS/UCI LISP MANUAL Page 33 VALUE, and SYM properties of each NOCALL atom. One can thus use DUMPATOMS to REMOB all NOCALL atoms (to save space), and if it is later discovered that one of the functions or special variables is needed after all, DSKIN the DUMPATOMS file to restore things to their previous state. If <file> is missing, (REMOB.LSP) is assumed. In addition to saving space by allowing unnecessary atomic symbols to be REMOBed, NOCALL declarations provide for faster execution by replacing function calls with direct jumps. It is now possible to cause all function calls to be loaded as direct ←←← jumps by setting NOCALL to T before loading the relevant files (it should be set back to NIL after loading is completed). Note that this should be done only after all functions are completely debugged, as none of the functions can be traced or redefined after loading. Specific functions may be exempted from this inclusive NOCALL by declaring them CALL at compile time (see above). This is optional in some cases (e.g., one wants to be able to trace a particular function), and necessary in others. In particular, any function which is listed as "undefined" at compile time must be declared CALL unless a compiled version of the function will later be loaded along with the LAP file. Note that when loading LAP files with NOCALL=T all functions are assumed to be either already defined when the files are loaded (e.g., system functions), or defined in the LAP files. If any existing compiled functions (such as system functions) are to be redefined, they must either be defined before they are referenced or must have their SUBR, FSUBR, or LSUBR properties removed before loading. LAP keeps track of any previously defined functions which are called via direct jumps (after loading is complete the value of NOCALL will be a list of such functions), and a warning message is printed if such a function is redefined. In-Line Code ←←←←←←←←←←←← A number of system functions are compiled in-line by the compiler, either because they generate only a few words of code or because they are FEXPRs which evaluate one or more arguments (if calls to such functions were not compiled in-line, the uncompiled arguments would be passed to the interpreter, slowing down execution considerably). Functions currently compiled in-line include: ERRSET, CATCH, THROW, RPTQ, COND, AND, OR, SELECTQ, PROG1, PROG2, PROGN (and DO), PROG, RETURN, GO, SETQ, MSG, TTYMSG, TTYIN, TTYOUT, SUBSET, EVERY, SOME, NOTANY, NOTEVERY, All Map Functions, APPEND (as *APPENDs), NCONC (as *NCONCs), LIST (as CONSes), CAR, CDR, RPLACA, RPLACD, EQ, NEQ, NULL (and NOT), ZEROP, ARG, SETARG, STORE, EVAL (as *EVAL or a direct call if possible), APPLY (as *APPLY or a direct call if possible), and APPLY# (as a direct call if possible). RUTGERS/UCI LISP MANUAL Page 34 Other Extensions ←←←←←←←←←←←←←←←← The compiler normally works by compiling all function definitions in the file (putting the compiled code in the LAP file), and copying all other expressions into the LAP file unchanged (except for comments and DECLARE expressions). It is sometimes desirable to change this standard convention. For example, the GLOBALMACRO declaration causes macros to be used by the compiler and also copied to the LAP file. Certain functions may have their compilation suppressed (with the symbolic definition copied to the LAP file) by placing their definitions inside a PROGN (the MBD: prettyprint command is useful for this). A new capability is now available which allows certain expressions to be evaluated when the symbolic file is loaded, but to not be copied to the LAP file. This is accomplished by placing the expressions inside a NOCOMPILE (which acts like a PROGN when evaluated). For example, the prettyprint package causes PPL prettyprint lists to disappear at compile time by placing the variable binding inside a NOCOMPILE expression. Recall that strings are normally not interned by the READ routine so that they will be garbage collected when no longer referenced. Strings appearing in compiled code will always be referenced, however, so LAP has been modified to intern them (by setting INTERNSTR to T). This has the advantage that functions which are compiled may reference the same string a number of times without penalty - only one copy will be stored. The compiler now prints the name of each function before its compilation has begun. If an error occurs, the last name printed is the function in error. Note also that the value returned by LAP (and thus printed by DSKIN) is now a list consisting of the name of the function loaded followed by the number of words of binary program space required for the compiled code. LAP maintains several global lists which the naive user should leave alone: LAPLST is used by the break package for associating variable names with special cells; LAPKLST (formerly KLIST) is used by LAP in order to reuse constants within compiled code; LAPQLST (formerly QLIST) is used in an attempt to reuse quoted expressions referenced from compiled code, and to make them known to the garbage collector; and LAPSLST is a list of special cells of NOCALL variables for use by the garbage collector. RUTGERS/UCI LISP MANUAL Page 35 VIII. INFORMATION FOR THE SYSTEM BUILDER ←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←← User Error Handling ←←←←←←←←←←←←←←←←←←← Recall that errors currently cause a message to be printed and a break to the break package to occur (unless an ERRSET is suppressing error messages or the break package has been turned off via (*RSET NIL)). The user now has the capability to grab control whenever an error is encountered by setting USERERRORX to the name of an error-handling function. If the user error handler returns NIL the system break package is entered, giving the user the ability to examine the form which caused the error (it is on the stack) and conditionally break to the break package. Otherwise it is assumed that the user error handler will process the error and either return a non-NIL value to continue the computation or restart at some other point. Note that the user error function should be a function of one argument, which in most cases should be ignored (it is an indication as to whether ILISP considers the error a "serious" error (T) or a "correctable" error (NIL); error messages for correctable errors may be suppressed via (*RSET @ERRORX)). Creating One's Own System ←←←←←←←←←←←←←←←←←←←←←←←←← Most users who create their own ILISP-based system will want to save only the low segment of their core image, with ILISP's sharable high segment loaded at run time. This may be accomplished by exiting from ILISP via (EXIT NIL), which removes the high segment so that SAVE will create only a SAV (low segment) file instead of LOW and HGH files. When such a SAV file is later RUN, ILISP's standard sharable high segment will automatically be loaded. Note that an EXCISE or a SYSCLR should always be done before exiting and saving ILISP - if this is not done the I/O buffers will be allocated as available space, causing the ALLOC? message to appear each time the saved program is run. Although it is suggested that most ILISP-based systems share the standard ILISP high segment as outlined above (ILISPC, FUZZY, etc. are of this type), it may be desirable that a heavily-used system with large amounts of compiled code have its own sharable high segment. In order to do this one must have write privileges for the system (see discussion under SETSYS in the UCI LISP manual), and must execute a HGHCOR to allocate space for compiled code in the high segment. The compiled code may then be loaded via the new function HGHIN, which is identical to DSKIN except compiled code is placed in the high segment. The following summarizes the procedure necessary to create a sharable system: RUTGERS/UCI LISP MANUAL Page 36 .R ILISP *(SETSYS (<proj>,<prog>) <name of system>) *(EXIT T) .SSA <name of system> .RU <name of system> *(HGHCOR <# of words of compiled code>) *(REALLOC <other space allocations> . . .) *(SETQ NOCALL T) *(HGHIN <your files>) *(SETQ NOCALL NIL) *(SYSCLR) *(INITFN @<fn to print header>) *(EXIT T) .SSA <name of system> Building ILISP ←←←←←←←←←←←←←← The files ILISP.CTL, ILISPC.CTL, PLNR.CTL, CNVR.CTL, and FUZZY.CTL are DOER control files which may be used for building the various ILISP modules. They should be consulted if any of these systems need to be reconstructed. After constructing the various modules, the following files should be copied into SYS: ILISP.LOW ILISP.SHR ILISP.LOD ILISP.SYM ILISPC.SAV PLNR.SAV (if desired) CNVR.SAV (if desired) FUZZY.SAV (if desired) RUTGERS/UCI LISP MANUAL Page 37 INDEX ←←←←← %DEVP . . . . . . . . . . . . . . . . . . . . . 19 * . . . . . . . . . . . . . . . . . . . . . . . 29 ** . . . . . . . . . . . . . . . . . . . . . . . 29 *** . . . . . . . . . . . . . . . . . . . . . . 29 *APPLY . . . . . . . . . . . . . . . . . . . . . 11 *FSUBR (or *FEXPR) . . . . . . . . . . . . . . . 32 *INSERT . . . . . . . . . . . . . . . . . . . . 14 *LSUBR (or *LEXPR) . . . . . . . . . . . . . . . 32 *MERGE . . . . . . . . . . . . . . . . . . . . . 14-15 *NCONC . . . . . . . . . . . . . . . . . . . . . 15 *NOPOINT . . . . . . . . . . . . . . . . . . . . 17 *NOPOINTDSK . . . . . . . . . . . . . . . . . . 17 *PG* . . . . . . . . . . . . . . . . . . . . . . 26, 30 *SORT . . . . . . . . . . . . . . . . . . . . . 15 *SUBR (or *EXPR) . . . . . . . . . . . . . . . . 32 ADDPROP . . . . . . . . . . . . . . . . . . . . 12 ALLFNS . . . . . . . . . . . . . . . . . . . . . 7 APPLY (Funarg Argument) . . . . . . . . . . . . 10 ARGS . . . . . . . . . . . . . . . . . . . . . . 24 ATOM . . . . . . . . . . . . . . . . . . . . . . 10 ATTACH . . . . . . . . . . . . . . . . . . . . . 16 BASE (With Negative Value) . . . . . . . . . . . 17 BF (Edit Command) . . . . . . . . . . . . . . . 23 BFP (Edit Command) . . . . . . . . . . . . . . . 23 BOUNDP . . . . . . . . . . . . . . . . . . . . . 11 BRACKETS . . . . . . . . . . . . . . . . . . . . 28 BREAK . . . . . . . . . . . . . . . . . . . . . 7, 23-24 CALL . . . . . . . . . . . . . . . . . . . . . . 32-33 CATCH . . . . . . . . . . . . . . . . . . . . . 10-11 COMMENT . . . . . . . . . . . . . . . . . . . . 30 COMMENTFLG . . . . . . . . . . . . . . . . . . . 23, 30 COMPL . . . . . . . . . . . . . . . . . . . . . 31 CONSP . . . . . . . . . . . . . . . . . . . . . 10 CONTINUE (Monitor Command) . . . . . . . . . . . 5 CURRCOL . . . . . . . . . . . . . . . . . . . . 22 DATE . . . . . . . . . . . . . . . . . . . . . . 9 DE . . . . . . . . . . . . . . . . . . . . . . . 7, 23 DECLARE . . . . . . . . . . . . . . . . . . . . 31 DEFLIST . . . . . . . . . . . . . . . . . . . . 12 DEFP . . . . . . . . . . . . . . . . . . . . . . 12 DEFV . . . . . . . . . . . . . . . . . . . . . . 12 DELIM . . . . . . . . . . . . . . . . . . . . . 22 DF . . . . . . . . . . . . . . . . . . . . . . . 7, 23 DIRF . . . . . . . . . . . . . . . . . . . . . . 19 DM . . . . . . . . . . . . . . . . . . . . . . . 7, 23 DO . . . . . . . . . . . . . . . . . . . . . . . 11 DPRINT . . . . . . . . . . . . . . . . . . . . . 21 DSKIN (Printing Control) . . . . . . . . . . . . 18 DSKLENGTH . . . . . . . . . . . . . . . . . . . 18 DSKOUT . . . . . . . . . . . . . . . . . . . . . 18, 25 DTIME . . . . . . . . . . . . . . . . . . . . . 9 DUMPATOMS . . . . . . . . . . . . . . . . . . . 32 E: . . . . . . . . . . . . . . . . . . . . . . . 27, 30 EDITCH . . . . . . . . . . . . . . . . . . . . . 6 EDITEXPR . . . . . . . . . . . . . . . . . . . . 23 EDITF . . . . . . . . . . . . . . . . . . . . . 7, 23 EDITP . . . . . . . . . . . . . . . . . . . . . 7, 23 EDITV . . . . . . . . . . . . . . . . . . . . . 7, 23 ENTER . . . . . . . . . . . . . . . . . . . . . 12, 15 EQSTR . . . . . . . . . . . . . . . . . . . . . 16 ERRCH . . . . . . . . . . . . . . . . . . . . . 6 ERRSET (Compiled In-line) . . . . . . . . . . . 31 EVAL (Funarg Argument) . . . . . . . . . . . . . 10 EVERY . . . . . . . . . . . . . . . . . . . . . 13 EXIT . . . . . . . . . . . . . . . . . . . . . . 5-6, 8 EXPBPS . . . . . . . . . . . . . . . . . . . . . 8 EXPFS . . . . . . . . . . . . . . . . . . . . . 8 EXPFWS . . . . . . . . . . . . . . . . . . . . . 8 F (Edit Command) . . . . . . . . . . . . . . . . 23 F: . . . . . . . . . . . . . . . . . . . . . . . 26 FILBAK . . . . . . . . . . . . . . . . . . . . . 18 FORMS: . . . . . . . . . . . . . . . . . . . . . 27 FP (Edit Command) . . . . . . . . . . . . . . . 23 FSCNT . . . . . . . . . . . . . . . . . . . . . 9 Funarg Pointers . . . . . . . . . . . . . . . . 10 FWCNT . . . . . . . . . . . . . . . . . . . . . 9 GETDEF . . . . . . . . . . . . . . . . . . . . . 18-19 GLOBALMACRO . . . . . . . . . . . . . . . . . . 32 HGHIN . . . . . . . . . . . . . . . . . . . . . 35 INCH . . . . . . . . . . . . . . . . . . . . . . 22 INSERT . . . . . . . . . . . . . . . . . . . . . 14 INTERNSTR . . . . . . . . . . . . . . . . . . . 17, 34 INTERSECTION . . . . . . . . . . . . . . . . . . 15 KLIST (Changed to LAPKLST) . . . . . . . . . . . 34 LAP . . . . . . . . . . . . . . . . . . . . . . 17, 25, 31-34 LAPKLST . . . . . . . . . . . . . . . . . . . . 34 LAPLST . . . . . . . . . . . . . . . . . . . . . 34 LAPQLST . . . . . . . . . . . . . . . . . . . . 34 LAPSLST . . . . . . . . . . . . . . . . . . . . 34 LASTWORD . . . . . . . . . . . . . . . . . . . . 7, 23, 25 LEXORDERCAR . . . . . . . . . . . . . . . . . . 14-15 LINEREAD . . . . . . . . . . . . . . . . . . . . 22 LINES . . . . . . . . . . . . . . . . . . . . . 21 LOAD (Aborted by ↑C) . . . . . . . . . . . . . . 5 LPTLENGTH (Identical to DSKLENGTH) . . . . . . . 18 MAPATOMS . . . . . . . . . . . . . . . . . . . . 13 MBD: . . . . . . . . . . . . . . . . . . . . . . 27, 34 MCONS . . . . . . . . . . . . . . . . . . . . . 16 MEMBFN . . . . . . . . . . . . . . . . . . . . . 12, 15 MERGE . . . . . . . . . . . . . . . . . . . . . 15 MODCHR (Interaction with PRINT) . . . . . . . . 18 MSG . . . . . . . . . . . . . . . . . . . . . . 20 NCONC1 . . . . . . . . . . . . . . . . . . . . . 16 NIL (CAR and CDR = NIL) . . . . . . . . . . . . 10 NOCALL . . . . . . . . . . . . . . . . . . . . . 31-33 NOCOMPILE . . . . . . . . . . . . . . . . . . . 34 NOPRETTYPROPS . . . . . . . . . . . . . . . . . 25 NOTANY . . . . . . . . . . . . . . . . . . . . . 14 NOTEVERY . . . . . . . . . . . . . . . . . . . . 14 OUTCH . . . . . . . . . . . . . . . . . . . . . 22 P: . . . . . . . . . . . . . . . . . . . . . . . 27 PATOM . . . . . . . . . . . . . . . . . . . . . 10 PEEKC . . . . . . . . . . . . . . . . . . . . . 22 PP . . . . . . . . . . . . . . . . . . . . . . . 7, 23, 25 PP* . . . . . . . . . . . . . . . . . . . . . . 30 PP* (Edit Command) . . . . . . . . . . . . . . . 23, 30 PP-COMMENT . . . . . . . . . . . . . . . . . . . 30 PP-FORMAT . . . . . . . . . . . . . . . . . . . 29 PP-LABELS . . . . . . . . . . . . . . . . . . . 29 PP-MISER . . . . . . . . . . . . . . . . . . . . 29 PP-MISER0 . . . . . . . . . . . . . . . . . . . 29 PPCOM . . . . . . . . . . . . . . . . . . . . . 26 PPL . . . . . . . . . . . . . . . . . . . . . . 25 PPL* . . . . . . . . . . . . . . . . . . . . . . 30 PRETTYPROPS . . . . . . . . . . . . . . . . . . 25-26 PRINA . . . . . . . . . . . . . . . . . . . . . 20-21 PRINAC . . . . . . . . . . . . . . . . . . . . . 20-21 PRINL . . . . . . . . . . . . . . . . . . . . . 21 PRINLC . . . . . . . . . . . . . . . . . . . . . 21 PRINTC . . . . . . . . . . . . . . . . . . . . . 21 PRINTMACRO . . . . . . . . . . . . . . . . . . . 27 PUT . . . . . . . . . . . . . . . . . . . . . . 13 PUTLIST . . . . . . . . . . . . . . . . . . . . 13 Q (The Octal Point) . . . . . . . . . . . . . . 17 QLIST (Changed to LAPQLST) . . . . . . . . . . . 34 RAISE . . . . . . . . . . . . . . . . . . . . . 7 READL . . . . . . . . . . . . . . . . . . . . . 22 REALLOC . . . . . . . . . . . . . . . . . . . . 8 REENTER (Monitor Command) . . . . . . . . . . . 5-6 REMLIST . . . . . . . . . . . . . . . . . . . . 13 REMPROPS . . . . . . . . . . . . . . . . . . . . 13 REREADCH . . . . . . . . . . . . . . . . . . . . 6 RPTN . . . . . . . . . . . . . . . . . . . . . . 11 RPTQ . . . . . . . . . . . . . . . . . . . . . . 11 SOME . . . . . . . . . . . . . . . . . . . . . . 13 SORT . . . . . . . . . . . . . . . . . . . . . . 15 SPACES . . . . . . . . . . . . . . . . . . . . . 21 SPDL Pointers . . . . . . . . . . . . . . . . . 10 SPECIAL . . . . . . . . . . . . . . . . . . . . 31 SPECIALS . . . . . . . . . . . . . . . . . . . . 31 SPRINT . . . . . . . . . . . . . . . . . . . . . 25, 27-28 START (Monitor Command) . . . . . . . . . . . . 5-6 SUBSET . . . . . . . . . . . . . . . . . . . . . 14 SUBSTRING . . . . . . . . . . . . . . . . . . . 16 TALK . . . . . . . . . . . . . . . . . . . . . . 20-21 THROW . . . . . . . . . . . . . . . . . . . . . 10-11 TIMER . . . . . . . . . . . . . . . . . . . . . 9 TRACE . . . . . . . . . . . . . . . . . . . . . 7, 23-24 TRACEV . . . . . . . . . . . . . . . . . . . . . 24 TTYIN . . . . . . . . . . . . . . . . . . . . . 22 TTYMSG . . . . . . . . . . . . . . . . . . . . . 20 TTYOUT . . . . . . . . . . . . . . . . . . . . . 20 TYPE . . . . . . . . . . . . . . . . . . . . . . 19 UNION . . . . . . . . . . . . . . . . . . . . . 15 UNSAVE . . . . . . . . . . . . . . . . . . . . . 7 UNSPECIAL . . . . . . . . . . . . . . . . . . . 31 UNTRACEV . . . . . . . . . . . . . . . . . . . . 24 USERERRORX . . . . . . . . . . . . . . . . . . . 35 V: . . . . . . . . . . . . . . . . . . . . . . . 27 ↑C . . . . . . . . . . . . . . . . . . . . . . . 5-6 ↑D . . . . . . . . . . . . . . . . . . . . . . . 5 ↑F . . . . . . . . . . . . . . . . . . . . . . . 6 ↑G . . . . . . . . . . . . . . . . . . . . . . . 6 ↑H . . . . . . . . . . . . . . . . . . . . . . . 6 ↑O . . . . . . . . . . . . . . . . . . . . . . . 9, 20-21 ↑R . . . . . . . . . . . . . . . . . . . . . . . 6 ↑U . . . . . . . . . . . . . . . . . . . . . . . 6 ↑X . . . . . . . . . . . . . . . . . . . . . . . 5-6, 8 ↑Z . . . . . . . . . . . . . . . . . . . . . . . 6