lean4-htt/tests/elab/partial_fixpoint_aeneas.lean
Garmelon 08eb78a5b2
chore: switch to new test/bench suite (#12590)
This PR sets up the new integrated test/bench suite. It then migrates
all benchmarks and some related tests to the new suite. There's also
some documentation and some linting.

For now, a lot of the old tests are left alone so this PR doesn't become
even larger than it already is. Eventually, all tests should be migrated
to the new suite though so there isn't a confusing mix of two systems.
2026-02-25 13:51:53 +00:00

149 lines
3.4 KiB
Text
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-!
Examples of partial functions taken from
https://github.com/AeneasVerif/aeneas/blob/9d3febaff93ff02756c648561c9ad2b18d5d9b62/backends/lean/Base/Diverge/Elab.lean
and using Option instead of Result
-/
abbrev Result := Option
abbrev Result.ok := @Option.some
def list_nth {a: Type u} (ls : List a) (i : Int) : Option a :=
match ls with
| [] => none
| x :: ls => do
if i = 0 then pure x
else pure (← list_nth ls (i - 1))
partial_fixpoint
def list_nth_with_back {a: Type} (ls : List a) (i : Int) :
Result (a × (a → Result (List a))) :=
match ls with
| [] => none
| x :: ls =>
if i = 0 then return (x, (λ ret => return (ret :: ls)))
else do
let (x, back) ← list_nth_with_back ls (i - 1)
return (x,
(λ ret => do
let ls ← back ret
return (x :: ls)))
partial_fixpoint
mutual
def is_even (i : Int) : Result Bool :=
if i = 0 then return true else return (← is_odd (i - 1))
partial_fixpoint
def is_odd (i : Int) : Result Bool :=
if i = 0 then return false else return (← is_even (i - 1))
partial_fixpoint
end
mutual
def foo (i : Int) : Result Nat :=
if i > 10 then return (← foo (i / 10)) + (← bar i) else bar 10
partial_fixpoint
def bar (i : Int) : Result Nat :=
if i > 20 then foo (i / 20) else .ok 42
partial_fixpoint
end
def test1 (_ : Option Bool) (_ : Unit) : Result Unit
:= test1 Option.none ()
partial_fixpoint
def infinite_loop : Result Unit := do
let _ ← infinite_loop
Result.ok ()
partial_fixpoint
def infinite_loop1 : Result Unit :=
infinite_loop1
partial_fixpoint
section HigherOrder
inductive Tree (a : Type u) where
| leaf (x : a)
| node (tl : List (Tree a))
def Tree.id {a : Type u} (t : Tree a) : Result (Tree a) :=
match t with
| .leaf x => .ok (.leaf x)
| .node tl =>
do
let tl ← List.mapM Tree.id tl
.ok (.node tl)
partial_fixpoint
def id1 {a : Type u} (t : Tree a) : Result (Tree a) :=
match t with
| .leaf x => .ok (.leaf x)
| .node tl =>
do
let tl ← List.mapM (fun x => id1 x) tl
.ok (.node tl)
partial_fixpoint
def id2 {a : Type u} (t : Tree a) : Result (Tree a) :=
match t with
| .leaf x => .ok (.leaf x)
| .node tl =>
do
let tl ← List.mapM (fun x => do let _ ← id2 x; id2 x) tl
.ok (.node tl)
partial_fixpoint
def incr (t : Tree Nat) : Result (Tree Nat) :=
match t with
| .leaf x => .ok (.leaf (x + 1))
| .node tl =>
do
let tl ← List.mapM incr tl
.ok (.node tl)
partial_fixpoint
def id3 (t : Tree Nat) : Result (Tree Nat) :=
match t with
| .leaf x => .ok (.leaf (x + 1))
| .node tl =>
do
let f := id3
let tl ← List.mapM f tl
.ok (.node tl)
partial_fixpoint
def id4 (t : Tree Nat) : Result (Tree Nat) :=
match t with
| .leaf x => .ok (.leaf (x + 1))
| .node tl =>
do
let f x := do
let x1 ← id4 x
id4 x1
let tl ← List.mapM f tl
.ok (.node tl)
partial_fixpoint
-- Like aeneas, we cannot handle the following
/--
error: Could not prove 'id5' to be monotone in its recursive calls:
Cannot eliminate recursive call `id5` enclosed in
Result.ok id5
-/
#guard_msgs in
def id5 (t : Tree Nat) : Result (Tree Nat) :=
match t with
| .leaf x => .ok (.leaf (x + 1))
| .node tl =>
do
let f ← .ok id5
let tl ← List.mapM f tl
.ok (.node tl)
partial_fixpoint
end HigherOrder