Preprocess nt patterns in pattern unification.

Specifically, correctly handle cases where an nt
production has named patterns.
This commit is contained in:
Burke Fetscher 2013-08-26 13:19:53 -05:00
parent 5800ce1cec
commit dc8ae059c6
4 changed files with 54 additions and 38 deletions

View File

@ -30,7 +30,10 @@
(struct-out unif-fail) (struct-out unif-fail)
not-failed? not-failed?
dq dq
predef-pat?) predef-pat?
unique-name-nums
fresh-pat-vars
make-uid)
;; ;;
@ -338,7 +341,7 @@
;; which match both pat and pat*... ;; which match both pat and pat*...
;; (those are the ones bind-names does nothing with) ;; (those are the ones bind-names does nothing with)
;; bind-names : pat env lang -> pat* or #f ;; bind-names : pat env lang -> pat* or unif-fail
(define (bind-names pat e L) (define (bind-names pat e L)
(match pat (match pat
[`(name ,name ,(bound)) [`(name ,name ,(bound))
@ -383,7 +386,7 @@
[_ pat])) [_ pat]))
;; unify* : pat* pat* env lang -> pat* or #f ;; unify* : pat* pat* env lang -> pat* or unif-fail
(define (unify* t0 u0 e L) (define (unify* t0 u0 e L)
(define t (resolve t0 e)) (define t (resolve t0 e))
(define u (resolve u0 e)) (define u (resolve u0 e))
@ -463,18 +466,18 @@
`(cstr ,nts ,res))])))) `(cstr ,nts ,res))]))))
(define (u*-2nts n-t n-u e L) (define (u*-2nts n-t n-u e L)
(if (equal? n-t n-u) (if (equal? n-t n-u)
(let ([n n-t]) `(nt ,n-t)
(if (hash-has-key? (compiled-lang-collapsible-nts L) n) (u*-1nt n-t `(nt ,n-u) e L)))
(hash-ref (compiled-lang-collapsible-nts L) n)
`(nt ,n)))
(u*-1nt n-t `(nt ,n-u) e L)))
(define (u*-1nt p u e L) (define (u*-1nt p u e L)
(and/fail (and/fail
(check-nt p L u) (check-nt p L u)
(if (hash-has-key? (compiled-lang-collapsible-nts L) p) (if (hash-has-key? (compiled-lang-collapsible-nts L) p)
(unify* (hash-ref (compiled-lang-collapsible-nts L) p) u e L) (let ([p-bn (bind-names (fresh-pat-vars (hash-ref (compiled-lang-collapsible-nts L) p) (make-hash)) e L)])
(and/fail
(not-failed? p-bn)
(unify* p-bn u e L)))
(let ([res (unify* u u e L)]) ;; look at structure of nt here? (let ([res (unify* u u e L)]) ;; look at structure of nt here?
(and/fail (not-failed? res) (and/fail (not-failed? res)
(when (lvar? res) (when (lvar? res)
@ -762,4 +765,27 @@
(define empty-lang (define empty-lang
(compiled-lang (compiled-lang
#f #f #f #f #f #f #f #f #f #f '() #f (hash) #f #f #f #f #f #f #f #f #f #f '() #f (hash)
(lang-enumerators '()))) (lang-enumerators '())))
(define unique-name-nums (make-parameter 0))
;; TODO: compare with free-identifier=? so renaming is safe
;; w/r/t macro expansion
;; (use free-id-table)
(define (fresh-pat-vars pre-pat instantiations)
(match pre-pat
[`(name ,id ,pat)
(define new-id (hash-ref instantiations id
(λ ()
(define unique-id (make-uid id))
(hash-set! instantiations id unique-id)
unique-id)))
`(name ,new-id ,(fresh-pat-vars pat instantiations))]
[`(list ,pats ...)
`(list ,@(for/list ([p pats]) (fresh-pat-vars p instantiations)))]
[_ pre-pat]))
(define (make-uid id)
(let ([uid-num (unique-name-nums)])
(unique-name-nums (add1 uid-num))
(string->symbol (string-append (symbol->string id) "_" (number->string uid-num)))))

View File

@ -215,29 +215,6 @@
(and (not-failed? u-res) (and (not-failed? u-res)
(loop (p*e-e u-res) rest))]))] (loop (p*e-e u-res) rest))]))]
[else #f])])) [else #f])]))
;; TODO: compare with free-identifier=? so renaming is safe
;; w/r/t macro expansion
;; (use free-id-table)
(define (fresh-pat-vars pre-pat instantiations)
(match pre-pat
[`(name ,id ,pat)
(define new-id (hash-ref instantiations id
(λ ()
(define unique-id (make-uid id))
(hash-set! instantiations id unique-id)
unique-id)))
`(name ,new-id ,(fresh-pat-vars pat instantiations))]
[`(list ,pats ...)
`(list ,@(for/list ([p pats]) (fresh-pat-vars p instantiations)))]
[_ pre-pat]))
(define (make-uid id)
(let ([uid-num (unique-name-nums)])
(unique-name-nums (add1 uid-num))
(string->symbol (string-append (symbol->string id) "_" (number->string uid-num)))))
(define (fresh-clause-vars clause-raw) (define (fresh-clause-vars clause-raw)
(define instantiations (make-hash)) (define instantiations (make-hash))
@ -276,7 +253,6 @@
(define str (format "depth bound exceeded at depth: ~s" (length tr-loc))) (define str (format "depth bound exceeded at depth: ~s" (length tr-loc)))
(raise (make-exn:fail:redex:search-failure str (current-continuation-marks) fails)))) (raise (make-exn:fail:redex:search-failure str (current-continuation-marks) fails))))
(define unique-name-nums (make-parameter 0))
(define generation-logger (make-logger 'generation-log (current-logger))) (define generation-logger (make-logger 'generation-log (current-logger)))

View File

@ -795,3 +795,13 @@
(test (gen-ith 0) 0) (test (gen-ith 0) 0)
(test (gen-ith 1) 1))) (test (gen-ith 1) 1)))
(let ()
(define-language L
(e ::= (name aha! any)))
(define-judgment-form L
#:mode (J I I)
[(J e e)])
(is-not-false
(generate-term L #:satisfying (J e_1 e_2) 10)))

View File

@ -587,8 +587,12 @@
(p*e 'variable (hash))) (p*e 'variable (hash)))
(check-equal? (unify/format `(nt y) 'any (hash) ntl) (check-equal? (unify/format `(nt y) 'any (hash) ntl)
(p*e 'variable (hash))) (p*e 'variable (hash)))
;; asymmetry ok here - if the nt doesn't get unified against,
;; it doesn't get collapsed
(check-equal? (unify/format `(nt y) '(nt Q) (hash) ntl) (check-equal? (unify/format `(nt y) '(nt Q) (hash) ntl)
(p*e '(cstr (Q) variable) (hash))) `(different-orders=>different-results
,(p*e '(cstr (Q) variable) (env (hash) '()))
,(p*e '(cstr (Q) (nt y)) (env (hash) '()))))
) )
@ -820,7 +824,7 @@
(p*e `(list λ y (name e_2 ,(bound))) (m-hash (lvar 'e_2) `(cstr (e) 3)))) (p*e `(list λ y (name e_2 ,(bound))) (m-hash (lvar 'e_2) `(cstr (e) 3))))
(u-test λn (λ x 3) (λ x e_2) (hash) (u-test λn (λ x 3) (λ x e_2) (hash)
(p*e `(list λ (name x ,(bound)) (name e_2 ,(bound))) (p*e `(list λ (name x ,(bound)) (name e_2 ,(bound)))
(m-hash (lvar 'e_2) `(cstr (e) 3) (lvar 'x) `variable-not-otherwise-mentioned))) (m-hash (lvar 'e_2) `(cstr (e) 3) (lvar 'x) `(nt x))))
(u-fails λn (λ x 3) (e_1 e_2) (hash)) (u-fails λn (λ x 3) (e_1 e_2) (hash))
(u-test λn (e_1 e_2) ((λ x x) 3) (hash) (u-test λn (e_1 e_2) ((λ x x) 3) (hash)
(p*e `(list (name e_1 ,(bound)) (name e_2 ,(bound))) (p*e `(list (name e_1 ,(bound)) (name e_2 ,(bound)))
@ -829,7 +833,7 @@
(lvar 'e_1) (lvar 'e_1)
`(cstr (e) (list λ (name x ,(bound)) (name x ,(bound)))) `(cstr (e) (list λ (name x ,(bound)) (name x ,(bound))))
(lvar 'x) (lvar 'x)
`variable-not-otherwise-mentioned))) `(nt x))))
(define-language p-types (define-language p-types
(t (t -> t) (t (t -> t)