[ ... continued ]
It was a simple experiment. Define a restricted package and interpret .asd files with a restricted read-eval loop.
(defpackage :asdf-prototype (:use ) (:documentation "A constrained package to use for loading asdf system prototypes.") (:export :intern) (:import-from :asdf :system :file :module :cl-source-file :defsystem :compile-op :load-op :test-op) (:import-from :common-lisp :*load-truename* :symbol-name :with-open-file :merge-pathnames :make-pathname :read :describe :string))
(defun asdf-prototype::funcall (&rest args) "Serves as a place-jolder in order to define systems, but should never be called." (error "attempted funcall: ~s." args))
(defun asdf-prototype::intern (string &optional package) (declare (ignore package)) (intern string :asdf-prototype))
(defun load-system-prototype (pathname) (with-open-file (input pathname :direction :input) (with-standard-io-syntax (let ((*package* (or (find-package :asdf-prototype) (error "No prototype package."))) ;;(*read-eval* nil) (*print-readably* nil) (form nil) (definition nil) (*load-truename* (truename pathname)) (system nil) (error nil) (repository-url-properties nil)) (loop (setf form (read input nil input)) (when (eq form input) (return)) (when (consp form) (when (eq (first form) 'asdf:defsystem) (setf definition form) (multiple-value-setq (system error) (ignore-errors (eval definition))) (when error (warn "Loading system definition causes an error: ~s,~%~a" pathname error)) (when system (setf (find-system-prototype (asdf:component- name system)) system) (setf (definition-form system) definition) (setf (definition-pathname system) pathname) (when (setf repository-url-properties (ignore-errors (load-repository-url (make- pathname :name "repository" :t ype "url" :d efaults (definition-metadata-directory system))))) (destructuring-bind (&key name url type &allow- other-keys) repository-url-properties (when (and (string-equal name (asdf:component-name system)) url type) (setf (system-repository-url system) url (system-repository-type system) type))))))))
(values system error)))))
Just in order to see how much it would cover, *read-eval* is left as t. Better would be to disable it. It included neutered intern and funcall operators to facilitated loading. They indicate the presence of idioms which should be eliminated.
Mostly it was uneventful. Which is nice. Of the 91 projects present in the clbuild wnpp-projects file, 84 system definitions loaded. Because some systems include numerous nominally indistinguishable .asd files, the ratio is not conclusive, but it is still heartening. I observed a bit more than a dozen failures. The most prevalent failure was reference to a specialized component class. None of which would be necessary if it were possible to declare extensions. Of the specialized component implementations, local-cl-source-file and system-with-readtable indicate capabilities which _really_ ought to be integrated into the asdf core: component- specific feature and declaration assertions.
Beyond those use-cases one enters the realm a project like elephant.
Under these circumstances, it would make asdf much more suitable to the purpose for which it is intended if it were changed as follows:
- find-system should be changed. rather than call load and then check whether there was any beneficial effect, it should use its own read- eval loop to interpret .asd files. this loop should - establish a restricted package - disable read evaluation - interpret two forms - asdf:defsystem; in which module and file components only are supported. specialization is declared with the :class attribute - cl:use-package; in which a reference to an unknown package leads to an attempt to load a system of that name. - support a mode which permits :class specifications for unknown classes and initialization arguments other than those from the core classes
Such .asd files would also be loadable as source if separate preparations were made to incorporate the extension modules.
?
--- [0] : http://common-lisp.net/project/elephant/darcs/elephant/ elephant.asd [2] : http://common-lisp.net/project/clbuild/ [ clbuild.lisp and the clbuild shell script are phenomenal for the things they accomplish despite that they really should not need to.] [1] : http://common-lisp.net/project/asdf/manual.html