Friday, Dec 5,1980 LQ+5D.18H.52M.7S. LISP 2057 - JonL - 1) Seven items of previous LISP RECENT (dated Oct 28,1980) have been emended: 1a) Documentation available for (STATUS USRHUNK) etc. 1b) Both " and # are set up in the initial environment as readmacros. 1c) CATCH and THROW are now autoloading macros from LISP:MLMAC. 1d) Warnings about MacLISP incompatibilites with NIL, and how to overcome the most common ones. 1e) +INTERNAL-PERMUTIBLE-P is an autoloading subr from LISP:MACAID. 1f) PAIRP and FBOUNDP are now initial system subrs; (PAIRP x) is the same as (EQ (TYPEP x) 'LIST), and (FBOUNDP x) is non-null iff x is a symbol with a functional "property". 1g) Several "internal" subrs exist to augment compiled code: *LDB, *DPB, *LOAD-BYTE, and *DEPOSIT-BYTE 1h) At user level, the function's name is FIND-METHOD (rather than SI:...) Also the names now are SI:MAKE-EXTEND, SI:EXTEND, SI:EXTEND-LENGTH, SI:XREF, and SI:XSET rather than the *:<...> versions. [more exposition below] 2) ** Incompatible change**" ARRAYDIMS called on a "NIL" type array will return (NIL ...) instead of (T ...) as formerly. New Functions, as on the LISPMachine: (ARRAY-DIMENSION-N <i> <array>) gets i'th dimension number of <array> (ARRAY-/#-DIMS <array>) gets the number of dimensions (ARRAY-TYPE <array>) is the same as (CAR (ARRAYDIMS <array>)) 3) DEFVST "macros" now all share code to minimize space. Interpretive access to structure components checks the type of the struct. New macros STRUCT-LET and STRUCT-SETF have featureful convience. [more exposition below] 4) Three new functions autoloadable from DEFMAX file: MACROEXPAND-1*M is a multiple-value returning subr of 1 arg called like (MSETQ-CALL (X ?) (MACROEXPAND-1*M Y)) +INTERNAL-TRY-AUTOLOADP a subr of 1 argument autoloadable from DEFMAX, tries to autoload a function's autoload file, if it has one. FLUSH-MACROMEMOS -- to flush the macromemo "cache"; and some new settings for the switch DEFMACRO-DISPLACE-CALL [more exposition below] 5) Some more LISPM-compatible autoloadable facilities, and error facilities. CERROR, FERROR, and ERROR-RESTART as on LISPM, from LISP:CERROR file. also a new subr +INTERNAL-LOSSAGE of three args, for use when an "unreasonable" point is reached. Y-OR-N-P from LISP:YESNOP file, for interactive querying. New "error-checking" routines from LISP:ERRCK file Documentation below for CHECK-TYPE and CHECK-SUBSEQUENCE. [more exposition below] 6) SXHASH may dynamically be adjusted to be more anti-symmetric [more exposition below] 7) LOOP and DEFINE-LOOP-PATH are now autoloading See the documentation file .INFO.;LISP LOOP, or the LCS Technical Report "LOOP Iteration Macro" MIT/LCS/TM-169. 8) DELASSQ, a new LSUBR of 2 or three args, is a cross between DELQ and ASSQ (DELASSQ 'A '((A . 1) (B . 2) (A . 3))) ==> ( (B . 2) ) but remember, that like DELQ, rplacds are being done. 9) #(...) notation is usable now whenever the VECTOR package is loaded; the print method for vectors generatates this syntax, and # will read it. #B is usabe when the BITS package is loaded; #T is usable when the EXTEND packages is loaded (any new NIL data type usage will load EXTEND). In MacLISP, #T is synonymous with T. #*400000000* now reads in correctly. 10) Four new internal subrs, to help with various STRING packages: +INTERNAL-CHAR-N +INTERNAL-RPLACHAR-N +INTERNAL-STRING-WORD-N +INTERNAL-SET-STRING-WORD-N [more exposition below] 11) Value of the variable PURCOPY is a list of things which the PURCOPY function should not actually copy. For example, CLASS objects should never be moved, and hence can't be PURCOPYied. 12) The function SQOZ/| is no longer part of the basic system -- it is defined in the GETMIDASOP file. For TWENEX users: X1) Twenex MacLISP offers a parsable "init file" facility now CURSORPOS and "rubout" of TTY input now work on systems with VTS [more exposition below] ____________________________________________________________________________ 1) Six items of previous LISP recent have been emmended significantly: 1a) Documentation available for (STATUS USRHUNK) etc. 1b) Both " and # are set up in the initial environment as readmacros. 1c) CATCH and THROW are now autoloading macros from LISP:MLMAC. 1d) Warnings about MacLISP incompatibilites with NIL, and how to overcome the most common ones. 1e) +INTERNAL-PERMUTIBLE-P is an autoloading subr from LISP:MACAID. 1f) PAIRP and FBOUNDP are now initial system subrs; (PAIRP x) is the same as (EQ (TYPEP x) 'LIST), and (FBOUNDP x) is non-null iff x is a symbol with a functional "property". 1g) Several "internal" subrs exist to augment compiled code: *LDB, *DPB, *LOAD-BYTE, and *DEPOSIT-BYTE 1h) At user level, the function's name is FIND-METHOD (rather than SI:...) Also the names now are SI:MAKE-EXTEND, SI:EXTEND, SI:EXTEND-LENGTH, SI:XREF, and SI:XSET rather than the *:<...> versions. 1a) Four new STATUS calls permit hooks into system functions, when given hunks as arguments -- used as the basis of the EXTEND system, as the LISP RECENT note of Oct 28,1980, item 3. See the documentation file ".INFO.;LISP SEND" on ITS systems and "LISP:SEND.DOC" on TOPS-10/20 systems. See also ".INFO.;LISP EXTEND" on ITS systems and "LISP:EXTEND.DOC" TOPS-10/20 systems. (SSTATUS USRHUNK <function>) specifies the "user hunk" predicate, which determines whether to "hook into" a user-provided definition for some system facility, or to treat the data strictly as a hunk. (SSTATUS SENDI <function>) specifies a "SEND" interpreter -- <function> is invoked in order to send a "message" to a "user hunk", when a hunk which passes the "usrhunk" test is given as argument to any of EQUAL SUBST PURCOPY EVAL PRINT EXPLODE FLATSIZE ALPHALESSP SAMEPNAMEP NAMESTRING SXHASH or to any of the following out-of-core facilities GFLATSIZE SPRINT USERATOMS-HOOK DESCRIBE WHICH-OPERATIONS See the file LISP:SEND.DOC (or .INFO.;LISP SEND on ITS systems) (SSTATUS CALLI <call-interpreter>) specifies a "transfer function" to be used when when a "user hunk" is FUNCALL'd. This is a hand-coded substitute for the IAPPLY internal LISP routine. See the file LISP:SEND.DOC (or .INFO.;LISP SEND on ITS systems) (SSTATUS VECTOR `(<vectorp> <vector-length> <vref>)) specifies the functions for LEXPR-FUNCALL to use for determining if the argument to be spread is a vector, determining its length, and accessing its elements. This allows one to do (LEXPR-FUNCALL #'LIST 'A 'B #(C D E)), for example, yielding (A B C D E). 1b) Both " and # are set up in the initial environment as readmacros. # still requires the file LISP:SHARPM.FASL, but the default function for " will still create a pseudo-string (un-intern'd symbol) rather than requiring the full STRING support package; loading in the file LISP:STRING.FASL will do a SETSYNTAX on " to get real STRINGs. 1c) CATCH and THROW will expand according to the old syntax, but someday this may change; currently (CATCH exp tag) ==> (*CATCH 'tag exp) and similarly for THROW. 1d) A MacLISP pre-loaded with most of the NIL facilities, is obtained by running the subsystem NILAID (NILAID^K on ITS systems); this is more- or-less a union of the MacLISP and NIL facilities, but one must remember the following incompatibilities: (1) The nullist is identified with the symbol |NIL| in MacLISP, but has a unique new data type in NIL, so NIL code which depends on the non-symbolness of the nullist wil lose -- check your usages of SYMBOLP. (2) The function atom is "false" for hunks in MacLISP, and thus is "false" for STRINGs, VECTORs and all other data embedded into the USRHUNK feature, so it would be more compatible to use (PAIRP X) rather than (NOT (ATOM X)), if you want to distinguish cons cells. The function LISTP is equivalent to (OR (NULL X) (PAIRP X)). (3) FBOUNDP in NIL will only return "true" or "false" -- namely #T or () -- but in MacLISP, it returns the information from the GETL function, when "true"; thus there is more information in the MacLISP result. Since there are no real SUBR objects in MacLISP, the result of FSYMEVAL will not be compatible; but used in limited ways, it will work, e.g. (FSET 'MUMBLE (FSYMEVAL x)). (4) CATCH (and THROW) in MacLISP still has the old semantics, but in NIL and NILAID it has the new, namely the same as *CATCH (and *THROW); use the * versions and be safe. (5) CASEQ will not work on CHARACTER objects in MacLISP (6) DEFUN will not keep track of the "documentation" string. (7) No real package system is set up -- so GET-PNAME merely returns the portion of a pname-string following the first ":" (if any). 1e) +INTERNAL-PERMUTIBLE-P is an autoloading subr from LISP:MACAID. (+INTERNAL-PERMUTIBLE-P l) is non-() iff the forms on the list 'l' may be EVAL'd in any order, and get the same results/effects. For example (5 (MUMBLE X)) is permutible, since nothing which happens inside MUMLBE can affect the value of 5; but (X (RPLACA Y)) is not permutible, since X may point to a list which is updated by the RPLACA. 1g) Currently, the compiler may turn LDB into a call to the internal subr *LDB, which has args the same as LDB except the "ppss" arg has been lsh'd by 30. places (also, no type-checking is done on the args). Similar remarks apply for *DPB, *LOAD-BYTE, and *DEPOSIT-BYTE. Another alternative is that it may turn LDB into a LSH followed by a LOGIOR. Someday, it may open-code these into an actual pdp10 LDB. 1h) For a certain amount of time, the EXTEND file will probably also put macro definitions on *:<foo> to become SI:<foo>, the names EXTEND, EXTEND-LENGTH, MAKE-EXTEND, XREF, and XSET. 3) DEFVST "macros" now all share code to minimize space. Interpretive access to structure components checks the type of the struct. New macros STRUCT-LET and STRUCT-SETF have featureful convience. Accessor macros for a structure generally gave rise to a modest amount of code, but a new scheme has just been implemented in which all such macros use precisely one function; each accessor macro, or constructor macro, needs only two properties on its property list -- a MACRO property pointing the the single expander function, and a small SELECTOR or CONSTRUCTOR property. Similarly, the output of the DEFVST macro is significantly smaller, due to calling an initialization function which will be autoloaded when needed, rather than expanding out lots of lisp code. In interpreter usages of selector "macros" (in *RSET mode) the code will certify that a selector macro is being applied to a structure of the correct type; if not, a proceedable error will be performed. STRUCT-LET and STRUCT-SETF have been devised to facilitate multiple settings, or gettings, of structure components. For example, suppose DESK is a strucure with four components, defined like (DEFVST DESK A B C D), and suppose that <grey> is a DESK possibly created by (SETQ <grey> (CONS-A-DESK C 'FULL)). Then (STRUCT-SETF (DESK <grey>) (A 'PAPER) (B 25.) (D (folders))) expands into a short program to fill in the DESK-A, DESK-B, and DESK-D components of <grey>. Also (STRUCT-LET (DESK <grey>) (A (D) (MIDDLE-DRAWER B)) ... do-some-work ... ) would lambda-bind the variables A, D, and MIDDLE-DRAWER respectively to the DESK-A, DESK-D and DESK-B components of <grey> and then do further work, indicated like the implicit progn of a LET. The code for DEFVST has been split up into three files. The new file DEFVSX (and auxillary file for structure usage) contains various common selector-macro expansion functions, constructor functions, etc; the file DEFVST now contains only the DEFVST macro itself, and all the various "methods" applicable to objects in the class STRUCT-CLASS. It should be possible to have a file of code which defines and uses structures, but which when compiled needs neither file loaded; the DEFVSX file would be loaded if in the resultant object environment it becomes necessary to expand any accessor/constructor macros at runtime. One needn't have DEFVST loaded except when compiling, or when wanting the more refined methods available through the EXTEND class hierarchy (as opposed to treating structures merely as hunks). The third file is DEFVSY, and is loaded whenever the output of DEFVST, in the runtime environment, actually is constructing up new instances of a defined structure. DEFVSY takes about 250. words of binary program space, and thus will probably "pay for itself" in terms of the code saved in the CONS-A-foo expansions. DEFVSX takes about 590.; and DEFVST takes about 1040. DEFVST created structures interface into the MacLISP (and NIL) CLASS system, but they do not load it if not already loaded. Structure instances created before the CLASS system is loaded will leave around a "skeleton" class, which the cooperating EXTEND file will "flesh out" when it is loaded. Typical usage of structures should cause no overhead in the run-time environment except possibly the DEFVSY file and a few "skeletal" classes. 4) Three new functions autoloadable from DEFMAX file: MACROEXPAND-1*M is a multiple-value returning subr of 1 arg called like (MSETQ-CALL (X ?) (MACROEXPAND-1*M Y)) +INTERNAL-TRY-AUTOLOADP a subr of 1 argument autoloadable from DEFMAX, tries to autoload a function's autoload file, if it has one. FLUSH-MACROMEMOS -- to flush the macromemo "cache"; and some new settings for the switch DEFMACRO-DISPLACE-CALL MACROEXPAND-1*M does one step in the macroexpansion of its argument, and returns that expansion (or the original form if it didn't represent a macro call, and also returns a flag, T or (), telling whether or not any expansion was done. The argument to +INTERNAL-TRY-AUTOLOADP should be a symbol; it tries to load in the file from the autoload property of its argument, if there is one. Non-null return value iff it did the loading. A user may request flushing all the "cacheings" for expansions of a macro FOO by doing (FLUSH-MACROMEMOS 'FOO () ), and may flush all "cacheings" by (FLUSH-MACROMEMOS () () ). Here, the word "flush" really means "invalidate", and generally nothing is done during "flushing" except updating some validation counter. This problem may be more thoroughly described by the following explanation. When DEFMACRO is used to define a macro, the value of thes witch DEFMACRO-DISPLACE-CALL determines whether the original cell which started out with a macro call will be displaced, either by the result of the macro expansion directly, or by an "expanded" marker which acts like a "cache" for the expansion; a third alternative is not to displace, but to enter into a hash table. A problem arises in trying to determine when to invalidate such "cache" or hash-table entries; clearly, such an invalidating must be done when the particular macro is redefined, but many macros call the function MACROEXPAND, and hence the value of their expansion would likely be changed by redefining some other (totally random?) macro. As a step in solving this problem, the durrent DEFMAX code recognized four conditions -- A "cached" or hash-tabled expansion which becomes invalid: 1) Only when the particular macro which gave rise to it is redefined. 2) When any macro is re-defined (including the one for which the expansions itself was done). All formerly compiled DEFMACROs will currently fall into this category. 3) When a new structure is defined (by means of DEFVST); this would be the case for a generalized structure-hacking macro such as STRUCT-LET, which utilizes information about a structure being decomposed, as well as any sub-macroexpansions. 4) When the user requests that all "cacheings" for this particular macro, say FOO, be flushed -- this can now be done by (FLUSH-MACROMEMOS 'FOO () ) -- or when the user requests that all "cacheings" or hash-tableings be invalidated; this can now be done by (FLUSH-MACROMEMOS () () ). Currently, a test of the switch DEFMACRO-DISPLACE-CALL at performed at macro-definition time to determine which one of 1-3 will be the case: (EQ DEFMACRO-DISPLACE-CALL MACROEXPAND) -- case 1 (EQ DEFMACRO-DISPLACE-CALL '|defvst-construction/||) -- case 3 (NULL DEFMACRO-DISPLACE-CALL) -- no "cacheing" (EQ DEFMACRO-DISPLACE-CALL 'DEFMACRO-DISPLACE) -- direct displace any other value for DEFMACRO-DISPLACE-CALL -- case 2 Note that the value which selects case 1 is not the (interned) symbol MACROEXPANDED, but its value as a global variable; this is a "safety" feature so that one will be less likely to get case 1 accidentally. Also note that the second argument to FLUSH-MACROMEMOS, if not null, is a signal to set up the right kind of flusher: case 1 -- 'FLUSH-MACROMEMOS case 2 -- value of MACROEXPEND case 3 -- '|defvst-construction/|| 5) Some more LISPM-compatible autoloadable facilities, and error facilities. CERROR, FERROR, and ERROR-RESTART as on LISPM, from LISP:CERROR file. also a new subr +INTERNAL-LOSSAGE of three args, for use when an "unreasonable" point is reached. Y-OR-N-P from LISP:YESNOP file, for interactive querying. New "error-checking" routines from LISP:ERRCK file Documentation below for CHECK-TYPE and CHECK-SUBSEQUENCE. Only CHECK-TYPE, CHECK-SUBSEQUENCE and +INTERNAL-LOSSAGE aren't documented in the LISPM manual. The first two are macros which produce code calling some internal subrs. CHECK-TYPE takes a variable name (which it "quotes"), a function usable as a type-testing predicate, and a symbol naming the routine which wants the test done. CHECK-SUBSEQUENCE sets up a multiple return value call and thus wants a list of variable names (again "unquoted"), the name of a sequence type such as LIST, VECTOR, STRING or BITS (or null which means any "sequence" is acceptable), and the name of the routine which wants the test done. In each case, the macro produces code to pass the "variables" to the internal checker, and to setq them to the possibly-corrected return values; if the type of the main argument isn't correct, a :WRONG-TYPE-ARGUMENT condition is signalled to CERROR, and the corresponding variable is set to the returned value; similarly, if the subsequence designated by the two more variables for "start index" and "number of items" doesn't lie within the main argument, then a :INCONSISTENT-ARGUMENTS condition is signalled. Examples: (CHECK-TYPE X #'FLONUMP 'Hooperbylic-SIN) (CHECK-SUBSEQUENCE (IN-STRING 1ST-CHAR-INDEX NCHARS) 'STRING 'MY-DOIT) The "number of items" variable may be written as (), in which case the check is merely that the index is valid for the sequence; also, it may be calculated up by the internal routine to coincide with the end of the sequence, by passing an optional 5th arg of (). E.g. (CHECK-SUBSEQUENCE (IN-STRING 1ST-CHAR-INDEX HAUMANY) 'STRING 'MY-DOIT () () ) would have one effect like (SETQ HAUMANY (- (STRING-LENGTH IN-STRING) 1ST-CHAR-INDEX)) +INTERNAL-LOSSAGE is for use when system code is admittedly incomplete, or some unfathomable point has been reached. (+INTERNAL-LOSSAGE <msg> <fun> <datum>) will print a message identifying this point, and run a FAIL-ACT error. <msg> should be an identifier, and <fun> should be the name of the function which is complaining; <datum> if non-() may be an associated piece of data. 6) SXHASH may dynamically be adjusted to be more anti-symmetric It seems that most persons are in favor of a change in the SXHASH algorithm which would break its current symmetric behaviour on lists; as the consequences of making this change are rather light, we offer a status call which will dynamically do it; but the initial setting is still the old way. Someday soon, we may set the default state to be this new anti-symmetric version. The consequences of having two different sxhash'ers for lists are primarily that extra space may be taken when loading in previously compiled files, or when using the EXPR-HASH feature; thus the change-over will likely be co-ordinated with a massive re-compilation of all system FASL files, and probably all MACSYMA files. (SSTATUS SXHASH 'T), the current default, causes SXHASH to maintain compatibility with the algorithm prior to the date Nov 3, 1980; (SSTATUS SXHASH () ) activates the new alogrithm (defun SXHASH-FOR-LIST (x) (+ (rot (sxhash (car x)) 11.) (rot (sxhash (cdr x)) 7))) Note that the use of an output from sxhash should be such that "all bits are considered". For example, if you want to reduce the range further to something less than the 36-bit 2's complement number that comes out, don't just take the low 18. bits or something like that, but take the remainder upon division by a suitable prime. 10) Four new internal subrs, to help with various STRING packages: +INTERNAL-CHAR-N +INTERNAL-RPLACHAR-N +INTERNAL-STRING-WORD-N +INTERNAL-SET-STRING-WORD-N The first two are interrupt-protected, non-checking versions of CHAR-N and RPLACHAR-N; the second two are similar, but deal with PDP10 words rather than characters. STRAUX (the STRing AUXillary file) will guarantee that these functions exist, either by noting their presence in the lisp system, or by supplying a somewhat-less-than-perfect version itself. X1) Twenex MacLISP offers a parsable "init file" facility now CURSORPOS and "rubout" of TTY input now work on systems with VTS As with MacLISP other on operating-systems, a space right after the subsystem name causes supression of the init facility. Thus, @MACLISP<cr> ;gets the default, LISP.INI, if it exists @MACLISP<space><cr> ;stops the search for an init file. @MACLISP FOO.BAR ;gets FOO.BAR as a LISP.INI file TOPS-20 systems may soon get the Virtual Terminal Service developed by Mike Travers at MIT-XX (now with Foonly); MacLISP uses it to achieve CURSORPOS and a "rubout" facililty for type-in