Improve compilation of hash table patterns with literal keys.

This commit is contained in:
Sam Tobin-Hochstadt 2016-07-04 18:19:19 -04:00
parent bdd11100bb
commit 8377fa842f
4 changed files with 36 additions and 12 deletions

View File

@ -55,11 +55,15 @@
(Row-vars-seen row))) (Row-vars-seen row)))
rows) rows)
esc)]) esc)])
#`[(#,predicate-stx #,x) rhs])) (if (procedure? predicate-stx)
#`[#,(predicate-stx x) rhs]
#`[(#,predicate-stx #,x) rhs])))
(define (compile-con-pat accs pred pat-acc) (define (compile-con-pat accs pred pat-acc)
(with-syntax* ([(tmps ...) (generate-temporaries accs)] (with-syntax* ([(tmps ...) (generate-temporaries accs)]
[(accs ...) accs] [(accs ...) accs]
[pred pred] [question (if (procedure? pred)
(pred x)
#`(#,pred #,x))]
[body (compile* [body (compile*
(append (syntax->list #'(tmps ...)) xs) (append (syntax->list #'(tmps ...)) xs)
(map (lambda (row) (map (lambda (row)
@ -70,7 +74,7 @@
(Row-vars-seen row))) (Row-vars-seen row)))
rows) rows)
esc)]) esc)])
#`[(pred #,x) (let ([tmps (accs #,x)] ...) body)])) #`[question (let ([tmps (accs #,x)] ...) body)]))
(cond (cond
[(eq? 'box k) [(eq? 'box k)
(compile-con-pat (list #'unsafe-unbox*) #'box? (compose list Box-p))] (compile-con-pat (list #'unsafe-unbox*) #'box? (compose list Box-p))]
@ -123,6 +127,7 @@
[pred (Struct-pred s)]) [pred (Struct-pred s)])
(compile-con-pat accs pred Struct-ps))] (compile-con-pat accs pred Struct-ps))]
[(syntax? k) (constant-pat k)] [(syntax? k) (constant-pat k)]
[(procedure? k) (constant-pat k)]
[else (error 'match-compile "bad key: ~a" k)])) [else (error 'match-compile "bad key: ~a" k)]))
@ -256,7 +261,10 @@
[pats (Row-pats row)] [pats (Row-pats row)]
[app-pats (App-ps first)]) [app-pats (App-ps first)])
(with-syntax ([(t ...) (generate-temporaries app-pats)]) (with-syntax ([(t ...) (generate-temporaries app-pats)])
#`(let-values ([(t ...) (#,(App-expr first) #,x)]) #`(let-values ([(t ...)
#,(if (procedure? (App-expr first))
((App-expr first) x)
#`(#,(App-expr first) #,x))])
#,(compile* (append (syntax->list #'(t ...)) xs) #,(compile* (append (syntax->list #'(t ...)) xs)
(list (make-Row (append app-pats (cdr pats)) (list (make-Row (append app-pats (cdr pats))
(Row-rhs row) (Row-rhs row)

View File

@ -8,7 +8,7 @@
"syntax-local-match-introduce.rkt") "syntax-local-match-introduce.rkt")
(provide ddk? parse-literal all-vars pattern-var? match:syntax-err (provide ddk? parse-literal all-vars pattern-var? match:syntax-err
match-expander-transform trans-match parse-struct match-expander-transform trans-match trans-match* parse-struct
dd-parse parse-quote parse-id in-splicing?) dd-parse parse-quote parse-id in-splicing?)
(define in-splicing? (make-parameter #f)) (define in-splicing? (make-parameter #f))
@ -155,6 +155,10 @@
(define (trans-match pred transformer pat) (define (trans-match pred transformer pat)
(make-OrderedAnd (list (make-Pred pred) (make-App transformer (list pat))))) (make-OrderedAnd (list (make-Pred pred) (make-App transformer (list pat)))))
(define (trans-match* preds transformers pats)
(make-OrderedAnd (append (map make-Pred preds)
(map (λ (t p) (make-App t (list p))) transformers pats))))
;; transform a match-expander application ;; transform a match-expander application
;; parse : stx -> pattern ;; parse : stx -> pattern
;; expander : identifier ;; expander : identifier

View File

@ -18,6 +18,13 @@
(define orig-insp (variable-reference->module-declaration-inspector (define orig-insp (variable-reference->module-declaration-inspector
(#%variable-reference))) (#%variable-reference)))
(define (literal-pat? p)
(syntax-case p ()
[(_quote e)
(eq? 'quote (syntax-e #'_quote))
(parse-literal (syntax-e #'e))]
[_ (parse-literal (syntax-e p))]))
;; parse : syntax -> Pat ;; parse : syntax -> Pat
;; compile stx into a pattern, using the new syntax ;; compile stx into a pattern, using the new syntax
(define (parse stx) (define (parse stx)
@ -88,6 +95,13 @@
(raise-syntax-error (raise-syntax-error
'match "dot dot k can only appear at the end of hash-table patterns" stx 'match "dot dot k can only appear at the end of hash-table patterns" stx
(ormap (lambda (e) (and (ddk? e) e)) (syntax->list #'(p ...))))] (ormap (lambda (e) (and (ddk? e) e)) (syntax->list #'(p ...))))]
[(hash-table (k v) ...)
(andmap (λ (p) (and (literal-pat? p) (not (identifier? p)))) (syntax->list #'(k ...)))
(let ([keys (map Exact-v (map literal-pat? (syntax->list #'(k ...))))])
(trans-match*
(cons #'hash? (for/list ([k (in-list keys)]) (λ (e) #`(hash-has-key? #,e '#,k))))
(for/list ([k (in-list keys)]) (λ (e) #`(hash-ref #,e '#,k)))
(map parse (syntax->list #'(v ...)))))]
[(hash-table p ...) [(hash-table p ...)
(trans-match #'hash? (trans-match #'hash?
#'(lambda (e) (hash-map e list)) #'(lambda (e) (hash-map e list))

View File

@ -49,16 +49,17 @@
;; (define-struct (Boolean Atom) () #:transparent) ;; (define-struct (Boolean Atom) () #:transparent)
(define-struct (Null CPat) (p) #:transparent) (define-struct (Null CPat) (p) #:transparent)
;; expr is an expression ;; expr is an expression or an (expression -> expression) procedure
;; ps is a list of patterns ;; ps is a list of patterns
(define-struct (App Pat) (expr ps) #:transparent) (define-struct (App Pat) (expr ps) #:transparent)
;; pred is an expression ;; pred is an expression, or an Expr -> Expr procedure
(define-struct (Pred Pat) (pred) #:transparent (define-struct (Pred Pat) (pred) #:transparent
#:property prop:equal+hash #:property prop:equal+hash
(list (lambda (a b e?) (list (lambda (a b e?)
(and (identifier? (Pred-pred a)) (identifier? (Pred-pred b)) (or (eq? (Pred-pred a) (Pred-pred b))
(free-identifier=? (Pred-pred a) (Pred-pred b)))) (and (identifier? (Pred-pred a)) (identifier? (Pred-pred b))
(free-identifier=? (Pred-pred a) (Pred-pred b)))))
(lambda (v r) (lambda (v r)
(if (identifier? (Pred-pred v)) (if (identifier? (Pred-pred v))
(r (syntax-e (Pred-pred v))) (r (syntax-e (Pred-pred v)))
@ -75,9 +76,6 @@
;; ps is a listof patterns ;; ps is a listof patterns
(define-struct (Struct CPat) (id pred super complete? accessors ps) #:transparent) (define-struct (Struct CPat) (id pred super complete? accessors ps) #:transparent)
;; both fields are lists of pats
(define-struct (HashTable CPat) (key-pats val-pats) #:transparent)
;; ps are patterns ;; ps are patterns
(define-struct (Or Pat) (ps) #:transparent) (define-struct (Or Pat) (ps) #:transparent)
(define-struct (And Pat) (ps) #:transparent) (define-struct (And Pat) (ps) #:transparent)