BSD 4_4 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Tue, 15 Dec 1987 10:02:24 +0000 (02:02 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Tue, 15 Dec 1987 10:02:24 +0000 (02:02 -0800)
Work on file usr/src/old/lisp/liszt/funb.l

Synthesized-from: CSRG/cd3/4.4

usr/src/old/lisp/liszt/funb.l [new file with mode: 0644]

diff --git a/usr/src/old/lisp/liszt/funb.l b/usr/src/old/lisp/liszt/funb.l
new file mode 100644 (file)
index 0000000..cc0112c
--- /dev/null
@@ -0,0 +1,787 @@
+(include-if (null (get 'chead 'version)) "../chead.l")
+(Liszt-file funb
+   "$Header: funb.l,v 1.13 87/12/15 17:02:17 sklower Exp $")
+
+;;; ----       f u n b                         function compilation
+;;;
+;;;                            -[Wed Aug 24 17:14:56 1983 by layer]-
+
+;--- c-declare :: handle the "declare" form
+; if a declare is seen inside a function definition, we just 
+; ignore it.  We probably should see what it is declareing, as it
+; might be declaring a special.
+;
+(defun c-declare nil nil)
+
+;--- c-do :: compile a "do" expression
+;
+; a do has this form:
+;  (do vrbls tst . body)
+; we note the special case of tst being nil, in which case the loop
+; is evaluated only once, and thus acts like a let with labels allowed.
+; The do statement is a cross between a prog and a lambda. It is like
+; a prog in that labels are allowed. It is like a lambda in that
+; we stack the values of all init forms then bind to the variables, just
+; like a lambda expression (that is the initial values of even specials
+; are stored on the stack, and then copied into the value cell of the
+; atom during the binding phase. From then on the stack location is
+; not used).
+;
+(defun c-do nil
+   (let (b-vrbls b-tst b-body chklab bodylab x-repeat x-vrbs x-fst
+                g-loc g-cc oldreguse (g-decls g-decls))
+       (forcecomment '(beginning do))
+       (setq g-loc 'reg  chklab (d-genlab)   bodylab (d-genlab))
+
+       (if (and (cadr v-form) (atom (cadr v-form)))
+          then (setq v-form (d-olddo-to-newdo (cdr v-form))))
+
+       (push (cons 'do 0) g-locs)              ; begin our frame
+
+       (setq b-vrbls (cadr v-form)
+            b-tst   (caddr v-form)
+            b-body  (cdddr v-form))
+
+       (d-scanfordecls b-body)
+
+       ; push value of init forms on stack
+       (d-pushargs (mapcar '(lambda (x)
+                               (if (atom x)
+                                   then nil ; no init form => nil
+                                   else (cadr x)))
+                          b-vrbls))
+
+       ; now bind to  the variables in the vrbls form
+       (d-bindlamb (mapcar '(lambda (x)
+                               (if (atom x) then x
+                                   else (car x)))
+                          b-vrbls))
+
+       ; search through body for all labels and assign them gensymed labels
+       (push (cons (d-genlab)
+                  (do ((ll b-body (cdr ll))
+                       (res))
+                      ((null ll) res)
+                      (if (and (car ll) (symbolp (car ll)))
+                          then (Push res
+                                     (cons (car ll) (d-genlab))))))
+            g-labs)
+
+       ; if the test is non nil, we do the test
+       ; another strange thing, a test form of (pred) will not return
+       ; the value of pred if it is not nil! it will return nil -- in this
+       ; way, it is not like a cond clause
+       (d-clearreg)
+       (if b-tst then (e-label chklab)
+          (let ((g-cc (cons nil bodylab)) g-loc g-ret)
+              (d-exp (car b-tst)))     ; eval test
+          ; if false, do body
+          (if (cdr b-tst) 
+              then (setq oldreguse (copy g-reguse))
+                   (d-exps (cdr b-tst))
+                   (setq g-reguse oldreguse)
+              else  (d-move 'Nil 'reg))
+          (e-goto (caar g-labs))               ; leave do
+          (e-label bodylab))           ; begin body
+
+       ; process body
+       (do ((ll b-body (cdr ll))
+           (g-cc) (g-loc)(g-ret))
+          ((null ll))
+          (if (or (null (car ll)) (not (symbolp (car ll))))
+              then (d-exp (car ll))
+              else (e-label (cdr (assoc (car ll) (cdar g-labs))))
+                   (d-clearreg)))
+
+       (if b-tst
+          then ; determine all repeat forms which must be
+               ; evaluated, and all the variables affected.
+               ; store the results in x-repeat and  x-vrbs
+               ; if there is just one repeat form, we calculate
+               ; its value directly into where it is stored,
+               ; if there is more than one, we stack them
+               ; and then store them back at once.
+               (do ((ll b-vrbls (cdr ll)))
+                   ((null ll))
+                   (if (and (dtpr (car ll)) (cddar ll))
+                       then (Push x-repeat (caddar ll))
+                            (Push x-vrbs   (caar ll))))
+               (if x-vrbs 
+                   then (if (null (cdr x-vrbs))  ; if just one repeat
+                            then (let ((g-loc (d-locv (car x-vrbs)))
+                                       (g-cc nil))
+                                     (d-exp (car x-repeat)))
+                            else (setq x-fst (car x-repeat))
+                                 (d-pushargs (nreverse
+                                                 (cdr x-repeat)))
+                                 (let ((g-loc (d-locv (car x-vrbs)))
+                                       (g-cc)
+                                       (g-ret))
+                                     (d-exp x-fst))
+                                 (do ((ll (cdr x-vrbs) (cdr ll)))
+                                     ((null ll))
+                                     (d-move 'unstack
+                                             (d-locv (car ll)))
+                                     (setq g-locs (cdr g-locs))
+                                     (decr g-loccnt))))
+               (e-goto chklab))
+
+       (e-label (caar g-labs))                 ; end of do label
+       (d-clearreg)
+       (d-unbind)
+       (setq g-labs (cdr g-labs))))
+
+;--- d-olddo-to-newdo  :: map old do to new do
+;
+; form of old do is  (do var tst . body)
+; where var is a symbol, not nil
+;
+(defun d-olddo-to-newdo (v-l)
+  `(do ((,(car v-l) ,(cadr v-l) ,(caddr v-l)))
+       (,(cadddr v-l))
+       ,@(cddddr v-l)))
+
+;--- cc-dtpr :: check for dtprness
+;
+(defun cc-dtpr nil
+  (d-typesimp (cadr v-form) #.(immed-const 3)))
+
+;--- cc-eq :: compile an "eq" expression
+;
+(defun cc-eq nil
+   (let ((arg1 (cadr v-form))
+        (arg2 (caddr v-form))
+        arg1loc
+        arg2loc)
+       (if (setq arg2loc (d-simple arg2))
+          then (if (setq arg1loc (d-simple arg1))
+                   then ; eq <simple> <simple>
+                        (d-cmp arg1loc arg2loc)
+                   else ; eq <nonsimple> <simple>
+                        (let ((g-loc 'reg)     ; put <nonsimple> in reg
+                              ; must rebind because
+                              ; cc->& may have modified
+                              (g-trueop #+(or for-vax for-tahoe) 'jneq
+                                        #+for-68k 'jne)
+                              (g-falseop #+(or for-vax for-tahoe) 'jeql
+                                         #+for-68k 'jeq)
+                              g-cc
+                              g-ret)
+                            (d-exp arg1))
+                        (d-cmp 'reg arg2loc))
+          else ; since second is nonsimple, must stack first
+               ; arg out of harms way
+               (let ((g-loc 'stack)
+                     (g-trueop #+(or for-vax for-tahoe) 'jneq #+for-68k 'jne)
+                     (g-falseop #+(or for-vax for-tahoe) 'jeql #+for-68k 'jeq)
+                     g-cc
+                     g-ret)
+                   (d-exp arg1)
+                   (push nil g-locs)
+                   (incr g-loccnt)
+                   (setq g-loc 'reg)           ; second arg to reg
+                   (d-exp arg2))
+               (d-cmp 'unstack 'reg)
+               (setq g-locs (cdr g-locs))
+               (decr g-loccnt)))
+   (d-invert))
+
+;--- cc-equal :: compile `equal'
+;
+(defun cc-equal nil
+  (let ((lab1 (d-genlab))
+       (lab11 (d-genlab))
+       lab2)
+       (d-pushargs (cdr v-form))
+       (e-cmp '(-8 #.np-reg) '(-4 #.np-reg))
+       (e-gotonil lab1)
+       (d-calltran 'equal '2)           ; not eq, try equal.
+       (d-clearreg)
+       #+(or for-vax for-tahoe) (e-tst (e-cvt 'reg))
+       #+for-68k (e-cmpnil (e-cvt 'reg))
+       (e-gotot lab11)         
+       (if g-loc then (d-move 'Nil g-loc))
+       (if (cdr g-cc) then (e-goto (cdr g-cc))
+          else (e-goto (setq lab2 (d-genlab))))
+       (e-writel lab1)
+       (e-dropnp 2)
+       (e-writel lab11)
+       (if g-loc then (d-move 'T g-loc))
+       (if (car g-cc) then (e-goto (car g-cc)))
+       (if lab2 then (e-writel lab2))
+       (setq g-locs (cddr g-locs))
+       (setq g-loccnt (- g-loccnt 2))))
+
+;--- c-errset :: compile an errset expression
+;
+; the errset has this form: (errset 'value ['tag])
+; where tag defaults to t.
+;
+(defun c-errset nil
+  (let ((g-loc 'reg)
+       (g-cc nil)
+       (g-ret nil)
+       (finlab (d-genlab))
+       (beglab (d-genlab)))
+       (d-exp (if (cddr v-form) then (caddr v-form) else t))
+       (d-pushframe #.F_CATCH (d-loclit 'ER%all nil) 'reg)
+       (push nil g-labs)               ; disallow labels
+       ; If retval is non zero then an error has throw us here so we 
+       ; must recover the value thrown (from _lispretval) and leave
+       ; If retval is zero then we shoud calculate the expression 
+       ; into r0  and put a cons cell around it
+       (e-tst '_retval)
+       (e-write2 #+(or for-vax for-tahoe) 'jeql #+for-68k 'jeq beglab)
+       (e-move '_lispretval (e-cvt 'reg))
+       (e-write2 #+(or for-vax for-tahoe) 'jbr #+for-68k 'jra finlab)
+       (e-label beglab)
+       (let ((g-loc 'stack)
+            (g-cc nil))
+           (d-exp (cadr v-form)))
+       (d-move 'Nil 'stack)    ; haven't updated g-loc, g-loccnt but it
+                               ; shouldn't hurt (famous last words)
+       (e-quick-call '_qcons)
+       (e-label finlab)
+       (d-popframe)
+       (unpush g-locs)         ; remove (catcherrset . 0)
+       (unpush g-labs)         ; remove nil
+       (d-clearreg)))
+
+;--- cm-fixnum-cxr :: open code a fixnum-cxr expression.
+; 
+; fixnum-cxr is a compile only hacky function which accesses an element
+; of a fixnum space and boxes the resulting fixnum.  It can be used
+; for rapid access to user defined structures.
+;
+(defun cm-fixnum-cxr ()
+  `(internal-fixnum-box (cxr ,@(cdr v-form))))
+
+(defun c-internal-fixnum-box ()
+  (let ((g-cc nil)
+       (g-ret nil)
+       (g-loc '#.fixnum-reg))
+       #+for-68k (d-regused '#.fixnum-reg)
+       (d-exp (cadr v-form))
+       (e-call-qnewint)))
+
+;--- cc-offset-cxr
+; return a pointer to the address of the object instead of the object.
+;
+(defun cc-offset-cxr nil
+  (d-supercxr nil t))
+
+;--- cc-fixp :: check for a fixnum or bignum
+;
+(defun cc-fixp nil
+  (d-typecmplx (cadr v-form) 
+              '#.(immed-const (plus 1_2 1_9))))
+
+;--- cc-floatp :: check for a flonum
+;
+(defun cc-floatp nil
+  (d-typesimp (cadr v-form) #.(immed-const 4)))
+
+;--- c-funcall :: compile a funcall
+;
+; we open code a funcall the resulting object is a compiled lambda.
+; We don't open code nlambda and macro funcalls since they are
+; rarely used and it would waste space to check for them
+(defun c-funcall nil
+   (if (null (cdr v-form))
+      then (comp-err "funcall requires at least one argument " v-form))
+   (let ((g-locs g-locs)
+        (g-loccnt g-loccnt)
+        (args (length (cdr v-form)))
+        (g-loc nil)
+        (g-ret nil)
+        (g-cc nil))
+      (d-pushargs (cdr v-form))
+      (rplaca (nthcdr (1- args) g-locs) 'funcallfcn)
+
+      (d-exp '(cond ((and (symbolp funcallfcn)
+                         (getd funcallfcn))
+                    (setq funcallfcn (getd funcallfcn)))))
+            
+      (d-exp `(cond ((and (bcdp funcallfcn) (eq 'lambda (getdisc funcallfcn)))
+                       (Internal-bcdcall ,args t))
+                      (t (Internal-bcdcall  ,args nil))))))
+
+;--- c-Internal-bcdcall
+; this is a compiler internal function call.  when this occurs, there
+;  are argnum objects stacked, the first of which is a function name
+;  or bcd object.  If dobcdcall is t then we want to do a bcdcall of
+;  the first object stacked.  If it is not true then we want to
+;  call the interpreter funcall function to handle it.
+;
+(defun c-Internal-bcdcall nil
+   (let ((argnum (cadr v-form))
+        (dobcdcall (caddr v-form)))
+      (cond (dobcdcall (d-bcdcall argnum))
+           (t (d-calltran 'funcall argnum)))))
+
+;--- cc-function :: compile a function function
+;
+; function is an nlambda, which the interpreter treats as 'quote'
+; If the argument is a lambda expression, then Liszt will generate
+; a new function and generate code to return the name of
+; that function.  If the argument is a symbol, then 'symbol
+; is compiled.   It would probably be better to return the function
+; cell of the symbol, but Maclisp returns the symbol and it
+; would cause compatibility problems.
+;
+(defun cc-function nil
+   (if (or (null (cdr v-form))
+          (cddr v-form))
+      then (comp-err "Wrong number of arguments to 'function': " v-form))
+   (let ((arg (cadr v-form)))
+      (if (symbolp arg)
+        then (d-exp `',arg)
+       elseif (and (dtpr arg)
+                  (memq (car arg) '(lambda nlambda lexpr)))
+        then (let ((newname (concat "in-line-lambda:"
+                                    (setq in-line-lambda-number
+                                          (add1 in-line-lambda-number)))))
+                (Push liszt-process-forms
+                      `(def ,newname ,arg))
+                (d-exp `',newname))
+        else (comp-err "Illegal argument to 'function': " v-form))))
+
+;--- c-get :: do a get from the prop list
+;
+(defun c-get nil
+  (if (not (eq 2 (length (cdr v-form))))
+      then (comp-err "Wrong number of args to get " v-form))
+  (d-pushargs (cdr v-form))            ; there better be 2 args
+  (e-quick-call '_qget)
+  (d-clearreg)
+  (setq g-locs (cddr g-locs))
+  (setq g-loccnt (- g-loccnt 2)))
+
+;--- cm-getaccess :: compile a getaccess instruction
+;
+(defun cm-getaccess nil `(cdr ,(cadr v-form)))
+
+;--- cm-getaux :: compile a getaux instruction
+;
+(defun cm-getaux  nil `(car ,(cadr v-form)))
+
+;--- cm-getd :: compile a getd instruction
+;
+; the getd function is open coded to look in the third part of a symbol
+; cell
+;
+(defun cm-getd nil `(cxr 2 ,(cadr v-form)))
+
+;--- cm-getdata :: compile a getdata instruction
+;
+; the getdata function is open coded to look in the third part of an 
+; array header.
+(defun cm-getdata nil `(cxr 2 ,(cadr v-form)))
+
+;--- cm-getdisc  :: compile a getdisc expression
+; getdisc accessed the discipline field of a binary object.
+;
+(defun cm-getdisc nil `(cxr 1 ,(cadr v-form)))
+
+;--- c-go :: compile a "go" expression
+;
+; we only compile the (go symbol)type expression, we do not
+; allow symbol to be anything by a non null symbol.
+;
+(defun c-go nil
+   ; find number of frames we have to go down to get to the label
+   (do ((labs g-labs (cdr labs))
+       (locs g-locs)
+       (locals 0)
+       (specials 0)
+       (catcherrset 0)
+       (label))
+       ((null labs)
+       (comp-err "go label not found for expression: " (or v-form)))
+
+       (if (car labs)          ; if we have a set of labels to look at...
+          then (if (setq label
+                         (do ((lbs (cdar labs) (cdr lbs)))
+                             ((null lbs))
+                             (if (eq (caar lbs) (cadr v-form))
+                                 then (return (cdar lbs)))))
+                   then (if (not (eq labs g-labs))
+                            then (comp-note g-fname ": non local go used : "
+                                            (or v-form)))
+                        ; three stack to pop: namestack, bindstack
+                        ;   and execution stack
+                        (e-pop locals)
+                        (if (greaterp specials 0)
+                            then (e-unshallowbind specials))
+                        (if (greaterp catcherrset 0)
+                            then (comp-note g-fname
+                                            ": Go through a catch or errset "
+                                            v-form)
+                                 (do ((i 0 (1+ i)))
+                                     ((=& catcherrset i))
+                                     (d-popframe)))
+                        (e-goto label)
+                        (return)))
+       ; tally all locals, specials and catcherrsets used in this frame
+       (do ()
+          ((dtpr (car locs))
+           (if (eq 'catcherrset (caar locs))
+              then (incr catcherrset)
+            elseif (eq 'progv (caar locs))
+              then (comp-err "Attempt to 'go' through a progv"))
+           (setq specials (+ specials (cdar locs))
+                 locs (cdr locs)))
+          (setq locs (cdr locs))
+          (incr locals))))
+                       
+;--- cc-ignore :: just ignore this code
+;
+(defun cc-ignore nil
+  nil)
+
+;--- c-lambexp :: compile a lambda expression
+;
+(defun c-lambexp nil
+  (let ((g-loc (if (or g-loc g-cc) then 'reg))
+       (g-cc nil)
+       (g-locs (cons (cons 'lambda 0) g-locs))
+       (g-labs (cons nil g-labs)))
+       (d-pushargs (cdr v-form))               ; then push vals
+       (d-lambbody (car v-form))
+       (d-clearreg)))
+
+;--- d-lambbody :: do a lambda body
+;      - body : body of lambda expression, eg (lambda () dld)
+;
+(defun d-lambbody (body)
+   (let ((g-decls g-decls))
+      (d-scanfordecls (cddr body))             ; look for declarations
+      (d-bindlamb (cadr body))         ; bind locals
+      (d-clearreg)
+      (d-exp (do ((ll (cddr body) (cdr ll))
+                 (g-loc)
+                 (g-cc)
+                 (g-ret))
+                ((null (cdr ll)) (car ll))
+                (d-exp (car ll))))
+
+      (d-unbind)))                             ; unbind this frame
+
+;--- d-bindlamb :: bind  variables in lambda list
+;      - vrbs : list of lambda variables, may include nil meaning ignore
+;
+(defun d-bindlamb (vrbs)
+  (let ((res (d-bindlrec (reverse vrbs) g-locs 0 g-loccnt)))
+       (if res then (e-setupbind)
+                   (mapc '(lambda (vrb) (e-shallowbind (car vrb) (cdr vrb)))
+                         res)
+                   (e-unsetupbind))))
+  
+;--- d-bindlrec :: recusive routine to bind lambda variables
+;      - vrb : list of variables yet to bind
+;      - locs : current location in g-loc
+;      - specs : number of specials seen so far
+;      - lev  : how far up from the bottom of stack we are.
+; returns: list of elements, one for each special, of this form:
+;              (<specialvrbname> stack <n>)
+;      where specialvrbname is the name of the special variable, and n is
+;      the distance from the top of the stack where its initial value is 
+;      located
+; also: puts the names of the local variables in the g-locs list, as well
+;      as placing the number of special variables in the lambda header.
+;
+(defun d-bindlrec (vrb locs specs lev)
+   (if vrb 
+       then (let ((spcflg (d-specialp (car vrb)))
+                 retv)
+               (if spcflg then (setq specs (1+ specs)))
+
+               (if (cdr vrb)           ; if more vrbls to go ...
+                   then (setq retv (d-bindlrec (cdr vrb)
+                                               (cdr locs)
+                                               specs
+                                               (1- lev)))
+                   else (rplacd (cadr locs)
+                                specs))        ; else fix up lambda hdr
+
+               (if (not spcflg) then (rplaca locs (car vrb))
+                   else (Push retv `(,(car vrb) stack ,lev)))
+
+               retv)))
+
+;--- d-scanfordecls
+; forms - the body of a lambda, prog or do.
+;  we look down the form for 'declare' forms.  They should be at the
+;  beginning, but there are macros which may unintentionally put forms
+;  in front of user written forms.  Thus we check a little further than
+;  the first form.
+(defun d-scanfordecls (forms)
+   ; look for declarations in the first few forms
+   (do ((count 3 (1- count)))
+       ((= 0 count))
+       (cond ((and (dtpr (car forms))
+                  (eq 'declare (caar forms))
+                  (apply 'liszt-declare (cdar forms)))))
+       (setq forms (cdr forms))))
+
+;--- c-list :: compile a list expression
+;
+; this is compiled as a bunch of conses with a nil pushed on the
+; top for good measure
+;
+(defun c-list nil
+  (prog (nargs)
+       (setq nargs (length (cdr v-form)))
+       (makecomment '(list expression))
+       (if (zerop nargs)
+           then (d-move 'Nil 'reg)     ; (list) ==> nil
+                (return))
+       (d-pushargs (cdr v-form))
+       #+(or for-vax for-tahoe) (e-write2 'clrl '#.np-plus) ; stack one nil
+       #+for-68k (L-push (e-cvt 'Nil))
+
+       ; now do the consing
+       (do ((i (max 1 nargs) (1- i)))
+          ((zerop i))
+          (e-quick-call '_qcons)
+          (d-clearreg)
+          (if (> i 1) then (L-push (e-cvt 'reg))))
+
+       (setq g-locs (nthcdr nargs g-locs)
+            g-loccnt (- g-loccnt nargs))))
+
+;--- d-mapconvert - access : function to access parts of lists
+;                - join         : function to join results
+;                - resu         : function to apply to result
+;                - form         : mapping form
+;      This function converts maps to an equivalent do form.
+;
+;  in this function, the variable vrbls contains a list of forms, one form
+;  per list we are mapping over.  The form of the form is 
+;    (dummyvariable  realarg  (cdr dummyvariable))
+; realarg may be surrounded by (setq <variable which holds result> realarg)
+; in the case that the result is the list to be mapped over (this only occurs
+; with the function mapc).
+;
+(defun d-mapconvert (access join resu form )
+   (prog (vrbls finvar acc accform compform
+               tmp testform tempvar lastvar)
+
+       (setq finvar (gensym 'X)   ; holds result
+
+            vrbls
+            (reverse
+                (maplist '(lambda (arg)
+                              ((lambda (temp)
+                                   (cond ((or resu (cdr arg))
+                                          `(,temp ,(car arg)
+                                             (cdr ,temp)))
+                                         (t `(,temp
+                                               (setq ,finvar
+                                                      ,(car arg))
+                                               (cdr ,temp)))))
+                               (gensym 'X)))
+                         (reverse (cdr form))))
+
+            ; the access form will either be nil or car.  If it is
+            ; nil, then we are doing something like a maplist,
+            ; if the access form is car, then we are doing something
+            ; like a mapcar.
+            acc (mapcar '(lambda (tem)
+                             (cond (access `(,access ,(car tem)))
+                                   (t (car tem))))
+                        vrbls)
+
+            accform (cond ((or (atom (setq tmp (car form)))
+                               (null (setq tmp (d-macroexpand tmp)))
+                               (not (member (car tmp) '(quote function))))
+                           `(funcall ,tmp ,@acc))
+                          (t `(,(cadr tmp) ,@acc)))
+
+            ; the testform checks if any of the lists we are mapping
+            ; over is nil, in which case we quit.
+            testform (cond ((null (cdr vrbls)) `(null ,(caar vrbls)))
+                           (t `(or ,@(mapcar '(lambda (x)
+                                                  `(null ,(car  x)))
+                                             vrbls)))))
+
+       ; in the case of mapcans and mapcons, you need two
+       ; extra variables to simulate the nconc.
+       ; testvar gets intermediate results and lastvar
+       ; points to then end of the list
+       (if (eq join 'nconc)
+          then (setq tempvar (gensym 'X)
+                     lastvar (gensym 'X)
+                     vrbls `((,tempvar) (,lastvar) ,@vrbls)))
+
+       (return
+          `((lambda
+                (,finvar)
+                (liszt-internal-do
+                    ( ,@vrbls)
+                    (,testform)
+                    ,(cond ((eq join 'nconc)
+                            `(cond ((setq ,tempvar ,accform)
+                                    (cond (,lastvar
+                                            (liszt-internal-do
+                                                ()
+                                                ((null (cdr ,lastvar)))
+                                                (setq ,lastvar
+                                                      (cdr ,lastvar)))
+                                            (rplacd ,lastvar ,tempvar))
+                                          (t (setq ,finvar
+                                                    (setq ,lastvar
+                                                          ,tempvar)))))))
+                           (join `(setq ,finvar (,join ,accform ,finvar)))
+                           (t accform)))
+                ,(cond ((eq resu 'identity) finvar)
+                       (resu `(,resu ,finvar))
+                       (t finvar)))
+            nil ))))
+
+; apply to successive elements, return second arg
+(defun cm-mapc nil
+         (d-mapconvert 'car nil nil (cdr v-form)))
+
+; apply to successive elements, return list of results
+(defun cm-mapcar nil
+         (d-mapconvert 'car 'cons 'nreverse (cdr v-form)))
+
+; apply to successive elements, returned nconc of results
+(defun cm-mapcan nil
+         (d-mapconvert 'car 'nconc 'identity (cdr v-form)))
+
+; apply to successive sublists, return second arg
+(defun cm-map nil
+         (d-mapconvert nil nil nil (cdr v-form)))
+
+; apply to successive sublists, return list of results
+(defun cm-maplist nil
+         (d-mapconvert nil 'cons 'reverse (cdr v-form)))
+
+; apply to successive sublists, return nconc of results
+(defun cm-mapcon nil
+         (d-mapconvert nil 'nconc 'identity (cdr v-form)))
+
+;--- cc-memq :: compile a memq expression
+;
+#+(or for-vax for-tahoe)
+(defun cc-memq nil
+  (let ((loc1 (d-simple (cadr v-form)))
+       (loc2 (d-simple (caddr v-form)))
+       looploc finlab)
+       (if loc2
+          then (d-clearreg 'r1)
+               (if loc1
+                   then (d-move loc1 'r1)
+                   else (let ((g-loc 'r1)
+                              g-cc
+                              g-ret)
+                            (d-exp (cadr v-form))))
+               (d-move loc2 'reg)
+          else (let ((g-loc 'stack)
+                     g-cc
+                     g-ret)
+                   (d-exp (cadr v-form)))
+               (push nil g-locs)
+               (incr g-loccnt)
+               (let ((g-loc 'reg)
+                     g-cc
+                     g-ret)
+                   (d-exp (caddr v-form)))
+               (L-pop 'r1)
+               (d-clearreg 'r1)
+               (unpush g-locs)
+               (decr g-loccnt))
+       ; now set up the jump addresses
+       (if (null g-loc)
+          then (setq loc1 (if (car g-cc) thenret else (d-genlab))
+                     loc2 (if (cdr g-cc) thenret else (d-genlab)))
+          else (setq loc1 (d-genlab)
+                     loc2 (d-genlab)))
+
+       (setq looploc (d-genlab))
+       (e-tst 'r0)
+       (e-write2 'jeql loc2)
+       (e-label looploc)
+       (e-cmp 'r1 '(4 r0))
+       (e-write2 'jeql loc1)
+       (e-move '(0 r0) 'r0)
+       (e-write2 'jneq looploc)
+       (if g-loc
+          then (e-label loc2)          ; nil result
+               (d-move 'reg g-loc)
+               (if (cdr g-cc)
+                   then (e-goto (cdr g-cc))
+                   else (e-goto (setq finlab (d-genlab))))
+          else (if (cdr g-cc)
+                   then (e-goto (cdr g-cc))
+                   else (e-label loc2)))
+       (if g-loc
+          then (e-label loc1)          ; non nil result
+               (d-move 'reg g-loc)
+               (if (car g-cc) then (e-goto (car g-cc)))
+          else (if (null (car g-cc)) then (e-label loc1)))
+       (if finlab then (e-label finlab))))
+
+#+for-68k
+(defun cc-memq nil
+   (let ((loc1 (d-simple (cadr v-form)))
+        (loc2 (d-simple (caddr v-form)))
+        looploc finlab
+        (tmp-data-reg (d-alloc-register 'd nil)))
+       (d-clearreg tmp-data-reg)
+       (d-clearreg 'a0)
+       (if loc2
+          then (if loc1
+                   then (d-move loc1 tmp-data-reg)
+                   else (let ((g-loc tmp-data-reg)
+                              g-cc
+                              g-ret)
+                            (d-exp (cadr v-form))))
+               (d-move loc2 'reg)
+          else (let ((g-loc 'stack)
+                     g-cc
+                     g-ret)
+                   (d-exp (cadr v-form)))
+               (push nil g-locs)
+               (incr g-loccnt)
+               (let ((g-loc 'reg)
+                     g-cc
+                     g-ret)
+                   (d-exp (caddr v-form)))
+               (L-pop tmp-data-reg)
+               (unpush g-locs)
+               (decr g-loccnt))
+       ; now set up the jump addresses
+       (if (null g-loc)
+          then (setq loc1 (if (car g-cc) thenret else (d-genlab))
+                     loc2 (if (cdr g-cc) thenret else (d-genlab)))
+          else (setq loc1 (d-genlab)
+                     loc2 (d-genlab)))
+       (setq looploc (d-genlab))
+       (e-cmpnil 'd0)
+       (e-write2 'jeq loc2)
+       (e-move 'd0 'a0)
+       (e-label looploc)
+       (e-cmp tmp-data-reg '(4 a0))
+       (e-write2 'jeq loc1)
+       (e-move '(0 a0) 'a0)
+       (e-cmpnil 'a0)
+       (e-write2 'jne looploc)
+       (e-move 'a0 'd0)
+       (if g-loc
+          then (e-label loc2)                  ; nil result
+               (d-move 'reg g-loc)
+               (if (cdr g-cc)
+                   then (e-goto (cdr g-cc))
+                   else (e-goto (setq finlab (d-genlab))))
+          else (if (cdr g-cc)
+                   then (e-goto (cdr g-cc))
+                   else (e-label loc2)))
+       (if g-loc
+          then (e-label loc1)                  ; non nil result
+               (d-move 'a0 g-loc)              ;a0 was cdr of non-nil result
+               (if (car g-cc) then (e-goto (car g-cc)))
+          else (if (null (car g-cc)) then (e-label loc1)))
+       (if finlab then (e-label finlab))))