[Untested] Fixed advanced version of match.

Need to start testing/converting stdlib, replacing case and case*
This commit is contained in:
William J. Bowman 2016-01-15 18:29:10 -05:00
parent 6820c07cd1
commit ceb2a1aefc
No known key found for this signature in database
GPG Key ID: DDD48D26958F0D1A
2 changed files with 46 additions and 29 deletions

View File

@ -35,17 +35,21 @@
(define square (run (exp (s (s z))))) (define square (run (exp (s (s z)))))
;; Credit to this function goes to Max (define (zero? (n : Nat))
(define nat-equal? (match n
(elim Nat Type (lambda (x : Nat) (-> Nat Bool)) [z true]
(elim Nat Type (lambda (x : Nat) Bool) [(s (n : Nat))
true false]))
(lambda (x : Nat) (ih-n2 : Bool) false))
(lambda (x : Nat) (ih : (-> Nat Bool)) (define (nat-equal? (n : Nat))
(elim Nat Type (lambda (x : Nat) Bool) (match n
false [z zero?]
(lambda (x : Nat) (ih-bla : Bool) [(s (n-1 : Nat))
(ih x)))))) (lambda (m : Nat)
(match m
[z false]
[(s (m-1 : Nat))
((recur n-1) m-1)]))]))
(define (even? (n : Nat)) (define (even? (n : Nat))
(match n (match n

View File

@ -157,7 +157,7 @@
#:attr indices #:attr indices
'() '()
#:attr decls #:attr decls
'(#`(#,(gensym) : x))) (list #`(#,(gensym) : x)))
(pattern (pattern
(x:id e:expr ...) (x:id e:expr ...)
@ -173,15 +173,17 @@
(for/list ([e (attribute e)]) (for/list ([e (attribute e)])
(type-infer/syn e)) (type-infer/syn e))
#:attr decls #:attr decls
`(,@(for/list ([name (attribute names)] (append
[type (attribute types)]) (for/list ([name (attribute names)]
#`(name : type)) [type (attribute types)])
#`(#,(gensym) : ((x e ...) #,@(attribute names)))))) #`(name : type))
;; TODO: quasisyntax/loc
(list #`(#,(gensym) : ((x e ...) #,@(attribute names)))))))
;; todo: Support just names, inferring types ;; todo: Support just names, inferring types
(define-syntax-class match-declaration (define-syntax-class match-declaration
(pattern (pattern
;; TODO: Use parameter-declaration defined earlier
(name:id (~datum :) type:expr) (name:id (~datum :) type:expr)
#:attr decl #:attr decl
#'(name : type))) #'(name : type)))
@ -202,7 +204,10 @@
(pattern (pattern
(x:id d:match-declaration ...) (x:id d:match-declaration ...)
#:attr local-env #:attr local-env
(apply dict-set* (make-immutable-hash) (attribute d.name) (attribute d.type)) (for/fold ([d (make-immutable-hash)])
([name (attribute d.name)]
[type (attribute d.type)])
(dict-set d name type))
#:attr decls #:attr decls
(attribute d.decl) (attribute d.decl)
#:attr names #:attr names
@ -221,9 +226,10 @@
[name-syn (attribute d.names)] [name-syn (attribute d.names)]
;; NB: Non-hygenic ;; NB: Non-hygenic
#:when (cur-equal? type-syn D)) #:when (cur-equal? type-syn D))
(let ([ih-name (format-id name-syn "ih-~a" name-syn)] (let ([ih-name (quasisyntax/loc d #,(format-id name-syn "ih-~a" name-syn))]
;; BUG TODO: This is broken; motive must be applied to indices and such, too
[ih-type #`(#,motive #,name-syn)]) [ih-type #`(#,motive #,name-syn)])
(dict-set! ih-dict (syntax-e 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)))))))
(define-syntax-class (match-preclause maybe-return-type) (define-syntax-class (match-preclause maybe-return-type)
@ -231,16 +237,21 @@
(p:match-prepattern b:expr) (p:match-prepattern b:expr)
#:attr return-type #:attr return-type
;; TODO: Check that the infered type matches maybe-return-type, if it is provied ;; TODO: Check that the infered type matches maybe-return-type, if it is provied
(or maybe-return-type (type-infer/syn #:local-env (attribute p.local-env) #'b)))) (or maybe-return-type
;; Ignore errors when trying to infer this type; other attempt might succeed
(with-handlers ([values (lambda _ #f)])
(type-infer/syn #:local-env (attribute p.local-env) #'b)))))
(define-syntax-class (match-clause src D motive) (define-syntax-class (match-clause D motive)
(pattern (pattern
((~var p (match-pattern D motive)) ((~var p (match-pattern D motive))
;; TODO: nothing more advanced? ;; TODO: nothing more advanced?
b:expr) b:expr)
#:attr method #:attr method
(quasisyntax/loc src (quasisyntax/loc #'p
(lambda #,@(attribute p.decls) b))))) #,(if (null? (attribute p.decls))
#'b
#`(lambda #,@(attribute p.decls) b))))))
(define-syntax (recur syn) (define-syntax (recur syn)
(syntax-case syn () (syntax-case syn ()
@ -254,6 +265,7 @@
;; TODO: Detect when inside a match to provide better error ;; TODO: Detect when inside a match to provide better error
(format (format
"Cannot recur on ~a. Ether not inside a match or ~a is not an inductive argument." "Cannot recur on ~a. Ether not inside a match or ~a is not an inductive argument."
(syntax->datum #'id)
(syntax->datum #'id)) (syntax->datum #'id))
syn)))])) syn)))]))
@ -261,13 +273,14 @@
(syntax-parse syn (syntax-parse syn
[(_ d:expr [(_ d:expr
(~optional (~optional
(~seq #:in t:inductive-type-declaration) (~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:expr)) (~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))) ...))
(~bind (return-type (ormap values (attribute prec.return-type)))) (~bind (return-type (ormap values (attribute prec.return-type))))
@ -277,13 +290,13 @@
"Could not infer return type. Try using #:return to declare it." "Could not infer return type. Try using #:return to declare it."
syn))) syn)))
(~bind (motive (quasisyntax/loc syn (~bind (motive (quasisyntax/loc syn
(lambda #,@(attribute t.decls) return-type)))) (lambda #,@(attribute D.decls) return-type))))
(~var c (match-clause syn (attribute t) (attribute motive))) ...) (~var c (match-clause (attribute D) (attribute motive))) ...)
(quasisyntax/loc syn (quasisyntax/loc syn
((elim t.inductive-name #,(type-infer/syn (attribute return-type))) (elim D.inductive-name #,(type-infer/syn (attribute return-type))
motive motive
c.method ... c.method ...
#,@(attribute t.indices) #,@(attribute D.indices)
d))])) d))]))
(begin-for-syntax (begin-for-syntax