home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / lisp / liszt / funb.l < prev    next >
Encoding:
Text File  |  1987-12-15  |  23.7 KB  |  788 lines

  1. (include-if (null (get 'chead 'version)) "../chead.l")
  2. (Liszt-file funb
  3.    "$Header: funb.l,v 1.13 87/12/15 17:02:17 sklower Exp $")
  4.  
  5. ;;; ----    f u n b                function compilation
  6. ;;;
  7. ;;;                -[Wed Aug 24 17:14:56 1983 by layer]-
  8.  
  9. ;--- c-declare :: handle the "declare" form
  10. ; if a declare is seen inside a function definition, we just 
  11. ; ignore it.  We probably should see what it is declareing, as it
  12. ; might be declaring a special.
  13. ;
  14. (defun c-declare nil nil)
  15.  
  16. ;--- c-do :: compile a "do" expression
  17. ;
  18. ; a do has this form:
  19. ;  (do vrbls tst . body)
  20. ; we note the special case of tst being nil, in which case the loop
  21. ; is evaluated only once, and thus acts like a let with labels allowed.
  22. ; The do statement is a cross between a prog and a lambda. It is like
  23. ; a prog in that labels are allowed. It is like a lambda in that
  24. ; we stack the values of all init forms then bind to the variables, just
  25. ; like a lambda expression (that is the initial values of even specials
  26. ; are stored on the stack, and then copied into the value cell of the
  27. ; atom during the binding phase. From then on the stack location is
  28. ; not used).
  29. ;
  30. (defun c-do nil
  31.    (let (b-vrbls b-tst b-body chklab bodylab x-repeat x-vrbs x-fst
  32.          g-loc g-cc oldreguse (g-decls g-decls))
  33.        (forcecomment '(beginning do))
  34.        (setq g-loc 'reg  chklab (d-genlab)   bodylab (d-genlab))
  35.  
  36.        (if (and (cadr v-form) (atom (cadr v-form)))
  37.        then (setq v-form (d-olddo-to-newdo (cdr v-form))))
  38.  
  39.        (push (cons 'do 0) g-locs)        ; begin our frame
  40.  
  41.        (setq b-vrbls (cadr v-form)
  42.          b-tst   (caddr v-form)
  43.          b-body  (cdddr v-form))
  44.  
  45.        (d-scanfordecls b-body)
  46.  
  47.        ; push value of init forms on stack
  48.        (d-pushargs (mapcar '(lambda (x)
  49.                 (if (atom x)
  50.                     then nil ; no init form => nil
  51.                     else (cadr x)))
  52.                b-vrbls))
  53.  
  54.        ; now bind to  the variables in the vrbls form
  55.        (d-bindlamb (mapcar '(lambda (x)
  56.                 (if (atom x) then x
  57.                     else (car x)))
  58.                b-vrbls))
  59.  
  60.        ; search through body for all labels and assign them gensymed labels
  61.        (push (cons (d-genlab)
  62.            (do ((ll b-body (cdr ll))
  63.             (res))
  64.                ((null ll) res)
  65.                (if (and (car ll) (symbolp (car ll)))
  66.                then (Push res
  67.                       (cons (car ll) (d-genlab))))))
  68.          g-labs)
  69.  
  70.        ; if the test is non nil, we do the test
  71.        ; another strange thing, a test form of (pred) will not return
  72.        ; the value of pred if it is not nil! it will return nil -- in this
  73.        ; way, it is not like a cond clause
  74.        (d-clearreg)
  75.        (if b-tst then (e-label chklab)
  76.        (let ((g-cc (cons nil bodylab)) g-loc g-ret)
  77.            (d-exp (car b-tst)))    ; eval test
  78.        ; if false, do body
  79.        (if (cdr b-tst) 
  80.            then (setq oldreguse (copy g-reguse))
  81.             (d-exps (cdr b-tst))
  82.             (setq g-reguse oldreguse)
  83.            else  (d-move 'Nil 'reg))
  84.        (e-goto (caar g-labs))        ; leave do
  85.        (e-label bodylab))        ; begin body
  86.  
  87.        ; process body
  88.        (do ((ll b-body (cdr ll))
  89.         (g-cc) (g-loc)(g-ret))
  90.        ((null ll))
  91.        (if (or (null (car ll)) (not (symbolp (car ll))))
  92.            then (d-exp (car ll))
  93.            else (e-label (cdr (assoc (car ll) (cdar g-labs))))
  94.             (d-clearreg)))
  95.  
  96.        (if b-tst
  97.        then ; determine all repeat forms which must be
  98.         ; evaluated, and all the variables affected.
  99.         ; store the results in x-repeat and  x-vrbs
  100.         ; if there is just one repeat form, we calculate
  101.         ; its value directly into where it is stored,
  102.         ; if there is more than one, we stack them
  103.         ; and then store them back at once.
  104.         (do ((ll b-vrbls (cdr ll)))
  105.             ((null ll))
  106.             (if (and (dtpr (car ll)) (cddar ll))
  107.             then (Push x-repeat (caddar ll))
  108.                  (Push x-vrbs   (caar ll))))
  109.         (if x-vrbs 
  110.             then (if (null (cdr x-vrbs))  ; if just one repeat
  111.                  then (let ((g-loc (d-locv (car x-vrbs)))
  112.                     (g-cc nil))
  113.                       (d-exp (car x-repeat)))
  114.                  else (setq x-fst (car x-repeat))
  115.                   (d-pushargs (nreverse
  116.                           (cdr x-repeat)))
  117.                   (let ((g-loc (d-locv (car x-vrbs)))
  118.                     (g-cc)
  119.                     (g-ret))
  120.                       (d-exp x-fst))
  121.                   (do ((ll (cdr x-vrbs) (cdr ll)))
  122.                       ((null ll))
  123.                       (d-move 'unstack
  124.                           (d-locv (car ll)))
  125.                       (setq g-locs (cdr g-locs))
  126.                       (decr g-loccnt))))
  127.         (e-goto chklab))
  128.  
  129.        (e-label (caar g-labs))            ; end of do label
  130.        (d-clearreg)
  131.        (d-unbind)
  132.        (setq g-labs (cdr g-labs))))
  133.  
  134. ;--- d-olddo-to-newdo  :: map old do to new do
  135. ;
  136. ; form of old do is  (do var tst . body)
  137. ; where var is a symbol, not nil
  138. ;
  139. (defun d-olddo-to-newdo (v-l)
  140.   `(do ((,(car v-l) ,(cadr v-l) ,(caddr v-l)))
  141.        (,(cadddr v-l))
  142.        ,@(cddddr v-l)))
  143.  
  144. ;--- cc-dtpr :: check for dtprness
  145. ;
  146. (defun cc-dtpr nil
  147.   (d-typesimp (cadr v-form) #.(immed-const 3)))
  148.  
  149. ;--- cc-eq :: compile an "eq" expression
  150. ;
  151. (defun cc-eq nil
  152.    (let ((arg1 (cadr v-form))
  153.      (arg2 (caddr v-form))
  154.      arg1loc
  155.      arg2loc)
  156.        (if (setq arg2loc (d-simple arg2))
  157.        then (if (setq arg1loc (d-simple arg1))
  158.             then ; eq <simple> <simple>
  159.              (d-cmp arg1loc arg2loc)
  160.             else ; eq <nonsimple> <simple>
  161.              (let ((g-loc 'reg)    ; put <nonsimple> in reg
  162.                    ; must rebind because
  163.                    ; cc->& may have modified
  164.                    (g-trueop #+(or for-vax for-tahoe) 'jneq
  165.                      #+for-68k 'jne)
  166.                    (g-falseop #+(or for-vax for-tahoe) 'jeql
  167.                       #+for-68k 'jeq)
  168.                    g-cc
  169.                    g-ret)
  170.                  (d-exp arg1))
  171.              (d-cmp 'reg arg2loc))
  172.        else ; since second is nonsimple, must stack first
  173.         ; arg out of harms way
  174.         (let ((g-loc 'stack)
  175.               (g-trueop #+(or for-vax for-tahoe) 'jneq #+for-68k 'jne)
  176.               (g-falseop #+(or for-vax for-tahoe) 'jeql #+for-68k 'jeq)
  177.               g-cc
  178.               g-ret)
  179.             (d-exp arg1)
  180.             (push nil g-locs)
  181.             (incr g-loccnt)
  182.             (setq g-loc 'reg)        ; second arg to reg
  183.             (d-exp arg2))
  184.         (d-cmp 'unstack 'reg)
  185.         (setq g-locs (cdr g-locs))
  186.         (decr g-loccnt)))
  187.    (d-invert))
  188.  
  189. ;--- cc-equal :: compile `equal'
  190. ;
  191. (defun cc-equal nil
  192.   (let ((lab1 (d-genlab))
  193.     (lab11 (d-genlab))
  194.     lab2)
  195.        (d-pushargs (cdr v-form))
  196.        (e-cmp '(-8 #.np-reg) '(-4 #.np-reg))
  197.        (e-gotonil lab1)
  198.        (d-calltran 'equal '2)         ; not eq, try equal.
  199.        (d-clearreg)
  200.        #+(or for-vax for-tahoe) (e-tst (e-cvt 'reg))
  201.        #+for-68k (e-cmpnil (e-cvt 'reg))
  202.        (e-gotot lab11)        
  203.        (if g-loc then (d-move 'Nil g-loc))
  204.        (if (cdr g-cc) then (e-goto (cdr g-cc))
  205.        else (e-goto (setq lab2 (d-genlab))))
  206.        (e-writel lab1)
  207.        (e-dropnp 2)
  208.        (e-writel lab11)
  209.        (if g-loc then (d-move 'T g-loc))
  210.        (if (car g-cc) then (e-goto (car g-cc)))
  211.        (if lab2 then (e-writel lab2))
  212.        (setq g-locs (cddr g-locs))
  213.        (setq g-loccnt (- g-loccnt 2))))
  214.  
  215. ;--- c-errset :: compile an errset expression
  216. ;
  217. ; the errset has this form: (errset 'value ['tag])
  218. ; where tag defaults to t.
  219. ;
  220. (defun c-errset nil
  221.   (let ((g-loc 'reg)
  222.     (g-cc nil)
  223.     (g-ret nil)
  224.     (finlab (d-genlab))
  225.     (beglab (d-genlab)))
  226.        (d-exp (if (cddr v-form) then (caddr v-form) else t))
  227.        (d-pushframe #.F_CATCH (d-loclit 'ER%all nil) 'reg)
  228.        (push nil g-labs)        ; disallow labels
  229.        ; If retval is non zero then an error has throw us here so we 
  230.        ; must recover the value thrown (from _lispretval) and leave
  231.        ; If retval is zero then we shoud calculate the expression 
  232.        ; into r0  and put a cons cell around it
  233.        (e-tst '_retval)
  234.        (e-write2 #+(or for-vax for-tahoe) 'jeql #+for-68k 'jeq beglab)
  235.        (e-move '_lispretval (e-cvt 'reg))
  236.        (e-write2 #+(or for-vax for-tahoe) 'jbr #+for-68k 'jra finlab)
  237.        (e-label beglab)
  238.        (let ((g-loc 'stack)
  239.          (g-cc nil))
  240.         (d-exp (cadr v-form)))
  241.        (d-move 'Nil 'stack)    ; haven't updated g-loc, g-loccnt but it
  242.                 ; shouldn't hurt (famous last words)
  243.        (e-quick-call '_qcons)
  244.        (e-label finlab)
  245.        (d-popframe)
  246.        (unpush g-locs)        ; remove (catcherrset . 0)
  247.        (unpush g-labs)        ; remove nil
  248.        (d-clearreg)))
  249.  
  250. ;--- cm-fixnum-cxr :: open code a fixnum-cxr expression.
  251. ; fixnum-cxr is a compile only hacky function which accesses an element
  252. ; of a fixnum space and boxes the resulting fixnum.  It can be used
  253. ; for rapid access to user defined structures.
  254. ;
  255. (defun cm-fixnum-cxr ()
  256.   `(internal-fixnum-box (cxr ,@(cdr v-form))))
  257.  
  258. (defun c-internal-fixnum-box ()
  259.   (let ((g-cc nil)
  260.     (g-ret nil)
  261.     (g-loc '#.fixnum-reg))
  262.        #+for-68k (d-regused '#.fixnum-reg)
  263.        (d-exp (cadr v-form))
  264.        (e-call-qnewint)))
  265.  
  266. ;--- cc-offset-cxr
  267. ; return a pointer to the address of the object instead of the object.
  268. ;
  269. (defun cc-offset-cxr nil
  270.   (d-supercxr nil t))
  271.  
  272. ;--- cc-fixp :: check for a fixnum or bignum
  273. ;
  274. (defun cc-fixp nil
  275.   (d-typecmplx (cadr v-form) 
  276.            '#.(immed-const (plus 1_2 1_9))))
  277.  
  278. ;--- cc-floatp :: check for a flonum
  279. ;
  280. (defun cc-floatp nil
  281.   (d-typesimp (cadr v-form) #.(immed-const 4)))
  282.  
  283. ;--- c-funcall :: compile a funcall
  284. ;
  285. ; we open code a funcall the resulting object is a compiled lambda.
  286. ; We don't open code nlambda and macro funcalls since they are
  287. ; rarely used and it would waste space to check for them
  288. (defun c-funcall nil
  289.    (if (null (cdr v-form))
  290.       then (comp-err "funcall requires at least one argument " v-form))
  291.    (let ((g-locs g-locs)
  292.      (g-loccnt g-loccnt)
  293.      (args (length (cdr v-form)))
  294.      (g-loc nil)
  295.      (g-ret nil)
  296.      (g-cc nil))
  297.       (d-pushargs (cdr v-form))
  298.       (rplaca (nthcdr (1- args) g-locs) 'funcallfcn)
  299.  
  300.       (d-exp '(cond ((and (symbolp funcallfcn)
  301.               (getd funcallfcn))
  302.              (setq funcallfcn (getd funcallfcn)))))
  303.          
  304.       (d-exp `(cond ((and (bcdp funcallfcn) (eq 'lambda (getdisc funcallfcn)))
  305.             (Internal-bcdcall ,args t))
  306.                (t (Internal-bcdcall  ,args nil))))))
  307.  
  308. ;--- c-Internal-bcdcall
  309. ; this is a compiler internal function call.  when this occurs, there
  310. ;  are argnum objects stacked, the first of which is a function name
  311. ;  or bcd object.  If dobcdcall is t then we want to do a bcdcall of
  312. ;  the first object stacked.  If it is not true then we want to
  313. ;  call the interpreter funcall function to handle it.
  314. ;
  315. (defun c-Internal-bcdcall nil
  316.    (let ((argnum (cadr v-form))
  317.      (dobcdcall (caddr v-form)))
  318.       (cond (dobcdcall (d-bcdcall argnum))
  319.         (t (d-calltran 'funcall argnum)))))
  320.  
  321. ;--- cc-function :: compile a function function
  322. ;
  323. ; function is an nlambda, which the interpreter treats as 'quote'
  324. ; If the argument is a lambda expression, then Liszt will generate
  325. ; a new function and generate code to return the name of
  326. ; that function.  If the argument is a symbol, then 'symbol
  327. ; is compiled.   It would probably be better to return the function
  328. ; cell of the symbol, but Maclisp returns the symbol and it
  329. ; would cause compatibility problems.
  330. ;
  331. (defun cc-function nil
  332.    (if (or (null (cdr v-form))
  333.        (cddr v-form))
  334.       then (comp-err "Wrong number of arguments to 'function': " v-form))
  335.    (let ((arg (cadr v-form)))
  336.       (if (symbolp arg)
  337.      then (d-exp `',arg)
  338.        elseif (and (dtpr arg)
  339.            (memq (car arg) '(lambda nlambda lexpr)))
  340.      then (let ((newname (concat "in-line-lambda:"
  341.                      (setq in-line-lambda-number
  342.                        (add1 in-line-lambda-number)))))
  343.          (Push liszt-process-forms
  344.                `(def ,newname ,arg))
  345.          (d-exp `',newname))
  346.      else (comp-err "Illegal argument to 'function': " v-form))))
  347.  
  348. ;--- c-get :: do a get from the prop list
  349. ;
  350. (defun c-get nil
  351.   (if (not (eq 2 (length (cdr v-form))))
  352.       then (comp-err "Wrong number of args to get " v-form))
  353.   (d-pushargs (cdr v-form))        ; there better be 2 args
  354.   (e-quick-call '_qget)
  355.   (d-clearreg)
  356.   (setq g-locs (cddr g-locs))
  357.   (setq g-loccnt (- g-loccnt 2)))
  358.  
  359. ;--- cm-getaccess :: compile a getaccess instruction
  360. ;
  361. (defun cm-getaccess nil `(cdr ,(cadr v-form)))
  362.  
  363. ;--- cm-getaux :: compile a getaux instruction
  364. ;
  365. (defun cm-getaux  nil `(car ,(cadr v-form)))
  366.  
  367. ;--- cm-getd :: compile a getd instruction
  368. ;
  369. ; the getd function is open coded to look in the third part of a symbol
  370. ; cell
  371. ;
  372. (defun cm-getd nil `(cxr 2 ,(cadr v-form)))
  373.  
  374. ;--- cm-getdata :: compile a getdata instruction
  375. ;
  376. ; the getdata function is open coded to look in the third part of an 
  377. ; array header.
  378. (defun cm-getdata nil `(cxr 2 ,(cadr v-form)))
  379.  
  380. ;--- cm-getdisc  :: compile a getdisc expression
  381. ; getdisc accessed the discipline field of a binary object.
  382. ;
  383. (defun cm-getdisc nil `(cxr 1 ,(cadr v-form)))
  384.  
  385. ;--- c-go :: compile a "go" expression
  386. ;
  387. ; we only compile the (go symbol)type expression, we do not
  388. ; allow symbol to be anything by a non null symbol.
  389. ;
  390. (defun c-go nil
  391.    ; find number of frames we have to go down to get to the label
  392.    (do ((labs g-labs (cdr labs))
  393.     (locs g-locs)
  394.     (locals 0)
  395.     (specials 0)
  396.     (catcherrset 0)
  397.     (label))
  398.        ((null labs)
  399.     (comp-err "go label not found for expression: " (or v-form)))
  400.  
  401.        (if (car labs)         ; if we have a set of labels to look at...
  402.        then (if (setq label
  403.               (do ((lbs (cdar labs) (cdr lbs)))
  404.                   ((null lbs))
  405.                   (if (eq (caar lbs) (cadr v-form))
  406.                   then (return (cdar lbs)))))
  407.             then (if (not (eq labs g-labs))
  408.                  then (comp-note g-fname ": non local go used : "
  409.                          (or v-form)))
  410.              ; three stack to pop: namestack, bindstack
  411.              ;   and execution stack
  412.              (e-pop locals)
  413.              (if (greaterp specials 0)
  414.                  then (e-unshallowbind specials))
  415.              (if (greaterp catcherrset 0)
  416.                  then (comp-note g-fname
  417.                          ": Go through a catch or errset "
  418.                          v-form)
  419.                   (do ((i 0 (1+ i)))
  420.                       ((=& catcherrset i))
  421.                       (d-popframe)))
  422.              (e-goto label)
  423.              (return)))
  424.        ; tally all locals, specials and catcherrsets used in this frame
  425.        (do ()
  426.        ((dtpr (car locs))
  427.         (if (eq 'catcherrset (caar locs))
  428.            then (incr catcherrset)
  429.          elseif (eq 'progv (caar locs))
  430.            then (comp-err "Attempt to 'go' through a progv"))
  431.         (setq specials (+ specials (cdar locs))
  432.           locs (cdr locs)))
  433.        (setq locs (cdr locs))
  434.        (incr locals))))
  435.             
  436. ;--- cc-ignore :: just ignore this code
  437. ;
  438. (defun cc-ignore nil
  439.   nil)
  440.  
  441. ;--- c-lambexp :: compile a lambda expression
  442. ;
  443. (defun c-lambexp nil
  444.   (let ((g-loc (if (or g-loc g-cc) then 'reg))
  445.     (g-cc nil)
  446.     (g-locs (cons (cons 'lambda 0) g-locs))
  447.     (g-labs (cons nil g-labs)))
  448.        (d-pushargs (cdr v-form))        ; then push vals
  449.        (d-lambbody (car v-form))
  450.        (d-clearreg)))
  451.  
  452. ;--- d-lambbody :: do a lambda body
  453. ;    - body : body of lambda expression, eg (lambda () dld)
  454. ;
  455. (defun d-lambbody (body)
  456.    (let ((g-decls g-decls))
  457.       (d-scanfordecls (cddr body))        ; look for declarations
  458.       (d-bindlamb (cadr body))        ; bind locals
  459.       (d-clearreg)
  460.       (d-exp (do ((ll (cddr body) (cdr ll))
  461.           (g-loc)
  462.           (g-cc)
  463.           (g-ret))
  464.          ((null (cdr ll)) (car ll))
  465.          (d-exp (car ll))))
  466.  
  467.       (d-unbind)))                ; unbind this frame
  468.  
  469. ;--- d-bindlamb :: bind  variables in lambda list
  470. ;    - vrbs : list of lambda variables, may include nil meaning ignore
  471. ;
  472. (defun d-bindlamb (vrbs)
  473.   (let ((res (d-bindlrec (reverse vrbs) g-locs 0 g-loccnt)))
  474.        (if res then (e-setupbind)
  475.             (mapc '(lambda (vrb) (e-shallowbind (car vrb) (cdr vrb)))
  476.               res)
  477.             (e-unsetupbind))))
  478.   
  479. ;--- d-bindlrec :: recusive routine to bind lambda variables
  480. ;    - vrb : list of variables yet to bind
  481. ;    - locs : current location in g-loc
  482. ;    - specs : number of specials seen so far
  483. ;    - lev  : how far up from the bottom of stack we are.
  484. ; returns: list of elements, one for each special, of this form:
  485. ;        (<specialvrbname> stack <n>)
  486. ;    where specialvrbname is the name of the special variable, and n is
  487. ;    the distance from the top of the stack where its initial value is 
  488. ;    located
  489. ; also: puts the names of the local variables in the g-locs list, as well
  490. ;    as placing the number of special variables in the lambda header.
  491. ;
  492. (defun d-bindlrec (vrb locs specs lev)
  493.    (if vrb 
  494.        then (let ((spcflg (d-specialp (car vrb)))
  495.           retv)
  496.         (if spcflg then (setq specs (1+ specs)))
  497.  
  498.         (if (cdr vrb)        ; if more vrbls to go ...
  499.             then (setq retv (d-bindlrec (cdr vrb)
  500.                         (cdr locs)
  501.                         specs
  502.                         (1- lev)))
  503.             else (rplacd (cadr locs)
  504.                  specs))    ; else fix up lambda hdr
  505.  
  506.         (if (not spcflg) then (rplaca locs (car vrb))
  507.             else (Push retv `(,(car vrb) stack ,lev)))
  508.  
  509.         retv)))
  510.  
  511. ;--- d-scanfordecls
  512. ; forms - the body of a lambda, prog or do.
  513. ;  we look down the form for 'declare' forms.  They should be at the
  514. ;  beginning, but there are macros which may unintentionally put forms
  515. ;  in front of user written forms.  Thus we check a little further than
  516. ;  the first form.
  517. (defun d-scanfordecls (forms)
  518.    ; look for declarations in the first few forms
  519.    (do ((count 3 (1- count)))
  520.        ((= 0 count))
  521.        (cond ((and (dtpr (car forms))
  522.            (eq 'declare (caar forms))
  523.            (apply 'liszt-declare (cdar forms)))))
  524.        (setq forms (cdr forms))))
  525.  
  526. ;--- c-list :: compile a list expression
  527. ;
  528. ; this is compiled as a bunch of conses with a nil pushed on the
  529. ; top for good measure
  530. ;
  531. (defun c-list nil
  532.   (prog (nargs)
  533.     (setq nargs (length (cdr v-form)))
  534.     (makecomment '(list expression))
  535.     (if (zerop nargs)
  536.         then (d-move 'Nil 'reg)    ; (list) ==> nil
  537.          (return))
  538.     (d-pushargs (cdr v-form))
  539.     #+(or for-vax for-tahoe) (e-write2 'clrl '#.np-plus) ; stack one nil
  540.     #+for-68k (L-push (e-cvt 'Nil))
  541.  
  542.        ; now do the consing
  543.        (do ((i (max 1 nargs) (1- i)))
  544.        ((zerop i))
  545.        (e-quick-call '_qcons)
  546.        (d-clearreg)
  547.        (if (> i 1) then (L-push (e-cvt 'reg))))
  548.  
  549.        (setq g-locs (nthcdr nargs g-locs)
  550.          g-loccnt (- g-loccnt nargs))))
  551.  
  552. ;--- d-mapconvert - access : function to access parts of lists
  553. ;          - join     : function to join results
  554. ;          - resu     : function to apply to result
  555. ;          - form     : mapping form
  556. ;    This function converts maps to an equivalent do form.
  557. ;
  558. ;  in this function, the variable vrbls contains a list of forms, one form
  559. ;  per list we are mapping over.  The form of the form is 
  560. ;    (dummyvariable  realarg  (cdr dummyvariable))
  561. ; realarg may be surrounded by (setq <variable which holds result> realarg)
  562. ; in the case that the result is the list to be mapped over (this only occurs
  563. ; with the function mapc).
  564. ;
  565. (defun d-mapconvert (access join resu form )
  566.    (prog (vrbls finvar acc accform compform
  567.         tmp testform tempvar lastvar)
  568.  
  569.        (setq finvar (gensym 'X)   ; holds result
  570.  
  571.          vrbls
  572.          (reverse
  573.          (maplist '(lambda (arg)
  574.                    ((lambda (temp)
  575.                     (cond ((or resu (cdr arg))
  576.                        `(,temp ,(car arg)
  577.                           (cdr ,temp)))
  578.                       (t `(,temp
  579.                         (setq ,finvar
  580.                                ,(car arg))
  581.                         (cdr ,temp)))))
  582.                 (gensym 'X)))
  583.               (reverse (cdr form))))
  584.  
  585.          ; the access form will either be nil or car.  If it is
  586.          ; nil, then we are doing something like a maplist,
  587.          ; if the access form is car, then we are doing something
  588.          ; like a mapcar.
  589.          acc (mapcar '(lambda (tem)
  590.                   (cond (access `(,access ,(car tem)))
  591.                     (t (car tem))))
  592.              vrbls)
  593.  
  594.          accform (cond ((or (atom (setq tmp (car form)))
  595.                 (null (setq tmp (d-macroexpand tmp)))
  596.                 (not (member (car tmp) '(quote function))))
  597.                 `(funcall ,tmp ,@acc))
  598.                (t `(,(cadr tmp) ,@acc)))
  599.  
  600.          ; the testform checks if any of the lists we are mapping
  601.          ; over is nil, in which case we quit.
  602.          testform (cond ((null (cdr vrbls)) `(null ,(caar vrbls)))
  603.                 (t `(or ,@(mapcar '(lambda (x)
  604.                            `(null ,(car  x)))
  605.                           vrbls)))))
  606.  
  607.        ; in the case of mapcans and mapcons, you need two
  608.        ; extra variables to simulate the nconc.
  609.        ; testvar gets intermediate results and lastvar
  610.        ; points to then end of the list
  611.        (if (eq join 'nconc)
  612.        then (setq tempvar (gensym 'X)
  613.               lastvar (gensym 'X)
  614.               vrbls `((,tempvar) (,lastvar) ,@vrbls)))
  615.  
  616.        (return
  617.        `((lambda
  618.          (,finvar)
  619.          (liszt-internal-do
  620.              ( ,@vrbls)
  621.              (,testform)
  622.              ,(cond ((eq join 'nconc)
  623.                  `(cond ((setq ,tempvar ,accform)
  624.                      (cond (,lastvar
  625.                          (liszt-internal-do
  626.                          ()
  627.                          ((null (cdr ,lastvar)))
  628.                          (setq ,lastvar
  629.                                (cdr ,lastvar)))
  630.                          (rplacd ,lastvar ,tempvar))
  631.                        (t (setq ,finvar
  632.                              (setq ,lastvar
  633.                                ,tempvar)))))))
  634.                 (join `(setq ,finvar (,join ,accform ,finvar)))
  635.                 (t accform)))
  636.          ,(cond ((eq resu 'identity) finvar)
  637.             (resu `(,resu ,finvar))
  638.             (t finvar)))
  639.          nil ))))
  640.  
  641. ; apply to successive elements, return second arg
  642. (defun cm-mapc nil
  643.       (d-mapconvert 'car nil nil (cdr v-form)))
  644.  
  645. ; apply to successive elements, return list of results
  646. (defun cm-mapcar nil
  647.       (d-mapconvert 'car 'cons 'nreverse (cdr v-form)))
  648.  
  649. ; apply to successive elements, returned nconc of results
  650. (defun cm-mapcan nil
  651.       (d-mapconvert 'car 'nconc 'identity (cdr v-form)))
  652.  
  653. ; apply to successive sublists, return second arg
  654. (defun cm-map nil
  655.       (d-mapconvert nil nil nil (cdr v-form)))
  656.  
  657. ; apply to successive sublists, return list of results
  658. (defun cm-maplist nil
  659.       (d-mapconvert nil 'cons 'reverse (cdr v-form)))
  660.  
  661. ; apply to successive sublists, return nconc of results
  662. (defun cm-mapcon nil
  663.       (d-mapconvert nil 'nconc 'identity (cdr v-form)))
  664.  
  665. ;--- cc-memq :: compile a memq expression
  666. ;
  667. #+(or for-vax for-tahoe)
  668. (defun cc-memq nil
  669.   (let ((loc1 (d-simple (cadr v-form)))
  670.     (loc2 (d-simple (caddr v-form)))
  671.     looploc finlab)
  672.        (if loc2
  673.        then (d-clearreg 'r1)
  674.         (if loc1
  675.             then (d-move loc1 'r1)
  676.             else (let ((g-loc 'r1)
  677.                    g-cc
  678.                    g-ret)
  679.                  (d-exp (cadr v-form))))
  680.         (d-move loc2 'reg)
  681.        else (let ((g-loc 'stack)
  682.               g-cc
  683.               g-ret)
  684.             (d-exp (cadr v-form)))
  685.         (push nil g-locs)
  686.         (incr g-loccnt)
  687.         (let ((g-loc 'reg)
  688.               g-cc
  689.               g-ret)
  690.             (d-exp (caddr v-form)))
  691.         (L-pop 'r1)
  692.         (d-clearreg 'r1)
  693.         (unpush g-locs)
  694.         (decr g-loccnt))
  695.        ; now set up the jump addresses
  696.        (if (null g-loc)
  697.        then (setq loc1 (if (car g-cc) thenret else (d-genlab))
  698.               loc2 (if (cdr g-cc) thenret else (d-genlab)))
  699.        else (setq loc1 (d-genlab)
  700.               loc2 (d-genlab)))
  701.  
  702.        (setq looploc (d-genlab))
  703.        (e-tst 'r0)
  704.        (e-write2 'jeql loc2)
  705.        (e-label looploc)
  706.        (e-cmp 'r1 '(4 r0))
  707.        (e-write2 'jeql loc1)
  708.        (e-move '(0 r0) 'r0)
  709.        (e-write2 'jneq looploc)
  710.        (if g-loc
  711.        then (e-label loc2)        ; nil result
  712.         (d-move 'reg g-loc)
  713.         (if (cdr g-cc)
  714.             then (e-goto (cdr g-cc))
  715.             else (e-goto (setq finlab (d-genlab))))
  716.        else (if (cdr g-cc)
  717.             then (e-goto (cdr g-cc))
  718.             else (e-label loc2)))
  719.        (if g-loc
  720.        then (e-label loc1)        ; non nil result
  721.         (d-move 'reg g-loc)
  722.         (if (car g-cc) then (e-goto (car g-cc)))
  723.        else (if (null (car g-cc)) then (e-label loc1)))
  724.        (if finlab then (e-label finlab))))
  725.  
  726. #+for-68k
  727. (defun cc-memq nil
  728.    (let ((loc1 (d-simple (cadr v-form)))
  729.      (loc2 (d-simple (caddr v-form)))
  730.      looploc finlab
  731.      (tmp-data-reg (d-alloc-register 'd nil)))
  732.        (d-clearreg tmp-data-reg)
  733.        (d-clearreg 'a0)
  734.        (if loc2
  735.        then (if loc1
  736.             then (d-move loc1 tmp-data-reg)
  737.             else (let ((g-loc tmp-data-reg)
  738.                    g-cc
  739.                    g-ret)
  740.                  (d-exp (cadr v-form))))
  741.         (d-move loc2 'reg)
  742.        else (let ((g-loc 'stack)
  743.               g-cc
  744.               g-ret)
  745.             (d-exp (cadr v-form)))
  746.         (push nil g-locs)
  747.         (incr g-loccnt)
  748.         (let ((g-loc 'reg)
  749.               g-cc
  750.               g-ret)
  751.             (d-exp (caddr v-form)))
  752.         (L-pop tmp-data-reg)
  753.         (unpush g-locs)
  754.         (decr g-loccnt))
  755.        ; now set up the jump addresses
  756.        (if (null g-loc)
  757.        then (setq loc1 (if (car g-cc) thenret else (d-genlab))
  758.               loc2 (if (cdr g-cc) thenret else (d-genlab)))
  759.        else (setq loc1 (d-genlab)
  760.               loc2 (d-genlab)))
  761.        (setq looploc (d-genlab))
  762.        (e-cmpnil 'd0)
  763.        (e-write2 'jeq loc2)
  764.        (e-move 'd0 'a0)
  765.        (e-label looploc)
  766.        (e-cmp tmp-data-reg '(4 a0))
  767.        (e-write2 'jeq loc1)
  768.        (e-move '(0 a0) 'a0)
  769.        (e-cmpnil 'a0)
  770.        (e-write2 'jne looploc)
  771.        (e-move 'a0 'd0)
  772.        (if g-loc
  773.        then (e-label loc2)            ; nil result
  774.         (d-move 'reg g-loc)
  775.         (if (cdr g-cc)
  776.             then (e-goto (cdr g-cc))
  777.             else (e-goto (setq finlab (d-genlab))))
  778.        else (if (cdr g-cc)
  779.             then (e-goto (cdr g-cc))
  780.             else (e-label loc2)))
  781.        (if g-loc
  782.        then (e-label loc1)            ; non nil result
  783.         (d-move 'a0 g-loc)        ;a0 was cdr of non-nil result
  784.         (if (car g-cc) then (e-goto (car g-cc)))
  785.        else (if (null (car g-cc)) then (e-label loc1)))
  786.        (if finlab then (e-label finlab))))
  787.