rAv5L8t_rE&|-K1US 0"K+0/'0@S5I46]?$P?WXr],QVu0ie0AzhH3M9WoeOxV t3M90A$DHie,F{t3M9Coom4t3M90YDD(rnsZlt]}\S:5pY?1RP3 0+ $$$$$$$$$$$$$$$ ANNOUNCING THE ONE, THE ONLY $$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$ >>> BIBOP LISP <<< $$$$$$$$$$$$$$$ December 1973; updated March 1974 The (in)famous "Bibop" (pronounced "bee-bop") LISP scheme has been available for some time now and seems to be more or less reliable. Bibop means "BIg Bag Of Pages", a reference to the method of memory management used to take advantage of the memory paging features of ITS. The average LISP user should not be greatly affected in converting to this new LISP (which very eventually will become the standard LISP, say in a few months). This document is divided into three sections: I. What the average user will need to know. This section is very short (about four pages) and should be read by everyone who wants to use Bibop LISP. II. What sophisticated users (e.g. those who construct and dump systems like MACSYMA and CONNIVER) will need to know. This section details general storage strategies and other features of Bibop, and describes at length how to exploit them. III. What only LISP system hackers and the insanely curious will need to know. This section describes some of the internal workings of Bibop LISP, and is intended primarily as an aid to LISP system hackers. Hopefully most people will need to read only the first section to use Bibop successfully. Much effort has been expended to keep Bibop and non-Bibop LISPs compatible. In particular, if LISP code written for non-Bibop LISP also works "as is" in Bibop LISP, then so will the corresponding LAP and FASL files; that is, the compiler output is completely compatible (and will be kept so). Unless you must alter source code for Bibop LISP, there is no need to recompile. I apologize in advance for the confusion this document will undoubtedly cause. Questions, comments, and complaints may be registered by saying :BUG BIBOP ^C or :FEATURE BIBOP ^C to DDT on either the Mathlab (ML) or the AI PDP-10. Good luck! -- Guy Steele (GLS) Bibop LISP - Section I. - For the Average LISP User - page 2 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $$$$$ I. INFORMATION FOR THE AVERAGE USER $$$$$ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $$$$$ [1] $$$$$ Atomic Symbols Are Different $$$$$ Atomic symbols in Bibop LISP are very different from those in non-Bibop LISP. The PNAME, ARGS, and VALUE "properties" are not stored on the property list, but in a secret hidden place. The ARGS property can be examined and altered with the function ARGS as in non-Bibop LISP, the VALUE property with EVAL, SET, SETQ, and BOUNDP, and the PNAME property with EXPLODE, GETCHAR, etc. The car of an atomic symbol is not -1 (#777777) in Bibop LISP. The cdr of an atomic symbol is still the property list, however; using RPLACD on an atom, though hackish, also works as before. EXPR and SUBR properties are kept on the property list as in non-Bibop LISP. Note well: (CONS (CAR NIL) ) is most definitely not a good way to construct a new atomic symbol (in Bibop, the result won't be an atom at all, but a dotted pair or whatever). If it is necessary to create a new atomic symbol in this manner, use the function COPYSYMBOL, which works as described in LISP ARCHIV in both Bibop and non-Bibop LISPs. $$$$$ [2] $$$$$ The Allocator Is Different $$$$$ When a Bibop LISP starts up, it says: BIBOP LISP ALLOC? All the usual responses have their usual effects; ^Q, ^W, space, Y, N, etc. work as in non-Bibop LISP. Some questions asked are different, however, and they are presented in a different order. Questions and their default values look something like: Bibop LISP - Section I. - For the Average LISP User - page 3 CORE = 51 LIST = 20000 FIXNUM = 5000 FLONUM = 2000 BIGNUM = 2000 SYMBOL = 2000 ARRAY = 200 REGPDL = 10000 SPECPDL = 4000 FXPDL = 10000 FLPDL = 2000 The first parameter controls the total amount of memory desired, in units of 1024. (1k) PDP-10 words. This is not an absolute constraint as it is in non-Bibop lisp, but merely a specification of the initial size desired for the Bibop lisp. The next six parameters control the maximum size for each of six "spaces" used to contain various objects. They are: LIST lists and dotted pairs FIXNUM fixnums (like FXS in non-Bibop LISP) FLONUM flonums (like FLS in non-Bibop LISP) BIGNUM bignums (actually, just the bignum headers, which hold the sign and point to the rest) SYMBOL atomic symbols (this is why you can't use CONS to create symbols; they are not in LIST space!) ARRAY array pointers (seen primarily on property lists as values of ARRAY properties; the allocation for these need not be large) Initially, you start off with much less core than you specify, but Bibop will "grow" each space to the specified size as soon as it is convenient and/or necessary. If the total amount of core you specify is greater than the total of the individual parts plus the size of the initial LISP system, Bibop will portion out the remainder to deserving spaces (like list and fixnum) in order to make the total size of the LISP be what you asked for. The four pdl parameters are upper limits to the sizes (in PDP-10 words) of the four push-down stacks in LISP. Don't be afraid to give large values for these allocations (or for others, either) since you are not really given as much core as you ask for, but only one page of core per pdl; as the pdls grow, more pages of core are added. On the other hand, the default allocations for the pdls are already quite large, and should be sufficient for most programs. As in non-Bibop LISP, if you type ^Q or other magic characters at the ALLOC? question, your .LISP. (INIT) file Bibop LISP - Section I. - For the Average LISP User - page 4 will be read. The first form should be a comment, as usual. The names of the spaces should be the same as the names used by ALLOC given above. Note that supplying nonexistent space names in the comment doesn't hurt, so you can use the same comment in non-Bibop LISPs as well as Bibop LISPs; for example, the comment (COMMENT FXS 4000 FIXNUM 5000 FLS 2000 SYMBOL 4000 FLONUM 2000 BIGNUM 1400) will for non-Bibop set the size for FXS=4000, FLS=2000 and for Bibop will set FIXNUM=5000, FLONUM=2000, SYMBOL=4000, BIGNUM=1400. $$$$$ [3] $$$$$ The ALLOC Function $$$$$ The primary feature of Bibop is that it allows you to expand memory dynamically. It does this automatically to a certain extent; however, the user may explicitly alter the sizes of memory spaces with the function ALLOC. This is a subr whose single argument should look like the comment form given in a .LISP. (INIT) file. Example: (ALLOC '(LIST 40000 FIXNUM 6000 SYMBOL 5000)) will dynamically re-allocate LIST space to be 40000 words, etc. (Note that LIST space will not actually expand to the specified size until the next time a garbage collection for LIST space is invoked.) At present Bibop can only expand memory, not shrink it, so if you specify a size for a space smaller than its current actual size, your request is ignored for that space. ALLOC returns T. (The ALLOC function is actually considerably more complicated, but the above description should suffice for the purposes of most users. An extended description of ALLOC may be found in section II.[3].) $$$$$ [4] $$$$$ A Few New Messages $$$$$ If you should run out of memory for any reason, you will see a message similar to that in non-Bibop LISP, e.g.: FIXNUM STORAGE CAPACITY EXCEEDED ;BKPT GC-LOSSAGE This indicates that you have run out of address space and therefore cannot add any more memory. However, in Bibop LISP another kind of break may occur: Bibop LISP - Section I. - For the Average LISP User - page 5 ;BKPT GC-OVERFLOW this indicates that some space has reached the maximum specified by ALLOC; the name of the space which got too large is the value of the variable ARGS, as usual. Now all is not lost at this point in a Bibop LISP; you may call the function ALLOC to make FIXNUM space bigger, then say $P to continue the computation. (Note that this is not really an error break, but more like a daemon; therefore $P does not error out to top level the way it would for, say, a FAIL-ACT break). To abort the computation, use ^G. If you see a message that looks something like ;ADDING A NEW FIXNUM SEGMENT - FIXNUM SPACE NOW 2000 WORDS it merely means that the garbage collector has decided to add more memory. You will only see this if you have typed ^D to see the garbage collector statistics (as in non-Bibop). Yet another message you may see (which also does not exist in non-Bibop LISP) is: ;BKPT PDL-OVERFLOW This means that you have used excessive amounts of pdl (by exceeding the specified PDLMAX parameter - see section II.6), and therefore are probably stuck in infinite recursion or something. If you want to keep going, just say $P and Bibop will try to extend the pdl if it can. To abort the computation, use ^G. (This procedure is similar to that for GC-OVERFLOW - see above.) Bibop LISP - Section II. - For Sophisticated LISP Users - page 6 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $$$$$ II. INFORMATION FOR SOPHISTICATED USERS $$$$$ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $$$$$ [1] $$$$$ The Garbage Collector Explained $$$$$ For each memory space (presently these are LIST, FIXNUM, FLONUM, BIGNUM, SYMBOL, and ARRAY) there are three parameters controlling when and how to expand it. These are called the GCSIZE, GCMIN, and GCMAX parameters. The GCSIZE parameter indicates the size that space is normally expected to be; GCMIN indicates the minimum number of words free after a garbage collection; and GCMAX indicates the maximum size to which the space is permitted to expand. The garbage collector is invoked whenever no free cells are left for a space. (We shall ignore the case where the user explicitly invokes it.) The algorithm for getting free cells is roughly as follows: [a] If the total size of the space under question is less than its GCSIZE parameter, then add some more memory to that space and return immediately, without doing a full-blown garbage collection. (If possible, enough memory will be added to bring the total size of the space up to its GCSIZE.) However, if the total size already exceeds the GCSIZE, or if adding more memory would cause the space to exceed the GCMAX parameter, do not add any memory yet, but go on to step [b] instead. [b] Do a garbage collection. If the number of words free is less than the GCMIN parameter, then add enough core to satisfy GCMIN (see below). (However, if satisfying the GCMIN would cause GCMAX to be exceeded for that space, then only as much as GCMAX allows will be added. On the other hand, at least "some" (as described above) will be added.) [c] If GC can't get more memory (the LISP is huge, or ITS won't give LISP any core), then a GC-LOSSAGE interrupt occurs. [d] If the total size of the space exceeds the GCMAX parameter, then a GC-OVERFLOW interrupt occurs. Note that this is not an error interrupt; it is rather more like the GC-DAEMON interrupt, and will not be trapped by ERRSET. The purpose of the GCSIZE parameter is to allow storage spaces to swell quickly to a predetermined size, e.g. while loading a package of functions. When more memory is needed, it is added immediately, without a time-consuming garbage collection. Bibop LISP - Section II. - For Sophisticated LISP Users - page 7 The GCMIN parameter takes over when a storage space becomes larger than GCSIZE. GCMIN may be either a fixnum or a flonum. If it is a fixnum, then more memory is added whenever the number of words reclaimed is less than that. If the GCMIN is a flonum, then more memory is added whenever the number of words reclaimed is less than the GCMIN times the total size of the space. Thus a GCMIN of 2000 for some space says to add more memory if fewer than 2000 words are reclaimed for that space; while a GCMIN of 0.25 says the space should be kept 25% free, adding more memory when necessary to maintain that percentage. Values of 0.2 to 0.4 are recommended for LIST, FIXNUM, and FLONUM spaces; 100. to 500. is recommended for BIGNUM, SYMBOL, and SAR spaces. (If your application involves creating and throwing away large numbers of SYMBOLs, you might be well-advised to use 0.3 or so for the SYMBOL GCMIN.) The GCMAX parameter is used primarily to keep tabs on programs which might go out of control and use up unlimited amounts of memory; this is a problem only because a space, once expanded, may not be shrunk again. A user-supplied GC-OVERFLOW interrupt function may be used to keep track of memory expansions (see section II.[4] below). $$$$$ [2] $$$$$ Dynamic Pdl Expansion $$$$$ The parameters you give to ALLOC for pdl sizes (see above) are very similar to the GCMAX parameters for free storage spaces: the pdls do not actually occupy that much core, but are rather permitted to grow that large if necessary. There is one difference, however: enough address space for the specified pdl sizes is reserved to accomodate the pdls, and at present this address space may not be used for anything else. Thus, if you allot 100K for pdls, the rest of your LISP may never grow larger than 156K. On the other hand, the initial allocations for pdls are quite reasonable (total about 12K), and few programs require more than that. Now the same remark made above about free storage applies to pdls also: one may not want an infinite recursion to gobble up 8K of pdl before giving a pdl overflow message. Each pdl therefore has a PDLMAX parameter, similar to GCMAX for storage spaces. The PDLMAX parameter for a given pdl specifies that when the number of words on the pdl exceeds PDLMAX, a PDL-OVERFLOW user interrupt (number 12.) should be given. The user interrupt function receives as its argument one of the four atomic symbols REGPDL, FLPDL, FXPDL, or SPECPDL. When this happens, the PDLMAX for that pdl is pushed up enough to give the user interrupt a little room to work in; but if the user interrupt function uses too much pdl itself without explicitly setting the PDLMAX up even Bibop LISP - Section II. - For Sophisticated LISP Users - page 8 further, it may be recursively re-invoked. If the absolute limit on the size of the pdl is reached, an uncorrectable error occurs. If this happens, the PDLMAX parameters will be reset to what they were before the PDL-OVERFLOW interrupt pushed them up. $$$$$ [3] $$$$$ The ALLOC Function Extended $$$$$ An extended form of the ALLOC function may be used to set the various parameters for spaces. Essentially, one may replace the number for a space by a 3-list of the GCSIZE, GCMAX, and GCMIN parameters (in that order). A NIL for any parameter means "don't change the current setting". Example: (ALLOC '(LIST (40000 60000 0.2) FIXNUM (4000 7000 NIL))) means to set the LIST GCSIZE to 40000 words, the LIST GCMAX to 60000 words, and the LIST GCMIN to 0.2 (meaning "keep LIST space 20% free"); and to set the FIXNUM GCSIZE and GCMAX to 4000 and 7000, and don't change the FIXNUM GCMIN. A typical call for a LISP with a maximum size of about 100K words might be: (ALLOC '(LIST (30000. 50000. 0.25) FIXNUM (6000. 11000. 0.2) FLONUM (1500. 2500. 0.2) BIGNUM (1000. 2000. 500.) SYMBOL (4000. 5000. 0.15) ARRAY (100. 600. 40.) REGPDL 8000. FLPDL 1000. FXPDL 5000. SPECPDL 8000.)) As a special hack, saying (ALLOC T) will get you back a list of this form, such that you could give it back to ALLOC to set the parameters. Thus, if you forget how to give arguments to ALLOC, just type (ALLOC T) at a Bibop LISP and figure it out! Specifying a value for a pdl sets that pdl's PDLMAX parameter. Note that you may specify only a fixnum for a pdl, not a 3-list. The following example of the use of ALLOC simulates the mode of typein at initial allocation time, and calls the ALLOC function to set parameters for the various spaces: Bibop LISP - Section II. - For Sophisticated LISP Users - page 9 (DEFUN ALLOC! NIL (TERPRI) (PRINC 'BIBOP/ LISP/ ) (PRINC (STATUS LISPVERSION)) (TERPRI) (PRINC 'ALLOC!) (TERPRI) (DO ((Q (ALLOC T) (CDDR Q)) (Y)) ((OR (NULL Q) (EQ Y '$)) (TERPRI) '*) (TERPRI) (PRINC (CAR Q)) (PRINC '/ =/ ) (PRINC (CADR Q)) (DO NIL ((NOT (< (- LINEL CHRCT) 40))) (PRINC '/ )) (AND (MEMQ (TYPEP (SETQ Y (READ))) '(LIST FIXNUM)) (ALLOC (LIST (CAR Q) Y))))) The interaction when this function is invoked would look like this (note that the user must type space after a number or $, and that the user may type a 3-list instead of a number when appropriate): BIBOP LISP 676 ALLOC! LIST = (20000 20263 0.25) 44444 FIXNUM = (5000 5046 0.2) (4000 6000 .4) FLONUM = (1000 1007 0.15) NIL BIGNUM = (1000 1000 100) (NIL NIL .2) SYMBOL = (4000 4036 40) NIL ARRAY = (300 400 10) 350 REGPDL = 13160 20000 FLPDL = 2620 $ * This function is in the file ML:GLS;BIBOP ALLOC! if you want to play with it. $$$$$ [4] $$$$$ Use of GC-OVERFLOW and GC-DAEMON Interrupts $$$$$ If you are concerned with building a system like MACSYMA or CONNIVER, you may want to be more friendly to the user than LISP is when some memory space overflows. For example, you might want to write a function which decides whether or not to add more memory, or asks the user politely, or something. This can be done by supplying a GC-OVERFLOW interrupt function (user interrupt number 13.). This function will be run whenever GC can't add more memory by itself (an explanation of this condition is given in section II.[1] above). It receives an argument which is the name of the space that overflowed. Within this interrupt function more memory probably can be obtained if desired (this is Bibop LISP - Section II. - For Sophisticated LISP Users - page 10 explained below). Here is an example of what a GC-OVERFLOW function might look like: (SETQ GC-OVERFLOW '(LAMBDA (X) (IOG NIL (TERPRI) (PRINC 'YOU/ HAVE/ RUN/ OUT/ OF/ ) (PRINC X) (PRINC '/ SPACE/./ MORE?:/ ) ;Ask if more memory desired. (COND ((MEMQ (READ) '(NIL N NO NEIN NYET)) (ERROR 'SPACE/ CAN/'T/ BE/ EXPANDED X 'GC-LOSSAGE)) (T (PRINC '/ OK/./ /() ;If so, allocate some. (ALLOC (LIST X (LIST NIL (PRINC (+ (CDR (SASSQ X '((LIST . 1400) (FIXNUM . 1400) (FLONUM . 600) (BIGNUM . 400) (SYMBOL . 400) (SAR . 100)) '(LAMBDA NIL '(NIL . 400)))) (CADR (GET (CONS NIL (ALLOC T)) X)))) NIL))) (PRINC '/ WORDS/)) (TERPRI)))))) This function tells the user what's happening and asks whether to go on or not. If the answer is affirmative, it increases the amount of core and returns to continue; otherwise it calls the ERROR function to cause a GC-LOSSAGE error. Note that SASSQ is used so that in case some new kind of space is implemented (and this may happen!) the function will still work properly. The interaction might look like this: YOU HAVE RUN OUT OF FIXNUM SPACE. MORE?: YES OK. (5000 WORDS) YOU HAVE RUN OUT OF LIST SPACE. MORE?: JA OK. (22000 WORDS) YOU HAVE RUN OUT OF FLONUM SPACE. MORE?: NO FLONUM SPACE CAN'T BE EXPANDED ;BKPT GC-LOSSAGE where the user typed "YES " to the first question, "JA " to the second, and "NO " to the third. Naturally, even more imaginative things may be done. This function is in the file ML:GLS;BIBOP GCOVER if you want to play with it. Bibop LISP - Section II. - For Sophisticated LISP Users - page 11 The GC-DAEMON user interrupt (number 20.) may be used to monitor the results of garbage collection as in a non-Bibop LISP. The argument to the GC-DAEMON function is a list of space items, where a space item is of the form ( . ) where is the name of the space, is a fixnum denoting the number of cells free just before the garbage collection, and is a fixnum denoting the number of cells free after garbage collection. (This is the same GC-DAEMON argument format now used by non-Bibop LISP.) $$$$$ [5] $$$$$ Pure Free Storage $$$$$ Note: this section is probably worth reading only if you are building a large system to be purified and run by many users. (MACSYMA people take note!) Bibop allows for four more kinds of storage spaces besides the six we have mentioned up to now. These new kinds are called pure LIST, pure FIXNUM, pure FLONUM, and pure BIGNUM. They are pure because (1) once a cell is consed up it can never be reclaimed, and (2) because this is true, such list structure can reside on read-only pages, and thus be shared between jobs in the same way pure executable code can be shared. A restriction is made that list structure pointers in pure spaces cannot point anywhere except to atomic symbols, subrs, sars, and other pure cells; this implies that (3) not only does the garbage collector not have to reclaim cells for pure spaces, but it need never mark through them (trace them) during garbage collections either; thus a time savings is realized as well as a space savings. Another restriction which follows from the above is that (4) one may not do RPLACAs, NCONCs, etc. on list structure residing in pure spaces (one might get a pure page violation trap). There are two ways to use pure free storage. The first is to make the variable *PURE non-nil before calling FASLOAD. (This is not the same as PURE, which is still used for its original purpose of making executable code pure, and to invoke the so-called "XCT hack".) In a non-Bibop LISP, *PURE is ignored. In a Bibop LISP, any constant list structure referred to by compiled code, and possibly other pieces of list structure (such as the PNAMEs of INTERNed symbols) are made purifiable. (Exactly what gets purified is up to FASLOAD, and is subject to change as this feature is experimented with.) There is thus an implicit assumption that compiled code will not contain such idiotic constructs as Bibop LISP - Section II. - For Sophisticated LISP Users - page 12 (DEFUN FOO (X) (NCONC '(A B) X)) [Think about it.] This all will happen automatically: the list structure will be consed into pure spaces instead of regular spaces, and magic bits will be set for the PURIFY function (see below). The variable *PURE also controls another hack in the function PUTPROP. If the value of *PURE is non-nil, then the value of the variable PUTPROP is a list of property names whose corresponding values may be purified. When *PURE is non-nil, the function PUTPROP checks its third argument against this list; if it is on the list, then the function PURCOPY (see below) is applied to the second argument before it is placed on the property list of the first argument. Furthermore, the two cells of the property list itself are purified if it is a new property being added (as opposed to changing the value of an already present property); in order to do this, PUTPROP may install the property somewhere in the middle of the property list, instead of at the beginning as it usually does. Note that this purification of property lists doesn't hurt, since if, after it is purified, the property is changed again, the system will copy the property list in order to make the change. (The property lists of most system symbols are initially pure in all versions of LISP!) Initially the value of PUTPROP is (SUBR FSUBR LSUBR), these properties may always be safely purified. Warning: ARRAY is definitely not a purifiable property! Example: suppose that the values of the property DATUM are always purifiable, i.e. are either always atomic or are list structure which is never RPLACA'd or otherwise clobbered. Then one might say: (SETQ PUTPROP (APPEND '(DATUM) PUTPROP)) When *PURE is set to non-nil, then PUTPROP will automatically purify all DATUM properties. Another way to use pure free storage is to call the function PURCOPY, a subr of one argument. In a non-Bibop LISP, this will merely return its argument (or possibly a copy thereof, if a number). In a Bibop LISP, the entire s-expression will be copied as much as possible into pure spaces, and the copy returned. Note that reasonable things are done for symbols and sars, though there are no pure SYMBOL or pure ARRAY spaces. This use of PURCOPY is intended for such things as (SETQ HUMUNGOUS-DATA-BASE (PURCOPY HUMUNGOUS-DATA-BASE)) or (PUTPROP 'FOO (PURCOPY (GET 'FOO 'PROP)) 'PROP) where HUMUNGOUS-DATA-BASE and FOO's PROP property will not be RPLACA'd into or anything nasty like that. Of course, there is little point in doing all this unless the job is to be purified and :PDUMPed, or unless the structures involved Bibop LISP - Section II. - For Sophisticated LISP Users - page 13 are very large. Furthermore, there is no point in PURCOPYing an object which is likely to be very temporary. In any case this is primarily an efficiency hack; it does not hurt not to use it. $$$$$ [6] $$$$$ New STATUS/SSTATUS Calls $$$$$ There are many STATUS functions in Bibop for examining and altering the various parameters described above. In the following, must evaluate to one of LIST, FIXNUM, FLONUM, BIGNUM, SYMBOL, or ARRAY, unless otherwise specified. (Actually, some Bibop LISPs may not have all these spaces; in particular BIGNUM may be missing.) To determine what spaces are available, and thus what space names are valid arguments, say: (STATUS SPCNAMES) to get a list of them. Recall that the space parameters described in section II.[1] do not control the actual size of a storage space, but merely specify how to expand it. To find the actual current size of a storage space, say: (STATUS SPCSIZE ) To find the total size of some pure space, say: (STATUS PURSIZE ) where in this latter context must evaluate to one of LIST, FIXNUM, FLONUM, or BIGNUM. Note that the initial LISP system has some pure LIST and FIXNUM storage. To find the current number of words on some pdl, say: (STATUS PDLSIZE ) where should evaluate to REGPDL, FLPDL, FXPDL, or SPECPDL. Note that some random variation is introduced by the fact that the call to STATUS uses some pdl, but this is only a few words. To find the absolute maximum for the size of a pdl (this is the quantity defined once and for all at initial allocation time), say: (STATUS PDLROOM ) where is as above. This quantity will generally be larger than the number given to the initial ALLOC; the Bibop LISP - Section II. - For Sophisticated LISP Users - page 14 latter number is made the initial PDLMAX, and PDLROOM is made larger so that the PDL-OVERFLOW user interrupt handler will have some extra pdl to work in. $$$$$ [7] $$$$$ Use of the PDL-OVERFLOW User Interrupt $$$$$ This is an example of what a handler for the PDL-OVERFLOW user interrupt might look like. It is similar to the one previously shown for the GC-LOSSAGE interrupt. If the PDL-OVERFLOW function returns at all, it means that the pdl should be extended and the computation continued. To abort the computation an error must be signaled explicitly; this is done here with the function ERROR (see LISP ARCHIV). (SETQ PDL-OVERFLOW '(LAMBDA (X) (TERPRI) (PRINC 'YOU/ HAVE/ USED/ ) (PRINC (STATUS PDLSIZE X)) (PRINC '/ WORDS/ OF/ ) (PRINC X) (PRINC '/./ MORE?:/ ) (COND ((MEMQ (READ) '(NIL N NO NEIN NYET)) (ERROR 'OVERFLOW/ LOSSAGE X)) (T (PRINC '/ OK/.) (TERPRI) (ALLOC (LIST X (MIN (STATUS PDLROOM X) (+ (GET (CONS NIL (ALLOC T)) X) 400)))))))) This function is in the file ML:GLS;BIBOP PDLOSS if you want to play with it. $$$$$ [8] $$$$$ The Purify Function $$$$$ The PURIFY function operates in the usual manner when its third argument is T or NIL. If, however, the third argument is BPORG (which means to do clever things when purifying compiled code), Bibop assumes that it knows more than you ever will about the kludgy things it's doing, and therefore more or less ignores the first two arguments!!! (Actually, they should both be fixnums; 0 and 0 will do, and calculating numbers as you would for non-Bibop doesn't hurt.) In any case, all the correct things should happen, including purification of sharable code and of pure free storage. It is, of course, as good an idea in Bibop LISP as in non-Bibop LISP to call the function PAGEBPORG before calling PURIFY with BPORG as its third argument. Bibop LISP - Section II. - For Sophisticated LISP Users - page 15 Another way to purify the LISP is to say (MACDMP 'PURIFY$G) where $=altmode. (Naturally, other stuff may be included in the valret string as well, such as a :PDUMP or whatever.) Unlike non-Bibop LISP, this will purify all possible pages, not just system pages. Bibop LISP - Section III. - For LISP System Hackers - page 16 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $$$$$ III. INFORMATION FOR THE SUPER-HACKERS $$$$$ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ The information in this section is primarily for the use of system hackers, and is for the most part subject to change without notice when implementation requires. This section makes no pretense at being self-explanatory; it should be read in conjunction with a listing of LISP. $$$$$ [1] $$$$$ The Segment Table $$$$$ At the heart of the Bibop scheme is the Segment Table (ST). The entire address space is divided into "segments" which are some fraction of 1K (typically 1/2K; the size is SEGSIZ=<1_SEGLOG>, where SEGLOG is an assembly parameter). The Segment Table contains one word for each segment; the contents of this word indicate what that segment may contain. A Segment Table entry is of this form: BIT # BIT NAME BIT DESCRIPTION 4.9 LS 1=list structure, 0=atomic 4.8 $FS free storage (bit 4.9 should be on also) 4.7 $FX fixnum storage (but not fixnum pdl) 4.6 $FL flonum storage (but not flonum pdl) 4.5 BN bignum header storage 4.4 SY symbol header storage 4.3 SA sar (array pointer) storage 4.2 VC value cell storage (bit 4.9 should be on also) 4.1 $FXP fixnum pdl area 3.9 $FLP flonum pdl area 3.8 $XM existent (random) area 3.7 $NXM nonexistent (random) area 3.6 PUR pure space (one of bits 4.8-4.5 should be on) 3.5-3.1 unused 2.9-1.1 address of one of these seven items: QLIST, QFIXNUM, QFLONUM, QBIGNUM, QSYMBOL, QRANDOM, QARRAY Note that these items occupy consecutive memory locations and thus numerically encode the page type. The basic algorithm for getting a Segment Table entry and testing it (given an address in, say, accumulator A) is: MOVEI TT,(A) ;in case we must save A LSH TT,-SEGLOG ;look at top few bits of address MOVE TT,ST(TT) ;fetch Segment Table entry TLNN TT, ;or maybe TLNE, or something Instead of the TLNN, one may also have something like: Bibop LISP - Section III. - For LISP System Hackers - page 17 JRST @JTABLE-QLIST(TT) ;n-way JRST on TYPEP where JTABLE is a table of addresses. Since bignums are not always present in the system, one ordinarily writes somthing like: JTABLE: JLIST ;jump to JLIST if TYPEP=LIST, etc. JFIXNUM JFLONUM IFN BIGNUM, JBIGNUM JSYMBOL JRANDOM JARRAY Various efficiencies can be introduced in special cases. The above sequence of code is so common that there is a macro called SKOTT (SKip On TT) which produces the above sequence, with a TLNN. (If is merely LS, however, then the MOVE and TLNN are collapsed into a SKIPL.) There is another Segment Table which is used by the garbage collector and related routines; it is called GCST. Its format is quite hairy: the positions and sizes of the bits and bytes in each entry are dependent on SEGLOG (for the sake of an efficiency hack in the GC mark phase). Basically, it indicates the address of the bit table, if any, for marking items in that segment, and also has a link field so that GCST entries may be strung together; there are also random bits telling GC how to mark items in the segment. If a segment requires no bit table, then its GCST entry has 0 as the bit table address. Exception: a segment which contains bit tables uses its GCST entry to aid allocation and initialization of the bit tables within the segment. As an example, if SEGLOG=11 (octal), the usual case, then the format of GCST entries is as follows: BIT # BIT NAME BIT DESCRIPTION 4.9 GCBMRK items in this page are markable 4.8 GCBVC this page contains value cells 4.7 GCBSYM this page contains symbol headers 4.6 GCBSAR this page contains array pointers 4.5 GCBCDR mark from cdrs of items 4.4 GCBCAR mark from cars (only if 4.5 also on) 3.4-2.5 SEGBYT field for chaining entries 2.4-1.1 ---- segment table address, lsh'ed Bibop additionally maintains a table called PURTBL, which has a two-bit byte for every page (that's right, not segment, but page) of possible address space. A zero means the page should be non-existent; a one, that the page should be impure; a two, that it should be pure; and a Bibop LISP - Section III. - For LISP System Hackers - page 18 three, that the page is some special case like a pdl page. These bits reflect what the pages should be, not what they are; indeed, what PURIFY$G does is to force the actual pages to conform to PURTBL! $$$$$ [2] $$$$$ Storage Spaces in Bibop $$$$$ Since Segment Table entries are used to determine TYPEP of objects, clearly things like atomic symbols may not reside in LIST space, as in a non-Bibop LISP. Furthermore, pure and impure objects must be not only in different segments, but on different pages. Thus Bibop distinguishes many kinds of segments and pages. All segments of a given type comprise a storage space. Non-Bibop LISP has five primary storage spaces: LIST, FIXNUM, FLONUM, ARRAY, and Binary Program Space (arrays are kept in BPS also, as opposed to array pointers, which are kept in ARRAY space.) Bibop LISP has many: LIST (pure and impure), FIXNUM (pure and impure), FLONUM (pure and impure), BIGNUM (pure and impure), SYMBOL, ARRAY, and Binary Program Space. The LIST, FIXNUM, FLONUM, and ARRAY spaces are analogous to those in non-Bibop LISP. The BIGNUM space actually holds only bignum headers, which contain the sign of a bignum in the sign bit, and a pointer to a list of fixnums, identical to that in non-Bibop LISP, in the right half. (Actually the left half must contain 0 or 777777; much code depends on it!) Note that with this representation, the sign of any LISP number, be it FIXNUM, FLONUM, or BIGNUM, may be determined by testing the sign of the word addressed by the LISP pointer to that number. SYMBOL space has a very peculiar format: it is actually sectioned into two spaces. One is called symbol header space, and is the space referred to by the garbage collector statistics. One word of symbol header space is required per symbol; thus when GC says 500 SYMBOL words free, it is possible to create 500 more symbols, even though symbols occupy more than one word in Bibop LISP. The other is called symbol block space, and is allocated in two-word chunks. Each symbol block is therefore at an even address. These symbol blocks are not garbage collected, but rather follow an explicit return discipline. Symbol blocks may be purified, while symbol headers may never be purified. Thus there are actually two symbol block spaces, pure and impure, though this is transparent to the user. Whenever a new symbol is created, a fresh symbol header is taken from symbol header space, and a fresh symbol block from impure symbol block space, unless the variable *PURE is non-nil, in which case a pure symbol block is used. Impure symbol blocks are also used when the contents of a pure symbol block must be altered; the contents of the pure symbol block are copied to a fresh impure one and the pure one forgotten forever. Pure symbol blocks are never returned Bibop LISP - Section III. - For LISP System Hackers - page 19 once used; impure symbol blocks are returned when their corresponding symbols are garbage collected. The symbol header has the property list in its right half (thus the cdr of an atomic symbol is its property list, as usual), and a pointer to the symbol block in its left half. The symbol block has two words. The left half of the first word contains random bits, including one which is on iff the symbol block is pure, and one which says that compiled code needs the symbol (and that therefore the symbol may never be garbage collected). This bit cannot be turned on in a pure symbol block, so whenever a pure symbol block is copied, the compiled-code-need-me bit is turned on in the copy - better to be safe than sorry! The index and indirect bits are zero (see below). The right half of the first word points to the value cell for that symbol. If the symbol does not have a value cell of its own, it points to SUNBOUND, the Standard UNBOUND value cell. (Such symbols are heliocentric.) In this way, one can indirect through the symbol block to get the symbol's value, saving an instruction. The left half of the second word contains the ARGS property for the symbol, in the format used by FASLOAD, i.e. as two nine-bit bytes. The PNAME of the symbol is in the right half of the second word. Note that the garbage collector does not mark symbol blocks per se, but only symbol headers; thus keeping a pointer to a symbol block in a marked accumulator does not guarantee that the symbol block will not go away! Another garbage collector hack is that one cannot use the symbol block for the gc mark bit, since it may be pure. However, the pointer in the left half of the symbol header must always be even, since symbol blocks have even addresses. Thus bit 3.1 of the symbol header is used as the mark bit. Of course, GC must reset these bits as it does the final sweep through symbol header space. Before the mark phase it sets a switch (MUNGP) and resets it after the sweep; if somehow ERINIT is reached before GC finishes, it will notice the switch and reset the mark bits. Bibop stores array pointers (also known as sars) in the same manner as non-Bibop lisp; the relevant information appears here for convenience. Sars consist of two words; the first is called the ASAR, and the second the TTSAR. A pointer to a sar points to the ASAR. The ASAR has the following format: Bibop LISP - Section III. - For LISP System Hackers - page 20 BIT # BIT NAMER BIT DESCRIPTION 4.3 AS.FIL this is a file array (for new i/o) 4.2 AS.RDT this is a readtable 4.1 AS.OBA this is an obarray 3.9 AS.SX this array holds s-expressions, 2/wd 3.8 AS.FX this array holds fixnums 3.7 AS.FL this array holds flonums 3.6 AS.GCP GC should mark array entries 3.5-3.1 ---- must be zero 2.9-1.1 ---- address of array header Bits 3.9-3.7 should be mutually exclusive - they define the type of array access mechanism to be used. Bit 3.6 is independent of this consideration; for example, a readtable has AS.FX set, but it also wants its macro character list garbage collected. GC only marks as many words of entries as specified by the aobjn pointer just before the array header. Bits 3.5-3.1 must be zero because compiled code does indirect PUSHJs through the ASAR to reach the array header, which computes subscript information. The format of the TTSAR is as follows: BIT # BIT NAME BIT DESCRIPTION 4.9-4.7 TTSDIM number of dimensions (1-5) 3.7 TTS.CN compiled code needs this sar 3.6 TTS.GC mark bit used by GC 3.5-3.1 ---- must contain (TT) 2.9-1.1 ---- address of first word of array data The indirect and index bits are such that indirecting through the TTSAR causes indexing by accumulator TT. Compiled code uses this fact to open-access arrays. Pure spaces are identical in function to impure spaces, but are allocated on separate pages so that they may be purified. Value cells are also kept in a space of their own for various reasons. They are also kept contiguous, but if the region reserved for value cells (a hole in memory of about 3k words) is ever exhausted, cells from LIST space will be used to create value cells. TYPEP of a value cell is indeed LIST. Value cells in the value cell region follow an explicit return discipline. The function MAKUNBOUND will return the specified symbol's value cell unless the symbol's compiled-code-needs-me bit is set (which might indicate that compiled code references the value cell). The garbage collector will return a value cell if the symbol pointing to it is swept up. Bibop LISP - Section III. - For LISP System Hackers - page 21 Bibop LISP - Section III. - For LISP System Hackers - page 22 $$$$$ [3] $$$$$ Storage Layout and Strategy $$$$$ The initial Bibop LISP system is laid out something like this: ---------------------------------------------------- < 0 | low page - impure (acs, temps, etc.) | ---------------------------------------------------- < BSYSSG | | | initial LISP system | | | | (executable code) | | | ---------------------------------------------------- < BSARSG | initial SARs (for READTABLE, OBARRAY, etc.) | ---------------------------------------------------- < BVCSG | initial value cells (plus expansion room) | ---------------------------------------------------- < BSYMSG | initial atomic symbols | ---------------------------------------------------- < BPFSSG | initial list structure and numbers - pure | ---------------------------------------------------- < BIFSSG | initial list structure and numbers - impure | ---------------------------------------------------- < BSTSG | segment tables (ST and GCST) | ---------------------------------------------------- < BBPSSG | Binary Program Space (expands upward) | < V(BPORG) ---,----,----,----,----,----,----,----,----,----,--- < V(BPEND) | arrays (float at top of BPS) | ---,----,----,----,----,----,----,----,----,----,--- < C(BPSH) | / / / / / / / / / /| | / / / / / / / / / / | | / / big hole of nonexistent memory / / | | / / / (the "big bag of pages") / / | |/ / / / / / / / / / | | / / / / / / / / / /| < C(HINXM) ---'----'----'----'----'----'----'----'----'----'--- | new storage space segments (expands downward) | ---------------------------------------------------- < C(FXC2) | push-down lists (FXP, FLP, P, SP) | | (sizes allocated by initial ALLOC) | ---------------------------------------------------- < BSCRSG | scratch pages (for PDP-6 slave, etc.) | ---------------------------------------------------- < 776000 | / / / high page - never used / / / | ---------------------------------------------------- < 777777 ------- Legend: C(foo) = contents of location foo Address V(foo) = fixnum value of symbol foo Note that "downward" means toward lower addresses, and thus up the diagram (too bad if you don't like it!) Bibop LISP - Section III. - For LISP System Hackers - page 23 The basic strategy is to allocate new storage segments from the top of memory downward, so that this area and Binary Program Space grow toward each other. Extra hair is involved to ensure that pure and impure segments stay on separate pages. The Bibop memory management routines maintain a table of two-bit bytes called PURTBL. Each byte describes the state of one page. For a further description, see TBLPUR$X below. Bibop only allocates pdl pages when necessary. Whenever ERINIT is called ($G startup, ^G quit, error to top level) all pdl pages are flushed, and the pdl pointers are all made to point to a one-word pdl called FAKPDL. Whenever pdl overflow occurs, the internal pdl overflow interrupt handler extends the pdl, getting a new page if necessary and possible. (If it is necessary but not possible, an uncorrectable error occurs). If the pdl's PDLMAX has been exceeded, the PDLMAX is temporarily pushed up some and a PDL-OVERFLOW use interrupt is signaled. The value returned from this interrupt is ignored; the mere fact of its returning indicates that the computation should be continued. The internal pdl overflow handler goes to some trouble to make sure a little pdl (about 8 words) is always available, even if the pdl overflow interrupt is temporarily inhibited (e.g. inside the internal interrupt dispatcher). It also uses two very small pdls called FAKP and FAKFXP for some purposes of its own. $$$$$ [4] $$$$$ Hairy STATUS Calls $$$$$ These STATUS calls are to ease debugging, and may be flushed in the future. BEWARE!!! The GCSIZE, GCMAX, and GCMIN parameters for storage spaces may be hacked en masse by the ALLOC function (see above), or individually by these calls: (STATUS GCSIZE ) (STATUS GCMAX ) (STATUS GCMIN ) (SSTATUS GCSIZE ) (SSTATUS GCMAX ) (SSTATUS GCMIN ) Note that if a flonum GCMIN is specified, it should be between 0.5 and 0.005. The SSTATUS versions return T if they succeed in setting the parameter, otherwise NIL. Bibop may fiddle with the parameters to keep them consistent. Bibop LISP - Section III. - For LISP System Hackers - page 24 To examine and set the PDLMAX parameter for some pdl, say: (STATUS PDLMAX ) (SSTATUS PDLMAX ) where is a fixnum. $$$$$ [5] $$$$$ Super Random Items about Bibop $$$$$ The following STATUS calls do not exist in Bibop: (STATUS FS) (STATUS FWS) (STATUS BT) The following additional status calls exist in Bibop: (STATUS SEGLOG) This is the log base 2 of the amount of memory by which a storage space may be incremented. Typically this is 10 or 11 octal. (STATUS HINXM) This is the highest address of the "hole" in memory the top of Binary Program Space and the bottom of the area free storage is allocated in. The following new $X frobs exist in Bibop LISP for examining and debugging from DDT: T.$X Prints some stuff which is essentially TYPEP of the right half of the currently open location. (Actually, it is a representation of the Segment Table entry for that word. It is of the form ,,. For example, $FX+PUR,,FIXNUM would be an entry for pure FIXNUM storage. If ?? appears among the bits, there is a bug somewhere.) TL.$X TL.$X : T.$X :: PL.$X : P.$X TP FOO$X TP FOO$X : T.$X :: PP FOO$X : P.$X TBLPUR$X Prints out the contents of the PURTBL, the table of magic bits used by PURIFY. Prints one digit for each page: 0 nonexistent memory 1 impure memory 2 pure memory 3 only Bibop knows for sure, e.g. arrays, pdl pages, pure free storage Bibop LISP - Section III. - For LISP System Hackers - page 25 which hasn't been purified yet, etc. Note that these are not necessarily the actual states of the pages, but what they "should" be in Bibop's eyes. At the end the total number of each kind of page is printed out in decimal. PAGPUR$X Similar to TBLPUR$X, but indicates the actual states of the pages (0=nonexistent, 1=impure, 2=pure). When examining the GCST table, it is easier to understand the entries if you say $T; to set the typeout mode; this will print out entries as three bytes: the random bits, the link, and the bit table address, in that order. Thus, to examine the GCST entry for FOO, say to DDT: +GCST/ $T; Typically SEGLOG=9.; if this is true for the Bibop LISP you are hacking, then you can easily examine ST and GCST entries as follows: if abcdef is the octal address of a location, then ST+abc is the ST entry for that address. To find all segments of a given kind of memory area, one can start from the following locations: FSSGLK impure LIST space FXSGLK impure FIXNUM space FLSGLK impure FLONUM space BNSGLK impure BIGNUM space SYSGLK SYMBOL space SASGLK SAR space S2SGLK symbol blocks BTSGLK segments containing bit tables IMSGLK a freelist of impure segments and trace down the GCST links. If the number of a segment is in, say, accumulator TT, then LDB TT,[SEGBYT,,GCST(TT)] will fetch the number of the segment the first one links to. (SEGBYT is the appropriate left half for a byte pointer to the link field of a GCST entry.) Example: to "mung" all impure flonum segments: Bibop LISP - Section III. - For LISP System Hackers - page 26 SKIPN TT,FLSGLK JRST DONE LOOP: mung(TT) LDB TT,[SEGBYT,,GCST(TT)] JUMPN TT,LOOP DONE: One should be very careful not to destroy entries in ST and GCST; the entire Bibop LISP system depends critically on them! In particular, updating any one of ST, GCST, and PURTBL generally requires that the other two should be updated to match. he 9GLS March 21, 1977 Here we discuss some considerations of implementing double-precision, complex, and double-precision complex numeric data types in PDP-10 MacLISP. In the first section we discuss user-level considerations: questions of I/O representations, new functions, and so on. In the second section we discuss systemic considerations: internal representations, compiler issues, etc. All the ideas expressed here are tentative and subject to revision. Constructive criticism is welcomed; reply to GLS@MIT-MC. The User Level Data Types The proposed scheme would introduce three new data types. Double-precision complex numbers are desirable not only for their own sake but also to solve the problem of contagious arithmetic when a double-precision number meets a complex number. As with bignums, a given version of MacLISP could omit either double precision or complex arithmetic, or both. (STATUS FEATURES) could indicate which numeric types were present in a LISP. New names for the types (as returned by TYPEP) must be chosen. I suggest DOUBLE and COMPLEX for the first two; choosing the third is less obvious. DOUBLE-COMPLEX is rather a long name. My best suggestion for a short name is DUPLEX, which is kind of a hack but has euphony. I will use this name throughout this document for brevity. I/O Representations The standard format +xxx.xxxxD+xx should be used for type DOUBLE. For complex numbers, two real numbers separated by a comma might look nice. It would be more FORTRAN-like to require parentheses around the pair, but then parentheses would have two meanings in LISP syntax. If the simpler syntax were used, the user could print parentheses around a complex number easily enough. A DUPLEX would be indicated by the use of DOUBLE numbers separated by a comma. (Question: what to do for something like "3.e0,4.d0"? Should the first number be converted to DOUBLE form?) Arithmetic Functions I suppose it will be necessary to introduce versions of + for each of the new data types. I propose the suffixes "$$", "%", and "%%" for DOUBLE, COMPLEX, and DUPLEX. Thus the new functions would be called +$$, +%, and +%; similarly for -, *, and //. I strongly suggest NOT having 1+$$, 1+%, etc.! How general should EXPT become? Currently it does indeed handle the case of flonum^flonum, using the standard formula with exp and log. We probably will want functions ^$$, ^%, ^%% which take fixnum-only exponents and produce the same type as they accept. The generic functions PLUS, DIFFERENCE, etc. can continue to be contagious; fixnums and bignums get converted to flonums on meeting a flonum; flonum versus double becomes double; flonum versus complex becomes complex; anything versus duplex becomes duplex. Mathematical Functions Is it desirable to have generic and specific forms for the mathematical functions, or does it matter? There is a very minor issue of the generic version having to do a type dispatch; a more difficult issue involves the semantics. Suppose we had functions variously named SQRT, SQRT$, SQRT$$, SQRT%, and SQRT%%. Clearly SQRT$ should complain on seeing a negative flonum; but should SQRT also barf on a negative flonum, or arrange to return a complex (if that version in fact has complex numbers)? Similar considerations apply to generic trig, exp, and log functions. There is no such difficulty with ABS; however, one might want specific versions anyway to help the compiler. ABS (like =) has been permitted not to have both fixnum and flonum versions partly because it is the same instruction for both on the PDP-10 (a crock). Here is a real hack: let ABS be the generic version. Let the specific versions for fixnum, flonum, double, complex, and duplex be called " ", " $", " $$", " %", and " %%" (those are spaces in the names). Because the names contain spaces, they print with vertical bars: | | | $| | $$| | %| | %%| and of course would be written that way also. Similar comments apply to MAX and MIN. I had thought for a while that we might want to adopt the FORTRAN revised standard names for many functions; however, standard FORTRAN doesn't support DUPLEX, and many of the names are meaningless (MAX0, MAX1, AMAX0, ...) or else have funny prefix letters to indicate type, so I have given up this idea (anyone object?). One theory on MAX and MIN is incompatible: let the generic versions be called MAXIMUM and MINIMUM, and let the versions for fixnum, flonum, double be MAX, MAX$, MAX$$ (same for MIN). A compatible theory is to call the specific versions IMAX, MAX$, MAX$$, or something. How do people feel about this? (There don't seem to be any good single characters to represent MAX and MIN, and anyway I am leery of tying down any more then we have already.) New Predicates NUMBERP would be extended in the obvious way, as well as TYPEP. Would we also want DOUBLEP, COMPLEXP, and DUPLEXP? SIGNP, MINUSP, PLUSP extend naturally to DOUBLE but not COMPLEX or DUPLEX. ZEROP is meaningful for all types of numbers. I think we should eliminate the ambiguity of <, >, = which was suffered primarily because the same instructions work on the PDP-10 for both fixnums and flonums. The obvious names are <$, <$$, <%, and <%%, with < meaning fixnums only (another incompatible proposal). Miscellaneous Functions Additional functions are needed for converting between various numeric types, and for constructing and decomposing complex and duplex numbers. Some suggestions: DOUBLE flonum to double conversion SINGLE double to flonum DFLOAT fixnum/bignum to double (perhaps generic, hence works for flonums and doubles) FIX works on doubles as well as flonums and fix/bignums COMPLEX of two flonum args, makes a complex DUPLEX of two double args, makes a duplex of one complex arg, makes a duplex REAL, REAL%, REAL%% real part (generic and specific) IMAG, IMAG%, IMAG%% imaginary part CONJUGATE, CONJG%, CONJG%% conjugate (generic and specific) Arrays Three new arrays types would be created for the three new data types, in the obvious manner. Compiler declarations One problem with declarations is that it would be nice to use the names DOUBLE, COMPLEX, and DUPLEX as type-conversion functions as described above; bu the compiler convention is to use the data type names as type-declaring functions. One way out would be to come up with other names for the conversion functions; however, they are sufficiently meaningful there, and close to the FORTRAN names, that I am reluctant to change them. (I might note that the full word COMPLEX is used for the above-described purpose in PL/I.) AN implementationally compatible alternative is to spell all the type declarations with a "*", retaining the current non-starred versions for compatibility. Thus we introduce *NOTYPE, *FIXNUM, *FLONUM, *DOUBLE, *COMPLEX, *DUPLEX. By analogy with *EXPR, *FEXPR, this makes a certain amount of sense. Would it be useful to have additional versions of *FIXSW and *FLOSW for the additional types? These are useful (??) to exploit the generic function names. Perhaps I have laid too much emphasis on generic and specific function names; we want to avoid the proliferation of names and include only useful ones. Completely Weird Functions I believe FSC will work on a double-precision number, but only if it is normalized. If it is not already normalized an incorrect answer results. LSH and ROT can be extended to DOUBLE numbers, returning the first word. For the sake of FASLAP we will need a function, say DBSW| (double second word) to get the second word of a DOUBLE (more on this in section 2). Do we need a LISP-level function to take the result of (LSH d 0) and (DBSW/| d) and produce a DOUBLE out of them? Systemic Considerations Internal Representations The KI10/KL10 double precision format differs from that for the KA10; namely, the entire second word (except sign bit) is extra mantissa. On the KA10, only 27. bits of the second word are mantissa. If we want to take advantage at all of the KL10 double-precision instructions, we must adopt the KL10 format (I'm not sure there is much point in supporting both formats). There are three alternatives regarding the KA10. One is not to support double-precision arithmetic on it. The second is to simulate KL10 arithmetic, which would be extremely difficult and rather slow. I propose a third alternative here which may be worth implementing if we want to fully support KA10's. The idea is to use KA10 "software" double-precision internally in a KA10 version of MacLISP. The official external format, however, remains KL10 format. It would be up to the KA10 version to convert between the two formats when necessary. The two key places are FASLOAD and DBSW|. FASLOAD must read in KL10-format doubles, and convert to KA10 format; DBSW| should arrange to return a KL10-format second word (easily accomplished with a shift). In this way the KA10 can use its own format, invisibly to the user (except that 8 fewer bits of precision are available, which of course would be advertised). One further difficulty is with compiled code which uses KL10 double-precision instructions. I believe that only eight of them will be needed, namely DMOVE, DMOVEM, DMOVN, DMOVNM (?), DFAD, DFSB, DFMP, and DFDV. Conceivably DADD, DSUB, DMUL, and DDIV might be used, but I doubt it. Anyway, the idea is that a KA10 could, within FASLOAD, substitute for these eight opcodes the opcodes 30-37 on loading a file. These UUOs would then simulate the instructions, using KA10 format, of course. This would be relatively slow, but would maintain the runnability of arithmetic code. Complex and duplex numbers would be represented as pairs of flonums or doubles in the obvious manner. One difficulty with open-coding duplex arithmetic is that one can get at the real part by indirecting through the pointer, but not the imaginary part (actually, this is true for arithmetic on complexes also, though not for moves, which can be done with DMOVE, etc.). Data Type Implementation Allocating space for two- and four-word number types will not be at all difficult, since they are very much like hunks for allocation purposes. There must be yet three more spaces (sigh), but this is not an implementation difficulty. We are running short of type bits in the left half of ST entries. I have shuffled the bits some already, by eliminating the separate bits for fixnum pdl and flonum pdl; instead, there is now a single pdl-number bit, and fixnum-pdl numbers, for example, have both the vanilla fixnum bit and the pdl-number bit set in the ST entry. (This change was upward-compatible with compiled code which checks ST entries; however, in three or six months we will want to change the magic octal constants on the compiler.) There are about five bits free now, of which three will go to the new numeric types. Number Pdls In order for NCOMPLR to win on these new numbers, we will need a corresponding new number pdl for each type. They must all be distinct pdls, and they must appear to have distinct data types. We do not have enough accumulators to go around, however. I propose the following solution: The accumulators FXP and FLP are to be regarded as a "cache" for numeric pdl pointers. Normally the fixnum and flonum pdl pointers are in these accumulators, as before. There are also memory locations called, say, DBP, CXP, and DXP, which are the "canonical homes" for the other pdl pointers. By convention, when a function call is done all pdl pointers must be in their canonical places. (The canonical places for fxp and flp are in those respective ac's, of course.) Within a function, however, the pdl pointers can be arbitrarily permuted with EXCH instructions. It is up to the programmer to keep track of which of them is where. When an interrupt occurs, the interrupt handler must determine what the hell is going on and permute the pointers back to their canonical places before running a user interrupt (arranging, of course, to restore them on return from the interrupt). This is not difficult since, after all, the pdl pointers have distinct types! By making the accumulators FXP and FLP be the canonical homes of the fxp and flp pointers, i think most existing code will work just fine. new code can permute them, use the other pdls, and permute them back. Notice that since the pdl pointers are only permuted among the canonical locations, and never copied, there are no timing problems. The compiler would need some additional organization. It would need a meta-slotlist (or whatever) to keep track of where the pdl pointers were, and would have to sync this at join points just as the pdl contents themselves are now. It would probably want "pdl" properties for internal functions similar to the current "acs" properties, which specify whether an internal function uses these pdls or not. (For example, it would not be necessary to canonicalize the pdl pointers when calling MEMQ or CONS (the latter requiring GC to be tolerant of confused PDL pointers...).) It would be possible to include SP in the pdl-swapping scheme, though I think it may not be desirable. P certainly is used too commonly to swap. (Actually, a good argument against swapping SP is twofold: the IWAIT routine which PCLSR's for user interrupts needs to check SP easily, possibly before the pdls are canonicalized; also, the interrupt handlers sometimes use FXP for temporary purposes, and this would work if any number PDL pointer were in FXP, but might cause problems with SP.) Pass 1 of the compiler could probably determine the kinds of arithmetic being used in a function and save some information for pass 2 to guide it in choosing which pdl to kick out of the cache for a new one. Some example code: (defun foo (x y) (declare (*double x y)) (barf (+$$ x y))) (lap foo subr) (dmove tt 0 a) ;fetch first arg (dfad tt 0 b) ;add second arg (exch flp dbp) ;swap in dbl prec pdl ptr (push flp tt) ;push double-flonum onto pdl (push flp d) (movei a -1 flp) ;note -1 to make correct ptr (exch flp dbp) ;swap back for call (call 1 'barf) (movn tt (% 0 0 2 2)) ;pop pdl back (addm tt dbp) (popj p) Notice that we can subtract off a swapped-out pdl faster by leaving it swapped out. Also, if two pdls have to be adjusted by the same amount we win even more. Other Compilation Considerations The compiler may find it convenient for purposes of double-precision arithmetic to think of there being two double-word accumulators (tt,d) and (r,f). Trying to allocate (d,r) could cause headaches. Similarly, it may be desirable to consider the set of four as a single, large ac for duplex arithmetic. One additional problem occurs with arrays. One needs tt for the array index, and after pulling one pair of words out with dmove there is no second number ac pair to pull out the other two into without clobbering the index. So one must be sure to fetch things in the right order. Probably in that case (r,f) should be real part and (tt,d) imaginary part; then: lsh tt,2 ;multiply by 4 dmove r,@ttsar(a) ;get real part addi tt,2 dmove tt,@ttsar(a) ;get imag part A difficulty occurs with the open-coding of ZEROP. PLUSP and MINUSP will still work on double numbers, but ZEROP, to be absolutely correct, should check both words. I guess it is true that if the first word is zero the second word better be also (otherwise the number would not be normalized), so maybe we win after all. However, ZEROP of a COMPLEX or DUPLEX must definitely check two words, and so we cannot open-code ZEROP in this case. Parhaps we should restrict ZEROP to real numbers, and require the loser to write (=% x 0.0,0.0) (possibly shortened to (=% x 0,0) if we do it right). Internal Routines We will need lots of stupid little routines like DBCONS, DBNV1, and so on. For duplex numbers, I suggest as mentioned above that the standard be to put the real part in (r,f) and the imaginary part in (tt,d). This will be backwards from everything else, but will probably save grief in the long run because of the array problem. Mathematical Software Do we want lots of crap like COSH$$ and ATAN% in the core system? Certainly the stuff in PLUS will have to be built-in, but the mathematical functions, and even stuff like +$$ and *%, could be put in a .FASL file. Maybe we need to sit down and solve once and for all the problem of hacing a single file which can either be assembled into the system or assembled as a separate .FASL file. Comments by MOON with replies by GLS Re: what to do for something like "3.e0,4.d0". -- clearly contagion rules should apply. EXCELLENT THINKING. Re: using number comma number. Is this less ugly than number+number i? If you don't allow spaces in this no really new syntax is introduced since numbers with embedded + signs and letters already exist. Also the marginal utility of pure imaginary. BALANCED AGAINST THIS IS THE POTENTIAL CONFUSION BETWEEN "I" AND "1"; BUT PURE IMAGINARIES ARE A GOOD IDEA. WE'LL HAVE TO THINK ABOUT THIS SOME MORE. Lisp machine is using % and %% prefixes. These don't really conflict with use as suffixes. Would this be confusing to users? NO MORE THAN HAULONG AND HAIPART, OR 1-$. Re: | |, | $|, etc. You have made me make a mess all over the floor of the Gosper room. I'M SORRY; I APOLOGIZE. Re: ABS, MAX, MIN. One possibility is to bring back #, as a suffix meaning FIXNUM. For + you can optionally omit it, but for MAX, MAX# is fixnum-only and MAX is the generic. OF COURSE, # USED TO MEAN "POINTER", NOT "FIXNUM", BUT IT'S NOT A BAD IDEA. OF COURSE, WE HAVE TENDED TO RESERVE # TO INDICATE AN UNREADABLE OBJECT. In the Lisp Machine we're going to have to do the type-dispatch anyway, so we probably will make everything generic. How much compatibility? Should error cases be compatible? What about fixnum-only operations, which will (probably) eventually be in-line in the microcompiler [but this may want to be done with declarations anyway.] Re: FSC working on a double-precision number. The instruction certainly doesn't. I DON'T SEE WHY NOT. IF THE NUMBER IS ALREADY NORMALIZED, THEN IT ONLY ADJUSTS THE EXPONENT. Re: Function to make a DOUBLE out of (LSH d 0) and (DBSW/| d). Isn't this just copying the double d? Or did I misunderstand? THE POINT IS THAT ONE MAY HAVE USED LSH AND DBSW/| TO MAKE TWO FIXNUMS TO OUTPUT TO A FIXNUM FILE, FOR EXAMPLE. (REGARDING THAT, IT MAY BE A GOOD IDEA TO LET OUT PROCESS ANY KIND OF NUMBER, AND HAVE FUNCTIONS VARIOUSLY CALLED IN, IN$, IN$$, ETC.? Why alter the opcodes of DMOVE, DFAD, etc. upon loading into a KA10? The instructions trap anyway. (Through 60, but ITS now pretends that they trapped through 40.) You would have to go through the system uuo handler, but that shouldn't slow it down too much, compared to it already being slow anyway. THE SCHEME I PROPOSED WOULD WORK UNDER TOPS-10. I hope the number-pdl-pointer-permuting hack doesn't run into trouble if a pdl overflows. Does the pointer still point into the space at this time? IT COULD POINT ONE WORD ABOVE THE SPACE. CERTAINLY THE PDL OVERFLOW HANDLER WILL HAVE TO BE SOMEWHAT SMARTER THAN THE AVERAGE INTERRUPT HANDLER. It is true that ZEROP of a double need only check the first word. I think this was carefully designed in. Having ZEROP randomly not work open-coded on complex would be a pain. What to do to ease the pain? ANYONE FOR ZEROP$, ZEROP$$, ZEROP%, ZEROP%%? (NOT ME!) For your information, the plan for numbers in the Lisp machine is as follows: There are two main kinds. The basic +,-,*,// operations are generic and work on all kinds. (Since they're checking type anyway.) One kind is inums (24-bit fixnums.) The other kind is extended-numbers, consisting of a pointer with DTP-EXTENDED-NUMBER to a contiguous block of N words, where the first word is a header. The pointer-field of the header contains type bits for the type of number, the count of words to follow, and additional cruft such as probably the sign, the exponent, and maybe an =0 flag. The remaining words contain bits, unfortunately can only be 24 per word. This format is used for bignums, flonums, complexes. Perhaps float and complex have arbitrary-precision, remains to be worked out. The data-type of the header word is usually DTP-HEADER, but it can be DTP-FIX if the number is embedded in some other structure, such as a pdl or an array. (This embedding is why we can only get 24 bits per word, not wanting to have separate number pdls.)  There appears to be no reason to make the default second file name different on TOPS-20 than on TOPS-10. This is a separate issue from what the variable DEFAULTF is initialized to - see points below. Commments with reasons are solicited from the BUG-LISP community. This, "default second file name", is the feature that affects only UREAD, UAPPEND, UFILE, UPROBE, and the compiler's command line parser, when only one file name is given; OPEN, and others, default the second file name thru DEFAULTF which is currently initialized inconsistently: ITS and TOPS-10 systems = ((DSK ) @ @) TOPS-20 systems = ((DSK ) FOO LISP ||) In neither case is is the second file name consistent with the "default second file name" as seen from this table: ITS = ">", TOPS-10 = "LSP", TOPS-20 = "MACLISP" I propose to make (A) the initial value of DEFAULTF have first file name "FOO" and second file name the same as the "default second file name"; and (B) the "default second file name" be as follows ITS = ">", TOPS-10 and TOPS-20 = "LSP", SAIL = "___" Some points in consideration are: 1) As was evident from the query about the default 2nd file name for MIDAS, the same extension "MID" is used for both systems. This seems like a reasonable approach, ** all other things bein equal **. 2) On TOPS-10, the extension LSP already conflicts with the standard choice for ILISP (and I presume LISP 1.6), but we are not likely to gain much by trying to change it now. CMU has adopted the standard extension MCL for maclisp code, which seems to indicate that the choice of "default second file name" could not be of primary importance to the users (since they have no files that would be selected by it). 3) There is no other extension "LSP" on TOPS-20 in standard use, and INTERLISP does not have the concept of "default second file name" since it uses the TENEX/TOPS-20 recognition feature. 4) We do not now have any MACLISP users in the TOPS-20 community, and it would be wise to get this "default" matter settled before it becomes settled "by default". 5) It greatly helps in the production of export tapes if the extensions used by TOPS-10 style are a prefix of those used by TOPS-20. Thus "MID" is a win since it is the same on both, "FASL" on the 20 is a win because it truncates to "FAS" for the 10, and "INI" can be used for both as the standard "lisp init file" extension. Does anyone on the BUG-LISP mailing list know of any other factors that might affect this choice? -- JONL -- =[?] THE FOLLOWING IS THE INTERESTING DISCUSSION THAT ENSUED BETWEEN THE LAST IMPLEMENTATION OF HUNKS AND THE CURRENT ONE. IT IS IN TWO PARTS, THE SECOND ONE PRECEDING THE FIRST HERE. THE MAIL IS IN REVERSE CHRONOLOGICAL ORDER (JUST LIKE LISP ARCHIV). HERE IS MORE MAIL ON HUNKS. AS BEFORE, MY INTERSPERSED REPLIES ARE INDENTED AND PRECEDED BY ";". ---------------------------------------------------------------- JONL@MIT-MC 06/16/76 15:40:57 TO: GLS AT MIT-MC I HAVE REASSEMBLED A HUNKLESS QIO FOR SYS UNTIL YOU DECIDE WHAT TO DO ABOUT THE BAD INTERACTION BETWEEN THE ORDERING OF SYMBOL NAMES [BIGNUM, LIST, HUNK, SUBR, ETC] AND THE VARIOUS DISPATCH TABLES SCATTERED AROUND IN THE INTERPRETER. ;I'LL FIX THEM AS SOON AS I CAN.  RZ@MIT-MC 06/16/76 15:15:07 TO: GLS AT MIT-MC WHEN YOU INSERTED THE ATOM HEADERS FOR HUNKS, YOU PUT THEM BETWEEN THOSE FOR LIST, FIXNUM FLONUM, BIGNUM ETC, AND SEPARATED THE ATOM HEADER FOR ARRAY FROM THESE. ;I DID THAT ON PURPOSE FOR SEVERAL REASONS. ; ONE WAS TO CATCH BUGS LIKE THIS (SIGH). THIS SEEMS TO SCREW UP SOME OF THE FUNCTIONAL DISPATCHES IN IAPPLY. LOTS OF LUSERS ARE COMPLAINING ABOUT ARRAYS BEING CALLED UNDEFINED WHEN THJEY PERFECTLY WELL EXIST.  MACRAK@MIT-MC 06/16/76 12:13:06 TO: GLS AT MIT-MC I FEEL IT IS IMPORTANT THAT YOU EMPHASIZE THAT THE SIZE OF A HUNK IS -FIXED- AND MUST NOT BE CHANGED BY RPLACX'S (SOMETHING WHICH STRONGLY DEPENDS ON IMPLEMENTATION AND ALSO IS NOT GENERAL ENOUGH--A 3-HUNK CAN BECOME A 4-HUNK, BUT NOT A 5-HUNK). ;MACRAK IS ABSOLUTELY RIGHT. THE LENGTH OF A ; HUNK IS FIXED ONCE IT IS CREATED. THE FACT ; THAT EXTRA SPACE IS ALLOCATED INTERNALLY IN ; THIS IMPLEMENTATION IS DANGEROUS TO TAKE ; ADVANTAGE OF. THE WAY TO HAVE AN EXPANDABLE ; HUNK THAT STAYS EQ IS TO USE AN ARRAY. BY THE WAY, WHY HUNK AND NOT SOMETHING MORE FAMILIAR, LIKE PLEX, WHICH ALSO HAS THE ADVANTAGE OF BEING AN INTERNATIONAL ROOT, LIKE CONS. BOTH ARE MEANINGLESS IN LATIN, BUT ARE CONNECTED TO IT. BASIC THINGS IN LISP MIGHT AS WELL BE EITHER MEANINGLESS (CAR, CDR) OR INTERNATIONAL, WHEN THERE IS A CHOICE. ;I KIND OF LIKE HUNK, BUT IT'S NOT TOO LATE TO ; CHANGE THE NAMES OF THINGS, I GUESS. COMMENTS, ; ANYONE? (ALSO SEE RBK'S REMARKS BELOW.) I SUPPOSE THE NEWEST PLEX-HACK MAKES SOME SENSE. IT'S NOT CLEAR THOUGH WHY (HUNK X) SHOULD BE (NCONS X) AND NOT (CONS NIL X). ;AGAIN, SO THAT THE S-EXPRESSION "(X)" WILL ; HAVE A CONSISTENT DEFINITION AS (HUNK X). FOR WHAT N IS (CXR N NIL) DEFINED? PERHAPS IT SHOULD BE ONLY FOR 0, OR (THOUGH THIS WILL RAISE DISSENT) NOT AT ALL. WHILE HUNKS ARE COMING IN, IT MAY BE THE RIGHT TIME TO FLUSH CAR/CDR ON ATOMS. ;SNERF. IT'S A PITY THERE'S NOTHING LIKE HUNKS FOR NUMBERS, WITHOUT THE OVERHEAD OF ARRAYS OR NUMBER-CONSING. I CAN SEE MYSELF WRITING A FUNCTION NHUNK (OR NPLEX) WHICH USES MUNKAM TO SHOVE NUMBERS INTO HUNKS, WITH THE ATTENDANT RANDOMIZING EFFECT ON GARBAGE COLLECTIONS (TOO MUCH MARKING)...HAVE YOU LOWERED SEGLOG TO MAKE USING HUNKS MORE MEMORY-EFFICIENT, WITH ONE HUNK SIZE PER SEGMENT? IF SO, PERHAPS THERE COULD BE NUMERICAL HUNK SEGMENTS..... OR EVEN SOME MECHANISM FOR STRUCTURES WITH BOTH, LIKE SAY MACSYMA POLYNOMIALS (CRE'S), ALTHOUGH UNLESS YOU DECLARE YOUR STRUCTURES TO THE COMPILER, AND START DOING PL/I-LIKE THINGS, YOU WOULD HAVE TO SUFFER QUITE SOME INTERPRETATION OVERHEAD. ;USING SUPER-RANDOM MUNKAMS IS RATHER DANGEROUS. ; I HAVE BANDIED ABOUT AN IDEA FOR A DATA TYPE ; CALLED A "CLOD" WHICH WOULD BE FOUR WORDS LONG, ; CONTAINING THREE MARKED POINTERS, AN UNMARKED ; POINTER, A FIXNUM, AND A FLONUM. THIS WOULD ; BE GENERAL ENOUGH TO BE EQUALLY USELESS TO ; EVERYONE. IT IS CALLED A CLOD BECAUSE THAT ; IS WHAT I WOULD CALL SOMEONE WHO TAKES THE ; IDEA SERIOUSLY... IT WOULD NOT BE HARD TO ; ADD FIXNUM HUNKS AS A NEW DATA TYPE. ONE ; PROBLEM IS THAT AS DATA TYPES PROLIFERATE ; ONE RUNS INTO ALLOCATION PROBLEMS AS THERE IS ; NO WAY TO RECLAIM SPACE ONCE IT IS ALLOCATED ; TO A PARTICULAR DATA TYPE. ENOUGH B.S.'ING FOR NOW. ;DAMN RIGHT.  RBK@MIT-MC 06/15/76 23:20:27 TO: GLS AT MIT-MC HUNKY DORY (AS THEY SAY IN THE NAVY)... BUT THEN AGAIN, NOT SO "HUNKY DORY". ALL MY LIFE I HAVE WAITED FOR HUNKS (FOR MONTHS I WAS ENAMORED WITH THE HULK JUST BECAUSE HIS NAME WAS SO CLOSE TO HUNK). AND THEN ONE FINE DAY IN JUNE, WHAT HO, THERE THEY WERE. BUT ALAS AND ALACK, WHEN ONE TRIES TO CREATE A HUNK OF ANY APPRECIABLE SIZE IN "Q" ON ML, ONE EVIDENTLY CAUSES LISP TO "ATTEMPT TO WRITE IN ROM...", WHICH IS NOT DWIM OR EVEN DWIA (=DOING WHAT IS ADVERTISED). ;A TRIVIAL BUG - ALREADY FIXED IN THE SOURCE. BUT YOU HAVE PROBABLY HEARD THIS AT LEAST 10 TIMES BY NOW, SO TO MAKE THIS COMPLAINT NOT SO HARD TO READ I HAVE TRIED TO MAKE IT A LITTLE "CUTSY". ;"CUTSY"? DO YOU MEAN "CUTESY" OR "GUTSY"? REGARDS, RAND 10-4  RBK@MIT-ML 06/16/76 23:15:29 TO: GLS AT MIT-ML IT IS OBVIOUS TO ME THAT THE WAR OF THE HUNKS WILL NOT SOON BE RESOLVED IN ANY WAY AND PROBABLY WON'T BE RESOLVED IN ANY WAY I CARE ABOUT. SO, AS AN INTERMEDIARY HACK, WHY DON'T YOU JUST PUT IN VECTORS WITH A NICE SQUARE OR CURLY BRACKET PRINT FORMAT. ;I WANT TO AVOID SQUARE BRACKETS, SINCE ; PEOPLE KEEP TELLING ME THAT SOMEDAY WE MAY ; ACTUALLY IMPLEMENT LOSING SUPER-BRACKETS. I WOULD LIKE THEM VERY MUCH, AND I REALLY DON'T CARE ABOUT THE MUNGINESS OF HAVING HUNKS BE COMPATIBLE WITH LIST, APPEND, EVAL, WHATHAVEYOU, I.E., LIST COMPATABLE WITH THOSE FUNCTIONS. OR, IS THIS WHAT MRG'S MODE CRUFT DOES? ;I DUNNO, BUT MY PROPOSAL WOULD FIT IN WELL ; WITH A MODE PACKAGE WHICH STORED A DATA TYPE ; NAME IN COMPONENT 0.  PSZ@MIT-ML 06/16/76 17:00:32 RE: HUNKS, PRINTING, ETC. TO: GLS AT MIT-ML CC: MRG AT MIT-ML, PSZ AT MIT-ML, LH AT MIT-ML, RVB AT MIT-ML WHILE THE SUBJECT OF PRINTING IS ON THE TABLE BECAUSE OF THE RECENT INTRODUCTION (AND MORE RECENT WITHDRAWAL) OF HUNKS, LET ME ALSO RAISE THE ISSUE OF HOW THINGS ARE TO BE PRINTED. 1) AS A MATTER OF PHILOSOPHY, I THINK THAT BOTH IN MACLISP AND IN ANY NEW LANGUAGES IMPLEMENTED IN IT BY EXTENSION (E.G., OWL, CONNIVER, ETC.), THERE OUGHT TO BE A CONSISTENT SET OF READ/PRINT PRIMITIVES. NAMELY, ANYTHING PRINTED SHOULD BE READABLE, AND SUCH PRINT-RELATED FUNCTIONS AS FLATSIZE, ETC. SHOULD BE MADE TO WORK WITH ALL AVAILABLE DATATYPES. ;AGREED THAT READ OF PRINT SHOULD BE AN ; IDENTITY (IN THE SENSE OF EQUAL, NOT EQ) ; AS MUCH AS POSSIBLE. THE FACT THAT READ ; CAN'T HANDLE HUNKS IS MERELY DUE TO ; MY LAZINESS AND THE COMPLEXITY OF THE READER, ; AND I WANTED TO GET SOMETHING IMPLEMENTED AND ; RUNNING FOR PEOPLE TO PLAY WITH. ;ANYTHING PRINT CAN PRINT, FLATSIZE CAN FLATTEN ; AND EXPLODE CAN DEMOLISH. (THEY ALL USE THE ; SAME INTERNAL MECHANISM, EXCEPT THAT FLATC ; HAS A SPEED HACK FOR SYMBOLS.) 2) A DESIRABLE CONSEQUENCE OF (1) WOULD BE THAT SORT-OF-STANDARD SYSTEM FUNCTIONS (E.G., GRIND, TRACE, STEP) WOULD DO SOME APPROPRIATE THING WITHOUT ANY MODIFICATION. ;THAT'S ONE REASON I AM STRIVING FOR HUNKS ; TO BE COMPATIBLE WITH LIST CELLS. THAT WAY ; GRIND ETC. WILL AT LEAST DO SOMETHING, EVEN ; IF NOT QUITE REASONABLE, DESPITE THE FACT ; THAT (ATOM ) = NIL. 3) CURRENTLY, NEITHER (1) NOR (2) ARE SATISFIED, BECAUSE INSTEAD OF REDEFINING PRINT, ETC., WE NOW TEND TO DEFINE FUNCTIONS LIKE OWL-PRINT AND THEN USE THE PRIN1 HACK (AND READ HACK) WHICH ALL LEAD TO INCONSISTENCIES (AN OWL CONCEPT USUALLY PRINTS CORRECTLY, BUT ON OCCASION--IF PASSED TO SOME POOR FUNCTION WHICH DOESN'T KNOW ABOUT OWL AND CALLS PRINT--IT'S AN INFINITE LOOP OF "("S). 4) I PROPOSE, THEREFORE, THAT THE STYLE OF LANGUAGE EXTENSION USED IN LISP BE TO ALLOW THE LANGUAGE WRITER TO REDEFINE FOR HIS LANGUAGE THE SET OF INPUT AND OUTPUT RELATED FUNCTIONS THAT DEAL WITH PRIMITIVE LOGICAL ENTITIES (ATOMS, S-EXPRS, CONCEPTS, TUPLES, ETC.). IN THE IMPLEMENTATION OF THOSE NEW LANGUAGE-SPECIFIC READ AND PRINT ROUTINES, OF COURSE, THE LANGUAGE WRITER NEEDS TO USE THE ORIGINAL BASIC LISP PRIMITIVES, WHICH SHOULD STILL BE AVAILABLE UNDER SOME OTHER NAME--SIMILAR TO THE OBARRAY HACKS IN FLAVOR. NOTE THAT ADOPTION OF SUCH A MECHANISM WOULD OBVIATE THE NEED FOR HACKS LIKE PRIN1, THOUGH OF COURSE IT WOULD REQUIRE THAT THERE BE NO "NON-UNSNAPPLE" INTERNAL SYSTEM LINKS TO KNOWN PRINT OR READ ROUTINES. ;THE I/O PROBLEM IS A SPECIAL CASE OF THE GREAT ; UNSOLVED "EXTENSIBLE DATA TYPES" PROBLEM. ; THE EXPERIENCE OF THE ECL AND CLU LOSERS ; SHOULD BE HELPFUL HERE (BUT IT ISN'T). ; COMMENTS TO GLS WELCOME. 5) AS AN AUGMENTATION OR ALTERNATIVE TO (4), ONE COULD PROVIDE A STANDARD SET OF "HOOKS" INTO THE READ/PRINT TYPE ROUTINES TO ALLOW THE STANDARD LISP ACTION IN ALL BUT A FEW SPECIALLY DEFINED CASES. FOR EXAMPLE, BY MAKING THE DISPATCH TABLE OF PRINT, FLATSIZE, ETC. LAMBDA-BINDABLE, ANY DESIRED SCHEME FOR PRINTING DATATYPES WHICH ARE RECOGNIZABLY DISTINCT TO LISP IS EASILY IMPLEMENTED. OF COURSE, TO EXTEND THIS ABILITY TO TYPES WHICH ARE DISTINCT ONLY TO THE NEW LANGUAGE (E.G., ALL IMPLEMENTED AS S-EXPRS), THE APPROACH IN (4) NEED STILL BE FOLLOWED. ;HARVARD'S ECL SYSTEM ESSENTIALLY CALLED ITS ; READER AND PRINTER (AND MANY OTHER ROUTINES) ; BY GOING THROUGH THE INTERPRETER/UUO HANDLER. ; I WONDER WHAT THER PROS/CONS OF THIS WERE. 6) REPLIES AND COMMENTS ARE WELCOME.  HGB@MIT-ML 06/16/76 12:21:00 RE: HUNKS TO: GLS AT MIT-ML CC: HGB AT MIT-ML, PRATT AT MIT-AI GUY: I LIKE THE IDEA OF HUNKS VERY MUCH. I WOULD OFFER SEVERAL SUGGESTIONS: 1) DON'T TELL ANYONE HOW MUCH STORAGE IS "ACTUALLY" BEING USED FOR HUNKS. IT IS TOO EARLY TO PIN DOWN ANY PARTICULAR KIND OF IMPLEMENTATION. ;I HAVE TO TELL PEOPLE FOR TWO REASONS: ; (1) A VERY FEW HACKERS (LIKE THE PLASMA ; PEOPLE) NEED HUNKS BECAUSE THEY ARE ; CRITICALLY TIGHT ON STORAGE. THEY CAN ; ADJUST THEIR APPLICATION SLIGHTLY TO THE ; PARTICULAR IMPLEMENTATION IF IT WILL AVOID ; WASTED SPACE. ; (2) I WANT IT WRITTEN DOWN SOMEWHERE IN CASE ; SOMEONE ELSE SHOULD HAVE TO MAINTAIN ; THE CRETINOUS CODE I HAD TO WRITE. ;YOU WILL NOTE THAT LISP RECENT CONTAINED A ; CAVEAT ABOUT DEPENDING ON THIS IMPLEMENTATION. ; SEE ALSO MACRAK'S REMARKS ABOVE. 2) THE OTHER SIDE OF THE COIN REQUIRES THAT THE USER INTERFACE BE DEFINED ELEGANTLY; I WOULD PREFER BEING ABLE TO FIND THE LENGTH OF A HUNK FAST. ;THE POINT OF HUNKS IS TO TAKE MINIMAL STORAGE. ; FURTHERMORE YOU HAVE A NON SEQUITUR THERE; ; WHAT DOES SPEED HAVE TO DO WITH ELEGANCE ; OF USER INTERFACE? 3) I WOULD NOT USE SEPARATE SPACES FOR HUNKS THE WAY YOU DO--I KNOW THAT YOU WANT TO AVOID STORING THE LENGTH. I WOULD USE ONE SPACE AND USE THE BUDDY SYSTEM TO ALLOCATE. THIS MEANS KEEPING A LIST OF LENGTH CEIL(LOG2(N)) WHICH KEEPS TRACK OF THE BLOCKS OF EACH SIZE. INITIALLY, THERE IS ONLY ONE BLOCK OF SIZE N, WHICH IS SUCCESSIVELY SPLIT AND APPORTIONED TO THE OTHER BLOCK SIZES WHEN NEEDED. ALLOCATION IS VERY FAST--THERE IS NEVER ANY NEED TO DO MORE THAN O(LOG2 N) AMOUNT OF WORK TO ALLOCATE. FREE BUDDYS ARE REJOINED BY THE GARBAGE COLLECTOR. ALL THIS IS NECESSARY IF YOU WANT TO AVOID COMPACTING HUNK SPACE (FOR EXAMPLE, IF SOME CRETIN USES MAKNUM, OR MORE CRETINOUS, MUNKAM). FOR THE PEOPLE WHO THINK POWERS OF TWO ARE WASTEFUL, A BUDDY SYSTEM CAN BE BUILT ON THE GENERALIZED FIBONACCI SERIES: F(N) = F(N-1) + F(N-K), FOR SOME INTEGER K>0. IF K=1, YOU HAVE SIMPLY THE POWERS OF TWO (ASSUMING APPROPRIATE BOUNDARY CONDITIONS); IF K=2, YOU HAVE THE NORMAL FIBONACCI NUMBERS. THE LARGER K IS, THE SLOWER THE SERIES GROWS, ALTHOUGH IT ALWAYS GROWS EXPONENTIALLY. FURTHERMORE, YOU GET TO SPECIFY THE FIRST K ELEMENTS OF THE SERIES YOURSELF! THEREFORE, IF K=5, YOU CAN CHOOSE BLOCK SIZES 1,2,3,4,5. IN THIS WAY, THE OVERHEAD FOR SMALL BLOCK SIZES IS KEPT TO A MINIMUM. THERE IS ALMOST NEVER A NEED FOR A BLOCK SIZE DISTRIBUTION OTHER THAN AN EXPONENTIAL ONE. WITH AN EXPONENTIAL DISTRIBUTION, THE AMOUNT OF SPACE WASTED BY ROUNDING UP CAN BE KEPT WITHIN A FIXED PERCENTAGE OF THE TOTAL SPACE--A NOT UNREASONABLE BEHAVIOR. OF COURSE, WITH LARGER K'S, THE AMOUNT OF WORK DONE AT ALLOCATION IS MORE, ALTHOUGH IT IS STILL O(LOG N). FURTHERMORE, ONE NEED NOT STORE THE ACTUAL SIZE OF THE BLOCK, ONLY THE INDEX INTO THE FIBONACCI SERIES. I HAVE ALMOST EVERY REFERENCE TO THE BUDDY SYSTEM EVER PUBLISHED IF YOU ARE INTERESTED. ;THANKS FOR THE EXPOSITION ON BUDDY AND ; SIMILAR SYSTEMS. I MENTIONED THE POSSIBLE ; USE OF BUDDY SYSTEM AS AN ALTERNATIVE ; IMPLEMENTATION IN LISP RECENT. I CHOSE THE ; CURRENT IMPLEMENTATION BECAUSE IT WAS VERY ; EASY TO GET UP AND RUNNING AT MINIMAL COST ; GIVEN THE EXISTING BIBOP MECHANISMS. ; (THE ADDED CODE TO THE SYSTEM PROBABLY IS ; ONLY ABOUT 200. WORDS OR LESS. ADDING ; BUDDY BLOCK AS AN SEPARATE ALLOCATION SCHEME ; WOULD COME CLOSER TO 500. OR MORE, I WOULD ; ESTIMATE.) FURTHERMORE, DETERMINING THE ; LENGTH OF A BLOCK IN BUDDY SYSTEM CAN BE ; QUITE DIFFICULT. MOST BUDDY IMPLEMENTATIONS ; EITHER STORE THE LENGTH IN THE BLOCK, ; RESERVE A BIT OR TWO IN THE BLOCK, OR ASSUME ; THE USER KEEPS TRACK OF IT AND USES EXPLICIT ; RECLAMATION. 4) ALL THIS SOPHISTICATION CAN BE ELIMINATED IF YOU ARE WILLING TO GO ON THE LINE FOR A COMPACTING HUNK SPACE (YIPPEE!). IN THIS CASE, ALLOCATION IS ABSOLUTELY TRIVIAL--INCREMENT THE FREE SPACE POINTER BY THE SIZE OF THE BLOCK. IN THIS CASE, THERE IS NO NEED FOR ROUNDING--SIMPLY ALLOCATE EXACTLY THE SIZE NEEDED. I WOULD MOST CERTAINLY STORE THE SIZE OF THE HUNK IN INDEX 0 OR -1, THOUGH, FOR THE GARBAGE COLLECTOR IF FOR NO ONE ELSE. THE COMPACTING GARBAGE COLLECTOR IS TRIVIAL FOR THIS SPACE, AS YOU ARE NO DOUBT ALREADY AWARE. ;WE ALREADY HAVE THIS IMPLEMENTED. ; THEY ARE CALLED ARRAYS. 5) I GO ON RECORD AS FAVORING A COMPLETELY NEW FORMAT FOR THE PRINTING AND READING OF HUNKS. I ALSO HAVE NO PROBLEMS ACCEPTING (CDR H) AS MEANING THE SECOND, RATHER THAN THE LAST, ELEMENT. I WOULD NOT USE CURLY BRACKETS, BECAUSE SETS MAY SOMEDAY BECOME THE FASHION; MIGHT WORK PRETTY WELL. ;CAN'T USE < AND > - THEY ARE THE NAMES OF ; LISP FUNCTIONS. CAN'T USE [ AND ] - HAVE TO ; SAVE THEM FOR SUPER-BRACKETS. CAN'T USE ; BRACES - MIGHT WANT TO IMPLEMENT SETS. ; CAN'T USE HORSESHOES - THEY ARE ^P AND ^Q, ; AND PEOPLE USE THE LATTER FOR UREAD, ETC. ; CAN'T USE LESS-OR-EQUAL AND GREATER-OR-EQUAL ; - THEY ARE ^\ AND ^]. SOME LOSER ACTUALLY ; SUGGESTED '[ AND ]' - SHADES OF PLANNER! ; WHAT TO DO? HENRY  RMS@MIT-AI 06/16/76 17:02:04 TO: GLS AT MIT-AI WHAT DOES IT MEAN FOR AN ELEMENT OF A HUNK TO BE "MARKED UNUSED"? DO YOU USE THE OTHER GC MARK BUTS FOR THIS? OR DOES "UNUSED" MEAN NIL? IN THAT CASE, YOU SHOULD SAY "NIL" RATHER THAN "UNUSED", AND PRINT SHOULD CERTAINLY NOT SCREW UP BECAUSE THERE IS AN INTERVENING NIL. FOR THAT MATTER, IT IS A BUG THAT |AB^@CD| PRINTS AS AB, AND IT SHOULD BE CHANGED. ;WELL, IT IS ALSO A KIND OF BUG TO GET ; NULLS IN THE MIDDLE OF A PRINT NAME. ; FIXING IT WOULD BE A PAIN, SO I'LL ; DEFER IT UNTIL SUCH TIME AS IT IS ; SCREWING SOMEONE. I AM NOT SURE I LIKE HAVING HUNKSIZE RETURN THE NUMBER OF "USED" ENTRIES IF NIL CAN'T BE DISTINGUISHED FROM UNUSED. AT LEAST, THERE SHOULD BE SOME WAY OF GETTING THE PHYSICAL SIZE OF THE HUNK, SO ONE CAN TELL WHAT INDICES ARE LEGAL. ;THERE IS - THE HUNKSIZE PRIMITIVE. ; IT WAS DESCRIBED IN LISP RECENT. IN ADDTION, IF UNUSED = NIL, IT MEANS THAT THERE CAN BE, DUE TO RPLACX'S, A HUNK WHOSE "SIZE" IS LESS THAN HALF ITS ACTUAL SIZE. IN THAT CASE, PRINTING IT OUT AND READING IT BACK WOULD TRUNCATE IT, WHICH IS WRONG. SUCH A HUNK MUST BE PRINTED WITH ENOUGH NIL . NIL . NIL . ... IN IN IT TO SHOW HOW BIG IT REALLY IS. ;UNUSED SLOTS ARE FILLED WITH AN "ILLEGAL" ; POINTER (ALL ONES - 777777). THIS IS SIMILAR ; THE USE OF "UNBOUND" IN VALUE CELLS. THERE IS ; NO POSSIBLE CONFUSION WITH NIL.  PRATT@MIT-AI 06/16/76 10:28:32 TO: GLS AT MIT-AI YOUR PROPOSED SOLUTION TO THE PROBLEM OF ORDERING HUNKETS (HOW'S THAT FOR A NAME FOR HUNK FIELDS?) IS MINE (MY FIRST ONE) WITH THE +1 MOVED FROM FETCH TO STORE. IT'S BEAUTIFUL! NOW I CAN THINK OF THE ELEMENTS NUMBERED USING 1-ORIGIN INDEXING, PROVIDED I REMEMBER TO WRAP AROUND AT THE END. WHEN SCANNING A HUNK IN THE ORDER HUNKIFIED, USERS WILL HAVE TO START FROM 1 AND COMPUTE MOD H, AS IN MY PROPOSAL BUT WITH THE MOD H BEING DONE BY THE USER RATHER THAN THE SYSTEM. AFTER ALL MY GRUMBLING ABOUT 0 VS 1 ORIGIN, I'M DAMNED IF I KNOW WHY I DIDN'T SEE IT BEFORE! ;ME TOO. I DON'T KNOW IF PEOPLE WILL REALLY ; WANT TO DO MOD N CALCULATIONS, BUT I DO ; THINK THIS IS THE MOST REASONABLE COMPROMISE.  ---------------------------------------------------------------- MANY PEOPLE HAVE COMPLAINED ABOUT THE IMPLEMENTATION OF HUNKS DESCRIBED IN THE PREVIOUS LISP RECENT. I RECEIVED MANY SUGGESTIONS AS TO HOW TO FIX IT. THE PROBLEM IS THAT THERE ARE SEVERAL COMPETING CONSTRAINTS: (1) COMPONENTS SHOULD PRINT IN ORDER. (2) THE ACCESS ALGORITHM SHOULD BE FAIRLY SIMPLE. (3) THE COMPILER SHOULD BE ABLE TO OPEN-CODE ACCESSES. (4) CAR AND CDR SHOULD BE COMPATIBLE WITH LIST CELLS. (5) CDR SHOULD (CONCEPTUALLY, AT LEAST) BE THE LAST COMPONENT, AND CAR THE FIRST COMPONENT. (6) A HUNK OF N POINTERS SHOULD REQUIRE NO MORE THAN (18. * N) + 1 BITS TO STORE (ONE BIT FOR GC). THE CURRENT IMPLEMENTATION SATISFIES (2), (3), AND (4). FOR EASE OF ALLOCATION IT USES (18. * N') + N/2 BITS OF STORAGE, WHERE N' IS A POWER OF TWO NO SMALLER THAN N. THE COMPONENTS DO NOT PRINT IN ORDER SO THAT LIST NOTATION WILL BE COMPATIBLE (A COROLLARY TO (4)). IT BLOWS (5) COMPLETELY. AFTER SOME CONSIDERATION, I WOULD LIKE TO PROPOSE THE FOLLOWING ALTERNATIVE: LET (CXR 0 X) = (CDR X), (CXR 1 X) = (CAR X), ETC. THAT IS, HUNKS WOULD BE STORED AS FOLLOWS: ----------------- | 1 | 0 | ----------------- | 3 | 2 | ----------------- : : : ----------------- | N-1 | N-2 | ----------------- HUNKS WOULD BE PRINTED AS NOW, I.E. COMPONENTS 1 THROUGH N-1, FOLLOWED BY COMPONENT 0. SO THAT (HUNKIFY 1 2 3) WOULD PRINT AS (1 . 2 . 3), THE ARGUMENTS TO HUNKIFY WOULD BE IN THE ORDER 1, 2, 3, ..., N-1, 0 (CDR LAST). AS BEFORE, (HUNKIFY X) = (NCONS X). IT WOULD BE POSSIBLE TO HAVE AN ALTERNATIVE PRINT FORMAT WHICH WOULD PRINT (HUNKIFY 0 1 2 3 4) AS {0 1 2 3 4}. (I WOULD LIKE TO AVOID USING SQUARE BRACKETS.) MAYBE WE COULD EVEN HAVE A HOOK FOR LETTING A USER FUNCTION GET IN (SIGH). FINALLY, I WOULD LIKE TO RENAME HUNK TO BE *HUNK, AND HUNKIFY TO BE HUNK. PLEASE SEND SUGGESTIONS OR COMMENTS TO GLS. ---------------------------------------------------------------- I HAVE RECEIVED SO MUCH INTERESTING MAIL ALREADY ON THE MATTER OF HUNKS THAT I WOULD LIKE TO SHARE IT WITH PEOPLE. HERE IS THAT MAIL, INTERSPERSED WITH POINT-BY-POINT REPLIES BY YOURS TRULY. MY COMMENTS ARE INDENTED AND PRECEDED BY ";" (WHAT ELSE?). ---------------------------------------------------------------- MSG: HUNKS 1 GLS@MIT-MC 06/15/76 19:51:11 RE: HUNKS THE IMPLEMENTATION OF HUNKS WILL PROBABLY CHANGE WITHIN THE NEXT COUPLE OF DAYS TO REMOVE THE GROSS PRINT ORDER. I AM NOT SURE WHAT I WILL DO, BUT IT WILL BE BETTER THAN THE CURRENT THING. I APOLOGIZE FOR THE KLUDGE - I HAD THREE OR FOUR CONFLICTING REQUIREMENTS, AND RESOLVED THEM ONE WAY. THE OVERWHELMING RESPONSE HAS BEEN FOR A DIFFERENT RESOLUTION OF THESE CONFLICTS. BY THE WAY, I TAKE ALL THE BLAME FOR THE CROCKISH DOT NOTATION, SINCE I MODIFIED RMS'S ORIGINAL PROPOSAL. THANK YOU ALL FOR THE QUICK RESPONSE. -- GUY STEELE P.S. I ASSEMBLED THE FEATURE ONLY INTO NEWIO THIS TIME AROUND SO NO ONE WOULD BE TOTALLY SCREWED IF THE FEATURE DIDN'T WORK. SOON IT WILL BE AVAILABLE IN ALL LISPS.  DATE: 15 JUN 1976 1919-EST FROM: ROBERT V. BARON (RVB @ MIT-ML) SUBJECT: HUNK PRINT OUT. TO: BUG-LITHP AT MIT-ML, RMS AT MIT-AI CC: PSZ AT MIT-ML PSZ HAS POINTED OUT THAT THERE IS A PROBLEM WITH HUNKS IN THAT THEY CAN'T BE READ IN BY THE STANDARD READER. I COULD COMPLAIN THAT I DON'T LIKE THE WAY HUNKS PRINT OUT; I WOULD MUCH PREFER TO SEE A HUNK OF A1, A2, A3, A4 PRINT OUT AS [ A1 A2 A3 A4 ]. (NEEDLESS TO SAY I WOULD HAVE A READ MACRO THAT ACCOMPDATED READING IN OF HUNKS IN THIS FORM.) BUT,.... I AM SURE THIS IS NOT GENERALLY USABLE FOR ALL USERS. SIMILARLY I AM SURE THAT YOU WILL SEE OTHER SUGGESSTIONS FOR HUNK PRINT OUT. I WOULD LIKE TO PROPOSE THE "MOST GENERAL SUGGESTION" FOR HUNK PRINTOUT: LET THE ATOM "HUNK-PRINT" IF NON NIL BE CALLED BY THE PRINT LOGIC WHEN A HUNK IS ENCOUNTERED. IT IS THE USERS RESPONSIBILITY TO DECIDE HOW TO PRINT THE HUNK. IF "HUNK-PRINT" IS NIL, THE DEFAULT HUNK PRINT OUT IS PREFORMED. IT IS THE USERS PROBLEM ALSO TO MAKE SURE THAT HE CAN READ IN HUNKS HE HAS PRINTED OUT. ;WELL, THIS MAY HAPPEN. ONE NICE THING ABOUT ; THE DOT NOTATION IS THAT IT IS GUARANTEED ; COMPATIBLE WITH ALL CURRENT MACRO CHARACTERS. ALSO "HUNK-PRINT" WOULD PROBABLY BE A LEXPR WHICH IS GIVEN THE HUNK SIZE AS ITS ARGUMENT, AND THE HUNK WOULD BE SPREAD ONTO THE STACK. OTHER MANNERS OF INTERFACE ARE POSSIBLE OF COURSE. ;THIS SOUNDS LIKE A SINGULARLY USELESS INTERFACE, ; SINCE THE STACK SPREAD SAVES NO CONSING AND ; THE HUNKSIZE FUNCTION IS AVAILABLE. -------  PRATT@MIT-AI 06/15/76 18:18:56 TO: BUG-LISP AT MIT-AI ON THE PRINCIPLE THAT I MAY AS WELL BE HUNK FOR A SHEEP AS A LAMBDA, HERE ARE SOME COMMENTS ON LISP RECENT. ;SO CONSIDER YOURSELF HUNK. 1. 3RD LINE (1-ORIGIN INDEXING) OF [5B]: N'TH ELEMENT -> N'TH ELEMENT (0-ORIGIN INDEXING) 2. 17TH AND 19TH LINES OF [5B]: (RPLACX 0 A?) -> (RPLACX 0 H A?) ;SORRY - H WAS OMITTED AS SECOND ARGUMENT IN TWO PLACES. 3. SEEMS ONLY TO BE OFFERED IN NEWIO, NOT IN OLDIO. 4. (HUNK I) FOR I>1 DOESN'T SEEM TO WORK. ;A BUG. WILL BE FIXED SOON. 5. WITH *RSET T, (CXR -200 X) DOESN'T PROTEST. MAKES IT TOUGH TO DEBUG. ;THIS WILL BE FIXED UP. 6. HUNKSIZE AND PRINT HAVE DIFFERENT IDEAS ON WHEN TO STOP. HUNKSIZE USES THE HIGHEST CELL NOT MARKED UNUSED, WHILE PRINT USES THE LOWEST CELL MARKED UNUSED. ;IN THE FOOTSTEPS OF A GRAND OLD TRADITION. ; (PRIN1 (MAKNAM '(101 102 0 103 104))) ; PRINTS "AB", NOT "ABCD" OR "AB^@CD". HOW ABOUT A HUNK KNOWING HOW BIG IT IS BY HUNKIFY STORING THAT VALUE SOMEWHERE? THEN BOTH HUNKSIZE AND PRINT COULD USE THAT VALUE. ALSO WITH *RSET T, THE VALUE WOULD BE OF USE IN CATCHING OUT-OF-RANGE INDICES. THE FOLLOWING IS YET ANOTHER USE. ;IT WOULD TAKE ADDITIONAL STORAGE TO KEEP THE SIZE ; AROUND. FOR HUNKS IT IS DEEMED PREFERABLE TO ; KEEP DOWN THE STORAGE SPACE. 7. RECALLING THE OLD APPALACHIAN WOMAN'S ADVICE ON MARRIAGE, THE ADVICE FOR PRINTING A HUNK SHOULD BE, "DON'T EVER DO IT." HERE'S A SOLUTION TO THE CURRENT MESS: (I) (AFFECTS CORRECTNESS): MAKE CDR THE LAST RATHER THAN THE 1ST (YOUR 0-ORIGIN INDEXING AGAIN!) ELEMENT OF A HUNK. OH NO, YOU SAY, THEN CDR COULDN'T BE APPLIED EFFICIENTLY TO A HUNK4 OR LARGER. NO PROBLEM: (II) (AFFECTS EFFICIENCY): LET H HAVE HUNKSIZE H. THEN (CXR N H) SHOULD BE WORD ((N+1) MOD H)/2 , CHOOSING LEFT HALF IFF (N+1) MOD H IS ODD. THUS (HUNKIFY 0 1) WILL STORE AS 0 1 , (HUNKIFY 0 1 2) AS 0 2 # 1, (HUNKIFY 0 1 2 3) AS 0 3 2 1, (HUNKIFY 0 1 2 3 4) AS 0 4 2 1 # 3 # #, (HUNKIFY 0 1 2 3 4 5) AS 0 5 2 1 4 3 # # , AND SO ON. NOTE THAT THIS SCHEME PRESUPPOSES THAT H IS ACCESSIBLE, AS PROPOSED UNDER 6 ABOVE. ANOTHER SCHEME THAT MAY HAVE MINISCULE SPEED ADVANTAGES IS TO TAKE (CXR N H) TO BE WORD MIN(N, H-N-1); IF H-N-1) = (CXR 1 ) IS, UNDOUBTEDLY, INTERNAL EFFICIENCY SINCE THAT WAY CDR IS APPLIED UNIFORMLY TO ANY LENGTH HUNK (INCLUDING CONS CELL). YOU SHOULD REALIZE, HOWEVER, THAT THIS IS MERELY AN IMPLEMENTATION ISSUE AND NEED NOT BE REFLECTED IN THE EXTERNAL APPEARANCE OF HUNKS. TO WIT, I AM DISTURBED BY: (HUNKIFY 0 1 2) ==> (0 . 2 . 1) WHICH VIOLATES MY GOOD SENSE OF HOW LISTS, ARRAYS, RECORDS OR ANY NORMAL DATATYPE IN ANY NORMAL PROGRAMMING LANGUAGE WORKS. HOWEVER, IF YOU WERE WILLING TO CHANGE YOUR DEFINITION OF CDR TO MEAN (CXR ) IN THE EXTERNAL NOTATION BUT INTERNALLY IMPLEMENT HUNKS IN SUCH A WAY THAT THE ORDER OF STORAGE IS 0,N-1,1,2,3,...,N-2 THEN YOU WOULD HAVE A DOUBLE WIN: THE IMPLEMENTATION EFFICIENCY WOULD REMAIN, AND AT THE SAME TIME YOUR NICE NOTATION HACK WOULD ALSO REMAIN, BUT SOLVE THE DISCONCERTING RE-ORDERING PROBLEM. ;BUT, AS NOTED ABOVE, THE COMPILER WOULD HAVE ; NO HOPE OF OPEN-CODING CXR REASONABLY. 4) IF AND WHEN READ KNOWS HOW TO READ THESE THINGS, THERE OUGHT TO BE A SWITCH WHICH DECLARES THEM VOID, SO THAT DOT CONTEXT ERRORS WILL CONTINUE TO BE DETECTABLE FOR PEOPLE WHO FORGO HUNKS BUT MAKE LIST ERRORS. ;AGREED. 5) OBVIOUSLY, IT IS NOW TIME TO BUILD A NICE (TYPE CHECKED?) RECORD PACKAGE ON TOP OF THIS. ;PROBABLY MRG SHOULD BE CONSULTED. IS THE LENGTH LIMITATION (N<17) ESSENTIAL? ;NO, IT IS AN ASSEMBLY PARAMETER. I CHOSE 16. AS ; THE LARGEST SIZE ARBITRARILY. LET ME KNOW HOW ; MUCH YOU NEED.  SEF@MIT-AI 06/15/76 14:34:20 TO: GLS AT MIT-AI ONE MORE THOUGHT ABOUT HUNKS: (HUNKIFY A B C ...) IS A LOT TO TYPE FOR SOMETHING THAT WILL BE USED FAIRLY OFTEN, CORRESPONDING TO CONS. HOW ABOUT HONS OR HUNS OR CXNS OR SOMETHING SIMILAR? ;AGREED. I WOULD LIKE TO CHANGE: ; HUNKIFY => HUNK ; HUNK => *HUNK  SEF@MIT-AI 06/15/76 14:18:23 TO: GLS AT MIT-AI HUNKS LOOK LIKE A DEFINITE WIN FOR MANY THINGS. TWO SUGGESTIONS, HOWEVER: 1. IT WOULD BE NICE TO HAVE HUNK SIZES IN MULTIPLES OF TWO INSTEAD OF POWERS. SIX WOULD BE ESPECIALLY NICE FOR SOME OF MY STUFF. ;THEY ARE ALLOCATED BY POWERS OF TWO BECAUSE IT MAKES ; THE IMPLEMENTATION SO MUCH EASIER. NOTE, HOWEVER, ; THAT (HUNKSIZE (HUNKIFY 0 1 2 3 4 5)) => 6. I ADMIT ; A MORE CLEVER IMPLEMENTATION COULD REMOVE THE WASTE. 2. PLEASE REGISTER MY VOTE AGAINST RMS'S CROCKISH PRINTING CONVENTION. I WOULD MUCH PREFER (1 . 2 . 3 . 4), ETC., AND DAMN THE "ELEGANT" EXTENSIONS. PERHAPS A NICE SWITCH TO LET EVERYONE HAVE HIS OWN PREFERENCE? ;SIGH. YET ANOTHER SWITCH. OR PERHAPS ONE COULD GAIN THE BEST OF BOTH WORLDS BY LETTING THE LAST ELEMENT IN A HUNK CORRESPOND TO THE CDR OF A LIST CELL. FOR EASY INTERFACING TO EXISTING FUNCTIONS, THIS LAST CELL COULD ACTUALLY BE STORED IN POSITION 2, BUT WOULD APPEAR LAST IN BOTH HUNK INPUT AND OUTPUT. THIS SEEMS NO MORE CONFUSING THAN BEFORE, AND WOULD BE MORE TRANSPARENT TO THE CASUAL USER, SINCE HUNK INPUT AND OUTPUT ORDERING WOULD BE THE SAME. AND IT SEEMS AS EASY TO THINK OF CDR AS THE LAST POINTER IN A "CELL" AS TO THINK OF IT AS THE SECOND ELEMENT. KEEP UP THE GOOD WORK.-- SCOTT FAHLMAN  DVM@MIT-AI 06/15/76 09:19:29 (1) WHEN DO HUNKS ARRIVE? ;THEY ARE HERE - I ONLY PUT THEM IN NEWIO THIS TIME ; SO PEOPLE COULD USE OLDIO IF HUNKS SCREWED THE WORLD. (2) IN THE HUNK DOCUMENTATION, I THINK THERE IS A MISPRINT IN THE DEFINITION OF HUNKIFY. ITS SECOND ARGUMENT SHOULD BE "A1," NOT "A2." THIS CAUSES INCREDIBLE CONFUSION GIVEN THE DISCUSSION OF NON-STANDARD PRINTING WHICH FOLLOWS! ;ABSOLUTELY RIGHT - "A1" WAS ACCIDENTALLY OMITTED ; BETWEEN "A0" AND "A2".   _ A User's Guide to the Fast Arithmetic Feature of the Lisp Compiler Eric Rosen 4/25/72 1- Introduction The fast-arithmetic feature of NCOMPLR attempts to take advantage of the new uniform representation of numbers in NLISP by open-coding arithmetic expressions, i.e. by generating machine instructions to do arithmetic, in lieu of generating calls to LISP's arithmetic functions. It will also generate compare or conditional jump instructions in lieu of calls to MINUSP, ZEROP, PLUSP, GREATERP, LESSP, SIGNP, and for numeric arguments, EQUAL. In order to facilitate this, the user MUST make declarations to the compiler, so the compiler knows which of the user's functions and variables have numerical values, and whether these values are fixnum or flonum. The compiler introduces a new data type which has no analogue in the interpreter, i.e. number quantities. A number quantity is merely a machine number. A LISP number is actually a pointer to a word in garbage-collectable FIXNUM or FLONUM space which contains a machine number; a number quantity is a machine number itself, with no intervening pointer. The compiler will automatically handle the intermediate results of open-coded PAGE 2 arithmetic expressions as number quantities. Also, by suitable use of declarations, the user may inform the compiler that certain of his variables are to be treated as number quantities. Number quantities are not stored in garbage-collectable space, but on the FIXNUM or FLONUM PDLs. Open compilation is, of course, only relevant to single- word arithmetic. Those users who wish to utilitize infinite- precision integer arithmetic (BIGNUMS) MUST close-compile their code. 2- Number Variables The following declarations enable the user to tell the ccmpiler which of his variables are always going to have either fixnum or flonum values, and whether these values are fixed or floating point: (DECLARE (FIXNUM XVAR1 XVAR2 ... XVARn) (FLONUM LVAR1 LVAR2 ... LVARn)) In the case of local variables (i.e. variables which have not been declared or made special) these declarations indicate that the value of the variable is a number quantity. In the case of special variables, these declarations indicate to the compiler that the value of the variable is a LISP number of the given type. (For technical reasons, no special variable can have a number quantity as its value.) It is important to realize that number variables, i.e. PAGE 3 variables whose values are number quantities, do not exist in the interpreter. Thus a number variable is not a LISP variable in the usual sense, and there are restrictions on its use. A NUMBER VARIABLE MAY NEVER HAVE ANY OTHER VALUE THAN A NUMBER. Furthermore, a fixnum number variable may never have a flonum value, and vice versa. If these restrictions are ignored, errors will result. The compiler will try to detect such errors, but most of them cannot be detected at compile time. Thus the user must be very careful to pay heed to these restrictions. FAILURE TO DO SO WILL MEAN THAT CODE WHICH MAY RUN PERFECTLY WELL UNDER THE INTERPRETER WILL RUN ERRONEOUSLY WHEN COMPILED. The user should be particularly careful with PROG variables that are also number variables. The interpreter initializes all PROG variables to NIL. However, since number variables may not have the value NIL, the compiler initializes number PROG variables to 0 or 0.0. Because of this inconsistency with the interpreter, IT IS AN ERROR TO USE NUMERIC PROG VARIABLES BEFORE INITIALIZING THEM. Again, the compiler will try to detect these errors, but will not always be able to. It is, of course, permissible to SETQ or LAMBDA-bind number variables to any expression whose value is a number, be it a number quantity or a LISP number. It is also permissible to SETQ or LAMBDA-bind LISP variables to number variables. In all cases the compiler will cause the correct conversion to be PAGE 4 done. It should be realized that if a number quantity is ever CONS'd into a list structure, it will have to first be converted into a LISP number. This is relatively expensive in time, because repeated number CONSing will cause more frequent garbage collections. The compiler makes every effort to avoid number CONSing, and therefore number CONSing is done only when absolutely necessary. However if the user keeps any numerical parameters for the purpose of CONSing them into lists, he may be better off making them regular LISP variables. (Parameters which are to be used in arithmetic computation are, of course, best kept in number variables.) The following declaration is available for negating the effect of previous FIXNUM or FLONUM declarations. (DECLARE (NOTYPE VAR1 VAR2 ... VARn)) 3- Declaring functions The following declarations are available for declaring functions to the compiler: (DECLARE (FIXNUM (XFN1 ARG1 ... ARGn) ... (XFNm ARG1 ... ARGn)) (FLONUM (LFN1 ARG1 .. . ARGn) .. . (LFNm ARG1 ... ARGn)) (NOTYPE (NFN1 ARG1 ... ARGn) ... (NFNm ARG1 ... ARGn))) PAGE 5 Of course, variable declarations may be intermingled with function declarations as in: (DECLARE (FIXNUM VAR1 VAR2 (FN FIXNUM NOTYPE))) The arguments to these FIXNUM, FLONUM, and NOTYPE declarations are lists. The CAR of each list is the name of the function being declared. The CDR of each list is a list of the types of the arguments of the functions, where each argument type is either 'FIXNUM' (or, as an abbreviation, any fixnum number), 'FLONUM' (or any flonum number), or 'NOTYPE' (or 'NIL'). The main declaration tells what kind of value the function returns. Hence these declarations have the effect of both declaring what kinds of arguments the function takes, and what kind of value it returns. For example, suppose function FOO returns a floating point number. Further, suppose FOO has three arguments - a fixed-point number, a random list, and a floating point number. The appropriate declaration is: (DECLARE (FLONUM (FOO FIXNUM NOTYPE FLONUM))) Suppose BAR is just like FOO, except that its value is not numeric. The appropriate declaration is: (DECLARE (NOTYPE (BAR FIXNUM NOTYPE FLONUM))) Arguments may be omitted on the right, in which case NOTYPE is assumed. For instance, if FOOBAR has three arguments , the following two declarations are completely equivalent: PAGE 6 (DECLARE (FIXNUM (FOOBAR FLONUM NOTYPE NOTYPE))) and (DECLARE (FIXNUM (FOOBAR FLONUM))) THE SAME DECLARATION MUST BE IN FORCE WHEN A FUNCTION IS COMPILED AS WHEN A CALL TO THAT FUNCTION IS COMPILED. If this rule is not followed, the functions may not interface properly, causing random results and/or LISP errors. Compiled functons should interface properly with uncompiled functions , however, regardless of declaratons. 4- Scope of declarations Declarations are either global, or local to the nearest- enclosing PROG or LAMBDA in which they appear. If a declaration occurs which is not within a function definition, it is global. It maintains its effects until countermanded by some other global declaration or temporarily overridden by a local declaration. Local declarations should always appear as the first statements of the PROG or LAMBDA in which they occur. They affect only the PROG or LAMBDA in which they occur, and they take precedence over any conflicting global or superior (in position) local declarations. When a function declaration is used to declare the arguments of the function, the scope is just the function in question. Only FIXNUM, FLONUM, and NOTYPE declarations are legal PAGE 7 as local declarations. All other declarations must be global, i.e. they cannot appear within a function body. It is not legal to locally undeclare a variable (i.e. by using the NOTYPE declaration). The only use of local function declarations is to declare bound variable functions. For example, where 'X' is a bound variable the declaration (DECLARE (FIXNUM (X FIXNUM))) means that 'X' is bound to a function whose first (perhaps only) argument is a fixnum and which returns a fixnum value. In order for this declaration to work properly, all the functions to which 'X' may be bound must have been so declared when they were compiled. 5- Open-coding arithmetic expressions The compiler is able to open-code the following arithmetic functions: PLUS, TIMES, DIFFERENCE, *DIF, QUOTIENT, *QUO, ADD1, SUB1, REMAINDER, MINUS, ABS, FIX, FLOAT, MINUSP, PLUSP, SIGNP, BOOLE, ROT, LSH, GREATERP, LESSP, and if its arguments are numeric, EQUAL. (DECLARE (CLOSED T)) inhibits open-coding. (DECLARE (CLOSED NIL)) enables it, and is the default option. If the compiler cannot figure out whether the arguments to the above functions are fixnums or flonums, it will be forced to generate a call to the appropriate routine in the interpreter. The compiler makes use of the user's declarations to determine the PAGE 8 types of the arguments. When the compiler encounters an expression with an argument whose type it can not determine, it tries to open-compile as much of the expression as it can. If an expression has to be even partially closed-compiled the compiler will print a warning message. This message is expected to be of aid to users who would like open-compiling but who aren't getting it because they forgot to make a declaration. However, users who want some expressions to be closed-compiled may want to inhibit this message by saying (DECLARE (MUZZLED T)). The compiler also offers the user other ways to force open-compilation. If the user says (DECLARE (FIXSW T)) , the compiler will assume that all arguments to open-codable functions (except, of course, EQUAL) are fixnums. Similarly, the user can (DECLARE (FLOSW T)) if he is only using flonums. The LISP functions + , - , * , / , | , 1+ , 1- , are just like PLUS , DIFFERENCE, TIMES, QUOTIENT, REMAINDER, ADD1, and SUB1 except that the former may take only fixnum arguments. Therefore the compiler is able to always open-code the former. Similarly, the LISP functions +$, -$, *$, /$, 1+$, and 1-$ (these are real dollar signs, not alt. modes) may take only flonum arguments, and are always open-coded. The predicates >, <, and = are also always open-coded; they correspond to GREATERP, LESSP, and EQUAL except that they always have two numerical arguments of the same type. (In these last 3 cases, PAGE 9 the compiler need not know which type the arguments are). The third way to force open-coding is by means of the ARITH declaration. The declaration (DECLARE (ARITH (FIXNUM ADD1 SUB1) (FLONUM QUOTIENT))) effectively causes all SUB1's to be replaced by 1-'s, ADD1's by 1+'s, and QUOTIENTS by /$'s. To revert back to normal (DECLARE (ARITH (NOTYPE ADD1 SUB1 QUOTIENT))). These techniques just described are NOT a substitute for declaring variables and functions. They are useful in cases where the compiler will not be able to determine the type of an argument, for instance (PLUS (CAR X) (CADR X)). Obviously the compiler has no way of knowing that (CAR X) is going to be a fixnum. So in a case like this, there is a definite advantage to using + instead of PLUS. And if all the user's arithmetic is in the same mode, a FIXSW or FLOSW declaration may be good for him. If a (FIXSW T) declaration is made, the only way to do any flonum arithmetic at all is to use a function which assumes that its arguments are flonums, e.g. +$. 6- Arrays The user should always declare his arrays to the compiler. The ARRAY* declaration is available for this purpose. (Note that 'ARRAY*' is not '*ARRAY; the latter is a LISP function). For instance, (DECLARE (ARRAY* (FIXNUM FOO 1 BAR 2) (FLONUM ARY 3) PAGE 10 (NOTYPE FOOBAR 1 ARY2 2))) This declares FOO to be a 1-dimensionsal array of fixnums, BAR a 2-dimensional array of fixnums, ARY a 3-dimensional array of flonums, FOOBAR a 1-dimensional array of random S-expressions, and ARY2 a 2-dimensional array of S-expressions. Undeclared arrays will be handled properly, but at great loss of efficiency. It should be understood that arrays cannot [currently] contain machine numbers - only LISP s-expressions, including LISP numbers, are permitted. However, by the end of calendar year 1973, there will be two new types of arrays implemented in LISP, the FIXNUM array and the FLONUM array, which will in fact contain machine numbers of the stated type. Accessing the elements of such arrays will be open-coded by NCOMPLR, and the resultant code should be speed-competitive with FORTRAN array accessing [except that there are no plans for implementing the hairier optimizations done by really good FORTRAN compilers}. 7- Miscellany The fast-arithmetic compiler is loaded by 'NCOMPLR~K', but all other interactions with it are exactly the same as with complr [command line parsing, compilations switches, etc.]. The code it produces runs only in LISPs with version number greater than 400. For general information on LISP, see Lisp Archiv. PAGE 11 Any bugs in the NCOMPLR should be reported to Eric Rosen (ECR) or Jonl White (JONL).  MIDAS.410 ****JMCLISP *U** LItITERPR"A3 4E *U*********S`ÙISP VɟN 785 [1785] ASSEMBLED ON ITS AT MC INITIAL SWITCH VALUES (*=EXPERIMENTAL): ITS=0 TOPS10=0 TOPS20=0 SAIL=0 * TENEX=0 * CMU=0 KA10=0 * KI10=0 * KL10=0 ML=0 BIGNUM=1 EDFLAG=1 OBTSIZ=777 FUNAFL=1 QIO=1 JOBQIO=1 HNKLOG=6 USELESS=1 * DBFLAG=0 * CXFLAG=0 * NARITH=0 * SFA=0 REDEFINITIONS: TTY: .INSRTed, end input with ^C ML==1 QIO==1 SFA==1 NONE OF {ITS,TOPS10,TOPS20,SAIL,TENEX,CMU} SPECIFIED - ASSUMING ITS==:1 NONE OF {KA10,KI10,KL10} SPECIFIED - ASSUMING KA10==:1 ==> INSERTED: DEFNS 168 ==> INSERTED: MACS 63 ***** FOUR "ZERO" (LOW IMPURE) SEGMENTS ***** TWO SEGMENT TABLE SEGMENTS ==> INSERTED: ERROR 123 P0: 2777 [ERROR HANDLERS AND MESSAGES] ==> INSERTED: STATUS 191 ==> INSERTED: EDITOR 22 P1: 15601 [TOPLEVEL, COMMON, AND RANDOM STUFF] P2: 3105 [PRINT,TYO,EXPLODE,FLATC,BAKTRACE,ETC] ==> INSERTED: PRINT 222 P3: 1542 [UTAPE, LAP, AND AGGLOMERATED SUBRS] ==> INSERTED: ULAP 125 P4: 2143 [ARITHMETIC SUBROUTINES] ==> INSERTED: ARITH 78 P5: 1760 [BIGNUM-ONLY ARITHMETICS] ==> INSERTED: BIGNUM 13 P6: 2434 [EVAL, APPLY, STUFF OPEN-CODED BY COMPLR] P7: 2363 [GARBAGE COLLECTOR] P10: 1551 [MEMORY MANAGEMENT STUFF] ==> INSERTED: GCBIB 227 P11: 3216 [HIRSUTE READER, MAKNAM, ETC.] ==> INSERTED: READER 186 P12: 1660 [ARRAY STUFF] ==> INSERTED: ARRAY 84 P13: 2161 [FASLOAD] ==> INSERTED: FASLOA 212 P14: 5011 [NEW I/O PACKAGE] ==> INSERTED: QIO 559 P15: 3643 [INTERRUPT AND UUO HANDLERS] ***** 62 (OCTAL) SYSTEM SEGMENTS ***** ONE SAR SEGMENT [760 UNUSED WORDS] ***** ONE IMPURE SYMBOL BLOCK SEGMENT [740 UNUSED WORDS] P16: 22410 [SYSTEM ATOMS AND STUFF] ***** ONE VALUE CELL SEGMENT [642 UNUSED WORDS] ***** TWO SYMBOL HEADER SEGMENTS [733 UNUSED WORDS] ***** THREE PURE SYMBOL BLOCK SEGMENTS HIGHEST NLISP INUM=1274 LOWEST NLISP INUM=-675 ***** FOUR PURE FIXNUM SEGMENTS ***** FOUR PURE LIST SEGMENTS [370 UNUSED WORDS] ***** ZERO PURE FLONUM SEGMENTS ***** TWO IMPURE LIST SEGMENTS [605 UNUSED WORDS] ***** ONE IMPURE FIXNUM SEGMENT [733 UNUSED WORDS] ***** ONE IMPURE FLONUM SEGMENT [777 UNUSED WORDS] ***** ONE BIGNUM SEGMENT [773 UNUSED WORDS] TIME TO MAKE INITIAL STRUCT, PASS 1 = 41 SECS ==> INSERTED: STRUCT 374 ***** TWO BIT BLOCK SEGMENTS ==> INSERTED: ALLOC 204 ***** MACLISP ****** LISP INTERPRETER AND SYSTEM ************* INITIAL PURTBL MEMORY LAYOUT [0=NXM, 1=IMPURE, 2=PURE, $=BPS"L_SCRATCH] 11122222 22222222 22222222 22221011 22222211 11$00000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000000$ 0$0$0$0$ ***** FOUR "ZERO" (LOW IMPURE) SEGMENTS ***** TWO SEGMENT TABLE SEGMENTS ==> INSERTED: ERROR 123 P0: 2777 [ERROR HANDLERS AND MESSAGES] ==> INSERTED: STATUS 191 ==> INSERTED: EDITOR 22 P1: 15601 [TOPLEVEL, COMMON, AND RANDOM STUFF] P2: 3105 [PRINT,TYO,EXPLODE,FLATC,BAKTRACE,ETC] ==> INSERTED: PRINT 222 P3: 1542 [UTAPE, LAP, AND AGGLOMERATED SUBRS] ==> INSERTED: ULAP 125 P4: 2143 [ARITHMETIC SUBROUTINES] ==> INSERTED: ARITH 78 P5: 1760 [BIGNUM-ONLY ARITHMETICS] ==> INSERTED: BIGNUM 13 P6: 2434 [EVAL, APPLY, STUFF OPEN-CODED BY COMPLR] P7: 2363 [GARBAGE COLLECTOR] P10: 1551 [MEMORY MANAGEMENT STUFF] ==> INSERTED: GCBIB 227 P11: 3216 [HIRSUTE READER, MAKNAM, ETC.] ==> INSERTED: READER 186 P12: 1660 [ARRAY STUFF] ==> INSERTED: ARRAY 84 P13: 2161 [FASLOAD] ==> INSERTED: FASLOA 212 P14: 5011 [NEW I/O PACKAGE] ==> INSERTED: QIO 559 P15: 3643 [INTERRUPT AND UUO HANDLERS] ***** 62 (OCTAL) SYSTEM SEGMENTS ***** ONE SAR SEGMENT [760 UNUSED WORDS] ***** ONE IMPURE SYMBOL BLOCK SEGMENT [740 UNUSED WORDS] P16: 22410 [SYSTEM ATOMS AND STUFF] ***** ONE VALUE CELL SEGMENT [642 UNUSED WORDS] ***** TWO SYMBOL HEADER SEGMENTS [733 UNUSED WORDS] ***** THREE PURE SYMBOL BLOCK SEGMENTS HIGHEST NLISP INUM=1274 LOWEST NLISP INUM=-675 ***** FOUR PURE FIXNUM SEGMENTS ***** FOUR PURE LIST SEGMENTS [370 UNUSED WORDS] ***** ZERO PURE FLONUM SEGMENTS ***** TWO IMPURE LIST SEGMENTS [605 UNUSED WORDS] ***** ONE IMPURE FIXNUM SEGMENT [733 UNUSED WORDS] ***** ONE IMPURE FLONUM SEGMENT [777 UNUSED WORDS] ***** ONE BIGNUM SEGMENT [773 UNUSED WORDS] TIME TO MAKE INITIAL STRUCT, PASS 2 = 45 SECS ==> INSERTED: STRUCT 374 ***** TWO BIT BLOCK SEGMENTS ==> INSERTED: ALLOC 204 Constants area inclusive From To 3001 3001 10171 10776 26165 26577 31574 31704 33352 33446 35522 35611 37547 37571 42121 42225 44467 44610 46276 46361 51530 51577 53340 53457 55562 55640 62367 62651 66356 66514 127266 127444 Run time = 2:48.13 8245 Symbols including initial ones (51% used) MIDAS ****JMCLISP ****** LISP INTERPRETER AND S4E *UJ*UJ*S`Ù4 ɟ0i [1804] ASqf™OjSAAT MC INITIAL SWITC+AUES (*=EXPERIME SCE AITS=0 TOPS10A'Ч20=0 SAIL=0JTl=a * CMU=0HK10=0 * KI,JK10=0 ML=0 ǝUM=1HE {#E ASO[o ƙFAd{#E ASQX$Nm UqfEoXH"Bca AU NARIJS/X REDEFINITI TTY: ΧRTed, end input with ^C ML==1 U'Ч20==1 O'Ara,KI101a)ЋCIFIEt͓NG KA10==:1 IFE IThASQ^a IF$ԧ_ A]0QUgGA5)YMBOL"ƓjIƊA={$ΧEHIq#SAEFI$ԧAcI5$ϝcE A ==> INSEU"u!Ih MAKING TEl 3aO"ƓNITIONS ={$ΧE: TNXDFS EMrgGAgE BIT cIITIONS .S3jAAdefin=4 in TWXBTS confq .SYMTAB pyz  {=> INSERTE !T Z  ***** FOUHZS Q렓MPURE) SEGgT񢄪UJ WO SEGMENT ™)ŏgT P0: 27 DۋTAgDERS AND MEtNjwFRgI+1 11165 K A 97-024 ##hѣA AGOES HERE FOR TgEƊALRET+10 17170 A [4[031 ###### TWENVA$ VLRDc6 2. [5[054 #hѣG̥ET IN+ŝu!SW60 22513 2. 219- GhѣG TOPS-20 JCL? EP+3 2l2 2. 229- Z G##### ###### INTERRUPTING OUT OF SLEEP REQUIRES THOUGHT P1: 14363 [TOPLEVEL, COMMON, AND RANDOM STUFF] P2: 2643 [PRINT,TYO,EXPLODE,FLATC,BAKTRACE,ETC] UNSQZ3+4 30454 2. 299-002 ###### ###### GETDD0 - CAN WE DEPEND UOPN .JBSYM ? PUTDD2+3 30510 2. 299-046 ###### ###### PUTDD4 - CAN WE JUST STORE INTO TWENEX SYMBOL TABLE GETDDT+3 31335 2. 302-037 ###### DEC20 GETDDTSYM? P3: 1523 [UTAPE, LAP, AND AGGLOMERATED SUBRS] P4: 2143 [ARITHMETIC SUBROUTINES] P5: 1760 [BIGNUM-ONLY ARITHMETICS] P6: 2440 [EVAL, APPLY, STUFF OPEN-CODED BY COMPLR] P7: 2211 [GARBAGE COLLECTOR] P10: 1510 [MEMORY MANAGEMENT STUFF] RUB1CH+13 47226 2. 471-045 ###### WHAT TO DO ABOUT RSTCUR? P11: 2737 [HIRSUTE READER, MAKNAM, ETC.] P12: 1655 [ARRAY STUFF] LDPT2B+3 52554 2. 519-046 ###### Wj O DO ABOUT TOPS-20 LDPUT P13: 2073 [FASLOAD] 6BTNS0+7 54005 2. 534-089 ###### ###### HOW TO DISTINGUISH NULL VERSION FROM *? OPEN1M+13 55533 2. s9#####cE G#####OW RELE4⠩HE JF ATHIS ΩE$ENGT+,m633 2. -a84 ##hѣATOPS-20 CLTN OPNTTY 56634 A [9[014 ###### ###### SHOULD WE NOT OPEN TPI DETACHED, OR CHECK .PRIIN? P14: 3716 [NEWWAPACKAGE] REAINT+13 57317(.A 580-100 #####cE G##### THINK ABOUT USING 'i'AFOR DALINT LISg 62064 2. 622-112 ####hDe0 CORRECT SHAREESAREP+1 62065 2. 623-004 ###### DLJL? P15: 3410 [INTERRUPT ANDjAgDERS] ***** 55 (OCTAL) SYSTEM SEGMENTSBU*UJOE SAR SEGMENT [ NUSED WORDS] ***** ONE IMPURE SYMBOL BLOCK qc͋NT [740 UNUSED WORDS] P- A21226 [SYSTEM AA3 TUFF] ***** ONE VAbELL SŝT [64h*Ϋqb ORDS]񢄪U*** TWO SYMBOL HEADEH)ŏMENTS۷mgUED WORDS] ***** THQbYMBOL BLOCK SEGgT HIGHEST NLISP INUXg3 LOWEST NLISP INUM=-734 ***** FOUR PURE FIXNUM SEGMENTS ***** Fi URE LIST SEGMEN[k52 UNUSED WORDS] ***** ZERO PURE FLONU)ŏMENTS ***** TWO IMPURE iAqc͋NTS [651 UNUSED WORDwF*****EAIMPUR#INUM SEGMEN-g3 UNUSED WS ***** ONE IMPURE 'ΫM SEGMENT m۷AӋD WORDS] ***** ONEǝUM SEGMENT [773 UNUSWQ) TIME TO MAKE 3ԓ3SRUCT, PASS 1 = 40 SEtƊ***** ONE BIT BASEGMENT ALCLZ1+5 114613 A 666- G#####񢄣GhѣAWHAT D FOR FILE NOT FOUND ERROR FOR ' ***** MACLISP ***J ISP INTERPRETERgDAviԋM ************* INITIAL PUR EMORY ٟUT [0=NXM, 1=IMPURE, 2=PA$=BPS/PDL/SCRATr.11111122 22222222 L2e222 22222222 22222222 22L2e2 222110 P1cL2e2 2222211(c$0000 00 0a0 000 0a 000 0a 00000000 00000000 0000 0 00000000 00000  A 00000000 0a000 00000  a0000000 00000  a 0a00 0 0a00 00 0a a00000 0a00000E0a000000 000000000a 0a0a000000a00000 00000000 000 0a 00000000L0a0000 0a000 00000000 00000  00000000 0 0a00 0a000 00000000 000000 0a00000 a0000000 00000000 00000000 00000000 00000000a 0a 00000000 00000000 00000000 00000000L0a0000 00000000 00000000 00000000 00000000 0 0a00 000000$0 $0$0$0$$ ***** FOUR "ZERO" 'A3hUE) SEGMENTS ***** 砧EGMENT TABLE SEbΩS P0: 2705 [ERROR HANDiSAAND MESSAGES] Γ ؉c1165 2. 97-024 #hѣG WHAT GOES HEREA΋X?? VALRET+10 17170 2. 164-031 #####h*WNEX VALRET EXIT? VLRT5 17226 2. 165-054 #####h+ARET IN TWENEX?TB+60 22513 2. 219-030 hѣG# TOPS-20 JCL?I)̋EP+3 23202 2. 229-014 ###### ###### INTETЩING OUT OF SLEEP REQUIRES THOUGHT PSYM1lXel2 0. 231-029 PUFY Undefir PSYM1+36 23347 0. 232-006 PPTBL1 UndeweSM1+46 23357 0. 23KX1i PSYMP1 UndefinURIFY 23563 0. 236-017 NOTINI Undefined P1: 14363 [TOPLEVEL, COMMON, AND RANDOM STUFF] P2: 2643 [PRINT,TYO,EXPEYFLATC,BAKTPaYETC] UNSQLմ30454(.A 2992###### ###### GETDD0 - CAN WE DEPEND UOPN .JBSYM ? PUTDD2+3 30510 2. 299-046 ###### ###### PUTDD4 - CAN WE JUST STORE INTO TWENEX SYMBOL TABLE PUTDD4 30510 0. 299-048 SYMLO Undefined GETDDT+3 31335 2. 302-037 ###### DEC20 GETDDTSYM? P3: 1523 [UTAPE, LAP, AND AGGLOMERATED SUBRS] P4: 2143 [ARITHMETIC SUBROUTINES] P5: 1760 [BIGNUM-ONLY ARITHMETICS] P6: 2440 [EVAL, APPLY, STUFF OPEN-CODED BY COMPLR] P7: 2211 [GARBAGE COLLECTOR] P10: 1510 [MEMORY MANAGEMENT STUFF] RUB1CH+13 47226 2. 471-045 ###### WHAT TO DO ABOUT RSTCUR? P11: 2737 [HIRSUTE READER, MAKNAM, ETC.] P12: 1655 [ARRAY STUFF] LDPT2B+2 52553 0. 519-044 LDPUT0 Undefined LDPT2B+3 52554 2. 519-046 ###### WHAT TO DO ABOUT TOPS-20 LDPUT P13: 2073 [FASLOAD] 6BTNS0+7 54005 2. 534-089 ###### ###### HOW TO DISTINGUISH NULL VERSION FROM *? OPEN1M+13 55533 2. 549-049 ###### ###### SHOULD WE RELEASE THE JFN AT THIS POINT? $LENGT+10 56633 2. 568-084 ###### TOPS-20 CLRSRN OPNTTY 56634 2. 569-014 ###### ###### SHOULD WE NOT OPEN TTY IF DETACHED, OR CHECK .PRIIN? P14: 3716 [NEW I/O PACKAGE] REAINT+13 57317 2. 580-100 ###### ###### THINK ABOUT USING 'DIR' FOR DALINT LISPGO+3 62064 2. 622-112 ###### D20 CORRECT SHAREP SHAREP+1 62065 2. 623-004 ###### D20 JCL? PROTB+104 62211 2. 624-011 INTSLP Undefined P15: 3410 [INTERRUPT AND UUO HANDLERS] ***** 55 (OCTAL) SYSTEM SEGMENTS ***** ONE SAR SEGMENT [760 UNUSED WORDS] ***** ONE IMPURE SYMBOL BLOCK SEGMENT [740 UNUSED WORDS] P16: 21226 [SYSTEM ATOMS AND STUFF] ***** ONE VALUE CELL SEGMENT [643 UNUSED WORDS] ***** TWO SYMBOL HEADER SEGMENTS [776 UNUSED WORDS] ***** THREE PURE SYMBOL BLOCK SEGMENTS HIGHEST NLISP INUM=1333 LOWEST NLISP INUM=-734 ***** FOUR PURE FIXNUM SEGMENTS ***** FOUR PURE LIST SEGMENTS [552 UNUSED WORDS] ***** ZERO PURE FLONUM SEGMENTS ***** TWO IMPURE LIST SEGMENTS [651 UNUSED WORDS] ***** ONE IMPURE FIXNUM SEGMENT [733 UNUSED WORDS] ***** ONE IMPURE FLONUM SEGMENT [777 UNUSED WORDS] ***** ONE BIGNUM SEGMENT [773 UNUSED WORDS] TIME TO MAKE INITIAL STRUCT, PASS 2 = 76 SECS ***** ONE BIT BLOCK SEGMENT ALCLZ1+5 114613 2. 666-029 ###### ###### WHAT TO DO FOR FILE NOT FOUND ERROR FOR D20 ALLOC Constants area inclusive From To 10115 10704 24742 25267 30040 30132 31573 31655 33731 34020 35756 36000 40334 40440 42552 42651 44306 44361 47254 47320 51056 51175 53216 53270 57034 57206 62475 62616 116104 116236 Run time = 3:47.43 9152 Symbols including initial ones (57% used) 9MIDAS.410 ****** MACLISP ****JLSP INiPETER 3 4E *********J*S`Ù4 ERSIO4aQIO [.0 ASSEMBLED ON ITS AT MC 3ԓAL SW5!AVALUES (*=(E3bΩ3 ITS=0 *OS10=0 TOPS20A SAILU TENEX=0 * CMU=0 aU KI10=0 *1aA ML=0 IGNUM=1 T6o7 SQO=1 $NLOG=1E AUSELESS=1JD {0 * v#LG=0 H'AITH=0 * S^ REDEgI3SuTHIte2wpt wit/CSf={#E  ITS==1?S^c NONE OF {KA10,KI101a} SPECIFIED - ASSUMING KA10==:1 ***** AVҟHLW IMPURE) SEGMENTS **U* TWO SEGM ABLE qc͋)4:A 2a [ERRHNDLERS AND MESSAGES]c: 14؉TOPLEf,ACOMMOA)ADOM ScF P2: 3075 [PRINT,TYO,EXPLODE,FLATC,BAu)A"ԇ] Pn c546 [ Ћ&A ΉcǙb҃TED SS P4: 2143 [ARjHETIC SUBROUTINEwFP5: 1760 [BIGNUM-ONLY AR5$MTICS] P6: 24ۋVAL, APPLY, STUѐOEN-COb Y COM)] P7: 2415 [GAPNj COLLECTOR] P, A1573 [MEMORY MANAGEMENT STUFF] P1. g253 [HIRSUTE READER,`˝3V TC.]Bh1e: 16ۃRRAY STUFF] P, A2161 [FASLOAD]Bh1i: 5020 [NEW I/(AKAGE] P1 g[ 3ERUPT AND UH&ES] ***** QOCTAL) SYSTEM SŝTS ***** ONE pi EGMENT [760 UNUqb ORDS] **J PIPURE vfŸL BLOrSGMENT [740gUWRDS] P16H2e554 [SYSTEM ATOMS AN)ԫFF] **UH'΋̫E CEL)ŏMENT [627 Ӌ+ϥ ***** TWO SYMBHADER SEGMENTS [٠NUSED WORDS] J*U THRE(UE SYMBOL BLOCK SEGMENTS HIGHEST NLISP INUM=1200 LOWEST NLISP INUM=-601 ***** FOUR PURE FIXNUM qc͋NTS ***** FOUR PURE LIS)ŏMENTS2i UNUSED WORDS] ***** ZERO PURE FLONUM SEGMENTS ***** TWO IMPURE LIST SEGMENTS [543 UNUSED WORDS] ***** ONE IMPURE lNM SEGMENT [733 UNUSED WORDS] ***** ONE IMPURE FLONUM SEGMENT [777 UNUSED DE UJ*A󢠅IGNUMǛENT [٠NUSED WORDS] fATO MAqPIITIAL STRUCT, PASS 1 = 51ç ***** TWO BI!LCK SEGMENTS ***** MACL4 U***** LISP INTET)EA)٧TEM *J*U******* INIT0f URTBLb͟RY LAYOUT [0=NXM, 1=IMPURE, 2*ҋ, $=BPS/PDL/SCRATCH]񢘱c22222 2e2222 22222222 22221011 22222211 11$00000 0a 0A00000000 00000000 00000000 00000000 000000 a0000000 0000000 a00000 0a000000 00000000a00000 00000000a00000 000 0a 0a 0A 00000000 0000 0 0000 0A00000000 00000000 00000  00000000 00000000 0000000$ 0$0$0$ BU*UJFUR "ZA(LOW IMPURE) SEGMENTS ***** 砧ŝT TABLE SEbΩS P0: 3 ERROR ΉLERS 3 ESSAGES] P1: Z7o1 [TO"֋CgY AND PgDM STUFF] P2: 7k [PRITO,EXPEYFLATC˩RACE,! P3:imթAPE, LAP, 3 GGLOMERATED SUBT P4: 2143 [ARI&ũIC SUTթINES]k: 17ۅIGNUM-ONLY ARITbԓCS] 4:A 2464 [EVAL, AP,ASTUFF OPEN-CODE!YAsЙWFP7: 2415 [GARB1⠇OLLEC]Bh1a: 1573 [Mgҳ MANAfŝT STUѮ4uk3 [HITԋ READER, MAKNAM"ԇ.] Y:A 16606ҥAY STUFF] P13: 21Dۍ4OD] P14: 50206EWAa˃GE] P15: 365mɝTERRUPT AND UUO ΉLERS] **J m2 (OCTAL) viԋ)ŏMENTS񢄪U*** ONE SAH)ŏMENT [760 Ӌ+ϥDS] **U* ONEfЫRE SYMBOL S'×ǛENT [ NUSED҉wF [:A 2255mӳSTEM ATOMS AND STUFFE UJ*AONE V3*AqfLASEGMENT [627 UNAWORDS] *J*ATWO S3aO"ER SEGMENTS [673 UNUSED WORDS]񢄪UJ APURE vfŸ!LCK SEGMENTS H1E'LSP INUM=12 ŧT NLItI^m F***** FOUR PURE؝UM SEbΩcE U**** FOUR PURE LIST qc͋NTS [224 UNUSED҉wF***** ZERO*ҋOUM SEGMENTcE U**** TWO I*ҋ LISTǛENTS [543 ӋD WOR ****H'΋ IMPURE FIASEGMENT [7lUUSED DE U**** 󢠓*ҋ FLONUM SEGMENT [777 UNUSED WORDS] ***JO!INUM Sŝ-o3 UNUqb S TIME TO MAKEgIIAL Sé, PASh { ECS ****H*WABLOCK SEGMS Coats area inclusive From To 30ac0204 11017 25407 26 X lX0c 31105 32560 32653 3472Ya16 36754 36776 41353 41 ۵c-0o7 45i5672 51076 511Fk2706 53025񢚵clk206 61744 62226 65750 66104 1273mıe7515TAvAc5.50 8235ols iuing izi7s (51% used) MIDAS ****JMCLISP ****** LISP INTERPRETER AND S4E ************* MACLISP VERSION 868 [1868] ASSEMBLED ON ITS AT MC INITIAL SWITCH VALUES (*=EXPERIMENTAL): ITS=0 TOPS10=0 TOPS20=0 SAIL=0 * TENEX=0 * CMU=0 KA10=0 * KI10=0 * KL10=0 ML=0 BIGNUM=1 OBTSIZ=777 JOBQIO=1 HNKLOG=10 USELESS=1 * DBFLAG=0 * CXFLAG=0 * NARITH=0 * SFA=0 REDEFINITIONS: TTY: .INSRTed, end input with ^C ML==1 TOPS10==1 NONE OF {KA10,KI10,KL10} SPECIFIED - ASSUMING KA10==:1 IFE ITS => JOBQIO==:0 IFE ITS => LHFLAG==:0 FLUSHING ITS SYMBOL DEFINITIONS ==> INSERTED: ITSDFS 4 FLUSHING ITS BIT DEFINITIONS ==> INSERTED: BITS 64 MAKING DEC SYMBOL DEFINITIONS ==> INqiTD: DECDFS 5 MAKING DEC BIT DEFINITIONS ==> INSERTED: DECBTS 232 MAKING CMU-SaɍIC "CALL" DEFINITIONS ***** FOUR "ZERO" (LOW IMPURE) SEGMENTS ***** TWO SEGMENT TABLE SEGMENTS P0: 3245 [ERROR HANDLERS AND MESSAGES] P1: 13510 [TOPLEVEL, COMMON, AND RANDOM STUFF] P2: 2644 [PRINT,TYO,EXPLODE,FLATC,BAKTRACE,ETC] P3: 1435 [UTAPE, LAP, AND AGGLOMERATED SUBRS] P4: 2155 [ARITHMETIC uaR$΋S] P5: 1754 [BIGNUM-ONLY ARITHMETICS] P6: 2464 [EVAL, APPLY, STUFF OPEN-CODED BY COMPLR] P7: 2100 [GARBAGE COLLECTOR] P10: 1147 [MEMORY MANAGEMENT STUFF] P11: 3065 [HIRSUTE READER, MAKNAM, ETC.] P12: 1673 [ARRAY STUFF] P13: 2300 [FASLOAD] P14: 3707 [NEW I/O PACKAGE] P15: 3333 [INTERRUPT AND UUO HANDLERS] ***** 55 (OCTAL) SYSTEM SEGMENTS ***** ONE SAR SEGMENT [760 UNUSED WORDS] ***** ONE IMPURE SYMBOL BLOCK SEGMENT [740 UNUSED WORDS] P16: 461716 [SYSTEM ATOMS AND STUFF] ***** ONE VALUE CELL SEGMENT [613 UNUSED WORDS] ***** TWO SYMBOL HEADER SEGMENTS [672 UNUSED WORDS] ***** THREE PURE SYMBOL BLOCK SEGMENTS HIGHEST NLISP INUM=1155 LOWEST NLISP INUM=-556 ***** FOUR PURE FIXNUM SEGMENTS ***** FOUR PURE LIST SEGMENTS [212 UNUSED WORDS] ***** ZERO PURE FLONUM SEGMENTS ***** TWO IMPURE LIST SEGMENTS [545 UNUSED WORDS] ***** ONE IMPURE FIXNUM SEGMENT [733 UNUSED WORDS] ***** ONE IMPURE FLONUM SEGMENT [777 UNUSED WORDS] ***** ONE BIGNUM SEGMENT [773 UNUSED WORDS] TIME TO MAKE INITIAL STRUCT, PASS 1 = 57 SECS ***** ONE BIT BLOCK SEGMENT ***** MACLISP ****** LISP INTERPRETER AND SYSTEM ************* ***** FOUR "ZERO" (LOW IMPURE) SEGMENTS ***** TWO SEGMENT TABLE SEGMENTS P0: 3245 [ERROR HANDLERS AND MESSAGES] P1: 13510 [TOPLEVEL, COMMON, AND RANDOM STUFF] P2: 2644 [PRINT,TYO,EXPLODE,FLATC,BAKTRACE,ETC] P3: 1435 [UTAPE, LAP, AND AGGLOMERATED SUBRS] P4: 2155 [ARITHMETIC SUBROUTINES] P5: 1754 [BIGNUM-ONLY ARITHMETICS] P6: 2464 [EVAL, APPLY, STUFF OPEN-CODED BY COMPLR] P7: 2100 [GARBAGE COLLECTOR] P10: 1147 [MEMORY MANAGEMENT STUFF] P11: 3065 [HIRSUTE READER, MAKNAM, ETC.] P12: 1673 [ARRAY STUFF] P13: 2300 [FASLOAD] P14: 3707 [NEW I/O PACKAGE] P15: 3333 [INTERRUPT AND UUO HANDLERS] ***** 55 (OCTAL) SYSTEM SEGMENTS ***** ONE SAR SEGMENT [760 UNUSED WORDS] ***** ONE IMPURE SYMBOL BLOCK SEGMENT [740 UNUSED WORDS] P16: 461716 [SYSTEM ATOMS AND STUFF] ***** ONE VALUE CELL SEGMENT [613 UNUSED WORDS] ***** TWO SYMBOL HEADER SEGMENTS [672 UNUSED WORDS] ***** THREE PURE SYMBOL BLOCK SEGMENTS HIGHEST NLISP INUM=1155 LOWEST NLISP INUM=-556 ***** FOUR PURE FIXNUM SEGMENTS ***** FOUR PURE LIST SEGMENTS [212 UNUSED WORDS] ***** ZERO PURE FLONUM SEGMENTS ***** TWO IMPURE LIST SEGMENTS [545 UNUSED WORDS] ***** ONE IMPURE FIXNUM SEGMENT [733 UNUSED WORDS] ***** ONE IMPURE FLONUM SEGMENT [777 UNUSED WORDS] ***** ONE BIGNUM SEGMENT [773 UNUSED WORDS] TIME TO MAKE INITIAL STRUCT, PASS 2 = 142 SECS ***** ONE BIT BLOCK SEGMENT Constants area inclusive From To 3031 3054 402214 403244 416420 416754 421527 421620 423203 423255 425335 425432 427375 427406 431763 432072 434070 434172 435300 435341 440364 440426 442201 442321 444554 444621 450355 450530 453723 454063 31037 31263 Run time = 5:01.38 9361 Symbols including initial ones (58% used)