www

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

stlc+occurrence-tests.rkt (16687B)


      1 #lang s-exp "../stlc+occurrence.rkt"
      2 (require turnstile/examples/tests/rackunit-typechecking)
      3 
      4 ;; -----------------------------------------------------------------------------
      5 ;; basic types & syntax
      6 
      7 (check-type 1 : Int)
      8 (check-type #f : Boolean)
      9 (check-type "hello" : Str)
     10 (check-type 1 : Top)
     11 (check-type (λ ([x : (∪ Boolean Int)]) x)
     12             : (→ (∪ Boolean Int) (∪ Boolean Int)))
     13 
     14 (typecheck-fail
     15  (λ ([x : ∪]) x)
     16  #:with-msg "Improper usage of type constructor ∪: ∪, expected >= 1 arguments")
     17 (typecheck-fail
     18  (λ ([x : (∪)]) x)
     19  #:with-msg "Improper usage of type constructor ∪")
     20 (typecheck-fail
     21  (λ ([x : (∪ ∪)]) x)
     22  #:with-msg "Improper usage of type constructor ∪")
     23 (typecheck-fail
     24  (λ ([x : (1 ∪)]) x)
     25  #:with-msg "")
     26 (typecheck-fail
     27  (λ ([x : (Int ∪)]) x)
     28  #:with-msg "expected identifier")
     29 (typecheck-fail
     30  (λ ([x : (→ ∪ ∪)]) x)
     31  #:with-msg "Improper usage of type constructor ∪")
     32 (typecheck-fail
     33  (λ ([x : (→ Int ∪)]) x)
     34  #:with-msg "Improper usage of type constructor ∪: ∪, expected >= 1 arguments")
     35 (typecheck-fail
     36  (λ ([x : (∪ Int →)]) x)
     37  #:with-msg "Improper usage of type constructor →: →, expected >= 1 arguments")
     38 
     39 ;; -----------------------------------------------------------------------------
     40 ;; --- type evaluation
     41 
     42 (check-type (λ ([x : (∪ Int Int Int Int)]) x)
     43             : (→ Int Int))
     44 (check-type (λ ([x : (∪ Int Boolean)]) 42)
     45             : (→ (∪ Boolean Int) Int))
     46 (check-type (λ ([x : (∪ Int Boolean Boolean Int)]) x)
     47             : (→ (∪ Boolean Int) (∪ Boolean Int)))
     48 (check-type (λ ([x : (∪ (∪ Int Boolean))]) 42)
     49             : (→ (∪ Int Boolean) Int))
     50 (check-type (λ ([x : (∪ Int Boolean)]) 42)
     51             : (→ (∪ (∪ Int Boolean)) Int))
     52 (check-type (λ ([x : (∪ Int Boolean)]) 42)
     53             : (→ (∪ (∪ Int Boolean) (∪ Int Boolean)) Int))
     54 
     55 
     56 ;; -----------------------------------------------------------------------------
     57 ;; --- subtyping
     58 
     59 ;; ---- basics
     60 (check-type 1 : (∪ Int))
     61 (check-type 1 : (∪ (∪ Int)))
     62 (check-type (λ ([x : Int]) x)
     63             : (→ Bot Top))
     64 
     65 (check-not-type 1 : (∪ Boolean))
     66 
     67 ;; - AMB : t <: t' => t <: (U ... t' ...)
     68 (check-type 1 : (∪ Boolean Int))
     69 (check-type -1 : (∪ Int Boolean))
     70 (check-type 1 : (∪ Boolean Int (→ Boolean Boolean)))
     71 (check-type 1 : (∪ (∪ Int Boolean) (∪ Int Boolean)))
     72 
     73 (check-not-type 1 : (∪ Boolean (→ Int Int)))
     74 
     75 ;; --- EXT : (U t' ...) <: (U t t' ...)
     76 (check-type (λ ([x : (∪ Int Boolean)]) x)
     77             : (→ (∪ Int Boolean) (∪ Int Boolean Str)))
     78 (check-type (λ ([x : (∪ Int Boolean)]) x)
     79             : (→ (∪ Boolean) (∪ Int Boolean Str)))
     80 
     81 (check-not-type (λ ([x : (∪ Int Boolean)]) x)
     82             : (→ (∪ Int Boolean) (∪ Int)))
     83 (check-not-type (λ ([x : (∪ Int Boolean)]) x)
     84             : (→ (∪ Boolean Int Str) (∪ Int Boolean)))
     85 
     86 ;; --- SUB : a<:b => (U a t' ...) <: (U b t' ...)
     87 (check-type (λ ([x : (∪ Int Str)]) x)
     88             : (→ (∪ Int Str) (∪ Num Str)))
     89 (check-type (λ ([x : (∪ Int Str)]) x)
     90             : (→ (∪ Nat Str) (∪ Num Str)))
     91 
     92 (check-type (λ ([x : (∪ Int Str)]) x)
     93             : (→ (∪ Int Str) Top))
     94 
     95 (check-not-type (λ ([x : (∪ Int Str)]) x)
     96             : (→ Top (∪ Num Str)))
     97 
     98 ;; --- ALL
     99 (check-type (λ ([x : (∪ Boolean Int Str)]) x)
    100             : (→ (∪ Boolean Int Str) Top))
    101 (check-type (λ ([x : (∪ Nat Int Num)]) x)
    102             : (→ (∪ Nat Int Num) Num))
    103 (check-type (λ ([x : (∪ Nat Int Num)]) x)
    104             : (→ Nat Num))
    105 
    106 ;; --- misc
    107 ;; Because Int<:(U Int ...)
    108 (check-type (λ ([x : (∪ Int Nat)]) #t)
    109                   : (→ Int Boolean))
    110 
    111 ;; -----------------------------------------------------------------------------
    112 ;; --- Basic Filters (applying functions)
    113 
    114 ;; --- is-boolean?
    115 (check-type
    116  (λ ([x : (∪ Boolean Int)])
    117     (test [Boolean ? x]
    118           #t
    119           #f))
    120  : (→ (∪ Boolean Int) Boolean))
    121 (check-type
    122  ((λ ([x : (∪ Boolean Int)])
    123      (test (Boolean ? x)
    124            #t
    125            #f)) #t)
    126   : Boolean ⇒ #t)
    127 (check-type
    128  ((λ ([x : (∪ Boolean Int)])
    129      (test (Boolean ? x)
    130            #t
    131            #f)) 902)
    132   : Boolean ⇒ #f)
    133 
    134 ;; --- successor
    135 (check-type
    136  (λ ([x : (∪ Int Boolean)])
    137     (test (Int ? x)
    138           (+ 1 x)
    139           0))
    140  : (→ (∪ Int Boolean) (∪ Num Nat)))
    141 (check-type
    142  ((λ ([x : (∪ Int Boolean)])
    143     (test (Int ? x)
    144           (+ 1 x)
    145           0)) #f)
    146  : Num ⇒ 0)
    147 (check-type
    148  ((λ ([x : (∪ Int Boolean)])
    149     (test (Int ? x)
    150           (+ 1 x)
    151           1)) #t)
    152  : Num ⇒ 1)
    153 (check-type
    154  ((λ ([x : (∪ Int Boolean)])
    155     (test (Int ? x)
    156           (+ 1 x)
    157           0)) 9000)
    158  : Num ⇒ 9001)
    159 
    160 ;; ;; --- Do-nothing filter
    161 (check-type
    162  (λ ([x : Int])
    163     (test (Int ? x) #t #f))
    164  : (→ Int Boolean))
    165 (check-type
    166  (λ ([x : Int])
    167     (test (Boolean ? x) 0 x))
    168  : (→ Int (∪ Nat Int)))
    169 
    170 ;; --- Filter a subtype
    171 (check-type
    172  (λ ([x : (∪ Nat Boolean)])
    173     (test (Int ? x)
    174           x
    175           x))
    176  : (→ (∪ Nat Boolean) (∪ Int (∪ Nat Boolean))))
    177 
    178 (check-type
    179  (λ ([x : (∪ Int Boolean)])
    180     (test (Nat ? x)
    181           x
    182           x))
    183  : (→ (∪ Boolean Int) (∪ Int Nat Boolean)))
    184 
    185 ;; --- Filter a supertype
    186 (check-type
    187  (λ ([x : (∪ Int Boolean)])
    188     (test (Num ? x)
    189           1
    190           x))
    191  : (→ (∪ Boolean Int) (∪ Nat Boolean)))
    192 
    193 (check-type
    194  ((λ ([x : (∪ Int Boolean)])
    195      (test (Num ? x)
    196            #f
    197            x)) #t)
    198  : Boolean
    199  ⇒ #t)
    200 
    201 ;; Should filter all the impossible types 
    202 (check-type
    203  ((λ ([x : (∪ Nat Int Num Boolean)])
    204      (test (Num ? x)
    205            #f
    206            x)) #t)
    207  : Boolean
    208  ⇒ #t)
    209 
    210 ;; Can refine non-union types
    211 (check-type
    212  ((λ ([x : Top])
    213     (test (Str ? x)
    214           x
    215           "nope"))
    216   "yes")
    217  : Str ⇒ "yes")
    218 
    219 ;; ----------------------------------------------------------------------------- 
    220 ;; --- misc subtyping + filters (regression tests)
    221 (check-type
    222  (λ ([x : (∪ Int Boolean)])
    223     (test (Int ? x)
    224           0
    225           1))
    226  : (→ (∪ Int Boolean) Nat))
    227 (check-type
    228  (λ ([x : (∪ Int Boolean)])
    229     (test (Int ? x)
    230           0
    231           1))
    232  : (→ (∪ Int Boolean) Int))
    233 
    234 ;; -----------------------------------------------------------------------------
    235 ;; --- Invalid filters
    236 
    237 (typecheck-fail
    238  (λ ([x : (∪ Int Boolean)])
    239     (test (1 ? x) #t #f))
    240  #:with-msg "not a well-formed type")
    241 (typecheck-fail
    242  (test (1 ? 1) #t #f)
    243  #:with-msg "not a well-formed type")
    244 (typecheck-fail
    245  (test (1 ? 1) #t #f)
    246  #:with-msg "not a well-formed type")
    247 (typecheck-fail
    248  (test (#f ? #t) #t #f)
    249  #:with-msg "not a well-formed type")
    250 
    251 ;; -----------------------------------------------------------------------------
    252 ;; --- Subtypes should not be collapsed
    253 
    254 (check-not-type (λ ([x : (∪ Int Nat)]) #t)
    255                 : (→ Num Boolean))
    256 (check-type ((λ ([x : (∪ Int Nat Boolean)])
    257                 (test (Int ? x)
    258                       2
    259                       (test (Nat ? x)
    260                             1
    261                             0)))
    262              #t)
    263             : Nat ⇒ 0)
    264 (check-type ((λ ([x : (∪ Int Nat)])
    265                 (test (Nat ? x)
    266                       1
    267                       (test (Int ? x)
    268                             2
    269                             0)))
    270              1)
    271             : Nat ⇒ 1)
    272 (check-type ((λ ([x : (∪ Int Nat)])
    273                 (test (Int ? x)
    274                       2
    275                       (test (Nat ? x)
    276                             1
    277                             0)))
    278              -10)
    279             : Nat ⇒ 2)
    280                
    281 ;; -----------------------------------------------------------------------------
    282 ;; --- Functions in union
    283 
    284 (check-type (λ ([x : (∪ Int (∪ Nat) (∪ (→ Int Str Int)) (→ (→ (→ Int Int)) Int))]) #t)
    285             : (→ (∪ Int Nat (→ Int Str Int) (→ (→ (→ Int Int)) Int)) Boolean))
    286 
    287 (check-type (λ ([x : (∪ Int (→ Int Int))]) #t)
    288             : (→ Int Boolean))
    289 
    290 ;; --- filter functions
    291 (check-type
    292  (λ ([x : (∪ Int (→ Int Int))])
    293     (test ((→ Int Int) ? x)
    294           (x 0)
    295           x))
    296  : (→ (∪ Int (→ Int Int)) Int))
    297 
    298 (check-type
    299  (λ ([x : (∪ (→ Int Int Int) (→ Int Int))])
    300     (test ((→ Int Int) ? x)
    301           (x 0)
    302     (test (Int ? x)
    303           x
    304           (x 1 0))))
    305  : (→ (∪ (→ Int Int Int) (→ Int Int)) Int))
    306 
    307 (check-type
    308  ((λ ([x : (∪ (→ Int Int Int) (→ Int Int) Int)])
    309     (test ((→ Int Int) ? x)
    310           (x 0)
    311     (test (Int ? x)
    312           x
    313           (x 1 0)))) 1)
    314  : Int ⇒ 1)
    315 
    316 (check-type
    317  ((λ ([x : (∪ (→ Int Int Int) (→ Int Int) Int)])
    318     (test ((→ Int Int) ? x)
    319           (x 0)
    320     (test (Int ? x)
    321           x
    322           (x 1 0)))) (λ ([y : Int]) 5))
    323  : Int ⇒ 5)
    324 
    325 (check-type
    326  ((λ ([x : (∪ (→ Int Int Int) (→ Int Int) Int)])
    327     (test ((→ Int Int) ? x)
    328           (x 0)
    329     (test (Int ? x)
    330           x
    331           (x 1 0)))) (λ ([y : Int] [z : Int]) z))
    332  : Int ⇒ 0)
    333 
    334 ;; --- disallow same-arity functions
    335 (typecheck-fail
    336  (λ ([x : (∪ (→ Int Int) (→ Str Str))]) 1)
    337  #:with-msg "Cannot discriminate")
    338 
    339 ;; -----------------------------------------------------------------------------
    340 ;; --- Filter with unions
    341 
    342 (check-type
    343  (λ ([x : (∪ Int Str)])
    344   (test ((∪ Int Str) ? x)
    345         x
    346         "nope"))
    347  : (→ (∪ Int Str) (∪ Int Str)))
    348 
    349 (check-type
    350  (λ ([x : (∪ Int Str Boolean)])
    351     (test ((∪ Int Str) ? x)
    352           x
    353           "Nope"))
    354  : (→ (∪ Int Str Boolean) (∪ Int Str)))
    355 
    356 (check-type
    357  (λ ([x : (∪ Int Str Boolean)])
    358     (test ((∪ Int Str) ? x)
    359           (test (Str ? x)
    360                 "yes"
    361                 "int")
    362           "bool"))
    363  : (→ (∪ Int Str Boolean) Str))
    364 
    365 (check-type
    366  ((λ ([x : (∪ Str Boolean)])
    367      (test ((∪ Int Nat Num) ? x)
    368            x
    369            (+ 1 2))) "hi")
    370  : Num ⇒ 3)
    371 
    372 (check-type
    373   ((λ ([x : (∪ Str Int Boolean)])
    374       (test ((∪ Int Str) ? x)
    375             x
    376             "error")) 1)
    377   : (∪ Str Int) ⇒ 1)
    378 
    379 (check-type
    380   ((λ ([x : (∪ Str Int Boolean)])
    381       (test ((∪ Int Str) ? x)
    382             x
    383             "error")) "hi")
    384   : (∪ Int Str) ⇒ "hi")
    385 
    386 ;; -----------------------------------------------------------------------------
    387 ;; --- Subtyping products
    388 
    389 (check-type (tup 1) : (× Nat))
    390 (check-type (tup 1) : (× Int))
    391 (check-type (tup 1) : (× Num))
    392 (check-type (tup 1) : (× Top))
    393 (check-type (tup 1) : Top)
    394 
    395 (check-not-type (tup 1) : Boolean)
    396 (check-not-type (tup 1) : Str)
    397 (check-not-type (tup 1) : (× Str))
    398 (check-not-type (tup 1) : (× Int Str))
    399 (check-not-type (tup 1) : Bot)
    400 
    401 (check-type (tup 1 2 3) : (× Int Nat Num))
    402 (check-type (tup 1 2 3) : (× Num Nat Num))
    403 (check-type (tup 1 2 3) : (× Top Top Num))
    404 (check-type (tup 1 "2" 3) : (× Int Top Int))
    405 
    406 (check-not-type (tup 1 2 3) : (× Nat Nat Str))
    407 
    408 ;; -----------------------------------------------------------------------------
    409 ;; --- Latent filters (on products)
    410 
    411 (check-type
    412  (λ ([v : (× (∪ Int Str) Int)])
    413     (test (Int ? (proj v 0))
    414           (+ (proj v 0) (proj v 1))
    415           0))
    416  : (→ (× (∪ Int Str) Int) Num))
    417 
    418 (check-type
    419  ((λ ([v : (× (∪ Int Str) Int)])
    420     (test (Int ? (proj v 0))
    421           (+ (proj v 0) (proj v 1))
    422           0))
    423   (tup ((λ ([x : (∪ Int Str)]) x) -2) -3))
    424  : Num ⇒ -5)
    425 
    426 (check-type
    427  ((λ ([v : (× (∪ Int Str) Int)])
    428     (test (Int ? (proj v 0))
    429           (+ (proj v 0) (proj v 1))
    430           0))
    431   (tup "hi" -3))
    432  : Num ⇒ 0)
    433 
    434 ;; --- Use a product as filter
    435 
    436 (check-type
    437  (λ ([x : (∪ Int (× Int Int Int))])
    438     (test (Int ? x)
    439           (+ 1 x)
    440           (+ (proj x 0) (+ (proj x 1) (proj x 2)))))
    441  : (→ (∪ (× Int Int Int) Int) Num))
    442 
    443 (check-type
    444  ((λ ([x : (∪ Int (× Int Int Int))])
    445      (test (Int ? x)
    446            (+ 1 x)
    447            (+ (proj x 0) (+ (proj x 1) (proj x 2)))))
    448   0)
    449  : Num ⇒ 1)
    450 
    451 (check-type
    452  ((λ ([x : (∪ Int (× Int Int Int))])
    453      (test (Int ? x)
    454            (+ 1 x)
    455            (+ (proj x 0) (+ (proj x 1) (proj x 2)))))
    456   (tup 2 2 2))
    457  : Num ⇒ 6)
    458 
    459 (check-type
    460  ((λ ([x : (∪ Int (× Str Nat) (× Int Int Int))])
    461      (test (Int ? x)
    462            (+ 1 x)
    463      (test ((× Int Int Int) ? x)
    464            (+ (proj x 0) (+ (proj x 1) (proj x 2)))
    465            (proj x 1))))
    466   (tup 2 2 2))
    467  : Num ⇒ 6)
    468 
    469 (check-type
    470  ((λ ([x : (∪ Int (× Str Nat) (× Int Int Int))])
    471      (test (Int ? x)
    472            (+ 1 x)
    473      (test ((× Int Int Int) ? x)
    474            (+ (proj x 0) (+ (proj x 1) (proj x 2)))
    475            (proj x 1))))
    476   (tup "yolo" 33))
    477  : Num ⇒ 33)
    478 
    479 ;; -- All together now
    480 
    481 (check-type
    482  ((λ ([x : (∪ Int (× Boolean Boolean) (× Int (∪ Str Int)))])
    483      (test (Int ? x)
    484            "just an int"
    485      (test ((× Boolean Boolean) ? x)
    486            "pair of bools"
    487            (test (Str ? (proj x 1))
    488                  (proj x 1)
    489                  "pair of ints"))))
    490   (tup 33 "success"))
    491  : Str ⇒ "success")
    492 
    493 (check-type
    494  ((λ ([x : (∪ Int (× Int Int) (× Int (∪ Str Int)))])
    495      (test (Int ? x)
    496            "just an int"
    497      (test ((× Int Int) ? x)
    498            "pair of ints"
    499            (test (Str ? (proj x 1))
    500                  (proj x 1)
    501                  "another pair of ints"))))
    502   (tup 33 "success"))
    503  : Str ⇒ "success")
    504 
    505 ;; -----------------------------------------------------------------------------
    506 ;; --- Filter lists
    507 
    508 (check-type
    509  (λ ([x : (List (∪ Int Str))])
    510     (test ((List Str) ? x)
    511           x
    512           #f))
    513  : (→ (List (∪ Int Str)) (∪ Boolean (List Str))))
    514 
    515 ;; -- -subtyping lists
    516 (check-type
    517  (cons 1 (nil {Nat}))
    518  : (List Int))
    519 
    520 (check-type
    521  ((λ ([filter/3 : (→ (List (∪ Int Str)) (List Int))]
    522       [add*/3 : (→ Num (List Num) (List Num))]
    523       [xs : (×  (∪ Int Str) (∪ Int Str) (∪ Int Str))])
    524      (add*/3 5 (filter/3 (cons (proj xs 0)
    525                                (cons (proj xs 1)
    526                                      (cons (proj xs 2)
    527                                            (nil {(∪ Str Int)})))))))
    528   ;; filter (okay this is a little tricky for recursion)
    529   (λ ([xs : (List (∪ Int Str))])
    530      ((λ ([v1 : (∪ Int Str)]
    531           [v2 : (∪ Int Str)]
    532           [v3 : (∪ Int Str)])
    533          (test (Int ? v1)
    534                (cons v1 (test (Int ? v2)
    535                               (cons v2 (test (Int ? v3)
    536                                              (cons v3 (nil {Int}))
    537                                              (nil {Int})))
    538                               (test (Int ? v3)
    539                                     (cons v3 (nil {Int}))
    540                                     (nil {Int}))))
    541                (test (Int ? v2)
    542                      (cons v2 (test (Int ? v3)
    543                                     (cons v3 (nil {Int}))
    544                                     (nil {Int})))
    545                      (test (Int ? v3)
    546                            (cons v3 (nil {Int}))
    547                            (nil {Int})))))
    548       (head xs) (head (tail xs)) (head (tail (tail xs)))))
    549   ;; add3
    550   (λ ([n : Num] [xs : (List Num)])
    551      (cons (+ n (head xs))
    552       (cons (+ n (head (tail xs)))
    553        (cons (+ n (head (tail (tail xs))))
    554         (nil {Num})))))
    555   ;; xs (3-tuple)
    556   (tup 1 "foo" 3))
    557  : (List Num))
    558 
    559 ;; -----------------------------------------------------------------------------
    560 ;; --- ICFP'10 examples
    561 
    562 ;; -- Exaple 1 (x can have any type)
    563 (check-type
    564  (λ ([x : Top])
    565     (test (Num ? x)
    566        (+ 1 x)
    567        0))
    568  : (→ Top Num))
    569 
    570 ;; -- Example 2
    571 (check-type
    572  (λ ([x : (∪ Str Num)]
    573      [str-length : (→ Str Num)])
    574     (test (Num ? x)
    575           (+ 1 x)
    576           (str-length x)))
    577  : (→ (∪ Str Num) (→ Str Num) Num))
    578 
    579 ;; -- TODO Example 3 (requires IF)
    580 ;; (check-type
    581 ;;  (λ ([member : (→ Num (List Num) Boolean)])
    582 ;;     (λ ([x : Num] [l : (List Num)])
    583 ;;        (if (member x l)
    584 ;;            <compute with x>
    585 ;;            <fail>)))
    586 ;;  : <compute-result>
    587 
    588 ;; -- Example 4
    589 (check-type
    590  (λ ([x : (∪ Num Str Top)] [f : (→ (∪ Num Str) Num)])
    591     (test ((∪ Num Str) ? x)
    592           (f x)
    593           0))
    594  : (→ (∪ Num Str Top) (→ (∪ Num Str) Num) Num))
    595 
    596 ;; Exmample 10 (we don't allow non-homogenous lists, so need to select head before filtering)
    597 (check-type
    598  (λ ([p : (List (∪ Nat Str))])
    599     ((λ ([x : (∪ Nat Str)])
    600        (test (Num ? x)
    601              (+ 1 x)
    602              7))
    603     (head p)))
    604  : (→ (List (∪ Nat Str)) Num))
    605 
    606 ;; -----------------------------------------------------------------------------
    607 ;; --- TODO CPS filters
    608 
    609 ;; -----------------------------------------------------------------------------
    610 ;; --- TODO Filter on values (should do nothing)
    611 
    612 ;; (check-type
    613 ;;  (test (Int ? 1) #t #f)
    614 ;;  : Boolean)
    615 
    616 ;; -----------------------------------------------------------------------------
    617 ;; --- TODO Values as filters (check equality)
    618