File: saved-errors.lisp

package info (click to toggle)
acl2 8.3dfsg-2
  • links: PTS
  • area: main
  • in suites: bullseye
  • size: 309,408 kB
  • sloc: lisp: 3,311,842; javascript: 22,569; cpp: 9,029; ansic: 7,872; perl: 6,501; xml: 3,838; java: 3,738; makefile: 3,383; ruby: 2,633; sh: 2,489; ml: 763; python: 741; yacc: 721; awk: 260; csh: 186; php: 171; lex: 154; tcl: 49; asm: 23; haskell: 17
file content (198 lines) | stat: -rw-r--r-- 8,766 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198


(in-package "ACL2")


;; This is a hack.

;; In summary:  WITH-SAVED-ERROR-MSG associates an error message with an
;; event form.  WITH-FINAL-ERROR-PRINTING, if wrapped around a failing
;; WITH-SAVED-ERROR-MSG form, will print the message associated with the
;; failing form.

;; This is meant to be used in cases where a lot of event forms are being
;; generated by make-events or macros and it might not be clear to the user
;; what is going on if one of them fails.  Here is an example.  Assume a
;; make-event generates the following:

;; (progn
;;   (encapsulate nil
;;     (event1))
;;   (progn
;;     (event2)
;;     (event3))
;;   (event4))

;; If, say, event2 fails, there might be some proof output and a couple of
;; failure messages printed at the end, and the user might have to search up to
;; even find the form that failed (assuming it was printed.)  This book offers
;; the ability to instead generate something like this:

;; (with-final-error-printing
;;  (progn
;;    (encapsulate nil
;;      (with-saved-error-msg
;;       (event1)
;;       "Event 1 failed.  This might be because...~%"))
;;    (progn
;;      (with-saved-error-msg
;;       (event2)
;;       (msg "Event 2 failed.  The form that caused the error was ~x0.~%" form))
;;      (with-saved-error-msg
;;       (event3)
;;       "Event 3 should be failure-proof.  Please contact the implementors.~%"))
;;    (with-saved-error-msg
;;     (event4)
;;     (msg "You were almost done! All that was left was ~x0!!~%" form))))

;; What does this mean?  WITH-SAVED-ERROR-MSG does very little: It is a
;; make-event that saves the given message in a certain state global variable,
;; then runs a PROGN which first runs the form then deletes the state global.
;; (The variable FORM is bound to the event form supplied, so it can be used in
;; generating the message.)  WITH-FINAL-ERROR-PRINTING is more complicated.
;; First, it checks to see if a book is being certified; if so, it simply
;; submits the event as-is.  If not, it runs the event within the make-event
;; expansion to check whether or not it succeeds.  If it does, it resubmits the
;; expanded form with a SKIP-PROOFS around it.  Otherwise, it looks at the
;; state global variable for the last message saved there.  It assumes this is
;; the message corresponding to the form that caused the error and prints it,
;; then generates an event form that fails quietly so that the error message is
;; nearly the last thing printed.

;; The major unresolved issue with this is that WITH-FINAL-ERROR-PRINTING adds
;; overhead because it reruns the expansion of the event, when successful,
;; using SKIP-PROOFS.  Normally this is okay.  It is somewhat bad if the
;; expanded event is so huge that it takes lots of time just to compile and
;; record the resulting form.  Also, if WITH-FINAL-ERROR-PRINTING forms are
;; nested, this overhead is paid once for each nesting.


