Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3c41d95
changes to MultiSubst.lean
WegmannDavid Mar 6, 2026
055bd9e
removed files that do not belong in this pull request
WegmannDavid Mar 6, 2026
c245bbc
removed files that do not belong in this pull request
WegmannDavid Mar 6, 2026
c9c2236
applied the same style suggestions from the previous pull request
WegmannDavid Mar 7, 2026
f21151b
removed accidental reversion in LcAt
WegmannDavid Mar 7, 2026
4e09785
removed accidental reversion in FullBeta
WegmannDavid Mar 7, 2026
58aae95
removed accidental reversion in Properties
WegmannDavid Mar 7, 2026
56dba11
instructed linter to ignore warnings
WegmannDavid Mar 7, 2026
83b6d04
removed one false too much
WegmannDavid Mar 7, 2026
107a419
ran lake exe mk_all
WegmannDavid Mar 7, 2026
85a6038
implemented some of the requested changed
WegmannDavid Mar 7, 2026
bedab8a
renamed multiApp_full_beta to list_full_beta and added l to notation …
WegmannDavid Mar 7, 2026
44683a1
added section variables to reduce hypothesis clutter
WegmannDavid Mar 7, 2026
06885f9
some style work
chenson2018 Mar 8, 2026
a92f85e
rm extra params to grind
chenson2018 Mar 8, 2026
a4ee71b
golf invert_abs_multiApp_mst
chenson2018 Mar 8, 2026
a03d127
golf invert_abs_multiApp_st
chenson2018 Mar 8, 2026
eb1e9eb
grind_lint
chenson2018 Mar 8, 2026
6de1a4d
added docstring
WegmannDavid Mar 8, 2026
9a5ccef
added docstrings to constructors of ListFullBeta
WegmannDavid Mar 8, 2026
f2b52e9
changed /- to /-- for docstrings to work
WegmannDavid Mar 8, 2026
1d63423
removed comma in docstring
WegmannDavid Mar 8, 2026
87e2024
Merge branch 'leanprover:main' into pr/MultiApp
WegmannDavid Mar 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cslib.lean
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ public import Cslib.Languages.LambdaCalculus.LocallyNameless.Untyped.Basic
public import Cslib.Languages.LambdaCalculus.LocallyNameless.Untyped.FullBeta
public import Cslib.Languages.LambdaCalculus.LocallyNameless.Untyped.FullBetaConfluence
public import Cslib.Languages.LambdaCalculus.LocallyNameless.Untyped.LcAt
public import Cslib.Languages.LambdaCalculus.LocallyNameless.Untyped.MultiApp
public import Cslib.Languages.LambdaCalculus.LocallyNameless.Untyped.Properties
public import Cslib.Languages.LambdaCalculus.Named.Untyped.Basic
public import Cslib.Logics.HML.Basic
Expand Down
141 changes: 141 additions & 0 deletions Cslib/Languages/LambdaCalculus/LocallyNameless/Untyped/MultiApp.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/-
Copyright (c) 2025 David Wegmann. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: David Wegmann
-/


module


public import Cslib.Languages.LambdaCalculus.LocallyNameless.Untyped.FullBeta

set_option linter.unusedDecidableInType false

@[expose] public section

namespace Cslib

universe u

variable {Var : Type u}

namespace LambdaCalculus.LocallyNameless.Untyped.Term

/-- multiApp f [x₁, x₂, ..., xₙ] applies the arguments x₁, x₂, ..., xₙ
to f in left-associative order, i.e. as (((f x₁) x₂) ... xₙ). -/
@[simp, scoped grind =]
def multiApp (f : Term Var) : List (Term Var) → Term Var
| [] => f
| a :: as => Term.app (multiApp f as) a

/-- A list of arguments performs a single reduction step

[x₁, ..., xᵢ ..., xₙ] ⭢βᶠ [x₁, ..., xᵢ', ..., xₙ]

if one of the arguments performs a single step xᵢ ⭢βᶠ xᵢ'
and the rest of the arguments are locally closed. -/
@[scoped grind, reduction_sys "lβᶠ"]
inductive ListFullBeta : List (Term Var) → List (Term Var) → Prop where
/-- head of the list performs a single reduction step, the rest are locally closed -/
| step : N ⭢βᶠ N' → (∀ N ∈ Ns, LC N) → ListFullBeta (N :: Ns) (N' :: Ns)
/-- given a list that already contains a step, we can add locally closed terms to the front -/
| cons : LC N → ListFullBeta Ns Ns' → ListFullBeta (N :: Ns) (N :: Ns')

variable {M M' : Term Var} {Ns Ns' : List (Term Var)}

/-- A term resulting from a multi-application is locally closed if
and only if the leftmost term and all arguments applied to it are locally closed -/
@[scoped grind ←]
lemma multiApp_lc : LC (M.multiApp Ns) ↔ LC M ∧ (∀ N ∈ Ns, LC N) := by
induction Ns with grind [cases LC]

