A loop's initialisers are checked in order and each sees the names bound before it, as a let's do
This commit is contained in:
parent
3a3674efb7
commit
b4e19bebf8
11
lib/check.ml
11
lib/check.ml
@ -4737,8 +4737,10 @@ and check_dotimes ctx ~want loc label name (b : Ast.bounds) body =
|
||||
and check_loop ctx ?want loc bs body =
|
||||
scoped ctx (fun () ->
|
||||
(* Each initial value is evaluated once, before the loop, exactly as a
|
||||
[let]'s is and as [dotimes]'s bound is. *)
|
||||
let inits =
|
||||
[let]'s is and as [dotimes]'s bound is — and bound before the next is
|
||||
checked, as a [let]'s is, so a later initialiser sees an earlier
|
||||
name. *)
|
||||
let binds =
|
||||
map_lr
|
||||
(fun (n, v) ->
|
||||
let v = check ctx v in
|
||||
@ -4747,12 +4749,9 @@ and check_loop ctx ?want loc bs body =
|
||||
fail v.Tast.loc "%s would be bound to %s, which is not a value" n
|
||||
(Types.to_string v.Tast.ty)
|
||||
| _ -> ());
|
||||
(n, v))
|
||||
(bind ctx n v.Tast.ty ~assignable:true, v))
|
||||
bs
|
||||
in
|
||||
let binds =
|
||||
List.map (fun (n, v) -> (bind ctx n v.Tast.ty ~assignable:true, v)) inits
|
||||
in
|
||||
let names = List.map (fun (slot, v) -> (slot, v.Tast.ty)) binds in
|
||||
(* The singleton is [in_loop]'s doing: it sits in this recursive group and
|
||||
is therefore monomorphic, and every other caller hands it a list. *)
|
||||
|
||||
@ -99,4 +99,10 @@
|
||||
(Some v) (recur (+ i 1) (+ acc v))
|
||||
None acc)))
|
||||
(println "") ; 0+1+2+3 = 6
|
||||
|
||||
;; The bindings are sequential, as a let's are: the second initialiser reads
|
||||
;; the first name. Only the initial values are; recur still rebinds at once.
|
||||
(print (loop [a 1 b (+ a 10)]
|
||||
(if (> a 3) b (recur (+ a 1) (+ b a)))))
|
||||
(println "") ; 11+1+2+3 = 17
|
||||
0)
|
||||
|
||||
@ -501,7 +501,7 @@ let () =
|
||||
rather than running out of stack. The swap line is the other — recur
|
||||
rebinds every name at once, and interleaved writes would print 1. *)
|
||||
outputs "loop and recur" "programs/recur.flan"
|
||||
"10\n2\n21\n8\n10000000\n64\n012\n0\n4\n012\n6\n";
|
||||
"10\n2\n21\n8\n10000000\n64\n012\n0\n4\n012\n6\n17\n";
|
||||
(* into. The count of pulls is the assertion a unit test cannot make: one
|
||||
pass, one call per element per stage it reaches, and no intermediate
|
||||
collection anywhere. The two show lines either side of it are the same
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user