lean4-htt/src/Lean/Meta/Sym/Simp/ControlFlow.lean
Leonardo de Moura f63ddd67a2
feat: add simpControl simproc for if-then-else simplification (#12035)
This PR adds `simpControl`, a simproc that handles control-flow
expressions such as `if-then-else`. It simplifies conditions while
avoiding unnecessary work on branches that won't be taken.

The key behavior of `simpControl`:
- Simplifies the condition of `if-then-else` expressions
- If the condition reduces to `True` or `False`, returns the appropriate
branch, and continue simplifying.
- If the condition simplifies to a new expression, rebuilds the
`if-then-else` with the simplified condition (synthesizing a new
`Decidable` instance), and mark it as "done". That is, simplifier main
loop will not visit branches.
- Does **not** visit branches unless the condition becomes `True` or
`False`

This is useful for symbolic simplification where we want to avoid
wasting effort
simplifying branches that may be eliminated after the condition is
resolved.

This PR also fixes a bug in `Sym/Simp/EvalGround.lean`, and adds some
helper functions.
2026-01-18 04:14:26 +00:00

49 lines
1.6 KiB
Text

/-
Copyright (c) 2026 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
public import Lean.Meta.Sym.Simp.SimpM
import Lean.Meta.Sym.AlphaShareBuilder
import Lean.Meta.Sym.Simp.App
import Lean.Meta.SynthInstance
import Lean.Expr
import Init.Sym.Lemmas
namespace Lean.Meta.Sym.Simp
open Internal
def simpIte : Simproc := fun e => do
let numArgs := e.getAppNumArgs
if numArgs < 5 then return .rfl (done := true)
propagateOverApplied e (numArgs - 5) fun e => do
let_expr ite _ c _ a b := e | return .rfl
match (← simp c) with
| .rfl _ => return .rfl (done := true)
| .step c' h _ =>
if c'.isTrue then
return .step a <| mkApp (e.replaceFn ``ite_cond_eq_true) h
else if c'.isFalse then
return .step b <| mkApp (e.replaceFn ``ite_cond_eq_false) h
else
let .some inst' ← trySynthInstance (mkApp (mkConst ``Decidable) c') | return .rfl
let e' := e.getBoundedAppFn 4
let e' ← mkAppS₄ e' c' inst' a b
let h' := mkApp3 (e.replaceFn ``Lean.Sym.ite_cond_congr) c' inst' h
return .step e' h' (done := true)
/--
Simplifies control-flow expressions such as `if-then-else` and `match` expressions.
It visits only the conditions and discriminants.
-/
public def simpControl : Simproc := fun e => do
if !e.isApp then return .rfl
let .const declName _ := e.getAppFn | return .rfl
if declName == ``ite then
simpIte e
else
-- **TODO**: Add more cases
return .rfl
end Lean.Meta.Sym.Simp