home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / gcl-1.000 / gcl-1 / gcl-1.0 / cmpnew / cmplam.lsp < prev    next >
Encoding:
Lisp/Scheme  |  1994-05-07  |  33.1 KB  |  972 lines

  1. ;;; CMPLAM  Lambda expression.
  2. ;;;
  3. ;; Copyright (C) 1994 M. Hagiya, W. Schelter, T. Yuasa
  4.  
  5. ;; This file is part of GNU Common Lisp, herein referred to as GCL
  6. ;;
  7. ;; GCL is free software; you can redistribute it and/or modify it under
  8. ;;  the terms of the GNU LIBRARY GENERAL PUBLIC LICENSE as published by
  9. ;; the Free Software Foundation; either version 2, or (at your option)
  10. ;; any later version.
  11. ;; 
  12. ;; GCL is distributed in the hope that it will be useful, but WITHOUT
  13. ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. ;; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public 
  15. ;; License for more details.
  16. ;; 
  17. ;; You should have received a copy of the GNU Library General Public License 
  18. ;; along with GCL; see the file COPYING.  If not, write to the Free Software
  19. ;; Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  
  22. (in-package 'compiler)
  23.  
  24. ;;; During Pass1, a lambda-list
  25. ;;;
  26. ;;; (    { var }*
  27. ;;;     [ &optional { var | ( var [ initform [ svar ] ] ) }* ]
  28. ;;;     [ &rest var ]
  29. ;;;     [ &key { var | ( { var | ( kwd var ) } [initform [ svar ]])}*
  30. ;;;         [&allow-other-keys]]
  31. ;;;     [ &aux {var | (var [initform])}*]
  32. ;;; )
  33. ;;;
  34. ;;; is transformed into
  35. ;;;
  36. ;;; (    ( { var }* )                ; required
  37. ;;;     ( { (var initform svar) }* )        ; optional
  38. ;;;     { var | nil }                ; rest
  39. ;;;     key-flag
  40. ;;;     ( { ( kwd-vv-index var initform svar) }* )    ; key
  41. ;;;     allow-other-keys-flag
  42. ;;; )
  43. ;;;
  44. ;;; where
  45. ;;;     svar:      nil        ; means svar is not supplied
  46. ;;;            | var
  47. ;;;
  48. ;;; &aux parameters will be embedded into LET*.
  49. ;;;
  50. ;;; c1lambda-expr receives
  51. ;;;    ( lambda-list { doc | decl }* . body )
  52. ;;; and returns
  53. ;;;    ( lambda info-object lambda-list' doc body' )
  54. ;;;
  55. ;;; Doc is NIL if no doc string is supplied.
  56. ;;; Body' is body possibly surrounded by a LET* (if &aux parameters are
  57. ;;; supplied) and an implicit block.
  58.  
  59. (defmacro ck-spec (condition)
  60.   `(unless ,condition
  61.            (cmperr "The parameter specification ~s is illegal." spec)))
  62.  
  63. (defmacro ck-vl (condition)
  64.   `(unless ,condition
  65.            (cmperr "The lambda list ~s is illegal." vl)))
  66.  
  67.  
  68. ;;;the following code implements downward closures.
  69. ;;;These are like closures, except they are guaranteed not
  70. ;;;to survive past the exit of the function in which they
  71. ;;;are born.
  72.  
  73.  
  74. (defmacro downward-function (x)
  75.   `(function ,x))
  76.  
  77. (setf (get 'downward-function  'c1special)
  78.       'c1downward-function)
  79.  
  80. (defun c1downward-function (x)
  81.   (let* ((tem (c1expr (list 'function (car x))))
  82.      (info (cadr tem)))
  83.     ;; for the moment we only allow downward closures with no args
  84.     (cond ((and (consp x) (consp (car x))
  85.         (eq (caar x) 'lambda)
  86.         (null (second (car x))))
  87.        (dolist (var (info-referred-vars info))
  88.            (cond ((and (eq (var-kind var) 'lexical)
  89.                    (var-ref-ccb var) t)
  90.               (setf (var-kind var) 'down)))
  91.            )
  92.        (setf (car tem) 'downward-function)
  93.        tem)
  94.       (t tem))))
  95.  
  96. (si::putprop   'downward-function  'c2downward-function  'c2)
  97. (si:putprop 'make-dclosure 'wt-make-dclosure 'wt-loc)
  98.  
  99. (defun wt-make-dclosure (cfun clink)clink  ;;Dbase=base0
  100.   (wt-nl "(DownClose"cfun".t=t_dclosure,DownClose" cfun ".dc_self=LC" cfun","
  101.      "DownClose" cfun ".dc_env=base0,(object)&DownClose" cfun ")"))
  102.  
  103. (defun wfs-error ()
  104.   (error "This error is not supposed to occur: Contact Schelter ~
  105.     ~%wfs@math.utexas.edu"))
  106.  
  107. (defun wt-downward-closure-macro (cfun)
  108.   (cond (*downward-closures*
  109.       (wt-h "#define DCnames" cfun " ")
  110.       (setq *downward-closures* (delete 'dcnames *downward-closures*))
  111.       (cond (*downward-closures*
  112.           (wt-h1 "struct dclosure ")
  113.           (do ((v *downward-closures* (cdr v)))
  114.               ((null v))
  115.               (wt-h1 "DownClose")
  116.               (wt-h1 (car v))
  117.               (if (cdr v) (wt-h1 ",")))
  118.           (wt-h1 ";"))))))
  119.  
  120. (defun c2downward-function (funob)
  121.   (let ((fun (make-fun :name 'closure :cfun (next-cfun))))
  122.               (push (list 'dclosure (if (null *clink*) nil (cons 0 0))
  123.                           *ccb-vs* fun funob)
  124.                     *local-funs*)
  125.               (push fun *closures*)
  126.           (push (fun-cfun fun) *downward-closures*)
  127.               (unwind-exit (list 'make-dclosure (fun-cfun fun) *clink*))))
  128.  
  129.  
  130.  
  131. (defun c1lambda-expr (lambda-expr
  132.                       &optional (block-name nil block-it)
  133.                       &aux (requireds nil) (optionals nil) (rest nil)
  134.                            (keywords nil) (key-flag nil)
  135.                lambda-list
  136.                            (allow-other-keys nil) (aux-vars nil)
  137.                            (aux-inits nil) doc vl spec body ss is ts
  138.                            other-decls vnames
  139.                            (*vars* *vars*)
  140.                            (info (make-info))
  141.                            (aux-info nil)
  142.                (setjmps *setjmps*)
  143.                       )
  144.   (cmpck (endp lambda-expr)
  145.          "The lambda expression ~s is illegal." (cons 'lambda lambda-expr))
  146.  
  147.   (multiple-value-setq (body ss ts is other-decls doc)
  148.                        (c1body (cdr lambda-expr) t))
  149.   
  150.   (when block-it (setq body (list (cons 'block (cons block-name body)))))
  151.  
  152.   (c1add-globals ss)
  153.  
  154.   (setq vl (car lambda-expr))
  155.   (block parse
  156.    (tagbody
  157.     Lreq
  158.       (when (null vl) (return-from parse))
  159.       (ck-vl (consp vl))
  160.       (case (setq spec (pop vl))
  161.             (&optional (go Lopt))
  162.             (&rest (go Lrest))
  163.             (&key (go Lkey))
  164.             (&aux (go Laux)))
  165.       (let ((v (c1make-var spec ss is ts)))
  166.            (push spec vnames)
  167.            (push v *vars*)
  168.            (push v requireds))
  169.       (go Lreq)
  170.  
  171.     Lopt
  172.       (when (null vl) (return-from parse))
  173.       (ck-vl (consp vl))
  174.       (case (setq spec (pop vl))
  175.             (&rest (go Lrest))
  176.             (&key (go Lkey))
  177.             (&aux (go Laux)))
  178.       (cond ((not (consp spec))
  179.              (let ((v (c1make-var spec ss is ts)))
  180.                   (push spec vnames)
  181.                   (push (list v (default-init (var-type v)) nil) optionals)
  182.                   (push v *vars*)))
  183.             ((not (consp (cdr spec)))
  184.              (ck-spec (null (cdr spec)))
  185.              (let ((v (c1make-var (car spec) ss is ts)))
  186.                   (push (car spec) vnames)
  187.                   (push (list v (default-init (var-type v)) nil) optionals)
  188.                   (push v *vars*)))
  189.             ((not (consp (cddr spec)))
  190.              (ck-spec (null (cddr spec)))
  191.              (let ((init (c1expr* (cadr spec) info))
  192.                    (v (c1make-var (car spec) ss is ts)))
  193.                   (push (car spec) vnames)
  194.                   (push
  195.                    (list v (and-form-type (var-type v) init (cadr spec)) nil)
  196.                    optionals)
  197.                   (push v *vars*)))
  198.             (t
  199.              (ck-spec (null (cdddr spec)))
  200.              (let ((init (c1expr* (cadr spec) info))
  201.                    (v (c1make-var (car spec) ss is ts))
  202.                    (sv (c1make-var (caddr spec) ss is ts))
  203.                    )
  204.                   (push (car spec) vnames)
  205.                   (push (caddr spec) vnames)
  206.                   (push
  207.                    (list v (and-form-type (var-type v) init (cadr spec)) sv)
  208.                    optionals)
  209.                   (push v *vars*)
  210.                   (push sv *vars*))))
  211.       (go Lopt)
  212.  
  213.     Lrest
  214.       (ck-vl (consp vl))
  215.       (push (car vl) vnames)
  216.       (setq rest (c1make-var (pop vl) ss is ts))
  217.       (push rest *vars*)
  218.       (when (null vl) (return-from parse))
  219.       (ck-vl (consp vl))
  220.       (case (setq spec (pop vl))
  221.             (&key (go Lkey))
  222.             (&aux (go Laux)))
  223.       (cmperr "Either &key or &aux is missing before ~s." spec)
  224.  
  225.     Lkey
  226.       (setq key-flag t)
  227.       (when (null vl) (return-from parse))
  228.       (ck-vl (consp vl))
  229.       (case (setq spec (pop vl))
  230.             (&aux (go Laux))
  231.             (&allow-other-keys (setq allow-other-keys t)
  232.                                (when (null vl) (return-from parse))
  233.                                (ck-vl (consp vl))
  234.                                (case (setq spec (pop vl))
  235.                                      (&aux (go Laux)))
  236.                                (cmperr "&aux is missing before ~s." spec)))
  237.       (when (not (consp spec)) (setq spec (list spec)))
  238.       (cond ((consp (car spec))
  239.              (ck-spec (and (keywordp (caar spec))
  240.                            (consp (cdar spec))
  241.                            (null (cddar spec))))
  242.              (setq spec (cons (caar spec) (cons (cadar spec) (cdr spec)))))
  243.             (t
  244.              (ck-spec (symbolp (car spec)))
  245.              (setq spec (cons (intern (string (car spec)) 'keyword)
  246.                               (cons (car spec) (cdr spec))))))
  247.       (cond ((not (consp (cddr spec)))
  248.              (ck-spec (null (cddr spec)))
  249.              (let ((v (c1make-var (cadr spec) ss is ts)))
  250.                   (push (cadr spec) vnames)
  251.                   (push
  252.                    (list (car spec) v (default-init (var-type v))
  253.                          (make-var :kind 'DUMMY))
  254.                    keywords)
  255.                   (push v *vars*)))
  256.             ((not (consp (cdddr spec)))
  257.              (ck-spec (null (cdddr spec)))
  258.              (let ((init (c1expr* (caddr spec) info))
  259.                    (v (c1make-var (cadr spec) ss is ts)))
  260.                   (push (cadr spec) vnames)
  261.                   (push (list (car spec) v
  262.                               (and-form-type (var-type v) init (caddr spec))
  263.                               (make-var :kind 'DUMMY))
  264.                         keywords)
  265.                   (push v *vars*)))
  266.             (t
  267.              (ck-spec (null (cddddr spec)))
  268.              (let ((init (c1expr* (caddr spec) info))
  269.                    (v (c1make-var (cadr spec) ss is ts))
  270.                    (sv (c1make-var (cadddr spec) ss is ts)))
  271.                   (push (cadr spec) vnames)
  272.                   (push (cadddr spec) vnames)
  273.                   (push (list (car spec) v
  274.                               (and-form-type (var-type v) init (caddr spec))
  275.                               sv)
  276.                         keywords)
  277.                   (push v *vars*)
  278.                   (push sv *vars*))))
  279.       (go Lkey)
  280.  
  281.     Laux
  282.       (setq aux-info (make-info))
  283.     Laux1
  284.       (when (null vl) (add-info info aux-info) (return-from parse))
  285.       (ck-vl (consp vl))
  286.       (setq spec (pop vl))
  287.       (cond ((consp spec)
  288.              (cond ((not (consp (cdr spec)))
  289.                     (ck-spec (null (cdr spec)))
  290.                     (let ((v (c1make-var (car spec) ss is ts)))
  291.                          (push (car spec) vnames)
  292.                          (push (default-init (var-type v)) aux-inits)
  293.                          (push v aux-vars)
  294.                          (push v *vars*)))
  295.                    (t
  296.                     (ck-spec (null (cddr spec)))
  297.                     (let ((init (c1expr* (cadr spec) aux-info))
  298.                           (v (c1make-var (car spec) ss is ts)))
  299.                          (push (car spec) vnames)
  300.                          (push (and-form-type (var-type v) init (cadr spec))
  301.                                aux-inits)
  302.                          (push v aux-vars)
  303.                          (push v *vars*)))))
  304.             (t
  305.              (let ((v (c1make-var spec ss is ts)))
  306.                   (push spec vnames)
  307.                   (push (default-init (var-type v)) aux-inits)
  308.                   (push v aux-vars)
  309.                   (push v *vars*))))
  310.       (go Laux1)
  311.       )
  312.    )
  313.   (setq requireds (reverse requireds)
  314.         optionals (reverse optionals)
  315.         keywords (reverse keywords)
  316.         aux-vars (reverse aux-vars)
  317.         aux-inits (reverse aux-inits))
  318.  
  319.   (check-vdecl vnames ts is)
  320.  
  321.   (setq body (c1decl-body other-decls body))
  322.  
  323.   (add-info info (cadr body))
  324.  
  325.   (dolist** (var requireds) (check-vref var))
  326.   (dolist** (opt optionals)
  327.             (check-vref (car opt))
  328.             (when (caddr opt) (check-vref (caddr opt))))
  329.   (when rest (check-vref rest))
  330.   (dolist** (kwd keywords)
  331.             (check-vref (cadr kwd))
  332.             (when (cadddr kwd) (check-vref (cadddr kwd))))
  333.   (dolist** (var aux-vars) (check-vref var))
  334.   
  335.   (when aux-vars
  336.         (add-info aux-info (cadr body))
  337.         (setq body (list 'let* aux-info aux-vars aux-inits body))
  338.     (or (eql setjmps *setjmps*) (setf (info-volatile aux-info) t)))
  339.   
  340.   (setq body (fix-down-args requireds body block-name))
  341.   (setq lambda-list
  342.     (list requireds optionals rest key-flag keywords allow-other-keys))
  343.   (and *record-call-info* (record-arg-info lambda-list))
  344.   (list 'lambda
  345.         info
  346.     lambda-list
  347.         doc
  348.         body)
  349.   )
  350.  
  351.  
  352. ;;this makes a let for REQUIREDS which are used in a downward 
  353. ;;lexical closure
  354.  
  355. (defun fix-down-args(requireds body name &aux auxv auxinit info v)
  356.   (let ((types     (get  name 'proclaimed-arg-types))
  357.     (fixed (get name 'fixed-args)))
  358.     (do ((vv requireds (cdr vv))
  359.      (typ types (cdr typ)))
  360.     ((null vv))
  361.     (setq v (car vv))
  362.     (cond ((not (or fixed (eq (car typ) t)))
  363.            (return-from fix-down-args body))
  364.           ((and (eq (var-kind v) 'DOWN) (eq (var-loc v) 'object))
  365.            ;;a downward variable could not have been special
  366.            ;;and must be type t.  We create a new variable
  367.            ;;for the arg, and bind the old one to it.
  368.            (let* ((new (c1make-var (var-name v) nil nil nil))
  369.               (init
  370.                (list 'var 
  371.                  (or info (setq info (make-info)))
  372.                  (list new nil))))
  373.          (push  v auxv)
  374.          (setf (car vv) new)
  375.          (push new (info-referred-vars info))
  376.          (push init auxinit)))))
  377.     (if auxv (list 'let* info auxv auxinit body)
  378.       body)))
  379.  
  380. (defun the-parameter (name)
  381.   (cmpck (not (symbolp name)) "The parameter ~s is not a symbol." name)
  382.   (cmpck (constantp name) "The constant ~s is being bound." name)
  383.   name
  384.   )
  385.  
  386. (defvar *rest-on-stack* nil)  ;; non nil means put rest arg on C stack.
  387.  
  388. (defun c2lambda-expr (lambda-list body &optional (fname nil s-fname))
  389.   (let ((*tail-recursion-info*            ;;; Tail recursion possible if
  390.          (if (and *do-tail-recursion*
  391.                   s-fname            ;;; named function,
  392.                   (dolist* (var (car lambda-list) t)
  393.                     (when (var-ref-ccb var) (return nil)))
  394.                 ;;; no required is closed in a closure,
  395.                   (null (cadr lambda-list))    ;;; no optionals,
  396.                   (null (caddr lambda-list))    ;;; no rest parameter, and
  397.                   (not (cadddr lambda-list)))    ;;; no keywords.
  398.              (cons fname (car lambda-list))
  399.              nil)))
  400.     (let ((*rest-on-stack*
  401.         (cond ((and (caddr lambda-list)
  402.             (eq (var-type (caddr lambda-list)) :dynamic-extent))
  403.            t)
  404.           (t *rest-on-stack*))))
  405.        (if (cadddr lambda-list) ;;; key-flag
  406.            (c2lambda-expr-with-key lambda-list body)
  407.            (c2lambda-expr-without-key lambda-list body)))
  408.   ))
  409.  
  410. (defun c2lambda-expr-without-key
  411.        (lambda-list body
  412.         &aux (requireds (car lambda-list))
  413.              (optionals (cadr lambda-list))
  414.              (rest (caddr lambda-list))
  415.              (labels nil)
  416.              (*unwind-exit* *unwind-exit*)
  417.              (*vs* *vs*) (*clink* *clink*) (*ccb-vs* *ccb-vs*)
  418.              (block-p nil)
  419.         )
  420.   (declare (object requireds optionals rest))
  421.   ;;; Allocate immediate-type parameters.
  422.  
  423.   (flet ((do-decl (var)
  424.            (let ((kind (c2var-kind var)))
  425.                 (declare (object kind))
  426.                 (when kind
  427.                       (let ((cvar (next-cvar)))
  428.                            (setf (var-kind var) kind)
  429.                            (setf (var-loc var) cvar)
  430.                            (wt-nl)
  431.                            (unless block-p (wt "{") (setq block-p t))
  432.                (wt-var-decl var)
  433.                )))))
  434.  
  435.         (dolist** (v requireds) (do-decl v))
  436.         (dolist** (opt optionals)
  437.                   (do-decl (car opt))
  438.                   (when (caddr opt) (do-decl (caddr opt))))
  439.         (when rest (do-decl rest))
  440.         )
  441.   ;;; check arguments
  442.   (when (or *safe-compile* *compiler-check-args*)
  443.     (cond ((or rest optionals)
  444.            (when requireds
  445.              (wt-nl "if(vs_top-vs_base<" (length requireds)
  446.                     ") too_few_arguments();"))
  447.            (unless rest
  448.              (wt-nl "if(vs_top-vs_base>"
  449.                     (+ (length requireds) (length optionals))
  450.                     ") too_many_arguments();")))
  451.           (t (wt-nl "check_arg(" (length requireds) ");"))))
  452.  
  453.   ;;; Allocate the parameters.
  454.   (dolist** (var requireds) (setf (var-ref var) (vs-push)))
  455.   (dolist** (opt optionals) (setf (var-ref (car opt)) (vs-push)))
  456.   (when rest (setf (var-ref rest) (vs-push)))
  457.   (dolist** (opt optionals)
  458.             (when (caddr opt) (setf (var-ref (caddr opt)) (vs-push))))
  459.  
  460.   ;;; Bind required parameters.
  461.   (dolist** (var requireds) (c2bind var))
  462.  
  463.   ;;; Bind optional parameters as long as there remain arguments.
  464.   ;;; The compile-time binding is discarded because they are bound again.
  465.   (when (and (or optionals rest) (not (null requireds)))
  466.         (wt-nl "vs_base=vs_base+" (length requireds) ";"))
  467.   (cond (optionals
  468.          (let ((*clink* *clink*)
  469.                (*unwind-exit* *unwind-exit*)
  470.                (*ccb-vs* *ccb-vs*))
  471.            (when rest
  472.              (wt-nl "vs_top[0]=Cnil;")
  473.              (wt-nl "{object *p=vs_top, *q=vs_base+" (length optionals) ";")
  474.              (wt-nl " for(;p>q;p--)p[-1]=MMcons(p[-1],p[0]);}"))
  475.            (do ((opts optionals (cdr opts)))
  476.                ((endp opts))
  477.                (declare (object opts))
  478.              (push (next-label) labels)
  479.              (wt-nl "if(vs_base>=vs_top){")
  480.              (reset-top)
  481.              (wt-go (car labels)) (wt "}")
  482.              (c2bind (caar opts))
  483.              (when (caddar opts) (c2bind-loc (caddar opts) t))
  484.              (when  (cdr opts)  (wt-nl "vs_base++;"))
  485.              )
  486.            (when rest (c2bind rest))
  487.            )
  488.  
  489.          (wt-nl) (reset-top)
  490.  
  491.          (let ((label (next-label)))
  492.            (wt-nl) (wt-go label)
  493.  
  494.            (setq labels (reverse labels))
  495.  
  496.            ;;; Bind unspecified optional parameters.
  497.            (dolist** (opt optionals)
  498.              (wt-label (car labels))
  499.              (pop labels)
  500.              (c2bind-init (car opt) (cadr opt))
  501.              (when (caddr opt) (c2bind-loc (caddr opt) nil)))
  502.  
  503.              (when rest (c2bind-loc rest nil))
  504.  
  505.              (wt-label label)))
  506.         (rest
  507.          (wt-nl "vs_top[0]=Cnil;")
  508.          (wt-nl "{object *p=vs_top;")
  509.          (wt-nl " for(;p>vs_base;p--)p[-1]="
  510.         (if *rest-on-stack* "ON_STACK_CONS" "MMcons")
  511.         "(p[-1],p[0]);}")
  512.          (c2bind rest)
  513.          (wt-nl)
  514.          (reset-top))
  515.         (t
  516.          (wt-nl)
  517.          (reset-top)))
  518.  
  519.   (when *tail-recursion-info*
  520.         (push 'tail-recursion-mark *unwind-exit*) (wt-nl1 "TTL:;"))
  521.  
  522.   ;;; Now the parameters are ready!
  523.   (c2expr body)
  524.  
  525.   (when block-p (wt-nl "}"))
  526.   )
  527.  
  528. (defun c2lambda-expr-with-key
  529.        (lambda-list body
  530.         &aux (requireds (nth 0 lambda-list))
  531.              (optionals (nth 1 lambda-list))
  532.              (rest (nth 2 lambda-list))
  533.              (keywords (nth 4 lambda-list))
  534.              (allow-other-keys (nth 5 lambda-list))
  535.              (labels nil)
  536.              (*unwind-exit* *unwind-exit*)
  537.              (*vs* *vs*) (*clink* *clink*) (*ccb-vs* *ccb-vs*)
  538.              (block-p nil)
  539.              )
  540.   (declare
  541.    (object requireds optionals rest keywords allow-other-keys))
  542.   ;;; Allocate immediate-type parameters.
  543.   (flet ((do-decl (var)
  544.            (let ((kind (c2var-kind var)))
  545.                 (declare (object kind))
  546.                 (when kind
  547.                       (let ((cvar (next-cvar)))
  548.                            (setf (var-kind var) kind)
  549.                            (setf (var-loc var) cvar)
  550.                            (wt-nl)
  551.                            (unless block-p (wt "{") (setq block-p t))
  552.                (wt-var-decl var)
  553.                )))))
  554.  
  555.         (dolist** (v requireds) (do-decl v))
  556.         (dolist** (opt optionals)
  557.                   (do-decl (car opt))
  558.                   (when (caddr opt) (do-decl (caddr opt))))
  559.         (when rest (do-decl rest))
  560.         (dolist** (kwd keywords)
  561.                   (do-decl (cadr kwd))
  562.                   (when (cadddr kwd) (do-decl (cadddr kwd))))
  563.         )
  564.   ;;; Check arguments.
  565.   (when (and (or *safe-compile* *compiler-check-args*) requireds)
  566.         (when requireds
  567.               (wt-nl "if(vs_top-vs_base<" (length requireds)
  568.                      ") too_few_arguments();")))
  569.  
  570.   ;;; Allocate the parameters.
  571.   (dolist** (var requireds) (setf (var-ref var) (vs-push)))
  572.   (dolist** (opt optionals)
  573.     (setf (var-ref (car opt)) (vs-push)))
  574.   (when rest (setf (var-ref rest) (vs-push)))
  575.   (dolist** (kwd keywords)
  576.     (setf (var-ref (cadr kwd)) (vs-push)))
  577.   (dolist** (kwd keywords)
  578.     (setf (var-ref (cadddr kwd)) (vs-push)))
  579.   (dolist** (opt optionals)
  580.     (when (caddr opt) (setf (var-ref (caddr opt)) (vs-push))))
  581.  
  582.   ;;; Assign rest and keyword parameters first.
  583.   ;;; parse_key does not change vs_base and vs_top.
  584.  
  585.   (wt-nl "parse_key(vs_base")
  586.   (when (or requireds optionals)
  587.         (wt "+" (+ (length requireds) (length optionals))))
  588.   (if rest (wt ",TRUE,") (wt ",FALSE,"))
  589.   (if allow-other-keys (wt "TRUE,") (wt "FALSE,"))
  590.   (wt (length keywords))
  591.   (dolist** (kwd keywords) (wt ",VV[" (add-symbol (car kwd)) "]"))
  592.   (wt ");")
  593.  
  594.   ;;; Bind required parameters.
  595.   (dolist** (var requireds) (c2bind var))
  596.  
  597.   ;;; Bind optional parameters as long as there remain arguments.
  598.   ;;; The compile-time binding is discarded because they are bound again.
  599.  
  600.   (when optionals
  601.  
  602.         (when requireds (wt-nl "vs_base += " (length requireds) ";"))
  603.  
  604.         (let ((*clink* *clink*)
  605.               (*unwind-exit* *unwind-exit*)
  606.               (*ccb-vs* *ccb-vs*))
  607.              (do ((opts optionals (cdr opts)))
  608.                  ((endp opts))
  609.                  (declare (object opts))
  610.                  (push (next-label) labels)
  611.                  (wt-nl "if(vs_base>=vs_top){vs_top=sup;")
  612.                  (wt-go (car labels)) (wt "}")
  613.                  (c2bind (caar opts))
  614.                  (when (caddar opts) (c2bind-loc (caddar opts) t))
  615.                  (when (cdr opts) (wt-nl "vs_base++;"))))
  616.  
  617.         (setq labels (reverse labels))
  618.         )
  619.  
  620.   (wt-nl "vs_top=sup;")
  621.  
  622.   (when optionals
  623.         (let ((label (next-label)))
  624.              (wt-go label)
  625.  
  626.              ;;; Bind unspecified optional parameters.
  627.  
  628.              (dolist** (opt optionals)
  629.                        (wt-label (car labels))
  630.                        (pop labels)
  631.                        (c2bind-init (car opt) (cadr opt))
  632.                        (when (caddr opt) (c2bind-loc (caddr opt) nil)))
  633.  
  634.              (wt-label label)
  635.              ))
  636.  
  637.   (when rest (c2bind rest))
  638.  
  639.   ;;; Bind keywords.
  640.  
  641.   (dolist** (kwd keywords)
  642.     (cond ((and (eq (caaddr kwd) 'LOCATION) (null (caddr (caddr kwd))))
  643.            ;;; Cnil has been set if keyword parameter is not supplied.
  644.            (c2bind (cadr kwd)))
  645.           (t
  646.            (wt-nl "if(") (wt-vs (var-ref (cadddr kwd))) (wt "==Cnil){")
  647.            (let ((*clink* *clink*)
  648.                  (*unwind-exit* *unwind-exit*)
  649.                  (*ccb-vs* *ccb-vs*))
  650.                 (c2bind-init (cadr kwd) (caddr kwd)))
  651.            (wt-nl "}else{")
  652.            (c2bind (cadr kwd))
  653.            (wt "}")))
  654.     (unless (eq (var-kind (cadddr kwd)) 'DUMMY) (c2bind (cadddr kwd))))
  655.  
  656.   ;;; Now the parameters are ready, after all!
  657.   (c2expr body)
  658.  
  659.   (when block-p (wt-nl "}"))
  660.   )
  661.  
  662. (defun need-to-set-vs-pointers (lambda-list)
  663.                 ;;; On entry to in-line lambda expression,
  664.                 ;;; vs_base and vs_top must be set iff,
  665.    (or *safe-compile*
  666.        *compiler-check-args*
  667.        (nth 1 lambda-list)    ;;; optional,
  668.        (nth 2 lambda-list)    ;;; rest, or
  669.        (nth 3 lambda-list)    ;;; key-flag.
  670.        ))
  671.  
  672.  
  673. ;;; The DEFMACRO compiler.
  674.  
  675. ;;; valid lambda-list to DEFMACRO is:
  676. ;;;
  677. ;;;    ( [ &whole sym ]
  678. ;;;      [ &environment sym ]
  679. ;;;      { v }*
  680. ;;;      [ &optional { sym | ( v [ init [ v ] ] ) }* ]
  681. ;;;      {  [ { &rest | &body } v ]
  682. ;;;         [ &key { sym | ( { sym | ( key v ) } [ init [ v ]] ) }*
  683. ;;;            [ &allow-other-keys ]]
  684. ;;;         [ &aux { sym | ( v [ init ] ) }* ]
  685. ;;;      |  . sym }
  686. ;;;     )
  687. ;;;
  688. ;;; where v is short for { defmacro-lambda-list | sym }.
  689. ;;; Defamcro-lambda-list is defined as:
  690. ;;;
  691. ;;;    ( { v }*
  692. ;;;      [ &optional { sym | ( v [ init [ v ] ] ) }* ]
  693. ;;;      {  [ { &rest | &body } v ]
  694. ;;;         [ &key { sym | ( { sym | ( key v ) } [ init [ v ]] ) }*
  695. ;;;            [ &allow-other-keys ]]
  696. ;;;         [ &aux { sym | ( v [ init ] ) }* ]
  697. ;;;      |  . sym }
  698. ;;;     )
  699.  
  700. (defvar *vnames*)
  701. (defvar *dm-info*)
  702. (defvar *dm-vars*)
  703.  
  704.  
  705. (defun c1dm (macro-name vl body
  706.                         &aux (*vs* *vs*) (whole nil) (env nil)
  707.     (setjmps *setjmps*)
  708.                         (*vnames* nil) (*dm-info* (make-info)) (*dm-vars* nil)
  709.                         doc ss is ts other-decls ppn)
  710.  
  711.   (multiple-value-setq (body ss ts is other-decls doc) (c1body body t))
  712.   (setq body (list (list* 'block macro-name body)))
  713.  
  714.   (c1add-globals ss)
  715.  
  716.   (when (and (listp vl) (eq (car vl) '&whole))
  717.         (push (cadr vl) *vnames*)
  718.         (setq whole (c1make-var (cadr vl) ss is ts))
  719.         (push whole *dm-vars*)
  720.         (push whole *vars*)
  721.         (setq vl (cddr vl))
  722.         )
  723.   (let ((env-m (and (listp vl) (do ((tail vl (cdr tail)))
  724.                    ((not (consp tail)) nil)
  725.                  (when (eq '&environment (car tail))
  726.                    (return tail))))))
  727.     (when env-m
  728.       (push (cadr env-m) *vnames*)
  729.       (setq env (c1make-var (cadr env-m) ss is ts))
  730.       (push env *dm-vars*)
  731.       (push env *vars*)
  732.       (setq vl (append (ldiff vl env-m) (cddr env-m)))))
  733.   (multiple-value-setq (vl ppn) (c1dm-vl vl ss is ts))
  734.  
  735.   (check-vdecl *vnames* ts is)
  736.   (setq body (c1decl-body other-decls body))
  737.   (add-info *dm-info* (cadr body))
  738.    (cond ((eql setjmps *setjmps*))
  739.          (t(setf (info-volatile *dm-info*) t)
  740.            (setf (get macro-name 'contains-setjmp) t)
  741.                ))
  742.   (dolist* (v *dm-vars*) (check-vref v))
  743.   (list doc ppn whole env vl body *dm-info*)
  744.   )
  745.  
  746. (defun c1dm-vl (vl ss is ts)
  747.   (do ((optionalp nil) (restp nil) (keyp nil) (allow-other-keys-p nil)
  748.        (auxp nil)
  749.        (requireds nil) (optionals nil) (rest nil) (key-flag nil)
  750.        (keywords nil) (auxs nil) (allow-other-keys nil)
  751.        (n 0) (ppn nil)
  752.        )
  753.     ((not (consp vl))
  754.      (when vl
  755.            (when restp (dm-bad-key '&rest))
  756.            (setq rest (c1dm-v vl ss is ts)))
  757.      (values (list (reverse requireds) (reverse optionals) rest key-flag
  758.                    (reverse keywords) allow-other-keys (reverse auxs))
  759.              ppn)
  760.      )
  761.     (let ((v (car vl)))
  762.          (declare (object v))
  763.       (cond
  764.        ((eq v '&optional)
  765.         (when optionalp (dm-bad-key '&optional))
  766.         (setq optionalp t)
  767.         (pop vl))
  768.        ((or (eq v '&rest) (eq v '&body))
  769.         (when restp (dm-bad-key v))
  770.         (setq rest (c1dm-v (cadr vl) ss is ts))
  771.         (setq restp t optionalp t)
  772.         (setq vl (cddr vl))
  773.         (when (eq v '&body) (setq ppn n)))
  774.        ((eq v '&key)
  775.         (when keyp (dm-bad-key '&key))
  776.         (setq keyp t restp t optionalp t key-flag t)
  777.         (pop vl))
  778.        ((eq v '&allow-other-keys)
  779.         (when (or (not keyp) allow-other-keys-p)
  780.               (dm-bad-key '&allow-other-keys))
  781.         (setq allow-other-keys-p t allow-other-keys t)
  782.         (pop vl))
  783.        ((eq v '&aux)
  784.         (when auxp (dm-bad-key '&aux))
  785.         (setq auxp t allow-other-keys-p t keyp t restp t optionalp t)
  786.         (pop vl))
  787.        (auxp
  788.         (let (x init)
  789.              (cond ((symbolp v) (setq x v init (c1nil)))
  790.                    (t (setq x (car v))
  791.                       (if (endp (cdr v))
  792.                           (setq init (c1nil))
  793.                           (setq init (c1expr* (cadr v) *dm-info*)))))
  794.              (push (list (c1dm-v x ss is ts) init) auxs))
  795.         (pop vl))
  796.        (keyp
  797.         (let (x k init (sv nil))
  798.              (cond ((symbolp v)
  799.                     (setq x v k (intern (string v) 'keyword) init (c1nil)))
  800.                    (t (if (symbolp (car v))
  801.                           (setq x (car v)
  802.                                 k (intern (string (car v)) 'keyword))
  803.                           (setq x (cadar v) k (caar v)))
  804.                       (cond ((endp (cdr v)) (setq init (c1nil)))
  805.                             (t (setq init (c1expr* (cadr v) *dm-info*))
  806.                                (unless (endp (cddr v))
  807.                                        (setq sv (caddr v)))))))
  808.              (push (list k (c1dm-v x ss is ts) init
  809.                          (if sv (c1dm-v sv ss is ts) nil))
  810.                    keywords)
  811.              )
  812.         (pop vl))
  813.        (optionalp
  814.         (let (x init (sv nil))
  815.              (cond ((symbolp v) (setq x v init (c1nil)))
  816.                    (t (setq x (car v))
  817.                       (cond ((endp (cdr v))
  818.                              (setq init (c1nil)))
  819.                             (t (setq init (c1expr* (cadr v) *dm-info*))
  820.                                (unless (endp (cddr v))
  821.                                        (setq sv (caddr v)))))))
  822.              (push (list (c1dm-v x ss is ts) init
  823.                          (if sv (c1dm-v sv ss is ts) nil))
  824.                    optionals))
  825.         (pop vl)
  826.         (incf n)
  827.         )
  828.        (t (push (c1dm-v v ss is ts) requireds)
  829.           (pop vl)
  830.           (incf n))
  831.        )))
  832.   )
  833.  
  834. (defun c1dm-v (v ss is ts)
  835.        (cond ((symbolp v)
  836.               (push v *vnames*)
  837.               (setq v (c1make-var v ss is ts))
  838.               (push v *vars*)
  839.               (push v *dm-vars*)
  840.               v)
  841.              (t (c1dm-vl v ss is ts))))
  842.  
  843. (defun c1dm-bad-key (key)
  844.        (cmperr "Defmacro-lambda-list contains illegal use of ~s." key))
  845.  
  846. (defun c2dm (whole env vl body
  847.                    &aux (cvar (next-cvar)))
  848.   (when (or *safe-compile* *compiler-check-args*)
  849.     (wt-nl "check_arg(2);"))
  850.   (cond (whole (setf (var-ref whole) (vs-push)))
  851.         (t (vs-push)))
  852.   (cond (env (setf (var-ref env) (vs-push)))
  853.         (t (vs-push)))
  854.   (c2dm-reserve-vl vl)
  855.   (wt-nl "vs_top=sup;")
  856.   (when whole (c2bind whole))
  857.   (when env (c2bind env))
  858.   (wt-nl "{object V" cvar "=base[0]->c.c_cdr;")
  859.   (c2dm-bind-vl vl cvar)
  860.   (wt "}")
  861.   (c2expr body)
  862.   )
  863.  
  864. (defun c2dm-reserve-vl (vl)
  865.   (dolist** (var (car vl)) (c2dm-reserve-v var))
  866.   (dolist** (opt (cadr vl))
  867.             (c2dm-reserve-v (car opt))
  868.             (when (caddr opt) (c2dm-reserve-v (caddr opt))))
  869.   (when (caddr vl) (c2dm-reserve-v (caddr vl)))
  870.   (dolist** (kwd (car (cddddr vl)))
  871.             (c2dm-reserve-v (cadr kwd))
  872.             (when (cadddr kwd) (c2dm-reserve-v (cadddr kwd))))
  873.   (dolist** (aux (caddr (cddddr vl)))
  874.             (c2dm-reserve-v (car aux)))
  875.   )
  876.  
  877. (defun c2dm-reserve-v (v)
  878.   (if (consp v)
  879.       (c2dm-reserve-vl v)
  880.       (setf (var-ref v) (vs-push))))
  881.  
  882. (defun c2dm-bind-vl (vl cvar
  883.                         &aux
  884.                         (requireds (car vl)) (optionals (cadr vl))
  885.                         (rest (caddr vl)) (key-flag (cadddr vl))
  886.                         (keywords (car (cddddr vl)))
  887.                         (allow-other-keys (cadr (cddddr vl)))
  888.                         (auxs (caddr (cddddr vl)))
  889.                         )
  890.   (declare (object requireds optionals rest key-flag keywords allow-other-keys
  891.                    auxs))
  892.   (do ((reqs requireds (cdr reqs)))
  893.       ((endp reqs))
  894.       (declare (object reqs))
  895.       (when (or *safe-compile* *compiler-check-args*)
  896.             (wt-nl "if(endp(V" cvar "))invalid_macro_call();"))
  897.       (c2dm-bind-loc (car reqs) `(car ,cvar))
  898.       (when (or (cdr reqs) optionals rest key-flag
  899.                 *safe-compile* *compiler-check-args*)
  900.             (wt-nl "V" cvar "=V" cvar "->c.c_cdr;")))
  901.   (do ((opts optionals (cdr opts)))
  902.       ((endp opts))
  903.       (declare (object opts))
  904.       (let ((opt (car opts)))
  905.            (declare (object opt))
  906.            (wt-nl "if(endp(V" cvar ")){")
  907.            (let ((*clink* *clink*)
  908.                  (*unwind-exit* *unwind-exit*)
  909.                  (*ccb-vs* *ccb-vs*))
  910.                 (c2dm-bind-init (car opt) (cadr opt))
  911.                 (when (caddr opt) (c2dm-bind-loc (caddr opt) nil))
  912.                 )
  913.            (wt-nl "} else {")
  914.            (c2dm-bind-loc (car opt) `(car ,cvar))
  915.            (when (caddr opt) (c2dm-bind-loc (caddr opt) t)))
  916.       (when (or (cdr opts) rest key-flag
  917.                 *safe-compile* *compiler-check-args*)
  918.             (wt-nl "V" cvar "=V" cvar "->c.c_cdr;"))
  919.       (wt "}"))
  920.   (when rest (c2dm-bind-loc rest `(cvar ,cvar)))
  921.   (dolist** (kwd keywords)
  922.     (let ((cvar1 (next-cvar)))
  923.          (wt-nl
  924.           "{object V" cvar1 "=getf(V" cvar ",VV[" (add-symbol (car kwd))
  925.           "],OBJNULL);")
  926.          (wt-nl "if(V" cvar1 "==OBJNULL){")
  927.          (let ((*clink* *clink*)
  928.                (*unwind-exit* *unwind-exit*)
  929.                (*ccb-vs* *ccb-vs*))
  930.               (c2dm-bind-init (cadr kwd) (caddr kwd))
  931.               (when (cadddr kwd) (c2dm-bind-loc (cadddr kwd) nil))
  932.               (wt-nl "} else {"))
  933.          (c2dm-bind-loc (cadr kwd) `(cvar ,cvar1))
  934.          (when (cadddr kwd) (c2dm-bind-loc (cadddr kwd) t))
  935.          (wt "}}")))
  936.   (when (and (or *safe-compile* *compiler-check-args*)
  937.              (null rest)
  938.              (null key-flag))
  939.         (wt-nl "if(!endp(V" cvar "))invalid_macro_call();"))
  940.   (when (and (or *safe-compile* *compiler-check-args*)
  941.              key-flag
  942.              (not allow-other-keys))
  943.         (wt-nl "check_other_key(V" cvar "," (length keywords))
  944.         (dolist** (kwd keywords)
  945.                   (wt ",VV[" (add-symbol (car kwd)) "]"))
  946.         (wt ");"))
  947.   (dolist** (aux auxs)
  948.             (c2dm-bind-init (car aux) (cadr aux)))
  949.   )
  950.  
  951. (defun c2dm-bind-loc (v loc)
  952.   (if (consp v)
  953.       (let ((cvar (next-cvar)))
  954.            (wt-nl "{object V" cvar "= " loc ";")
  955.            (c2dm-bind-vl v cvar)
  956.            (wt "}"))
  957.       (c2bind-loc v loc)))
  958.  
  959. (defun c2dm-bind-init (v init)
  960.   (if (consp v)
  961.       (let* ((*vs* *vs*) (*inline-blocks* 0)
  962.              (cvar (next-cvar))
  963.              (loc (car (inline-args (list init) '(t)))))
  964.             (wt-nl "{object V" cvar "= " loc ";")
  965.             (c2dm-bind-vl v cvar)
  966.             (wt "}")
  967.             (close-inline-blocks))
  968.       (c2bind-init v init)))
  969.  
  970.  
  971.  
  972.