Advanced match!

Advanced match now works in all stdlib. case and case* deprecated.
This commit is contained in:
William J. Bowman 2016-01-18 00:22:28 -05:00
parent b52dca0114
commit d48a5a0647
No known key found for this signature in database
GPG Key ID: DDD48D26958F0D1A
3 changed files with 63 additions and 29 deletions

View File

@ -16,7 +16,7 @@
(define (list-ref (A : Type) (ls : (List A))) (define (list-ref (A : Type) (ls : (List A)))
(match ls (match ls
[nil (lambda (n : Nat) (none A))] [(nil (A : Type)) (lambda (n : Nat) (none A))]
[(cons (A : Type) (a : A) (rest : (List A))) [(cons (A : Type) (a : A) (rest : (List A)))
(lambda (n : Nat) (lambda (n : Nat)
(match n (match n

View File

@ -40,28 +40,25 @@
(define pf:and-is-symmetric (define pf:and-is-symmetric
(lambda (P : Type) (Q : Type) (ab : (And P Q)) (lambda (P : Type) (Q : Type) (ab : (And P Q))
(case* And Type ab (P Q) (match ab
(lambda (P : Type) (Q : Type) (ab : (And P Q)) [(conj (P : Type) (Q : Type) (x : P) (y : Q))
(And Q P)) (conj/i y x)])))
((conj (P : Type) (Q : Type) (x : P) (y : Q)) IH: () (conj/i y x)))))
(define thm:proj1 (define thm:proj1
(forall (A : Type) (B : Type) (c : (And A B)) A)) (forall (A : Type) (B : Type) (c : (And A B)) A))
(define pf:proj1 (define pf:proj1
(lambda (A : Type) (B : Type) (c : (And A B)) (lambda (A : Type) (B : Type) (c : (And A B))
(case* And Type c (A B) (match c
(lambda (A : Type) (B : Type) (c : (And A B)) A) [(conj (A : Type) (B : Type) (a : A) (b : B)) a])))
((conj (A : Type) (B : Type) (a : A) (b : B)) IH: () a))))
(define thm:proj2 (define thm:proj2
(forall (A : Type) (B : Type) (c : (And A B)) B)) (forall (A : Type) (B : Type) (c : (And A B)) B))
(define pf:proj2 (define pf:proj2
(lambda (A : Type) (B : Type) (c : (And A B)) (lambda (A : Type) (B : Type) (c : (And A B))
(case* And Type c (A B) (match c
(lambda (A : Type) (B : Type) (c : (And A B)) B) [(conj (A : Type) (B : Type) (a : A) (b : B)) b])))
((conj (A : Type) (B : Type) (a : A) (b : B)) IH: () b))))
#| TODO: Disabled until #22 fixed #| TODO: Disabled until #22 fixed
(data Or : (forall* (A : Type) (B : Type) Type) (data Or : (forall* (A : Type) (B : Type) Type)

View File

@ -150,9 +150,25 @@
[(_ D U e (p ...) P clause* ...) [(_ D U e (p ...) P clause* ...)
#`(elim D U P #,@(map rewrite-clause (syntax->list #'(clause* ...))) p ... e)])) #`(elim D U P #,@(map rewrite-clause (syntax->list #'(clause* ...))) p ... e)]))
;; Quite fragie to give a syntactic treatment of pattern matching -> eliminator. Replace with "Elimination with a Motive"
(begin-for-syntax (begin-for-syntax
(define ih-dict (make-hash)) (define ih-dict (make-hash))
(define-syntax-class curried-application
(pattern
((~literal real-app) name:id e:expr)
#:attr args
(list #'e))
(pattern
((~literal real-app) a:curried-application e:expr)
#:attr name #'a.name
#:attr args
;; TODO BUG: repeated appends are not performant; cons then reverse in inductive-type-declaration
(append
(attribute a.args)
(list #'e))))
(define-syntax-class inductive-type-declaration (define-syntax-class inductive-type-declaration
(pattern (pattern
x:id x:id
@ -161,21 +177,24 @@
#:attr indices #:attr indices
'() '()
#:attr decls #:attr decls
(list #`(#,(gensym 'anon-discriminant) : x))) (list #`(#,(gensym 'anon-discriminant) : x))
#:attr abstract-indices
values)
(pattern (pattern
;; For some reason app is made explicit here ;; BUG TODO NB: Because the inductive type may have been inferred, it may appear in Curnel syntax, i.e., nested applications starting with dep-app
((~optional (~literal real-app)) x:id e:expr ...+) ;; Best to ensure it *always* is in Curnel form, and pattern match on that.
a:curried-application
#:attr inductive-name #:attr inductive-name
#'x (attribute a.name)
#:attr indices #:attr indices
(attribute e) (attribute a.args)
#:attr names #:attr names
(for/list ([e (attribute e)]) (for/list ([e (attribute indices)])
(format-id e "~a" (gensym 'anon-index))) (format-id e "~a" (gensym 'anon-index)))
#:attr types #:attr types
;; TODO: Detect failure, report error/suggestions ;; TODO: Detect failure, report error/suggestions
(for/list ([e (attribute e)]) (for/list ([e (attribute indices)])
(or (type-infer/syn e) (or (type-infer/syn e)
(raise-syntax-error (raise-syntax-error
'match 'match
@ -187,13 +206,25 @@
(append (append
(for/list ([name (attribute names)] (for/list ([name (attribute names)]
[type (attribute types)] [type (attribute types)]
[src (attribute e)]) [src (attribute indices)])
(quasisyntax/loc src (quasisyntax/loc src
(#,name : #,type))) (#,name : #,type)))
;; TODO: quasisyntax/loc
(list (list
(quasisyntax/loc #'x (quasisyntax/loc #'a
(#,(gensym 'anon-discriminant) : (x #,@(attribute names)))))))) (#,(gensym 'anon-discriminant) : (inductive-name #,@(attribute names))))))
#:attr abstract-indices
(lambda (return)
;; NB: unhygenic
;; Normalize at compile-time, for efficiency at run-time
(normalize/syn
#`((lambda
;; TODO: utteraly fragile; relines on the indices being referred to by name, not computed
;; works only for simple type familes and simply matches on them
#,@(for/list ([name (attribute indices)]
[type (attribute types)])
#`(#,name : #,type))
#,return)
#,@(attribute names))))))
;; todo: Support just names, inferring types ;; todo: Support just names, inferring types
(define-syntax-class match-declaration (define-syntax-class match-declaration
@ -243,9 +274,10 @@
;; NB: Non-hygenic ;; NB: Non-hygenic
;; BUG TODO: This fails when D is an inductive applied to arguments... ;; BUG TODO: This fails when D is an inductive applied to arguments...
#:when (cur-equal? type-syn D)) #:when (cur-equal? type-syn D))
(define/syntax-parse type:inductive-type-declaration type-syn) (define/syntax-parse type:inductive-type-declaration (cur-expand type-syn))
(let ([ih-name (quasisyntax/loc src #,(format-id name-syn "ih-~a" name-syn))] (let ([ih-name (quasisyntax/loc src #,(format-id name-syn "ih-~a" name-syn))]
[ih-type #`(#,motive #,@(attribute type.indices) #,name-syn)]) ;; Normalize at compile-time, for efficiency at run-time
[ih-type (normalize/syn #`(#,motive #,@(attribute type.indices) #,name-syn))])
(dict-set! ih-dict (syntax->datum name-syn) ih-name) (dict-set! ih-dict (syntax->datum name-syn) ih-name)
(append decls (list #`(#,ih-name : #,ih-type))))))) (append decls (list #`(#,ih-name : #,ih-type)))))))
@ -288,18 +320,20 @@
(define-syntax (match syn) (define-syntax (match syn)
(syntax-parse syn (syntax-parse syn
[(_ d:expr [(_ d
~!
(~optional (~optional
(~seq #:in t) (~seq #:in ~! t)
#:defaults #:defaults
([t (or (type-infer/syn #'d) ([t (or (type-infer/syn #'d)
(raise-syntax-error (raise-syntax-error
'match 'match
"Could not infer discrimnant's type. Try using #:in to declare it." "Could not infer discrimnant's type. Try using #:in to declare it."
syn))])) syn))]))
(~parse D:inductive-type-declaration (attribute t)) (~optional (~seq #:return ~! maybe-return-type))
(~optional (~seq #:return maybe-return-type:expr))
(~peek (~seq (~var prec (match-preclause (attribute maybe-return-type))) ...)) (~peek (~seq (~var prec (match-preclause (attribute maybe-return-type))) ...))
~!
(~parse D:inductive-type-declaration (cur-expand (attribute t)))
(~bind (return-type (ormap values (attribute prec.return-type)))) (~bind (return-type (ormap values (attribute prec.return-type))))
(~do (unless (attribute return-type) (~do (unless (attribute return-type)
(raise-syntax-error (raise-syntax-error
@ -307,9 +341,12 @@
"Could not infer return type. Try using #:return to declare it." "Could not infer return type. Try using #:return to declare it."
syn))) syn)))
;; BUG TODO: return-type is inferred with the indexes of the branches, but those must be abstracted in the motive... ;; BUG TODO: return-type is inferred with the indexes of the branches, but those must be abstracted in the motive...
;; Replace each of the D.indicies with the equivalent name from D.decls
(~bind (motive (quasisyntax/loc syn (~bind (motive (quasisyntax/loc syn
(lambda #,@(attribute D.decls) return-type)))) (lambda #,@(attribute D.decls)
#,((attribute D.abstract-indices) (attribute return-type))))))
(~var c (match-clause (attribute D) (attribute motive))) ...) (~var c (match-clause (attribute D) (attribute motive))) ...)
;; TODO: Make all syntax extensions type check, report good error, rather than fail at Curnel
(quasisyntax/loc syn (quasisyntax/loc syn
(elim (elim
D.inductive-name D.inductive-name