Skip to content

Commit eaf747b

Browse files
committed
Merge probe-fixes into probe-III
2 parents 0ce4847 + e122d01 commit eaf747b

File tree

1 file changed

+44
-15
lines changed

1 file changed

+44
-15
lines changed

src/haz3lcore/zipper/Zipper.re

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,27 @@ let neighbor_tokens = (z: t): (option(Token.t), option(Token.t)) => (
220220
neighbor_token(Right, z),
221221
);
222222

223-
let rec do_until_piece =
224-
(action: t => option(t), p_n: neighbors => bool, z: t): option(t) => {
225-
let* z = action(z);
226-
if (p_n(Siblings.neighbors(z.relatives.siblings))) {
227-
Some(z);
228-
} else {
229-
do_until_piece(action, p_n, z);
223+
/* Iterative version to avoid stack overflow on large programs */
224+
let do_until_piece =
225+
(action: t => option(t), p_n: neighbors => bool, z: t): option(t) => {
226+
let current = ref(action(z));
227+
let result = ref(None);
228+
let done_ = ref(false);
229+
while (! done_^) {
230+
switch (current^) {
231+
| None =>
232+
result := None;
233+
done_ := true;
234+
| Some(z) =>
235+
if (p_n(Siblings.neighbors(z.relatives.siblings))) {
236+
result := Some(z);
237+
done_ := true;
238+
} else {
239+
current := action(z);
240+
}
241+
};
230242
};
243+
result^;
231244
};
232245

233246
/* Do `action` until the predicate on the generalized neigbors of the
@@ -236,15 +249,31 @@ let rec do_until_piece =
236249
we are at the edge of a segment, in which case it's the relevant shard
237250
of the parent. The None case strictly means the beginning/end of the program.
238251
If no such piece is found, don't move. Does not check predicate before
239-
moving; caller should handle that case if necessary */
240-
let rec do_until =
241-
(action: t => option(t), p_n: neighbors => bool, z: t): option(t) => {
242-
let* z = action(z);
243-
if (p_n(generalized_neighbors(z))) {
244-
Some(z);
245-
} else {
246-
do_until(action, p_n, z);
252+
moving; caller should handle that case if necessary.
253+
254+
NOTE: This is implemented iteratively to avoid stack overflow on large
255+
programs. The previous recursive implementation would overflow when
256+
traversing documents with thousands of tokens. */
257+
let do_until =
258+
(action: t => option(t), p_n: neighbors => bool, z: t): option(t) => {
259+
let current = ref(action(z));
260+
let result = ref(None);
261+
let done_ = ref(false);
262+
while (! done_^) {
263+
switch (current^) {
264+
| None =>
265+
result := None;
266+
done_ := true;
267+
| Some(z) =>
268+
if (p_n(generalized_neighbors(z))) {
269+
result := Some(z);
270+
done_ := true;
271+
} else {
272+
current := action(z);
273+
}
274+
};
247275
};
276+
result^;
248277
};
249278

250279
let do_to_extreme = (action: t => option(t), z: t): t =>

0 commit comments

Comments
 (0)