let rec get_if_value_type session_id term =

  match term with 
    Pair(t1,t2) ->
      If_pair(get_if_value_type session_id t1, get_if_value_type  session_id t2)
  | Scrypt(t1,t2) ->
      If_scrypt(get_if_value_type session_id t1, get_if_value_type session_id t2)
  | Crypt(t1,t2) ->
      If_crypt(get_if_value_type session_id t1, get_if_value_type session_id t2)
  | Inv(t) ->
      If_inv(get_if_value_type session_id t)
  | Function(t1,l) ->
      begin
        (*
           The result of the application depends on the type of [t1]. In a first pass,
           we only support the case where [t1] is a variable.
         *)

        match t1 with
          Base(Var(i))
        | Base(Const(i))
        | Prime(Var(i)) -> 
            begin
              let var_type = (Globals.type_table#get_type i) in
              match var_type with
                Function(_) ->
                  (*
                     In this case, we have a function application. We first translate
                     the two components into the [if_value_type] type, and then compute
                     the value of the function.
                   *)

                  let if_value_of_t1 = get_if_value_type session_id t1 in
                  let if_value_of_args = List.map (get_if_value_type session_id) l in
                  find_function_value if_value_of_t1 if_value_of_args
              | Base(Hash_func-> 
                  (*
                     In this case, we have a hash function.
                   *)

                  If_function (get_if_value_type session_id t1, List.map (get_if_value_type session_id) l)
              | _ ->
                  (*
                     In this last case, we have a function application by something with is not
                     a function. We abort.
                   *)

                  if (!debug_level >= 1) then
                    begin
                      prerr_endline ("Application of "^(Globals.string_id#get_name i)^"which is *not* a function.");
                      prerr_endline "Aborting.";
                    end;
                  raise Not_found
            end
        | _ -> 
            if (!debug_level >= 1) then
              begin
                prerr_endline "Function application is currently only supported when the function is a variable or a constant";
                prerr_endline "Aborting.";
              end;
            raise Not_found
      end
  | Cons(t1,t2) ->
      If_cons(get_if_value_type session_id t1, get_if_value_type session_id t2)
  | Delete(t1,t2) ->
      If_delete(get_if_value_type session_id t1, get_if_value_type session_id t2)
  | Set(l) ->
      If_set(List.map (get_if_value_type session_id) l)
(*  | Lst(l) ->
      If_lst(List.map (get_if_value_type session_id) l) *)

  | Base(Var(i)) -> 
      Globals.value_table#get_value (memory_map#get_map (global_var_id#get_id_of session_id i))
  | Base(Const(i)) -> 
      If_const(i)
  | Prime(Var(i)) ->
      If_address (global_var_id#get_id_of session_id i)
  | Prime(_) -> (* add a semantic error in this following case ! *)
      prerr_endline "Utils.get_if_value_type: Warning: invalid primed constant"
      raise Not_found
  | Hash(_) ->
      prerr_endline "Utils.get_if_value_type: Impossible error: invalid hash type/term"
      raise Not_found