#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))