#lang racket (require racket/pretty "../proof/proof.rkt" "../acl2/acl2.rkt" "../acl2/rep.rkt" "../private/hash.rkt" "term-state.rkt") ;; A ProofState is: ;; (make-proof-state Loc Nat (Or Nat #f) (Hash Nat TermState)) (define-struct proof-state (loc size index terms) #:prefab) ;; ====================================================================== ;; ;; IMPLEMENTATION ;; ;; ====================================================================== ;; ================================================== ;; ;; Constructors. ;; ;; ================================================== (define (initial-proof-state part) (let* ([loc0 (part-loc part)] [loc1 (make-loc (loc-source loc0) (loc-start loc0) (loc-start loc0))] [terms (make-immutable-hash null)] [terms (hash-set terms 0 (empty-term-state loc1))] [terms (for/fold ([terms terms]) ([n (in-range (part-length part))]) (hash-set terms (+ n 1) (initial-term-state (part-nth part n))))]) (make-proof-state loc0 (+ (part-length part) 1) #f terms))) (define (proof-state-populate old-state new-part) (let* ([new-state (initial-proof-state new-part)]) (match (list old-state new-state) [(list (struct proof-state [_ _ #f _]) _) new-state] [(list (struct proof-state [old-loc old-size old-index old-terms]) (struct proof-state [new-loc new-size new-index new-terms])) (make-proof-state new-loc new-size old-index (for/fold ([terms new-terms]) ([n (in-range 0 (+ old-index 1))]) (hash-set terms n (term-state-populate (hash-ref/check old-terms n) (hash-ref/check new-terms n)))))]))) (define (proof-state-start-term state acl2-state index saved) (make-proof-state (proof-state-loc state) (proof-state-size state) index (hash-update (proof-state-terms state) index (lambda (term) (term-state-start-acl2 term acl2-state saved))))) (define (proof-state-start-acl2 state acl2-state) (proof-state-start-term state acl2-state 0 #t)) (define (proof-state-update-acl2 state acl2-state) (struct-copy proof-state state [terms (hash-update (proof-state-terms state) (proof-state-index state) (lambda (term) (term-state-update-acl2 term acl2-state)))])) (define (proof-state-advance state acl2-state saved) (proof-state-start-term state acl2-state (+ (proof-state-index state) 1) saved)) (define (proof-state-rewind state) (make-proof-state (proof-state-loc state) (proof-state-size state) (- (proof-state-index state) 1) (hash-update (proof-state-terms state) (proof-state-index state) (lambda (term) (term-state-stop-acl2 term))))) (define (proof-state-edit state) (if (proof-state-admitted? state) (error 'proof-state-edit "Attempted to edit an admitted term") (make-proof-state (proof-state-loc state) (proof-state-size state) (proof-state-index state) (hash-update (proof-state-terms state) (proof-state-index state) (lambda (term) (term-state-edit term)))))) (define (proof-state-stop-acl2 state) (make-proof-state (proof-state-loc state) (proof-state-size state) #f (for/fold ([terms (proof-state-terms state)]) ([n (in-range 0 (+ (proof-state-index state) 1))]) (hash-update terms n term-state-stop-acl2)))) ;; ================================================== ;; ;; ACL2 text. ;; ;; ================================================== (define (proof-state-initial-prompt state) (term-state-initial-prompt (proof-state-current-term state))) (define (proof-state-acl2-input state) (term-state-acl2-input (proof-state-current-term state))) (define (proof-state-acl2-output state) (term-state-acl2-output (proof-state-current-term state))) (define (proof-state-final-prompt state) (term-state-final-prompt (proof-state-current-term state))) (define (proof-state-proof-tree state) (term-state-proof-tree (proof-state-current-term state))) (define (proof-state-total-output state) (let loop ([i 0]) (let* ([term-state (hash-ref/default (proof-state-terms state) i #f)]) (if (term-state-active? term-state) (string-append (term-state-total-output term-state) "\n" (loop (add1 i))) "\n")))) ;; ================================================== ;; ;; Predicates. ;; ;; ================================================== (define (proof-state-acl2-open? v) (and (proof-state? v) (integer? (proof-state-index v)))) (define (proof-state-start-of-proof? state) (or (= (proof-state-index state) 0) (and (= (proof-state-index state) 1) (not (proof-state-admitted? state))))) (define (proof-state-end-of-proof? state) (and (= (proof-state-index state) (- (proof-state-size state) 1)) (proof-state-admitted? state))) (define (proof-state-at-first-term? state) (= (proof-state-index state) 0)) (define (proof-state-at-last-term? state) (= (proof-state-index state) (- (proof-state-size state) 1))) (define (proof-state-finished? state) (term-state-finished? (proof-state-current-term state))) (define (proof-state-admitted? state) (term-state-admitted? (proof-state-current-term state))) (define (proof-state-edited? state) (term-state-edited? (proof-state-current-term state))) ;; ================================================== ;; ;; Highlighting positions. ;; ;; ================================================== (define (proof-state-first-admitted-position state) (loc-start (proof-state-loc state))) (define (proof-state-last-admitted-position state) (match state [(struct proof-state [loc size index terms]) (let* ([term-state (hash-ref/check terms index)]) (if (term-state-admitted? term-state) (if (= index (sub1 size)) (loc-end loc) (loc-end (term-state-loc term-state))) (if (= index 0) (loc-start loc) (loc-end (term-state-loc (hash-ref/check terms (sub1 index)))))))])) (define (proof-state-last-attempted-position state) (let* ([term-state (proof-state-current-term state)]) (if (term-state-admitted? term-state) (proof-state-last-admitted-position state) (if (term-state-has-input? term-state) (loc-end (term-state-loc term-state)) (proof-state-last-admitted-position state))))) ;; ================================================== ;; ;; Cursor search. ;; ;; ================================================== ;; proof-state-index-before-pos : ProofState Nat -> Nat (define (proof-state-index-before-pos state pos) (let loop ([index (proof-state-index state)]) (if (or (= (add1 index) (proof-state-size state)) (<= pos (loc-start (term-state-loc (hash-ref/check (proof-state-terms state) (add1 index)))))) index (loop (add1 index))))) ;; proof-state-index-after-pos : ProofState Nat -> Nat (define (proof-state-index-after-pos state pos) (let loop ([index (add1 (proof-state-index state))]) (if (or (= index 1) (>= pos (loc-end (term-state-loc (hash-ref/check (proof-state-terms state) (sub1 index)))))) index (loop (sub1 index))))) (define (proof-state-next-sexp state) (term-state-sexp (proof-state-next-term state))) (define (proof-state-save-before-next-sexp state) (term-state-save-before-sexp (proof-state-next-term state))) (define (proof-state-restore-saved-sexp state) (term-state-restore-saved-sexp (proof-state-current-term state))) ;; ===================================================================== ;; ;; HELPERS ;; ;; ====================================================================== (define (proof-state-term-index state) (proof-state-index state)) (define (proof-state-current-term state) (hash-ref/check (proof-state-terms state) (proof-state-index state))) (define (proof-state-next-term state) (hash-ref/check (proof-state-terms state) (add1 (proof-state-index state)))) ;; ====================================================================== ;; ;; CONTRACTS ;; ;; ====================================================================== (define (state-pos/c state) (and/c exact-nonnegative-integer? (>=/c (loc-start (proof-state-loc state))) (<=/c (loc-end (proof-state-loc state))))) (define (state-index/c state) (and/c exact-nonnegative-integer? (>=/c 0) (<=/c (proof-state-size state)))) (provide/contract [proof-state? (-> any/c boolean?)] [proof-state-acl2-open? (-> any/c boolean?)] [initial-proof-state (-> part? proof-state?)] [proof-state-populate (-> proof-state? part? proof-state?)] [proof-state-start-acl2 (-> (and/c proof-state? (not/c proof-state-acl2-open?)) acl2? proof-state-acl2-open?)] [proof-state-update-acl2 (-> proof-state-acl2-open? acl2? proof-state-acl2-open?)] [proof-state-advance (-> (and/c proof-state-acl2-open? (not/c proof-state-at-last-term?)) acl2? (or/c sexp/c #f) proof-state-acl2-open?)] [proof-state-rewind (-> (and/c proof-state-acl2-open? (not/c proof-state-at-first-term?)) proof-state-acl2-open?)] [proof-state-edit (-> proof-state-acl2-open? proof-state-acl2-open?)] [proof-state-stop-acl2 (-> proof-state-acl2-open? (and/c proof-state? (not/c proof-state-acl2-open?)))] [proof-state-start-of-proof? (-> proof-state-acl2-open? boolean?)] [proof-state-end-of-proof? (-> proof-state-acl2-open? boolean?)] [proof-state-at-first-term? (-> proof-state-acl2-open? boolean?)] [proof-state-at-last-term? (-> proof-state-acl2-open? boolean?)] [proof-state-finished? (-> proof-state-acl2-open? boolean?)] [proof-state-admitted? (-> proof-state-acl2-open? boolean?)] [proof-state-edited? (-> proof-state-acl2-open? boolean?)] [proof-state-proof-tree (-> proof-state-acl2-open? string?)] [proof-state-total-output (-> proof-state-acl2-open? string?)] [proof-state-initial-prompt (-> proof-state-acl2-open? string?)] [proof-state-acl2-input (-> proof-state-acl2-open? string?)] [proof-state-acl2-output (-> proof-state-acl2-open? string?)] [proof-state-final-prompt (-> proof-state-acl2-open? string?)] [proof-state-next-sexp (-> (and/c proof-state-acl2-open? (not/c proof-state-at-last-term?)) sexp/c)] [proof-state-save-before-next-sexp (-> (and/c proof-state-acl2-open? (not/c proof-state-at-last-term?)) sexp/c)] [proof-state-restore-saved-sexp (-> (and/c proof-state-admitted? (not/c proof-state-at-first-term?)) sexp/c)] [proof-state-size (-> proof-state? exact-positive-integer?)] [proof-state-term-index (->d ([state proof-state-acl2-open?]) () [_ (state-index/c state)])] [proof-state-index-before-pos (->d ([state proof-state-acl2-open?] [pos exact-nonnegative-integer?]) () [_ (state-index/c state)])] [proof-state-index-after-pos (->d ([state proof-state-acl2-open?] [pos exact-nonnegative-integer?]) () [_ (state-index/c state)])] [proof-state-first-admitted-position (->d ([state proof-state-acl2-open?]) () [_ (state-pos/c state)])] [proof-state-last-admitted-position (->d ([state proof-state-acl2-open?]) () [_ (state-pos/c state)])] [proof-state-last-attempted-position (->d ([state proof-state-acl2-open?]) () [_ (state-pos/c state)])] )