****************************************************************************** ***** NIL ****** NEWFUN - Description of New Functions, not in MACLISP ******* ****************************************************************************** ******** (c) Copyright 1981 Massachusetts Institute of Technology ************ ************ this is a read-only file! (all writes reserved) ***************** ****************************************************************************** ______________________________________________________________________________ 1. Implementation-dependent values and functions 1.1 Machine and Character-encoding Dependencies 1.1.1 Encoding-dependent Variables 1.1.2 Encoding-dependent Functions 1.2 CLASS and SUBR Facilities 1.3 READTABLE and PACKAGE Facilities 1.4 Storage Allocation Facilities 2. Functions on Sequences 2.1 Generic Sequence Functions 2.1.1 For All Types of Sequences 2.1.2 Functions Restricted to Q-Sequences 2.2 LIST Specific Functions 2.2.1 MEMBER/DELETE Generalizations 2.3 VECTOR Specific Functions 2.4 STRING Specific Functions 2.5 BITS Specific Functions 2.6 Sequence Type Coercions 2.7 Pointer Manipulation 3. Numerical Functions 4. SYMBOL and Package Functions 5. Miscellaneous Functions 5.1 TYPE Usage and Predicates 5.2 For CHARACTERs 5.3 Functional Manipulation 5.4 Identities 5.5 For EXTENDed Data - ARRAYs etc. 5.6 THROW and Error Handling 5.7 PDL and Value Cell hacking 6. Special Forms 7. STREAM Usage functions 8. Aids to EVAL and user interface. 9. Co-Routine Capabilities ______________________________________________________________________________ 1. Implementation-dependent values and functions 1.1 Machine and Character-encoding Dependencies 1.1.1 Encoding-dependent Variables *:MAX-FIXNUM ;stored as a FIXNUM *:MIN-FIXNUM ;" " *:MAX-SMALLNUM ;" " *:MIN-SMALLNUM ;" " *:MAX-SMALL-FLONUM ;" " *:MIN-SMALL-FLONUM ;" " *:MAX-FLONUM ;stored as a FLONUM *:MIN-POS-FLONUM ;" " *:MAX-NEG-FLONUM ;" " *:MIN-FLONUM ;" " *:BITS-PER-Q ;stored as a FIXNUM *:BITS-PER-FIXNUM ;" " *:BITS-PER-SMALLNUM ;" " *:BITS-PER-CHARACTER ;" " *:BITS-PER-BYTE ;" " *:BITS-PER-SMALL-FLONUM-MANTISSA;" " *:BITS-PER-SMALL-FLONUM-EXPONENT;" " *:BITS-PER-FLONUM-MANTISSA ;" " *:BITS-PER-FLONUM-EXPONENT ;" " *:MACHINE-INPUT-BASE ;" " *:BYTES-PER-Q ;" " *:EOF-CHARACTER ;stored as a CHARACTER *:PTR-TYPEP-TABLE ;32-Q vector with symbolic type names *:PRIMITIVE-TYPES-CLASS-TABLE ; 1.1.2 Encoding-dependent functions *:SMALL-FLONUM-EXPONENT Returns the exponent part as a fixnum *:SMALL-FLONUM-MANTISSA Returns the mantissa part as a fixnum *:FLONUM-EXPONENT Returns the exponent part as a fixnum *:FLONUM-MANTISSA Returns the mantissa part as a bignum *:FIX-TO-FLOAT Takes fixed-point input (e.g. FIXNUM, BIGNUM) produces either FLONUM or BIGFLOAT *:ARGFRAME-INDEX *:GET-MODULE find the module of which the arg is a subpart *:NPTR-TYPEP Extracts the type codes bits from a pointer, and returns result as a fixnum [What good are the following? Can they be flushed?] *:OBJECT-SIZE Takes one argument. For "sequence" s, returns the element size as follows: VECTOR - returns the Q size (32 bits on VAX) LIST - also returns the Q size STRING - the machine's byte-size (8 on VAX) BITS - obviously 1. EXTEND - 1 Q ARRAY ??? *:TOTAL-SIZE Takes one argument, a "sequence" {see section 2} and returns the total number of bits in it. *:SET-TOTAL-SIZE Takes two argument, a "sequence" and a fixnum, and sets the size field. This should only decrease the size of a VECTOR, and at most increase the size of a STRING or BITS to the next Q-boundary.) *:SYSCALL Grossly machine-dependent trap to the operating system) 1.2 CLASS and SUBR facilities SI:CLASS-INSTANCE-SIZE ;Number of slots instances of class CLASS have SI:KNOWN-CLASSES SI:OBJECT-CLASS SI:CLASS-CLASS SI:NUMBER-CLASS SI:COMPLEX-CLASS SI:BIGNUM-CLASS SI:BIGFLOAT-CLASS SI:ARRAY-CLASS SI:STREAM-CLASS SI:CLOSURE-CLASS SI:CLOSURE-COMPILED-CLASS SI:BUFFERKEY-CLASS SI:PACKAGE-CLASS SI:READTABLE-CLASS *:EXTEND-CLASS-INDEX ;numeric arg to *:GET-LEADER *:SUBR-NAME-INDEX ;numeric arg to *:GET-LEADER *:SUBR-DESCRIPTOR-INDEX ;numeric arg to *:GET-LEADER *:SUBR-DOCUMENTATION-INDEX ;numeric arg to *:GET-LEADER Functions: CLASS-OF Gets the class structure for any object. Same as *:CLASS-OF, except CLASS-OF is closed-compiled and checks type of arg. (SI:EXTEND-CLASS-OF does no error checking). CLASS-OF also works on non-EXTENDs also, retrieving the canonical CLASS object for instances of FIXNUMs, PAIRs, etc. SI:EXTEND-CLASS-OF Gets the "leader" slot of an EXTEND which points to the CLASS object, of which this item is an instance. SI:SET-EXTEND-CLASS-OF Updates the class "leader" slot of an EXTEND. MAKE-EXTEND Takes 1 to 3 args; 1st is a count of the number of slots, 2nd is a class object (defaults to OBJECT-CLASS) and third is a initialization sequence (defaults to null). SI:MAKE-EXTEND Another name for MAKE-EXTEND (takes precisely 2 args) SI:MAKE-SUBR Conses up a SUBR with as many bits as specified by the first arg, and three more args for the leader slots NAME, DESCRIPTOR, and DOCUMENTATION. SUBR-NAME Gets the "name" compononet of the subr leader. SET-SUBR-NAME Sets the "name" compononet of the subr leader. SUBR-DESCRIPTOR SET-SUBR-DESCRIPTOR SUBR-DOCUMENTATION SET-SUBR-DOCUMENTATION SI:APPLY-SUBR This is like APPLY (the "list" of arguments may also be a vector) of arguments, but the function must be a SUBR. This is how the function APPLY dispatches to a SUBR. SI:COPY-SUBR Make a copy of a SUBR. This is the primitive by which FSET (SUBRIFY) performs the "mediation" step of creating trampolines for LAMBDA- expressions, MACROs, and EXTENDs. [Are the following two really necessary? JONL - 8/1/80] *:GET-LEADER Two args: 1st is frob which admits "leaders", 2nd is index into the "leader" area. *:SET-LEADER A CLASS object is a structure with the following components, for which accessor macros are defined in the SYSTEM-INTERNALS package: SI:CLASS-TYPEP The value to be returned by TYPEP for instances SI:CLASS-SUPRS Superior(s) of this class in class hierarchy SI:CLASS-SENDI Function to interpret SENDs to instances SI:CLASS-CALLI Interpreter for applications of instances SI:CLASS-MTHDS A-list (or a-vector) of methods for SENDs SI:CLASS-DESCR A vector describing each slot of an instance. [The above will need some serious re-thinking when/if FLAVORs and dirty EXTENDs arrive on the scene...] [Talk about GC methods?] 1.3 READTABLE and PACKAGE Facilities Two global variables, READTABLE and PACKAGE operates similarly to MACLISP or LISPM, but each should holds an extended object of the right type. [Explain PKG-GOTO here. Should we have an analogous function for READTABLEs?] In addition, a new global variable SI:PRINT-PACKAGE will control the action of PRIN1 and PRINC, in that a symbol is always printed out with a preceeding package identifier, namely that of its "owner" package, but if the symbol is owned by the package in the current value of SI:PRINT-PACKAGE, then the package identifier is omitted. Initial setting of SI:PRINT-PACKAGE is to the "USER" package. [What good is this?] Another new global variable, SI:STANDARD-INPUT-RADIX, is initially ten. (In the PDP10 and LISPM, this is called IBASE, but in NIL changing it is something only a hacker should do - one should generally write his programs with radix markers included, if something other than ten is desired.) A READTABLE object is a "structure", consisting of ten entries -- two special characters, six sub-tables, and an alist for macros: SYNTAX-ESCAPE-CHARACTER ;a CHARACTER which "quotes" the next ; character of the input stream so that ; it has no special syntax. Slash! PACKAGE-NAME-CHARACTER ;a CHARACTER which signals package name ; to the left and symbol to the right CONSTITUENT-TRANSLATION-TABLE ;a STRING - ith element is translation ; during SYMBOL reading for character ; with numerical value i. INPUT-TRANSLATION-TABLE ;a STRING - ith element is translation ; on INCH from "logical" character set OUTPUT-TRANSLATION-TABLE ;a STRING - ith element is translation ; on OUCH to "logical" character set INVISIBLE-CHARACTER-TABLE ;a BITS such that bit number i is 1 iff ; the character with code number i is ; considered a "white-space" character TOKEN-TERMINATOR-TABLE ;a BITS - index i 1 iff char should ; break a string of "letters" or digits ; (Will be hacked by macro-chars.) MACRO-CHARACTER-TABLE ;a BITS - 1 iff char is a "macro" MACRO-CHARACTER-INFO ;a VECTOR, or list, of macro-char funs SHARP-MACRO-LIST ;a VECTOR, or list, of dispatch data ; for characters following a /# A PACKAGE object is a structure of the following elements: [Many of these items have been simply lifted from LISPM's PACKAGE structure. We need a little thinking about this. However, the only ones SI:RINTERN need pay attention to are SI:PACKAGE-SUPER-PACKAGES, SI:PACKAGE-SYMBOL-COUNT, SI:PACKAGE-LOCKED, SI:PACKAGE-MAX-SYMBOL-COUNT, and SI:PACKAGE-SYMBOL-TABLE. Also, PKG-FIND-PACKAGE is necessary in the cold-load environment for VASLOAD, and it needs to look at SI:PACKAGE-REF-NAME-AVECTOR] SI:PACKAGE-SUPER-PACKAGES List of "superior" packages - essentially, where INTERN will continue searching. SI:PACKAGE-SUB-PACKAGES list of spawns SI:PACKAGE-NAME Name of this package, for PRINT SI:PACKAGE-DOCUMENTATION string describing what belongs on the package SI:PACKAGE-ADVERTIZED-SYMBOLS symbols which are advertized as being the "features" of this package. These become available to other packages who USE this package via package declarations. SI:PACKAGE-LOADED Non-NULL if package has been loaded SI:PACKAGE-USER-PACKAGES Packages which USE this package SI:PACKAGE-SYMBOL-TABLE vector of SYMBOLS, see SYMBOL-TABLE-INDEX function SI:PACKAGE-REF-NAME-AVECTOR VECTOR of dotted pairs of strings and the packages they refer to, in the context of this package. Searched with (essentially) (ASS #'(LAMBDA (X Y) (NOT (STRING-MISMATCH X Y))) reference (SI:PACKAGE-REF-NAME-AVECTOR package)) SI:PACKAGE-EXTERNAL-LIST List of symbols we can DEFUN from superior, or T meaning OK to redefine anything SI:PACKAGE-SYMBOL-COUNT Number of symbols interned in this package. SI:PACKAGE-MAX-SYMBOL-COUNT Number of symbols before time to grow vector SI:PACKAGE-LOCKED T if package is not to be written in. SI:PACKAGE-DECLARED T if package has been declared SI:PACKAGE-FILES Vector of files declared to be in this package SI:PACKAGE-SHADOW-LIST List of symbols specified to be shadowing super-package symbols. DEFREADTABLE - a function with an optional argument, which is taken to be a readtable to be copied; with no argument, a copy of the initial standard readtable is made. DEFREADMACRO ( &optional ( READTABLE)) is made into a macro character in the readtable , which if not supplied as argument, defaults to the value of the variable used by READ. should take two arguments, the first is the character which invoked it, and the second is the stream from which it came. may be among {SINGLE, LIST, CHARACTER, PROG} SINGLE is like the standard, elemental, maclisp reader macro; LIST means the same as the maclisp SPLICING macro (the must return either () or a list of forms); CHARACTER means that the will return a STRING, which is the "putback" as a BLOCK into the stream - thus one character may expand into many characters, just as in MIDAS; PROG means that the type is not constant, and each invocation of will return a pair ( . ) where is among {SINGLE, LIST, CHARACTER}, and the is as if that call were a macro-character of the given type. DEFREADTRANSLATION ( &optional ( ) ( READTABLE)) Installs a "translation", of one character into another; this translation only affects the function READ. Action is on the readtable which defaults to the value of READTABLE. (DEFREADTRANSLATION ) would reinstall the translation of that character to itself. SI:FIND-CONSTANT - one argument which may be a string (or symbol, which is immediately converted to a string). Tries to find the built-in CONSTANT which has that string as pname. 1.4 Storage Allocation Facilities (many GC primitives will appear here) 2. Functions on Sequences Let "Sequence" be a conceptual data-type, which is the union of LIST, VECTOR, STRING, and BITS. We note that there are four basic kinds of operations to be performed on sequences: SELECTing, REPLACEing, SEARCHing, and COMPAREing; and in each case, the key may be either a basic element, or a subsequence. Following is a table of names of these generic functions: Operation | Element-key | Subsequence-key _____________|_______________________________________________________________ | | Select | ELT | SUBSEQ Replace | SETELT, FILL | REPLACE Search | POSITION, POSQ, POS | SEARCH, SEARCHQ, SEAR Compare | SKIP, SKIPQ, SKP | MISMATCH, MISMATCHQ, MISMAT Predicates | SEQUENCEP, LISTP, VECTORP, STRINGP, BITSP Constructions | MAKE-, APPEND, REVERSE, REMOVE Also, for searching in a "backwards" direction, there will be a limited number of predicates composed by prefixing a "B" to the name of the forward-searching root name. E.g. BPOSITION, BSEARCH, BSKIP (as well as names like STRING-BPOSQ, STRING-BSEARCHQ, STRING-BSKIPQ). A new predicate of one argument, SEQUENCEP, which will return () if the argument is not a sequence, and the PTR-TYPEP of the argument if it is. The generic comparison functions "sequence-EQUAL" are not generally being added, due to a conflicting nomenclature with the LISPM terms, but instead STRING-EQUAL will be compatible with that definition. For type-testing, there are the specific predicates whose names are formed according to the rule "P"; i.e. LISTP, VECTORP, STRINGP, and BITSP. There are also all the various type-specific selector/updator functions, but one problem with the consistency the nomenclature is that these more-often used names will be shorter and according to the general naming rule. Thus we have VREF rather than VECTOR-ELT, RPLACHAR rather than STRING-SETELT, and so on. (see the individual type-specific sections). For each , there is also a constructor function "MAKE-" of one argument which constructs a sequence of that type, with as many "null" elements as specified by the argument. The "null" element is type-specifie, but these MAKE functions admit one optional argument which specifies what the particular filler element is to be; one exception, is that () for the filler to MAKE-STRING and MAKE-BITS means "no filling", and hence the contents of the newly allocated sequence will be random. There are also two constructor functions LIST and VECTOR which accepts arbitrarily many arguments, and construct up a list and vector respectively with just those arguments as elements. Thus, for example, we could write (LIST 'A 3 (MUMBLE)), and (VECTOR '(A B) ~e 3.4) 2.1 Generic sequence functions First, we take some standard LISP functions, and generalize them in the obvious way for "sequence"-like data: LENGTH APPEND REVERSE NREVERSE. The function GET will be generalized for VECTORs and LISTs only, which will be called "Q-sequences". 2.1.1 For All Kinds of Sequences Fun name | Arglist ___________|_______________________________________________________________ | LENGTH APPEND REVERSE NREVERSE ELT ( ) ;generalized selector SETELT ( ) ;generalized updator SUBSEQ ( &OPTIONAL ( 0) ( (- (LENGTH ) ))) Gets a new sequence (a "subsequence") of the same type as the first argument, and of length composed of the elements beginning at . If + is greater than length{}, then signal an error. FILL ( &OPTIONAL ( 0) ( (- (LENGTH ) ))) The object is stored into successive positions of , beginning at ; If + is greater than length{}, then an error is signalled. The argument must be of a type appropriate to be a component of ; otherwise an error is signalled. REPLACE ( &OPTIONAL ( 0) ( 0) ( (min (- (LENGTH ) ) (- (LENGTH ) ))) Replaces successive elements of beginning at , with the elements of beginning from . If + is greater than length{}, or if + is greater than length{}, then an error is signalled. If seq1 and seq2 are not of the same type, then there will be some type-coercion, according to the hierarchy (1) LIST, (2) VECTOR, (3) STRING, and (4) BITS. POSITION POSQ ( &OPTIONAL ( 0) ( (- (LENGTH ) ))) Scans the , beginning at until finding the first instance of ; returns the index whereat found or () if not found. Scanning is limited to the index interval [ , +-1 ] which is the range of indices within which a match is sought. For LISTs and VECTORs, the equality predicate is EQUAL; for STRINGs and BITs it is EQ (note that EQUAL on "0" and "1" is just EQ). The function POSQ works the same as POSITION except that the equality predicate is EQ in all cases. If the is not of a type permissible as a component in the (e.g., a flonum is not an element of a character string) then there will be some type-coercion, according to rules which will likely be elucidated in the future. {TO BE DONE LATER} POS ( &OPTIONAL ( 0) ( (- (LENGTH ) ))) The function POS permits the user to supply an equality predicate. In all other respects, POS is like POSITION. SEARCH SEARCHQ ( &OPTIONAL ( 0) ( (- (LENGTH ) (LENGTH ) -1 ))) Scan the , beginning at until finding the first instance of a subsequence which is element-for-element equal to the sequence ; returns the index whereat found, or () if not found. Scanning is limited to the index interval [ , +-1 ] which is the range of indices at which pattern-matching may begin. For LISTs and VECTORs, the equality predicate is EQUAL; for STRINGs and BITs it is EQ (note that EQUAL on "0" and "1" is just EQ). The function SEARCHQ works the same as SEARCH except that the equality predicate is EQ in all cases. SEAR ( &OPTIONAL ( 0) ( (- (LENGTH ) (LENGTH ) -1 ))) The function SEAR permits the user to supply an equality predicate; otherwise, its actions is like SEARCH. SKIP SKIPQ ( &OPTIONAL ( 0) ( (- (LENGTH ) ))) Scan the , beginning at until finding the first instance of an element which is not equal to ; returns the index whereat found, or () if not found. Scanning is limited to the index interval [ , +-1 ] which is the range of indices at which comparisons are made. For LISTs and VECTORs, the equality predicate is EQUAL; for STRINGs and BITs it is EQ (note that EQUAL on "0" and "1" is just EQ). The function SKIPQ works the same as SKIP except that the equality predicate is EQ in all cases. SKP ( &OPTIONAL ( 0) ( (- (LENGTH ) ))) The function SKP permits the user to supply an equality predicate; otherwise, its actions is like SKIP. MISMATCH MISMATCHQ ( &OPTIONAL ( 0) ( 0) ( (min (- (LENGTH ) ) (- (LENGTH ) ))) ) Compares successive elements of beginning at , with the elements of beginning from . Returns null if all elements are equal, and returns the least index of a mismatch (index into ) if not. If + is greater than length{}, or if + is greater than length{}, then an error is signalled. If seq1 and seq2 are not of the same type, then there will be some type-coercion, according to the hierarchy (1) LIST, (2) VECTOR, (3) STRING, and (4) BITS. MISMAT ( &OPTIONAL ( 0) ( 0) ( (min (- (LENGTH ) ) (- (LENGTH ) ))) ) The function MISMAT permits the user to supply an equality predicate; otherwise, its actions is like SEARCH. REMOVE REMQ ( &OPTIONAL ( 0) ( (- (LENGTH ) ))) Makes a new, possibly shorter, sequence with all instances of removed; likely BITS-REMOVE will not be used. For LISTs, the new list may shar a tail with the original list. REM ( &OPTIONAL ( 0) ( (- (LENGTH ) ))) The function REM permits the user to supply an equality predicate. In all other respects, REM is like REMOVE. For every generic function FUN here defined on sequences, there are type-specific functions LIST-FUN, VECTOR-FUN, STRING-FUN, and BITS-FUN (the exception to this is ELT and SETELT, since each data-type has common-use names for the selector functions). Thus, for every among {LIST, VECTOR, STRING, BITS}, and every among {LENGTH, APPEND, REVERSE, NREVERSE, SUBSEQ, FILL, REPLACE, SKIP, SKIPQ, SKP, POSITION, POSQ, POS, SEARCH, SEARCHQ, SEAR, MISMATCH, MISMATCHQ, MISMAT, REMOVE} there will be a type-specific function "-". For example, there is STRING-LENGTH, VECTOR-NREVERSE, LIST-POSQ, and so on. Most of these names are of little value, but some may be open-coded by the compiler The following functions will be supported by minisubrs: LIST-LENGTH, sequence-SUBSEQ, sequence-FILL, sequence-REPLACE, sequence-SKIPQ, sequence-POSQ, sequence-SEARCHQ, sequence-MISMATCHQ, sequence-REMOVE {and possibly STRING-BPOSQ, STRING-BSEARCHQ, STRING-BMISMATCHQ, STRING-REMOVE} There will be 2 different minisubr entries for each, depending on whether the &optional arg is supplied). On the VAX, the following functions will likely be open-coded VECTOR-LENGTH, STRING-LENGTH, BITS-LENGTH STRING-SKIPQ, STRING-POSQ, STRING-SEARCHQ, STRING-MISMATCHQ (and the various "STRING-B...Q" versions of the above line) 2.1.2 Limited to Q-Sequences GET will work on LISTs, VECTORs, or SYMBOLs (the latter case is converted to the case of a LIST by taking the plis). The following are generalized for VECTORs (as well as LISTs): ASSOC ASSQ ASS RASSOC RASSQ RASS POSASSOC POSASSQ POSASS In each corresponding case, the predicate used is: EQUAL EQ Under 2.2.1 below, "LIST Specific Functions", there are definitions of these new functions, such as MEMASSOC, and DELASSOC. 2.2 LIST specific functions Name of fun | Arglist | Comments ________________|_______________________________|____________________________ | | LISTP () ;Type-specific predicate MAKE-LIST ( &optional ) ;CONSs a new LIST of ()s LIST (&rest . . . ) LIST-LENGTH () SET-LIST-LENGTH ( ) ;Uses RPLACD on the list LIST-ELT ( ) LIST-SETELT ( ) [The preceeding two functions don't really offer any advantage over the generic ELT and SETELT functions. The following two functions have arguments in reverse order from the generic ELT/SETELT in order to accommodate these definititons from MACLISP and the LISPMachine.] NTH ( ) ;Selects the ith element of a list NTHCDR ( ) ;Selects the ith tail of a list LIST-TO-VECTOR ( &OPTIONAL ( 0) ( (- (LENGTH ) ))) The elements of are sequentially stored into a fresh vector, beginning at element number and going for number of elements. [Although not new, it would be well to remember here the list-specific functions MEMBER, DELETE and their variants such as MEMQ and DELQ] 2.2.1 MEMBER/DELETE Generalizations The following are only for LISTs: MEMBER MEMQ MEM DELETE DELQ DEL MEMASSOC MEMASSQ MEMASS DELASSOC DELASSQ DELASS The MEMASSOC series (and DELASSOC series) are like a cross between ASSOC and MEMBER (DELETE). The equality predicate is applied not to the successive CARs of the list, but to the successive CAARs, as ASSOC would do; however, the return value for MEMASSOC is the tail of the list (rather than the item "found), just as MEMBER returns. DELASSOC will "splice out" the "found" item, but still returns the whole list, just as DELETE does. 2.3 VECTOR specific functions Name of fun | Arglist | Comments ________________|_______________________________|____________________________ | | VECTORP () ;Type-specific predicate MAKE-VECTOR ( &optional ) ;Allocates a new VECTOR VECTOR (&rest . . . ) Could be defined (but isn't implemented) by (REPLACE (MAKE-VECTOR 'n) (LIST . . . )) Thus (VECTOR ... ) makes a vector with n elements initialized to the expressions . VECTOR-LENGTH () SET-VECTOR-LENGTH ( ) ;Cannot increase length VREF ( ) ;Selects the ith element of a vector VSET ( ) ;Store into the ith element of a vector [The preceeding two functions are vector-specifict, and may have an efficiency consequence in compiled code, when compared to the generic selectors.] VECTOR-TO-LIST ( &OPTIONAL ( 0) ( (- (LENGTH ) ))) The elements of are enlisted, beginning at and going for number of elements. Note that most primitive VECTOR operations will also work on EXTENDs, since the latter is merely a different type pointer to a structurally similar object. In particular VREF, VSET, and VECTOR-LENGTH are planned for now. 2.4 STRING specific functions Name of fun | Arglist | Comments ________________|_______________________________|____________________________ | | STRINGP () ;Type-specific predicate MAKE-STRING ( &optional ( (ASCII 0)) ;Allocate a new STRING, and fill each slot of it with ; the character ; if is null, ; then do no filling (the string will be random chars). STRING-LENGTH () SET-STRING-LENGTH ( ) ;Cannot increase length CHAR ( ) ;gets ith character of RPLACHAR ( ) ;sets ith character of to be CHAR-N ( ) ;ith character of as a fixnum RPLACHAR-N ( ) ;sets ith character of to be ; the one with ascii value STRING () Tries to "coerce" to be a STRING - Permits strings, symbols characters etc. As mentioned in section 2.1, there will be string-specific functions with names such as "STRING-REPLACE", "STRING-APPEND", etc. Also, there are a limited number of such functions which accept a "character" argument represented as the fixnum value of the character, rather than requiring a CHARACTER object: e.g. corresponding to STRING-FILL, STRING-POSQ, and STRING-SKIPQ, there are STRING-FILL-N, STRING-POSQ-N, STRING-SKIPQ-N. Again as mentioned in section 2.1, there will be a limited number of "backwards searching" functions: corresponding to STRING-POSQ and STRING-SKIPQ, there are STRING-BPOSQ, STRING-BPOSQ-N, STRING-BSKIPQ, and STRING-BSKIPQ-N. [The following STRING-specific functions can open-code, on the VAX, and probably something on the S1] STRING-POSQ (and STRING-POSITION) ;LOCC or SKPC on the VAX STRING-MISMATCHQ (and STRING-MISMATCH) ;CMPC on the VAX STRING-SEARCHQ ;MATCHC on the VAX STRING-SKIPQ (and STRING-SKIP) ;SKIPC on the VAX STRING-HASH ;CRC on the VAX Takes one argument, a string, and returns a 30-bit twos-complement integer. 2.5 BITS functions Name of fun | Arglist | Comments ________________|_______________________________|____________________________ | | BITSP () ;Type-specific predicate MAKE-BITS ( &optional ( 0) ) ;Allocate a new BITS, and fill each slot of it with ; the bit ; if is null, ; then do no filling (the contents of the bits will ; be random). BITS (&rest . . . ) BITS-LENGTH () SET-BITS-LENGTH ( ) ;Cannot increase length BIT ( ) ;gets a 0 or 1 from index i BIT1P ( ) ;#T iff bit at index i = 1 RPLACBIT ( ) ; must be FIXNUM ; (low bit is used) GET-A-BYTE ( ) ;Select the ith group of *:BITS-PER-BYTE bits ; from and make into a positive fixnum GET-A-BYTE-2C ( ) ;Select the ith group of *:BITS-PER-BYTE bits ; from , and make into twos-complement, ; sign-extended fixnum SET-A-BYTE ( ) ;low-order *:BITS-PER-BYTE of are stored ; into beginning at index NIBBLE ( ) Select bits of the bit-string , beginning at index , and return the answer as a positive fixnum. NIBBLE-2C ( ) Select bits of the bit-string , beginning at index , and return the answer as a twos-complement, sign-extended fixnum. SET-NIBBLE ( ) The low-order bits of the FIXNUM are stored in the bit-string , beginning at index . One reason, perhaps, for using NIBBLE where appropriate, rather than BITS-SUBSEQ (or even SUBSEQ), is that the latter will require the consing of at least two words for the resultant bitstring, but to return a fixnum requires no consing. 2.6 Sequence Type Coercions The generic functions "TO-" take one argument, which must be a sequence, and construct a new sequence of type with all the elements from the input argument. The sequence returned behaves the same with respect to LENGTH and ELT as the original does. One provision is that if a sequence of type is given as argument, then TO- will simply return its argument without creating a new one. Specifically, there are TO-LIST, TO-STRING, TO-VECTOR, and TO-BITS. To help in certifying the validity of arguments to sequence functions, there is the function SI:CHECK-SUBSEQUENCER, the calls to which are normally set up by the special-form CHECK-SUBSEQUENCE (likely implemented as a macro). (DEFMACRO CHECK-SUBSEQUENCE ( (SEQ-VAR START-I-VAR COUNT-VAR) TYPE FUN &OPTIONAL (STARTP #T) (COUNTP #T) (FORWARDP #T)) ...) What this means is that "FUN" should be the name of the function that that is requesting the check, and the the sequence argument must be of type "TYPE". SI:CHECK-SUBSEQUENCER will return three values to update the original three arguments, and thus the items "SEQ-VAR", "START-I-VAR", and "COUNT-VAR" must be the variables which hold correspondingly the 1) sequence of type "TYPE", 2) a "starting index" for a subsequence thereof, 3) and a length "count" for such subsequence. The item "FORWARDP", when non-null, says that the subsequence is specified by a "start index" which specifies the least-index element of the original sequence contained in the subsequence; in the "backwards" looking case, it specifies one beyond the greatest-index element. Calculation of default values: SI:CHECK-SUBSEQUENCER will calculate the appropriate default values for "START-I-VAR" and "COUNT-VAR", when the STARTP and/or COUNTP items show that these optional arguments to the calling function FUN were not supplied by the user. Start indices default to 0 in the forward- looking case, and to the lenght of the sequence in the other case; length-count values default to the length of the sequence minus the start index, in the forward-looking case, and to merely the start index value in the other case. Correction of illegal arguments: SI:CHECK-SUBSEQUENCER will run correctible errors if any of these conditions are not met: 1) the sequence argument is of the type, 2) the start index is not a fixnum, or it is a fixnum, but is negative, or is not less than the length of the sequence (when the "forwardp" item specifies forwards looking -- for backwards looking the start index is permitted to be equal to the length of the sequence). 3) the length count, as supplied by the caller to FUN, is not a fixnum, or it is but is negative or too big. For both the start index and length count values, the corresponding items STARTP and COUNTP tell whether or not the caller of the function FUN supplied them, or whether the default value (from the definition of FUN was taken. In the latter case, if the FUN defaults them to null, then SI:CHECK-SUBSEQUENCER will do the default value calculations instead of running an error. Consider an example usage, for the lisp-definition of STRING-SUBSEQ (defun STRING-SUBSEQ (str i &optional (cnt () cntp)) (cond (*RSET (check-subsequence (str i cnt) 'STRING 'STRING-SUBSEQ #T cntp)) ((not cntp) (setq cnt (- (string-length str) i))) (#T "No checks or defaulting need be done in this case")) (+internal-substringify str i cnt)) 2.7 Pointer Manipulation *:NPTR-TYPEP Extract a pointer's type field, and return the result as a fixnum. *:PTR-ADDRESS Extract a pointer's address field, and return the result as a fixnum. *:MAKE-PTR First argument is a fixnum representing a machine address, and second is a ptr-typep code (as a fixnum such as would come from *:NPTR-TYPEP); returns a new typed pointer. *:TRANSFER-TYPE Given a pointer and a machine address as a fixnum, return a pointer whose type is the same as that of the pointer, and whose address is the new machine address. *:<%, *:<=%, *:=% Compare two pointers as machine words. If they *:>=%, *:>% differ in type the result will probably be meaningless. For FIXNUMs, this is the same as <. *:+% All but one arg should be FIXNUMs; the arguments are added together as machine words, so the result is likely to be the same type as the remaining arg. *:-% Similar to *:+%, but if two args are of the same type, the result will be of type FIXNUM. *:FIXNUM-TO-CHARACTER Could be defined as follows: (DEFUN *:FIXNUM-TO-CHARACTER (PTR) (*:TRANSFER-TYPE ~/X PTR)) *:CHARACTER-TO-FIXNUM This is an alias for *:POINTER-ADDRESS. 3. Numerical Functions: Name of fun | Arglist _____________|_______________________________________________________________ | DIVIDE A generic function like QUOTIENT, but returns two values, namely the QUOTIENT and REMAINDER. BIGNUMP Same as maclisp's BIGP FIXNUMP (FIXNUMP ) ::= (EQ (TYPEP ) 'FIXNUM) FLONUMP (FLONUMP ) ::= (EQ (TYPEP ) 'FLONUM) FLOATP (FLOATP ) ::= (MEMQ (TYPEP ) '(FLONUM BIGFLOAT SMALL-FLONUM)) SMALL-FLONUMP an INOB with limited flonum-like capacity MAKE-SMALL-FLONUM Takes one argument, a FLONUM, and tries to put it into the SMALL-FLONUM format; error if fail. SMALLNUMP smallnums are merely a subrange of the FIXNUMs, dependent on various machine considerations; probably two bytes of bits. [may not be in pilot version of Summer 1981] FLOAT ( &optional ( 'FLONUM) ( 10.) ( 0) ( () )) Creates a floating-point number of type determined by , by coerceing , and scaling it by multiplying by to the power of . may be among FLONUM, BIGFLOAT, or SMALL-FLONUM; if is BIGFLOAT, then the number of bits of precision is specified by . NEAR-ENOUGH An attempt to "fuzz" the equality notion for floating-point, as is done with COMPARISON-TOLERANCE in APL. Thus there will be a global-variable, say "SI:FLOATING-NEARNESS", such that (modulo certain boundary conditions) we will say that "a is NEAR-ENOUGH to b" iff a = b in the sense of NUMER= below, or ||a|-|b||/max{|a|,|b|} < SI:FLOATING-NEARNESS NUMER= A kind of numerical equality, that does its best to say "true" to pairs like (3.5, 3.5B0), (54, 54.0S0) etc. ONEP A nice complement to ZEROP. MAX& "Max" and "Min" functions constrained to FIXNUMs MIN& MAX$ "Max" and "Min" functions constrained to FLONUMs MIN$ [The following functions exist, as on the PDP10 MACLISP, in order to constrain the data form of the arguments so that open-compilation may produce simple machine instructions. All other similar "old" functions from PDP10 MACLISP are also to be added, such as "+", "*$", etc.] = Numerical equality, with types of arguments constrained to FIXNUM. =$ Numerical equality, with types of arguments constrained to FLONUM. > Constrained to FIXNUMs; extended to accept two or more arguments < >= (greater-than-or-equal for two or more FIXNUMs) <= >$ Constrained to FLONUMs; extended to accept two or more arguments <$ >=$ (greater-than-or-equal for two or more FLONUMs) <=$ The following functions are primarily intended to aid in the writing of bignum arithmetic routines in NIL iteself. The all take three input arguments, and return two values. All arguments and results are ordinary FIXNUMs. SI:FULLADD (SI:FULLADD x y carry_in) ==> [sum_x+y+carry_in, carry_out] SI:FULLSUB (SI:FULLSUB x y carry_in) ==> [difference_x-y+carry_in, carry_out] Where the sum and difference indicated are two's complement results, and the "carry"s are all restricted to -1, 0 and +1. Since true integer addition cannot be restricted to a finite range, there must be "wrap-around" even in these functions. Thus, let n+1 be the number of bits in the FIXNUM (two's-complement) representation; then mx :== 2^n - 1 ;maximum representible (positive) FIXNUM mnx :== -2^n ;minimum representible (negative) FIXNUM Then both (SI:FULLADD mnx mnx -1) and (SI:FULLSUB mx mnx 1) will "wrap-around" (i.e., "overflow"). Thus a fail-safe, but slightly pessimistic, test for "overflow" is merely to test the second argument for being equal to "mnx". Happily, the most important system usages of these two have an explicit 0 carry_in, but at a few places in the BIGNUM implementation they require the full generality. SI:FULLMUL (SI:FULLMUL x y carry_in) ==> let productsum == x*y+carry_in [productsum_div_by_2^n, productsum_div_by_2^n] Note that if both x and y are equal to "mnx" as described above, the the result will "overflow". SI:FULLDIV (SI:FULLDIV low hi divsr) ==> [quotient, remainder] The division indicated is (hi*2^n+low)/divsr 4. SYMBOL and PACKAGE Functions SYMBOLP GET-PNAME Gets the PNAME cell of a symbol (which is a string). SI:SYMBOL-PACKAGE Gets contents of the symbol's package cell -- ususally it's the package which originally interned the sym. SI:SET-SYMBOL-PACKAGE The following functions parallel BOUNDP, SYMEVAL, SET, and MAKUNBOUND. FBOUNDP Non-null only if symbol has something in its function cell FSYMEVAL Gets the contents of a function cell of a symbol, but "mediates" it if it is a LAMBDA expression or MACRO. SI:FSYMEVAL-SUBR Gets contents of a symbol's special function cell of as a SUBR pointer, does not do the "unmediation" step, but merely adjoins the type code for subr. SI:FSET-SUBR Stores a SUBR into a special function cell (as an address) FSET Stores into the function cell, but may have to cons up a "mediation" subr on the fly. FMAKUNBOUND Stores a pointer to an error routine in the function cell. MAKE-SYMBOL ( &OPTIONAL ( () ) ( () ) ) INTERN ( &OPTIONAL ( PACKAGE)) "" is really a package in the LISPM sense. INTERN-LOCAL INTERN-SOFT INTERN-LOCAL-SOFT INTERNDP ( &OPTIONAL ( PACKAGE) ) Will not install any symbols on any packages - merely returns #T or () depending on whether there is already one there. The "" argument tells whether or not to continue searching for a symbol in the predecessors of the argument. REMOB ( &OPTIONAL ( PACKAGE)) SI:RINTERN Three arguments - a string is first. Second if null says to incorporate the string into a new symbol if there is not one already samepnamep, if non-null, is a count of how many chars to compare in string-mismatch test, and to copy that segment if a new symbol is needed. Third is a package on which to do the interning. [This function is primarily the Reader's intern] PACKAGEP PKG-ADD-REFNAME from-pkg refname to-pkg Causes 'from-pkg' to be known by 'to-pkg' by refname 'refname.' PKG-GOTO package PKG-FIND-PACKAGE x &optional (create-p () ) (under "global") Tries to interpret X as a package. Most function with arguments which are (yet to be) described by "may be either a package or the name of a package" call PKG-FIND-PACKAGE to interpret their argument. READ and VASLOAD use it to interpret symbol references like FOO:BAR, to pass a package argument to RINTERN. SI:SYMBOL-CONS One arg, a string, which will be used as the pname. *** to be mini-subr'd *** SI:SYMBOL-TABLE-INDEX Four args - a vector (considered to be a "symbol table", that is, entries are either symbols or null), a string, and a fixnum (considered to be a limit on the number of chars of the string to consider). Returns the index of the vector whereat a SYMBOL is found which is samepnamep to the argument string (albeit, limited to the first n chars, where n is the third arg) *** to be mini-subr'd *** SI:SYMBOL-PACKAGE-PREFIX symbol Returns a string which would be an appropriate second argument to INTERN-SOFT for recovering the symbol, or () if none would be needed (i. e. symbol is on "current" package or superior, accounting for shadowing, etc.). This is called by the printer and the assembler. This assumes that package references can be resolved with a single string, i. e. that in Nil, unlike Lispm, symbols will never need to print as FOO:BAR:BAZ. This replaces Lispm's PKG-MAP-REFNAMES. 5. Miscellaneous Functions 5.1 TYPE Usage and Predicates PTR-TYPEP A Primitive TYPEP, which only gets info from the pointer (DEFUN PTR-TYPEP (X) (VREF *:PTR-TYPEP-TABLE (*:NPTR-TYPEP X))) TYPEP Compatible with MACLISP, except in the case of (), which in Maclisp is SYMBOL and in Nil is LIST. TYPE-OF A slight generalization of TYPEP; acts the same for non-EXTEND data, but for EXTENDs selects a fixed slot within the CLASS object for that extend which holds a symbolic "type" name to be returned. PAIRP Non-null-list-predicate FEATUREP Like (STATUS FEATURE mumble) in MACLISP 5.2 For CHARACTERs The next three functions are for LISPM compatibility: CHARACTER Coerces, into the fixnum value of a CHARACTER, any of CHARACTER STRING FIXNUM or SYMBOL, so that functions which want a "character" as input can be lenient (LISPM compatible). See TO-CHARACTER below. CHAR-EQUAL Takes two "characters" as fixnums (ascii value), and returns non-null if and only if, after ignoring case, the two args are the same character. CHAR-LESSP Similar to CHAR-EQUAL - takes two fixnum arguments, ignores case, and uses the numerical ordering of the (ascii) alphabet. DIGITP One argument, run an error if argument is not coercible to a CHARACTER. Returns non-() iff argument represents one of the 10. decimal digits 0, 1, ... 9. DIGIT-WEIGHT Like DIGITP, except that the domain is extended to the "supra-decimal" digits too, namely the 36. characters 0, 1, ... 9, A, B, ... Z Returns () if argument is not in the domain, and otherwise returns a fixnum in the range 0 - 35. which is the digit's numerical value. TO-CHARACTER Coerces, into a CHARACTER, any of CHARACTER, STRING, FIXNUM, or SYMBOL, so that functions which want a "character" as input can be lenient. Runs a correctible error if argument is no one of these types. TO-CHARACTER-N Essentially the same as TO-CHARACTER, but result is the fixnum value of the result (see *:CHARACTER-TO-FIXNUM). TO-CHARACTER-N? Two args, second is a flag saying whether or not to cause an error when the first argument is not coercible. When second arg is (), and first arg is not coercibble, the result is (); otherwise action is identical to TO-CHARACTER-N. 5.3 Functional Manipulation [The functions of this section are only tentatively named as of March 1981] ARG As in MACLISP, (ARG 0) gets the number of arguments passed in to the current (lexical) function. APPLICABLEP whether or not an item is an applicable function. Returns the thing which is primitively applicable - i.e., strips off ILE and traces down the "real" thing. SUBRIFY Takes an applicable thing, and makes a subr for it; e.g. SI:FSYMEVAL-SUBR for symbols, *:MAKE-SUBR for lambdas. DESUBRIFY The inverse of SUBRIFY, for use by FSYMEVAL and FSYMEVALQ. [??? what do we really need here for argspectrum ???] ARGSPECTRUM if arrgument is applicable, then its argspectrum is a list of three numbers: ( ) is either 0, meaning no &rest argument, or else 1. CLOSURE - A limited FUNARG device which creates a semi-closed environment in which to run a function. Several closures may share all or part of their closure'd environment. Two arguments, first is a "function", second a list of variable names whose special-value cells will be included in the closure. If an item of the list is, rather than a name, a list of the form "(FUNCTION symbol)", then the special function cell name is meant; if it is a list of the form "(LOCAL symbol)", then the local-value cell is meant. Example: (DEFUN GSOGET (EXTRA-TOL) (DECLARE (SPECIAL EXTRA-TOL)) (CLOSURE (FUNCTION (LAMBDA (X) (LET ((EPSILON (TIMES EPSILON EXTRA-TOL))) (SQRT X)))) '(EXTRA-TOL SEQUENCE-RUN))) This would be useful where SQRT is a function which references a free variable EPSILON - each call to GSOGET would then produce a functional object which would "stretch" EPSILON by the amount requested (as the argument EXTRA-TOL); furthermore, the variable SEQUENCE-RUN, which is not otherwise lexically present in the code, is included in the environment of the closure (perhaps because it represents some experimental tag number when the closure is created) There is no requirement that the variables saved in the environment actually be "used". See also FLEXURE below under "SPECIAL FORMS" SI:MAKE-CLOSURE-N N arguments (0 < N < 255.), each a SLINK index, which determines a cell to be included in the closure. It returns an EXTEND, which contains for each argument the link-cell index and the value-cell address of the variable included in the closure. 5.4 Identities FIXNUM-IDENTITY [For maclisp compatiblity, and potential future FLONUM-IDENTITY use in an optimizing numeric compiler] 5.5 For EXTENDed Data - ARRAYs etc. AREF For referencing arrays, e.g. "(AREF 3 5)" ASET For storing into arrays, e.g. "(ASET 3 5)" 5.6 THROW and Error Handling THROW - (THROW ) Both and are evaluated as in normal SUBR control, and a control-chain break-up is initiated, passing along both values; at some higher level, the break-up will be "caught". If the "catching" is by CATCH, then the value of is passed to CATCH; if by CATCHALL, the both values are passed (q.v.). These semantics seem to imply that THROW is a SUBR, but it is so intimately tied up with CATCH that it must be considered a special form and discussed herein. ERRFRAME - If there is an error frame set back up the stack, then this function will fetch the relevant info from it; generally, errors will stack up some info and enter a system handler, which may re-enter user code. ERROR - essentially the same as in MACLSP, but if no correction is to be done, then execute "(*THROW 'SI:ERRSET )". CERROR -- the "Correctible ERROR signaler" just like on the LISPM. FERROR -- as on LISPM. 5.7 PDL and Value Cell hacking SI:PDLDEPTH ( &optional ) - returns an integer indicating how many Q's in the current size of that pdl, ** not including any stack space taken by SI:PDLDEPTH itself ** "" is among REGPDL, SPECPDL "" if null means current one *** to be mini-subr'd *** SI:CLINK () merely gets the nth entry in the SLINK/CLINK; indices are negative for most CLINK entries, positive for SLINK. *** to be open-compiled as a VREF over SI:SLINK-VECTOR *** SI:FIND-SLINK-INDEX ( ) - returns the slink index of the requested cell (from the 4V scheme). If is null, then return null if cell does not already exist; otherwise, create one if not there. "" is a fixnum obtained by viewing the low four bits as encoding one part of the 4V scheme: LOCAL VALUE CANONICAL ADDRESS 0 SPECIAL FUNCTION LINK INDEX 1 8 4 2 1 The low bit must be on, since this function will not return an address. Example: to find SVLI$FOO, which is stored in CL$SVLI_FOO, call "(SI:FIND-SLINK-INDEX 'FOO 11. () )" *** to be mini-subr'd *** SI:CERTIFY-PRIVATE-VALUE-CELL () *** to be mini-subr'd *** SI:SLINKI-EVAL () gets the contents of the "value" cell associated with the link-cell index . SI:CURRENT-ARGFRAME-SUBR-INDEX - no args. By fetching the appropriate slot out of the argframe, a subr can find out what named function started it running (generally, by having a pointer to the subr in the function cell). 6. Special Forms Formerly, SYMBOLs which in LISP programs were used to designate special form handling by the interpreter were called FSUBRs. This means that the normal rule of functional application to arguments, written in a style of functional composition, does not apply, and the program evaluator has to take some special action. In NIL, all symbols representing special forms will be stored in a system-provided hash-table, and the index in that table will be the corresponding index in a table of functions to which the interpreter will dispatch for the "execution" of the special form. (likely, two "address comparisons" will serve to check if a symbol is in the "hash" table). All special forms will be "open-coded" by the compiler, so there is no question of "calling" such a subroutine except by the interpreter when evaluating EXPR programs. SI:SPECIAL-FORMP () returns index into SI:SPECIAL-FORM-FUNCTIONS if is a special form, but null if not. *** open-compiled into address comparison *** SI:SPECIAL-FORM-FUNCTIONS -- a vector of functions corresponding to the special-form located in a special system-supplied table. Below is a listing of all NIL special forms, along with a description of their semantics, in alphabetical order. @DEFINE - Do nothing, much like COMMENT. For use with some of the various cross-reference programs. AND - (AND e1 e2 ... e) The classic! what more need be said. Evaluates e1 to e in order, stopping and returning null if any the values so obtained are null; if all are non-null, returns the value of e. BREAK - As in maclisp CASEQ - (CASEQ ( e11 e12 ... e1) ( e12 e22 ... e2) . . . (> em1 em2 ... em)) Each clause is a list of possibilities for testing against the value of : the test is either EQ in case the clause items (and the value of ) are all SYMBOLs, or all CHARACTERs; or else numeric equality in case the items and value are all FIXNUMs or all FLONUMs or all SMALL-FLONUMs. A clause may be a single SYMBOL, CHARACTER, FIXNUM, FLONUM, or SMALL-FLONUM, in which case it is treated the same as if it were the singleton list of the item; one exception the symbol T, which if appearing as a "clause" means force acceptance. (This is for compatibility with LISPM and MACLISP.) In general, the interpretation is similar to that of a COND whose predicate parts are the aforementioned testings; thus if a match is found at >, and at no earlier clause, then the forms ek1, ek2, ... through ek are evaluated in order and the value of the last one is returned as the value of the CASEQ form. CATCH - (CATCH e1 e2 ... e) Forms e1 through e are evaluated, returning the last as the value of the CATCH, unless a THROW (q.v.) occurs whose tag matches one in the tag-list during the sub-evaluations; then the value of the catch is the value from the THROW. The is obtained by evaluation before any of the ei are evaluated, and may be either a list of symbols (tags), one symbol which is treated like a list of that symbol. {CATCHALL - (CATCHALL e1 e2 ... e) Has same semantics as CATCH, except that if **any** THROW occurs during the sub-evaluations, then the value of the CATCH is obtained by applying the value of (obtained by evaluation before evaluating any of the ei) to the throw value and throw tag. E.g. (CATCHALL '(LAMBDA (TG VAL) ;Note that for some tags, the throw is ; repeated, so that the CATCHALL acts as ; if it in fact ignores that THROW. (COND ((MEMQ TG '(TOPLEVEL BREAK)) (THROW VAL TG)) ((OR STOPP (EQ TG 'FOO)) (THROW VAL 'FOO)) (#T VAL))) (SETUP 25) (RUNLIKE ABAT)) } CATCH-BARRIER - (CATCH-BARRIER e1 e2 ... e) This has the same syntax as CATCH, and more or less the same semantics, but if a thrown tag is not in the tag-list, then the THROW that threw it goes into an unseen-throw-tag error. The idea is that searching does not proceed back up the stack beyond this point; whereas if a tag THROW is not caught by a particular CATCH, then tag searching continues all the way back up to the very stack beginning. COND - (COND ( e11 e12 ... e1) ( e12 e22 ... e2) . . . (> em1 em2 ... em)) Our old standby COND, namely each clause is implicitly an PROGN after the predicate part; and if no predicate is satisfied then the value is null. COMMENT For compatibility with MACLISP; does nothing except return COMMENT. DECLARE - This will be for local declarations of NIL; global declarations will be supported by the EVAL-WHEN feature. Maybe the compiler can make a temporary macro-definition of DECLARE so that top- level DECLAREs will turn themselves into EVAL-WHENs. DEFUN - As in MACLISP, but extended to handle "&OPTIONAL", "&REST", and "&AUX" arguments, as on the LISPM. Furthermore, any slot which is not atomic is taken for "destructuring"; for example: (DEFUN FOO ((A . B) C) ...) is like (DEFUN FOO (G0003 C) (SETQ A (CAR G0003) B (CDR G0003)) ...) DESETQ - Like LET, so that one doesn't have to cons in order to interpret it. Also, LET and DESETQ can share some code. DO - Format to be compatible with MACLISP (DO ...ordinary-prog-body... ) A is one of Same as (). must be SYMBOL () Like a PROG variable ( ) The initial value is computed before ( binding of the DO variables. ) After a pass thru the DO loop, all stepper forms are computed before rebinding any of the vars to them. Thus the initial-value bindings, and stepper-form bindings have the semantics of "parallel" setting. If is null, then the body is executed just once, returning null, with no looping and stepper-form calculations; in fact, it acts just like a PROG. But if is not null, then it is of the form ( ... ) where the value of is the value returned for the DO. If n = 0, ie there is only the predicate, then the nullist is returned. DO-NAMED - as above for DO, but first item immediately following "DO-NAMED" is a (non-null) symbol which is taken as a name for the DO; this has exactly the save effect as a name for a PROG (q.v.) EVAL-WHEN - (EVAL-WHEN ... ) The forms through are evaluated depending on whether the EVAL-WHEN is being evaluated in a context that matches the . Possibile conditions are EVAL Normal evaluating, or load-in of expr code COMPILE Compiler is processing the file, producing a file of output proto-modules. LOAD When a proto-module is being loaded into memory, some load-time evaluation is permitted. FLEXURE - This is similar to CLOSURE, except that all lexically-appearent variables, whether for dynamic (fluid) binding or for strictly local binding, are included in the environment. First arguments (required) is the function; two optional arguments permit excluding some variables (or functions) which otherwise would be included, and including some which otherwise would not. (FLEXURE ) is exclusionary, rather than inclusionary. Another format, (FLEXURE ) permits the inclusion of non-lexically-present names. In each of of these optional arguments, a straight symbol specifies a variable name, and a form "(FUNCTION )" specifies a function name. Example: (DEFUN USELESS (X Y RUN-FLAG) (DECLARE (SPECIAL RUN-FLAG)) (LIST (FLEXURE 'EVAL) (FLEXURE (SEARCH-FUN X) '(X Y) '(SEQUENCE-RUN (FUNCTION RUMBLE))))) will return a list of two "closures", the first of which has in its environment a local (non-fluid binding) X and a local Y, as well as the special variable RUN-FLAG; the second has the two special variables RUN-FLAG and SEQUENCE-RUN, and the one function RUMBLE. [may not be in pilot version of Summer 1981] FSETQ - Like SETQ, but hacs the function cell, instead of the value cell Localness or specialness is determined from context, just as in the handling of variables. FSYMEVALQ - In order to get the function cell (special or lexical, as declaration context indicates -- note that this differs from (FSYMEVAL 'FOO), instead of the value cell. [Is it opening up a can of worms to ask for versions of FSETQ and FSYMEVALQ which, like SI:Fxxx-SUBR, omit the DESUBRIFYing step?] FUNCTION - Unlike Maclisp, this probably cannot be as simple as QUOTE in the interpreter. Nil's interpreter implements lexical scoping, so having (FUNCTION (LAMBDA ...)) return just the LAMBDA will lose the lexical context, causing free variables which in a non-lexical interperter, and in the compiled version of the same code, would otherwise be bound correctly, to be unbound in the Nil interpreter. Thus the evaluation of FUNCTION will probably have to create a lexical closure. There are questions with the SYMBOL case, also: on the Lispm, (FUNCTION FOO) is the same as (FSYMEVAL 'FOO). There are arguments in favor of this implementation, but also arguments in favor of having (FUNCTION FOO) be the same as (QUOTE FOO). Let it simply rest that these questions are undecided for now. GO - (GO ), or (GO ) If is a symbol, go to that tag in **any** lexically surrounding PROG. If it is desired to specify a particular surrrounding PROG, then , a symbol, restricts "go"ing to the PROG with the identification (q.v.). In NIL, there will be no "computed" GO; instead, use CASEQ with GO's at the end of each clause. LET - This will act just as in MACLISP. Briefly, (LET ( (A 1) B (C 2) ) ...) evaluates like ((LAMBDA (A B C) ...) 1 () 2) In addition, the variable positions are "destructured" as in DESETQ: if at a place where a variable would normally be found, there is an S-expression (list or vector), then the expansion CARs and CDRs (VREFs) the argument in order to bind the symbols at the fringe of the S-expression to the corresponding car-cdr (vref) extraction of the argument. E.g., (LET ( ((A (B (() () D ()) C)) (GRUMBLE)) ) ...) expands, modulo a little compression of CAR/CDRs, into ((LAMBDA (G0005 C D G0006 B A) (SETQ A (CAR G0005)) (SETQ G0005 (CADR G0005)) (SETQ B (CAR G0005)) (SETQ G0005 (CDR G0005)) (SETQ G0006 (CDDAR G0005)) (SETQ D (CAR G0006)) (SETQ C (CADR G0005)) ...) (GRUMBLE) () () () () () ) LAMBDA - Well, it wouldn't be LISP without lambda, would it? The variables list is generalized to permit three key-words &OPTIONAL &REST &AUX following the LISPM syntax. Although this generality does not make sense in the context of an explicit lambda-application, it extends the flexibility of defining functions. E.g. (DEFUN FOO (R1 R2 &optional A (B ) (C (LIST R1 B)) &rest W &aux TEM (FLAG (COND (W R1) ('T R2))) ) . . . ) means that at least two arguments are required in any usage of FOO, which are bound to the variables R1 and R2; and (up to) the next three arguments will be bound to the variables A, B, and C; any further arguments passed will be placed in an VECTOR to which the variable W will be bound. The assignment of values for the &OPTIONAL and &AUX variables (A, B, C, TEM and FLAG) proceeds in a left-to-right fashion, with default computations shown for B and C in case there are not enough arguments passed to fill out all the &OPTIONALs. &AUX variables are never bound to input arguments, but are merely a convenient way to get some PROG variables (possibly with initializations). Note that the "later" &OPTIONAL and &AUX variables may make use of the bindings the "earlier" variables, as the example, with C and FLAG, shows. See also the section below on the semantics of binding and unbinding value cells and value-link cells. (The same mechanism holds for function cells and function-link cells.) [Some day we need to discuss the use of the keywords &special, &lexical, &function, and &value...] [The question of just what (LAMBDA ...) evaluates to is still open. Probably this will be the same as (FLEXURE (LAMBDA ...)) or (FUNCTION (LAMBDA ...)).] MACRO - As in MACLISP, a primitive way to define macros. MAPF - (MAPF ... ) This is an attempt to generalize all the various mappers by having the first two arguments specify the various options. *** These first two items are not evaluated, but the remaining arguments are evaluated just as in MACLISP. must be among {LIST, NCONC, PROJ1, VECTOR, STRING, BITS, +, +$} is a list of symbols which are source-descriptors; a single symbol is treated like an infinite list of that symbol. The descriptors are among {LIST, CAR, VECTOR, STRING, BITS, 1+, 1-, 1+$, 1-$, CONSTANT} should evaluate to a function of n arguments, and ... evaluate to the argument sources for The meaning of the is: LIST Return a LIST of all the successive results of the application of NCONC Same as LIST, but as if NCONC were applied to the result, flattening it by one level. PROJ1 Return the value of , as MAPC would. VECTOR Return a VECTOR of all the successive results of the application of STRING The result of each application must be a CHARACTER - Return, then, the STRING of all those CHARACTERs. BITS The result of each application must be either 0 or 1 - the resultant 0's and 1's are packed into a BITS. +, +$ Return the numerical sum of all outputs. "+" specifies that they will all be FIXNUMs, "+" for FLONUMs. The meaning of the is: LIST The argument source is a list, which is successivly CDR'd after successive applications. CAR Same as LIST, except CAR of the list is given as the argument to VECTOR The successive items of a VECTOR are given STRING The successive characters of a STRING are given BITS The successive bits (0's or 1's) of a BITS are given 1+, 1+$ The argument source is a FIXNUM (or FLONUM in the "1+$" case) which is successively incremented by 1. 1-, 1-$ Same as "1+" case, but is decremented by 1. CONSTANT The argument source is repeatedly given, unmodified as the corresponding argument to ; it ** DOES NOT ** mean that the type of the source is a constant, but only that it is not "stepped". Right now, not all the combinations are worked out, but these will certainly be installed initially: (MAP FOO . rst) ==> (MAPF 'PROJ1 'LIST FOO . rst) (MAPLIST FOO . rst) ==> (MAPF 'LIST 'LIST FOO . rst) (MAPC FOO . rst) ==> (MAPF 'PROJ1 'CAR FOO . rst) (MAPCAR FOO . rst) ==> (MAPF 'LIST 'CAR FOO . rst) (MAPCON FOO . rst) ==> (MAPF 'NCONC 'LIST FOO . rst) (MAPCAN FOO . rst) ==> (MAPF 'NCONC 'CAR FOO . rst) (MAPVECTOR FOO . rst) ==> (MAPF 'VECTOR 'VECTOR FOO . rst) MAPATOMS - arguments are functional: ( &optional ( PACKAGE) ( &optional ( PACKAGE)) MULTIPLE-VALUE Call a function which gives back multiple return values; they are "spread" into the list of variables provided. E.g., (MULTIPLE-VALUE (R THETA) (FIND-POLAR-POSITION SHIP)) The routine FIND-POLAR-POSITION must exit, or return, with a VALUES of at least two values -- any more than two are ingored. Currently, there is a limitation of eight on the number of multiple return values, and the form appearing as second "arg" to the MULTIPLE-VALUE must have the last thing evaluated be a call to a function which really does return multiple values. for example, (MULTIPLE-VALUE (X Y) (PROG1 (FIND-POLAR-POSITION SHIP) (FROB))) would be invalid. MULTIPLE-VALUE-BIND -- like MULTIPLE-VALUE, except that a "binding-contour" is created for all the variables mentioned, rather than merely SETQ'ing them. Also, additional forms follow just as in a LET construct. E.g. (MULTIPLE-VALUE-BIND (R THETA) (FIND-POLAR-POSITION SHIP) (IF (< R 0) (FERROR () "This can't happen")) (SETQ R (SQRT R) ;Do a torsion twist on THETA (TIMES THETA THETA)) ; the coordinates (COGITATE-UPON THETA) (LIST R THETA)) will return the list of "twisted" and cogitated co-ordinates. MULTIPLE-VALUE-LIST -- like MULTIPLE-VALUE, it initiates a call to some functions which returns multiple values, but instead of "spreading" them out in some variables, it makes a list of them. From the example above, (MULTIPLE-VALUE-LIST (FIND-POLAR-POSITION SHIP)) returns a list such as would be returned by (PROG2 (MULTIPLE-VALUE (R THETA) (FIND-POLAR-POSITION SHIP)) (LIST R THETA)) MULTIPLE-VALUE-RETURN -- this is basically like RETURN, for use within a PROG, but the "multiple values" obtained from the calculation of the argument to MULTIPLE-VALUE-RETURN are directly passed back as the "multiple values" of the function containg the PROG. OR - (OR e1 e2 ... e) The classic! what more need be said. Returns the first non-null value, by evaluating in order e1 to e until some non-null value is obtained; if all values are null, the returns null. PROG1 - (PROG1 e1 e2 ... e) evaluates e1 through e in order, and returns the value of e1. PROG2 - (PROG2 e1 e2 ... e) evaluates e1 through e in order, and returns the value of e2. PROGN - (PROGN e1 e2 ... e) evaluates e1 through e in order, returning the value of e. PROG - (PROG . . . prog-body-including-tags . . . ) If a (non-null) symbol occurs before the , then it is taken as a local (lexical) name for that PROG. Thus RETURN-FROM can specify which (lexical) prog from which to return, and GO can do the same. However, the prog name "T" means that no RETURN will exit that PROG - only (RETURN-FROM T ...) will do so - and no nameless GO will go to tags in such a prog. If a PROG "falls off the end", it returns null. PROGV - As in MACLISP, (PROGV e1 e2 ... e) where the and are evaluated, and the corresponding bindings made, and the rest for the form is treated like a PROGN. If is longer than , the extra variables are bound to a distinguished constant which will cause an error upon access ("unbound variable"); nothing special happens in the reverse case when is shorter than . PSETQ - "parallel" SETQ. The "set"ings of the variables occurs after all the evaluations are done. Thus (SETQ A 'FOO B (LIST A)) gives B the value FOO; but in an environment where A is bound to BAR, (PSETQ A 'FOO B (LIST A)) gives B the value BAR. QUOTE - (QUOTE ) The classic evaluation-stopper. Returns directly. RETURN - (RETURN ) A lexical break-up is done on the immediately surrounding PROG, (unless it is a named prog with name "T") and the value of is returned as the value of the PROG. Multiple values may also be returned from a PROG (which must be in a lexical position of being the return value of the function in which it appears). (RETURN ) returns three values. RETURN-LIST -- (RETURN-LIST l) is essentially just (MULTIPLE-VALUE-RETURN (VALUES-LIST l)) RETURN-FROM - (RETURN-FROM ) Essentially the same as RETURN, but the PROG may be any lexically surrounding one. The one of reference is the one with identifying it. As with RETURN, RETURN-FROM may return multiple values: (RETURN ) returns three values. SEND - Not really a special form, but has a special enough position in the language that it should be mentioned here. This is the functional which signalls the "message-passing" semantics of object-oriented programming. Thus if is an object of some CLASS (or FLAVOR), then (SEND 'LIFT-PEN 3.5) would send it the "LIFT-PEN" message along with the argument 3.5. The LISPM has been using FUNCALL for this purpose. SETQ - Standard primitive for updating the value of a program variable. TYPECASEQ - (TYPECASEQ ( e11 e12 ... e1) ( e12 e22 ... e2) . . . (> em1 em2 ... em)) This is essentially a CASEQ on the PTR-TYPEP of - the reason such a separate form exists is that the compiler may optimize it differently. The items in the clauses are symbolic names of the various primitive types. (PTR-TYPEP, "pointer-typep", differs from TYPEP in that no extra processing on the type field is done - only the type-bits from the pointer are extracted and converted into the symbolic name for that type. UNWIND-PROTECT - (UNWIND-PROTECT u1 u2 ... u) The form will be evaluated, but if any valid THROW occurs therein (ie, there is a CATCH above the THROW with a matching tag), then the break-up processor must cause the evaluation, in order, of u1 through u in the environment that obtains by first unwinding to the stack point of the UNWIND-PROTECT; then the unwinding may continue. If there is no throwing, then the value will be that obtained from , but the forms u1 through u will be evaluated also. The intent is that the operation of will do some things that need to be undone after sucessful completion, but which can not be undone merely by lambda-binding (eg, closing an opened file). Thus any aborting of the evaluation of will not leave undesired states hanging around. VALUES -- This is the basic way to indicate multiple return values. (Actually, an internal "multiple return values" vector is set up.) To continue the example mentioned under MULTIPLE-VALUE and under MULTIPLE-VALUE-LIST, we could define (DEFUN FIND-POLAR-POSITION (VEHICLE &AUX X Y) (SETQ X (GET-X-COORDINATE VEHICLE) Y (GET-Y-COORDINATE VEHICLE)) (VALUES (SQRT (PLUS (SQUARE X) (SQUARE Y))) (ARCTAN X Y))) Thus, as many arguments as a call to VALUES seems to have, then that many values will be (multiply) returned from the function, by installing them in the canonical place for SUBR's to return values. VALUES-LIST -- takes one argument, a LIST or VECTOR, and returns all the elements of it as multiple values. 7. STREAM Usage functions INCH (&optional ( INFILE) ( *:EOF-CHARACTER)) INCHPEEK (&optional ( INFILE) ( *:EOF-CHARACTER)) "Peeking" does not remove the object from the stream OUCH ( &optional ( OUTFILES)) INSTR ( &optional ( INFILE)) A kind of "block" call to INCH - if is a fixnum, then a new string of that length is created, and filled with characters coming from the ; if it is a string, then it is destructively filled. OUSTR ( &optional ( OUTFILES) ( 0) ( (- (string-length ) ))) A kind of "block" call to OUCH - all the characters of , beginning at index and going for a total of characters, are outputted to the . PUTBACK ( ) may be either SINGLE, meaning that the single item is to be put back into the stream, as if in a "fifo" queue. If is BUFFERKEY, then a block of "putbacks" is to be done, where is a 3-element vector used as a buffer "key", which is put as a unit into the stream. A buffer key is like: #( ) The effect on the stream would be similar to what (DO I (1- I) (< I ) (PUTBACK 'SINGLE (ELT I) ) would do; however, the 0'th element of the buffer is actually incremented each time that an element is taken out of the part, to reflect the fact that the stream has been advanced by one unit. A third alternative for is STREAM, in which case is another stream which is inserted "in front of" the remainder of the argument ; when this "inserted" stream drys up (by giving out the EOF signal?), then the advancing of the original stream stuff continues. {STREAMIFY-STRINGS Generates a stream which is a source of characters from the given input strings, finally followed by an eof-character. (requests for more should be an error). } {STREAMIFY-CHARACTER-SINK Generates a stream into which you can write characters and which will regurgitate out, on demand, a string which is the concatenation of all the written chars. } 8. SI:TOPLEVEL-FORM -- a variable which (as in maclisp) holds a form to be EVAL'd inplace of the normal READ-EVAL-PRINT at toplevel. SI:BREAK-FORM -- again, as in maclisp, the replacement for BREAK loops. SI:FUNCALL-EXTRA-NULLS (SI:FUNCALL-EXTRA-NULLS FUN ... N) is the same as (FUNCALL FUN ... ,,,) where ,,, is N ()'s. This is how the interpreter gets stack space for storing argument values. Example: (SI:FUNCALL-EXTRA-NULLS FOO X 4) is the same as (FUNCALL FOO X () () () () ). LEXPR-FUNCALL As on the LISPM, (LEXPR-FUNCALL FUN ... SEQ) spreads the last sequence argument as the tail of the sequence of arguments to be passed to the function. LEXPR-SEND This is to SEND, as LEXPR-FUNCALL is to FUNCALL. LEXPR-SEND-AS This is to SEND-AS, as LEXPR-FUNCALL is to FUNCALL. 9. Co-Routine Capabilities [As of March 1981, this hasn't been developed yet]