Implement 1-level named repeats with named patterns inside.

This commit is contained in:
Max New 2013-11-04 10:47:53 -06:00
parent 5fbcc62e9a
commit 3b64ee8c81
4 changed files with 192 additions and 88 deletions

View File

@ -34,6 +34,7 @@
(struct name-ref (name) #:transparent)
(struct mismatch-ref (name) #:transparent)
(struct nrep-ref (name subpat) #:transparent)
(struct named-pats (names map) #:transparent
) ;; listof symbol and hash symbol -o> (or named, mismatched, named-repeat, mismatch-repeat)
@ -84,14 +85,14 @@
(define (pat/e pat l-enums unused/e)
(match-define (ann-pat nv pp-pat) (preprocess pat))
(map/e
(λ (e-p)
(ann-pat (car e-p) (cdr e-p)))
ann-pat
(λ (ap)
(cons (ann-pat-ann ap)
(ann-pat-pat ap)))
(cons/e (env/e nv l-enums unused/e)
(pat-refs/e pp-pat l-enums unused/e))))
(values (ann-pat-ann ap)
(ann-pat-pat ap)))
(env/e nv l-enums unused/e)
(pat-refs/e pp-pat l-enums unused/e)))
;; (: pat-refs/e : Pat (HashTable Symbol (Enum Pat)) (Enum Symbol) -> Enum RefPat)
(define (pat-refs/e pat nt-enums unused/e)
(define (loop pat)
(match-a-pattern
@ -118,46 +119,59 @@
[`(name ,n ,pat)
(const/e (name-ref n))]
[`(mismatch-name ,n ,pat)
(const/e (mismatch-ref n))]
(unimplemented "mismatch-name")]
[`(in-hole ,p1 ,p2) ;; untested
(map/e
(λ (ts)
(decomposition (car ts)
(cdr ts)))
(λ (decomp)
(cons (decomposition-ctx decomp)
(decomposition-term decomp)))
(cons/e
(loop p1)
(loop p2)))]
(unsupported pat)]
[`(hide-hole ,p)
(loop p)]
(unsupported pat)]
[`(side-condition ,p ,g ,e)
(unsupported pat)]
[`(cross ,s)
(unsupported pat)]
[`(list ,sub-pats ...)
;; enum-list
(list/e
(for/list ([sub-pat (in-list sub-pats)])
(match sub-pat
[`(repeat ,pat #f #f)
(map/e
(λ (ts)
(repeat (length ts)
ts))
(λ (rep)
(repeat-terms rep))
(many/e (loop pat)))]
[`(repeat ,tag ,n #f)
(const/e (nrep-ref n tag))]
[`(repeat ,pat ,n ,m)
(error 'unimplemented "repeats")]
(unimplemented "mismatch repeats (..._!_)")]
[else (loop sub-pat)])))]
[(? (compose not pair?))
(const/e pat)]))
(loop pat))
(define (env/e nv l-enums unused/e)
(define names (env-names nv))
(define (val/e p)
(pat/e p l-enums unused/e))
(define names-env
(hash-traverse/e val/e names))
(map/e
env
env-names
names-env))
(define/match (env/e nv l-enums unused/e)
[((env names nreps) _ _)
(define (val/e p)
(pat-refs/e p l-enums unused/e))
(define/match (reprec/e nv-t)
[((cons nv tpats))
(define tpats/e
(hash-traverse/e val/e tpats))
(many/e
(cons/e (env/e nv l-enums unused/e)
tpats/e))])
(define names-env
(hash-traverse/e val/e names))
(define nreps-env
(hash-traverse/e reprec/e nreps))
(map/e
t-env
(match-lambda
[(t-env names nreps)
(values names nreps)])
names-env
nreps-env)])
(define (map-nt-rhs-pat f nonterminal)
(nt (nt-name nonterminal)
@ -586,24 +600,44 @@
bool/e
var/e))
;; fill-refs : (ann-pat env pat-with-refs) -> redex term
;; fill-refs : (ann-pat t-env pat-with-refs) -> redex term
(define/match (fill-refs ap)
[((ann-pat nv term))
(define (rec term)
(cond [(ann-pat? term)
(fill-refs term)]
[(name-ref? term)
(fill-refs (env-name-ref nv (name-ref-name term)))]
[(decomposition? term)
(error 'unsupported "in-hole")]
[(list? term)
(append*
(for/list ([sub-term (in-list term)])
(cond [(repeat? sub-term)
(map rec (repeat-terms sub-term))]
[else (list (rec sub-term))])))]
[else term]))
(rec term)])
((refs-to-fn term) nv)])
;; refs-to-fn : RefPat -> (TEnv -> Term)
(define (refs-to-fn refpat)
(match refpat
[(ann-pat _ _)
(define term
(fill-refs refpat))
(λ (_) term)]
[(name-ref n)
(λ (nv)
(t-env-name-ref nv n))]
[(list subrefpats ...)
(compose
append*
(sequence-fn
(for/list ([subrefpat (in-list subrefpats)])
(match subrefpat
[(repeat _ subs)
(sequence-fn (map refs-to-fn subs))]
[(nrep-ref n tag)
(λ (nv)
(define env-ts (t-env-nrep-ref nv n))
(for/list ([nv-t (in-list env-ts)])
(match nv-t
[(cons nv tterms)
((refs-to-fn (hash-ref tterms tag)) nv)])))]
[_ (sequence-fn (list (refs-to-fn subrefpat)))]))))]
[else (λ (_) refpat)]))
;; (: sequence-fn : (All (a b) (Listof (a -> b)) -> (a -> (Listof b))))
(define (sequence-fn fs)
(λ (x)
(for/list ([f (in-list fs)])
(f x))))
;; to-term : augmented term -> redex term
(define (to-term aug)

View File

@ -1,48 +1,103 @@
#lang typed/racket
(provide env
env?
(provide (struct-out env)
empty-env
add-name
env-name-ref
add-nrep
env-union
env-names)
(struct-out t-env)
t-env-name-ref
t-env-nrep-ref)
;; For now, accept any pattern
(define-type Pattern Any)
(define-type Tag Number)
(define-type Term Any)
(define-type Env env)
(define-type TEnv t-env)
(define-type Tag Integer)
(define-type (Tagged a) (HashTable Tag a))
(struct: env ([names : (HashTable Symbol Pattern)])
(struct: env ([names : (HashTable Symbol Pattern)]
[nreps : (HashTable Symbol (Pairof Env (Tagged Pattern)))])
#:transparent)
(struct: t-env ([names : (HashTable Symbol Term)]
[nreps : (HashTable Symbol (Listof (Pairof TEnv (Tagged Term))))])
#:transparent)
(: empty-env : Env)
(define empty-env
(env (hash)))
(env (hash) (hash)))
(: add-name : Env Symbol Pattern -> Env)
(define/match (add-name e n p)
[((env names) _ _)
[((env names nreps) _ _)
(define (default) p)
(define update identity)
(env (hash-update names n update default))])
(env (hash-update names n update default) nreps)])
(: env-name-ref : Env Symbol -> Pattern)
(define/match (env-name-ref e n)
[((env names) _)
(hash-ref names n (λ () (error (format "env-name-ref: name not found: ~s" n))))])
(: add-nrep : Env Symbol Env Tag Pattern -> Env)
(define/match (add-nrep e n repnv tag pat)
[((env names nreps) _ _ _ _)
(: update-nreps : (Pairof Env (Tagged Pattern)) -> (Pairof Env (Tagged Pattern)))
(define/match (update-nreps e-t)
[((cons nv tagged))
(cons (env-union nv repnv)
(hash-set tagged tag pat))])
(: default : (-> (Pairof Env (Tagged Pattern))))
(define (default)
(: tagged : (Tagged Pattern))
(define tagged (hash-set (ann (hash) (Tagged Pattern))
tag pat))
(cons repnv tagged))
(env names
(hash-update nreps n update-nreps default
))])
(: t-env-name-ref : TEnv Symbol -> Pattern)
(define/match (t-env-name-ref e n)
[((t-env names _) _)
(hash-ref names n (thunk (error (format "t-env-name-ref: name not found: ~s" n))))])
(: t-env-nrep-ref : TEnv Symbol -> (Listof (Pairof TEnv Term)))
(define/match (t-env-nrep-ref nv n)
[((t-env _ nreps) n)
(hash-ref nreps n (thunk (error (format "t-env-nrep-ref: repeat not found: ~s" n))))])
(: env-union : Env Env -> Env)
(define/match (env-union e1 e2)
[((env ns1) (env ns2))
(define ks1 (list->set (hash-keys ns1)))
(define ks2 (list->set (hash-keys ns2)))
;; For some reason in-set is not typed so I can't use it
(env (for/hash: : (HashTable Symbol Pattern)
([k : Symbol (set-union ks1 ks2)])
(: ref-default : (HashTable Symbol Pattern) -> Pattern)
(define (ref-default ns)
(hash-ref ns k (thunk #f)))
(match-define p1 (ref-default ns1))
(match-define p2 (ref-default ns2))
(values k (or p1 p2))))])
[((env ns1 rs1) (env ns2 rs2))
(define names-union
(hash-union ns1
ns2
(λ (v1 v2) v1)))
(: combo : (Pairof Env (Tagged Pattern)) (Pairof Env (Tagged Pattern)) -> (Pairof Env (Tagged Pattern)))
(define/match (combo e-t1 e-t2)
[((cons nv1 t1) (cons nv2 t2))
(cons (env-union nv1 nv2)
(hash-union t1 t2 (λ (_1 _2) (error "2 tags should never collide"))))])
(define nreps-union
(hash-union rs1 rs2 combo))
(env names-union nreps-union)])
(: key-set : (All (k v) (HashTable k v) -> (Setof k)))
(define (key-set m)
(list->set (hash-keys m)))
(: hash-union : (All (k v) (HashTable k v) (HashTable k v) (v v -> v) -> (HashTable k v)))
(define (hash-union m1 m2 combo)
(: ks1 : (Setof k))
(: ks2 : (Setof k))
(define ks1 (key-set m1))
(define ks2 (key-set m2))
;; TODO: in-set should be typed in HEAD, fix this after rebasing.
(for/hash: : (HashTable k v)
([k : k (set-union ks1 ks2)])
(define v1 (hash-ref m1 k (thunk #f)))
(define v2 (hash-ref m2 k (thunk #f)))
(define v
(cond [(and v1 v2)
(combo v1 v2)]
[else (or v1 v2 (error "absurd"))]))
(values k v)))

View File

@ -17,25 +17,30 @@
;; This function returns an env containing all top-level name references, i.e., the ones that need to be enumerated doing anything
(define (build-env pat)
(define counter 0)
(define (get-and-inc!)
(begin0 counter
(set! counter (add1 counter))))
(define (walk pat)
(match-a-pattern/single-base-case pat
[`(name ,n ,subpat)
(match-define (ann-pat subenv _) (walk subpat))
(match-define (ann-pat subenv new-subpat) (walk subpat))
(ann-pat (add-name subenv n subpat)
pat)]
`(name ,n ,new-subpat))]
[`(mismatch-name ,n ,subpat)
;; TODO
(unimplemented "mismatch-name")]
[`(in-hole ,p1 ,p2)
(match-define (ann-pat subenv1 _)
(match-define (ann-pat subenv1 newsub1)
(walk p1))
(match-define (ann-pat subenv2 _)
(match-define (ann-pat subenv2 newsub2)
(walk p2))
(ann-pat (env-union subenv1 subenv2) pat)]
(ann-pat (env-union subenv1 subenv2)
`(in-hole ,newsub1 ,newsub2))]
[`(hide-hole ,p)
(match-define (ann-pat subenv _)
(match-define (ann-pat subenv newsub)
(walk p))
(ann-pat subenv pat)]
(ann-pat subenv `(hide-hole ,newsub))]
[`(side-condition ,p ,c ,s)
(error 'unsupported "side condition is not supported.")]
[`(list ,sub-pats ...)
@ -44,19 +49,27 @@
(match sub-pat
[`(repeat ,p #f #f)
(ann-pat empty-env sub-pat)]
[`(repeat ,p ,n #f)
(match-define (ann-pat subenv _)
(walk p))
(define tag (get-and-inc!))
(ann-pat (add-nrep empty-env n subenv tag p)
`(repeat ,tag ,n #f))]
[`(repeat ,p ,n ,m)
(unimplemented "named repeat")]
(unimplemented (format "mismatch repeat (..._!_): ~s ~s" n m))]
[_ (walk sub-pat)])))
(define list-env
(for/fold ([accenv empty-env])
([sub-apat (in-list ann-sub-pats)])
([sub-apat (in-list ann-sub-pats)])
(match sub-apat
[(ann-pat subenv _)
(env-union subenv accenv)])))
(ann-pat list-env pat)]
(ann-pat list-env (cons 'list (map ann-pat-pat ann-sub-pats)))]
[_ (pure-ann-pat pat)]))
(walk pat))
(define res
(walk pat))
res)
(define (remove-names pat)
(define names-2set (find-names pat))

View File

@ -11,10 +11,10 @@
(for ([i (in-range N)])
(check-not-exn
(λ ()
(unless (redex-match
l p
(generate-term l p #:i-th i))
(error 'bad-term "line ~a: i=~a" line i)))))))]))
(define term
(generate-term l p #:i-th i))
(unless (redex-match l p term)
(error 'bad-term (format "line ~a: i=~a" line i))))))))]))
(define-language Nats
(n natural))
@ -99,11 +99,13 @@
(try-it 20 VarMentioned var)
(define-language NRep
(v (natural ..._1 natural ..._1))
(v2 (v ..._1 v ..._2 v ..._1 v ..._2)))
(v (natural ..._1 natural ..._1))
(v2 (v ..._1 v ..._2 v ..._1 v ..._2))
(v3 (natural_1 ..._1 natural_1 ..._1)))
(try-it 100 NRep v)
(try-it 100 NRep v2)
(try-it 100 NRep v3)
;; Test production sort
(define-language rec