(defmacro with-final-error-printing (form &key (ctx 'with-final-error-printing))
  `(with-output
    :off (summary warning!)
    :stack :push
    (make-event
     (if (or (acl2::f-get-global 'acl2::certify-book-info state)
             (acl2::global-val 'include-book-path (w state))
             (ld-skip-proofsp state))
         ;; We're in a certify-book, include-book, or skip-proofs, so just
         ;; produce the form without any error printing.
         (value '(with-output :stack :pop ,form))
       (mv-let (erp val state)
         ;; Run the form inside a make-event.  This allows us to access its
         ;; expansion later.  Note that this is happening within make-event
         ;; expansion -- we're not *returning* this form, just running it.
         (with-output :stack :pop (make-event ',form))
         (if erp
             ;; If the event failed, print the error message and then produce
             ;; an unsuccessful but quiet make-event.
             (er-progn
              ;; Save state globals related to REDO-FLAT.
              (assign error-redo-flat-fail
                      (f-get-global 'redo-flat-fail state))
              (assign error-redo-flat-succ
                      (f-get-global 'redo-flat-succ state))
              (er very-soft ',ctx
                           "~@0~%"
                           (if (boundp-global 'saved-error-for-final-error-printing state)
                               (@ saved-error-for-final-error-printing)
                             "The event failed, but no error message was saved~%"))
                     (value '(with-output :off :all (make-event nil))))
           ;; The event succeeded, so produce a skip-proofs of its expansion
           ;; with all output turned off to finish.
           (value `(with-output :off :all
                                (progn (skip-proofs
                                        ,(f-get-global
                                          'last-make-event-expansion
                                          state))
                                       (value-triple ',val))))))))))

(defmacro with-saved-error-msg (form msg)
  `(make-event
    (let ((form ',form))
      (er-progn
       (assign saved-error-for-final-error-printing ,msg)
       (value `(progn ,form
                      (with-output
                       :off :all
                       (make-event
                        (let ((state (makunbound-global
                                      'saved-error-for-final-error-printing
                                      state)))
                          (value '(value-triple :invisible)))))))))))

(defmacro error-redo-flat (&key (succ-ld-skip-proofsp 't)
                                (label 'r)
                                (succ 't)
                                (fail 't)
                                (pbt 't)
                                (show 'nil))

  `(if (null (f-get-global 'error-redo-flat-fail state))
       (pprogn (fms "
There is no failure saved from a WITH-FINAL-ERROR-PRINTING form.~|"
                    nil (standard-co state) state nil)
               (value :invisible))
     ,(if show
          `(pprogn (fms "List of events (from encapsulate or progn) preceding ~
                         the failure:~|~%~x0~|"
                        (list (cons #\0 (f-get-global 'error-redo-flat-succ state)))
                        (standard-co state) state (ld-evisc-tuple state))
                   (fms "Failed event:~|~%~x0~|"
                        (list (cons #\0 (f-get-global 'error-redo-flat-fail state)))
                        (standard-co state) state (ld-evisc-tuple state))
                   (value :invisible))
        `(let ((error-redo-flat-succ (f-get-global 'error-redo-flat-succ state))
               (error-redo-flat-fail (f-get-global 'error-redo-flat-fail state)))
           (state-global-let*
            ((error-redo-flat-succ error-redo-flat-succ)
             (error-redo-flat-fail error-redo-flat-fail))
            (ld (list ,@(and succ label `('(deflabel ,label)))
                      ,@(and succ (list (list 'list ''ld
                                              (list 'cons
                                                    ''list
                                                    (list 'kwote-lst 'error-redo-flat-succ))
                                              :ld-skip-proofsp succ-ld-skip-proofsp)))
                      ,@(and fail (list (list 'list ''ld
                                              (list 'list
                                                    ''list
                                                    (list 'list ''quote 'error-redo-flat-fail))
                                              :ld-error-action :continue
                                              :ld-pre-eval-print t)))
                      ,@(and pbt succ label
                             `('(pprogn (newline (proofs-co state)
                                                 state)
                                        (pbt ',label)))))))))))



(defun saved-error-cond-fn (conds)
  (if (atom conds)
      '((t (value '(value-triple 'bindings-ok))))
    (let ((test (caar conds))
          (msg (cadar conds)))
      (cons `(,test
              (er-progn (assign saved-error-for-final-error-printing ,msg)
                        (value `(with-output :off :all (make-event nil)))))
            (saved-error-cond-fn (cdr conds))))))



(defmacro saved-error-cond (&rest conds)
  `(with-output
    :off :all
    (make-event
     (cond
      . ,(saved-error-cond-fn conds)))))



(defun skip-proofs-outside-certify-fn (form)
  `(make-event
    (if (acl2::f-get-global 'acl2::certify-book-info state)
        ',form
      `(skip-proofs ,',form))))

(defmacro skip-proofs-outside-certify (form)
  (skip-proofs-outside-certify-fn form))