UNB/ CS/ David Bremner/ teaching/ cs4613/ practices/ practice01/ if-tc.rkt
#lang plait
(define-type BinOp [Plus] [Or]) 

(define-type Exp
  [binE (operator : BinOp)
        (left : Exp)
        (right : Exp)]
  [numE (value : Number)]
  [boolE (value : Boolean)]
  [ifE (check : Exp) (then-e : Exp) (else-e : Exp)])

(define-type Value [boolV (value : Boolean)] [numV (value : Number)])
(define-type Type [boolT] [numT])

(define (expect2 type lt rt)
  (if (and (equal? type lt) (equal? type rt)) type (error 'expect2 "type mismatch")))

(define (tc expr)
  (type-case Exp expr
    [(numE n) (numT)]
    [(boolE b) (boolT)]
    [(ifE check then-e else-e) ....]
    [(binE o l r)
     (let ([l-t (tc l)]
           [r-t (tc r)])
       (type-case BinOp o
         [(Or) (expect2 (boolT) l-t r-t)]
         [(Plus) (expect2 (numT) l-t r-t)]))]))

(test (tc (binE (Plus) (numE 3) (numE 4))) (numT))
(test (tc (binE (Or) (boolE #t) (boolE #f))) (boolT))
(test (tc (ifE (boolE #f) (numE 1) (numE 2)))  (numT))