let rec mk_apply op a =
if is_i op then a else
match d_apply op with
| k', [b]
when is_k k' ->
b
| s', [c; b]
when is_s s' ->
mk_apply (mk_apply c a) (mk_apply b a)
| c', [d; c; b]
when is_c c' ->
if Term.eq a b then a
else (match Term.is_equal c d with
| Three.Yes -> b
| Three.No -> a
| Three.X ->
if Term.eq d a && Term.eq c b then a
else
(match d_apply b, d_apply a with
| (z, [a']), (z', [b'])
when Term.eq z z'
&& Term.eq d a'
&& Term.eq c b' -> mk_apply z a'
| _ ->
Term.App.mk_app Sym.Cl.apply [c'; d; c; b; a]))
| f', bl ->
(try
if not(!reflection_enabled) then
raise Not_found;
let (op', n') = d_reify f' in
if n' = List.length bl + 1 then
reflect op' (bl @ [a])
else
raise Not_found
with
Not_found ->
Term.App.mk_app Sym.Cl.apply ([f'] @ bl @ [a]))
and mk_apply2 op a1 a2 =
mk_apply (mk_apply op a1) a2
and mk_apply3 op a1 a2 a3 =
mk_apply (mk_apply (mk_apply op a1) a2) a3
and mk_apply_star op = function
| [] -> op
| a :: al ->
let op' = mk_apply op a in
mk_apply_star op' al
and mk_cases a b c d =
mk_apply (mk_apply (mk_apply (mk_apply (mk_c()) a) b) c) d
and sigma op al =
Trace.msg "foo32" "Cl.sigma" (op, al) (Sym.Cl.pp Term.pp);
match op, al with
| Sym.Apply, [x; y] -> mk_apply x y
| Sym.S, [] -> mk_s ()
| Sym.K, [] -> mk_k ()
| Sym.I, [] -> mk_i ()
| Sym.C, [] -> mk_c ()
| Sym.Reify(f, n), [] -> mk_reify (f, n)
| Sym.C, [a; b; c; d] -> mk_cases a b c d
| Sym.S, [a; b; c] -> mk_apply3 (mk_s()) a b c
| Sym.K, [a; b] -> mk_apply2 (mk_k()) a b
| Sym.I, [a] -> mk_apply (mk_i()) a
| Sym.Apply, [c; a1; a2; a3; a4] when is_c(c) -> mk_cases a1 a2 a3 a4
| Sym.Apply, [s; a1; a2; a3] when is_s(s) -> mk_apply3 (mk_s()) a1 a2 a3
| Sym.Apply, [k; a1; a2] when is_k(k) -> mk_apply2 (mk_k()) a1 a2
| _ ->
assert false
and reflect f al =
match Sym.get f with
| Sym.Arith(op) -> Arith.sigma op al
| Sym.Product(op) -> Product.sigma op al
| Sym.Bv(op) -> Bitvector.sigma op al
| Sym.Coproduct(op) -> Coproduct.sigma op al
| Sym.Propset(op) -> Propset.sigma op al
| Sym.Cl(op) -> sigma op al
| Sym.Pp(op) -> Pprod.sigma op al
| Sym.Uninterp _ -> Term.App.mk_app f al
| Sym.Arrays(op) -> Funarr.sigma Term.is_equal op al
and reify f al =
let n = List.length al in
let op = mk_reify (f, n) in
try
reflection_enabled := false;
let b = mk_apply_star op al in
reflection_enabled := true;
b
with
exc ->
reflection_enabled := true;
raise exc