macrotypes/tapl/tests/exist-tests.rkt
Stephen Chang f5a043b7e6 mlish: add hash, fl prims, str prims, output, and some other prims
- allow begin exprs to have any type (not just unit)
- add fasta test
2016-03-07 00:31:25 -05:00

368 lines
15 KiB
Racket
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#lang s-exp "../exist.rkt"
(require "rackunit-typechecking.rkt")
(check-type (pack (Int 0) as ( (X) X)) : ( (X) X))
(check-type (pack (Int 0) as ( (X) X)) : ( (Y) Y))
(typecheck-fail (pack (Int 0) as ( (X) Y)))
(check-type (pack (Bool #t) as ( (X) X)) : ( (X) X))
(typecheck-fail (pack (Int #t) as ( (X) X)))
(check-type (pack (Int (pack (Int 0) as ( (X) X))) as ( (Y) ( (X) X)))
: ( (Y) ( (X) X)))
(check-type (pack (Int +) as ( (X) ( X Int Int))) : ( (X) ( X Int Int)))
(check-type (pack (Int (pack (Int +) as ( (X) ( X Int Int))))
as ( (Y) ( (X) ( X Y Int))))
: ( (Y) ( (X) ( X Y Int))))
(check-not-type (pack (Int (pack (Int +) as ( (X) ( X Int Int))))
as ( (Y) ( (X) ( X Y Int))))
: ( (X) ( (X) ( X X Int))))
; cant typecheck bc X has local scope, and no X elimination form
;(check-type (open ([(X x) <= (pack (Int 0) as (∃ (X) X))]) x) : X)
(check-type 0 : Int)
(check-type (+ 0 1) : Int 1)
(check-type ((λ ([x : Int]) (+ x 1)) 0) : Int 1)
(typecheck-fail (open ([(X x) <= (pack (Int 0) as ( (X) X))]) (+ x 1))) ; can't use as Int
(check-type (λ ([x : ( (X) X)]) x) : ( ( (X) X) ( (Y) Y)))
(check-type ((λ ([x : ( (X) X)]) x) (pack (Int 0) as ( (Z) Z)))
: ( (X) X) 0)
(check-type ((λ ([x : ( (X) X)]) x) (pack (Bool #t) as ( (Z) Z)))
: ( (X) X) #t)
;; example where the two binding X's are conflated, see exist.rkt for explanation
(check-type (open ([(X x) <= (pack (Int 0) as ( (X) X))]) ((λ ([y : X]) 1) x))
: Int 1)
(check-type
(pack (Int (tup [a = 5] [f = (λ ([x : Int]) (+ x 1))]))
as ( (X) (× [a : X] [f : ( X X)])))
: ( (X) (× [a : X] [f : ( X X)])))
(define p4
(pack (Int (tup [a = 5] [f = (λ ([x : Int]) (+ x 1))]))
as ( (X) (× [a : X] [f : ( X Int)]))))
(check-type p4 : ( (X) (× [a : X] [f : ( X Int)])))
(check-not-type (open ([(X x) <= p4]) (proj x a)) : Int) ; type is X, not Int
; type is (→ X X), not (→ Int Int)
(check-not-type (open ([(X x) <= p4]) (proj x f)) : ( Int Int))
(typecheck-fail (open ([(X x) <= p4]) (+ 1 (proj x a))))
(check-type (open ([(X x) <= p4]) ((proj x f) (proj x a))) : Int 6)
(check-type (open ([(X x) <= p4]) ((λ ([y : X]) ((proj x f) y)) (proj x a))) : Int 6)
(check-type
(open ([(X x) <= (pack (Int 0) as ( (Y) Y))])
((λ ([y : X]) 1) x))
: Int 1)
(check-type
(pack (Int (tup [a = 5] [f = (λ ([x : Int]) (+ x 1))]))
as ( (X) (× [a : Int] [f : ( Int Int)])))
: ( (X) (× [a : Int] [f : ( Int Int)])))
(typecheck-fail
(pack (Int (tup [a = 5] [f = (λ ([x : Int]) (+ x 1))]))
as ( (X) (× [a : Int] [f : ( Bool Int)]))))
(typecheck-fail
(pack (Int (tup [a = 5] [f = (λ ([x : Int]) (+ x 1))]))
as ( (X) (× [a : X] [f : ( X Bool)]))))
(check-type
(pack (Bool (tup [a = #t] [f = (λ ([x : Bool]) (if x 1 2))]))
as ( (X) (× [a : X] [f : ( X Int)])))
: ( (X) (× [a : X] [f : ( X Int)])))
(define counterADT
(pack (Int (tup [new = 1]
[get = (λ ([i : Int]) i)]
[inc = (λ ([i : Int]) (+ i 1))]))
as ( (Counter) (× [new : Counter]
[get : ( Counter Int)]
[inc : ( Counter Counter)]))))
(check-type counterADT :
( (Counter) (× [new : Counter]
[get : ( Counter Int)]
[inc : ( Counter Counter)])))
(typecheck-fail
(open ([(Counter counter) <= counterADT])
(+ (proj counter new) 1))
#:with-msg (expected "Int, Int" #:given "Counter, Int"))
(typecheck-fail
(open ([(Counter counter) <= counterADT])
((λ ([x : Int]) x) (proj counter new)))
#:with-msg (expected "Int" #:given "Counter"))
(check-type
(open ([(Counter counter) <= counterADT])
((proj counter get) ((proj counter inc) (proj counter new))))
: Int 2)
(check-type
(open ([(Counter counter) <= counterADT])
(let ([inc (proj counter inc)]
[get (proj counter get)])
(let ([add3 (λ ([c : Counter]) (inc (inc (inc c))))])
(get (add3 (proj counter new))))))
: Int 4)
(check-type
(open ([(Counter counter) <= counterADT])
(let ([get (proj counter get)]
[inc (proj counter inc)]
[new (λ () (proj counter new))])
(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))))])
(open ([(FlipFlop flipflop) <=
(pack (Counter (tup [new = (new)]
[read = (λ ([c : Counter]) (is-even? (get c)))]
[toggle = (λ ([c : Counter]) (inc c))]
[reset = (λ ([c : Counter]) (new))]))
as ( (FlipFlop) (× [new : FlipFlop]
[read : ( FlipFlop Bool)]
[toggle : ( FlipFlop FlipFlop)]
[reset : ( FlipFlop FlipFlop)])))])
(let ([read (proj flipflop read)]
[togg (proj flipflop toggle)])
(read (togg (togg (togg (togg (proj flipflop new)))))))))))
: Bool #f)
(define counterADT2
(pack ((× [x : Int])
(tup [new = (tup [x = 1])]
[get = (λ ([i : (× [x : Int])]) (proj i x))]
[inc = (λ ([i : (× [x : Int])]) (tup [x = (+ 1 (proj i x))]))]))
as ( (Counter) (× [new : Counter]
[get : ( Counter Int)]
[inc : ( Counter Counter)]))))
(check-type counterADT2 :
( (Counter) (× [new : Counter]
[get : ( Counter Int)]
[inc : ( Counter Counter)])))
;; same as above, but with different internal counter representation
(check-type
(open ([(Counter counter) <= counterADT2])
(let ([get (proj counter get)]
[inc (proj counter inc)]
[new (λ () (proj counter new))])
(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))))])
(open ([(FlipFlop flipflop) <=
(pack (Counter (tup [new = (new)]
[read = (λ ([c : Counter]) (is-even? (get c)))]
[toggle = (λ ([c : Counter]) (inc c))]
[reset = (λ ([c : Counter]) (new))]))
as ( (FlipFlop) (× [new : FlipFlop]
[read : ( FlipFlop Bool)]
[toggle : ( FlipFlop FlipFlop)]
[reset : ( FlipFlop FlipFlop)])))])
(let ([read (proj flipflop read)]
[togg (proj flipflop toggle)])
(read (togg (togg (togg (togg (proj flipflop new)))))))))))
: Bool #f)
;; err cases
(typecheck-fail
(pack (Int 1) as Int)
#:with-msg
"Expected type of expression to match pattern \\(∃ \\(\\(X)) τ_body), got: Int")
(typecheck-fail
(open ([(X x) <= 2]) 3)
#:with-msg
"Expected type of expression to match pattern \\(∃ \\(\\(X)) τ_body), got: Int")
;; previous tets from stlc+reco+var-tests.rkt ---------------------------------
;; define-type-alias
(define-type-alias Integer Int)
(define-type-alias ArithBinOp ( Int Int Int))
;(define-type-alias C Complex) ; error, Complex undefined
(check-type ((λ ([x : Int]) (+ x 2)) 3) : Integer)
(check-type ((λ ([x : Integer]) (+ x 2)) 3) : Int)
(check-type ((λ ([x : Integer]) (+ x 2)) 3) : Integer)
(check-type + : ArithBinOp)
(check-type (λ ([f : ArithBinOp]) (f 1 2)) : ( ( Int Int Int) Int))
;; records (ie labeled tuples)
(check-type "Stephen" : String)
(check-type (tup [name = "Stephen"] [phone = 781] [male? = #t]) :
(× [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)
: String "Stephen")
(check-type (proj (tup [name = "Stephen"] [phone = 781] [male? = #t]) phone)
: Int 781)
(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]))
(check-not-type (tup [name = "Stephen"] [phone = 781] [male? = #t]) :
(× [name : String] [my-phone : Int] [male? : Bool]))
(check-not-type (tup [name = "Stephen"] [phone = 781] [male? = #t]) :
(× [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)
;; previous tests: ------------------------------------------------------------
;; tests for tuples -----------------------------------------------------------
;; old tuple syntax not supported here
;(check-type (tup 1 2 3) : (× Int Int Int))
;(check-type (tup 1 "1" #f +) : (× Int String Bool (→ Int Int Int)))
;(check-not-type (tup 1 "1" #f +) : (× Unit String Bool (→ Int Int Int)))
;(check-not-type (tup 1 "1" #f +) : (× Int Unit Bool (→ Int Int Int)))
;(check-not-type (tup 1 "1" #f +) : (× Int String Unit (→ Int Int Int)))
;(check-not-type (tup 1 "1" #f +) : (× Int String Bool (→ Int Int Unit)))
;
;(check-type (proj (tup 1 "2" #f) 0) : Int ⇒ 1)
;(check-type (proj (tup 1 "2" #f) 1) : String ⇒ "2")
;(check-type (proj (tup 1 "2" #f) 2) : Bool ⇒ #f)
;(typecheck-fail (proj (tup 1 "2" #f) 3)) ; index too large
;(typecheck-fail (proj 1 2)) ; not tuple
;; ext-stlc.rkt tests ---------------------------------------------------------
;; 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)
; 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 --------------------------
; 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)
(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)