;;;
;;; tests of type inference
;;;

(load "4-4.scm")

(type-check "let f = proc (? x) add1(x) in (f 4)")

(type-check "let f = proc (? x) add1(x) in f")

(type-check
"
let apply = proc (?f, ? x) (f add1(x) x)
    g     = proc (? x, ? y) *(x,y)
in (apply g 3)"
) 

                       ; int, 12
 (type-check
"
let apply = proc (?f, ? x) (f add1(x) x)
    g     = proc (? x, ? y) *(x,y)
    h     = proc (? x, ? y) true
in (apply h 3)"
)

(type-check
"
let apply = proc (?f, ? x) (f add1(x) x)
    g     = proc (? x, ? y) *(x,y)
    h     = proc (? x, ? y) true
in (apply h (apply g 3))")


(type-check 
"letrec int f(? x,? y) = +(x,y) 
              in (f 40 50)"
)



            ; int, 90

(type-check 
"
letrec 
  ? fact(? x)= if zero?(x) then 1 else *(x, (fact sub1(x)))
in fact"
) 


 ;  (int -> int)

(type-check
"
letrec ? odd(? x)  = if zero?(x) then 0 else (even sub1(x))
       ? even(? x) = if zero?(x) then 1 else (odd  sub1(x))
in odd" 
)


 ; (int -> int)

(type-check
"
letrec ? odd(? x)  = if zero?(x) then 0 else (even sub1(x))
       ? even(bool x) = if zero?(x) then 1 else (odd  sub1(x))
in (odd 13)"
)



 ; error

;; circular type
(type-check
"
let fix =  proc (? f)
            let d = proc (? x) proc (? z) (f (x x) z)
            in proc (? n) (f (d d) n)
    t4m = proc (? f, ? x) if zero?(x) then 0 else +(4,(f -(x,1)))
in let times4 = (fix t4m)
   in (times4 3)"
)


;  error

(type-check
  "letrec ? even(? odd, ? x) =  if zero?(x) then 1 else (odd sub1(x))
   in letrec  ? odd(? x)  = if zero?(x) then 0 else (even odd sub1(x))
   in (odd 13)"
)


 ;   int

(type-check
"
lettype
  myint = int  % like the integers, but zero is represented as 1!
  myint zero() = 1
  myint succ(myint x) = add1(x)
  myint pred(myint x) = sub1(x)
  bool  iszero?(myint x) =  zero?(-(x,1))
in letrec ? plus(? x,? y) = if (iszero? x) then y else (succ (plus (pred x) y))
in plus"
)


;  (myint * myint -> myint)

(type-check
"
lettype
  myint = int  % like the integers, but zero is represented as 1!
  myint zero() = 1
  myint succ(myint x) = let f = proc(? x) x in add1((f x))
  myint pred(myint x) = sub1(x)
  bool  iszero?(myint x) =  zero?(-(x,1))
in letrec ? plus(? x,? y) = if (iszero? x) then y else (succ (plus (pred x) y))
in plus"
)



   ;     (myint * myint -> myint)
