Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Guess lexicographic order for well-founded recursion #2874

Merged
merged 32 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
a2d5d94
feat: Guess lexicographic order for well-founded recursion
nomeata Nov 14, 2023
ea171dc
Use same error message as before
nomeata Nov 14, 2023
0414156
Avoid overshooting in lambdaTelescope in matchers/casesOn
nomeata Nov 14, 2023
01f9968
feat: Add MatcherApp. and CasesOnApp.transform
nomeata Nov 15, 2023
a117d02
Use forallTelescope
nomeata Nov 16, 2023
338a239
Improve documentation, also for existing code
nomeata Nov 16, 2023
9c1b76b
Refactor stuff arount .transfer
nomeata Nov 15, 2023
dd26a05
Avoid TermElabM where MetaM suffices
nomeata Nov 15, 2023
b741f14
More comments
nomeata Nov 15, 2023
9252151
Less TermElabM
nomeata Nov 15, 2023
c514fa3
Code walkthrough with Sebastian
nomeata Nov 15, 2023
e8b6cb3
Use forallTelescope
nomeata Nov 16, 2023
9e3db47
Use forallTelescope
nomeata Nov 18, 2023
d0b5a26
Tuple syntax, forallTelescope
nomeata Nov 18, 2023
6d17de5
Docstring all the functions
nomeata Nov 20, 2023
2f04011
Change copyright
nomeata Nov 21, 2023
9321b8a
Merge branch 'joachim/transform' into joachim/guess-lex
nomeata Nov 23, 2023
6f7165a
Clean-up pass
nomeata Nov 23, 2023
5611e58
Apply review comments
nomeata Nov 23, 2023
815891d
Merge branch 'nightly' of github.com:leanprover/lean4 into joachim/tr…
nomeata Nov 23, 2023
3e0f14c
Merge branch 'joachim/transform' into joachim/guess-lex
nomeata Nov 23, 2023
cd7fbd4
Forgot one
nomeata Nov 23, 2023
da93cc9
Merge branch 'joachim/transform' into joachim/guess-lex
nomeata Nov 23, 2023
069da84
.transform got renamed
nomeata Nov 23, 2023
4299967
Docstring
nomeata Nov 23, 2023
768c532
Apply review comments
nomeata Nov 23, 2023
f4f64e5
Remove old guessing code
nomeata Nov 23, 2023
64a8074
Add test cases
nomeata Nov 23, 2023
40fcd73
Factor out generateMeasures
nomeata Nov 23, 2023
c157b6a
Merge branch 'nightly' of github.com:leanprover/lean4 into joachim/gu…
nomeata Nov 24, 2023
b33b524
Empty commit to trigger mathlib CI
nomeata Nov 24, 2023
99cb590
Let’s just leave this here for now
nomeata Nov 24, 2023
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
Prev Previous commit
Next Next commit
Improve documentation, also for existing code
  • Loading branch information
nomeata committed Nov 16, 2023
commit 338a239e20990a00b65016e3cf4295aa4e49f193
24 changes: 17 additions & 7 deletions src/Lean/Meta/CasesOn.lean
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,17 @@ def CasesOnApp.toExpr (c : CasesOnApp) : Expr :=
/--
Given a `casesOn` application `c` of the form
```
casesOn As (fun is x => motive[i, xs]) is major (fun ys_1 => (alt_1 : motive (C_1[ys_1])) ... (fun ys_n => (alt_n : motive (C_n[ys_n]) remaining
casesOn As (fun is x => motive[is, xs]) is major (fun ys_1 => (alt_1 : motive (C_1[ys_1])) ... (fun ys_n => (alt_n : motive (C_n[ys_n]) remaining
```
and an expression `e : B[is, major]`, construct the term
```
casesOn As (fun is x => B[is, x] → motive[i, xs]) is major (fun ys_1 (y : B[C_1[ys_1]]) => (alt_1 : motive (C_1[ys_1])) ... (fun ys_n (y : B[C_n[ys_n]]) => (alt_n : motive (C_n[ys_n]) e remaining
casesOn As (fun is x => B[is, x] → motive[i, xs]) is major (fun ys_1 (y : B[_, C_1[ys_1]]) => (alt_1 : motive (C_1[ys_1])) ... (fun ys_n (y : B[_, C_n[ys_n]]) => (alt_n : motive (C_n[ys_n]) e remaining
```
We use `kabstract` to abstract the `is` and `major` from `B[is, major]`.

