lean4-htt/tests/elab/whileRepeat.lean
Sebastian Graf 4d7b7dd8e6
feat: support while let in do blocks via unified condition syntax (#13534)
This PR generalizes the `while` syntax in `do` blocks so that the
condition can be any `doIfCond`, the same condition form already
accepted by `if`. As a result, `while let pat := e do …` and `while let
pat ← e do …` are now supported in addition to `while cond do …` and
`while h : cond do …`. The previously separate `doWhile` and `doWhileH`
parsers and their accompanying macros are unified into a single
`doWhile` parser whose macro delegates to the existing `doIf`
desugaring.
2026-04-27 09:23:36 +00:00

118 lines
1.7 KiB
Text

def test2 : IO Unit := do
let mut i := 0
repeat
println! "{i}"
i := i + 1
until i >= 10
println! "test2 done {i}"
/--
info: 0
1
2
3
4
5
6
7
8
9
test2 done 10
-/
#guard_msgs in
#eval test2
def test3 : IO Unit := do
let mut i := 0
repeat
println! "{i}"
if i > 10 && i % 3 == 0 then break
i := i + 1
println! "test3 done {i}"
/--
info: 0
1
2
3
4
5
6
7
8
9
10
11
12
test3 done 12
-/
#guard_msgs in
#eval test3
-- `while let pat := e do ...` exits when the pattern fails to match.
def testWhileLet : IO Unit := do
let mut xs := [0, 1, 2, 3]
while let x :: rest := xs do
println! "{x}"
xs := rest
println! "done {xs.length}"
/--
info: 0
1
2
3
done 0
-/
#guard_msgs in
#eval testWhileLet
-- `while let pat ← e do ...` evaluates the bind on each iteration.
def testWhileLetBind : IO Unit := do
let mut xs := [0, 1, 2, 3]
while let some x ← pure xs.head? do
println! "{x}"
xs := xs.tail
println! "done"
/--
info: 0
1
2
3
done
-/
#guard_msgs in
#eval testWhileLetBind
-- Pops entries from an `IO.Ref`-backed list to show that the bound expression
-- in `while let pat ← e do ...` is re-evaluated each iteration.
def testWhileLetBindRef : IO Unit := do
let r ← IO.mkRef [0, 1, 2, 3]
while let x :: rest ← r.get do
println! "{x}"
r.set rest
println! "done {(← r.get).length}"
/--
info: 0
1
2
3
done 0
-/
#guard_msgs in
#eval testWhileLetBindRef
-- Unified `while` keeps supporting the `while h : cond do ...` form.
def testWhileH (xs : Array Nat) : Nat := Id.run do
let mut i := 0
let mut sum := 0
while h : i < xs.size do
sum := sum + xs[i]
i := i + 1
return sum
/-- info: 6 -/
#guard_msgs in
#eval testWhileH #[1, 2, 3]