Skip to content

Commit a08ae93

Browse files
committed
omit-proofs: handle commands that may have global effects
Add the predicate `proof-script-cmd-prevents-proof-omission' to the omit-proofs framework, whose purpose is to check whether commands inside proofs might have global effects such that the proof must not be omitted. Fixes ProofGeneral#688
1 parent 0d5ae06 commit a08ae93

File tree

6 files changed

+71
-14
lines changed

6 files changed

+71
-14
lines changed

ci/simple-tests/coq-test-omit-proofs.el

-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,6 @@ In particular, test that with proof-omit-proofs-option configured:
178178
(should (eq (first-overlay-face) 'proof-locked-face)))
179179

180180
(ert-deftest omit-proofs-never-omit-hints ()
181-
:expected-result :failed
182181
"Test that proofs containing Hint are never omitted.
183182
This test only checks that the face in the middle of the proof is
184183
the normal `proof-locked-face'.

coq/coq-syntax.el

+5
Original file line numberDiff line numberDiff line change
@@ -1428,6 +1428,11 @@ different."
14281428
(defconst coq-command-decl-regexp (coq-add-command-prefix coq-keywords-decl))
14291429
(defconst coq-command-defn-regexp (coq-add-command-prefix coq-keywords-defn))
14301430

1431+
(defconst coq-lowercase-command-regexp "^[a-z]"
1432+
"Regular expression matching commands starting with a lowercase letter.
1433+
Used in `coq-cmd-prevents-proof-omission' to identify tactics
1434+
that only have proof-local effects.")
1435+
14311436
;; must match:
14321437
;; "with f x y :" (followed by = or not)
14331438
;; "with f x y (z:" (not followed by =)

coq/coq.el

+14-1
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,18 @@ If locked span already has a state number, then do nothing. Also updates
745745
;; (message "Unknown command, hopes this won't desynchronize ProofGeneral")
746746
;; t))))
747747

748+
(defun coq-cmd-prevents-proof-omission (cmd)
749+
"Instanciation for `proof-script-cmd-prevents-proof-omission'.
750+
This predicate decides whether a command inside a proof might
751+
have effects outside the proof, which would prohibit omitting the
752+
proof, see `proof-script-omit-proofs'.
753+
754+
Commands starting lower case are deemed as tactics that have
755+
proof local effect only. Everything else is checked against the
756+
STATECH field in the coq syntax data base, see coq-db.el."
757+
(if (proof-string-match coq-lowercase-command-regexp cmd)
758+
nil
759+
(not (coq-state-preserving-p cmd))))
748760

749761
(defun coq-hide-additional-subgoals-switch ()
750762
"Function invoked when the user switches option `coq-hide-additional-subgoals'."
@@ -1954,7 +1966,8 @@ at `proof-assistant-settings-cmds' evaluation time.")
19541966
proof-script-proof-start-regexp coq-proof-start-regexp
19551967
proof-script-proof-end-regexp coq-proof-end-regexp
19561968
proof-script-definition-end-regexp coq-definition-end-regexp
1957-
proof-script-proof-admit-command coq-omit-proof-admit-command)
1969+
proof-script-proof-admit-command coq-omit-proof-admit-command
1970+
proof-script-cmd-prevents-proof-omission #'coq-cmd-prevents-proof-omission)
19581971

19591972
(setq proof-cannot-reopen-processed-files nil)
19601973

doc/PG-adapting.texi

+8-4
Original file line numberDiff line numberDiff line change
@@ -1187,10 +1187,14 @@ match of @samp{@code{proof-script-proof-end-regexp}}, are omitted (not send
11871187
to the proof assistant) and replaced by
11881188
@samp{@code{proof-script-proof-admit-command}}. If a match for
11891189
@samp{@code{proof-script-definition-end-regexp}} is found while searching
1190-
forward for the proof end, the current proof (up to and including
1191-
the match of @samp{@code{proof-script-definition-end-regexp}}) is considered
1192-
to be not opaque and not omitted, thus all these proof commands
1193-
_are_ sent to the proof assistant.
1190+
forward for the proof end or if
1191+
@samp{@code{proof-script-cmd-prevents-proof-omission}} recognizes a proof
1192+
command that prevents proof omission then the current proof (up
1193+
to and including the match of
1194+
@samp{@code{proof-script-definition-end-regexp}} or
1195+
@samp{@code{proof-script-proof-end-regexp}}) is considered to be not opaque
1196+
and not omitted, thus all these proof commands _are_ sent to the
1197+
proof assistant.
11941198

11951199
The feature does not work for nested proofs. If a match for
11961200
@samp{@code{proof-script-proof-start-regexp}} is found before the next match

generic/proof-config.el

+20-4
Original file line numberDiff line numberDiff line change
@@ -715,10 +715,14 @@ match of `proof-script-proof-end-regexp', are omitted (not send
715715
to the proof assistant) and replaced by
716716
`proof-script-proof-admit-command'. If a match for
717717
`proof-script-definition-end-regexp' is found while searching
718-
forward for the proof end, the current proof (up to and including
719-
the match of `proof-script-definition-end-regexp') is considered
720-
to be not opaque and not omitted, thus all these proof commands
721-
_are_ sent to the proof assistant.
718+
forward for the proof end or if
719+
`proof-script-cmd-prevents-proof-omission' recognizes a proof
720+
command that prevents proof omission then the current proof (up
721+
to and including the match of
722+
`proof-script-definition-end-regexp' or
723+
`proof-script-proof-end-regexp') is considered to be not opaque
724+
and not omitted, thus all these proof commands _are_ sent to the
725+
proof assistant.
722726
723727
The feature does not work for nested proofs. If a match for
724728
`proof-script-proof-start-regexp' is found before the next match
@@ -759,6 +763,18 @@ See `proof-omit-proofs-configured'."
759763
:type 'string
760764
:group 'proof-script)
761765

766+
(defcustom proof-script-cmd-prevents-proof-omission nil
767+
"Optional predicate recognizing proof commands that prevent proof omission.
768+
If set, this option should contain a function that takes a proof
769+
command (as string) as argument and returns t or nil. If set, the
770+
function is called on every proof command inside a proof while
771+
scanning for proofs to omit. The predicate should return t if the
772+
command has effects ouside the proof, potentially breaking the
773+
script if the current proof is omitted. If the predicate returns
774+
t, the proof is considered to be not opaque and thus not omitted."
775+
:type 'function
776+
:group 'proof-script)
777+
762778

763779
;;
764780
;; Proof script indentation

generic/proof-script.el

+24-4
Original file line numberDiff line numberDiff line change
@@ -2028,6 +2028,8 @@ start is found inside a proof."
20282028
maybe-result
20292029
inside-proof
20302030
proof-start-span-start proof-start-span-end
2031+
;; t if the proof contains state changing commands and must be kept
2032+
proof-must-be-kept
20312033
;; the current vanilla item
20322034
item
20332035
;; the command of the current item
@@ -2061,7 +2063,12 @@ start is found inside a proof."
20612063
(line-number-at-pos (span-end (car item))))))
20622064

