X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Fmodule.lisp;h=fe3b7652987606dce2b307ea25e234eb5bbf7326;hb=7dfa54273d2ebc6c2be9a39ab5cd6df639d340c9;hp=83f129d716fdda520fffbe5239c6382a7217318b;hpb=9f8b254664d2864ae524c3a12c912437accfdb20;p=sbcl.git diff --git a/src/code/module.lisp b/src/code/module.lisp index 83f129d..fe3b765 100644 --- a/src/code/module.lisp +++ b/src/code/module.lisp @@ -22,9 +22,8 @@ "This is a list of module names that have been loaded into Lisp so far. It is used by PROVIDE and REQUIRE.") -(defvar sb!ext::*MODULE-PROVIDER-FUNCTIONS* '(module-provide-contrib) - "See function documentation for REQUIRE") - +(defvar *module-provider-functions* (list 'module-provide-contrib) + "See function documentation for REQUIRE.") ;;;; PROVIDE and REQUIRE @@ -35,43 +34,70 @@ (pushnew (string module-name) *modules* :test #'string=) t) +(defvar *requiring* nil) + +(defun require-error (control &rest arguments) + (error 'extension-failure + :format-control control + :format-arguments arguments + :references + (list + '(:sbcl :variable *module-provider-functions*) + '(:sbcl :function require)))) + (defun require (module-name &optional pathnames) #!+sb-doc "Loads a module, unless it already has been loaded. PATHNAMES, if supplied, is a designator for a list of pathnames to be loaded if the module needs to be. If PATHNAMES is not supplied, functions from the list *MODULE-PROVIDER-FUNCTIONS* are called in order with MODULE-NAME - as an argument, until one of them returns non-NIL." - (let ((saved-modules (copy-list *modules*))) - (unless (member (string module-name) *modules* :test #'string=) - (cond (pathnames - (unless (listp pathnames) (setf pathnames (list pathnames))) - ;; ambiguity in standard: should we try all pathnames in the - ;; list, or should we stop as soon as one of them calls PROVIDE? - (dolist (ele pathnames t) - (load ele)) - ;; should we do this? Probably can't hurt, while we're - ;; taking the above view of "load everything"... though - ;; maybe having REQUIRE directly call PROVIDE is - ;; aesthetically suboptimal. - (provide module-name)) - (t - (unless (some (lambda (p) (funcall p module-name)) - sb!ext::*module-provider-functions*) - (error "Don't know how to load ~A" module-name))))) - (set-difference *modules* saved-modules))) + as an argument, until one of them returns non-NIL. User code is + responsible for calling PROVIDE to indicate a successful load of the + module." + (let ((name (string module-name))) + (when (member name *requiring* :test #'string=) + (require-error "~@" 'require module-name)) + (let ((saved-modules (copy-list *modules*)) + (*requiring* (cons name *requiring*))) + (unless (member name *modules* :test #'string=) + (cond (pathnames + (unless (listp pathnames) (setf pathnames (list pathnames))) + ;; ambiguity in standard: should we try all pathnames in the + ;; list, or should we stop as soon as one of them calls PROVIDE? + (dolist (ele pathnames t) + (load ele))) + (t + (unless (some (lambda (p) (funcall p module-name)) + *module-provider-functions*) + (require-error "Don't know how to ~S ~A." + 'require module-name))))) + (set-difference *modules* saved-modules)))) + ;;;; miscellany (defun module-provide-contrib (name) "Stringify and downcase NAME, then attempt to load the file $SBCL_HOME/name/name" - (let ((filesys-name (string-downcase (string name)))) - (load - (merge-pathnames (make-pathname :directory (list :relative filesys-name) - :name filesys-name) - (truename (posix-getenv "SBCL_HOME"))))) - (provide name) - t) - - + (let* ((filesys-name (string-downcase (string name))) + (unadorned-path + (merge-pathnames + (make-pathname :directory (list :relative filesys-name) + :name filesys-name) + (truename (or (sbcl-homedir-pathname) + (return-from module-provide-contrib nil))))) + (fasl-path (merge-pathnames + (make-pathname :type *fasl-file-type*) + unadorned-path)) + (lisp-path (merge-pathnames (make-pathname :type "lisp") + unadorned-path))) + ;; KLUDGE: there's a race condition here; the file we probe could + ;; be removed by the time we get round to trying to load it. + ;; Maybe factor out the logic in the LOAD guesser as to which file + ;; was meant, so that we can use it here on open streams instead? + (when (or (probe-file unadorned-path) + (probe-file fasl-path) + (probe-file lisp-path)) + (load unadorned-path) + t)))