feat(library/init/meta/smt_tactic): add assert/assertv/define/definev/pose/note for smt_tactic
This commit is contained in:
parent
b636f03bb9
commit
3adcf30d2f
7 changed files with 167 additions and 70 deletions
|
|
@ -83,8 +83,13 @@ meta instance : alternative smt_tactic :=
|
|||
map := @fmap _ _}
|
||||
|
||||
namespace smt_tactic
|
||||
meta constant intros : smt_tactic unit
|
||||
meta constant close : smt_tactic unit
|
||||
/-- (intros_core fresh_names), if fresh_names is tt, then create fresh names for new hypotheses.
|
||||
Otherwise, it just uses the given names. -/
|
||||
meta constant intros_core : bool → smt_tactic unit
|
||||
meta constant close : smt_tactic unit
|
||||
|
||||
meta def intros : smt_tactic unit :=
|
||||
intros_core tt
|
||||
|
||||
meta def try {α : Type} (t : smt_tactic α) : smt_tactic unit :=
|
||||
λ ss ts, tactic_result.cases_on (t ss ts)
|
||||
|
|
@ -146,6 +151,39 @@ do (s::ss, t::ts) ← get_goals | failed,
|
|||
(new_ss, new_ts) ← get_goals,
|
||||
set_goals (new_ss ++ ss) (new_ts ++ ts)
|
||||
|
||||
meta def swap : smt_tactic unit :=
|
||||
do (ss, ts) ← get_goals,
|
||||
match ss, ts with
|
||||
| (s₁ :: s₂ :: ss), (t₁ :: t₂ :: ts) := set_goals (s₂ :: s₁ :: ss) (t₂ :: t₁ :: ts)
|
||||
| _, _ := failed
|
||||
end
|
||||
|
||||
/- (assert h t), adds a new goal for t, and the hypothesis (h : t) in the current goal. -/
|
||||
meta def assert (h : name) (t : expr) : smt_tactic unit :=
|
||||
tactic.assert_core h t >> swap >> intros_core ff >> swap >> try close
|
||||
|
||||
/- (assertv h t v), adds the hypothesis (h : t) in the current goal if v has type t. -/
|
||||
meta def assertv (h : name) (t : expr) (v : expr) : smt_tactic unit :=
|
||||
tactic.assertv_core h t v >> intros_core ff >> return ()
|
||||
|
||||
/- (define h t), adds a new goal for t, and the hypothesis (h : t := ?M) in the current goal. -/
|
||||
meta def define (h : name) (t : expr) : smt_tactic unit :=
|
||||
tactic.define_core h t >> swap >> intros_core ff >> swap >> try close
|
||||
|
||||
/- (definev h t v), adds the hypothesis (h : t := v) in the current goal if v has type t. -/
|
||||
meta def definev (h : name) (t : expr) (v : expr) : smt_tactic unit :=
|
||||
tactic.definev_core h t v >> intros_core ff >> return ()
|
||||
|
||||
/- Add (h : t := pr) to the current goal -/
|
||||
meta def pose (h : name) (pr : expr) : smt_tactic unit :=
|
||||
do t ← tactic.infer_type pr,
|
||||
definev h t pr
|
||||
|
||||
/- Add (h : t) to the current goal, given a proof (pr : t) -/
|
||||
meta def note (n : name) (pr : expr) : smt_tactic unit :=
|
||||
do t ← tactic.infer_type pr,
|
||||
assertv n t pr
|
||||
|
||||
meta def destruct (e : expr) : smt_tactic unit :=
|
||||
smt_tactic.seq (tactic.destruct e) smt_tactic.intros
|
||||
|
||||
|
|
|
|||
|
|
@ -305,14 +305,14 @@ meta constant mk_instance : expr → tactic expr
|
|||
/- Change the target of the main goal.
|
||||
The input expression must be definitionally equal to the current target. -/
|
||||
meta constant change : expr → tactic unit
|
||||
/- (assert H T), adds a new goal for T, and the hypothesis (H : T) in the current goal. -/
|
||||
meta constant assert : name → expr → tactic unit
|
||||
/- (assertv H T P), adds the hypothesis (H : T) in the current goal if P has type T. -/
|
||||
meta constant assertv : name → expr → expr → tactic unit
|
||||
/- (define H T), adds a new goal for T, and the hypothesis (H : T := ?M) in the current goal. -/
|
||||
meta constant define : name → expr → tactic unit
|
||||
/- (definev H T P), adds the hypothesis (H : T := P) in the current goal if P has type T. -/
|
||||
meta constant definev : name → expr → expr → tactic unit
|
||||
/- (assert_core H T), adds a new goal for T, and change target to (T -> target). -/
|
||||
meta constant assert_core : name → expr → tactic unit
|
||||
/- (assertv_core H T P), change target to (T -> target) if P has type T. -/
|
||||
meta constant assertv_core : name → expr → expr → tactic unit
|
||||
/- (define_core H T), adds a new goal for T, and change target to (let H : T := ?M in target) in the current goal. -/
|
||||
meta constant define_core : name → expr → tactic unit
|
||||
/- (definev_core H T P), change target to (Let H : T := P in target) if P has type T. -/
|
||||
meta constant definev_core : name → expr → expr → tactic unit
|
||||
/- rotate goals to the left -/
|
||||
meta constant rotate_left : nat → tactic unit
|
||||
meta constant get_goals : tactic (list expr)
|
||||
|
|
@ -393,16 +393,6 @@ get_goals >>= set_goals
|
|||
meta def step {α : Type u} (t : tactic α) : tactic unit :=
|
||||
t >>[tactic] cleanup
|
||||
|
||||
/- Add (H : T := pr) to the current goal -/
|
||||
meta def pose (n : name) (pr : expr) : tactic unit :=
|
||||
do t ← infer_type pr,
|
||||
definev n t pr
|
||||
|
||||
/- Add (H : T) to the current goal, given a proof (pr : T) -/
|
||||
meta def note (n : name) (pr : expr) : tactic unit :=
|
||||
do t ← infer_type pr,
|
||||
assertv n t pr
|
||||
|
||||
meta def is_prop (e : expr) : tactic bool :=
|
||||
do t ← infer_type e,
|
||||
return (to_bool (t = expr.prop))
|
||||
|
|
@ -537,6 +527,32 @@ do gs ← get_goals,
|
|||
| e := skip
|
||||
end
|
||||
|
||||
/- (assert h t), adds a new goal for t, and the hypothesis (h : t) in the current goal. -/
|
||||
meta def assert (h : name) (t : expr) : tactic unit :=
|
||||
assert_core h t >> swap >> intro h >> swap
|
||||
|
||||
/- (assertv h t v), adds the hypothesis (h : t) in the current goal if v has type t. -/
|
||||
meta def assertv (h : name) (t : expr) (v : expr) : tactic unit :=
|
||||
assertv_core h t v >> intro h >> return ()
|
||||
|
||||
/- (define h t), adds a new goal for t, and the hypothesis (h : t := ?M) in the current goal. -/
|
||||
meta def define (h : name) (t : expr) : tactic unit :=
|
||||
define_core h t >> swap >> intro h >> swap
|
||||
|
||||
/- (definev h t v), adds the hypothesis (h : t := v) in the current goal if v has type t. -/
|
||||
meta def definev (h : name) (t : expr) (v : expr) : tactic unit :=
|
||||
definev_core h t v >> intro h >> return ()
|
||||
|
||||
/- Add (h : t := pr) to the current goal -/
|
||||
meta def pose (h : name) (pr : expr) : tactic unit :=
|
||||
do t ← infer_type pr,
|
||||
definev h t pr
|
||||
|
||||
/- Add (h : t) to the current goal, given a proof (pr : t) -/
|
||||
meta def note (n : name) (pr : expr) : tactic unit :=
|
||||
do t ← infer_type pr,
|
||||
assertv n t pr
|
||||
|
||||
/- Return the number of goals that need to be solved -/
|
||||
meta def num_goals : tactic nat :=
|
||||
do gs ← get_goals,
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@ Author: Leonardo de Moura
|
|||
#include "library/vm/vm_name.h"
|
||||
#include "library/vm/vm_expr.h"
|
||||
#include "library/tactic/tactic_state.h"
|
||||
#include "library/tactic/intro_tactic.h"
|
||||
|
||||
namespace lean {
|
||||
vm_obj assert_define(bool is_assert, name const & n, expr const & t, tactic_state const & s) {
|
||||
vm_obj assert_define_core(bool is_assert, name const & n, expr const & t, tactic_state const & s) {
|
||||
optional<metavar_decl> g = s.get_main_goal_decl();
|
||||
if (!g) return mk_no_goals_exception(s);
|
||||
type_context ctx = mk_type_context_for(s);
|
||||
|
|
@ -24,31 +25,30 @@ vm_obj assert_define(bool is_assert, name const & n, expr const & t, tactic_stat
|
|||
local_context lctx = g->get_context();
|
||||
metavar_context mctx = ctx.mctx();
|
||||
expr new_M_1 = mctx.mk_metavar_decl(lctx, t);
|
||||
expr l;
|
||||
if (is_assert)
|
||||
l = lctx.mk_local_decl(n, t);
|
||||
else
|
||||
l = lctx.mk_local_decl(n, t, new_M_1);
|
||||
expr new_M_2 = mctx.mk_metavar_decl(lctx, g->get_type());
|
||||
expr new_val;
|
||||
if (is_assert)
|
||||
new_val = mk_app(mk_lambda(n, t, mk_delayed_abstraction(new_M_2, mlocal_name(l))), new_M_1);
|
||||
else
|
||||
new_val = mk_let(n, t, new_M_1, mk_delayed_abstraction(new_M_2, mlocal_name(l)));
|
||||
expr new_M_2, new_val;
|
||||
if (is_assert) {
|
||||
expr new_target = mk_pi(n, t, g->get_type());
|
||||
new_M_2 = mctx.mk_metavar_decl(lctx, new_target);
|
||||
new_val = mk_app(new_M_2, new_M_1);
|
||||
} else {
|
||||
expr new_target = mk_let(n, t, new_M_1, g->get_type());
|
||||
new_M_2 = mctx.mk_metavar_decl(lctx, new_target);
|
||||
new_val = new_M_2;
|
||||
}
|
||||
mctx.assign(head(s.goals()), new_val);
|
||||
list<expr> new_gs = cons(new_M_1, cons(new_M_2, tail(s.goals())));
|
||||
return mk_tactic_success(set_mctx_goals(s, mctx, new_gs));
|
||||
}
|
||||
|
||||
vm_obj tactic_assert(vm_obj const & n, vm_obj const & t, vm_obj const & s) {
|
||||
return assert_define(true, to_name(n), to_expr(t), to_tactic_state(s));
|
||||
vm_obj tactic_assert_core(vm_obj const & n, vm_obj const & t, vm_obj const & s) {
|
||||
return assert_define_core(true, to_name(n), to_expr(t), to_tactic_state(s));
|
||||
}
|
||||
|
||||
vm_obj tactic_define(vm_obj const & n, vm_obj const & t, vm_obj const & s) {
|
||||
return assert_define(false, to_name(n), to_expr(t), to_tactic_state(s));
|
||||
vm_obj tactic_define_core(vm_obj const & n, vm_obj const & t, vm_obj const & s) {
|
||||
return assert_define_core(false, to_name(n), to_expr(t), to_tactic_state(s));
|
||||
}
|
||||
|
||||
vm_obj assertv_definev(bool is_assert, name const & n, expr const & t, expr const & v, tactic_state const & s) {
|
||||
vm_obj assertv_definev_core(bool is_assert, name const & n, expr const & t, expr const & v, tactic_state const & s) {
|
||||
optional<metavar_decl> g = s.get_main_goal_decl();
|
||||
if (!g) return mk_no_goals_exception(s);
|
||||
type_context ctx = mk_type_context_for(s);
|
||||
|
|
@ -67,35 +67,43 @@ vm_obj assertv_definev(bool is_assert, name const & n, expr const & t, expr cons
|
|||
}
|
||||
local_context lctx = g->get_context();
|
||||
metavar_context mctx = ctx.mctx();
|
||||
expr l;
|
||||
if (is_assert)
|
||||
l = lctx.mk_local_decl(n, t);
|
||||
else
|
||||
l = lctx.mk_local_decl(n, t, v);
|
||||
expr new_M = mctx.mk_metavar_decl(lctx, g->get_type());
|
||||
expr new_val;
|
||||
if (is_assert)
|
||||
new_val = mk_app(mk_lambda(n, t, mk_delayed_abstraction(new_M, mlocal_name(l))), v);
|
||||
else
|
||||
new_val = mk_let(n, t, v, mk_delayed_abstraction(new_M, mlocal_name(l)));
|
||||
expr new_M, new_val;
|
||||
if (is_assert) {
|
||||
expr new_target = mk_pi(n, t, g->get_type());
|
||||
new_M = mctx.mk_metavar_decl(lctx, new_target);
|
||||
new_val = mk_app(new_M, v);
|
||||
} else {
|
||||
expr new_target = mk_let(n, t, v, g->get_type());
|
||||
new_M = mctx.mk_metavar_decl(lctx, new_target);
|
||||
new_val = new_M;
|
||||
}
|
||||
mctx.assign(head(s.goals()), new_val);
|
||||
list<expr> new_gs = cons(new_M, tail(s.goals()));
|
||||
return mk_tactic_success(set_mctx_goals(s, mctx, new_gs));
|
||||
}
|
||||
|
||||
vm_obj tactic_assertv(vm_obj const & n, vm_obj const & e, vm_obj const & pr, vm_obj const & s) {
|
||||
return assertv_definev(true, to_name(n), to_expr(e), to_expr(pr), to_tactic_state(s));
|
||||
vm_obj tactic_assertv_core(vm_obj const & n, vm_obj const & e, vm_obj const & pr, vm_obj const & s) {
|
||||
return assertv_definev_core(true, to_name(n), to_expr(e), to_expr(pr), to_tactic_state(s));
|
||||
}
|
||||
|
||||
vm_obj tactic_definev(vm_obj const & n, vm_obj const & e, vm_obj const & pr, vm_obj const & s) {
|
||||
return assertv_definev(false, to_name(n), to_expr(e), to_expr(pr), to_tactic_state(s));
|
||||
vm_obj tactic_definev_core(vm_obj const & n, vm_obj const & e, vm_obj const & pr, vm_obj const & s) {
|
||||
return assertv_definev_core(false, to_name(n), to_expr(e), to_expr(pr), to_tactic_state(s));
|
||||
}
|
||||
|
||||
vm_obj assertv_definev(bool is_assert, name const & n, expr const & t, expr const & v, tactic_state const & s) {
|
||||
vm_obj r = assertv_definev_core(is_assert, n, t, v, s);
|
||||
if (optional<tactic_state> const & s2 = is_tactic_success(r)) {
|
||||
return intro(n, *s2);
|
||||
} else {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
void initialize_assert_tactic() {
|
||||
DECLARE_VM_BUILTIN(name({"tactic", "assert"}), tactic_assert);
|
||||
DECLARE_VM_BUILTIN(name({"tactic", "assertv"}), tactic_assertv);
|
||||
DECLARE_VM_BUILTIN(name({"tactic", "define"}), tactic_define);
|
||||
DECLARE_VM_BUILTIN(name({"tactic", "definev"}), tactic_definev);
|
||||
DECLARE_VM_BUILTIN(name({"tactic", "assert_core"}), tactic_assert_core);
|
||||
DECLARE_VM_BUILTIN(name({"tactic", "assertv_core"}), tactic_assertv_core);
|
||||
DECLARE_VM_BUILTIN(name({"tactic", "define_core"}), tactic_define_core);
|
||||
DECLARE_VM_BUILTIN(name({"tactic", "definev_core"}), tactic_definev_core);
|
||||
}
|
||||
|
||||
void finalize_assert_tactic() {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ Author: Leonardo de Moura
|
|||
#pragma once
|
||||
#include "library/tactic/tactic_state.h"
|
||||
namespace lean {
|
||||
vm_obj assert_define(bool is_assert, name const & n, expr const & t, tactic_state const & s);
|
||||
vm_obj assert_define_core(bool is_assert, name const & n, expr const & t, tactic_state const & s);
|
||||
vm_obj assertv_definev_core(bool is_assert, name const & n, expr const & t, expr const & v, tactic_state const & s);
|
||||
vm_obj assertv_definev(bool is_assert, name const & n, expr const & t, expr const & v, tactic_state const & s);
|
||||
void initialize_assert_tactic();
|
||||
void finalize_assert_tactic();
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ optional<expr> intron(environment const & env, options const & opts, metavar_con
|
|||
optional<expr> intron(environment const & env, options const & opts, metavar_context & mctx,
|
||||
expr const & mvar, unsigned n);
|
||||
|
||||
vm_obj intro(name const & n, tactic_state const & s);
|
||||
|
||||
void initialize_intro_tactic();
|
||||
void finalize_intro_tactic();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ tactic_state revert_all(tactic_state const & s) {
|
|||
return revert(hs, s);
|
||||
}
|
||||
|
||||
vm_obj preprocess(tactic_state const & s, smt_pre_config const & cfg) {
|
||||
vm_obj preprocess(tactic_state s, smt_pre_config const & cfg) {
|
||||
lean_assert(s.goals());
|
||||
optional<metavar_decl> g = s.get_main_goal_decl();
|
||||
type_context ctx = mk_type_context_for(s, transparency_mode::Reducible);
|
||||
|
|
@ -163,28 +163,34 @@ vm_obj preprocess(tactic_state const & s, smt_pre_config const & cfg) {
|
|||
simp_lemmas_for eq_lemmas;
|
||||
if (auto r = cfg.m_simp_lemmas.find(get_eq_name()))
|
||||
eq_lemmas = *r;
|
||||
expr new_target = dsimplify_fn(ctx, max_steps, visit_instances, eq_lemmas)(target);
|
||||
dsimplify_fn dsimp(ctx, max_steps, visit_instances, eq_lemmas);
|
||||
expr new_target = dsimp(target);
|
||||
ctx.set_env(dsimp.update_defeq_canonizer_state(ctx.env()));
|
||||
bool contextual = false;
|
||||
bool lift_eq = true;
|
||||
bool canonize_instances = true;
|
||||
bool canonize_proofs = false;
|
||||
bool use_axioms = true;
|
||||
simp_result r = simplify_fn(ctx, cfg.m_simp_lemmas, max_steps,
|
||||
contextual, lift_eq, canonize_instances,
|
||||
canonize_proofs, use_axioms)(get_eq_name(), new_target);
|
||||
simplify_fn simp(ctx, cfg.m_simp_lemmas, max_steps,
|
||||
contextual, lift_eq, canonize_instances,
|
||||
canonize_proofs, use_axioms);
|
||||
simp_result r = simp(get_eq_name(), new_target);
|
||||
ctx.set_env(simp.update_defeq_canonizer_state(ctx.env()));
|
||||
if (!r.has_proof()) {
|
||||
s = set_env(s, ctx.env());
|
||||
return change(r.get_new(), s);
|
||||
} else {
|
||||
expr new_M = ctx.mk_metavar_decl(ctx.lctx(), r.get_new());
|
||||
expr h = mk_app(ctx, get_eq_mpr_name(), r.get_proof(), new_M);
|
||||
metavar_context mctx = ctx.mctx();
|
||||
mctx.assign(head(s.goals()), h);
|
||||
tactic_state new_s = set_mctx_goals(s, mctx, cons(new_M, tail(s.goals())));
|
||||
tactic_state new_s = set_env_mctx_goals(s, ctx.env(), mctx, cons(new_M, tail(s.goals())));
|
||||
return mk_tactic_success(new_s);
|
||||
}
|
||||
}
|
||||
|
||||
expr intros(environment const & env, options const & opts, metavar_context & mctx, expr const & mvar, smt_goal & s_goal) {
|
||||
expr intros(environment const & env, options const & opts, metavar_context & mctx, expr const & mvar, smt_goal & s_goal,
|
||||
bool use_unused_names) {
|
||||
optional<metavar_decl> decl = mctx.get_metavar_decl(mvar);
|
||||
lean_assert(decl);
|
||||
type_context ctx(env, opts, mctx, decl->get_context(), transparency_mode::Semireducible);
|
||||
|
|
@ -201,7 +207,8 @@ expr intros(environment const & env, options const & opts, metavar_context & mct
|
|||
}
|
||||
if (is_pi(target)) {
|
||||
expr type = instantiate_rev(binding_domain(target), to_inst.size(), to_inst.data());
|
||||
name n = ctx.get_unused_name(binding_name(target));
|
||||
name n = binding_name(target);
|
||||
if (use_unused_names) n = ctx.get_unused_name(n);
|
||||
expr h = locals.push_local(n, type);
|
||||
to_inst.push_back(h);
|
||||
new_Hs.push_back(h);
|
||||
|
|
@ -211,7 +218,8 @@ expr intros(environment const & env, options const & opts, metavar_context & mct
|
|||
} else if (is_let(target)) {
|
||||
expr type = instantiate_rev(let_type(target), to_inst.size(), to_inst.data());
|
||||
expr value = instantiate_rev(let_value(target), to_inst.size(), to_inst.data());
|
||||
name n = ctx.get_unused_name(let_name(target));
|
||||
name n = let_name(target);
|
||||
if (use_unused_names) n = ctx.get_unused_name(n);
|
||||
expr h = locals.push_let(n, type, value);
|
||||
to_inst.push_back(h);
|
||||
new_Hs.push_back(h);
|
||||
|
|
@ -257,7 +265,8 @@ vm_obj mk_smt_state(tactic_state s, smt_config const & cfg) {
|
|||
s = to_tactic_state(get_tactic_result_state(r));
|
||||
|
||||
metavar_context mctx = s.mctx();
|
||||
expr new_M = intros(s.env(), s.get_options(), mctx, head(s.goals()), new_goal);
|
||||
bool use_unused_names = true;
|
||||
expr new_M = intros(s.env(), s.get_options(), mctx, head(s.goals()), new_goal, use_unused_names);
|
||||
s = set_mctx_goals(s, mctx, cons(new_M, tail(s.goals())));
|
||||
return mk_tactic_success(mk_vm_cons(to_obj(new_goal), mk_vm_nil()), s);
|
||||
}
|
||||
|
|
@ -560,7 +569,7 @@ vm_obj smt_tactic_close(vm_obj const & ss, vm_obj const & _ts) {
|
|||
return mk_tactic_exception("smt_tactic.close failed", ts);
|
||||
}
|
||||
|
||||
vm_obj smt_tactic_intros(vm_obj const & ss, vm_obj const & _ts) {
|
||||
vm_obj smt_tactic_intros_core(vm_obj const & use_unused_names, vm_obj const & ss, vm_obj const & _ts) {
|
||||
tactic_state ts = to_tactic_state(_ts);
|
||||
if (is_nil(ss))
|
||||
return mk_smt_state_empty_exception(ts);
|
||||
|
|
@ -573,7 +582,8 @@ vm_obj smt_tactic_intros(vm_obj const & ss, vm_obj const & _ts) {
|
|||
ts = to_tactic_state(get_tactic_result_state(r));
|
||||
|
||||
metavar_context mctx = ts.mctx();
|
||||
expr new_mvar = intros(ts.env(), ts.get_options(), mctx, head(ts.goals()), new_sgoal);
|
||||
expr new_mvar = intros(ts.env(), ts.get_options(), mctx, head(ts.goals()), new_sgoal,
|
||||
to_bool(use_unused_names));
|
||||
|
||||
tactic_state new_ts = set_mctx_goals(ts, mctx, cons(new_mvar, tail(ts.goals())));
|
||||
vm_obj new_ss = mk_vm_cons(to_obj(new_sgoal), tail(ss));
|
||||
|
|
@ -588,7 +598,7 @@ void initialize_smt_state() {
|
|||
DECLARE_VM_BUILTIN(name({"smt_state", "to_format"}), smt_state_to_format);
|
||||
DECLARE_VM_BUILTIN("tactic_to_smt_tactic", tactic_to_smt_tactic);
|
||||
DECLARE_VM_BUILTIN(name({"smt_tactic", "close"}), smt_tactic_close);
|
||||
DECLARE_VM_BUILTIN(name({"smt_tactic", "intros"}), smt_tactic_intros);
|
||||
DECLARE_VM_BUILTIN(name({"smt_tactic", "intros_core"}), smt_tactic_intros_core);
|
||||
}
|
||||
|
||||
void finalize_smt_state() {
|
||||
|
|
|
|||
22
tests/lean/run/smt_assert_define.lean
Normal file
22
tests/lean/run/smt_assert_define.lean
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
open smt_tactic
|
||||
|
||||
example (a b c : nat) : a = b + 0 → a + c = b + c :=
|
||||
by using_smt $ do
|
||||
pr ← tactic.to_expr `(add_zero b),
|
||||
note `h pr,
|
||||
trace_state, return ()
|
||||
|
||||
constant p : nat → nat → Prop
|
||||
constant f : nat → nat
|
||||
axiom pf (a : nat) : p (f a) (f a) → p a a
|
||||
|
||||
example (a b c : nat) : a = b → p (f a) (f b) → p a b :=
|
||||
by using_smt $ do
|
||||
t ← tactic.to_expr `(p (f a) (f a)),
|
||||
assert `h t, -- assert automatically closed the new goal
|
||||
trace_state,
|
||||
tactic.trace "-----",
|
||||
pr ← tactic.to_expr `(pf _ h),
|
||||
note `h2 pr,
|
||||
trace_state,
|
||||
return ()
|
||||
Loading…
Add table
Reference in a new issue