diff --git a/doc/changes.md b/doc/changes.md index 647969d0a4..93d8ce1af8 100644 --- a/doc/changes.md +++ b/doc/changes.md @@ -5,6 +5,9 @@ master branch (aka work in progress branch) * In addition to user-defined notation parsers introduced in Lean 3.2.0, users may now also define top-level commands in Lean. For an example, see the [`coinductive` command](https://github.com/leanprover/lean/blob/814a5edaf172c3835c000e3f631bddd85bd879ab/library/init/meta/coinductive_predicates.lean#L551-L552) that has been ported to the new model. +* Add new simplifier configuration option `simp_config.single_pass`. It is useful for simplification rules that may produce non-termination. + Example: `simp {single_pass := tt}` + *Changes* * We now have two type classes for converting to string: `has_to_string` and `has_repr`. diff --git a/library/init/meta/simp_tactic.lean b/library/init/meta/simp_tactic.lean index eed30ef769..14cfd2926a 100644 --- a/library/init/meta/simp_tactic.lean +++ b/library/init/meta/simp_tactic.lean @@ -203,6 +203,7 @@ structure simp_config := (beta : bool := tt) (eta : bool := tt) (proj : bool := tt) -- reduce projections +(single_pass : bool := ff) meta constant simplify_core (c : simp_config) diff --git a/src/library/tactic/simplify.cpp b/src/library/tactic/simplify.cpp index 5e3f2919d5..cb23e57a6f 100644 --- a/src/library/tactic/simplify.cpp +++ b/src/library/tactic/simplify.cpp @@ -71,7 +71,8 @@ simp_config::simp_config(): m_zeta(false), m_beta(false), m_eta(true), - m_proj(true) { + m_proj(true), + m_single_pass(false) { } simp_config::simp_config(vm_obj const & obj) { @@ -85,6 +86,7 @@ simp_config::simp_config(vm_obj const & obj) { m_beta = to_bool(cfield(obj, 7)); m_eta = to_bool(cfield(obj, 8)); m_proj = to_bool(cfield(obj, 9)); + m_single_pass = to_bool(cfield(obj, 10)); } /* ----------------------------------- @@ -696,8 +698,10 @@ simp_result simplify_core_fn::visit(expr const & e, optional const & paren } else if (r2->first.get_new() == curr_result.get_new()) { break; } else { - /* continue simplifying */ curr_result = join(new_result, r2->first); + if (m_cfg.m_single_pass) + break; + /* continue simplifying */ } } else { curr_result = new_result; diff --git a/src/library/tactic/simplify.h b/src/library/tactic/simplify.h index 2b568d87f5..c814df3649 100644 --- a/src/library/tactic/simplify.h +++ b/src/library/tactic/simplify.h @@ -25,6 +25,7 @@ structure simp_config := (beta : bool) (eta : bool) (proj : bool) +(single_pass : bool) */ struct simp_config { unsigned m_max_steps; @@ -37,6 +38,7 @@ struct simp_config { bool m_beta; bool m_eta; bool m_proj; + bool m_single_pass; simp_config(); simp_config(vm_obj const & o); }; diff --git a/tests/lean/run/simp_single_pass.lean b/tests/lean/run/simp_single_pass.lean new file mode 100644 index 0000000000..8226a1c2d1 --- /dev/null +++ b/tests/lean/run/simp_single_pass.lean @@ -0,0 +1,14 @@ +open nat well_founded + +def gcd : ℕ → ℕ → ℕ | y := λ x, +if h : y = 0 then + x +else + have x % y < y, by { apply mod_lt, cases y, contradiction, apply succ_pos }, + gcd (x % y) y + +lemma gcd_zero_right (x : nat) : gcd 0 x = x := +begin + simp [gcd] {single_pass := tt}, + simp +end