<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>[ ... continued ]</div><div><br></div><div><div>It was a simple experiment. Define a restricted package and interpret .asd files with a restricted read-eval loop.</div><div><br></div><div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; ">(defpackage :asdf-prototype</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (:use )</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (:documentation "A constrained package to use for loading asdf system prototypes.")</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (:export :intern)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (:import-from :asdf</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :system</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :file</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :module</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :cl-source-file</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :defsystem</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :compile-op</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :load-op</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :test-op)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (:import-from :common-lisp</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :*load-truename*</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :symbol-name</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :with-open-file</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :merge-pathnames</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :make-pathname</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :read</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :describe</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :string))</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 9px/normal Monaco; min-height: 12px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 9px/normal Monaco; min-height: 12px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; ">(defun asdf-prototype::funcall (&rest args)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> "Serves as a place-jolder in order to define systems, but should never be called."</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (error "attempted funcall: ~s." args))</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 9px/normal Monaco; min-height: 12px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; ">(defun asdf-prototype::intern (string &optional package)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (declare (ignore package))</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (intern string :asdf-prototype))</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 9px/normal Monaco; min-height: 12px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 9px/normal Monaco; min-height: 12px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span class="Apple-style-span" style="font-size: 9px; ">(defun load-system-prototype (pathname)</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (with-open-file (input pathname :direction :input)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (with-standard-io-syntax</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (let ((*package* (or (find-package :asdf-prototype) (error "No prototype package.")))</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> ;;(*read-eval* nil)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (*print-readably* nil)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (form nil)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (definition nil)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (*load-truename* (truename pathname))</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (system nil)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (error nil)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (repository-url-properties nil))</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (loop (setf form (read input nil input))</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (when (eq form input) (return))</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (when (consp form)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (when (eq (first form) 'asdf:defsystem)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (setf definition form)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (multiple-value-setq (system error)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (ignore-errors (eval definition)))</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (when error</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (warn "Loading system definition causes an error: ~s,~%~a"</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> pathname error))</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (when system</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (setf (find-system-prototype (asdf:component-name system)) system)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (setf (definition-form system) definition)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (setf (definition-pathname system) pathname)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (when (setf repository-url-properties</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (ignore-errors</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (load-repository-url (make-pathname :name "repository"</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :type "url"</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> :defaults (definition-metadata-directory system)))))</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (destructuring-bind (&key name url type &allow-other-keys) repository-url-properties</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (when (and (string-equal name (asdf:component-name system)) url type)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (setf (system-repository-url system) url</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (system-repository-type system) type))))))))</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 9px/normal Monaco; min-height: 12px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Monaco" size="1" style="font: normal normal normal 9px/normal Monaco; "> (values system error)))))</font></div><div><font class="Apple-style-span" size="1"><span class="Apple-style-span" style="font-size: 9px; "><br></span></font></div></div><div><br></div><div>Just in order to see how much it would cover, *read-eval* is left as t. Better would be to disable it.</div><div>It included neutered intern and funcall operators to facilitated loading. They indicate the presence of idioms which should be eliminated.</div><div><br></div><div>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.</div><div><br></div><div>Beyond those use-cases one enters the realm a project like elephant.</div></div><div><br></div><div>Under these circumstances, it would make asdf much more suitable to the purpose for which it is intended if it were changed as follows:</div><div><br></div><div>- 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</div><div> - establish a restricted package</div><div> - disable read evaluation</div><div> - interpret two forms</div><div> - asdf:defsystem; in which module and file components only are supported. specialization is declared with the :class attribute</div><div> - cl:use-package; in which a reference to an unknown package leads to an attempt to load a system of that name.</div><div> - support a mode which permits :class specifications for unknown classes and initialization arguments other than those from the core classes</div><div><br></div><div>Such .asd files would also be loadable as source if separate preparations were made to incorporate the extension modules.</div><div><br></div><div>?</div><div><br></div><div>---</div><div> [0] : <a href="http://common-lisp.net/project/elephant/darcs/elephant/elephant.asd">http://common-lisp.net/project/elephant/darcs/elephant/elephant.asd</a></div><div> [2] : <a href="http://common-lisp.net/project/clbuild/">http://common-lisp.net/project/clbuild/</a> [ clbuild.lisp and the clbuild shell script are phenomenal for the things they accomplish despite that they really should not need to.]</div> [1] : <a href="http://common-lisp.net/project/asdf/manual.html">http://common-lisp.net/project/asdf/manual.html</a></body></html>