This is used in in `Lean.Elab.PreDefinition.WF.Fix` when replacing recursive calls with calls to
the argument provided by `fix` to refine the termination argument, which may mention `major`.
See there for how to use this function.
-/
def CasesOnApp.addArg (c : CasesOnApp) (arg : Expr) (checkIfRefined : Bool := false) : MetaM CasesOnApp := do
lambdaTelescope c.motive fun motiveArgs motiveBody => do
Expand Down Expand Up @@ -117,15 +121,20 @@ def CasesOnApp.addArg? (c : CasesOnApp) (arg : Expr) (checkIfRefined : Bool := f
/--
Given a `casesOn` application `c` of the form
```
casesOn As (fun is x => motive[i, xs]) is major (fun ys_1 => (alt_1 : motive (C_1[ys_1])) ... (fun ys_n => (alt_n : motive (C_n[ys_n]) remaining
casesOn As (fun is x => motive[is, xs]) is major (fun ys_1 => (alt_1 : motive (C_1[ys_1])) ... (fun ys_n => (alt_n : motive (C_n[ys_n]) remaining
```
and a type `e : B[is, major]`, for every alternative `i`, construct the type
and an expression `B[is, major]`, for every alternative `i`, construct the type
```
B[C_i[ys_i]]
B[_, C_i[ys_i]]
```
with `ys_i` as loose bound variables, ready to be `.instantiateRev`d; arity according to `CasesOnApp.altNumParams`.

This is similar to `CasesOnApp.addArg` when you only have a type to transform, not a concrete value.
This is similar to `CasesOnApp.addArg` when you only have an expression to
refined, and not a type with a value.

This is used in in `Lean.Elab.PreDefinition.WF.GuessFix` when constructing the context of recursive
calls to refine the functions' paramter, which may mention `major`.
See there for how to use this function.
-/
def CasesOnApp.transform (c : CasesOnApp) (e : Expr) : MetaM (Array Expr) :=
lambdaTelescope c.motive fun motiveArgs _motiveBody => do
Expand All @@ -137,7 +146,8 @@ def CasesOnApp.transform (c : CasesOnApp) (e : Expr) : MetaM (Array Expr) :=
for motiveArg in motiveArgs.reverse, discr in discrs.reverse do
eAbst ← kabstract eAbst discr
eAbst := eAbst.instantiate1 motiveArg
-- Let's create something Prop-typed that mentions `e`, by writing `e = e`.
-- Let's create something that’s a `Sort` and mentions `e`, by writing `e = e`,
-- so that we can use it as a motive
let eEq ← mkEq eAbst eAbst
let motive ← mkLambdaFVars motiveArgs eEq
let us := if c.propOnly then c.us else levelZero :: c.us.tail!
Expand Down
25 changes: 21 additions & 4 deletions src/Lean/Meta/Match/Match.lean
Original file line number Diff line number Diff line change
Expand Up @@ -910,11 +910,17 @@ private partial def updateAlts (typeNew : Expr) (altNumParams : Array Nat) (alts
- matcherApp `match_i As (fun xs => motive[xs]) discrs (fun ys_1 => (alt_1 : motive (C_1[ys_1])) ... (fun ys_n => (alt_n : motive (C_n[ys_n]) remaining`, and
- expression `e : B[discrs]`,
Construct the term
`match_i As (fun xs => B[xs] -> motive[xs]) discrs (fun ys_1 (y : B[C_1[ys_1]]) => alt_1) ... (fun ys_n (y : B[C_n[ys_n]]) => alt_n) e remaining`, and
`match_i As (fun xs => B[xs] -> motive[xs]) discrs (fun ys_1 (y : B[C_1[ys_1]]) => alt_1) ... (fun ys_n (y : B[C_n[ys_n]]) => alt_n) e remaining`.

We use `kabstract` to abstract the discriminants from `B[discrs]`.

This method assumes
- the `matcherApp.motive` is a lambda abstraction where `xs.size == discrs.size`
- each alternative is a lambda abstraction where `ys_i.size == matcherApp.altNumParams[i]`

This is used in in `Lean.Elab.PreDefinition.WF.Fix` when replacing recursive calls with calls to
the argument provided by `fix` to refine the termination argument, which may mention `major`.
See there for how to use this function.
-/
def MatcherApp.addArg (matcherApp : MatcherApp) (e : Expr) : MetaM MatcherApp :=
lambdaTelescope matcherApp.motive fun motiveArgs motiveBody => do
Expand Down Expand Up @@ -961,11 +967,20 @@ def MatcherApp.addArg? (matcherApp : MatcherApp) (e : Expr) : MetaM (Option Matc

/-- Given
- matcherApp `match_i As (fun xs => motive[xs]) discrs (fun ys_1 => (alt_1 : motive (C_1[ys_1])) ... (fun ys_n => (alt_n : motive (C_n[ys_n]) remaining`, and
- expression `e : B[discrs]`,
returns the expressions `B[C_1[ys_1]]) ... B[C_n[ys_n]]`,
- a type `B[discrs]`,
returns the types `B[C_1[ys_1]] ... B[C_n[ys_n]]`,
with `ys_i` as loose bound variables, ready to be `.instantiateRev`d; arity according to `matcherApp.altNumParams`.

This is similar to `MatcherApp.addArg` when you only have a type to transform, not a concrete value.
This method assumes
- the `matcherApp.motive` is a lambda abstraction where `xs.size == discrs.size`
- each alternative is a lambda abstraction where `ys_i.size == matcherApp.altNumParams[i]`

This is similar to `MatcherApp.addArg` when you only have an expression to
refined, and not a type with a value.

This is used in in `Lean.Elab.PreDefinition.WF.GuessFix` when constructing the context of recursive
calls to refine the functions' paramter, which may mention `major`.
See there for how to use this function.
-/
def MatcherApp.transform (matcherApp : MatcherApp) (e : Expr) : MetaM (Array Expr) :=
lambdaTelescope matcherApp.motive fun motiveArgs _motiveBody => do
Expand All @@ -979,6 +994,8 @@ def MatcherApp.transform (matcherApp : MatcherApp) (e : Expr) : MetaM (Array Exp
let discr := matcherApp.discrs[i]!
let eTypeAbst ← kabstract eAbst discr
return eTypeAbst.instantiate1 motiveArg
-- Let's create something that’s a `Sort` and mentions `e`, by writing `e = e`,
-- so that we can use it as a motive
let eEq ← mkEq eAbst eAbst

let matcherLevels ← match matcherApp.uElimPos? with
Expand Down