define-typed-syntax: support define-simple-macro-like single-clause syntax

This commit is contained in:
Stephen Chang 2016-09-22 16:56:48 -04:00
parent bce55e8741
commit d0c14c7e07
14 changed files with 205 additions and 233 deletions

View File

@ -14,16 +14,15 @@
(define-type-constructor #:bvs = 1)
(define-typed-syntax pack
[(_ (τ:type e) as ∃τ:type)
#:with (~∃* (τ_abstract) τ_body) #'∃τ.norm
#:with τ_e (subst #'τ.norm #'τ_abstract #'τ_body)
[ e e- τ_e]
--------
[ e- ∃τ.norm]])
(define-typed-syntax (pack (τ:type e) as ∃τ:type)
#:with (~∃* (τ_abstract) τ_body) #'∃τ.norm
#:with τ_e (subst #'τ.norm #'τ_abstract #'τ_body)
[ e e- τ_e]
--------
[ e- ∃τ.norm])
(define-typed-syntax open #:datum-literals (<= with)
[(_ [x:id <= e_packed with X:id] e)
(define-typed-syntax
(open [x:id (~datum <=) e_packed (~datum with) X:id] e)
;; The subst below appears to be a hack, but it's not really.
;; It's the (TaPL) type rule itself that is fast and loose.
;; Leveraging the macro system's management of binding reveals this.
@ -67,8 +66,8 @@
;; ------------------------------
;; Γ ⊢ (open [x <= e_packed with X_2] e) : τ_e
;;
[ e_packed e_packed- (~∃ (Y) τ_body)]
#:with τ_x (subst #'X #'Y #'τ_body)
[([X X- : #%type]) ([x x- : τ_x]) e e- τ_e]
--------
[ (let- ([x- e_packed-]) e-) τ_e]])
[ e_packed e_packed- (~∃ (Y) τ_body)]
#:with τ_x (subst #'X #'Y #'τ_body)
[([X X- : #%type]) ([x x- : τ_x]) e e- τ_e]
--------
[ (let- ([x- e_packed-]) e-) τ_e])

View File

@ -48,17 +48,15 @@
(define-primop sub1 : ( Int Int))
(define-primop not : ( Bool Bool))
(define-typed-syntax and
[(_ e ...)
[ e e- Bool] ...
--------
[ (and- e- ...) Bool]])
(define-typed-syntax (and e ...)
[ e e- Bool] ...
--------
[ (and- e- ...) Bool])
(define-typed-syntax or
[(_ e ...)
[ e e- Bool] ...
--------
[ (or- e- ...) Bool]])
(define-typed-syntax (or e ...)
[ e e- Bool] ...
--------
[ (or- e- ...) Bool])
(begin-for-syntax
(define current-join

View File

@ -82,35 +82,31 @@
(current-type=? type=?)
(current-typecheck-relation (current-type=?)))
(define-typed-syntax Λ
[(_ bvs:kind-ctx e)
[([bvs.x tv- : bvs.kind] ...) () e e- τ_e]
--------
[ e- ( ([tv- : bvs.kind] ...) τ_e)]])
(define-typed-syntax (Λ bvs:kind-ctx e)
[([bvs.x tv- : bvs.kind] ...) () e e- τ_e]
--------
[ e- ( ([tv- : bvs.kind] ...) τ_e)])
(define-typed-syntax inst
[(_ e τ ...)
[ e e- : (~∀ (tv ...) τ_body) ( : (~∀★ k ...))]
[ τ τ- k] ...
#:with τ-inst (substs #'(τ- ...) #'(tv ...) #'τ_body)
--------
[ e- τ-inst]])
(define-typed-syntax (inst e τ ...)
[ e e- : (~∀ (tv ...) τ_body) ( : (~∀★ k ...))]
[ τ τ- k] ...
#:with τ-inst (substs #'(τ- ...) #'(tv ...) #'τ_body)
--------
[ e- τ-inst])
;; TODO: merge with regular λ and app?
;; - see fomega2.rkt
(define-typed-syntax tyλ
[(_ bvs:kind-ctx τ_body)
[[bvs.x tv- : bvs.kind] ... τ_body τ_body- k_body]
#:fail-unless ((current-kind?) #'k_body)
(format "not a valid type: ~a\n" (type->str #'τ_body))
--------
[ (λ- (tv- ...) τ_body-) ( bvs.kind ... k_body)]])
(define-typed-syntax (tyλ bvs:kind-ctx τ_body)
[[bvs.x tv- : bvs.kind] ... τ_body τ_body- k_body]
#:fail-unless ((current-kind?) #'k_body)
(format "not a valid type: ~a\n" (type->str #'τ_body))
--------
[ (λ- (tv- ...) τ_body-) ( bvs.kind ... k_body)])
(define-typed-syntax tyapp
[(_ τ_fn τ_arg ...)
[ τ_fn τ_fn- (~⇒ k_in ... k_out)]
#:fail-unless (stx-length=? #'[k_in ...] #'[τ_arg ...])
(num-args-fail-msg #'τ_fn #'[k_in ...] #'[τ_arg ...])
[ τ_arg τ_arg- k_in] ...
--------
[ (#%app- τ_fn- τ_arg- ...) k_out]])
(define-typed-syntax (tyapp τ_fn τ_arg ...)
[ τ_fn τ_fn- (~⇒ k_in ... k_out)]
#:fail-unless (stx-length=? #'[k_in ...] #'[τ_arg ...])
(num-args-fail-msg #'τ_fn #'[k_in ...] #'[τ_arg ...])
[ τ_arg τ_arg- k_in] ...
--------
[ (#%app- τ_fn- τ_arg- ...) k_out])

View File

@ -78,17 +78,15 @@
(current-type=? type=?)
(current-typecheck-relation (current-type=?)))
(define-typed-syntax Λ
[(_ bvs:kind-ctx e)
[[bvs.x tv- : bvs.kind] ... e e- τ_e]
--------
[ e- ( ([tv- : bvs.kind] ...) τ_e)]])
(define-typed-syntax (Λ bvs:kind-ctx e)
[[bvs.x tv- : bvs.kind] ... e e- τ_e]
--------
[ e- ( ([tv- : bvs.kind] ...) τ_e)])
(define-typed-syntax inst
[(_ e τ ...)
[ e e- : (~∀ (tv ...) τ_body) ( : (~∀★ k ...))]
[ τ τ- k] ...
#:with τ-inst (substs #'(τ- ...) #'(tv ...) #'τ_body)
--------
[ e- τ-inst]])
(define-typed-syntax (inst e τ ...)
[ e e- : (~∀ (tv ...) τ_body) ( : (~∀★ k ...))]
[ τ τ- k] ...
#:with τ-inst (substs #'(τ- ...) #'(tv ...) #'τ_body)
--------
[ e- τ-inst])

View File

@ -44,11 +44,10 @@
;; 2) instantiation of ∀
;; Problem: need type annotations, even in expanded form
;; Solution: store type annotations in a (quasi) kind <:
(define-typed-syntax #:datum-literals (<:)
[(_ ([tv:id <: τ:type] ...) τ_body)
--------
; eval first to overwrite the old #%type
[ #,((current-type-eval) #'(sysf:∀ (tv ...) τ_body)) (<: τ.norm ...)]])
(define-typed-syntax ( ([tv:id (~datum <:) τ:type] ...) τ_body)
--------
; eval first to overwrite the old #%type
[ #,((current-type-eval) #'(sysf:∀ (tv ...) τ_body)) (<: τ.norm ...)])
(begin-for-syntax
(define-syntax ~∀
(pattern-expander
@ -73,20 +72,18 @@
#:src #'any
#:msg "Expected ∀ type, got: ~a" #'any))))]))))
(define-typed-syntax Λ #:datum-literals (<:)
[(_ ([tv:id <: τsub:type] ...) e)
;; NOTE: store the subtyping relation of tv and τsub in the
;; environment with a syntax property using another tag: '<:
;; The "expose" function looks for this tag to enforce the bound,
;; as in TaPL (fig 28-1)
[([tv tv- : #%type <: τsub] ...) () e e- τ_e]
--------
[ e- ( ([tv- <: τsub] ...) τ_e)]])
(define-typed-syntax inst
[(_ e τ:type ...)
[ e e- (~∀ ([tv <: τ_sub] ...) τ_body)]
[τ.norm τ⊑ τ_sub #:for τ] ...
#:with τ_inst (substs #'(τ.norm ...) #'(tv ...) #'τ_body)
--------
[ e- τ_inst]])
(define-typed-syntax (Λ ([tv:id (~datum <:) τsub:type] ...) e)
;; NOTE: store the subtyping relation of tv and τsub in the
;; environment with a syntax property using another tag: '<:
;; The "expose" function looks for this tag to enforce the bound,
;; as in TaPL (fig 28-1)
[([tv tv- : #%type <: τsub] ...) () e e- τ_e]
--------
[ e- ( ([tv- <: τsub] ...) τ_e)])
(define-typed-syntax (inst e τ:type ...)
[ e e- (~∀ ([tv <: τ_sub] ...) τ_body)]
[τ.norm τ⊑ τ_sub #:for τ] ...
#:with τ_inst (substs #'(τ.norm ...) #'(tv ...) #'τ_body)
--------
[ e- τ_inst])

View File

@ -11,22 +11,19 @@
(define-type-constructor Ref)
(define-typed-syntax ref
[(_ e)
[ e e- τ]
--------
[ (box- e-) (Ref τ)]])
(define-typed-syntax (ref e)
[ e e- τ]
--------
[ (box- e-) (Ref τ)])
(define-typed-syntax deref
[(_ e)
[ e e- (~Ref τ)]
--------
[ (unbox- e-) τ]])
(define-typed-syntax (deref e)
[ e e- (~Ref τ)]
--------
[ (unbox- e-) τ])
(define-typed-syntax := #:literals (:=)
[(_ e_ref e)
[ e_ref e_ref- (~Ref τ)]
[ e e- τ]
--------
[ (set-box!- e_ref- e-) Unit]])
(define-typed-syntax (:= e_ref e)
[ e_ref e_ref- (~Ref τ)]
[ e e- τ]
--------
[ (set-box!- e_ref- e-) Unit])

View File

@ -20,29 +20,25 @@
[:id (~List τ)
--------
[ null-]])
(define-typed-syntax cons
[(cons e1 e2)
[ e1 e1- τ1]
[ e2 e2- (List τ1)]
--------
[ _ (cons- e1- e2-) (List τ1)]])
(define-typed-syntax isnil
[(_ e)
[ e e- (~List _)]
--------
[ (null?- e-) Bool]])
(define-typed-syntax head
[(_ e)
[ e e- (~List τ)]
--------
[ (car- e-) τ]])
(define-typed-syntax tail
[(_ e)
[ e e- τ-lst]
#:fail-unless (List? #'τ-lst)
(format "Expected a list type, got: ~a" (type->str #'τ-lst))
--------
[ (cdr- e-) τ-lst]])
(define-typed-syntax (cons e1 e2)
[ e1 e1- τ1]
[ e2 e2- (List τ1)]
--------
[ (cons- e1- e2-) (List τ1)])
(define-typed-syntax (isnil e)
[ e e- (~List _)]
--------
[ (null?- e-) Bool])
(define-typed-syntax (head e)
[ e e- (~List τ)]
--------
[ (car- e-) τ])
(define-typed-syntax (tail e)
[ e e- τ-lst]
#:fail-unless (List? #'τ-lst)
(format "Expected a list type, got: ~a" (type->str #'τ-lst))
--------
[ (cdr- e-) τ-lst])
(define-typed-syntax list
[(_)
--------
@ -53,29 +49,25 @@
[(_ x . rst) ; no expected type
--------
[ (cons x (list . rst))]])
(define-typed-syntax reverse
[(_ e)
[ e e- τ-lst]
#:fail-unless (List? #'τ-lst)
(format "Expected a list type, got: ~a" (type->str #'τ-lst))
--------
[ (reverse- e-) τ-lst]])
(define-typed-syntax length
[(_ e)
[ e e- τ-lst]
#:fail-unless (List? #'τ-lst)
(format "Expected a list type, got: ~a" (type->str #'τ-lst))
--------
[ (length- e-) Int]])
(define-typed-syntax list-ref
[(_ e n)
[ e e- (~List τ)]
[ n n- Int]
--------
[ (list-ref- e- n-) τ]])
(define-typed-syntax member
[(_ v e)
[ e e- (~List τ)]
[ v v- τ]
--------
[ (member- v- e-) Bool]])
(define-typed-syntax (reverse e)
[ e e- τ-lst]
#:fail-unless (List? #'τ-lst)
(format "Expected a list type, got: ~a" (type->str #'τ-lst))
--------
[ (reverse- e-) τ-lst])
(define-typed-syntax (length e)
[ e e- τ-lst]
#:fail-unless (List? #'τ-lst)
(format "Expected a list type, got: ~a" (type->str #'τ-lst))
--------
[ (length- e-) Int])
(define-typed-syntax (list-ref e n)
[ e e- (~List τ)]
[ n n- Int]
--------
[ (list-ref- e- n-) τ])
(define-typed-syntax (member v e)
[ e e- (~List τ)]
[ v v- τ]
--------
[ (member- v- e-) Bool])

View File

@ -31,21 +31,20 @@
(define-typed-syntax effect:#%app #:export-as #%app
[(_ efn e ...)
[ efn e_fn-
( : (~→ τ_in ... τ_out)
( ν (~locs tyns ...))
( := (~locs tyas ...))
( ! (~locs tyds ...)))
( ν (~locs fns ...))
( := (~locs fas ...))
( ! (~locs fds ...))]
( : (~→ τ_in ... τ_out)
( ν (~locs tyns ...))
( := (~locs tyas ...))
( ! (~locs tyds ...)))
( ν (~locs fns ...))
( := (~locs fas ...))
( ! (~locs fds ...))]
#:fail-unless (stx-length=? #'[e ...] #'[τ_in ...])
(num-args-fail-msg #'efn #'[τ_in ...] #'[e ...])
[ [e e_arg-
[ e e_arg-
( : τ_in)
( ν (~locs ns ...))
( := (~locs as ...))
( ! (~locs ds ...))]
...]
( ! (~locs ds ...))] ...
--------
[ (#%app- e_fn- e_arg- ...)
( : τ_out)
@ -53,20 +52,19 @@
( := (locs fas ... tyas ... as ... ...))
( ! (locs fds ... tyds ... ds ... ...))]])
(define-typed-syntax λ
[(_ bvs:type-ctx e)
[[bvs.x x- : bvs.type] ...
e e-
( : τ_res)
( ν (~locs ns ...))
( := (~locs as ...))
( ! (~locs ds ...))]
--------
[ (λ- (x- ...) e-)
( : ( bvs.type ... τ_res)
(define-typed-syntax (λ bvs:type-ctx e)
[[bvs.x x- : bvs.type] ...
e e-
( : τ_res)
( ν (~locs ns ...))
( := (~locs as ...))
( ! (~locs ds ...))]
--------
[ (λ- (x- ...) e-)
( : ( bvs.type ... τ_res)
( ν (locs ns ...))
( := (locs as ...))
( ! (locs ds ...)))]])
( ! (locs ds ...)))])
(define-type-constructor Ref)

View File

@ -36,16 +36,14 @@
(current-type=? type=?)
(current-typecheck-relation type=?))
(define-typed-syntax unfld
[(_ τ:type-ann e)
#:with (~μ* (tv) τ_body) #'τ.norm
[ e e- τ.norm]
--------
[ e- #,(subst #'τ.norm #'tv #'τ_body)]])
(define-typed-syntax fld
[(_ τ:type-ann e)
#:with (~μ* (tv) τ_body) #'τ.norm
#:with τ_e (subst #'τ.norm #'tv #'τ_body)
[ e e- τ_e]
--------
[ e- τ.norm]])
(define-typed-syntax (unfld τ:type-ann e)
#:with (~μ* (tv) τ_body) #'τ.norm
[ e e- τ.norm]
--------
[ e- #,(subst #'τ.norm #'tv #'τ_body)])
(define-typed-syntax (fld τ:type-ann e)
#:with (~μ* (tv) τ_body) #'τ.norm
#:with τ_e (subst #'τ.norm #'tv #'τ_body)
[ e e- τ_e]
--------
[ e- τ.norm])

View File

@ -87,20 +87,18 @@
(add-orig res (get-orig res))])))
;; records
(define-typed-syntax tup #:datum-literals (=)
[(_ [l:id = e] ...)
[ e e- τ] ...
--------
[ (list- (list- 'l e-) ...) (× [l : τ] ...)]])
(define-typed-syntax proj #:literals (quote)
[(_ e_rec l:id)
[ e_rec e_rec- τ_e]
#:fail-unless (×? #'τ_e)
(format "Expected expression ~s to have × type, got: ~a"
(syntax->datum #'e_rec) (type->str #'τ_e))
#:with τ_l (×-ref #'τ_e #'l)
--------
[ (cadr- (assoc- 'l e_rec-)) τ_l]])
(define-typed-syntax (tup [l:id (~datum =) e] ...)
[ e e- τ] ...
--------
[ (list- (list- 'l e-) ...) (× [l : τ] ...)])
(define-typed-syntax (proj e_rec l:id)
[ e_rec e_rec- τ_e]
#:fail-unless (×? #'τ_e)
(format "Expected expression ~s to have × type, got: ~a"
(syntax->datum #'e_rec) (type->str #'τ_e))
#:with τ_l (×-ref #'τ_e #'l)
--------
[ (cadr- (assoc- 'l e_rec-)) τ_l])
(define-type-constructor /internal #:arity >= 0)
@ -161,14 +159,13 @@
--------
[ (list- 'l e)]])
(define-typed-syntax case #:datum-literals (of =>)
[(_ e [l:id x:id => e_l] ...)
#:fail-unless (not (null? (syntax->list #'(l ...)))) "no clauses"
[ e e- (~* [l_x : τ_x] ...)]
#:fail-unless (stx-length=? #'(l ...) #'(l_x ...)) "wrong number of case clauses"
#:fail-unless (typechecks? #'(l ...) #'(l_x ...)) "case clauses not exhaustive"
[[x x- : τ_x] e_l e_l- τ_el] ...
--------
[ (let- ([l_e (car- e-)])
(cond- [(symbol=?- l_e 'l) (let- ([x- (cadr- e-)]) e_l-)] ...))
( τ_el ...)]])
(define-typed-syntax (case e [l:id x:id (~datum =>) e_l] ...)
#:fail-unless (not (null? (syntax->list #'(l ...)))) "no clauses"
[ e e- (~* [l_x : τ_x] ...)]
#:fail-unless (stx-length=? #'(l ...) #'(l_x ...)) "wrong number of case clauses"
#:fail-unless (typechecks? #'(l ...) #'(l_x ...)) "case clauses not exhaustive"
[[x x- : τ_x] e_l e_l- τ_el] ...
--------
[ (let- ([l_e (car- e-)])
(cond- [(symbol=?- l_e 'l) (let- ([x- (cadr- e-)]) e_l-)] ...))
( τ_el ...)])

View File

@ -26,10 +26,9 @@
--------
[ (list- e- ...) (× τ ...)]])
(define-typed-syntax proj
[(_ e_tup n:nat)
[ e_tup e_tup- (~× τ ...)]
#:fail-unless (< (syntax-e #'n) (stx-length #'[τ ...])) "index too large"
--------
[ (list-ref- e_tup- n) #,(stx-list-ref #'[τ ...] (syntax-e #'n))]])
(define-typed-syntax (proj e_tup n:nat)
[ e_tup e_tup- (~× τ ...)]
#:fail-unless (< (syntax-e #'n) (stx-length #'[τ ...])) "index too large"
--------
[ (list-ref- e_tup- n) #,(stx-list-ref #'[τ ...] (syntax-e #'n))])

View File

@ -20,17 +20,15 @@
---------
[ (λ- (x- ...) e-)]])
(define-typed-syntax #%app
[(_ e_fn e_arg ...)
[ e_fn e_fn- (~→ τ_in ... τ_out)]
#:fail-unless (stx-length=? #'[τ_in ...] #'[e_arg ...])
(num-args-fail-msg #'e_fn #'[τ_in ...] #'[e_arg ...])
[ e_arg e_arg- τ_in] ...
--------
[ (#%app- e_fn- e_arg- ...) τ_out]])
(define-typed-syntax (#%app e_fn e_arg ...)
[ e_fn e_fn- (~→ τ_in ... τ_out)]
#:fail-unless (stx-length=? #'[τ_in ...] #'[e_arg ...])
(num-args-fail-msg #'e_fn #'[τ_in ...] #'[e_arg ...])
[ e_arg e_arg- τ_in] ...
--------
[ (#%app- e_fn- e_arg- ...) τ_out])
(define-typed-syntax ann #:datum-literals (:)
[(_ e : τ:type)
[ e e- τ.norm]
--------
[ e- τ.norm]])
(define-typed-syntax (ann e (~datum :) τ:type)
[ e e- τ.norm]
--------
[ e- τ.norm])

View File

@ -14,11 +14,10 @@
(define-type-constructor #:bvs >= 0)
(define-typed-syntax Λ
[(_ (tv:id ...) e)
[([tv tv- : #%type] ...) () e e- τ]
--------
[ e- ( (tv- ...) τ)]])
(define-typed-syntax (Λ (tv:id ...) e)
[([tv tv- : #%type] ...) () e e- τ]
--------
[ e- ( (tv- ...) τ)])
(define-typed-syntax inst
[(_ e τ:type ...)

View File

@ -367,6 +367,12 @@
(define-syntax define-typed-syntax
(lambda (stx)
(syntax-parse stx
;; single-clause def
[(def (name:id . pats) . rst)
;; cannot always bind name as pat var, eg #%app, so replace with _
#:with r:rule #'[(_ . pats) . rst]
#'(-define-typed-syntax name r.norm)]
;; multi-clause def
[(def name:id
(~and (~seq kw-stuff ...) :stxparse-kws)
rule:rule