Added better pattern matcher. Undocumented
Added match, a better pattern matching construct than case. Automatically infers inductive arguments, and feature a "recur" syntax. Converted several functions from stdlib/nat to use this.
This commit is contained in:
parent
8eaedabe3b
commit
c3efd3ae6e
|
@ -53,13 +53,13 @@
|
||||||
define-syntax
|
define-syntax
|
||||||
begin-for-syntax
|
begin-for-syntax
|
||||||
define-for-syntax
|
define-for-syntax
|
||||||
(for-syntax (all-from-out syntax/parse))
|
|
||||||
syntax-case
|
syntax-case
|
||||||
syntax-rules
|
syntax-rules
|
||||||
define-syntax-rule
|
define-syntax-rule
|
||||||
(for-syntax (all-from-out racket))
|
|
||||||
;; reflection
|
|
||||||
(for-syntax
|
(for-syntax
|
||||||
|
(all-from-out syntax/parse)
|
||||||
|
(all-from-out racket)
|
||||||
|
(all-from-out racket/syntax)
|
||||||
cur->datum
|
cur->datum
|
||||||
cur-expand
|
cur-expand
|
||||||
type-infer/syn
|
type-infer/syn
|
||||||
|
|
|
@ -15,18 +15,17 @@
|
||||||
(check-equal? (add1 (s z)) (s (s z))))
|
(check-equal? (add1 (s z)) (s (s z))))
|
||||||
|
|
||||||
(define (sub1 (n : Nat))
|
(define (sub1 (n : Nat))
|
||||||
(case n
|
(match n
|
||||||
[z z]
|
[z z]
|
||||||
[(s (x : Nat)) IH: ((ih-n : Nat)) x]))
|
[(s (x : Nat)) x]))
|
||||||
(module+ test
|
(module+ test
|
||||||
(check-equal? (sub1 (s z)) z))
|
(check-equal? (sub1 (s z)) z))
|
||||||
|
|
||||||
(define (plus (n1 : Nat) (n2 : Nat))
|
(define (plus (n1 : Nat) (n2 : Nat))
|
||||||
(case n1
|
(match n1
|
||||||
[z n2]
|
[z n2]
|
||||||
[(s (x : Nat))
|
[(s (x : Nat))
|
||||||
IH: ((ih-n1 : Nat))
|
(s (recur x))]))
|
||||||
(s ih-n1)]))
|
|
||||||
(module+ test
|
(module+ test
|
||||||
(check-equal? (plus z z) z)
|
(check-equal? (plus z z) z)
|
||||||
(check-equal? (plus (s (s z)) (s (s z))) (s (s (s (s z))))))
|
(check-equal? (plus (s (s z)) (s (s z))) (s (s (s (s z))))))
|
||||||
|
@ -48,11 +47,10 @@
|
||||||
(check-equal? (nat-equal? (s z) (s z)) true))
|
(check-equal? (nat-equal? (s z) (s z)) true))
|
||||||
|
|
||||||
(define (even? (n : Nat))
|
(define (even? (n : Nat))
|
||||||
(elim Nat Type (lambda (x : Nat) Bool)
|
(match n
|
||||||
true
|
[z true]
|
||||||
(lambda* (n : Nat) (odd? : Bool)
|
[(s (n : Nat))
|
||||||
(not odd?))
|
(not (recur n))]))
|
||||||
n))
|
|
||||||
|
|
||||||
(define (odd? (n : Nat))
|
(define (odd? (n : Nat))
|
||||||
(not (even? n)))
|
(not (even? n)))
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
define-type
|
define-type
|
||||||
case
|
case
|
||||||
case*
|
case*
|
||||||
|
match
|
||||||
|
recur
|
||||||
let
|
let
|
||||||
|
|
||||||
;; type-check
|
;; type-check
|
||||||
|
@ -24,8 +26,7 @@
|
||||||
run
|
run
|
||||||
step
|
step
|
||||||
step-n
|
step-n
|
||||||
query-type
|
query-type)
|
||||||
)
|
|
||||||
|
|
||||||
(require
|
(require
|
||||||
(only-in "../cur.rkt"
|
(only-in "../cur.rkt"
|
||||||
|
@ -33,7 +34,6 @@
|
||||||
[#%app real-app]
|
[#%app real-app]
|
||||||
[define real-define]))
|
[define real-define]))
|
||||||
|
|
||||||
|
|
||||||
(define-syntax (-> syn)
|
(define-syntax (-> syn)
|
||||||
(syntax-case syn ()
|
(syntax-case syn ()
|
||||||
[(_ t1 t2) #`(forall (#,(gensym) : t1) t2)]))
|
[(_ t1 t2) #`(forall (#,(gensym) : t1) t2)]))
|
||||||
|
@ -112,6 +112,67 @@
|
||||||
[(_ 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)]))
|
||||||
|
|
||||||
|
(begin-for-syntax
|
||||||
|
(define-struct clause (args body))
|
||||||
|
(define ih-dict (make-hash))
|
||||||
|
(define (clause-parse syn)
|
||||||
|
(syntax-case syn (:)
|
||||||
|
[((con (a : A) ...) body)
|
||||||
|
(make-clause #'((a : A) ...) #'body)]
|
||||||
|
[(e body)
|
||||||
|
(make-clause #'() #'body)]))
|
||||||
|
|
||||||
|
(define (infer-result clauses)
|
||||||
|
(for/or ([clause clauses])
|
||||||
|
(type-infer/syn (clause-body clause))))
|
||||||
|
|
||||||
|
(define (infer-ihs D motive args-syn)
|
||||||
|
(syntax-case args-syn (:)
|
||||||
|
[((a : A) ...)
|
||||||
|
(for/fold ([ih-dict (make-immutable-hash)])
|
||||||
|
([type-syn (syntax->list #'(A ...))]
|
||||||
|
[arg-syn (syntax->list #'(a ...))]
|
||||||
|
;; NB: Non-hygenic
|
||||||
|
#:when (cur-equal? type-syn D))
|
||||||
|
(dict-set ih-dict (syntax->datum arg-syn) `(,(format-id args-syn "ih-~a" arg-syn) . ,#`(#,motive #,arg-syn))))]
|
||||||
|
[() '()]))
|
||||||
|
|
||||||
|
(define (clause->method D motive clause)
|
||||||
|
(dict-clear! ih-dict)
|
||||||
|
(let* ([ihs (infer-ihs D motive (clause-args clause))]
|
||||||
|
[ih-args (dict-map
|
||||||
|
ihs
|
||||||
|
(lambda (k v)
|
||||||
|
(dict-set! ih-dict k (car v))
|
||||||
|
#`(#,(car v) : #,(cdr v))))])
|
||||||
|
#`(lambda* #,@(clause-args clause) #,@ih-args #,(clause-body clause)))))
|
||||||
|
|
||||||
|
(define-syntax (recur syn)
|
||||||
|
(syntax-case syn ()
|
||||||
|
[(_ id)
|
||||||
|
(dict-ref
|
||||||
|
ih-dict
|
||||||
|
(syntax->datum #'id)
|
||||||
|
(lambda ()
|
||||||
|
(raise-syntax-error
|
||||||
|
'match
|
||||||
|
(format "Cannot recur on ~a" (syntax->datum #'id))
|
||||||
|
syn)))]))
|
||||||
|
|
||||||
|
;; TODO: Test
|
||||||
|
(define-syntax (match syn)
|
||||||
|
(syntax-case syn ()
|
||||||
|
[(_ e clause* ...)
|
||||||
|
(let* ([clauses (map clause-parse (syntax->list #'(clause* ...)))]
|
||||||
|
[R (infer-result clauses)]
|
||||||
|
[D (type-infer/syn #'e)]
|
||||||
|
[motive #`(lambda (x : #,D) #,R)]
|
||||||
|
[U (type-infer/syn R)])
|
||||||
|
#`((elim #,D #,U)
|
||||||
|
#,motive
|
||||||
|
#,@(map (curry clause->method D motive) clauses)
|
||||||
|
e))]))
|
||||||
|
|
||||||
(begin-for-syntax
|
(begin-for-syntax
|
||||||
(define-syntax-class let-clause
|
(define-syntax-class let-clause
|
||||||
(pattern
|
(pattern
|
||||||
|
|
Loading…
Reference in New Issue
Block a user