ui: Auto-compile user code, and improve error reporting.
Reported by Christian Grothoff. * guix/ui.scm (load*): Add 'frame-with-source'. Set %load-should-auto-compile. Change error handle to just (exit 1). Add pre-unwind handler to capture the stack and call 'report-load-error'. (report-load-error): Add optional 'frame' parameter and pass it to 'display-error'. * tests/guix-system.sh: Add "unbound variable" test.
This commit is contained in:
parent
fbb25e5651
commit
2abcc97fd1
|
@ -13,6 +13,7 @@
|
||||||
.
|
.
|
||||||
((indent-tabs-mode . nil)
|
((indent-tabs-mode . nil)
|
||||||
(eval . (put 'eval-when 'scheme-indent-function 1))
|
(eval . (put 'eval-when 'scheme-indent-function 1))
|
||||||
|
(eval . (put 'call-with-prompt 'scheme-indent-function 1))
|
||||||
(eval . (put 'test-assert 'scheme-indent-function 1))
|
(eval . (put 'test-assert 'scheme-indent-function 1))
|
||||||
(eval . (put 'test-assertm 'scheme-indent-function 1))
|
(eval . (put 'test-assertm 'scheme-indent-function 1))
|
||||||
(eval . (put 'test-equal 'scheme-indent-function 1))
|
(eval . (put 'test-equal 'scheme-indent-function 1))
|
||||||
|
|
43
guix/ui.scm
43
guix/ui.scm
|
@ -35,6 +35,7 @@
|
||||||
#:use-module (srfi srfi-11)
|
#:use-module (srfi srfi-11)
|
||||||
#:use-module (srfi srfi-19)
|
#:use-module (srfi srfi-19)
|
||||||
#:use-module (srfi srfi-26)
|
#:use-module (srfi srfi-26)
|
||||||
|
#:use-module (srfi srfi-31)
|
||||||
#:use-module (srfi srfi-34)
|
#:use-module (srfi srfi-34)
|
||||||
#:use-module (srfi srfi-35)
|
#:use-module (srfi srfi-35)
|
||||||
#:use-module (srfi srfi-37)
|
#:use-module (srfi srfi-37)
|
||||||
|
@ -147,18 +148,50 @@ messages."
|
||||||
|
|
||||||
(define (load* file user-module)
|
(define (load* file user-module)
|
||||||
"Load the user provided Scheme source code FILE."
|
"Load the user provided Scheme source code FILE."
|
||||||
|
(define (frame-with-source frame)
|
||||||
|
;; Walk from FRAME upwards until source location information is found.
|
||||||
|
(let loop ((frame frame)
|
||||||
|
(previous frame))
|
||||||
|
(if (not frame)
|
||||||
|
previous
|
||||||
|
(if (frame-source frame)
|
||||||
|
frame
|
||||||
|
(loop (frame-previous frame) frame)))))
|
||||||
|
|
||||||
(catch #t
|
(catch #t
|
||||||
(lambda ()
|
(lambda ()
|
||||||
|
;; XXX: Force a recompilation to avoid ABI issues.
|
||||||
(set! %fresh-auto-compile #t)
|
(set! %fresh-auto-compile #t)
|
||||||
|
(set! %load-should-auto-compile #t)
|
||||||
|
|
||||||
(save-module-excursion
|
(save-module-excursion
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(set-current-module user-module)
|
(set-current-module user-module)
|
||||||
(primitive-load file))))
|
|
||||||
(lambda args
|
|
||||||
(report-load-error file args))))
|
|
||||||
|
|
||||||
(define (report-load-error file args)
|
;; Hide the "auto-compiling" messages.
|
||||||
|
(parameterize ((current-warning-port (%make-void-port "w")))
|
||||||
|
;; Give 'load' an absolute file name so that it doesn't try to
|
||||||
|
;; search for FILE in %LOAD-PATH. Note: use 'load', not
|
||||||
|
;; 'primitive-load', so that FILE is compiled, which then allows us
|
||||||
|
;; to provide better error reporting with source line numbers.
|
||||||
|
(load (canonicalize-path file))))))
|
||||||
|
(lambda _
|
||||||
|
;; XXX: Errors are reported from the pre-unwind handler below, but
|
||||||
|
;; calling 'exit' from there has no effect, so we call it here.
|
||||||
|
(exit 1))
|
||||||
|
(rec (handle-error . args)
|
||||||
|
;; Capture the stack up to this procedure call, excluded, and pass
|
||||||
|
;; the faulty stack frame to 'report-load-error'.
|
||||||
|
(let* ((stack (make-stack #t handle-error))
|
||||||
|
(depth (stack-length stack))
|
||||||
|
(last (and (> depth 0) (stack-ref stack 0)))
|
||||||
|
(frame (frame-with-source
|
||||||
|
(if (> depth 1)
|
||||||
|
(stack-ref stack 1) ;skip the 'throw' frame
|
||||||
|
last))))
|
||||||
|
(report-load-error file args frame)))))
|
||||||
|
|
||||||
|
(define* (report-load-error file args #:optional frame)
|
||||||
"Report the failure to load FILE, a user-provided Scheme file, and exit.
|
"Report the failure to load FILE, a user-provided Scheme file, and exit.
|
||||||
ARGS is the list of arguments received by the 'throw' handler."
|
ARGS is the list of arguments received by the 'throw' handler."
|
||||||
(match args
|
(match args
|
||||||
|
@ -172,7 +205,7 @@ ARGS is the list of arguments received by the 'throw' handler."
|
||||||
(exit 1)))
|
(exit 1)))
|
||||||
((error args ...)
|
((error args ...)
|
||||||
(report-error (_ "failed to load '~a':~%") file)
|
(report-error (_ "failed to load '~a':~%") file)
|
||||||
(apply display-error #f (current-error-port) args)
|
(apply display-error frame (current-error-port) args)
|
||||||
(exit 1))))
|
(exit 1))))
|
||||||
|
|
||||||
(define (warn-about-load-error file args) ;FIXME: factorize with ↑
|
(define (warn-about-load-error file args) ;FIXME: factorize with ↑
|
||||||
|
|
|
@ -45,6 +45,32 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Reporting of unbound variables.
|
||||||
|
|
||||||
|
cat > "$tmpfile" <<EOF
|
||||||
|
(use-modules (gnu)) ; 1
|
||||||
|
(use-service-modules networking) ; 2
|
||||||
|
|
||||||
|
(operating-system ; 4
|
||||||
|
(host-name "antelope") ; 5
|
||||||
|
(timezone "Europe/Paris") ; 6
|
||||||
|
(locale "en_US.UTF-8") ; 7
|
||||||
|
|
||||||
|
(bootloader (GRUB-config (device "/dev/sdX"))) ; 9
|
||||||
|
(file-systems (cons (file-system
|
||||||
|
(device "root")
|
||||||
|
(title 'label)
|
||||||
|
(mount-point "/")
|
||||||
|
(type "ext4"))
|
||||||
|
%base-file-systems)))
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if guix system build "$tmpfile" -n 2> "$errorfile"
|
||||||
|
then false
|
||||||
|
else
|
||||||
|
grep "$tmpfile:9:.*[Uu]nbound variable.*GRUB-config" "$errorfile"
|
||||||
|
fi
|
||||||
|
|
||||||
# Reporting of duplicate service identifiers.
|
# Reporting of duplicate service identifiers.
|
||||||
|
|
||||||
cat > "$tmpfile" <<EOF
|
cat > "$tmpfile" <<EOF
|
||||||
|
|
Loading…
Reference in New Issue