Print a form whose evaluation caused a guard violation
By default, ACL2 checks input constraints on functions, known as
guards. When guards are violated, an informative message is printed;
but sometimes it is useful to investigate why the guard check fails. The
utility
Example Forms: (print-gv) :print-gv ; same as above (print-gv ; same as above, showing all system defaults :conjunct nil :evisc-tuple (print-gv-evisc-tuple) :substitute nil) (print-gv :substitute 20) (print-gv :evisc-tuple (evisc-tuple 4 4 nil nil)) (print-gv :evisc-tuple (evisc-tuple 4 4 nil nil)) (print-gv :evisc-tuple (evisc-tuple 4 ; print-level 5 ; print-length (world-evisceration-alist state nil) nil ; hiding-cars ))
General Form: (print-gv :conjunct c :substitute s :evisc-tuple e)
where the keyword arguments are optional. These arguments have the following effects and system defaults, but note that the defaults can be changed by the user; see set-print-gv-defaults.
Again, the user can change these defaults; see set-print-gv-defaults. For example, one might wish to evaluate
Remarks
To see how one might use
(defun foo (x) (declare (xargs :guard (and (integerp x) (posp (+ -2 x)) (posp (+ 3 x)) (posp (+ -4 x))))) x)
Now suppose we evaluate a call of foo and obtain a guard violation.
ACL2 !>(foo 1) ACL2 Error in TOP-LEVEL: The guard for the function call (FOO X), which is (AND (INTEGERP X) (POSP (+ -2 X)) (POSP (+ 3 X)) (POSP (+ -4 X))), is violated by the arguments in the call (FOO 1). See :DOC set-guard-checking for information about suppressing this check with (set-guard-checking :none), as recommended for new users. To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.
Let us investigate this guard failure. First we use
ACL2 !>:print-gv (FLET ((FOO{GUARD} (X) (DECLARE (IGNORABLE X)) (AND (INTEGERP X) (POSP (+ -2 X)) (POSP (+ 3 X)) (POSP (+ -4 X))))) (FOO{GUARD} 1)) ACL2 !>(FLET ((FOO{GUARD} (X) (DECLARE (IGNORABLE X)) (AND (INTEGERP X) (POSP (+ -2 X)) (POSP (+ 3 X)) (POSP (+ -4 X))))) (FOO{GUARD} 1)) NIL
This form doesn't tell us which of the four conjuncts actually evaluated to
ACL2 !>(print-gv :conjunct t) Showing guard conjunct (#2 of 4) that evaluates to nil: (FLET ((FOO{GUARD} (X) (POSP (+ -2 X)))) (FOO{GUARD} 1)). ACL2 !>
But here's another way to analyze the guard failure. Let's change and to list in the result of
ACL2 !>(FLET ((FOO{GUARD} (X) (DECLARE (IGNORABLE X)) (list (INTEGERP X) (POSP (+ -2 X)) (POSP (+ 3 X)) (POSP (+ -4 X))))) (FOO{GUARD} 1)) (T NIL T NIL) ACL2 !>
The
If you use local stobjs (see with-local-stobj) or stobj
fields of stobjs, you may need to edit the output of
(defstobj st fld) (defun g (x st) (declare (xargs :guard (consp x) :stobjs st) (ignore x)) (fld st)) (defun test () (with-local-stobj st (mv-let (result st) (mv (g 3 st) st) result))) (test)
Then
(FLET ((G{GUARD} (X ST) (DECLARE (IGNORABLE X ST)) (AND (STP ST) (CONSP X)))) (G{GUARD} 3 |<some-stobj>|))
In this example you could replace ``
(defstobj st2 fld2) (defun g2 (st2) (declare (xargs :guard (null (fld2 st2)) :stobjs st2)) (mv 0 st2)) (defun test2 () (with-local-stobj st2 (mv-let (result st2) (let ((st2 (update-fld2 17 st2))) (g2 st2)) result))) (test2)
In this case,
(FLET ((G2{GUARD} (ST2) (DECLARE (IGNORABLE ST2)) (AND (ST2P ST2) (NULL (FLD2 ST2))))) (G2{GUARD} |<some-stobj>|))
But if you replace ``
ACL2 !>(FLET ((G2{GUARD} (ST2) (DECLARE (IGNORABLE ST2)) (AND (ST2P ST2) (NULL (FLD2 ST2))))) (G2{GUARD} st2)) T ACL2 !>
We conclude with an example that illustrates point (1) above, regarding the
installation of the world that was in place at the time the guard
violation took place. In the following, the progn call fails when the
form
(progn (defn g (x) (consp x)) (defun foo (x) (declare (xargs :guard (g x))) (car x)) (value-triple (foo 3)))
We can then issue
ACL2 !>:print-gv (FLET ((FOO{GUARD} (X) (DECLARE (IGNORABLE X)) (G X))) (FOO{GUARD} 3)) ACL2 !>
However, if you try to evaluate this form, you will get an error because
the function