src/module-{proto,impl}.lisp, etc.: Don't output erroneous modules.
authorMark Wooding <mdw@distorted.org.uk>
Fri, 6 Jul 2018 22:58:45 +0000 (23:58 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Mon, 9 Jul 2018 11:11:39 +0000 (12:11 +0100)
Add a new reader `module-errors' which reports the number of errors
found while processing the module.  Notice (but decline to handle)
errors while loading modules.  And, in the front-end, don't try to
output erroneous modules.

This fixes an annoying problem where errors are reported and cause
`make' to fail, and then a subsequent `make' apparently succeeds,
possibly with bogus C code.

doc/SYMBOLS
doc/module.tex
src/frontend.lisp
src/module-impl.lisp
src/module-proto.lisp

index 4f13521..944a975 100644 (file)
@@ -588,6 +588,7 @@ module-proto.lisp
   finalize-module                               generic
   module                                        class
   module-dependencies                           generic setf
+  module-errors                                 generic
   module-import                                 generic
   module-items                                  generic setf
   module-name                                   generic
@@ -1323,6 +1324,8 @@ module-dependencies
   module
 (setf module-dependencies)
   t module
+module-errors
+  module
 module-import
   t
   module
index 3c62625..802e32b 100644 (file)
@@ -53,6 +53,7 @@
 \begin{describe*}
     {\dhead{gf}{module-name @<module> @> @<pathname>}
      \dhead{gf}{module-pset @<module> @> @<pset>}
+     \dhead{gf}{module-errors @<module> @> @<integer>}
      \dhead{gf}{module-items @<module> @> @<list>}
      \dhead{gf}{module-dependencies @<module> @> @<list>}
      \dhead{gf}{module-state @<module> @> @<keyword>}}
index a4625f7..7648e2d 100644 (file)
 
               ;; Parse and write out the remaining modules.
               (dolist (arg args)
-                (hack-module (read-module arg)))))
+                (let ((module (read-module arg)))
+                  (when (zerop (module-errors module))
+                    (hack-module module))))))
 
       (if backtracep (hack-modules)
          (multiple-value-bind (hunoz nerror nwarn)
index cb3a8ad..4da7804 100644 (file)
     (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.
index a79069a..7e42a5b 100644 (file)
 ;;;--------------------------------------------------------------------------
 ;;; Module objects.
 
-(export '(module module-name module-pset module-items module-dependencies))
+(export '(module module-name module-pset module-errors
+         module-items module-dependencies))
 (defclass module ()
   ((name :initarg :name :type pathname :reader module-name)
    (%pset :initarg :pset :initform (make-pset)
          :type pset :reader module-pset)
+   (errors :initarg :errors :initform 0 :type fixnum :reader module-errors)
    (items :initarg :items :initform nil :type list :accessor module-items)
    (dependencies :initarg :dependencies :initform nil
                 :type list :accessor module-dependencies)