#lang scheme
(require "../acl2/acl2.ss"
"../private/hash.ss")
(define-struct loc (source start end) #:prefab)
(define-struct term (sexp loc) #:prefab)
(define-struct part (name terms loc) #:prefab)
(define-struct proof (size parts by-number by-name) #:prefab)
(define (build-part name loc terms)
(make-part name (list->vector terms) loc))
(define (syntax->loc stx)
(let* ([source (syntax-source stx)]
[pos (syntax-position stx)]
[span (syntax-span stx)]
[start (and pos (sub1 pos))]
[end (and start span (+ start span))])
(make-loc source start end)))
(define (syntax->term stx)
(make-term (syntax->datum stx) (syntax->loc stx)))
(define (syntax->part stx #:name [name 'Proof])
(make-part name
(apply vector-immutable
(map syntax->term (syntax->list stx)))
(syntax->loc stx)))
(define (build-proof . parts)
(let* ([by-number (apply vector-immutable parts)]
[size (vector-length by-number)]
[names (map part-name parts)]
[by-name (make-immutable-hasheq (map cons names parts))])
(make-proof size names by-number by-name)))
(define (part-length part)
(vector-length (part-terms part)))
(define (part-nth part n)
(vector-ref (part-terms part) n))
(define (proof-part proof name)
(hash-ref/check (proof-by-name proof) name))
(define (proof-nth proof n)
(vector-ref (proof-by-number proof) n))
(define nat? exact-nonnegative-integer?)
(define nat/f (or/c nat? #f))
(provide/contract
[loc? (-> any/c boolean?)]
[syntax->loc (-> syntax? loc?)]
[make-loc (-> any/c nat/f nat/f loc?)]
[loc-source (-> loc? any/c)]
[loc-start (-> loc? nat/f)]
[loc-end (-> loc? nat/f)]
[term? (-> any/c boolean?)]
[syntax->term (-> syntax? term?)]
[make-term (-> sexp/c loc? term?)]
[term-sexp (-> term? sexp/c)]
[term-loc (-> term? loc?)]
[part? (-> any/c boolean?)]
[syntax->part (->* [(and/c syntax? syntax->list)] [#:name symbol?] part?)]
[rename build-part make-part (-> symbol? loc? (listof term?) part?)]
[part-name (-> part? symbol?)]
[part-loc (-> part? loc?)]
[part-length (-> part? nat?)]
[part-nth
(->d ([part part?] [n (and/c nat? (</c (part-length part)))]) ()
[_ term?])]
[proof? (-> any/c boolean?)]
[rename build-proof make-proof (->* [] [] #:rest (listof part?) proof?)]
[proof-size (-> proof? nat?)]
[proof-parts (-> proof? (listof symbol?))]
[proof-part (-> proof? symbol? part?)]
[proof-nth
(->d ([proof proof?] [n (and/c nat? (</c (proof-size proof)))]) ()
[_ part?])]
)