www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit c151463a6f88ad5d3eed80b1c46254d0a0dd8980
parent a12e85d4bc691b5ba7572915895543a61c7f3f6d
Author: Stephen Chang <stchang@ccs.neu.edu>
Date:   Tue,  4 Aug 2015 17:31:36 -0400

use #%type in stlc+reco+var.rkt; tests passing

Diffstat:
Mtapl/stlc+reco+var.rkt | 37++++++++++++++++++++++---------------
Mtapl/tests/run-all-tests.rkt | 38+++++++++++++++++++-------------------
Mtapl/tests/stlc+reco+var-tests.rkt | 264++++++++++++++++++++++++++++++++++++++++---------------------------------------
3 files changed, 176 insertions(+), 163 deletions(-)

diff --git a/tapl/stlc+reco+var.rkt b/tapl/stlc+reco+var.rkt @@ -7,7 +7,7 @@ (provide (except-out (all-from-out "stlc+tup.rkt") stlc:#%app stlc:let stlc:begin stlc:tup stlc:proj (for-syntax stlc:type=?))) -(provide tup proj); var case) +(provide tup proj var case) (provide (for-syntax type=?)) @@ -56,7 +56,7 @@ ; re-define tuples as records (define-type-constructor - (× [~$ label τ_fld] ...) #:lits (~$) + (× [~× label τ_fld] ...) #:lits (~×) #:declare label str #:declare τ_fld type ) @@ -68,12 +68,12 @@ (syntax-parse stx #:datum-literals (=) [(_ [l:str = e] ...) #:with ([e- τ] ...) (infers+erase #'(e ...)) - (⊢ (list (list l e-) ...) : (× [~$ l τ] ...))] + (⊢ (list (list l e-) ...) : (× [~× l τ] ...))] #;[(_ e ...) #'(stlc:tup e ...)])) (define-syntax (proj stx) (syntax-parse stx #:literals (quote) - [(_ rec l:str ~!) + [(_ rec l:str) #:with [rec- τ_rec] (infer+erase #'rec) ; #:when (printf "inferred type: ~a\n" (syntax->datum #'τ_rec)) ; #:when (printf "inferred type eval ~a\n" (syntax->datum ((current-type-eval) #'τ_rec))) @@ -86,32 +86,39 @@ #;[(_ e ...) #'(stlc:proj e ...)])) -#;(define-type-constructor (∨ [: label τ] ...)) +(define-type-constructor + (∨ [~∨ label τ_var] ...) #:lits (~∨) + #:declare label str + #:declare τ_var type) -#;(define-syntax (var stx) +(define-syntax (var stx) (syntax-parse stx #:datum-literals (as =) #:literals (quote) [(_ l:str = e as τ:type) - #:when (∨? #'τ.norm) - #:with (['l_τ:str τ_l] ...) (stx-map :-args (∨-args #'τ.norm)) +; #:when (∨? #'τ.norm) +; #:with (['l_τ:str τ_l] ...) (stx-map :-args (∨-args #'τ.norm)) + #:with ('l_τ:str ...) (∨-get label from τ) + #:with (τ_l ...) (∨-get τ_var from τ) #:with (l_match:str τ_match) (str-stx-assoc #'l #'((l_τ τ_l) ...)) #:with (e- τ_e) (infer+erase #'e) #:when (typecheck? #'τ_e #'τ_match) - (⊢ #'(list l e) #'τ.norm)])) -#;(define-syntax (case stx) + (⊢ (list l e) : τ)])) +(define-syntax (case stx) (syntax-parse stx #:datum-literals (of =>) #:literals (quote) [(_ e [l:str x => e_l] ...) #:fail-when (null? (syntax->list #'(l ...))) "no clauses" #:with (e- τ_e) (infer+erase #'e) - #:when (∨? #'τ_e) - #:with (['l_x:str τ_x] ...) (stx-map :-args (∨-args #'τ_e)) + #:with ('l_x:str ...) (∨-get label from τ_e) + #:with (τ_x ...) (∨-get τ_var from τ_e) +; #:when (∨? #'τ_e) +; #:with (['l_x:str τ_x] ...) (stx-map :-args (∨-args #'τ_e)) #:fail-unless (= (stx-length #'(l ...)) (stx-length #'(l_x ...))) "wrong number of case clauses" #:fail-unless (typechecks? #'(l ...) #'(l_x ...)) "case clauses not exhaustive" #:with (((x-) e_l- τ_el) ...) (stx-map (λ (bs e) (infer/type-ctxt+erase bs e)) #'(([x : τ_x]) ...) #'(e_l ...)) #:fail-unless (same-types? #'(τ_el ...)) "branches have different types" - (⊢ #'(let ([l_e (car e-)]) - (cond [(string=? l_e l) (let ([x- (cadr e-)]) e_l-)] ...)) - (stx-car #'(τ_el ...)))])) + (⊢ (let ([l_e (car e-)]) + (cond [(string=? l_e l) (let ([x- (cadr e-)]) e_l-)] ...)) + : #,(stx-car #'(τ_el ...)))])) (define-syntax (define/tc stx) (syntax-parse stx diff --git a/tapl/tests/run-all-tests.rkt b/tapl/tests/run-all-tests.rkt @@ -6,21 +6,21 @@ (require "ext-stlc-tests.rkt") (require "stlc+tup-tests.rkt") (require "stlc+reco+var-tests.rkt") -(require "stlc+cons-tests.rkt") -(require "stlc+box-tests.rkt") - -(require "stlc+rec-iso-tests.rkt") - -(require "exist-tests.rkt") - -;; subtyping -(require "stlc+sub-tests.rkt") -(require "stlc+reco+sub-tests.rkt") -(require "fsub-tests.rkt") - -;; system F -(require "sysf-tests.rkt") - -;; F_omega -(require "fomega-tests.rkt") -(require "fomega2-tests.rkt") -\ No newline at end of file +;(require "stlc+cons-tests.rkt") +;(require "stlc+box-tests.rkt") +; +;(require "stlc+rec-iso-tests.rkt") +; +;(require "exist-tests.rkt") +; +;;; subtyping +;(require "stlc+sub-tests.rkt") +;(require "stlc+reco+sub-tests.rkt") +;(require "fsub-tests.rkt") +; +;;; system F +;(require "sysf-tests.rkt") +; +;;; F_omega +;(require "fomega-tests.rkt") +;(require "fomega2-tests.rkt") +\ No newline at end of file diff --git a/tapl/tests/stlc+reco+var-tests.rkt b/tapl/tests/stlc+reco+var-tests.rkt @@ -15,10 +15,10 @@ ; records (ie labeled tuples) (check-type "Stephen" : String) (check-type (tup) : (×)) -(check-type (tup ["name" = "Stephen"]) : (× [~$ "name" String])) +(check-type (tup ["name" = "Stephen"]) : (× [~× "name" String])) (check-type (proj (tup ["name" = "Stephen"]) "name") : String ⇒ "Stephen") (check-type (tup ["name" = "Stephen"] ["phone" = 781] ["male?" = #t]) : - (× [~$ "name" String] [~$ "phone" Int] [~$ "male?" Bool])) + (× [~× "name" String] [~× "phone" Int] [~× "male?" Bool])) (check-type (proj (tup ["name" = "Stephen"] ["phone" = 781] ["male?" = #t]) "name") : String ⇒ "Stephen") (check-type (proj (tup ["name" = "Stephen"] ["phone" = 781] ["male?" = #t]) "name") @@ -28,58 +28,64 @@ (check-type (proj (tup ["name" = "Stephen"] ["phone" = 781] ["male?" = #t]) "male?") : Bool ⇒ #t) (check-not-type (tup ["name" = "Stephen"] ["phone" = 781] ["male?" = #t]) : - (× [~$ "my-name" String] [~$ "phone" Int] [~$ "male?" Bool])) + (× [~× "my-name" String] [~× "phone" Int] [~× "male?" Bool])) (check-not-type (tup ["name" = "Stephen"] ["phone" = 781] ["male?" = #t]) : - (× [~$ "name" String] [~$ "my-phone" Int] [~$ "male?" Bool])) + (× [~× "name" String] [~× "my-phone" Int] [~× "male?" Bool])) (check-not-type (tup ["name" = "Stephen"] ["phone" = 781] ["male?" = #t]) : - (× [~$ "name" String] [~$ "phone" Int] [~$ "is-male?" Bool])) + (× [~× "name" String] [~× "phone" Int] [~× "is-male?" Bool])) ;; variants -;(check-type (var "coffee" = (void) as (∨ [: "coffee" Unit])) : (∨ [: "coffee" Unit])) -;(check-not-type (var "coffee" = (void) as (∨ [: "coffee" Unit])) : (∨ [: "coffee" Unit] [: "tea" Unit])) -;(typecheck-fail ((λ ([x : (∨ [: "coffee" Unit] [: "tea" Unit])]) x) -; (var "coffee" = (void) as (∨ [: "coffee" Unit])))) -;(check-type (var "coffee" = (void) as (∨ [: "coffee" Unit] [: "tea" Unit])) : (∨ [: "coffee" Unit] [: "tea" Unit])) -;(check-type (var "coffee" = (void) as (∨ [: "coffee" Unit] [: "tea" Unit] [: "coke" Unit])) -; : (∨ [: "coffee" Unit] [: "tea" Unit] [: "coke" Unit])) -; -;(typecheck-fail -; (case (var "coffee" = (void) as (∨ [: "coffee" Unit] [: "tea" Unit])) -; ["coffee" x => 1])) ; not enough clauses -;(typecheck-fail -; (case (var "coffee" = (void) as (∨ [: "coffee" Unit] [: "tea" Unit])) -; ["coffee" x => 1] -; ["teaaaaaa" x => 2])) ; wrong clause -;(typecheck-fail -; (case (var "coffee" = (void) as (∨ [: "coffee" Unit] [: "tea" Unit])) -; ["coffee" x => 1] -; ["tea" x => 2] -; ["coke" x => 3])) ; too many clauses -;(typecheck-fail -; (case (var "coffee" = (void) as (∨ [: "coffee" Unit] [: "tea" Unit])) -; ["coffee" x => "1"] -; ["tea" x => 2])) ; mismatched branch types -;(check-type -; (case (var "coffee" = 1 as (∨ [: "coffee" Int] [: "tea" Unit])) -; ["coffee" x => x] -; ["tea" x => 2]) : Int ⇒ 1) -;(define-type-alias Drink (∨ [: "coffee" Int] [: "tea" Unit] [: "coke" Bool])) -;(check-type ((λ ([x : Int]) (+ x x)) 10) : Int ⇒ 20) -;(check-type (λ ([x : Int]) (+ (+ x x) (+ x x))) : (→ Int Int)) -;(check-type -; (case ((λ ([d : Drink]) d) -; (var "coffee" = 1 as (∨ [: "coffee" Int] [: "tea" Unit] [: "coke" Bool]))) -; ["coffee" x => (+ (+ x x) (+ x x))] -; ["tea" x => 2] -; ["coke" y => 3]) -; : Int ⇒ 4) -; -;(check-type -; (case ((λ ([d : Drink]) d) (var "coffee" = 1 as Drink)) -; ["coffee" x => (+ (+ x x) (+ x x))] -; ["tea" x => 2] -; ["coke" y => 3]) -; : Int ⇒ 4) +(check-type (var "coffee" = (void) as (∨ [~∨ "coffee" Unit])) : (∨ [~∨ "coffee" Unit])) +(check-not-type (var "coffee" = (void) as (∨ [~∨ "coffee" Unit])) : (∨ [~∨ "coffee" Unit] [~∨ "tea" Unit])) +(typecheck-fail ((λ ([x : (∨ [~∨ "coffee" Unit] [~∨ "tea" Unit])]) x) + (var "coffee" = (void) as (∨ [~∨ "coffee" Unit]))) + #:with-msg "Arguments to function.+have wrong type") +(check-type (var "coffee" = (void) as (∨ [~∨ "coffee" Unit] [~∨ "tea" Unit])) : + (∨ [~∨ "coffee" Unit] [~∨ "tea" Unit])) +(check-type (var "coffee" = (void) as (∨ [~∨ "coffee" Unit] [~∨ "tea" Unit] [~∨ "coke" Unit])) + : (∨ [~∨ "coffee" Unit] [~∨ "tea" Unit] [~∨ "coke" Unit])) + +(typecheck-fail + (case (var "coffee" = (void) as (∨ [~∨ "coffee" Unit] [~∨ "tea" Unit])) + ["coffee" x => 1]) + #:with-msg "wrong number of case clauses") +(typecheck-fail + (case (var "coffee" = (void) as (∨ [~∨ "coffee" Unit] [~∨ "tea" Unit])) + ["coffee" x => 1] + ["teaaaaaa" x => 2]) + #:with-msg "case clauses not exhaustive") +(typecheck-fail + (case (var "coffee" = (void) as (∨ [~∨ "coffee" Unit] [~∨ "tea" Unit])) + ["coffee" x => 1] + ["tea" x => 2] + ["coke" x => 3]) + #:with-msg "wrong number of case clauses") +(typecheck-fail + (case (var "coffee" = (void) as (∨ [~∨ "coffee" Unit] [~∨ "tea" Unit])) + ["coffee" x => "1"] + ["tea" x => 2]) + #:with-msg "branches have different types") +(check-type + (case (var "coffee" = 1 as (∨ [~∨ "coffee" Int] [~∨ "tea" Unit])) + ["coffee" x => x] + ["tea" x => 2]) : Int ⇒ 1) +(define-type-alias Drink (∨ [~∨ "coffee" Int] [~∨ "tea" Unit] [~∨ "coke" Bool])) +(check-type ((λ ([x : Int]) (+ x x)) 10) : Int ⇒ 20) +(check-type (λ ([x : Int]) (+ (+ x x) (+ x x))) : (→ Int Int)) +(check-type + (case ((λ ([d : Drink]) d) + (var "coffee" = 1 as (∨ [~∨ "coffee" Int] [~∨ "tea" Unit] [~∨ "coke" Bool]))) + ["coffee" x => (+ (+ x x) (+ x x))] + ["tea" x => 2] + ["coke" y => 3]) + : Int ⇒ 4) + +(check-type + (case ((λ ([d : Drink]) d) (var "coffee" = 1 as Drink)) + ["coffee" x => (+ (+ x x) (+ x x))] + ["tea" x => 2] + ["coke" y => 3]) + : Int ⇒ 4) ;; previous tuple tests: ------------------------------------------------------------ ;; wont work anymore @@ -100,85 +106,85 @@ ;; should still pass ;; new literals and base types -;(check-type "one" : String) ; literal now supported -;(check-type #f : Bool) ; literal now supported -; -;(check-type (λ ([x : Bool]) x) : (→ Bool Bool)) ; Bool is now valid type -; -;;; Unit -;(check-type (void) : Unit) -;(check-type void : (→ Unit)) -;(typecheck-fail ((λ ([x : Unit]) x) 2)) -;(typecheck-fail ((λ ([x : Unit])) void)) -;(check-type ((λ ([x : Unit]) x) (void)) : Unit) -; -;;; begin -;(typecheck-fail (begin)) -;(check-type (begin 1) : Int) -;(typecheck-fail (begin 1 2 3)) -;(check-type (begin (void) 1) : Int ⇒ 1) -; -;;;ascription -;(typecheck-fail (ann 1 : Bool)) -;(check-type (ann 1 : Int) : Int ⇒ 1) -;(check-type ((λ ([x : Int]) (ann x : Int)) 10) : Int ⇒ 10) -; +(check-type "one" : String) ; literal now supported +(check-type #f : Bool) ; literal now supported + +(check-type (λ ([x : Bool]) x) : (→ Bool Bool)) ; Bool is now valid type + +;; Unit +(check-type (void) : Unit) +(check-type void : (→ Unit)) +(typecheck-fail ((λ ([x : Unit]) x) 2)) +(typecheck-fail ((λ ([x : Unit])) void)) +(check-type ((λ ([x : Unit]) x) (void)) : Unit) + +;; begin +(typecheck-fail (begin)) +(check-type (begin 1) : Int) +(typecheck-fail (begin 1 2 3)) +(check-type (begin (void) 1) : Int ⇒ 1) + +;;ascription +(typecheck-fail (ann 1 : Bool)) +(check-type (ann 1 : Int) : Int ⇒ 1) +(check-type ((λ ([x : Int]) (ann x : Int)) 10) : Int ⇒ 10) + ;; let -;(check-type (let () (+ 1 1)) : Int ⇒ 2) -;(check-type (let ([x 10]) (+ 1 2)) : Int) -;(typecheck-fail (let ([x #f]) (+ x 1))) -;(check-type (let ([x 10] [y 20]) ((λ ([z : Int] [a : Int]) (+ a z)) x y)) : Int ⇒ 30) -;(typecheck-fail (let ([x 10] [y (+ x 1)]) (+ x y))) ; unbound identifier -; -;(check-type (let* ([x 10] [y (+ x 1)]) (+ x y)) : Int ⇒ 21) -;(typecheck-fail (let* ([x #t] [y (+ x 1)]) 1)) -; -;; letrec -;(typecheck-fail (letrec ([(x : Int) #f] [(y : Int) 1]) y)) -;(typecheck-fail (letrec ([(y : Int) 1] [(x : Int) #f]) x)) -; -;(check-type (letrec ([(x : Int) 1] [(y : Int) (+ x 1)]) (+ x y)) : Int ⇒ 3) -; -;;; recursive -;(check-type -; (letrec ([(countdown : (→ Int String)) -; (λ ([i : Int]) -; (if (= i 0) -; "liftoff" -; (countdown (- i 1))))]) -; (countdown 10)) : String ⇒ "liftoff") -; -;;; mutually recursive -;(check-type -; (letrec ([(is-even? : (→ Int Bool)) -; (λ ([n : Int]) -; (or (zero? n) -; (is-odd? (sub1 n))))] -; [(is-odd? : (→ Int Bool)) -; (λ ([n : Int]) -; (and (not (zero? n)) -; (is-even? (sub1 n))))]) -; (is-odd? 11)) : Bool ⇒ #t) -; -;;; tests from stlc+lit-tests.rkt -------------------------- +(check-type (let () (+ 1 1)) : Int ⇒ 2) +(check-type (let ([x 10]) (+ 1 2)) : Int) +(typecheck-fail (let ([x #f]) (+ x 1))) +(check-type (let ([x 10] [y 20]) ((λ ([z : Int] [a : Int]) (+ a z)) x y)) : Int ⇒ 30) +(typecheck-fail (let ([x 10] [y (+ x 1)]) (+ x y))) ; unbound identifier + +(check-type (let* ([x 10] [y (+ x 1)]) (+ x y)) : Int ⇒ 21) +(typecheck-fail (let* ([x #t] [y (+ x 1)]) 1)) + +; letrec +(typecheck-fail (letrec ([(x : Int) #f] [(y : Int) 1]) y)) +(typecheck-fail (letrec ([(y : Int) 1] [(x : Int) #f]) x)) + +(check-type (letrec ([(x : Int) 1] [(y : Int) (+ x 1)]) (+ x y)) : Int ⇒ 3) + +;; recursive +(check-type + (letrec ([(countdown : (→ Int String)) + (λ ([i : Int]) + (if (= i 0) + "liftoff" + (countdown (- i 1))))]) + (countdown 10)) : String ⇒ "liftoff") + +;; mutually recursive +(check-type + (letrec ([(is-even? : (→ Int Bool)) + (λ ([n : Int]) + (or (zero? n) + (is-odd? (sub1 n))))] + [(is-odd? : (→ Int Bool)) + (λ ([n : Int]) + (and (not (zero? n)) + (is-even? (sub1 n))))]) + (is-odd? 11)) : Bool ⇒ #t) + +;; tests from stlc+lit-tests.rkt -------------------------- ;; most should pass, some failing may now pass due to added types/forms -;(check-type 1 : Int) -;;(check-not-type 1 : (Int → Int)) -;;(typecheck-fail "one") ; literal now supported -;;(typecheck-fail #f) ; literal now supported -;(check-type (λ ([x : Int] [y : Int]) x) : (→ Int Int Int)) -;(check-not-type (λ ([x : Int]) x) : Int) -;(check-type (λ ([x : Int]) x) : (→ Int Int)) -;(check-type (λ ([f : (→ Int Int)]) 1) : (→ (→ Int Int) Int)) -;(check-type ((λ ([x : Int]) x) 1) : Int ⇒ 1) +(check-type 1 : Int) +(check-not-type 1 : (→ Int Int)) +;(typecheck-fail "one") ; literal now supported +;(typecheck-fail #f) ; literal now supported +(check-type (λ ([x : Int] [y : Int]) x) : (→ Int Int Int)) +(check-not-type (λ ([x : Int]) x) : Int) +(check-type (λ ([x : Int]) x) : (→ Int Int)) +(check-type (λ ([f : (→ Int Int)]) 1) : (→ (→ Int Int) Int)) +(check-type ((λ ([x : Int]) x) 1) : Int ⇒ 1) ;(typecheck-fail ((λ ([x : Bool]) x) 1)) ; Bool now valid type, but arg has wrong type -;;(typecheck-fail (λ ([x : Bool]) x)) ; Bool is now valid type -;(typecheck-fail (λ ([f : Int]) (f 1 2))) ; applying f with non-fn type -;(check-type (λ ([f : (→ Int Int Int)] [x : Int] [y : Int]) (f x y)) -; : (→ (→ Int Int Int) Int Int Int)) -;(check-type ((λ ([f : (→ Int Int Int)] [x : Int] [y : Int]) (f x y)) + 1 2) : Int ⇒ 3) -;(typecheck-fail (+ 1 (λ ([x : Int]) x))) ; adding non-Int -;(typecheck-fail (λ ([x : (→ Int Int)]) (+ x x))) ; x should be Int -;(typecheck-fail ((λ ([x : Int] [y : Int]) y) 1)) ; wrong number of args -;(check-type ((λ ([x : Int]) (+ x x)) 10) : Int ⇒ 20) -; +;(typecheck-fail (λ ([x : Bool]) x)) ; Bool is now valid type +(typecheck-fail (λ ([f : Int]) (f 1 2))) ; applying f with non-fn type +(check-type (λ ([f : (→ Int Int Int)] [x : Int] [y : Int]) (f x y)) + : (→ (→ Int Int Int) Int Int Int)) +(check-type ((λ ([f : (→ Int Int Int)] [x : Int] [y : Int]) (f x y)) + 1 2) : Int ⇒ 3) +(typecheck-fail (+ 1 (λ ([x : Int]) x))) ; adding non-Int +(typecheck-fail (λ ([x : (→ Int Int)]) (+ x x))) ; x should be Int +(typecheck-fail ((λ ([x : Int] [y : Int]) y) 1)) ; wrong number of args +(check-type ((λ ([x : Int]) (+ x x)) 10) : Int ⇒ 20) +