20632065
;; else - no nested proof, but still inside-proof
2064-
(if (string-match proof-script-proof-end-regexp cmd)
2066+
(if (and (string-match proof-script-proof-end-regexp cmd)
2067+
(not proof-must-be-kept))
2068+
;; End of opaque proof recognized and we didn't
2069+
;; recognize a state changing command inside the
2070+
;; proof that would prohibit throwing the proof
2071+
;; away.
20652072
(let
20662073
;; Reuse the Qed span for the whole proof,
20672074
;; including the faked Admitted command.
@@ -2102,15 +2109,27 @@ start is found inside a proof."
21022109
(setq inside-proof nil))
21032110

21042111
;; else - no nested proof, no opaque proof, but still inside
2105-
(if (string-match proof-script-definition-end-regexp cmd)
2112+
(if (or (string-match proof-script-definition-end-regexp cmd)
2113+
(and (string-match proof-script-proof-end-regexp cmd)
2114+
proof-must-be-kept))
21062115
;; A proof ending in Defined or something similar.
2116+
;; Or a proof containing a state changing command
2117+
;; such that the proof-must-be-kept.
21072118
;; Need to keep all commands from the start of the proof.
21082119
(progn
21092120
(setq result (cons item (nconc maybe-result result)))
21102121
(setq maybe-result nil)
21112122
(setq inside-proof nil))
2112-
;; normal proof command - maybe it belongs to a
2123+
2124+
;; else - inside proof, no proof termination recognized
2125+
;; Normal proof command - maybe it belongs to a
21132126
;; Defined, keep it separate, until we know.
2127+
(when (and proof-script-cmd-prevents-proof-omission
2128+
(not (eq (span-property (car item) 'type) 'comment))
2129+
(not proof-must-be-kept)
2130+
(funcall proof-script-cmd-prevents-proof-omission
2131+
cmd))
2132+
(setq proof-must-be-kept t))
21142133
(push item maybe-result)))))
21152134

21162135
;; else - outside proof
@@ -2121,7 +2140,8 @@ start is found inside a proof."
21212140
(push item result)
21222141
(setq proof-start-span-start (span-start (car item)))
21232142
(setq proof-start-span-end (span-end (car item)))
2124-
(setq inside-proof t))
2143+
(setq inside-proof t)
2144+
(setq proof-must-be-kept nil))
21252145
;; outside, no proof start - keep it unmodified
21262146
(push item result)))
21272147
(setq vanillas (cdr vanillas)))

0 commit comments

Comments
 (0)