let is_constant e =
  let rec get_expr_nature e =
    let get_var_def v =
      match v.var_def with
        | Some d -> d
        | None -> raise (Parse_error("internal error (unresolved variable definition)", v.var_pos))
    in
    let is_a_constant v =
      match (get_var_def v).def_value with
        | Constant _ -> true
        | _ -> false
    in
    let score_of_nature = function
      | Cst -> 0
      | Varb -> 1
      | Funct -> 2
      | Unknown_nature -> failwith "trying to get the nature of a not yet typed expression"
    in
    let nature_of_score = function
      | 0 -> Cst
      | 1 -> Varb
      | 2 -> Funct
      | _ -> failwith "internal error"
    in
      match e.expr_val with
        | Lt(e1, e2)
        | Le(e1, e2)
        | Eq(e1, e2)
        | Neq(e1, e2)
        | Plus(e1, e2)
        | Minus(e1, e2)
        | Mult(e1, e2)
        | Div(e1, e2)
        | Mod(e1, e2)
        | And(e1, e2)
        | Or(e1, e2) ->
            nature_of_score (max (score_of_nature (get_expr_nature e1)) (score_of_nature (get_expr_nature e2)))
        | Uminus e
        | Not e -> get_expr_nature e
        | Int _
        | Bool _ -> Cst
        | Var(v, []) when is_a_constant v -> Cst
        | Var(v, _) -> Varb
        | New _
        | Rec _
        | Arr _ -> Varb (* first approximation *)
        | Address_of _
        | Bang _ -> Varb
  in
    match get_expr_nature e with
      | Cst -> true
      | _ -> false