Skip to content
dependencies-interpreter.lisp 6.07 KiB
Newer Older
#+xcvb (module (:depends-on ("normalize-dependency" "traversal")))
(in-package :xcvb)

(defgeneric build-command-for-lisp (env name))
(defgeneric build-command-for-fasl (env name))
(defgeneric build-command-for-cfasl (env name))
(defgeneric build-command-for-lisp-object (env name)) ;; XXX or should have link-commands instead ?
(defgeneric build-command-for-asdf (env name))
(defgeneric build-command-for-require (env name))
(defgeneric build-command-for-static-library (env name))
(defgeneric build-command-for-dynamic-library (env name))
(defgeneric build-command-for-source (env name &key in))
(defgeneric build-command-for-build (env name))
(defgeneric build-command-for-compile-build (env name))
(defgeneric build-command-for-build-named (env name))
(defgeneric build-command-for-when (env expression &rest dependencies))
(defgeneric build-command-for-cond (env &rest cond-expressions))
(defgeneric simple-build-command-for-grain (env command grain))
(define-simple-dispatcher build-command-for #'build-command-for-atom :generic t)
Francois-Rene Rideau's avatar
Francois-Rene Rideau committed
  (build-command-for-dispatcher env (tweak-dependency env spec)))

(defun build-command-for* (env specs)
  (dolist (spec specs)
    (build-command-for env spec)))
(defun build-command-for-atom (env spec)
  (declare (ignore env))
  (error "Cannot produce a build command for the invalid dependency ~S" spec))
(define-build-command-for :lisp (env name)
  (simple-build-command-for
Francois-Rene Rideau's avatar
Francois-Rene Rideau committed
   env `(:load-file ,name) `(:lisp ,name)))
(define-build-command-for :fasl (env name)
  (simple-build-command-for
   env `(:load-file (:fasl ,name)) `(:fasl ,name)))
(define-build-command-for :cfasl (env name)
  (simple-build-command-for
   env `(:load-file (:cfasl ,name)) `(:cfasl ,name)))
(define-build-command-for :lisp-object (env name)
  (simple-build-command-for
   env `(:load-file (:lisp-object ,name)) `(:lisp-object ,name)))
(define-build-command-for :dynamic-library (env name)
  (simple-build-command-for
   env `(:load-file (:dynamic-library ,name)) `(:dynamic-library ,name)))
(define-build-command-for :static-library (env name)
  (simple-build-command-for
   env `(:load-file (:static-library ,name)) `(:static-library ,name)))
(define-build-command-for :asdf (env name)
  (build-command-for env `(:build "/asdf"))
  (simple-build-command-for env `(:load-asdf ,name) `(:asdf ,name)))
(define-build-command-for :require (env name)
  (simple-build-command-for env `(:require ,name) `(:require ,name)))
(defun simple-build-command-for (env command fullname)
  (call-with-dependency-grain
   env fullname
   (lambda (grain) (simple-build-command-for-grain env command grain))))

(defmethod simple-build-command-for-grain (env command grain)
  (with-dependency-loading (env grain)
    (build-commands-for-build-dependencies env grain)
    (build-commands-for-load-dependencies env grain)
    (issue-build-command env command)))
(define-build-command-for :source (env name &key in)
  ;; Suffices to know data file exists.  No need to issue load command.
  (call-with-dependency-grain
   (lambda (grain)
     (with-dependency-loading (env grain)
       (values)))))
(defun call-with-dependency-grain (environment dep fun)
  (let* ((grain (graph-for environment dep)))
    (with-dependency (:type type) dep
      (unless (typep grain type)
        (error "Expected a grain of type ~S for ~S, instead got ~S"
               type dep grain))
      (funcall fun grain))))
(define-build-command-for :build (env name)
  (let ((build (registered-build name :ensure-build t)))
    (if (target-ecl-p)
	(build-command-for env `(:dynamic-library ,name))
	(with-dependency-loading (env build)
	  (build-commands-for-load-dependencies env build)))))
(define-build-command-for :compile-build (env name)
  (let ((build (registered-build name :ensure-build t)))
    (with-dependency-loading (env build)
      (build-commands-for-build-dependencies env build)
      (build-commands-for-compile-dependencies env build))))
(defun build-commands-for-load-dependencies (env grain)
  (build-command-for* env (load-dependencies grain)))
(defun build-commands-for-compile-dependencies (env grain)
  (build-command-for* env (compile-dependencies grain)))
(defun build-commands-for-cload-dependencies (env grain)
  (build-command-for* env (cload-dependencies grain)))
(defun build-commands-for-build-dependencies (env grain)
  (build-command-for* env (build-dependencies grain)))
(define-build-command-for :when (env expression &rest dependencies)
    (build-command-for* env dependencies)))
(define-build-command-for :cond (env &rest cond-expressions)
  (loop :for cond-expression :in cond-expressions
        :when (evaluate-condition env (car cond-expression))
        :do (return (build-command-for* env (cdr cond-expression)))))

(define-simple-dispatcher evaluate-condition #'evaluate-condition-atom)

(defun evaluate-condition (env expression)
  (evaluate-condition-dispatcher env expression))

(defun evaluate-condition-atom (env atom)
  (declare (ignore env))
  (if (typep atom 'boolean)
    atom
    (error "Invalid condition ~S" atom)))

(define-evaluate-condition :featurep (env feature-expression)
  (evaluate-featurep env feature-expression))

(defun evaluate-featurep (env feature-expression)
  (evaluate-featurep-dispatcher env feature-expression))

(define-simple-dispatcher evaluate-featurep #'evaluate-featurep-atom)

(defun evaluate-featurep-atom (env atom)
  (declare (ignore env))
  (unless (keywordp atom)
    (error "Invalid feature ~S" atom))

(define-evaluate-featurep :and (env &rest feature-expressions)
  (loop :for feature-expression :in feature-expressions
        :always (evaluate-featurep env feature-expression)))

(define-evaluate-featurep :or (env &rest feature-expressions)
  (loop :for feature-expression :in feature-expressions
        :thereis (evaluate-featurep env feature-expression)))

(define-evaluate-featurep :not (env feature-expression)
  (not (evaluate-featurep env feature-expression)))