+-------------------------------------------+ | | | | | Document #3621001 | | | | LISP on CMS at UIC | | | | Version of 06/30/77 | | | | | | 44 Pages | | | +-------------------------------------------+ June 1977 PREFACE This manual is a reference for the modified version of Stanford LISP/360 used at the UIC Computer Center. The modifications are designed to allow convenient interactive use of LISP for modest computations. It is assumed that the reader has a general working knowledge of LISP 1.5 as described in the LISP 1.5 Pro- grammers' Manual by John McCarthy, and in the LISP 1.5 Primer by Clark Weiss- man, and that the reader has a general knowledge of the operating environment of OS 370. Beginning users of LISP will find the sections "The LISP System", "Organization of Storage", "Functions", "LISP Editing Functions", and "LISP System Messages" most helpful in obtaining a basic understanding of the LISP system. Other sec- tions of the manual are intended for users desiring a more extensive knowledge of LISP. From the Stanford LISP/360 Reference Manual: "The particular implementation to which this reference manual is directed was started by Mr. J. Kent while he was at the University of Waterloo. It is modeled after his implemention of LISP 1.5 for the CDC 3600." NOTE TO FULL-SCREEN CMS USERS In Section 11, LISP on CMS at UIC, the use of the Break Key as an interrupt in LISP is discussed. As is always true, one should NEVER use the Break Key LISP at UIC 06/30/77 Page 2 during a Full-Screen CMS session. Unfortunately, there is no Full-Screen equivalent for the Break Key in LISP. NOTE March 1985 The LISP interpreter has been removed from TSO due to lack of use. This same interpreter (with the minor differences described in Section 11 of this docu- ment) is presently available on CMS, but might be replaced by a newer version of LISP within in the next year. We have changed the name of this document, describing the old version of LISP, to minimize confusion (it formerly was "LISP on TSO at UIC"), but otherwise it has not been changed. LISP at UIC 06/30/77 Page 3 Note from Authors: This version of LISP, and this manual, would not have been possible except for the assistance and encouragement of many of the staff of the UIC Computer Cen- ter. Richard G. Larson Neil W. Rickert Mathematics Department University of Illinois at Chicago * * * Table of Contents Preface Table of Contents 1. The LISP System 2. Organization of Storage 2.1 Free Cell Storage (FCS) 2.1.1 Atoms 2.1.2 Numbers 2.1.3 Object List 2.2 Push-down Stack (PDS) 2.3 System Functions 2.4 Binary Program Space (BPS) 2.5 Input-Output Buffers 3. Functions, Predefined Atoms and Character-Objects 3.1 LISP Functions 3.2 Atoms with Initial Values 3.3 Character-objects 4. Special Differences in this Version of LISP 5. LISP Editing Functions 5.1 Editing and Printing Functions 5.1.1 Edit (name) 5.1.2 Error Messages with EDIT LISP at UIC 06/30/77 Page 4 5.1.3 DISPLAY (exp) 5.2 Simple Data Management - Functions 5.2.1 OUTFILE (ddn a[list indlist) 5.2.2 INFILE (ddn) 6. LISP Attention Interrupt Functions 6.1 Interruption of Computations 6.1.1 RESUME ( ) 6.1.2 INIT ( ) 6.2 Programmer Attention Interrupt Handling 6.2.1 BREAK (e alst) 7. Data Management in LISP 7.1 Data Management Functions 7.1.1 OPEN (ddname,list,at) 7.1.2 CLOSE (ddname) 7.1.3 ASA (p) 7.1.4 OTLL (n) 7.1.5 WRS (ddname) 7.1.6 INLL (n) 7.1.7 RDS (ddname) 7.2 Checkpoint Facilities in LISP/360 7.2.1 CHKPOINT (ddname) 7.2.2 RESTORE (ddname) 8. The Garbage Collector 9. Using LISP In Batch 10. LISP System Messages 10.1 Supervisor 10.2 Tracing in LISP 10.3 Garbage Collector Message 10.4 Interruption Message 10.5 Error Diagnostics 10.5.1 Syntax Errors 10.5.2 Execution Errors 10.5.3 Error Codes and Messages 11. LISP on CMS at UIC (October 1980) Appendix: The LISP Interpreter References * * * * * * * * * * * * * * * * * * * 1. THE LISP SYSTEM LISP at UIC 06/30/77 Page 5 LISP operates under the IBM System/370 Operating System (MVS). It can operate either with an EVALQUOTE Supervisor or with an EVAL Supervisor. The operation with the EVALQUOTE Supervisor is as follows: 1. Read a function and list of arguments. 2. Pass the function and list of arguments to the function EVALQUOTE for evaluation. 3. Print the computed value of the function. 4. Start again at step 1. The operation with the EVAL Supervisor is as follows: 1. Read a form. 2. Pass the form to the function EVAL for evaluation. 3. Print the computed value of the form. 4. Start again at Step 1. When LISP is first entered, it runs with the EVALQUOTE Supervisor. The func- tion EVALSUP(p) is used to change supervisors. LISP is exited upon detection of end of file on input file LISPIN (enter /* at the terminal) or by calling the function STOP( ). An optional timer is provided to print the time required to do Step 2 with either supervisor. The LISP system initially consists of a large body of predefined functions and provides the facility to add additional function definitions. Statements in the LISP language are evaluated interpretively to determine their value, although some functions are evaluated more for their effect than for their value. During execution, LISP data structures (including LISP function definitions) are constructed in Free Cell Storage (FCS). The Push-down Stack (PDS) is used to store program parameters dynamically during recursion. Other system areas are allocated as Binary Program Space (BPS) to contain the machine code for all compiled functions and as I/O Buffers to be used by OS. 2. ORGANIZATION OF STORAGE Within the LISP system, computer memory is subdivided into several functional areas. The largest portion of system memory is devoted to Free Cell Storage (FCS), the area used to contain all working data structures. The remaining parts of memory are used for the Push-down Stack (PDS), Binary Program Space (BPS), Input/Output Buffers, and system functions. 2.1 Free Cell Storage (FCS) A large portion of LISP memory is devoted to the storage of working data struc- tures in Free Cell Storage. Each word of FCS (called a LISP cell) is a double- word (64 bits) consisting of an upper word (32 bits) and a lower word (32 bits). LISP cells, depending on their use, may contain four fields: Bits 0-7 LISP at UIC 06/30/77 Page 6 are used for flags, 8-31 for the first address (the address of the CAR) 32-39 for flags, and 40-63 for the second address (the address of the CDR). Initially, all available words in FCS are in a free cell list. As LISP cells are used to create data structures, they are removed from the free cell list until removal of the last word forces the system to perform a garbage collec- tion in an attempt to restore words to the free cell list. A LISP cell is normally considered to contain pointers to other LISP cells in both its upper and lower words, but a special type of LISP cell is defined in which the upper word contains information other than a pointer. This LISP cell is called a full cell. Since the length of the LISP cell is 64 bits, and only 24 bits are needed to express an address, the first 8 bits in the upper word and the first 8 bits in the lower are available for other uses. The following indicates the uses for some of these bits as explained below. Bit 0 - indicates that this cell is an atomhead (i.e., the first cell in an atom). Bits 1, 2 & 3 - refer to a full cell list associated with an atom. Bits 1, 2 and 3 are used as follows: Bit 1 - Number Marker Bit 2 - Floating-point Marker Bit 3 - Logical Marker For an atomhead (bit 0 is set to one), one of the following bit patterns will be used to describe the full cell list associated with the atom: BIT 0 BIT 1 BIT 2 BIT 3 ----- ----- ----- ---- 1 0 0 0 EBCDIC Characters 1 1 0 0 Fixed-point number 1 1 1 0 Floating-point Number 1 1 0 1 Logical Number Bit 7 - indicates that a function is to be traced. Bit 32 - is used by the garbage collector to mark active cells. Bit 33 - indicates that this is a full cell. Bit 34 - is used in a full cell to indicate that the first word (first 32 bits) contains EBCDIC characters or a number. Bit 34 is not set in a full cell when the first word contains an address. LISP at UIC 06/30/77 Page 7 =================================================================================+ | ------------------------ | . . . . /. | . 1 . . . / . | . . . . / . | . 0 . . . / . | . . . . . / . | --------.--------------- | . | . | . | ./ | bits 32-34 bits 32-34 | ----------------------- ----------------------- | . . . . . . . /. | . . . --------> . . / . | . E X A M . 011 . . . P L E . 011 . / . | . . . . . . . / . | . . . . . . . / . | ----------------------- ----------------------- | | | Figure 1: LISP atom with an empty property list | | =================================================================================+ 2.1.1 Atoms An atom begins with a LISP cell (called an atomhead) that contains in its first address position a pointer to a full cell list associated with that atom. The full cell list contains either the printname of the atom (in the case of a lit- eral atom) or the binary value of the atom (in the case of a number). The second address position contains a pointer to the list of properties asso- ciated with that atom -- if it exists (numbers never have properties). The first bit of the first word (bit 0) is set to one to indicate that this cell represents the start of an atom. Figure 1 illustrates the atom EXAMPLE and its full cell list. The property list is empty. Figure 2 illustrates the atom FF and its property list. The property list includes all the attributes associated with that atom. In this example, the atom FF is a function, namely an EXPR, which starts (LAMBDA . . .) Attributes of the atom are designated by flags or indicators on the property list. Flags are atoms which by themselves indicate that the atom (on whose property list the flag occurs) has some attribute (e.g., COMMON). Indicators are atoms which identify the atom (on whose property list the indicator occurs) as having a special value which is found as the next item on the property list (e.g., SPECIAL, APVAL). Indicators used by the LISP system include: LISP at UIC 06/30/77 Page 8 =================================================================================+ | | | --------------- -------------- ----------------- | . . . . . . . . . . . . . . /. | . 1 . . . . . . . . . . . . . / . | . . . . -----> . . . ------> . . . / . | . . . . . . . . . . . . . . . . . / . | ------.-------- ----.--------- -----.----------- | . . . | . . . | . bits / . | / 32-34 atom EXPR / | | --------------------- ------------------- | . . . /. . . . . | . F F . 011 . / . . . . ------> | . . . / . . . . . . | . . ./ . . . . . . | --------------------- --------.---------- | . | . | ./ | LAMBDA | | | | Figure 2: LISP Atom with Associated Property List | | =================================================================================+ APVAL -- The atom is a constant whose value is given by the following item in the property list. EXPR -- The atom is a function name. The lambda expression defining the function is the following item in the property list. FEXPR -- The atom is a special function name. The lambda expression defin- ing the function is the following item in the property list. An FEXPR differs from EXPR in that the FEXPR is defined with pre- cisely two arguments and may be called with an indefinite number of arguments. When an FEXPR is called, the list of arguments and the current association list are bound to the lambda variables defined in the FEXPR expression, so that the arguments are not evaluated before the function is called. SUBR -- The atom is a compiled EXPR or a built-in function. The entry address of the subroutine is the following item in the property list. FSUBR -- The atom is a compiled FEXPR. The entry address of the subroutine LISP at UIC 06/30/77 Page 9 is the following item in the property list. DCBADDR -- The atom is a ddname. The address of the DCB follows the indi- cator on the property list. Atoms are created in LISP in several ways. READ, GENSYM1, and MKATOM all cre- ate literal atoms. READ creates atoms from the input text and places them on the object list. GENSYM1 creates an atom but does not place it on the object list. MKATOM creates an atom on the object list using the buffer filled by the function RLIT. Numeric atoms are created by every numeric function. Thus, the same number may be different atoms. These numeric atoms are not placed on the object list. 2.1.2 Numbers There are three kinds of numbers: 1. Fixed-point (integers) 2. Floating-point 3. Logical (hexadecimal) All numbers are stored as 32 bit binary numbers with the help of a full cell and must be converted from EBCDIC characters on input and to EBCDIC characters on output. (The EBCDIC representation of a number is not stored.) The first word of a numeric atomhead points to this full cell; the second word is NIL. A fixed-point number is a signed or unsigned integer (written without a decimal point) in the range -2**31 < number < 2**31-1. For example: 0 91 -91 173 -2147483647 A floating-point number is a signed or unsigned string of decimal digits with a decimal point. The string of decimal digits may be followed by a decimal expo- nent. Floating-point numbers may have absolute values in the range 10**75 < number < 10**75, including zero. For example: 7. -3.4 2.5E+07 -3.2E-4 2.6E7 LISP at UIC 06/30/77 Page 10 A logical number consists of from 1 to 8 hexadecimal digits (0, 1, 2,. . ., 9, A, B, C, D, E, F) which may be followed by the letter 'X'. If the number begins with one of the letters A through F, it must be preceded by a zero to avoid ambiguity with character atoms. Logical numbers need not be followed by 'X' if they contain any of the digits A through F. All numeric functions treat logical numbers as integers. For example: 14X -3ABX 0AX 0FFFFFFFCX 14AF5 2.1.3 Object List Pointers to LISP atoms are chained together on a list called the 'object list'. The system searches this list in order to find atoms referenced by the LISP program. As literal atoms are added to the system, their pointers are added to the front of the object list, immediately following the pointer to the atom NIL except for literal atoms created by GENSYM1, which are not added to the object list. The predefined atom OBLIST has an APVAL on its property list which points to the object list. To print the object list, the following statement can be used with the EVALQUOTE Supervisor: EVAL(OBLIST NIL) 2.2 Push-down Stack (PDS) The PDS is used to save active data structures and addresses during program recursion. The size of the PDS is fixed at 4K words (32 bits/word), and it can only be changed by regenerating the LISP system. 2.3 System Functions The system function area contains the control program, the EVALQUOTE inter- preter, predefined system functions, the garbage collector, and the error han- dler. 2.4 Binary Program Space (BPS) This area contains all compiled code not part of the standard LISP system, such as EDIT and DISPLAY. 2.5 Input/Output Buffers This is an area of 4K bytes (8 bits/byte) returned to OS for use as input/out- put storage. LISP at UIC 06/30/77 Page 11 3. FUNCTIONS, PREDEFINED ATOMS, AND CHARACTER-OBJECTS 3.1 LISP Functions This section gives the definitions of the functions available in LISP. The symbols used for function arguments are defined as follows: alst - association list at - atom ch - character-object ddname - ddname e - valid LISP form fn - function ind - indicator list - list n - number p - predicate x - S-expression ADD1(n) ADD1 takes a number as its argument and returns that number plus 1. If n is a fixed-point number, the result is a fixed point number. If n is a floating-point number, the result is floating-point. ALLSTACK(p) ALLSTACK controls the printing of the stack during an error traceback. ALLSTACK(NIL) causes only valid S-expressions to be printed. ALLSTACK(T) causes all valid S-expressions to be printed, and pointers to other data to be printed as hexadecimal numbers. ALLSTACK(NIL) is the default. AND(p1,p2,. . .,pn) AND evaluates its arguments from left to right until one is NIL or the end of the list is reached. It returns NIL or T, respectively. APPEND(list1,list2) APPEND takes two lists as its arguments. Its value is a list of the ele- ments of list1 followed by the elements of list2. APPEND((A B C) (D E F)) = (A B C D E F) APPEND1(list,x) APPEND1 causes the element x to be added onto the end of 'list': the value is the modified list. APPEND1(A B C) D) = (A B C D) APPLY(fn,list,alst) APPLY causes the function, fn, to be applied to the arguments in the list; alst is used as the association list. LISP at UIC 06/30/77 Page 12 ASA(p) (see Section 7.1.3) ATOM(x) ATOM returns T if x is an atom (either numeric or literal): otherwise it returns NIL. ATTRIB(list1,list2) ATTRIB modifies list1 by tacking on list2 at the end. The value is list2. ATTRIB has the same effect an NCONC although the value is different. Note that if list1 is an atom, list2 is added to the end of the property list of list1. BPSZ( ) BPSZ takes no arguments. BPSZ deletes all binary program space and adds that storage to Free Cell Storage. Jobs not using EDIT can call BPSZ for maximum storage. BREAK(e alst) (See Section 6.2.1) BREAKP(ch) BREAKP is a predicate. If its argument is one of these character-objects: blank left parenthesis ( right parenthesis ) comma , period . its value is T; otherwise its value is NIL. CAAAR(x) CAADR(x) CAAR (x) CADAR(x) CADDR(x) CADR(x) CAR(x) CDAAR(x) CDADR(x) CDAR(x) CDDAR(x) CDDDR(x) CDDR(x) CDR(x) These functions represent all possible nestings of CAR and CDR up to three levels. CHEX(x) CHEX returns the contents of the LISP cell x as a list of two hexadecimal numbers. If the argument is a logical number, its value is interpreted as the address of the cell to be listed. Otherwise the cell pointed to by x is listed. LISP at UIC 06/30/77 Page 13 CHKPOINT(ddname) (see Section 7.2.1) CLOSE(ddname) (see Section 7.1.2) CONS(x1,x2) CONS obtains a new doubleword from the free storage list (see Section 2.1) and places its two arguments in the first and second words, respectively. It does not check to see if the arguments are valid list structures. The value of CONS is a pointer to the word that was just created. If the free storage list has been exhausted, CONS calls the garbage collector to make a new free storage list and then performs the CONS operation. COUNT(n) The argument n must be an integer. COUNT turns on a counter which auto- matically causes a trap when CONS has been done more than 'n' times. Any CONS performed by system functions are also counted. The counter is turned off by UNCOUNT(NIL). The counter is turned on and reset each time COUNT is executed. The counter can be turned on so as to continue count- ing from the state it was in when last turned off by executing COUNT(NIL). The function SPEAK( ) gives the current value of the counter, which is decremented each time a CONS occurs. CSET(at,x) CSET is used to create a constant by putting the indicator APVAL and a value on the property list of the atom. The value stored in the property list of the atom is CONS(x,NIL). The value of CSET is its second argu- ment. If 'at' already had an APVAL, the old value is removed. CSETQ(at,x) CSETQ is like CSET except that the first argument is quoted instead of being evaluated. DEFINE(list) The argument 'list' of pairs DEFINE is a list of ((u1 v1) (u2 v2) ... (un vn)) where each u is a name and each v is a lambda-expression for a function. For each pair, DEFINE puts an EXPR on the property list for u pointing to v. DEFINE puts things on at the front of the property list. The value of DEFINE is a list of the u's. DEFLIST(list,at) DEFLIST is a more general defining function than DEFINE. Its first argu- ment is a list of pairs as for DEFINE. Its second argument is the indica- tor that is to be used. The second argument should be a literal atom. After DEFLIST has been executed with (u v) as its first arguments, the property list of u will begin with the indicator, at, followed by v. DEFINE(((FN (LAMBDA(X) (CAR X))))) = DEFLIST(((FN (LAMBDA(X) (CAR X)))) EXPR) LISP at UIC 06/30/77 Page 14 DIFFERENCE(n1,n2) Both arguments of DIFFERENCE must be numbers. The value is n1 minus n2. If either argument is a floating-point number, the resut is floating- point. DIGP(ch) DIGP is a predicate. If its argument is one of these character-objects: 0, 1, 2, . ., 9 its value is T; otherwise its value is NIL. DISPLAY(x) (see Section 5.1.3) EDIT(at) (see Section 5.1.1) EJECT( ) EJECT takes no arguments. It causes a line to be written with a 'new- page' control character in the first byte (skip to new page) . EQ(x1,x2) EQ is a predicate which tests if its two arguments point to the same loca- tion in storage. Literal atoms are stored uniquely, so that if x1 is an atom, EQ(x1,x2) will be true if x2 is the same atom. List structures and numbers are not stored uniquely, however, and thus it is possible for two equivalent list structures not to be EQ. EQ returns T if its arguments are the same, otherwise it returns NIL. EQUAL(x1,x2) EQUAL is a predicate. It returns T if its two arguments are equivalent list structures. EQUAL is recursive, using EQ to test literal atoms. Two numbers are assumed to be EQUAL if they differ by less than 10**-6. ERROR(x) ERROR is one way for a user to cause a LISP error. The message '***A1 - CALL TO ERROR' and the value of x will be printed, followed by a trace- back as described in Section 10.5. ERROR does not return and so it has no value. EVAL(e,alst) The first argument e must be a valid LISP expression. It is evaluated using alst as an association list for values of variables. EVALSUP(p) EVALSUP controls the choice of Supervisor under which LISP runs. EVALSUP(T) switches from the EVALQUOTE Supervisor to the EVAL Supervisor. (EVALSUP NIL) switches from the EVAL Supervisor to the EVALQUOTE Supervi- sor. EVCON(list,alst) The argument is a list of the form ((p1 e1)(p2 e2)(p3 e3). .(pn en)) where the p's and e's are valid LISP expressions. The p's are evaluated LISP at UIC 06/30/77 Page 15 in order until a non-NIL vaue is obtained. Then the corresponding e is evaluated and its value is returned as the value of EVCON. For each of these evaluations, alst is used as the association list. EVENP(n) EVENP returns T if the fixed-point number 'n' is even; otherwise it returns NIL. EVLIS(list,alst) The first argument is a list of valid LISP expressions. They are evalu- ated in order using alst as the association list. The list of the values is returned. EXITERR(p) EXITERR(T) causes the run to terminate after the occurrence of any error that is generated in the execution of the program. EXITERR(NIL), the default, turns off this feature. EXPLODE(at) EXPLODE takes an atom as an argument and has as its value a list of the characters in the printname of the atom. EXPT(n1,n2) EXPT takes two numbers as its arguments. The second argument must be a fixed number. It returns n1 to the n2th power. The value is floating- point if n1 is floating-point or if n2 is negative. FIX(n) FIX takes a floating-point number as its argument. The argument is trun- cated to an integer. FIXP(x) FIXP returns T if x is a fixed-point number, otherwise it returns NIL. FLAG(list,at) FLAG puts the flag 'at' on the property list of every atomic symbol in the list. Note that 'list' must be a list of atoms. No atom ever receives a duplicate flag. The value of FLAG is NIL. FLAGP(at1,at2) FLAGP searches the property list of the atom at1 (CDR at1) for an occur- rence of an item EQ to at2. If such an item is found, the value of FLAGP is the rest of the list beginning with that item. Otherwise, the value is NIL. FLOAT(n) FLOAT takes a fixed-point number as its argument. It returns that number converted to floating-point. FLOATP(x) FLOATP returns T if its argument is a floating-point number; otherwise it returns NIL. LISP at UIC 06/30/77 Page 16 FUNCTION(fn) FUNCTION is a special form. Its 'argument' must be the name of a function or a lambda expression. FUNCTION is used to pass functional arguments to other functions. When the form (FUNCTION (LAMBDA(X) . . .)) is evaluated in interpreted LISP, FUNCTION returns the special form (FUNARG (LAMBDA(X)...)) alst) where alst is the current association list. Then the FUNARG form is interpreted by APPLY as a function, with the association list taken from alst instead of taking the association list at the time APPLY is called. Thus, FUNCTION, in effect, saves the current association list along with 'fn', so that later calls will use current variable bindings. GCD(n1,n2) GCD Computes the greatest common divisor of the two integer arguments n1, n2. If either argument is a floating-point number, 0.0 is returned. GENSYM1(at) GENSYM1 creates a new atom whose printname consists of the first four characters of the atom which is passed as its argument, followed by four digits. The atoms that GENSYM1 creates are NOT on the object list, unlike other atoms in the system. Thus, GENSYM1(ALPHA) = ALPH0502 Even if there already exists an atom whose name is ALPH0502, the result of GENSYM1 will be unique. GET(at1,at2) GET searches the property list (CDR) of its first argument for an indica- tor EQ to its second argument. GET then returns the item following the indicator in the property list. If no element of CDR (at1) is EQ to at2, GET returns NIL. GO(at) GO is a special form. Its one argument must be a label in the PROG in which GO appears. Its argument is not evaluated. GO causes PROG to branch to the label specified. In compiled LISP, GO cannot appear except as a statement in a PROG, or in the top level of a COND which is a state- ment in a PROG. Specifically, GO cannot appear within a PROG2 within a COND. GREATERP(n1,n2) GREATERP is a predicate which takes two numbers as its arguments. The value is T if the first argument is numerically greater than the second, and NIL if they are equal or the first is less than the second. LISP at UIC 06/30/77 Page 17 INIT( ) (see Section 6.1.2) INLL(n) (see Section 7.1.6) LAST(list) The argument is a list. LAST returns the tail end of list which contains only the last element: LAST((A B C D)) = (D) (This is the list of the last element, not just the last element.) LEFTSHIFT(n1,n2) LEFTSHIFT takes two numbers as its arguments. The second argument must be a fixed-point number. The word (32 bits) which contains the number given by the first argument is shifted left the number of places specified by the second argument. If the second argument is negative, the first argu- ment is shifted right. The value is a logical number. LENGTH(list) LENGTH returns the number of top-level elements contained in the list given as its argument. LENGTH( ((A B C) D (E F)) ) = 3 LESSP(n1,n2) LESSP is a predicate which takes two numbers as its arguments. The value is T if the first argument is numerically less than the second; otherwise it is NIL. LETP(ch) LETP is a predicate. If its argument is one of the letters in the range A, B, . . ., Z, its value is T; otherwise its value is NIL. LIST(x1,x2,. . .,xn) LIST takes an indefinite number of arguments, and returns a list of those values. LITP(ch) = NOT(OR(BREAKP(ch),DIGP(ch))). LOGAND(n1,n2,. . .,nk) LOGAND takes an indefinite number of arguments. LOGAND performs a bit-by- bit logical AND on its arguments and returns the logical number thus pro- duced. LOGOR(n1,n2,...,nk) LOGOR is similar to LOGAND, except that it computes the bit-by-bit log- ical OR of its arguments. LISP at UIC 06/30/77 Page 18 LOGP(x) It returns T if its argument is a logical number, and NIL otherwise. LOGXOR(n1,n2,. . .,nk) LOGXOR is similar to LOGAND and LOGOR, except that it computes the logical exclusive OR of its arguments. MAPCAR(list,fn) MAPCAR takes two arguments: the first is a list and the second is a func- tion of one argument. MAPCAR applies the given function first to the CAR of list, then to the CADR of list, and successively to each element of list until the end of the list is reached. MAPCAR returns a list whose kth element is the value of the function applied to the kth element of the list given as an argument. MAPLIST(list,fn) MAPLIST takes two arguments: the first is a list and the second is a functional argument. MAPLIST applies the given function first to list, then to CDR list, and successively to each 'tail end' of list, until the end of the list is reached. MAPLIST returns the list of the values of those function evaluations. MAX(n1,n2,. . .,nk) MAX takes an indefinite number of arguments. If any of the arguments are floating-point numbers, the result will be floating-point. MEMBER(x,list) MEMBER searches the list for an occurrence of an element EQUAL to x. If such an element is found, MEMBER returns T; otherwise it returns NIL. MIN(n1,n2,. . .,nk) MIN takes an indefinite number of arguments, and returns the smallest of them. If any of the arguments are floating point numbers, the result will be a floating-point number. MINUS(n) MINUS takes a number for its argument, and returns the negative of that number. MINUSP(n) MINUSP takes a number for its argument; it returns T if that number is less than zero and NIL otherwise. MKATOM( ) MKATOM is a function with no arguments. It is used to make atoms out of the information put into the internal character buffer by RLIT or RNUMB. MKATOM returns the atom created. LISP at UIC 06/30/77 Page 19 NCONC(list,x) The first argument must be a list. NCONC changes the end of 'list' to point to x. In effect, NCONC is like APPEND except that it actually changes its first argument instead of copying it. NCONC returns the modi- fied first argument. NOT(x) NOT returns T if its argument is NIL. and NIL otherwise. It is the same as EQ(x,NIL). NULL(x) NULL is the same as NOT(x). NUMBERP(x) NUMBERP is a predicate which returns T if its argument is a number (log- ical, fixed-point or floating-point); otherwise it returns NIL. OPEN(ddname,list,at) (see Section 7.1.1) OR(p1,p2,. . .,pn) OR takes an indefinite number of arguments. The arguments are evaluated from left to right until one is reached whose value is not NIL, or the end of the list is reached. OR returns T or NIL respectively. ORDERP(at1,at2) ORDERP imposes an arbitrary canonical order on literal atoms. For charac- ter-objects that order is alphabetic; for all other atoms, the order depends on the actual location in storage of the atomhead. ORDERP returns T if the two arguments are EQ or the first comes before the second in this canonical order, and NIL if the first argument comes after the second. OTLL(n) (see Section 7.1.4) OUTOFF(p) OUTOFF controls the printing of the output line giving the value of the function or form evaluated by the supervisor. OUTOFF(T) causes no output lines to be printed. OUTOFF(NIL) causes the output lines to be printed. PAIR(list1,list2) PAIR is a function used internally by the LISP system to build association lists. PAIR takes two lists as its arguments. The lists must be of equal length; otherwise an error will occur. PAIR matches the elements of the first argument with the elements of the second argument and returns a list of dotted pairs; the CARs of the pairs are the elements of the first list and the CDRs of the pairs are the elements of the second list. The list of dotted pairs is in the reverse order of the input lists. PAIR((A B C) (D E F)) = ((C . F) (B . E) (A . D)) PAIR ((A B) (C D E)) ----> *** F2 - TOO MANY ARGUMENTS - EXPR LISP at UIC 06/30/77 Page 20 PLANT(x1,x2) PLANTDC(x1,x2) These functions are used by the PLANTSQ(x1,x2) compiler to insert code into BPS PLANT1(x1,x2) Binary Program Space). PLUS(n1,n1,. . .,nk) PLUS takes an indefinite number of arguments. PLUS computes the algebraic sum of its arguments and returns that number If any of the arguments are floating-point numbers, the result will be floating-point. PLUS( ) = 0 PRBUFFER(p) PRBUFFER takes T or NIL as an argument. PRBUFFER(T) will cause READ and READCH to print the input buffer every time a new record is moved into it. A '=>' in the margin of a line indicates that the line is a buffer print- out. PRBUFFER(NIL) will stop the printing of the input buffer. PRBUFFER is used when it is necessary to show exactly what was given as input to LISP. PRINT(x) PRINT takes an arbitrary S-expression for its argument. PRINT causes that S-expression to be written on the output device currently write selected (default LISPOUT). PRIN1(at) The argument of PRIN1 must be an atom (numeric or literal). PRIN1 trans- lates its argument into output format and places it in the output buffer. PRIN1 does not terminate the line, however, and sucessive calls to PRIN1 will place the values immediately following each other in the output line. PROG(list,e1,e2,..,en) PROG is a special form. It provides the capability to perform iteration by allowing looping and the use of temporary variables. The list contains the variables of the PROG required by the statements e1,e2,. . .,en. PROG variables are initially NIL; they can be reset with the functions SET or SETQ . The "statements" e1,e2,. . .,en must be either expressions or lit- eral atoms. The literal atoms are used as statement labels. PROG evalu- ates the statements e1 through en in sequence, unless it comes to the spe- cial forms GO or RETURN. When a GO is evaluated, PROG continues evaluation at the statement immediately following the label given in the GO. When a RETURN is evaluated, the expression given in RETURN is returned by PROG. If no RETURN is reached before the last statement, PROG returns NIL. PROG2(x1,x2) PROG2 takes two arguments and returns the second as its value. QUOTIENT(n1,n2) Both arguments of QUOTIENT must be numbers. N1 is divided by n2 and the quotient is returned. IF both n1 and n2 are fixed-point numbers, the value is truncated to an integer; otherwise the result is a floating-point number. LISP at UIC 06/30/77 Page 21 RDS(ddname) (see Section 7.1.7) READ( ) The execution of READ causes one S-expression to be read from the current input file (as defined by RDS). The value of READ is the S-expression. READCH(p) If the argument is NIL, READCH will read the next character from the input buffer and return with the corresponding character-object as a value. READCH(T) causes a simulated backspace. The value of READCH(NIL) after a READCH(T) has been executed will be the same as that returned by the pre- vious READCH(NIL). READCH(T) should only be executed once before calling READCH(NIL). RECIP(n) For floating-point numbers, the value is the reciprocal of n. For fixed- point numbers the value is 0. RECLAIM( ) RECLAIM causes a garbage collection to occur. The value is NIL. REMAINDER(n1,n2) The value of the function is the remainder given when dividing n1 by n2. REMFLAG(list,at) This function removes all occurrences of the flag 'at' (a literal atom used as a flag on atomic property lists) from the property list of each atomic symbol in the list. When the flag is found, the pointer in the preceding element of the property list is modified to delete the flag from the list. The value of REMFLAG is NIL. REMOB(at) This function removes the atom 'at' from the OBLIST. It causes the symbol and all its properties to be lost unless the symbol is referred to by an active list structure. When an atomic symbol has been removed, subsequent reading of its name from input will create a different atomic symbol. REMPROP(at,ind) REMPROP searches the property list of 'at' looking for all occurrences of the atomic symbol 'ind'. If the atomic symbol is found, it is removed from the list along with the succeeding element. Removal is accomplished as described in REMFLAG. The value of REMPROP is NIL. RESTORE(ddname) (see Section 7.2.2) LISP at UIC 06/30/77 Page 22 RESUME( ) (see Section 6.1.1) RETURN(x) This function is used in the PROG feature. RETURN is the normal end of a program. The argument of RETURN is evaluated and this is the value of the program. No further statements are executed. REVERSE(list) REVERSE causes the top level of list to be reversed. Thus, REVERSE( (A (B . C)) ) = ((B . C) A) RLIT(ch) RLIT takes a character-object as an argument and puts the corresponding character into an internal character buffer. RNUMB(ch) RNUMB takes one of these character-objects as an argument; +, -, E, 0, 1, 2, . . .,9. RNUMB will construct a partially translated number in the internal character buffer. Remember that the character-objects, 0, 1, 2, . . ., 9 are different from the numbers 0, 1, 2, . . .9. The sequence of character-objects presented to RNUMB, one at a time, must represent a meaningful integer or floating-point number. MKATOM can then be called to make a numeric atom out of the information in the character buffer. RPLACA(x1,x2) RPLACA replaces the CAR of the LISP cell x1 with x2. This provides a method of changing list structures without using CONS, and thus creating no new LISP cells. The value is the new x which can be described as CONS(x2 (CDR(x1)). RPLACD(x1,x2) RPLACD replaces the CDR of the LISP cell x1 with x2, as described in RPLACA. The value is the new x which can be described by CONS((CARx1) x2). SASSOC(x,alst,fn) SASSOC searchs alst, which is a list of dotted pairs, for the pair whose first element is equal to x. If such a pair is found, the value of the function is this pair. Otherwise the value is the function of no argu- ments, fn. SET(x1,x2) The value of x1 is bound to the value of x2 on the current association list. The value is the value of x2. LISP at UIC 06/30/77 Page 23 SETQ(x1,x2) SETQ is like SET except that the first argument is quoted (not evaluated). SPEAK( ) SPEAK gives the number of CONS function calls since the CONS counter was last reset. STOP( ) STOP exits LISP and returns to the monitor. SUBLIS(alst,x) Alst is a list of dotted pairs, ((u1.v1) (u2.v2). . .(un.vn)). The value of SUBLIS is the result of substituting each v1 for the corresponding u1 in x. SUB1(n) The value of SUB1 is n-1. TERPRI( ) This function terminates the print line. TIMELINE(p) TIMELINE controls the printing of the execution time for the evaluation of the form or function which is given to the supervisor. TIMELINE(NIL) causes the time not to be printed. TIMELINE(T) causes the time to be printed. TIMES(n1,. . .,nn) the value of TIMES is the product of the arguments. TRACE(list) The argument of TRACE is a list of functions. After TRACE has been exe- cuted, the arguments and values of these functions are printed each time the function is entered. The value of TRACE is NIL. TTAB(n) TTAB moves the curent output cursor to the nth positon in the output buffer. Whatever is PRINTed next will appear starting at the given col- umn. UNCOUNT( ) UNCOUNT turns off the CONS counter. LISP at UIC 06/30/77 Page 24 UNTRACE(list) This function removes TRACEing from all functions in the list. The value of UNTRACE is NIL. VERBOS(p) VERBOS controls the printing of garbage collection messages. VERBOS(NIL) turns off the messages and VERBOS(T) turns the messages on. The value of VERBOS is NIL. WHEX(x) WHEX returns the address of the LISP cell pointed to by x as a hexadecimal number. WRS(ddname) (see Section 7.1.5) XTAB(n) XTAB moves the current output cursor 'n' characters to the right. The argument must be a positive integer. Whatever is PRINTed next will appear starting 'n' columns to the right of the end of whatever was last printed (using PRIN1). ZEROP(n) ZEROP takes a number for its argument. It returns T if the absolute value of its argument is less than 10**-6, and NIL otherwise. LISP at UIC 06/30/77 Page 25 3.2 Atoms With Initial Values Several atoms have predefined values (APVALS) in LISP. These atoms and their corresponding values are as follows: Atom Value ALIST association list BLANK blank BPS start and end of binary program space COMMA , DASH - DOLLAR $ EQSIGN = F NIL NIL NIL OBLIST object list PERIOD . PLUSS + QUERY ? RPAR ) SLASH / STAR * T T 3.3 Character-objects The following character-objects are defined in the system. blank ( ! X 4 A + $ Y 5 B | * Z 6 C & ) unprintable 7 D J ; , 8 E K ] % 9 F L - _ : G M / > # H N S ? I O T 0 ' [ P U 1 = . Q V 2 " < R W 3 The 'unprintable' character has no graphic symbol on the printer. Its punched card code is 12-11. READCH will translate any one of the 256 characters avail- able on the IBM System/370 into one of the above mentioned 64 character-ob- jects. Lower-case letters are translated into upper-case letters. Note that READ does not perform this translation. LISP at UIC 06/30/77 Page 26 4. SPECIAL DIFFERENCES IN THIS VERSION OF LISP In this version of LISP there exist special differences from the standard LISP of which the user should be aware. Several differences pertain to numbers: 1. Fixed-point numbers may have absolute values up to 2**31 2. Floating-point numbers may have absolute values between 10**75 and 10**(-75), including 0. 3. Floating-point significance on input is 6 digits. 4. Numbers are considered equal if the absolute value of their difference is less than 10**(-6). 5. Signs are ignored in reading logical numbers. Some other differences refer to atoms, control cards, and several functions: 1. Alphanumeric atoms in LISP may have up to 80 characters. 2. CAR of an atom is not junk as in LISP 1.5, but the address of the full cell list of that atom. 3. No control cards of any type exist in LISP. 4. If a PRINT is executed after PRIN1, the list generated by PRINT follows the data output by PRIN1. 5. GO can only be given atomic labels. 6. READ ignores extra right parentheses. 5. LISP EDITING FUNCTIONS The LISP Editing Functions allow the user to edit and save functions, con- stants, etc. which have been defined while using the LISP interpreter. This eliminates the need for completely retyping functions, constants, etc. which have been defined to the interpreter. 5.1 Editing and Printing Functions 5.1.1 EDIT(name) The function EDIT gets the S-expression associated with the indicator EXPR, FEXPR, or APVAL on the property list of the atom name. If the atom INDEDIT has been CSET to an atomic value ind, then the property list of name is searched for the indicator ind before it is searched for the indicators EXPR, FEXPR, and APVAL. The function EDIT then converts the S-expression to a list of atoms, right and left parentheses, and dots, and positions a cursor to the left of the first item in this list. LISP at UIC 06/30/77 Page 27 Various commands allow for moving the cursor, deleting and inserting items at the cursor position, and for printing out all or part of the list. When edit- ing is finished, the list is converted back to an S-expression after an appro- priate number of right parentheses are added or deleted, and this S-expression is put on the property list of name with the correct indicator. The value of the function EDIT is (name). For convenience, an item will be understood to be an atom, number, right or left parenthesis, or a dot. We now give a list of the commands available in EDIT. For those commands which are preceded by an integer n, the integer may be omitted, in which case it is understood to be 1. (Thus R is equivalent to 1 R.) n L Move the cursor Left past n items. n R Move the cursor Right past n items. If in L or R n is so large that the cursor would be moved away from the list, it will be positioned so that it is at the appropriate end of the list. B Move the cursor Back to the beginning of the list and add or subtract the number of right parentheses at the end of the list necessary to give a balanced parenthesis count. n F w Move the cursor right, Finding occurrences of item w until the cursor is positioned immediately to the left of the nth occurrence of item w. If n items equal to w are not found, NO SUCH ITEM is typed out and a B is executed. If w is a left or right parenthesis or a dot, it should be typed in as $$'(',$$')', or $$'.' respectively. n D Delete the n items immediately to the right of the cursor. n I w1 w2. . .wn Insert the n items w1,. . .wn in order at the cursor position. After this command the cursor is positioned immediately to right of the last item inserted. When using this command, (must be typed as $$'(', ) must be typed as $$')', and . must be typed as $$'.'. ID d x y z. . . d Insert the items x, y, z,. . . between the Delimiters d. This delim- iter may be any atom. See command I for other details. n ILP Insert n Left Parentheses. n IRP Insert n Right Parentheses. IDT Insert one DoT. W Show Where the cursor is by printing the first cnt items to the right of the cursor. The cursor is not moved. The initial value of cnt is 5. n C Set Cnt to n. LISP at UIC 06/30/77 Page 28 INDX w Change to w the INDicator with which the edited S-eXpression will be returned to the property list. The S-expression associated with the original indicator will be left unchanged. NAMEX w Change to w the NAME of the atom to whose property list the edited S-expression will be returned. The property list of the original atom will be left unchanged. P Ignoring initial right parentheses, Print the first complete S-expres- sion to the right of the cursor using the function DISPLAY (See Sec- tion 5.1.3) E End editing. Add or subtract the necessary number of right parenthe- ses at the end of the list to give a balanced parenthesis count. Con- vert the resulting list to an S-expression and put it on the property list of name with the correct indicator. Return the value (name). A Abort editing. Do not change the property list of name. Return NIL. Note that several instructions may be typed on the same line. For example: 7 R 3 D 3 I X Y Z B 20 C W moves the cursor 7 times items to the right, deletes the next 3 items, inserts atoms X, Y, and Z, moves the cursor to the beginning of the list and types out the first 20 items in the list. 5.1.2 Error Messages with EDIT INVALID COMMAND: a command other than the ones listed above was given, perhaps as a result of typing too many items after an I command. Another command is requested. (Note that redundant numbers before a command are ignored, e.g., 8 4 3 I is interpreted as 3 I.) NO SUCH EXPR-FEXPR-APVAL: None of the indicators EXPR, FEXPR, or APVAL were found on the property list of name, nor did INDEDIT have an atomic value which was found as an indicator on the property list of name. NO SUCH ITEM: See F command. RPAR ERROR: While attempting to delete right parentheses to give a balanced parenthesis count, the function found that it did not have enough right paren- theses to delete. This error is fatal to EDIT. The user should Abort. SGET ERROR: Not enough right parentheses were available to form an S-expres- sion. If this error occurs during a P command, necessary right parentheses are added for printing. Otherwise fatal to EDIT. The user should Abort. LISP at UIC 06/30/77 Page 29 5.1.3 DISPLAY(exp) The pseudo-function DISPLAY prints out the S-expression exp in a fashion intended to make its structure clear: a list (fn arg1. . .argn), where fn is an atom, is printed (fn arg1 . . argn), a list (LAMBDA varlist body) is printed (LAMBDA varlist body), a list (PROG varlist exp1. . .label expk. . .expn) is printed (PROG varlist exp1 . . . label expk . . . expn) (Labels longer than six characters are truncated). Other expressions will be printed out with indentation expressing parenthesis depth. DISPLAY is normally used in conjunction with EDIT. To use it directly, for example with the EVAL Supervisor, type (DISPLAY exp), where exp is the expression whose value you wish printed out. 5.2 Simple Data Management Functions 5.2.1 OUTFILE(ddn atlist indlist) The function OUTFILE writes the properties associated with the indicators EXPR, FEXPR, APVAL, and the indicators on the list indlist, which are found on the property lists of the atoms on the list atlist, onto the data set to which the file name ddn is allocated. If atlist is an atom, it is assumed that its value is the list of atoms whose properties are to be written onto the data set. In this case, if the atom atlist is not a member of the list, it is added to the beginning of the list and atlist is CSET to the extended list. (This allows the list of atoms to be saved.) LISP at UIC 06/30/77 Page 30 5.2.2 INFILE(ddn) The function INFILE reads the definitions written by OUTFILE from the data set to which the file name ddn is allocated. 6. LISP ATTENTION INTERRUPT FUNCTIONS LISP recognizes two uses of the break key: 1. Termination of a traceback during an error message and return of control to the supervisor. 2. Interruption of a computation being done. This is done in a manner that permits the computation to be resumed at a later time. Successive interrup- tions of this form may be stacked up and resumed one at a time. 6.1 Interruption of Computations The interruption of a computation is done as follows: when the break key is depressed, a check is made to see whether an error printout is in progress. If one is, control is returned to the supervisor. Otherwise, the program prompts the user with LISP, and stops and waits for input. There are now three alter- natives: 1) if a null line (carriage return alone) is entered, the computation resumes, with possibly the loss of several lines of output to the terminal. 2) if the break key is depressed again, LISP returns to the Terminal Monitor Program, which prompts the user with READY. 3) if a non-null line is entered, the input and output streams are re-directed to the terminal if necessary, and a flag is set at the entry point of the func- tion EVAL and computation is resumed. When the function EVAL is next called, the form being evaluated and the association list are saved by the function BREAK on the PDS, together with other information which will be necessary for resuming the computation. A false bottom is put on the PDS, and control is given to the supervisor, which processes the line entered. This allows other computations to be done, functions to be redefined, etc. A call of the func- tion RESUME( ) causes LISP to remove the false bottom from the PDS, and to use the information placed on the PDS below it to resume computation at the call to EVAL which was flagged. Several false bottoms may be placed on the PDS, and removed one at a time by successive calls of RESUME( ). If it is not desired to resume the previous computation, a call of the function INIT( ) causes all saved computations to be removed from the PDS, and control to be given to the supervisor. LISP at UIC 06/30/77 Page 31 6.1.1 RESUME( ) This function causes computation to be resumed at the most recent point where it was suspended by the break key. A second call of RESUME( ) causes computa- tion to be resumed at the previous point of interruption, etc. 6.1.2 INIT( ) This function causes all entries on the stack to be discarded, and deletes all computations which were interrupted by the break key. 6.2 Programmer Attention Interrupt Handling The following facilities for programmer handling of attention interrupts are provided: When the flagged call of EVAL(e alst) is executed, first the atom ATTNFN is tested for the indicator FEXPR. If this indicator is not found, the function BREAK(e alst) is called. If the indicator is found (ATTNFN e) is evaluated with association list alst. Therefore the programmer can control the handling of the interrupt by appropriately defining ATTNFN as a FEXPR. For example, this function could examine the form e and association list alst, and then continue with the processing of the interuption by calling BREAK(e alst). Note that BREAK(e alst) followed by RESUME( ) is equivalent to EVAL(e alst). 6.2.1 BREAK(e alst) This function saves e, alst, the timer information, the PROG-indicator, and the address of the previous bottom of the stack on the PDS. It then sets the address of the bottom of the stack to the current stack pointer, prints BRK, and gives control to the supervisor. 7. DATA MANAGEMENT IN LISP 7.1 Data Management Functions LISP can read or write data sets on any OS/370 supported device with the aid of the function OPEN, CLOSE, WRS, and RDS. The handling of its buffers can be modified by the functions ASA, INLL, and OTLL. It is assumed in the following paragraphs that the reader has a working knowledge of the OS/370 Data Manage- ment. 7.1.1 OPEN(ddname,list,at) All data sets must be 'opened' by the function OPEN before they are used. A DD statement is used to define the data set and OPEN uses the ddname in the state- ment to refer to the data set. The ddname is the argument of OPEN. The record length (LRECL), blocksize (BLKSIZE) and whether or not the record's first char- acter is a control character (A) can be specified in the second argument of OPEN. The third argument of OPEN specifies whether the data set is to be used for input (INPUT) or output (OUTPUT). The following is an example of the opening of the data set defined by the DD statement named DATA: LISP at UIC 06/30/77 Page 32 OPEN(DATA ((LRECL.100) (BLKSIZE.1000) (A))OUTPUT) The second and third arguments of this OPEN indicate that the data set has record length of 100 bytes, a block size of 1000 bytes, that the first charac- ter in each record is a control character, and that the data set is to be used for output. The record length and the blocksize can be given in the DD state- ment instead of in OPEN. All other DCB parameters are fixed by OPEN and they cannot be changed by the LISP user. The record format is set to fixed blocked (FB), and the error option (EROPT) is 'accept' (ACC) on input and 'skip' (SKP) on output. The three ddnames LISPIN, LISPOUT, and LISPUNCH are given special significance in OPEN. LISPIN and LISPOUT are opened automatically by the interpreter and therefore need not be OPENed. The second and third arguments are implied by LISPUNCH, and are therefore ignored when OPEN is given LISPUNCH as its first argument. LISPUNCH implies a record length of 80 bytes, a blocksize of 80 bytes, that the first character in each record is data and not a control char- acter, and the data set is to be used for output. One of the atoms SYSIN, SYSOUT, SYSPUNCH and SYSFILE may be used as the second argument of OPEN. SYSIN implies a record length of 80 bytes, a blocksize of 80 bytes, and that the data set will be used for input. SYSOUT implies a record length of 133 bytes, a blocksize of 665 bytes that the first character in each record is a control character, and that the data set will be used for output. SYSPUNCH implies a record length of 80 bytes, a blocksize of 80 bytes, and that the data set will be used for output. SYSFILE implies a record length of 64 bytes and blocksize of 2496 bytes. SYSFILE should be specified for all data sets used by CHKPOINT or RESTORE. OPEN puts a DCBADDR indicator on the atom which is the filename, with a pointer to the DCB for that file. 7.1.2 CLOSE(ddname) All data sets should be 'closed' by the function CLOSE after use. CLOSE takes as its argument the ddname in the DD statement that defines the data set. The two ddnames LISPIN and LISPOUT refer to data sets that remain open throughout a LISP job. LISPIN and LISPOUT cannot be closed by CLOSE. They are, however, closed automatically at the end of a LISP job. 7.1.3 ASA(p) A control character is normally prefixed to all output records produced by LISP. Executing ASA(NIL) stops the prefixing of control characters. This is useful when LISP is used to produce output that will be input to LISP later on. Executing ASA(T) will cause LISP to start prefixing control characters again. LISP at UIC 06/30/77 Page 33 7.1.4 OTLL(n) For 'n' in the range 0 < n < 120, OTLL (out-line-length) specifies how many character positions LISP can use in each output record. After OTLL(n) has been evaluated, LISP will fill in exactly 'n' positions in each output record. Whenever necessary, atoms will be split across two output records so that pre- cisely 'n' POSITIONS ARE filled in each output record. This is useful when LISP is used to produce output that will be input to LISP later on. In a few cases, OTLL is called automatically by WRS. 7.1.5 WRS(ddname) WRS (write-select) is an output directing function that takes as its argument the ddname from the DD statement that defines the desired output data set. All output from LISP/360 will go to the data set associated with the ddname after WRS(ddname) has been executed. The two ddnames LISPOUT and LISPUNCH are given special significance in WRS. In addition to directing the output to LISPOUT, executing WRS(LISPOUT) will have an effect similar to executing ASA(T) and OTLL(100). Similarly, in addition to directing the output to LISPUNCH, execut- ing WRS(LISPUNCH) will have an effect similar to executing ASA(NIL) and OTLL(72). For all other files, the user must call OTLL explicitly - it does not occur automatically. WRS will open LISPUNCH if it is not already opened. A data set produced by PRINT when LISPUNCH was write selected (i.e., WRS(LISPUNCH)) is in SYSIN format. 7.1.6 INLL(n) INLL (in-line-length) specifies how many character positions LISP should scan in each input record. This is useful when LISP is required to read data sets that are not in SYSIN format. 7.1.7 RDS(ddname) RDS (read-select) is an input selecting function that takes as its argument the ddname from the DD statement that defines the desired input data set. All input to LISP will be taken from the data set associated with the ddname after RDS(ddname) has been executed. The ddname LISPIN is given special significance in RDS. In addition to selecting input from LISPIN, executing RDS(LISPIN) will have an effect similar to executing INLL(72). For all other files, the user must call INLL explicitly. 7.2 Checkpoint Facilities in LISP/360 Free Cell Storage (FCS) and binary program space (BPS) can be saved at any time by executing CHKPOINT. By executing RESTORE, free cell storage and binary pro- gram space can then be reset to the state they were in when saved. CHKPOINT and RESTORE should only use data sets that were opened by using the DCB parame- ter SYSFILE. 7.2.1 CHKPOINT(ddname) Execution of CHKPOINT(ddname) will cause free cell storage and binary program space to be written into the data set associated with the ddname. Only the data sets associated with LISPIN, LISPOUT, LISPUNCH and the ddname given as an LISP at UIC 06/30/77 Page 34 argument to CHKPOINT should be open when CHKPOINT is executed. 7.2.2 RESTORE(ddname) Execution of RESTORE(ddname) will cause free cell storage and binary program space to be overwritten by the contents of the data set associated with the ddname. RESTORE will check whether the data set is compatible with the LISP system that executes RESTORE. Only the data sets associated with LISPIN, LISPOUT, LISPUNCH and the ddname given as an argument to RESTORE should be open when RESTORE is executed. 8. THE GARBAGE COLLECTOR Garbage collection refers to the process by which currently unused LISP cells in FCS are returned to the free cell list. The process is initiated whenever the free cell list is empty. The first phase involves marking within the confines of the free cell storage area all LISP cells which are in use as part of some list structure. The group of pointers in the LISP system which reference all active data structures are referred to as base pointers. For each base pointer, the system starts with the LISP cell pointed to by the base pointer and marks all LISP cells reached by chaining through the CAR part or the CDR part (both recursively). All cells having an address within the free cell storage area are marked by turning on bit 0 of the CDR part of the cell. Fullword cells are detected and only their CDR parts are chained through. Cells on common sublists which have already been marked are chained through only once. The second phase consists of collecting all unused cells and placing them on the free word list. The free cell storage is now traversed linearly. Each cell which is marked has its mark bit turned off. Each cell which is unmarked is placed on the free cell storage list, and the number of cells thus collected is counted. 9. USING LISP IN BATCH It is sometimes desirable to execute LISP in batch. The following example shows the job setup: /*JOBPARM parameters //stepname EXEC PGM=BTCHLISP,PARM='B=0' //STEPLIB DD DSN=UCA6035.#LISP.LOAD,DISP=SHR //LISPOUT DD SYSOUT=A //LISPIN DD * | LISP STATEMENTS | Additional DD statements may be included for other datasets. The functions INFILE and OUTFILE are not available for use in batch. Therefore, any files other than LISPIN and LISPOUT must be opened with the function OPEN, read or written on with the functions RDS or WRS (or with RESTORE or CHKPOINT), and closed with the function CLOSE. LISP at UIC 06/30/77 Page 35 The parameters B and F specify the percentages of allocation of memory between free cell storage (FSC) and binary program space (BPS). //stepname EXEC PGM=BTCHLISP,PARM='F=66' will cause 66 percent of the memory available for the run to be allocated to free cell storage and 34 percent of the core to be allocated to BPS. The statement //stepname EXEC PGM=BTCHLISP,PARM='B=34' will cause the same allocations to be made. If the user specifies both parame- ters, the 'B' parameter will take precedence. The default values are F=66 (B=34). Since binary program space is used only by the Stanford LISP compiler, and by compiled functions, the programmer would normally specify PARM='B=0', to get maximum usable memory. If the user RESTORE's from any file (including the compiler), the values speci- fied in the PARM field are overridden by the values specified when that file was created. In this case, the F and B options of the PARM field are meaning- less. One additional PARM field entry may be made to indicate the amount of memory to be reserved by the system for opening and closing files. The statement //stepname EXEC PGM=BTCHLISP,PARM='R=8K,B=0' will cause 8*1024 bytes to be reserved for OS OPEN's and CLOSE's. This parame- ter may also be specified without the 'K'. For example, R=7000 will reserve 7000 bytes. The default value for 'R' is 8K. 10. LISP SYSTEM MESSAGES 10.1 Supervisor Messages The supervisor prints out the value resulting from evaluating the doublet or form typed in. This printout can be suppressed with the function OUTOFF. The printing of the timer is controlled by the function TIMELINE. The timer mes- sage is printed before the value. It has the format TIME xxxxxMS, VALUE: The time xxxxx given is the number of milliseconds spent evaluating the doublet or form typed in. The time does not include time spent in garbage collection. 10.2 Tracing LISP Tracing is controlled by the pseudo-function TRACE, whose argument is a list of functions to be traced. After TRACE has been executed, tracing will occur when- ever these functions are entered. However, because of the nature of the link- age between compiled functions, once a call by a compiled function to a com- piled function has been executed untraced, it can never be traced again. The trace-handler prints out the name of a function and a list of its arguments LISP at UIC 06/30/77 Page 36 when it is entered, and its name and value when it is finished unless that function is a FEXPR or a FSUBR. When tracing of certain functions is no longer desired, it can be terminated by the pseudo-function UNTRACE whose argument is a list of functions that are no longer to be traced. 10.3 Garbage Collection Message The message COLLECT xxxxx CELLS; STACK: yyyyWORDS. TIME: zzz MSEC. is printed after every garbage collection. The message gives an indication of the amount of free cell storage freed (xxxxx LISP cells), the size of the push- down stack left (yyyy words), and the amount of time used (zzz milliseconds) at each garbage collection. The printing of this message can be controlled by the function VERBOS. 10.4 Interrupt Message An interrupt supervisor takes care of all program interrupts in LISP. See the IBM manual System/370 Principles of Operation for information about System/370 interrupts. The program status word (PSW), the contents of registers 0-15 and the message '***ERROR: CAR TAKEN OF FULLCELL' are printed if the interrupt code is 1 to 7. A trace-back is then given of the same type as described in section 10.5.2. This type of interrupt is usually caused by indiscriminate use of CAR and CDR past the atomic level. The execution of the doublet or form that caused the interrupt is halted and a new doublet or form is read in for evaluation. Note that many functions (EQUAL, etc.) which chain through the CDR of lists do not check for the full cell mark. Thus, if these functions are applied to the CAR of an atom or a property list which contains an FSUBR or SUBR, this type of interrupt can occur. Additionally, this type of interrupt can occur during the trace-back of another error. An interrupt code of 8 to F means that an overflow or underflow occurred. This type of interrupt causes the message '***OVER- OR UNDERFLOW OF TYPExx' to be printed. Xx is the interrupt code. Execution of the function that caused the overvflow or underflow is resumed after the interrupt. 10.5 Error Diagnostics 10.5.1 Syntax Errors If the scanner finds syntactical errors in an S-expression it inserts special atoms at appropriate places in the S-expression. These special atoms are used as follows: Atom Meaning ERRB A '.' (dot) encountered as the first non-blank character after a '('. DOTERR1 The second S-expression in a dotted pair is not followed by a right parenthesis. LISP at UIC 06/30/77 Page 37 DOTERR2 A '.' or '(' encountered as the first non-blank character after a dot. The message '***R1-SYNTAX ERROR' precedes the printing of the S-expression with the error. A doublet or form containing one or more syntactical errors causes the following message to appear '***ERRORS ENCOUNTERED WHILE READING. CONTINUING WITH NEXT DOUBLET' and evaluation of the doublet or form is skipped. 10.5.2 Execution Errors When an error occurs during execution, the following error diagnostic is printed: ***error code-error message S-expression 1 S-expression 2 ***TRACE-BACK FOLLOWS S-expression 3 . . S-expressions 1 and 2 are related to the type of error encountered and are described below with the error messages. The trace-back includes the lists and pointers to list structures on the stack at the time the error occurred. The printing of the pointers to list structures is controlled with the function ALLSTACK. The most recently used list in the stack (the list on top) is printed first. Therefore, the first few lists will usually give a good indica- tion of what caused the error. As an example, assume that none of the functions being interpreted are using the PROG-feature and that TRACE has not been executed. Under these conditions, the list bound on the stack will be alternately function calls and association lists. When reading the stack, the user should keep in mind that the innermost functions are evaluated first, even though the functions are interpreted from the outside in. Therefore, the call on the function being evaluated when the error occurred will be near the top of the stack, if the call to that function is being interpreted. If TRACE is executed within a LISP job, the name of an EXPR that was called will be found on the stack between the defintion of the EXPR and the corre- sponding association list. If a function using the PROG feature was called, it will cause the following lists to appear in the stack printout: The association list. The GO-list. A list of the uninterpreted statements in the function starting with the one to be evaluated when the error occurred. LISP at UIC 06/30/77 Page 38 The complete argument of PROG (omitting the name of the function). The following is an example of the error that might occur when using the PROG definition shown. After the function has been defined and called, the error messages given below would be printed. Note that the four items after the trace-back message are the ones described above. DEFINE(((TEST2)LAMBDA(X) (PROG(Y) (SETQ Y (CAR X)) (SETQ Y (CAR X)) (SETQ Y (CONS X Y) ) (SETQ Y (CAR Y)) (SETQ Z (CAR Y)) )))))) TEST2((ABC)) After execution has started, the following will appear: ***A5-SET VARIABLE UNDEF (see Section 10.5.3) * Z * ((Y A B C) (X A B C)) ***TRACE-BACK FOLLOWS * NIL * ((SETQ Z (CAR Y))) * ((Y) (SETQ Y (CAR X)) (CONS X Y)) (SETQY (CAR Y)) (SETQ Z (CAR Y))) 10.5.3 Error Codes and Messages A1-CALL TO ERROR This message is given if a LISP program calls error. The argument (if any) of ERROR is printed (S-expression 1). The trace-back is not given with this message. A2-FUNCTION NOT DEFINED This message occurs when an atom given as the first argument of APPLY does not have a function definition either on its property list or on the associ- ation list. S-expression 1 is the atom in question. S-expression 2 is the association list. A3-NO ARGS OF COND TRUE None of the propositions following COND are true. S-expression 1 is the list of the arguments given COND. S-expression 2 is the association list. A5-SET VARIABLE UNDEF The function SET or SETQ was given an undefined program variable. S-expression 1 is the program variable. S-expression 2 is the association list. LISP at UIC 06/30/77 Page 39 A6-UNDEF LABEL IN GO The label given as the argument of GO has not been defined. S-expression 1 is the label. S-expression 2 is the list of the labeled statements. A7-MORE THAN 22 ARGS More than 22 arguments were given to an EXPR or a SUBR. S-expression 1 is the list of arguments to the function. A8-UNDEFINED VARIABLE A variable is not bound on the association list, nor does it have an APVAL. This error occurs in EVAL. S-expression 1 is the variable in question. S-expression 2 is the association list. A9-FUNCTION NOT DEFINED The form given as the first argument to EVAL has as its first element an atom with no function definition either on its property list or on the asso- ciation list. S-expression 1 is the atom in question. S-expression 2 is the association list. D2-FILE CANNOT BE OPENED - NO STORAGE AVLBL OPEN was asked to open a data set (file) when there was no storage available in which to put the DCB for that data set. CLOSE releases the space taken up by the DCB of the data set that it is closing. S-expression 1 is the ddname given as the first argument to OPEN. D3-RDS FILE NOT OPENED D4-WRS FILE NOT OPENED A data set (file) must be opened by OPEN before LISP/370 can write or read from it. S-expression 1 is the ddname given as the argument to RDS or WRS. D5-CHKPOINT FILE NOT OPENED D6-RESTORE FILE NOT OPENED A data set (file) must be opened by OPEN before CHKPOINT or RESTORE can use it. S-expression 1 is the ddname given as the argument to CHKPOINT or RESTORE. D7-RESTORE GIVEN FILE INCOMPATIBLE WITH SYSTEM SPECIFIED D8-CHECKPOINT BLEW IT LISP at UIC 06/30/77 Page 40 D9-RESTORE BLEW IT The indicated function failed for some unknown reason. F2-TOO MANY ARGUMENTS-EXPR F3-TOO FEW ARGUMENTS-EXPR The wrong number of arguments has been given to a defined function. S-expression 1 is the list of the function variables. S-expression 2 is the list of supplied arguments. F2-TOO MANY ARGUMENTS-SUBR F3-TOO FEW ARGUMENTS-SUBR The wrong number of arguments has been given to an SUBR. S-expression 1 is the function. S-expression 2 is the list of arguments. G2-PUSHDOWN STACK OVERFLOW Recursion is very deep. Non-terminating recursion will cause this error. S-expressions 1 and 2 will, if given, depend on where in the interpreter the stack was last used. The trace-back is not given on this error. The mes- sage 'IN THE GARBAGE COLLECTOR' may follow immediately after this message. This means that there was not enough stack left for the garbage collector to work with when the garbage collector was called. This is a fatal error and LISP gives up control to OS. GC2-STORAGE EXHAUSTED The garbage collector is unable to find unused cells in free cell storage. S-expressions 1 and 2 are the arguments of CONS. The trace-back is not given on this error. This is a fatal error and LISP gives up control to OS. I3-BAD ARITHMETIC ARGUMENT An arithmetic routine was given a non-arithmetic argument. S-expressions 1 and 2 will depend on which arithmetic routine found the error. I5-ATTEMPT TO RAISE 0 TO 0 This error is caused by trying to execute either EXPT(0,0) or EXPT(0.0,0). I6-ATTEMPT TO RAISE 0 TO NEGATIVE POWER This error is cause by trying to execute either EXPT(0,n) or EXPT(0.0,n), where n is negative. I8-EXPT CANNOT TAKE REAL EXPONENT This error occurs when the second argument of EXPT is a floating-point num- ber. R1-SYNTAX ERROR A syntax error has occurred while reading an S-expression. S-expression 1 is the S-expression in question. The trace-back is not given on this error. LISP at UIC 06/30/77 Page 41 R2-BAD BRACKET COUNT An end-of-file was reached while reading an S-expression. S-expression 1 is the list as read with needed brackets (i.e., right parentheses or terminat- ing character in the '$$' notation) generated. The trace-back is not given on this error. This is a fatal error and LISP gives up control to OS. R3-BAD BRACKET COUNT ON USER FILE An end-of-file was reached while reading an S-expression from a data set other LISPIN. S-expression 1 is the list as read with needed brackets gen- erated. The trace-back is not given on this error. The error causes LISP to start reading from LISPIN. R5-NAME OR NUMBER TOO LONG An EBCDIC printname or a number is longer than that accepted by the inter- preter. Truncation occurs on the right. Only the message appears for this error. LISP on CMS at UIC October 1980 The following briefly describes the difference between the version of LISP run- ning on TSO and the version of LISP running on CMS. Section numbers refer to sections in this document (above). ATTENTION INTERRUPT (Section 6) Only Applicable for Line-Edit CMS; do no use the break key when using Full Screen CMS. (See note on title page of document.) The break key serves three functions in LISP on Line-Edit CMS: a) line delete key; b) termination of a traceback during an error message and return of control to the Supervisor; c) interruption of a computation being done. Unlike the version of LISP run on TSO, LISP on CMS does not permit the stacking of Breaks to be resumed at a later time as described in Section 6. If you press the BREAK key during a computation, you get the message LISP and a new prompt for input. If you then enter a carriage return, the computation is resumed. If you enter any non-empty line, the Supervisor is restarted. The functions RESUME, INIT, and BREAK described in Section 6 are not recognized by LISP on CMS. DATA MANAGEMENT IN LISP (Section 7) LISP at UIC 06/30/77 Page 42 The functions described in Section 7 all operate on CMS file names rather than on OS ddnames. All references to blocksize are meaningless; attempts to specify a blocksize are ignored. I/O errors are handled differently than described in Section 7. The function OPEN(fn,list,at) opens the CMS file. The first argument fn gives the filename. The filetype defaults to LISP unless the second argument is SYSFILE, in which case it is LISPCKPT. The second argument may be SYSIN, SYSOUT, SYSFILE, or ((LRECL . n)), where n is the logical record length. An attempt to specify blocksize or con- trol characters will be ignored. LISPUNCH may not be specified for the second argument. The third argument is INPUT or OUTPUT. If a file is opened for out- put, any existing file of that filename and filetype is erased. The property following the indicator DCBADDR on the property list of the atom specifying the file name is a pointer to the FSCB for that file. LISP at UIC 06/30/77 Page 43 APPENDIX THE LISP INTERPETER evalquote[fn;args] = [get[fn;FEXPR] V get[get[fn;FSUBR]-> eval[cons[fn;args];NIL] T -> apply[fn;args;NIL]] apply[fn;args;a] = [ null[fn] -> NIL; atom[fn] -> [get[fn;EXPR] -> apply[expr;(Note 1)args;a]; get[fn;SUBR] -> spread[args](Note 3);ALIST:=a;BAL subr(Note 1); T -> apply[cdr[sassoc[fn;a;[[ ];error[A2]]]];args;a]; eq[car[fn];LABEL] -> apply[caddr[fn];args;cons[cons[cadr[fn];caddr[fn]];a]]; eq[car[fn];FUNARG] -> apply[cadr[fn];args;caddr[fn]]; eq[car[fn];LAMBDA] -> eval[caddr[fn];nconc[pair[cadr[fn];args];a]]; T -> apply[eval[fn;a];args;a]] eval[form;a] = [ null[form] -> NIL; numberp[form] -> form; atom[form] -> [get[form;APVAL] -> car[apval(Note 1)]; T -> cdr[sassoc[form;a;[[ ];error[A8]]]]]; eq[car[form];QUOTE] -> cadr[form];(Note 2) eq[car[form];FUNCTION] -> list[FUNARG;cadr[form];a];(Note 2) eq[car[form];COND] -> evcon[cdr[form];a]; eq[car[form];PROG] -> prog[cdr[form];a];(Note 2) atom[car[form]] -> [get[car[form];EXPR] -> apply[expr;(Note 1)evlis[cdr[form;a];a]; get[car[form];FEXPR] -> apply[fexpr;(Note 1)list[cdr[form];a]a;]; get[car[form];SUBR] -> spread[evlis[cdr[form];a]];(Note 3) ALIST:=a;BAL subr(Note 1); get[car[form];FSUBR] -> A:=cdr[form];Q:=ALIST:=a;BAL fsubr(Note 1); T -> eval[cons[cdr[sassoc[car[form];a;[[ ];error[A9]]]]; cdr[form]];a]]; T -> apply[car[form];evlis[cdr[form];a];a]] evcon[c;a] = [null[c] -> error[A3]; eval[caar[c];a] -> eval[cadar[a];a]; T -> evcon[cdr[c];a]] evlis[m;a] = [null[m] -> NIL; T -> cons[eval[car[m];a];evlis[cdr[m];a]]] 1. The value of get is set aside. This is the meaning of the apparent free or undefined variable. 2. In the actual system this is handled by an FSUBR rather than as the sepa- rate special case shown here. 3. 'Spread' loads the appropriate registers with values given it. Note: Some modification of the definition is necessary where actual machine LISP at UIC 06/30/77 Page 44 instructions are shown to give the representation for the IBM System/370 REFERENCES 1. LISP 1.5 PRIMER, Clark Weissman, Dickenson Publishing Company 2. The Programming Language LISP: Its Operation and Applications, Berkeley, E.C. and Bobrow, D.G., editors, M.I.T. Press 3. LISP 1.5 Programmer's Manual, McCarthy, J., M.I.T. Press 4. Programming Systems and Languages, Rosen, S., editor, McGraw-Hill Publish- ing Company, pp. 455-490 5. An Introduction to LISP, Griffith, A.K., University of Florida 6. The BBN-LISP System, Bobrow, D.G., Murphy, D.L., and Teitelman, W., Bolt Beranek and Newman, Inc. 7. Stanford LISP 1.6 Manual, Quam, L.H., Stanford Artificial Intelligence Project 8. A Paged LISP Using the Dynamic Relocation Hardware of an IBM 360/67, Berns, R.I., (soon to be published) 9. IBM System/360 Principles of Operation, Form No. A22-6821