type expr =
  | Num of int
  | Add of expr * expr
  | Mul of expr * expr

let rec simp e =
  match e with
  | Num n -> Num n
  | Add (a, b) ->
    (match (simp a, simp b) with
     | (Num 0, x) -> x
     | (x, Num 0) -> x
     | (Num n, Num m) -> Num (n + m)
     | (a', b') -> Add (a', b'))
  | Mul (a, b) ->
    (match (simp a, simp b) with
     | (Num 0, _) -> Num 0
     | (_, Num 0) -> Num 0
     | (Num 1, x) -> x
     | (x, Num 1) -> x
     | (Num n, Num m) -> Num (n * m)
     | (a', b') -> Mul (a', b'))

let rec eval e =
  match e with
  | Num n -> n
  | Add (a, b) -> eval a + eval b
  | Mul (a, b) -> eval a * eval b

;;

let e = Add (Mul (Num 3, Num 5), Add (Num 0, Mul (Num 1, Num 7))) in
eval (simp e)
