/-
Copyright (c) 2017 Gabriel Ebner. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Gabriel Ebner
-/
import .superposition
open tactic monad expr

namespace super

meta def is_demodulator (c : clause) : bool :=
match c^.get_lits with
| [clause.literal.right eqn] := eqn^.is_eq^.is_some
| _ := ff
end

variable gt : expr → expr → bool

meta def demod' (cs1 : list derived_clause) : clause → list derived_clause → tactic (list derived_clause × clause) | c2 used_demods :=
(first $ do
  i ← list.range c2^.num_lits,
  pos ← rwr_positions c2 i,
  c1 ← cs1,
  (ltr, congr_ax) ← [(tt, ``super.sup_ltr), (ff, ``super.sup_rtl)],
  [do c2' ← try_sup gt c1^.c c2 0 i pos ltr tt congr_ax,
      demod' c2' (c1 :: used_demods)]
) <|> return (used_demods, c2)

meta def demod (cs1 : list derived_clause) (c2 : clause) : tactic (list derived_clause × clause) := do
c2qf ← c2^.open_constn c2^.num_quants,
(used_demods, c2qf') ← demod' gt cs1 c2qf.1 [],
if used_demods^.empty then return ([], c2) else
return (used_demods, c2qf'^.close_constn c2qf.2)

meta def demod_fwd_inf : inference :=
take given, do
active ← get_active,
demods ← return (do ac ← active^.values, guard $ is_demodulator ac^.c, guard $ ac^.id ≠ given^.id, [ac]),
if demods^.empty then skip else do
(used_demods, given') ← demod gt demods given^.c,
if used_demods^.empty then skip else do
remove_redundant given^.id used_demods,
mk_derived given' given^.sc^.sched_now >>= add_inferred

meta def demod_back1 (given active : derived_clause) : prover unit := do
(used_demods, c') ← demod gt [given] active^.c,
if used_demods^.empty then skip else do
remove_redundant active^.id used_demods,
mk_derived c' active^.sc^.sched_now >>= add_inferred

meta def demod_back_inf : inference :=
take given, if ¬is_demodulator given^.c then skip else
do active ← get_active, sequence' $ do
ac ← active^.values,
guard $ ac^.id ≠ given^.id,
[demod_back1 gt given ac]

@[super.inf]
meta def demod_inf : inf_decl := {
  prio := 10,
  inf := take given, do
    gt ← get_term_order,
    demod_fwd_inf gt given,
    demod_back_inf gt given,
    skip
}

end super
