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.
118 lines
1.7 KiB
Text
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]
|