let rec eval_expr_int e =
  match e.expr_val with
    | Int i -> i
    | Var(v, []) when is_some v.var_def ->
        (
          match (get_some v.var_def).def_value with
            | Constant c -> eval_expr_int c
            | _ -> raise (Parse_error("internal error in eval_expr_int function (trying to compute a non-integer expression)", e.expr_pos))
        )
    | Uminus e -> -(eval_expr_int e)
    | Plus(e1, e2) -> (eval_expr_int e1) + (eval_expr_int e2)
    | Minus(e1, e2) -> (eval_expr_int e1) - (eval_expr_int e2)
    | Mult(e1, e2) -> (eval_expr_int e1) * (eval_expr_int e2)
    | Div(e1, e2) -> (eval_expr_int e1) / (eval_expr_int e2)
    | Mod(e1, e2) -> (eval_expr_int e1) mod (eval_expr_int e2)
    | Not _ | And _ | Or _ | Neq _ | Eq _ | Le _ | Lt _ | Bool _
        -> raise (Parse_error("internal error in eval_expr_int function (trying to compute a non-integer expression)", e.expr_pos))
    | Bang _ | Address_of _ | Rec _ | Arr _ | Var _ | New _
        -> raise (Parse_error("internal error in eval_expr_int function (trying to compute a non-constant expression)", e.expr_pos))

(** Compute the value of a constant boolean expression. *)

and eval_expr_bool e =
  match e.expr_val with
    | Bool b -> b
    | Var(v, []) when is_some v.var_def ->
        (
          match (get_some v.var_def).def_value with
            | Constant c -> eval_expr_bool c
            | _ -> raise (Parse_error("internal error in eval_expr_bool function (trying to compute a non-boolean expression)", e.expr_pos))
        )
    | Le(e1, e2) -> (eval_expr_int e1) <= (eval_expr_int e2)
    | Lt(e1, e2) -> (eval_expr_int e1) < (eval_expr_int e2)
    | Eq(e1, e2) ->
        (
          match e1.expr_type with
            | Integer -> (eval_expr_int e1) = (eval_expr_int e2)
            | Boolean -> (eval_expr_bool e1) = (eval_expr_bool e2)
            | _ -> raise (Parse_error("internal error in eval_expr_bool function (equality can only be computed between integers or booleans)", e.expr_pos))
        )
    | Neq(e1, e2) ->
        (
          match e1.expr_type with
            | Integer -> (eval_expr_int e1) <> (eval_expr_int e2)
            | Boolean -> (eval_expr_bool e1) <> (eval_expr_bool e2)
            | _ -> raise (Parse_error("internal error in eval_expr_bool function (inequality can only be computed between integers or booleans)", e.expr_pos))
        )
    | Not e -> not (eval_expr_bool e)
    | Or(e1, e2) -> (eval_expr_bool e1) || (eval_expr_bool e2)
    | And(e1, e2) -> (eval_expr_bool e1) && (eval_expr_bool e2)
    | _ -> raise (Parse_error("internal error in eval_expr_bool function (trying to compute a non-boolean expression)", e.expr_pos))