add stlc tests for recursive define-types (ie intlist)

This commit is contained in:
Stephen Chang 2014-08-13 14:28:45 -04:00
parent e490825797
commit dff0f2b79f
2 changed files with 36 additions and 7 deletions

View File

@ -100,4 +100,29 @@
(check-type-error (define (maybeint->wrong [maybint : MaybeInt])
(cases maybint
[None () #f]
[Just (x) x])))
[Just (x) x])))
(define-type IntList (variant (Null) (Cons Int IntList)))
(check-type-and-result (Null) : IntList => (Null))
(check-type-and-result (Cons 1 (Null)) : IntList => (Cons 1 (Null)))
(check-type-error (Cons "one" (Null)))
(check-type-error (Cons 1 2))
(define (map/IntList [f : ( Int Int)] [lst : IntList])
(cases lst
[Null () (Null)]
[Cons (x xs) (Cons (f x) (map/IntList f xs))]))
(check-type-and-result (map/IntList add1 (Null)) : IntList => (Null))
(check-type-and-result (map/IntList add1 (Cons 1 (Null))) : IntList => (Cons 2 (Null)))
(check-type-and-result (map/IntList add1 (Cons 2 (Cons 1 (Null))))
: IntList => (Cons 3 (Cons 2 (Null))))
(check-type-error (map/IntList (λ ([n : Int]) #f) (Null)))
(define-type BoolList (variant (BoolNull) (BoolCons Bool BoolList)))
(define (map/BoolList [f : ( Bool Int)] [lst : BoolList])
(cases lst
[BoolNull () (Null)]
[BoolCons (x xs) (Cons (f x) (map/BoolList f xs))]))
(check-type (map/BoolList (λ ([b : Bool]) (if b 0 1)) (BoolNull)) : IntList)
(check-type-and-result
(map/BoolList (λ ([b : Bool]) (if b 0 1)) (BoolCons #f (BoolNull)))
: IntList => (Cons 1 (Null)))
(check-not-type (map/BoolList (λ ([b : Bool]) (if b 0 1)) (BoolNull)) : BoolList)

View File

@ -21,8 +21,12 @@
[datum/tc #%datum] [module-begin/tc #%module-begin]
[cons/tc cons] [null/tc null] [null?/tc null?] [first/tc first] [rest/tc rest]))
;; TODO:
;; - type of top level (or module level) vars not checked
;; Simply-Typed Lambda Calculus+
;; Features:
;; - letrec
;; - lists
;; - user (recursive) function definitions
;; - user (recursive) (variant) type-definitions
;; for types, just need the identifier bound
(define-syntax-rule (define-builtin-type τ) (begin (define τ #f) (provide τ)))
@ -176,7 +180,7 @@
#:with ((x ...) ...) (stx-map generate-temporaries #'((τ_fld ...) ...))
#:when (Γ (type-env-extend #'([Cons ( τ_fld ... τ)] ...)))
#'(begin
(struct Cons (x ...)) ...)]))
(struct Cons (x ...) #:transparent) ...)]))
(define-syntax (cases stx)
(syntax-parse stx
[(_ e [Cons (x ...) body ... body_result] ...)
@ -184,7 +188,7 @@
#:with (Cons+ ...) (stx-map expand/df #'(Cons ...))
#:with (( τ ... τ_Cons) ...) (stx-map typeof #'(Cons+ ...))
#:when (stx-andmap (λ (τ) (assert-type #'e+ τ)) #'(τ_Cons ...))
#:with ((lam xs+ body+ ... body_result+) ...)
#:with ((lam (x+ ...) body+ ... body_result+) ...)
(stx-map (λ (bods xs τs)
(with-extended-type-env
(stx-map list xs τs)
@ -197,7 +201,7 @@
#:when (or (null? (syntax->list #'(τ_result ...)))
(andmap (λ (τ) (type=? τ (car (syntax->list #'(τ_result ...)))))
(cdr (syntax->list #'(τ_result ...)))))
#'(match e+ [(Cons+ x ...) body+ ... body_result+] ...)]))
#`(match e+ [(Cons+ x+ ...) body+ ... body_result+] ...)]))
;; typed forms ----------------------------------------------------------------
(define-syntax (datum/tc stx)
@ -379,7 +383,7 @@
#:with (τ ...) (template ((?@ . mb-form.τ) ...))
#:with (e ...) (template ((?@ . mb-form.e) ...))
#:when (Γ (type-env-extend #'([f τ] ...)))
#:when (printf "fvs :~a\n" (fvs))
; #:when (printf "fvs :~a\n" (fvs))
;; error: "Just10: unbound identifier; also, no #%top syntax transformer is bound"
;; cause: for struct def, define-values must come before define-syntaxes
(quasisyntax/loc stx