open Ast open Ast.Value exception No_operation exception No_such_variable of string let rec binop op l r = let tl = typeof l and tr = typeof r in let ty = Type.merge tl tr in let rec promote_until t x = if typeof x = t then x else promote_until t (promote x) in let l = promote_until ty l and r = promote_until ty r in match Binop.get op ty with | None -> begin try binop op (promote l) (promote r) with _ -> raise No_operation end | Some f -> f l r let eval ans ast = let rec aux = function | Value v -> v | Var v -> if v = "ans" then ans else raise @@ No_such_variable v | Binop (l, op, r) -> let l = aux l and r = aux r in binop op l r | Set_binop_pre (op, l) -> let l = match aux l with | Int n -> n | v -> raise @@ Invalid_type (typeof v) in Hashtbl.replace Parser.precedence op l; Nop | Get_binop_pre op -> Int (Hashtbl.find Parser.precedence op) in aux ast