/-- Just like ordinary beta reduction, the left-hand side
of a multi-application step is locally closed -/
@[scoped grind ←]
lemma step_multiApp_l (steps : M ⭢βᶠ M') (lc_Ns : ∀ N ∈ Ns, LC N) :
M.multiApp Ns ⭢βᶠ M'.multiApp Ns := by
induction Ns <;> grind [FullBeta.appR]

/-- Congruence lemma for multi reduction of the left most term of a multi-application -/
lemma steps_multiApp_l (steps : M ↠βᶠ M') (lc_Ns : ∀ N ∈ Ns, LC N) :
M.multiApp Ns ↠βᶠ M'.multiApp Ns := by
induction steps <;> grind

/-- Congruence lemma for single reduction of one of the arguments of a multi-application -/
@[scoped grind ←]
lemma step_multiApp_r (steps : Ns ⭢lβᶠ Ns') (lc_M : LC M) : M.multiApp Ns ⭢βᶠ M.multiApp Ns' := by
induction steps <;> grind [FullBeta.appL, FullBeta.appR]

/-- Congruence lemma for multiple reduction of one of the arguments of a multi-application -/
lemma steps_multiApp_r (steps : Ns ↠lβᶠ Ns') (lc_M : LC M) : M.multiApp Ns ↠βᶠ M.multiApp Ns' := by
induction steps <;> grind [FullBeta.appL, FullBeta.appR]

/-- If a term (λ M) N P_1 ... P_n reduces in a single step to Q, then
Q must be one of the following forms:

Q = (λ M') N P₁ ... Pₙ where M ⭢βᶠ M' or
Q = (λ M) N' P₁ ... Pₙ where N ⭢βᶠ N' or
Q = (λ M) N P₁' ... Pₙ' where P_i ⭢βᶠ P_i' for some i or
Q = (M ^ N) P₁ ... Pₙ -/
lemma invert_abs_multiApp_st {Ps} {M N Q : Term Var}
(h_red : multiApp (M.abs.app N) Ps ⭢βᶠ Q) :
(∃ M', M.abs ⭢βᶠ Term.abs M' ∧ Q = multiApp (M'.abs.app N) Ps) ∨
(∃ N', N ⭢βᶠ N' ∧ Q = multiApp (M.abs.app N') Ps) ∨
(∃ Ps', Ps ⭢lβᶠ Ps' ∧ Q = multiApp (M.abs.app N) Ps') ∨
(Q = multiApp (M ^ N) Ps) := by
induction Ps generalizing M N Q with
| nil => grind [cases FullBeta]
| cons P Ps ih =>
generalize Heq : (M.abs.app N).multiApp Ps = Q'
have : ∀ P', Q'.app P' = (M.abs.app N).multiApp (P' :: Ps) := by grind
rw [multiApp, Heq] at h_red
cases h_red with
| beta => cases Ps <;> contradiction
| appR => grind [→ ListFullBeta.cons]
| appL => grind

/-- If a term (λ M) N P₁ ... Pₙ reduces in multiple steps to Q, then either Q if of the form

Q = (λ M') N' P'₁ ... P'ₙ

or

we first reach an intermediate term of this shape,

(λ M) N P₁ ... Pₙ ↠βᶠ (λ M') N' P'₁ ... P'ₙ

then perform a beta reduction and reduce further to Q

(λ M') N' P'₁ ... P'ₙ ↠βᶠ M' ^ N' P'_₁ ... P'_ₙ ↠βᶠ Q

where M ↠βᶠ M' and N ↠βᶠ N' and P_i ↠βᶠ P_i' for all i -/
lemma invert_abs_multiApp_mst {Ps} {M N Q : Term Var}
(h_red : multiApp (M.abs.app N) Ps ↠βᶠ Q) :
∃ M' N' Ns', M.abs ↠βᶠ M'.abs ∧ N ↠βᶠ N' ∧ Ps ↠lβᶠ Ns' ∧
(Q = multiApp (M'.abs.app N') Ns' ∨
(multiApp (M.abs.app N) Ps ↠βᶠ multiApp (M' ^ N') Ns' ∧
multiApp (M' ^ N') Ns' ↠βᶠ Q)) := by
induction h_red with
| refl => grind
| tail _ step ih =>
obtain ⟨_, _, _, _, _, _, h⟩ := ih
rcases h with heq | _
· subst heq
grind [invert_abs_multiApp_st step]
· grind [Relation.ReflTransGen.single]

variable [DecidableEq Var] [HasFresh Var]

/-- Just like ordinary beta reduction, the right-hand side
of a multi-application step is locally closed -/
lemma multiApp_step_lc_r (step : Ns ⭢lβᶠ Ns') : ∀ N ∈ Ns', LC N := by
induction step <;> grind [FullBeta.step_lc_r]

/-- Just like ordinary beta reduction, multiple steps of a argument list preserves local closure -/
lemma multiApp_steps_lc (step : Ns ↠lβᶠ Ns') (H : ∀ N ∈ Ns, LC N) : ∀ N ∈ Ns', LC N := by
induction step <;> grind [FullBeta.step_lc_r, multiApp_step_lc_r]

end LambdaCalculus.LocallyNameless.Untyped.Term

end Cslib
2 changes: 2 additions & 0 deletions CslibTests/GrindLint.lean
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ open_scoped_all Cslib
#grind_lint skip Cslib.LambdaCalculus.LocallyNameless.Untyped.Term.FullBeta.redex_app_l_cong
#grind_lint skip Cslib.LambdaCalculus.LocallyNameless.Untyped.Term.FullBeta.redex_app_r_cong
#grind_lint skip Cslib.LambdaCalculus.LocallyNameless.Untyped.Term.subst_intro
#grind_lint skip Cslib.LambdaCalculus.LocallyNameless.Untyped.Term.ListFullBeta.cons
#grind_lint skip Cslib.LambdaCalculus.LocallyNameless.Untyped.Term.ListFullBeta.step
#grind_lint skip Cslib.LambdaCalculus.LocallyNameless.Fsub.Env.Wf.sub
#grind_lint skip Cslib.LambdaCalculus.LocallyNameless.Fsub.Env.Wf.ty
#grind_lint skip Cslib.Logic.HML.bisimulation_satisfies
Expand Down