let crosscond_to_pred ?event cross op_logic_var status_logic_var =
  let inv = match event with None -> true | Some _ -> false in
  let check_current_event f status pred =
    let (curr_f, curr_status) = Extlib.the event in
    if Kernel_function.equal curr_f f && curr_status = status then pred
    else (Bool3.False, pfalse)
  in
  let rec convert =
    function
    (* Lazy evaluation of logic operators if the result can be statically
       computed *)

    | TOr  (c1, c2) -> (*BinOp(LOr,convert c1,convert c2,Cil.intType)*)
        begin
          let (c1_val,c1_pred) = convert c1 in
          match c1_val with
            | Bool3.True      -> (c1_val,c1_pred)
            | Bool3.False     -> convert c2
            | Undefined ->
                let (c2_val,c2_pred) = convert c2 in
                match c2_val with
                  | Bool3.True      -> (c2_val,c2_pred)
                  | Bool3.False     -> (c1_val,c1_pred)
                  | Undefined -> (Undefined,Logic_const.por(c1_pred, c2_pred))
        end

    | TAnd (c1, c2) -> (*BinOp(LAnd,convert c1,convert c2,Cil.intType)*)
        begin
          let (c1_val,c1_pred) = convert c1 in
          match c1_val with
            | Bool3.True      -> convert c2
            | Bool3.False     -> (c1_val,c1_pred)
            | Undefined ->
                let (c2_val,c2_pred) = convert c2 in
                match c2_val with
                  | Bool3.True      -> (c1_val,c1_pred)
                  | Bool3.False     -> (c2_val,c2_pred)
                  | Undefined -> (Undefined,Logic_const.pand(c1_pred, c2_pred))
        end

    | TNot (c1)     -> (*UnOp(LNot,convert c1,Cil.intType)*)
        begin
          let (c1_val,c1_pred) = convert c1 in
          match c1_val with
            | Bool3.True      -> (Bool3.False,pfalse)
            | Bool3.False     -> (Bool3.True,ptrue)
            | Undefined -> (c1_val,Logic_const.pnot(c1_pred))
        end

    (* Call and return are statically defined -- Case where inv = true *)
    | TCall (kf,b) when inv ->
      let s = Kernel_function.get_name kf in
      let res = 
        [ prel(Req,
              Logic_const.tvar op_logic_var,
              Logic_const.term (TConst(func_to_cenum  s))
                (Ctype (func_enum_type()))
         );
         prel(Req,
              Logic_const.tvar status_logic_var,
              Logic_const.term
                (TConst(op_status_to_cenum Promelaast.Call))
                (Ctype (status_enum_type()))
         )]
      in
      let res = 
        match b with
            None -> res
          | Some b ->
            List.rev_append
              (List.rev_map 
                 Logic_utils.named_of_identified_predicate b.b_assumes)
              res
      in
      (UndefinedLogic_const.pands res)
    | TReturn kf when inv ->
      let s = Kernel_function.get_name kf in
      (Undefined,
       Logic_const.pand(
         prel(Req,
              Logic_const.term
                (TLval(TVar(op_logic_var),TNoOffset))
                (Ctype Cil.intType),
              Logic_const.term
                (TConst(func_to_cenum s))
                (Ctype Cil.intType)
         ),
         prel(Req,
              Logic_const.term
                (TLval(TVar(status_logic_var),TNoOffset))
                (Ctype Cil.intType),
              Logic_const.term
                (TConst(op_status_to_cenum Promelaast.Return))
                (Ctype Cil.intType)
         )
       )
      )
    | TCall (f,b) ->
      let pred = match b with
          None -> Bool3.True, ptrue
        | Some b ->
          (Bool3.Undefined,
           Logic_const.pands
             (List.map Logic_utils.named_of_identified_predicate b.b_assumes))
      in
      check_current_event f Promelaast.Call pred
    | TReturn f ->
      check_current_event f Promelaast.Return (Bool3.True, ptrue)

    (* Other expressions are left unchanged *)
    | TTrue -> (Bool3.True, ptrue)
    | TFalse -> (Bool3.False, pfalse)
    | TRel(rel,t1,t2) ->
      (Bool3.UndefinedLogic_const.prel (rel,t1,t2))
  in
  snd (convert cross)