open Ast

exception Invalid_type

let arith intf a b =
  match a, b with
  | Int a, Int b -> Int (intf a b)
  | _ -> raise Invalid_type

let binop_to_func = function
  | Add -> arith Int.add
  | Sub -> arith Int.sub
  | Mul -> arith Int.mul
  | Div -> arith Int.div
  | Mod -> arith Int.rem
  | _ -> assert false

let rec eval = function
  | Value v -> v
  | Binop (l, op, r) ->
    let f = binop_to_func op in
    f (eval l) (eval r)
  | Set_binop_pre (op, l) ->
    let l = match eval l with Int n -> n | _ -> raise Invalid_type in
    Hashtbl.replace Parser.precedence op l;
    Unit
  | Get_binop_pre op ->
    Int (Hashtbl.find Parser.precedence op)