(let ((existing (gethash truename *module-map*)))
(cond ((null existing))
((eq (module-state existing) t)
+ (when (plusp (module-errors existing))
+ (error "Module `~A' contains errors" name))
(return-from build-module existing))
(t
- (error "Module ~A already being imported at ~A"
+ (error "Module `~A' already being imported at ~A"
name (module-state existing))))))
;; Construct the new module.
(progv
(mapcar #'car *module-bindings-alist*)
(module-variables module)
- (unwind-protect (funcall thunk)
- (setf (module-variables module)
- (mapcar (compose #'car #'symbol-value)
- *module-bindings-alist*)))))
+ (handler-bind ((error (lambda (cond)
+ (declare (ignore cond))
+ (incf (slot-value module 'errors))
+ :decline)))
+ (unwind-protect (funcall thunk)
+ (setf (module-variables module)
+ (mapcar (compose #'car #'symbol-value)
+ *module-bindings-alist*))))))
(defun call-with-temporary-module (thunk)
"Invoke THUNK in the context of a temporary module, returning its values.
;;;--------------------------------------------------------------------------
;;; Code fragments.
-(export '(c-fragment c-fragment-text))
-(defclass c-fragment ()
- ((location :initarg :location :type file-location :reader file-location)
- (text :initarg :text :type string :reader c-fragment-text))
- (:documentation
- "Represents a fragment of C code to be written to an output file.
-
- A C fragment is aware of its original location, and will bear proper #line
- markers when written out."))
-
(defun output-c-excursion (stream location func)
"Invoke FUNC surrounding it by writing #line markers to STREAM.
(prin1 (subseq text 0 37) stream)
(write-string "..." stream))))
(output-c-excursion stream location
- (lambda (stream) (write-string text stream))))))
+ (lambda (stream)
+ (awhen (file-location-column location)
+ (dotimes (i it) (write-char #\space stream)))
+ (write-string text stream))))))
(defmethod make-load-form ((fragment c-fragment) &optional environment)
(make-load-form-saving-slots fragment :environment environment))
See `find-file' for the grubby details.")
(export 'find-file)
-(defun find-file (scanner name what thunk)
+(defun find-file (home name what thunk)
"Find a file called NAME on the module search path, and call THUNK on it.
- The file is searched for relative to the SCANNER's current file, and also
+ The file is searched for relative to the HOME file or directory, and also
in the directories mentioned in the `*module-dirs*' list. If the file is
found, then THUNK is invoked with two arguments: the name we used to find
it (which might be relative to the starting directory) and the truename
THUNK is not invoked with any additional handlers defined."
(handler-case
- (dolist (dir (cons (pathname (scanner-filename scanner)) *module-dirs*)
- (values nil nil))
+ (dolist (dir (cons home *module-dirs*) (values nil nil))
(let* ((path (merge-pathnames name dir))
(probe (probe-file path)))
(when probe