Major Section: IO
When ACL2 pretty-prints large expressions using formatted printing
(see fmt), it may save time and space by printing tokens `#
' or
`...
' in place of certain subexpressions. By default this only happens
for a few settings such as error and warning messages; see set-evisc-tuple
for controlling such elision in general. The full expression is unavailable
to the user when `#
' or `...
' is printed, but that is easily solved
by evaluating the form
(set-iprint t)to enable a mode called ``iprinting''. Then, instead of printing `
#
' or
`...
', ACL2 prints `#@i#
' for i
= 1,2,3,... -- all in base 10.
ACL2 can read back in such `#@i#
' because under the hood, i
is
associated with its corresponding elided form. Thus the term ``iprint'' can
be viewed as suggesting ``interactive print'' or ``index print''. We also
think of ``iprint'' as suggesting ``i
printing'', to suggest the printing
of token `#@i#
'. We call i
the ``iprint index'' of that token.The following example should suffice to illustrate how to recover elided
subexpressions. (Below this example we provide details that may be of
interest only to advanced users.) Here we cause an error by defining a macro
of one argument and then calling it with two arguments. By default, error
messages abbreviate subexpressions deeper than level 5 with `#
' and past
the 7th element of a list with `...
'. We see this behavior below.
ACL2 !>(defmacro foo (x) x) Summary Form: ( DEFMACRO FOO ...) Rules: NIL Warnings: None Time: 0.02 seconds (prove: 0.00, print: 0.00, other: 0.02) FOO ACL2 !>(foo arg1 (a (b (c (d (e (f (g)))))) h i j k l m n)) ACL2 Error in macro expansion: Wrong number of args in macro expansion of (FOO ARG1 (A (B (C (D #))) H I J K L ...)). (See :DOC set-iprint to be able to see elided values in this message.) ACL2 !>(set-iprint t) ACL2 Observation in SET-IPRINT: Iprinting has been enabled. ACL2 !>(foo arg1 (a (b (c (d (e (f (g)))))) h i j k l m n)) ACL2 Error in macro expansion: Wrong number of args in macro expansion of (FOO ARG1 (A (B (C (D #@1#))) H I J K L . #@2#)). ACL2 !>(acl2-count '(FOO ARG1 (A (B (C (D #@1#))) H I J K L . #@2#))) 23 ACL2 !>Sometimes you may want to supply the abbreviated form not to compute with it, as in the
acl2-count
example just above, but so that you can see it.
The macro without-evisc
eliminates elision during printing. Below we
show two ways to use this utility: first, we use it to print the elided form,
and then, we use it instead on the original input form to print the entire
error message.
ACL2 !>(without-evisc '(FOO ARG1 (A (B (C (D #@1#))) H I J K L . #@2#))) (FOO ARG1 (A (B (C (D (E (F (G)))))) H I J K L M N)) ACL2 !>(without-evisc (foo arg1 (a (b (c (d (e (f (g)))))) h i j k l m n))) ACL2 Error in macro expansion: Wrong number of args in macro expansion of (FOO ARG1 (A (B (C (D (E (F (G)))))) H I J K L M N)). ACL2 !>
The documentation above probably suffices for most users. For those who want
more details, below we detail all the ways to use the set-iprint
utility.
Example Forms: (set-iprint t) ; enable iprinting (elision with #@i@) (set-iprint nil) ; disable iprinting General Form: (set-iprint action ; t, nil, :reset, :reset-enable, or :same :soft-bound s ; initially 1000 :hard-bound h ; initially 10000)where all arguments are optional, but ACL2 queries for
action
if it is
omitted. We defer the explanations of :soft-bound
and :hard-bound
.
The values for action
are as follows:
T
-- Enable iprinting.
NIL
-- Disable iprinting.
:RESET
-- Reset iprinting to its initial disabled state, so that when enabled, the first indexi
for which `#@i#
is printed will be 1. Note that all stored information for existing iprint indices will be erased.
:RESET-ENABLE
-- Reset iprinting as with:reset
, and then enable iprinting.
:SAME
-- Make no change to the iprinting state (other than setting the:soft-bound
and/or:hard-bound
if specified, as explained below).
Immediately after a top-level form is read, hence before it is evaluated, a
check is made for whether the latest iprint index exceeds a certain bound,
(iprint-soft-bound state)
-- 1000, by default. If so, then the
(iprint-last-index state)
is set back to 0. This soft bound can be
changed to any positive integer k
by calling set-iprint
with
:soft-bound k
, typically (set-iprint :same :soft-bound k
)].
The above ``soft bound'' is applied once for each top-level form, but you may
want finer control by applying a bound after the pretty-printing of each
individual form (since many forms may be pretty-printed between successive
evaluations of top-level forms). That bound is
(iprint-hard-bound state)
, and can be set with the :hard-bound
argument in analogy to how :soft-bound
is set, as described above.
A ``rollover'' is the detection that the soft or hard bound has been exceeded, along with a state update so that the next iprint index will be 1. When a rollover occurs, any index beyond the latest iprint index is no longer available for reading. At the top level of the ACL2 read-eval-print loop, this works as follows: ACL2 reads the next top-level form according to the current iprint state, then handles a rollover if the latest iprint index exceeded the current soft bound. The following log illustrates a rollover, which follows the description above.
ACL2 !>(set-iprint t :soft-bound 3) ACL2 Observation in SET-IPRINT: The soft-bound for iprinting has been set to 3. ACL2 Observation in SET-IPRINT: Iprinting has been enabled. ACL2 !>(set-evisc-tuple (evisc-tuple 2 3 nil nil) :sites :ld) (:LD) ACL2 !>'((a b c d e f g) (a b c d e f g) (a b c d e f g)) ((A B C . #@1#) (A B C . #@2#) (A B C . #@3#)) ACL2 !>'((a b c d e f g) (a b c d e f g) (a b c d e f g)) ((A B C . #@4#) (A B C . #@5#) (A B C . #@6#)) ACL2 !>(without-evisc '((A B C . #@4#) (A B C . #@5#) (A B C . #@6#))) ((A B C D E F G) (A B C D E F G) (A B C D E F G)) ACL2 !>'(1 2 3 4 5) (1 2 3 . #@1#) ACL2 !>'((a b c d e f g) (a b c d e f g) (a b c d e f g)) ((A B C . #@2#) (A B C . #@3#) (A B C . #@4#)) ACL2 !>(without-evisc '((A B C . #@4#) (A B C . #@5#) (A B C . #@6#))) ((A B C D E F G) (A B C D E F G) (A B C D E F G)) ACL2 !>(without-evisc '((A B C . #@4#) (A B C . #@5#) (A B C . #@6#))) *********************************************** ************ ABORTING from raw Lisp *********** Error: Out-of-bounds index in #@5#. See :DOC set-iprint. *********************************************** If you didn't cause an explicit interrupt (Control-C), then the root cause may be call of a :program mode function that has the wrong guard specified, or even no guard specified (i.e., an implicit guard of t). See :DOC guards. To enable breaks into the debugger (also see :DOC acl2-customization): (SET-DEBUGGER-ENABLE T) ACL2 !>
We conclude by mentioning two cases where iprinting and evisc-tuples are
ignored. (1) This is typically the case when printing results in raw Lisp
outside the ACL2 loop. To use iprinting and evisc-tuples in raw Lisp, use
raw-mode; see set-raw-mode. In raw-mode, results that are ACL2 objects will
be printed in the same way that ACL2 would print those results if not in
raw-mode. (2) Iprinting and evisc-tuples are ignored by print-object$
,
which however is sensitive to many settings that do not affect formatted
(fmt
etc.) printing; see print-control.
The reader interested in design and implementation issues considered during the addition of iprinting to ACL2 is invited to read the paper ``Abbreviated Output for Input in ACL2: An Implementation Case Study''; see the proceedings of ACL2 Workshop 2009, http://www.cs.utexas.edu/users/moore/acl2/workshop-2009/.