(* Baseline: a tiny expression evaluator using ADTs + match *)
type expr =
  | Lit of int
  | Add of expr * expr
  | Mul of expr * expr
  | Neg of expr
;;

let rec eval e =
  match e with
  | Lit n -> n
  | Add (a, b) -> eval a + eval b
  | Mul (a, b) -> eval a * eval b
  | Neg x -> 0 - eval x
;;

(* (1 + 2) * (3 + 4) - 5 = 21 - 5 = 16 *)
eval
  (Add (Mul (Add (Lit 1, Lit 2), Add (Lit 3, Lit 4)), Neg (Lit 5)))
