diff options
| author | David Aspinall | 1998-09-03 13:51:41 +0000 |
|---|---|---|
| committer | David Aspinall | 1998-09-03 13:51:41 +0000 |
| commit | 8b836f84d70fcea59ffa186f6809ebc6765b8a5f (patch) | |
| tree | 8dc74b560cadf3b6e847e547776ccd0015dfa7f1 /proof.el | |
| parent | abbe57d8b69d79e9eb6899f182379d9c6c4fdc7f (diff) | |
Renamed for new subdirectory structure
Diffstat (limited to 'proof.el')
| -rw-r--r-- | proof.el | 1838 |
1 files changed, 0 insertions, 1838 deletions
diff --git a/proof.el b/proof.el deleted file mode 100644 index c37f863b..00000000 --- a/proof.el +++ /dev/null @@ -1,1838 +0,0 @@ -;; proof.el Major mode for proof assistants -;; Copyright (C) 1994 - 1998 LFCS Edinburgh. -;; Authors: David Aspinall, Yves Bertot, Healfdene Goguen, -;; Thomas Kleymann and Dilip Sequeira - -;; Maintainer: LEGO Team <lego@dcs.ed.ac.uk> -;; Thanks to Robert Boyer, Rod Burstall, -;; James McKinna, Mark Ruys, Martin Steffen, Perdita Stevens - - -(require 'cl) -(require 'compile) -(require 'comint) -(require 'etags) -(cond ((fboundp 'make-extent) (require 'span-extent)) - ((fboundp 'make-overlay) (require 'span-overlay)) - (t nil)) -(require 'proof-syntax) -(require 'proof-indent) -(require 'easymenu) -(require 'tl-list) - -(autoload 'w3-fetch "w3" nil t) - -(defmacro deflocal (var value docstring) - (list 'progn - (list 'defvar var 'nil docstring) - (list 'make-variable-buffer-local (list 'quote var)) - (list 'setq var value))) - - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Generic config for proof assistant ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defvar proof-assistant "" - "Name of the proof assistant") - -(defvar proof-www-home-page "" - "Web address for information on proof assistant") - -(defvar proof-shell-cd nil - "*Command of the inferior process to change the directory.") - -(defvar proof-shell-process-output-system-specific nil - "*Errors, start of proofs, abortions of proofs and completions of - proofs are recognised in the function `proof-shell-process-output'. - All other output from the proof engine is simply reported to the - user in the RESPONSE buffer. - - To catch further special cases, set this variable to a tuple of - functions '(condf . actf). Both are given (cmd string) as arguments. - `cmd' is a string containing the currently processed command. - `string' is the response from the proof system. To change the - behaviour of `proof-shell-process-output', (condf cmd string) must - return a non-nil value. Then (actf cmd string) is invoked. See the - documentation of `proof-shell-process-output' for the required - output format.") - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Proof mode variables ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defconst proof-mode-version-string - "PROOF-MODE. ALPHA Version 2 (August 1998) LEGO Team <lego@dcs.ed.ac.uk>") - -(defconst proof-info-dir "/usr/local/share/info" - "Directory to search for Info documents on Script Management.") - -(defconst proof-universal-keys - (list (cons '[(control c) (control c)] 'proof-interrupt-process) - (cons '[(control c) (control v)] - 'proof-execute-minibuffer-cmd) - (cons '[(meta tab)] 'tag-complete-symbol)) - "List of keybindings which are valid in both in the script and the - response buffer. Elements of the list are tuples (k . f) - where `k' is a keybinding (vector) and `f' the designated function.") - -(defvar proof-prog-name-ask-p nil - "*If t, you will be asked which program to run when the inferior - process starts up.") - - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Other buffer-local variables used by proof mode ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; These should be set before proof-config-done is called - -(defvar proof-terminal-char nil "terminator character") - -(defvar proof-comment-start nil "Comment start") -(defvar proof-comment-end nil "Comment end") - -(defvar proof-save-command-regexp nil "Matches a save command") -(defvar proof-save-with-hole-regexp nil "Matches a named save command") -(defvar proof-goal-with-hole-regexp nil "Matches a saved goal command") - -(defvar proof-goal-command-p nil "Is this a goal") -(defvar proof-count-undos-fn nil "Compute number of undos in a target segment") -(defvar proof-find-and-forget-fn nil "Compute command to forget up to point") - -(defvar proof-goal-hyp-fn nil - "A function which returns cons cell if point is at a goal/hypothesis. -First element of cell is a symbol, 'goal' or 'hyp'. The second -element is a string: the goal or hypothesis itself. This is used -when parsing the proofstate output") - -(defvar proof-kill-goal-command nil "How to kill a goal.") -(defvar proof-global-p nil - "Is this a global declaration") - -(defvar proof-state-preserving-p nil - "A predicate, non-nil if its argument preserves the proof state") - -(defvar pbp-change-goal nil - "*Command to change to the goal %s") - -;; these should be set in proof-pre-shell-start-hook - -(defvar proof-prog-name nil "program name for proof shell") -(defvar proof-mode-for-shell nil "mode for proof shell") -(defvar proof-mode-for-pbp nil "The actual mode for Proof-by-Pointing.") -(defvar proof-shell-insert-hook nil - "Function to config proof-system to interface") - -(defvar proof-pre-shell-start-hook) -(defvar proof-post-shell-exit-hook) - -(defvar proof-shell-prompt-pattern nil - "comint-prompt-pattern for proof shell") - -(defvar proof-shell-init-cmd nil - "The command for initially configuring the proof process") - -(defvar proof-shell-handle-delayed-output-hook - '(proof-pbp-focus-on-first-goal) - "*This hook is called after output from the PROOF process has been - displayed in the RESPONSE buffer.") - -(defvar proof-shell-handle-error-hook - '(proof-goto-end-of-locked-if-pos-not-visible-in-window) - "*This hook is called after an error has been reported in the - RESPONSE buffer.") - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Generic config for script management ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defvar proof-shell-wakeup-char nil - "A character terminating the prompt in annotation mode") - -(defvar proof-shell-annotated-prompt-regexp "" - "Annotated prompt pattern") - -(defvar proof-shell-abort-goal-regexp nil - "*Regular expression indicating that the proof of the current goal - has been abandoned.") - -(defvar proof-shell-error-regexp nil - "A regular expression indicating that the PROOF process has - identified an error.") - -(defvar proof-shell-interrupt-regexp nil - "A regular expression indicating that the PROOF process has - responded to an interrupt.") - -(defvar proof-shell-proof-completed-regexp nil - "*Regular expression indicating that the proof has been completed.") - -(defvar proof-shell-result-start "" - "String indicating the start of an output from the prover following - a `pbp-goal-command' or a `pbp-hyp-command'.") - -(defvar proof-shell-result-end "" - "String indicating the end of an output from the prover following a - `pbp-goal-command' or a `pbp-hyp-command'.") - -(defvar proof-shell-start-goals-regexp "" - "String indicating the start of the proof state.") - -(defvar proof-shell-end-goals-regexp "" - "String indicating the end of the proof state.") - -(defvar pbp-error-regexp nil - "A regular expression indicating that the PROOF process has - identified an error.") - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Internal variables used by scripting and pbp ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defvar proof-mode-name "Proof") - -(defvar proof-shell-echo-input t - "If nil, input to the proof shell will not be echoed") - -(defvar proof-terminal-string nil - "End-of-line string for proof process.") - -(defvar proof-re-end-of-cmd nil - "You are not authorised for this information.") - -(defvar proof-re-term-or-comment nil - "You are not authorised for this information.") - -(defvar proof-marker nil - "You are not authorised for this information.") - -(defvar proof-shell-buffer nil - "You are not authorised for this information.") - -(defvar proof-script-buffer nil - "You are not authorised for this information.") - -(defvar proof-pbp-buffer nil - "You are not authorised for this information.") - -(defvar proof-shell-busy nil - "You are not authorised for this information.") - -(deflocal proof-buffer-type nil - "You are not authorised for this information.") - -(defvar proof-action-list nil "action list") - -(defvar proof-included-files-list nil - "Files currently included in proof process") - -(deflocal proof-active-buffer-fake-minor-mode nil - "An indication in the modeline that this is the *active* buffer") - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; A couple of small utilities ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun proof-define-keys (map kbl) - "Adds keybindings `kbl' in `map'. The argument `kbl' is a list of - tuples (k . f) where `k' is a keybinding (vector) and `f' the - designated function." - (mapcar - (lambda (kbl) - (let ((k (car kbl)) (f (cdr kbl))) - (define-key map k f))) - kbl)) - -(defun proof-string-to-list (s separator) - "converts strings `s' separated by the character `separator' to a - list of words" - (let ((end-of-word-occurence (string-match (concat separator "+") s))) - (if (not end-of-word-occurence) - (if (string= s "") - nil - (list s)) - (cons (substring s 0 end-of-word-occurence) - (proof-string-to-list - (substring s - (string-match (concat "[^" separator "]") - s end-of-word-occurence)) separator))))) - -;; FIXME: this doesn't belong here (and shouldn't be called w3-* !!) -(defun w3-remove-file-name (address) - "remove the file name in a World Wide Web address" - (string-match "://[^/]+/" address) - (concat (substring address 0 (match-end 0)) - (file-name-directory (substring address (match-end 0))))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Basic code for the locked region and the queue region ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defvar proof-locked-hwm nil - "Upper limit of the locked region") - -(defvar proof-queue-loose-end nil - "Limit of the queue region that is not equal to proof-locked-hwm.") - -(defvar proof-locked-span nil - "Upper limit of the locked region") - -(defvar proof-queue-span nil - "Upper limit of the locked region") - -(make-variable-buffer-local 'proof-locked-span) -(make-variable-buffer-local 'proof-queue-span) - -(defun proof-init-segmentation () - (setq proof-queue-loose-end nil) - (if (not proof-queue-span) - (setq proof-queue-span (make-span 1 1))) - (set-span-property proof-queue-span 'start-closed t) - (set-span-property proof-queue-span 'end-open t) - (span-read-only proof-queue-span) - - (make-face 'proof-queue-face) - ;; Whether display has color or not - (cond ((and (fboundp 'device-class) - (eq (device-class (frame-device)) 'color)) - (set-face-background 'proof-queue-face "mistyrose")) - ((and (fboundp 'x-display-color-p) (x-display-color-p)) - (set-face-background 'proof-queue-face "mistyrose")) - (t (progn - (set-face-background 'proof-queue-face "Black") - (set-face-foreground 'proof-queue-face "White")))) - (set-span-property proof-queue-span 'face 'proof-queue-face) - - (detach-span proof-queue-span) - - (setq proof-locked-hwm nil) - (if (not proof-locked-span) - (setq proof-locked-span (make-span 1 1))) - (set-span-property proof-locked-span 'start-closed t) - (set-span-property proof-locked-span 'end-open t) - (span-read-only proof-locked-span) - - (make-face 'proof-locked-face) - ;; Whether display has color or not - (cond ((and (fboundp 'device-class) - (eq (device-class (frame-device)) 'color)) - (set-face-background 'proof-locked-face "lavender")) - ((and (fboundp 'x-display-color-p) (x-display-color-p)) - (set-face-background 'proof-locked-face "lavender")) - (t (set-face-property 'proof-locked-face 'underline t))) - (set-span-property proof-locked-span 'face 'proof-locked-face) - - (detach-span proof-locked-span)) - -(defsubst proof-lock-unlocked () - (span-read-only proof-locked-span)) - -(defsubst proof-unlock-locked () - (span-read-write proof-locked-span)) - -(defsubst proof-set-queue-endpoints (start end) - (set-span-endpoints proof-queue-span start end)) - -(defsubst proof-set-locked-endpoints (start end) - (set-span-endpoints proof-locked-span start end)) - -(defsubst proof-detach-queue () - (and proof-queue-span (detach-span proof-queue-span))) - -(defsubst proof-detach-locked () - (and proof-locked-span (detach-span proof-locked-span))) - -(defsubst proof-set-queue-start (start) - (set-span-endpoints proof-queue-span start (span-end proof-queue-span))) - -(defsubst proof-set-queue-end (end) - (set-span-endpoints proof-queue-span (span-start proof-queue-span) end)) - -(defun proof-detach-segments () - (proof-detach-queue) - (proof-detach-locked)) - -(defsubst proof-set-locked-end (end) - (if (>= (point-min) end) - (proof-detach-locked) - (set-span-endpoints proof-locked-span (point-min) end))) - -(defun proof-unprocessed-begin () - "proof-unprocessed-begin returns end of locked region in script - buffer and point-min otherwise." - (or - (and (eq proof-script-buffer (current-buffer)) - proof-locked-span (span-end proof-locked-span)) - (point-min))) - -(defun proof-locked-end () - "proof-locked-end returns the end of the locked region. It should - only be called if we're in the scripting buffer." - (if (eq proof-script-buffer (current-buffer)) - (proof-unprocessed-begin) - (error "bug: proof-locked-end called from wrong buffer"))) - -(defsubst proof-end-of-queue () - (and proof-queue-span (span-end proof-queue-span))) - -(defun proof-dont-show-annotations () - "This sets the display values of the annotations used to - communicate with the proof assistant so that they don't show up on - the screen." - (let ((disp (make-display-table)) - (i 128)) - (while (< i 256) - (aset disp i []) - (incf i)) - (cond ((fboundp 'add-spec-to-specifier) - (add-spec-to-specifier current-display-table disp - (current-buffer))) - ((boundp 'buffer-display-table) - (setq buffer-display-table disp))))) - -;;; in case Emacs is not aware of read-shell-command-map - -(defvar read-shell-command-map - (let ((map (make-sparse-keymap))) - (if (not (fboundp 'set-keymap-parents)) - (setq map (append minibuffer-local-map map)) - (set-keymap-parents map minibuffer-local-map) - (set-keymap-name map 'read-shell-command-map)) - (define-key map "\t" 'comint-dynamic-complete) - (define-key map "\M-\t" 'comint-dynamic-complete) - (define-key map "\M-?" 'comint-dynamic-list-completions) - map) - "Minibuffer keymap used by shell-command and related commands.") - - -;;; in case Emacs is not aware of the function read-shell-command -(or (fboundp 'read-shell-command) - ;; from minibuf.el distributed with XEmacs 19.11 - (defun read-shell-command (prompt &optional initial-input history) - "Just like read-string, but uses read-shell-command-map: -\\{read-shell-command-map}" - (let ((minibuffer-completion-table nil)) - (read-from-minibuffer prompt initial-input read-shell-command-map - nil (or history - 'shell-command-history))))) - -;; The package fume-func provides a function with the same name and -;; specification. However, fume-func's version is incorrect. -(and (fboundp 'fume-match-find-next-function-name) -(defun fume-match-find-next-function-name (buffer) - "General next function name in BUFFER finder using match. - The regexp is assumed to be a two item list the car of which is the regexp - to use, and the cdr of which is the match position of the function name" - (set-buffer buffer) - (let ((r (car fume-function-name-regexp)) - (p (cdr fume-function-name-regexp))) - (and (re-search-forward r nil t) - (cons (buffer-substring (setq p (match-beginning p)) (point)) p))))) - -(defun proof-goto-end-of-locked-interactive () - "Jump to the end of the locked region." - (interactive) - (switch-to-buffer proof-script-buffer) - (goto-char (proof-locked-end))) - -(defun proof-goto-end-of-locked () - "Jump to the end of the locked region." - (goto-char (proof-locked-end))) - -(defun proof-goto-end-of-locked-if-pos-not-visible-in-window () - "If the end of the locked region is not visible, jump to the end of - the locked region." - (interactive) - (let ((pos (save-excursion - (set-buffer proof-script-buffer) - (proof-locked-end)))) - (or (pos-visible-in-window-p pos (get-buffer-window - proof-script-buffer t)) - (proof-goto-end-of-locked-interactive)))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Starting and stopping the proof-system shell ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun proof-shell-live-buffer () - (and proof-shell-buffer - (comint-check-proc proof-shell-buffer) - proof-shell-buffer)) - -(defun proof-start-shell () - (if (proof-shell-live-buffer) - () - (run-hooks 'proof-pre-shell-start-hook) - (setq proof-included-files-list nil) - (if proof-prog-name-ask-p - (save-excursion - (setq proof-prog-name (read-shell-command "Run process: " - proof-prog-name)))) - (let ((proc - (concat "Inferior " - (substring proof-prog-name - (string-match "[^/]*$" proof-prog-name))))) - (while (get-buffer (concat "*" proc "*")) - (if (string= (substring proc -1) ">") - (aset proc (- (length proc) 2) - (+ 1 (aref proc (- (length proc) 2)))) - (setq proc (concat proc "<2>")))) - - (message (format "Starting %s process..." proc)) - - ;; Starting the inferior process (asynchronous) - (let ((prog-name-list (proof-string-to-list proof-prog-name " "))) - (apply 'make-comint (append (list proc (car prog-name-list) nil) - (cdr prog-name-list)))) - ;; To send any initialisation commands to the inferior process, - ;; consult proof-shell-config-done... - - (setq proof-shell-buffer (get-buffer (concat "*" proc "*"))) - (setq proof-pbp-buffer (get-buffer-create (concat "*" proc "-goals*"))) - - (save-excursion - (set-buffer proof-shell-buffer) - (funcall proof-mode-for-shell) - (set-buffer proof-pbp-buffer) - (funcall proof-mode-for-pbp)) - - (setq proof-script-buffer (current-buffer)) - (proof-init-segmentation) - (setq proof-active-buffer-fake-minor-mode t) - - (if (fboundp 'redraw-modeline) - (redraw-modeline) - (force-mode-line-update)) - - (or (assq 'proof-active-buffer-fake-minor-mode minor-mode-alist) - (setq minor-mode-alist - (append minor-mode-alist - (list '(proof-active-buffer-fake-minor-mode - " Scripting"))))) - - (message - (format "Starting %s process... done." proc))))) - - -(defun proof-stop-shell () - "Exit the PROOF process - - Runs proof-shell-exit-hook if non nil" - - (interactive) - (save-excursion - (let ((buffer (proof-shell-live-buffer)) (proc)) - (if buffer - (progn - (save-excursion - (set-buffer buffer) - (setq proc (process-name (get-buffer-process))) - (comint-send-eof) - (save-excursion - (set-buffer proof-script-buffer) - (proof-detach-segments)) - (kill-buffer)) - (run-hooks 'proof-shell-exit-hook) - - ;;it is important that the hooks are - ;;run after the buffer has been killed. In the reverse - ;;order e.g., intall-shell-fonts causes problems and it - ;;is impossible to restart the PROOF shell - - (message (format "%s process terminated." proc))))))) - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Proof by pointing ;; -;; All very lego-specific at present ;; -;; To make sense of this code, you should read the ;; -;; relevant LFCS tech report by tms, yb, and djs ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - -(defvar pbp-goal-command nil - "Command informing the prover that `pbp-button-action' has been - requested on a goal.") - -(defvar pbp-hyp-command nil - "Command informing the prover that `pbp-button-action' has been - requested on an assumption.") - -(defun pbp-button-action (event) - (interactive "e") - (mouse-set-point event) - (pbp-construct-command)) - -; Using the spans in a mouse behavior is quite simple: from the -; mouse position, find the relevant span, then get its annotation -; and produce a piece of text that will be inserted in the right -; buffer. - -(defun proof-expand-path (string) - (let ((a 0) (l (length string)) ls) - (while (< a l) - (setq ls (cons (int-to-string (aref string a)) - (cons " " ls))) - (incf a)) - (apply 'concat (nreverse ls)))) - -(defun proof-send-span (event) - (interactive "e") - (let* ((span (span-at (mouse-set-point event) 'type)) - (str (span-property span 'cmd))) - (cond ((and (eq proof-script-buffer (current-buffer)) (not (null span))) - (proof-goto-end-of-locked) - (cond ((eq (span-property span 'type) 'vanilla) - (insert str))))))) - -(defun pbp-construct-command () - (let* ((span (span-at (point) 'proof)) - (top-span (span-at (point) 'proof-top-element)) - top-info) - (if (null top-span) () - (setq top-info (span-property top-span 'proof-top-element)) - (pop-to-buffer proof-script-buffer) - (cond - (span - (proof-invisible-command - (format (if (eq 'hyp (car top-info)) pbp-hyp-command - pbp-goal-command) - (concat (cdr top-info) (proof-expand-path - (span-property span 'proof)))))) - ((eq (car top-info) 'hyp) - (proof-invisible-command (format pbp-hyp-command (cdr top-info)))) - (t - (proof-insert-pbp-command (format pbp-change-goal (cdr top-info)))))) - )) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Turning annotated output into pbp goal set ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defvar proof-shell-first-special-char nil "where the specials start") -(defvar proof-shell-goal-char nil "goal mark") -(defvar proof-shell-start-char nil "annotation start") -(defvar proof-shell-end-char nil "annotation end") -(defvar proof-shell-field-char nil "annotated field end") -(defvar proof-shell-eager-annotation-start nil "eager ann. field start") -(defvar proof-shell-eager-annotation-end nil "eager ann. field end") - -(defvar proof-shell-assumption-regexp nil - "A regular expression matching the name of assumptions.") - -;; FIXME: da: where is this variable used? -;; dropped in favour of goal-char? -(defvar proof-shell-goal-regexp nil - "A regular expressin matching the identifier of a goal.") - -(defvar proof-shell-noise-regexp nil - "Unwanted information output from the proof process within - `proof-start-goals-regexp' and `proof-end-goals-regexp'.") - -(defun pbp-make-top-span (start end) - (let (span name) - (goto-char start) - ;; FIXME: why name? This is a character function - (setq name (funcall proof-goal-hyp-fn)) - (beginning-of-line) - (setq start (point)) - (goto-char end) - (beginning-of-line) - (backward-char) - (setq span (make-span start (point))) - (set-span-property span 'mouse-face 'highlight) - (set-span-property span 'proof-top-element name))) - - -;; Need this for processing error strings and so forth - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; The filter. First some functions that handle those few ;; -;; occasions when the glorious illusion that is script-management ;; -;; is temporarily suspended ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; Output from the proof process is handled lazily, so that only -;; the output from the last of multiple commands is actually -;; processed (assuming they're all successful) - -(defvar proof-shell-delayed-output nil - "The last interesting output the proof process output, and what to do - with it.") - -(defvar proof-analyse-using-stack nil - "Are annotations sent by proof assistant local or global") - -;; FIXME: da: what's magical value 128 below? should be in defconst? -(defun proof-shell-analyse-structure (string) - (save-excursion - (let* ((ip 0) (op 0) ap (l (length string)) - (ann (make-string (length string) ?x)) - (stack ()) (topl ()) - (out (make-string l ?x)) c span) - (while (< ip l) - (if (< (setq c (aref string ip)) 128) - (progn (aset out op c) - (incf op))) - (incf ip)) - (display-buffer (set-buffer proof-pbp-buffer)) - (erase-buffer) - (insert (substring out 0 op)) - - (setq ip 0 - op 1) - (while (< ip l) - (setq c (aref string ip)) - (cond - ((= c proof-shell-goal-char) - (setq topl (cons op topl)) - (setq ap 0)) - ((= c proof-shell-start-char) - (if proof-analyse-using-stack - (setq ap (- ap (- (aref string (incf ip)) 128))) - (setq ap (- (aref string (incf ip)) 128))) - (incf ip) - (while (not (= (setq c (aref string ip)) proof-shell-end-char)) - (aset ann ap (- c 128)) - (incf ap) - (incf ip)) - (setq stack (cons op (cons (substring ann 0 ap) stack)))) - ((= c proof-shell-field-char) - (setq span (make-span (car stack) op)) - (set-span-property span 'mouse-face 'highlight) - (set-span-property span 'proof (car (cdr stack))) - ;; Pop annotation off stack - (and proof-analyse-using-stack - (progn - (setq ap 0) - (while (< ap (length (cadr stack))) - (aset ann ap (aref (cadr stack) ap)) - (incf ap)))) - ;; Finish popping annotations - (setq stack (cdr (cdr stack)))) - (t (incf op))) - (incf ip)) - (setq topl (reverse (cons (point-max) topl))) - ;; If we want Coq pbp: (setq coq-current-goal 1) - (while (setq ip (car topl) - topl (cdr topl)) - (pbp-make-top-span ip (car topl)))))) - -(defun proof-shell-strip-annotations (string) - (let* ((ip 0) (op 0) (l (length string)) (out (make-string l ?x ))) - (while (< ip l) - (if (>= (aref string ip) proof-shell-first-special-char) - (if (char-equal (aref string ip) proof-shell-start-char) - (progn (incf ip) - (while (< (aref string ip) proof-shell-first-special-char) - (incf ip)))) - (aset out op (aref string ip)) - (incf op)) - (incf ip)) - (substring out 0 op))) - -(defun proof-shell-handle-delayed-output () - (let ((ins (car proof-shell-delayed-output)) - (str (cdr proof-shell-delayed-output))) - (display-buffer proof-pbp-buffer) - (save-excursion - (cond - ((eq ins 'insert) - (setq str (proof-shell-strip-annotations str)) - (set-buffer proof-pbp-buffer) - (erase-buffer) - (insert str)) - ((eq ins 'analyse) - (proof-shell-analyse-structure str)) - (t (set-buffer proof-pbp-buffer) - (insert "\n\nbug???"))))) - (run-hooks 'proof-shell-handle-delayed-output-hook) - (setq proof-shell-delayed-output (cons 'insert "done"))) - -(defun proof-shell-handle-error (cmd string) - (save-excursion - (display-buffer (set-buffer proof-pbp-buffer)) - (if (not (eq proof-shell-delayed-output (cons 'insert "done"))) - (progn - (set-buffer proof-pbp-buffer) - (erase-buffer) - (insert (proof-shell-strip-annotations - (cdr proof-shell-delayed-output))))) - (goto-char (point-max)) - (if (re-search-backward pbp-error-regexp nil t) - (delete-region (- (point) 2) (point-max))) - (newline 2) - (insert-string string) - (beep)) - (set-buffer proof-script-buffer) - (proof-detach-queue) - (delete-spans (proof-locked-end) (point-max) 'type) - (proof-release-lock) - (run-hooks 'proof-shell-handle-error-hook)) - -(defun proof-shell-handle-interrupt () - (save-excursion - (display-buffer (set-buffer proof-pbp-buffer)) - (goto-char (point-max)) - (newline 2) - (insert-string - "Interrupt: Script Management may be in an inconsistent state\n") - (beep)) - (set-buffer proof-script-buffer) - (if proof-shell-busy - (progn (proof-detach-queue) - (delete-spans (proof-locked-end) (point-max) 'type) - (proof-release-lock)))) - - -(defun proof-goals-pos (span maparg) - "Given a span, this function returns the start of it if corresponds - to a goal and nil otherwise." - (and (eq 'goal (car (span-property span 'proof-top-element))) - (span-start span))) - -(defun proof-pbp-focus-on-first-goal () - "If the `proof-pbp-buffer' contains goals, the first one is brought - into view." - (and (fboundp 'map-extents) - (let - ((pos (map-extents 'proof-goals-pos proof-pbp-buffer - nil nil nil nil 'proof-top-element))) - (and pos (set-window-point - (get-buffer-window proof-pbp-buffer t) pos))))) - - - -(defun proof-shell-process-output (cmd string) - "Deals with errors, start of proofs, abortions of proofs and - completions of proofs. All other output from the proof engine is - simply reported to the user in the RESPONSE buffer. To extend this - function, set `proof-shell-process-output-system-specific'. - - The basic output processing function - it can return one of 4 - things: 'error, 'interrupt, 'loopback, or nil. 'loopback means this - was output from pbp, and should be inserted into the script buffer - and sent back to the proof assistant." - (cond - ((string-match proof-shell-error-regexp string) - (cons 'error (proof-shell-strip-annotations - (substring string (match-beginning 0))))) - - ((string-match proof-shell-interrupt-regexp string) - 'interrupt) - - ((and proof-shell-abort-goal-regexp - (string-match proof-shell-abort-goal-regexp string)) - (setq proof-shell-delayed-output (cons 'insert "\n\nAborted")) - ()) - - ((string-match proof-shell-proof-completed-regexp string) - (setq proof-shell-delayed-output - (cons 'insert (concat "\n" (match-string 0 string))))) - - ((string-match proof-shell-start-goals-regexp string) - (let (start end) - (while (progn (setq start (match-end 0)) - (string-match proof-shell-start-goals-regexp - string start))) - (setq end (string-match proof-shell-end-goals-regexp string start)) - (setq proof-shell-delayed-output - (cons 'analyse (substring string start end))))) - - ((string-match proof-shell-result-start string) - (let (start end) - (setq start (+ 1 (match-end 0))) - (string-match proof-shell-result-end string) - (setq end (- (match-beginning 0) 1)) - (cons 'loopback (substring string start end)))) - - ;; hook to tailor proof-shell-process-output to a specific proof - ;; system - ((and proof-shell-process-output-system-specific - (funcall (car proof-shell-process-output-system-specific) - cmd string)) - (funcall (cdr proof-shell-process-output-system-specific) - cmd string)) - - (t (setq proof-shell-delayed-output (cons 'insert string))))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Low-level commands for shell communication ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun proof-shell-insert (string) - (set-buffer proof-shell-buffer) - (goto-char (point-max)) - - (run-hooks 'proof-shell-insert-hook) - (insert string) - - ;; xemacs and emacs19 have different semantics for what happens when - ;; shell input is sent next to a marker - ;; the following code accommodates both definitions - (if (marker-position proof-marker) - (let ((inserted (point))) - (comint-send-input) - (set-marker proof-marker inserted)) - (comint-send-input))) - -(defun proof-send (string) - (let ((l (length string)) (i 0)) - (while (< i l) - (if (= (aref string i) ?\n) (aset string i ?\ )) - (incf i))) - (save-excursion (proof-shell-insert string))) - -;; Note that this is not really intended for anything complicated - -;; just to stop the user accidentally sending a command while the -;; queue is running. -(defun proof-check-process-available (&optional relaxed) - "Checks - (1) Is a proof process running? - (2) Is the proof process idle? - (3) Does the current buffer own the proof process? - (4) Is the current buffer a proof script? - and signals an error if at least one of the conditions is not - fulfilled. If relaxed is set, only (1) and (2) are tested." - (if (proof-shell-live-buffer) - (cond - (proof-shell-busy (error "Proof Process Busy!")) - (relaxed ()) ;exit cond - ((not (eq proof-script-buffer (current-buffer))) - (error "Don't own proof process")))) - (if (not (or relaxed (eq proof-buffer-type 'script))) - (error "Must be running in a script buffer"))) - -(defun proof-grab-lock (&optional relaxed) - (proof-start-shell) - (proof-check-process-available relaxed) - (setq proof-shell-busy t)) - -(defun proof-release-lock () - (if (proof-shell-live-buffer) - (progn - (if (not proof-shell-busy) - (error "Bug: Proof process not busy")) - (if (not (eq proof-script-buffer (current-buffer))) - (error "Bug: Don't own process")) - (setq proof-shell-busy nil)))) - -; Pass start and end as nil if the cmd isn't in the buffer. - -(defun proof-start-queue (start end alist &optional relaxed) - (if start - (proof-set-queue-endpoints start end)) - (let (item) - (while (and alist (string= - (nth 1 (setq item (car alist))) - "COMMENT")) - (funcall (nth 2 item) (car item)) - (setq alist (cdr alist))) - (if alist - (progn - (proof-grab-lock relaxed) - (setq proof-shell-delayed-output (cons 'insert "Done.")) - (setq proof-action-list alist) - (proof-send (nth 1 item)))))) - -; returns t if it's run out of input - -(defun proof-shell-exec-loop () - (save-excursion - (set-buffer proof-script-buffer) - (if (null proof-action-list) (error "Non Sequitur")) - (let ((item (car proof-action-list))) - (funcall (nth 2 item) (car item)) - (setq proof-action-list (cdr proof-action-list)) - (while (and proof-action-list - (string= - (nth 1 (setq item (car proof-action-list))) - "COMMENT")) - (funcall (nth 2 item) (car item)) - (setq proof-action-list (cdr proof-action-list))) - (if (null proof-action-list) - (progn (proof-release-lock) - (proof-detach-queue) - t) - (proof-send (nth 1 item)) - nil)))) - -(defun proof-shell-insert-loopback-cmd (cmd) - "Insert command sequence triggered by the proof process -at the end of locked region (after inserting a newline and indenting)." - (save-excursion - (set-buffer proof-script-buffer) - (let (span) - (proof-goto-end-of-locked) - (newline-and-indent) - (insert cmd) - (setq span (make-span (proof-locked-end) (point))) - (set-span-property span 'type 'pbp) - (set-span-property span 'cmd cmd) - (proof-set-queue-endpoints (proof-locked-end) (point)) - (setq proof-action-list - (cons (car proof-action-list) - (cons (list span cmd 'proof-done-advancing) - (cdr proof-action-list))))))) - -;; ******** NB ********** -;; While we're using pty communication, this code is OK, since all -;; eager annotations are one line long, and we get input a line at a -;; time. If we go over to piped communication, it will break. - -(defun proof-shell-popup-eager-annotation () - "Eager annotations are annotations which the proof system produces -while it's doing something (e.g. loading libraries) to say how much -progress it's made. Obviously we need to display these as soon as they -arrive." - (let (mrk str file module) - (save-excursion - (goto-char (point-max)) - (search-backward proof-shell-eager-annotation-start) - (setq mrk (+ 1 (point))) - (search-forward proof-shell-eager-annotation-end) - (setq str (buffer-substring mrk (- (point) 1))) - (display-buffer (set-buffer proof-pbp-buffer)) - (goto-char (point-max)) - (insert str "\n")) - (if (string-match "Creating mark \"\\(.*\\)\" \\[\\(.*\\)\\]" str) - (progn - (setq file (match-string 2 str) - module (match-string 1 str)) - (if (string= file "") - (setq file (buffer-file-name proof-script-buffer))) - (setq file (expand-file-name file)) - (if (string-match "\\(.*\\)\\.." file) - (setq file (match-string 1 file))) - (setq proof-included-files-list (cons (cons module file) - proof-included-files-list)))))) - -(defun proof-shell-filter (str) - "The filter for the shell-process. We sleep until we get a - wakeup-char in the input, then run proof-shell-process-output, and - set proof-marker to keep track of how far we've got." - (if (string-match proof-shell-eager-annotation-end str) - (proof-shell-popup-eager-annotation)) - (if (or - ;; Some proof systems can be hacked to have annotated prompts; - ;; for these we set proof-shell-wakeup-char to the annotation special. - (and proof-shell-wakeup-char - (string-match (char-to-string proof-shell-wakeup-char) str)) - ;; Others rely on a standard top-level (e.g. SML) whose prompt can't - ;; be hacked. For those we use the prompt regexp. - (string-match proof-shell-annotated-prompt-regexp str)) - (if (null (marker-position proof-marker)) - ;; Set marker to first prompt in output buffer, and sleep again. - (progn - (goto-char (point-min)) - (re-search-forward proof-shell-annotated-prompt-regexp) - ;; FIXME: da: why is this next line here? to delete the - ;; possibly several character prompt? why? - ;; TMS: Its purpose is to remove the wakeup - ;; character associated with the prompt. This - ;; should not be necessary anymore, because the wakeup - ;; character isn't displayed anyway; see - ;; `proof-dont-show-annotations'. Watch this space! - (backward-delete-char 1) - (set-marker proof-marker (point))) - ;; We've matched against a second prompt in str now. Search - ;; the output buffer for the second prompt after the one previously - ;; marked. - (let (string res cmd) - (goto-char (marker-position proof-marker)) - (re-search-forward proof-shell-annotated-prompt-regexp nil t) - (backward-char (- (match-end 0) (match-beginning 0))) - (setq string (buffer-substring (marker-position proof-marker) - (point))) - (goto-char (point-max)) ; da: assumed to be after a prompt? - (backward-delete-char 1) ; da: WHY? nasty assumption. - (setq cmd (nth 1 (car proof-action-list))) - (save-excursion - (setq res (proof-shell-process-output cmd string)) - (cond - ((and (consp res) (eq (car res) 'error)) - (proof-shell-handle-error cmd (cdr res))) - ((eq res 'interrupt) - (proof-shell-handle-interrupt)) - ((and (consp res) (eq (car res) 'loopback)) - (proof-shell-insert-loopback-cmd (cdr res)) - (proof-shell-exec-loop)) - (t (if (proof-shell-exec-loop) - (proof-shell-handle-delayed-output))))))))) - -(defun proof-last-goal-or-goalsave () - (save-excursion - (let ((span (span-at-before (proof-locked-end) 'type))) - (while (and span - (not (eq (span-property span 'type) 'goalsave)) - (or (eq (span-property span 'type) 'comment) - (not (funcall proof-goal-command-p - (span-property span 'cmd))))) - (setq span (prev-span span 'type))) - span))) - -;; This needs some work to make it generic, since most of the code -;; doesn't apply to Coq at all. -(defun proof-steal-process () - "This allows us to steal the process if we want to change the buffer - in which script management is running." - (proof-start-shell) - (if proof-shell-busy (error "Proof Process Busy!")) - (if (not (eq proof-buffer-type 'script)) - (error "Must be running in a script buffer")) - (cond - ((eq proof-script-buffer (current-buffer)) - nil) - (t - (let ((flist proof-included-files-list) - (file (expand-file-name (buffer-file-name))) span (cmd "")) - (if (string-match "\\(.*\\)\\.." file) (setq file (match-string 1 file))) - (while (and flist (not (string= file (cdr (car flist))))) - (setq flist (cdr flist))) - (if (null flist) - (if (not (y-or-n-p "Steal script management? " )) (error "Aborted")) - (if (not (y-or-n-p "Reprocess this file? " )) (error "Aborted"))) - (if (not (buffer-name proof-script-buffer)) - (message "Warning: Proof script buffer deleted: proof state may be inconsistent") - (save-excursion - (set-buffer proof-script-buffer) - (setq proof-active-buffer-fake-minor-mode nil) - (setq span (proof-last-goal-or-goalsave)) - ;; This won't work for Coq if we have recursive goals in progress - (if (and span (not (eq (span-property span 'type) 'goalsave))) - (setq cmd proof-kill-goal-command)) - (proof-detach-segments) - (delete-spans (point-min) (point-max) 'type))) - - (setq proof-script-buffer (current-buffer)) - (proof-init-segmentation) - (setq proof-active-buffer-fake-minor-mode t) - - (cond - (flist - (list nil (concat cmd "ForgetMark " (car (car flist)) ";") - `(lambda (span) (setq proof-included-files-list - (quote ,(cdr flist)))))) - ((not (string= cmd "")) - (list nil cmd 'proof-done-invisible)) - (t nil)))))) - -(defun proof-done-invisible (span) ()) - -(defun proof-invisible-command (cmd &optional relaxed) - "Send cmd to the proof process without responding to the user." - (proof-check-process-available relaxed) - (if (not (string-match proof-re-end-of-cmd cmd)) - (setq cmd (concat cmd proof-terminal-string))) - (proof-start-queue nil nil (list (list nil cmd - 'proof-done-invisible)) relaxed)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; User Commands ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; Script management uses two major segments: Locked, which marks text -; which has been sent to the proof assistant and cannot be altered -; without being retracted, and Queue, which contains stuff being -; queued for processing. proof-action-list contains a list of -; (span,command,action) triples. The loop looks like: Execute the -; command, and if it's successful, do action on span. If the -; command's not successful, we bounce the rest of the queue and do -; some error processing. -; -; when a span has been processed, we classify it as follows: -; 'goalsave - denoting a 'goalsave pair in the locked region -; a 'goalsave region has a 'name property which is the name of the goal -; 'comment - denoting a comment -; 'pbp - denoting a span created by pbp -; 'vanilla - denoting any other span. -; 'pbp & 'vanilla spans have a property 'cmd, which says what -; command they contain. - -; We don't allow commands while the queue has anything in it. So we -; do configuration by concatenating the config command on the front in -; proof-send - -;; proof-assert-until-point, and various gunk for its ;; -;; setup and callback ;; - -;; This code is for nested goals in Coq, and shouldn't affect things -;; in LEGO. It lifts "local" lemmas from inside goals out to top -;; level. - -(defun proof-lift-global (glob-span) - (let (start (next (span-at 1 'type)) str (goal-p nil)) - (while (and next (and (not (eq next glob-span)) (not goal-p))) - (if (and (eq (span-property next 'type) 'vanilla) - (funcall proof-goal-command-p (span-property next 'cmd))) - (setq goal-p t) - (setq next (next-span next 'type)))) - - (if (and next (not (eq next glob-span))) - (progn - (proof-unlock-locked) - (setq str (buffer-substring (span-start glob-span) - (span-end glob-span))) - (delete-region (span-start glob-span) (span-end glob-span)) - (goto-char (span-start next)) - (setq start (point)) - (insert str "\n") - (set-span-endpoints glob-span start (point)) - (set-span-start next (point)) - (proof-lock-unlocked))))) - -;; This is the actual callback for assert-until-point. - -(defun proof-done-advancing (span) - (let ((end (span-end span)) nam gspan next cmd) - (proof-set-locked-end end) - (proof-set-queue-start end) - (setq cmd (span-property span 'cmd)) - (cond - ((eq (span-property span 'type) 'comment) - (set-span-property span 'mouse-face 'highlight)) - ((string-match proof-save-command-regexp cmd) - ;; In coq, we have the invariant that if we've done a save and - ;; there's a top-level declaration then it must be the - ;; associated goal. (Notice that because it's a callback it - ;; must have been approved by the theorem prover.) - (if (string-match proof-save-with-hole-regexp cmd) - (setq nam (match-string 2 cmd))) - (setq gspan span) - (while (or (eq (span-property gspan 'type) 'comment) - (not (funcall proof-goal-command-p - (setq cmd (span-property gspan 'cmd))))) - (setq next (prev-span gspan 'type)) - (delete-span gspan) - (setq gspan next)) - - (if (null nam) - (if (string-match proof-goal-with-hole-regexp - (span-property gspan 'cmd)) - (setq nam (match-string 2 (span-property gspan 'cmd))) - ;; This only works for Coq, but LEGO raises an error if - ;; there's no name. - ;; FIXME: a nonsense for Isabelle. - (setq nam "Unnamed_thm"))) - - (set-span-end gspan end) - (set-span-property gspan 'mouse-face 'highlight) - (set-span-property gspan 'type 'goalsave) - (set-span-property gspan 'name nam) - - (proof-lift-global gspan)) - (t - (set-span-property span 'mouse-face 'highlight) - (if (funcall proof-global-p cmd) - (proof-lift-global span)))))) - -; depth marks number of nested comments. quote-parity is false if -; we're inside ""'s. Only one of (depth > 0) and (not quote-parity) -; should be true at once. -- hhg - -(defun proof-segment-up-to (pos) - "Create a list of (type,int,string) pairs from the end of the locked -region to pos, denoting the command and the position of its -terminator. type is one of comment, or cmd. 'unclosed-comment may be -consed onto the start if the segment finishes with an unclosed -comment." - (save-excursion - (let ((str (make-string (- (buffer-size) (proof-locked-end) -10) ?x)) - (i 0) (depth 0) (quote-parity t) done alist c) - (proof-goto-end-of-locked) - (while (not done) - (cond - ((and (= (point) pos) (> depth 0)) - (setq done t alist (cons 'unclosed-comment alist))) - ((= (point) (point-max)) - (if (not quote-parity) - (message "Warning: unclosed quote")) - (setq done t)) - ((and (looking-at "\\*)") quote-parity) - (if (= depth 0) - (progn (message "Warning: extraneous comment end") (setq done t)) - (setq depth (- depth 1)) (forward-char 2) - (if (eq i 0) - (setq alist (cons (list 'comment "" (point)) alist)) - (aset str i ?\ ) (incf i)))) - ((and (looking-at "(\\*") quote-parity) - (setq depth (+ depth 1)) (forward-char 2)) - ((> depth 0) (forward-char)) - (t - (setq c (char-after (point))) - (if (or (> i 0) (not (= (char-syntax c) ?\ ))) - (progn (aset str i c) (incf i))) - (if (looking-at "\"") - (setq quote-parity (not quote-parity))) - (forward-char) - (if (and (= c proof-terminal-char) quote-parity) - (progn - (setq alist - (cons (list 'cmd (substring str 0 i) (point)) alist)) - (if (>= (point) pos) (setq done t) (setq i 0))))))) - alist))) - -(defun proof-semis-to-vanillas (semis &optional callback-fn) - "Convert a sequence of semicolon positions (returned by the above -function) to a set of vanilla extents." - (let ((ct (proof-locked-end)) span alist semi) - (while (not (null semis)) - (setq semi (car semis) - span (make-span ct (nth 2 semi)) - ct (nth 2 semi)) - (if (eq (car (car semis)) 'cmd) - (progn - (set-span-property span 'type 'vanilla) - (set-span-property span 'cmd (nth 1 semi)) - (setq alist (cons (list span (nth 1 semi) - (or callback-fn 'proof-done-advancing)) - alist))) - (set-span-property span 'type 'comment) - (setq alist (cons (list span "COMMENT" 'proof-done-advancing) alist))) - (setq semis (cdr semis))) - (nreverse alist))) - -; Assert until point - We actually use this to implement the -; assert-until-point, active terminator keypress, and find-next-terminator. -; In different cases we want different things, but usually the information -; (i.e. are we inside a comment) isn't available until we've actually run -; proof-segment-up-to (point), hence all the different options when we've -; done so. - -(defun proof-assert-until-point - (&optional unclosed-comment-fun ignore-proof-process-p) - "Process the region from the end of the locked-region until point. - Default action if inside a comment is just to go until the start of - the comment. If you want something different, put it inside - unclosed-comment-fun. If ignore-proof-process-p is set, no commands - will be added to the queue." - (interactive) - (let ((pt (point)) - (crowbar (or ignore-proof-process-p (proof-steal-process))) - semis) - (save-excursion - (if (not (re-search-backward "\\S-" (proof-locked-end) t)) - (progn (goto-char pt) - (error "Nothing to do!"))) - (setq semis (proof-segment-up-to (point)))) - (if (and unclosed-comment-fun (eq 'unclosed-comment (car semis))) - (funcall unclosed-comment-fun) - (if (eq 'unclosed-comment (car semis)) (setq semis (cdr semis))) - (if (and (not ignore-proof-process-p) (not crowbar) (null semis)) - (error "Nothing to do!")) - (goto-char (nth 2 (car semis))) - (and (not ignore-proof-process-p) - (let ((vanillas (proof-semis-to-vanillas (nreverse semis)))) - (if crowbar (setq vanillas (cons crowbar vanillas))) - (proof-start-queue (proof-locked-end) (point) vanillas)))))) - -;; insert-pbp-command - an advancing command, for use when ;; -;; PbpHyp or Pbp has executed in LEGO, and returned a ;; -;; command for us to run ;; - -(defun proof-insert-pbp-command (cmd) - (proof-check-process-available) - (let (span) - (proof-goto-end-of-locked) - (insert cmd) - (setq span (make-span (proof-locked-end) (point))) - (set-span-property span 'type 'pbp) - (set-span-property span 'cmd cmd) - (proof-start-queue (proof-locked-end) (point) - (list (list span cmd 'proof-done-advancing))))) - - -;; proof-retract-until-point and associated gunk ;; -;; most of the hard work (i.e computing the commands to do ;; -;; the retraction) is implemented in the customisation ;; -;; module (lego.el or coq.el) which is why this looks so ;; -;; straightforward ;; - - -(defun proof-done-retracting (span) - "Updates display after proof process has reset its state. See also -the documentation for `proof-retract-until-point'. It optionally -deletes the region corresponding to the proof sequence." - (let ((start (span-start span)) - (end (span-end span)) - (kill (span-property span 'delete-me))) - (proof-set-locked-end start) - (proof-set-queue-end start) - (delete-spans start end 'type) - (delete-span span) - (if kill (delete-region start end)))) - -(defun proof-setup-retract-action (start end proof-command delete-region) - (let ((span (make-span start end))) - (set-span-property span 'delete-me delete-region) - (list (list span proof-command 'proof-done-retracting)))) - -(defun proof-retract-target (target delete-region) - (let ((end (proof-locked-end)) - (start (span-start target)) - (span (proof-last-goal-or-goalsave)) - actions) - - (if (and span (not (eq (span-property span 'type) 'goalsave))) - (if (< (span-end span) (span-end target)) - (progn - (setq span target) - (while (and span (eq (span-property span 'type) 'comment)) - (setq span (next-span span 'type))) - (setq actions (proof-setup-retract-action - start end - (if (null span) "COMMENT" - (funcall proof-count-undos-fn span)) - delete-region) - end start)) - - (setq actions (proof-setup-retract-action (span-start span) end - proof-kill-goal-command - delete-region) - end (span-start span)))) - - (if (> end start) - (setq actions - (nconc actions (proof-setup-retract-action - start end - (funcall proof-find-and-forget-fn target) - delete-region)))) - - (proof-start-queue (min start end) (proof-locked-end) actions))) - -(defun proof-retract-until-point (&optional delete-region) - "Sets up the proof process for retracting until point. In - particular, it sets a flag for the filter process to call - `proof-done-retracting' after the proof process has actually - successfully reset its state. It optionally deletes the region in - the proof script corresponding to the proof command sequence. If - this function is invoked outside a locked region, the last - successfully processed command is undone." - (interactive) - (proof-check-process-available) - (let ((span (span-at (point) 'type))) - (if (null (proof-locked-end)) (error "No locked region")) - (and (null span) - (progn (proof-goto-end-of-locked) (backward-char) - (setq span (span-at (point) 'type)))) - (proof-retract-target span delete-region))) - -;; proof-try-command ;; -;; this isn't really in the spirit of script management, ;; -;; but sometimes the user wants to just try an expression ;; -;; without having to undo it in order to try something ;; -;; different. Of course you can easily lose sync by doing ;; -;; something here which changes the proof state ;; - -(defun proof-done-trying (span) - (delete-span span) - (proof-detach-queue)) - -(defun proof-try-command - (&optional unclosed-comment-fun) - - "Process the command at point, - but don't add it to the locked region. This will only happen if - the command satisfies proof-state-preserving-p. - - Default action if inside a comment is just to go until the start of - the comment. If you want something different, put it inside - unclosed-comment-fun." - (interactive) - (let ((pt (point)) semis crowbar test) - (setq crowbar (proof-steal-process)) - (save-excursion - (if (not (re-search-backward "\\S-" (proof-locked-end) t)) - (progn (goto-char pt) - (error "Nothing to do!"))) - (setq semis (proof-segment-up-to (point)))) - (if (and unclosed-comment-fun (eq 'unclosed-comment (car semis))) - (funcall unclosed-comment-fun) - (if (eq 'unclosed-comment (car semis)) (setq semis (cdr semis))) - (if (and (not crowbar) (null semis)) (error "Nothing to do!")) - (setq test (car semis)) - (if (not (funcall proof-state-preserving-p (nth 1 test))) - (error "Command is not state preserving")) - (goto-char (nth 2 test)) - (let ((vanillas (proof-semis-to-vanillas (list test) - 'proof-done-trying))) - (if crowbar (setq vanillas (cons crowbar vanillas))) - (proof-start-queue (proof-locked-end) (point) vanillas))))) - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; misc other user functions ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - -(defun proof-undo-last-successful-command () - "Undo last successful command, both in the buffer recording the - proof script and in the proof process. In particular, it deletes - the corresponding part of the proof script." - (interactive) - (goto-char (span-start (span-at-before (proof-locked-end) 'type))) - (proof-retract-until-point t)) - -(defun proof-interrupt-process () - (interactive) - (if (not (proof-shell-live-buffer)) - (error "Proof Process Not Started!")) - (if (not (eq proof-script-buffer (current-buffer))) - (error "Don't own process!")) - (if (not proof-shell-busy) - (error "Proof Process Not Active!")) - (save-excursion - (set-buffer proof-shell-buffer) - (comint-interrupt-subjob))) - - -(defun proof-find-next-terminator () - "Set point after next `proof-terminal-char'." - (interactive) - (let ((cmd (span-at (point) 'type))) - (if cmd (goto-char (span-end cmd)) - (and (re-search-forward "\\S-" nil t) - (proof-assert-until-point nil 'ignore-proof-process))))) - -(defun proof-process-buffer () - "Process the current buffer and set point at the end of the buffer." - (interactive) - (end-of-buffer) - (proof-assert-until-point)) - -;; For when things go horribly wrong - -(defun proof-restart-script () - (interactive) - (save-excursion - (if (buffer-live-p proof-script-buffer) - (progn - (set-buffer proof-script-buffer) - (setq proof-active-buffer-fake-minor-mode nil) - (delete-spans (point-min) (point-max) 'type) - (proof-detach-segments))) - (setq proof-shell-busy nil - proof-script-buffer nil) - (if (buffer-live-p proof-shell-buffer) - (kill-buffer proof-shell-buffer)) - (if (buffer-live-p proof-pbp-buffer) - (kill-buffer proof-pbp-buffer)))) - -;; A command for making things go horribly wrong - it moves the -;; end-of-locked-region marker backwards, so user had better move it -;; correctly to sync with the proof state, or things will go all -;; pear-shaped. - -(defun proof-frob-locked-end () - (interactive) - "Move the end of the locked region backwards. - Only for use by consenting adults." - (cond - ((not (eq proof-script-buffer (current-buffer))) - (error "Not in proof buffer")) - ((> (point) (proof-locked-end)) - (error "Can only move backwards")) - (t (proof-set-locked-end (point)) - (delete-spans (proof-locked-end) (point-max) 'type)))) - -(defvar proof-minibuffer-history nil - "The last command read from the minibuffer") - -(defun proof-execute-minibuffer-cmd () - (interactive) - (let (cmd) - (proof-check-process-available 'relaxed) - (setq cmd (read-string "Command: " nil 'proof-minibuffer-history)) - (proof-invisible-command cmd 'relaxed))) - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Popup and Pulldown Menu ;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; Menu commands for the underlying proof assistant -(defvar proof-ctxt-string "" - "Command to display context in proof assistant") - -(defvar proof-help-string "" - "Command to ask for help in proof assistant") - -(defvar proof-prf-string "" - "Command to display proof state in proof assistant") - -(defun proof-ctxt () - "List context." - (interactive) - (proof-invisible-command (concat proof-ctxt-string proof-terminal-string))) - -(defun proof-help () - "Print help message giving syntax." - (interactive) - (proof-invisible-command (concat proof-help-string proof-terminal-string))) - -(defun proof-prf () - "List proof state." - (interactive) - (proof-invisible-command (concat proof-prf-string proof-terminal-string))) - -;;; To be called from menu -(defun proof-info-mode () - "Info mode on proof mode." - (interactive) - (info "script-management")) - -(defun proof-exit () - "Exit Proof-assistant." - (interactive) - (proof-restart-script)) - -(defvar proof-help-menu - '("Help" - ["Proof assistant web page" - (w3-fetch proof-www-home-page) t] - ["Help on Emacs proof-mode" proof-info-mode t] - ) - "The Help Menu in Script Management.") - -(defvar proof-shared-menu - (append-element '( - ["Display context" proof-ctxt - :active (proof-shell-live-buffer)] - ["Display proof state" proof-prf - :active (proof-shell-live-buffer)] - ["Exit proof assistant" proof-exit - :active (proof-shell-live-buffer)] - "----" - ["Find definition/declaration" find-tag-other-window t] - ) - proof-help-menu)) - -(defvar proof-menu - (append '("Commands" - ["Toggle active terminator" proof-active-terminator-minor-mode - :active t - :style toggle - :selected proof-active-terminator-minor-mode] - "----") - (list (if (string-match "XEmacs 19.1[2-9]" emacs-version) - "--:doubleLine" "----")) - proof-shared-menu - ) - "*The menu for the proof assistant.") - -(defvar proof-shell-menu proof-shared-menu - "The menu for the Proof-assistant shell") - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Active terminator minor mode ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(deflocal proof-active-terminator-minor-mode nil - "active terminator minor mode flag") - -(defun proof-active-terminator-minor-mode (&optional arg) - "Toggle PROOF's Active Terminator minor mode. -With arg, turn on the Active Terminator minor mode if and only if arg -is positive. - -If Active terminator mode is enabled, a terminator will process the -current command." - - (interactive "P") - -;; has this minor mode been registered as such? - (or (assq 'proof-active-terminator-minor-mode minor-mode-alist) - (setq minor-mode-alist - (append minor-mode-alist - (list '(proof-active-terminator-minor-mode - (concat " " proof-terminal-string)))))) - - (setq proof-active-terminator-minor-mode - (if (null arg) (not proof-active-terminator-minor-mode) - (> (prefix-numeric-value arg) 0))) - (if (fboundp 'redraw-modeline) - (redraw-modeline) - (force-mode-line-update))) - -(defun proof-process-active-terminator () - "Insert the terminator in an intelligent way and assert until the - new terminator. Fire up proof process if necessary." - (let ((mrk (point)) ins) - (if (looking-at "\\s-\\|\\'\\|\\w") - (if (not (re-search-backward "\\S-" (proof-unprocessed-begin) t)) - (error "Nothing to do!"))) - (if (not (= (char-after (point)) proof-terminal-char)) - (progn (forward-char) (insert proof-terminal-string) (setq ins t))) - (proof-assert-until-point - (function (lambda () - (if ins (backward-delete-char 1)) - (goto-char mrk) (insert proof-terminal-string)))))) - -(defun proof-active-terminator () - (interactive) - (if proof-active-terminator-minor-mode - (proof-process-active-terminator) - (self-insert-command 1))) - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Proof mode configuration ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - -(define-derived-mode proof-mode fundamental-mode - proof-mode-name "Proof mode - not standalone" - ;; define-derived-mode proof-mode initialises proof-mode-map - (setq proof-buffer-type 'script)) - -;; This has to come after proof-mode is defined - -(define-derived-mode proof-shell-mode comint-mode - "proof-shell" "Proof shell mode - not standalone" - (setq proof-buffer-type 'shell) - (setq proof-shell-busy nil) - (setq proof-shell-delayed-output (cons 'insert "done")) - (setq comint-prompt-regexp proof-shell-prompt-pattern) - (add-hook 'comint-output-filter-functions 'proof-shell-filter nil t) - (setq comint-get-old-input (function (lambda () ""))) - (proof-dont-show-annotations) - (setq proof-marker (make-marker))) - -(easy-menu-define proof-shell-menu - proof-shell-mode-map - "Menu used in the proof assistant shell." - (cons proof-mode-name (cdr proof-shell-menu))) - -(easy-menu-define proof-mode-menu - proof-mode-map - "Menu used in proof mode." - (cons proof-mode-name (cdr proof-menu))) - -;; the following callback is an irritating hack - there should be some -;; elegant mechanism for computing constants after the child has -;; configured. - -(defun proof-config-done () - -;; calculate some strings and regexps for searching - - (setq proof-terminal-string (char-to-string proof-terminal-char)) - - (setq pbp-goal-command (concat "Pbp %s" proof-terminal-string)) - (setq pbp-hyp-command (concat "PbpHyp %s" proof-terminal-string)) - - (make-local-variable 'comment-start) - (setq comment-start (concat proof-comment-start " ")) - (make-local-variable 'comment-end) - (setq comment-end (concat " " proof-comment-end)) - (make-local-variable 'comment-start-skip) - (setq comment-start-skip - (concat (regexp-quote proof-comment-start) "+\\s_?")) - - (setq proof-re-end-of-cmd (concat "\\s_*" proof-terminal-string "\\s_*\\\'")) - (setq proof-re-term-or-comment - (concat proof-terminal-string "\\|" (regexp-quote proof-comment-start) - "\\|" (regexp-quote proof-comment-end))) - -;; func-menu --- Jump to a goal within a buffer - (and (boundp 'fume-function-name-regexp-alist) - (defvar fume-function-name-regexp-proof - (cons proof-goal-with-hole-regexp 2)) - (push (cons major-mode 'fume-function-name-regexp-proof) - fume-function-name-regexp-alist)) - (and (boundp 'fume-find-function-name-method-alist) - (push (cons major-mode 'fume-match-find-next-function-name) - fume-find-function-name-method-alist)) - -;; Info - (or (memq proof-info-dir Info-default-directory-list) - (setq Info-default-directory-list - (cons proof-info-dir Info-default-directory-list))) - -;; keymaps and menus - (easy-menu-add proof-mode-menu proof-mode-map) - - (proof-define-keys proof-mode-map proof-universal-keys) - - (define-key proof-mode-map - (vconcat [(control c)] (vector proof-terminal-char)) - 'proof-active-terminator-minor-mode) - - (define-key proof-mode-map [(control c) (control e)] - 'proof-find-next-terminator) - - (define-key proof-mode-map (vector proof-terminal-char) - 'proof-active-terminator) - (define-key proof-mode-map [(control c) (return)] 'proof-assert-until-point) - (define-key proof-mode-map [(control c) (control t)] 'proof-try-command) - (define-key proof-mode-map [(control c) ?u] 'proof-retract-until-point) - (define-key proof-mode-map [(control c) (control u)] - 'proof-undo-last-successful-command) - - (define-key proof-mode-map [(control c) ?\'] - 'proof-goto-end-of-locked-interactive) - (define-key proof-mode-map [(control button1)] 'proof-send-span) - (define-key proof-mode-map [(control c) (control b)] 'proof-process-buffer) - (define-key proof-mode-map [(control c) (control z)] 'proof-frob-locked-end) - - (define-key proof-mode-map [tab] 'proof-indent-line) - (make-local-variable 'indent-line-function) - (setq indent-line-function 'proof-indent-line) - - (define-key (current-local-map) [(control c) (control p)] 'proof-prf) - (define-key (current-local-map) [(control c) ?c] 'proof-ctxt) - (define-key (current-local-map) [(control c) ?h] 'proof-help) - -;; For fontlock - (remove-hook 'font-lock-after-fontify-buffer-hook 'proof-zap-commas-buffer t) - (add-hook 'font-lock-after-fontify-buffer-hook 'proof-zap-commas-buffer nil t) - (remove-hook 'font-lock-mode-hook 'proof-unfontify-separator t) - (add-hook 'font-lock-mode-hook 'proof-unfontify-separator nil t) - -;; if we don't have the following, zap-commas fails to work. - - (and (boundp 'font-lock-always-fontify-immediately) - (setq font-lock-always-fontify-immediately t)) - - (run-hooks 'proof-mode-hook)) - -(defun proof-shell-config-done () - (accept-process-output (get-buffer-process (current-buffer))) - - ;; If the proof process in invoked on a different machine e.g., - ;; for proof-prog-name="rsh fastmachine proofprocess", one needs - ;; to adjust the directory: - (and proof-shell-cd - (proof-shell-insert (format proof-shell-cd - ;; under Emacs 19.34 default-directory contains "~" which causes - ;; problems with LEGO's internal Cd command - (expand-file-name default-directory)))) - - (if proof-shell-init-cmd - (proof-shell-insert proof-shell-init-cmd)) - -;; Note that proof-marker actually gets set in proof-shell-filter. -;; This is manifestly a hack, but finding somewhere more convenient -;; to do the setup is tricky. - - (while (null (marker-position proof-marker)) - (if (accept-process-output (get-buffer-process (current-buffer)) 15) - () - (error "Failed to initialise proof process")))) - -(define-derived-mode pbp-mode fundamental-mode - proof-mode-name "Proof by Pointing" - ;; defined-derived-mode pbp-mode initialises pbp-mode-map - (setq proof-buffer-type 'pbp) - (suppress-keymap pbp-mode-map 'all) -; (define-key pbp-mode-map [(button2)] 'pbp-button-action) - (proof-define-keys pbp-mode-map proof-universal-keys) - (erase-buffer)) - - -(provide 'proof) |
