| /-! | |
| A few cases where guessing the lexicographic order fails, and | |
| where we want to keep tabs on the output. | |
| All functions take more than one changing argument, because the guesslex | |
| code skips non-mutuals unary functions with only one plausible measure. | |
| -/ | |
| def nonTerminating : Nat → Nat → Nat | |
| | 0, _ => 0 | |
| | n, m => nonTerminating (.succ n) (.succ m) | |
| -- Saying decreasing_by forces Lean to use structural recursion, which gives a different | |
| -- error message | |
| def nonTerminating2 : Nat → Nat → Nat | |
| | 0, _ => 0 | |
| | n, m => nonTerminating2 (.succ n) (.succ m) | |
| decreasing_by decreasing_tactic | |
| def noArguments : Nat := noArguments | |
| def noNonFixedArguments (n : Nat) : Nat := noNonFixedArguments n | |
| def Array.sum (xs : Array Nat) : Nat := xs.foldl (init := 0) Nat.add | |
| namespace InterestingMatrix | |
| def f : (n m l : Nat) → Nat | |
| | n+1, m+1, l+1 => #[ | |
| f (n+1) (m+1) (l+1), | |
| f (n+1) (m-1) (l), | |
| f (n) (m+1) (l) ].sum | |
| | _, _, _ => 0 | |
| decreasing_by decreasing_tactic | |
| end InterestingMatrix | |
| namespace InterestingMatrixWithForbiddenArguments | |
| def f : (n m : Nat) → (h : True) → Nat → Nat | |
| | n+1, m+1, h, l+1 => #[ | |
| f (n+1) (m+1) h (l+1), | |
| f (n+1) (m-1) h (l), | |
| f (n) (m+1) h (l) ].sum | |
| | _, _, _, _ => 0 | |
| decreasing_by decreasing_tactic | |
| end InterestingMatrixWithForbiddenArguments | |
| namespace InterestingMatrixWithNames | |
| -- Hopefully eventually lean will pick up names even with pattern match syntax | |
| def f (n m l : Nat) : Nat := match n, m, l with | |
| | n+1, m+1, l+1 => #[ | |
| f (n+1) (m+1) (l+1), | |
| f (n+1) (m-1) (l), | |
| f (n) (m+1) (l) ].sum | |
| | _, _, _ => 0 | |
| decreasing_by decreasing_tactic | |
| end InterestingMatrixWithNames | |
| namespace Mutual | |
| mutual | |
| def f (fixed n m l : Nat) : Nat := match n, m, l with | |
| | n+1, m+1, l+1 => #[ | |
| f fixed (n+1) (m+1) (l+1), | |
| f fixed (n+1) (m-1) (l), | |
| g fixed (n) (m+1) trivial (l)].sum | |
| | _, _, _ => 0 | |
| def g (fixed n m : Nat) (H : True) (l : Nat) : Nat := match n, m, l with | |
| | n+1, m+1, l+1 => #[ | |
| g fixed (m+1) (n+1) H (l+1), | |
| g fixed (m+1) (n-1) H (l), | |
| h fixed (m) (n+1) ].sum | |
| | _, _, _ => 0 | |
| def h (fixed : Nat) : (n m : Nat) -> Nat | |
| | n+1, m+1 => #[ | |
| f fixed (n+1) (m+1) (n+1), | |
| h fixed (n+1) (m-1), | |
| h fixed (n) (m+1) ].sum | |
| | _, _ => 0 | |
| end | |
| end Mutual | |
| namespace DuplicatedCall | |
| def dup (a : Nat) (b : Nat := a) := a + b | |
| def f : (n m : Nat) → Nat | |
| | 0, m => m | |
| | n+1, m => dup (f (n+2) (m+1)) | |
| end DuplicatedCall | |
| namespace TrickyCode | |
| -- These tests run GuessLex on peculiar code that it once stumbled over, or might | |
| -- stumble over in the future. | |
| -- The GuessLex code at some point did not like eta-contracted motives in `casesOn`. | |
| def FinPlus1 n := Fin (n + 1) | |
| def badCasesOn (n m : Nat) : Fin (n + 1) := | |
| Nat.casesOn (motive := FinPlus1) n (⟨0,Nat.zero_lt_succ _⟩) (fun n => Fin.succ (badCasesOn n (.succ m))) | |
| -- termination_by n | |
| decreasing_by decreasing_tactic | |
| -- This actually also fails with an explicit termination_by, and could be fixed | |
| -- by eta-expanding the motive. | |
| -- TODO: Fix by using eta-expanding variant of lambdaTelescope, e.g. | |
| -- https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there-code-for-X.3F/topic/Going.20under.20exactly.20one.20lambda/near/404278529 | |
| def badCasesOn2 (n m : Nat) : Fin (n + 1) := | |
| Nat.casesOn (motive := FinPlus1) n (⟨0,Nat.zero_lt_succ _⟩) (fun n => Fin.succ (badCasesOn2 n (.succ m))) | |
| termination_by n | |
| decreasing_by decreasing_tactic | |
| -- The GuessLex code at does not like `casesOn` alternative with insufficient lambdas | |
| -- TODO: Fix by using eta-expanding variant of lambdaTelescope, e.g. | |
| -- https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there-code-for-X.3F/topic/Going.20under.20exactly.20one.20lambda/near/404278529 | |
| def Fin_succ_comp (f : (n : Nat) → Fin (n + 1)) : (n : Nat) → Fin (n + 2) := fun n => Fin.succ (f n) | |
| def badCasesOn3 (n m : Nat) : Fin (n + 1) := | |
| Nat.casesOn (motive := fun n => Fin (n + 1)) n (⟨0,Nat.zero_lt_succ _⟩) | |
| (Fin_succ_comp (fun n => badCasesOn3 n (.succ m))) | |
| -- termination_by n | |
| decreasing_by decreasing_tactic | |
| -- Same test, explicit termination_by | |
| def badCasesOn4 (n m : Nat) : Fin (n + 1) := | |
| Nat.casesOn (motive := fun n => Fin (n + 1)) n (⟨0,Nat.zero_lt_succ _⟩) | |
| (Fin_succ_comp (fun n => badCasesOn4 n (.succ m))) | |
| termination_by n | |
| decreasing_by decreasing_tactic | |
| end TrickyCode |