Skip to content

Commit c5ec4ab

Browse files
committed
Fix issue with flat functions having refinement (non-flat) annotations
The underlying issue was that a step with a call to _checkAnn was created for refinements in flat functions, with no corresponding restart code for the stack capture. In theory, this regression test should actually work as a flat function, since the is-predicate is flat itself. However, PPredAnn _always_ does a safeCall when checking the annotation, which can cause a stack capture. A few things going forward: - This fix is "obviously" correct, but way more pessimistic than it needs to be long-term. It currently makes all functions with not obviously trivial annotations be non-flat. It really should use more static information to check if any annotation has a non-flat refinement. This is not information we have floating around because we cannot track this information through type aliases (and hence across modules). - A slightly less pessimistic, but still naive way to do this would be to check if annotations directly contain a refinement, or if they are "unknown" aliases other than names like Number, String, or a datatype in the current module. Then we could compile those names to a new kind of dynamic annotation called PFlatPredAnn (in contrast with PPredAnn), which would count as a "cheapAnnotation" that doesn't get a safeCall around it. - The right thing to do is enrich all static annotation information with flatness information, since any compound type (e.g. tuple or object) or aliased type could refer to a predicate.
1 parent 2f86c9d commit c5ec4ab

File tree

3 files changed

+45
-1
lines changed

3 files changed

+45
-1
lines changed

src/arr/compiler/js-of-pyret.arr

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,11 @@ fun flatness-max(a :: Option<Number>, b :: Option<Number>) -> Option<Number>:
228228
end
229229
end
230230

231+
fun is-trivial-ann(ann):
232+
A.is-a-blank(ann) or A.is-a-any(ann)
233+
or (A.is-a-tuple(ann) and ann.fields.all(lam(field-a): A.is-a-blank(field-a) or A.is-a-any(field-a) end))
234+
end
235+
231236
# Maybe compress Option<Number> into a type like FlatnessInfo or something (maybe something without "Info" in the name)
232237
fun make-expr-flatness-env(
233238
aexpr :: AA.AExpr,
@@ -237,7 +242,17 @@ fun make-expr-flatness-env(
237242
make-expr-flatness-env(body, sd)
238243
| a-let(_, bind, val, body) =>
239244
val-flatness = if AA.is-a-lam(val) block:
240-
lam-flatness = make-expr-flatness-env(val.body, sd)
245+
has-nontrivial-arg-ann = for lists.any(elt from val.args):
246+
not(is-trivial-ann(elt))
247+
end
248+
has-nontrivial-ann = has-nontrivial-arg-ann or not(is-trivial-ann(val.ret))
249+
250+
lam-flatness = if has-nontrivial-ann:
251+
none
252+
else:
253+
make-expr-flatness-env(val.body, sd)
254+
end
255+
241256
sd.set-now(bind.id.key(), lam-flatness)
242257
# flatness of defining this lambda is 0, since we're not actually
243258
# doing anything with it

tests/pyret/regression.arr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ import file("./regression/bogus-global-type-name.arr") as _
2121
import file("./regression/duplicate-check-block-report.arr") as _
2222
import file("./regression/escaping-module-uris.arr") as _
2323
import file("./regression/tail-recursion-arg-order.arr") as _
24+
import file("./regression/flat-refinement.arr") as _
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
data D:
2+
| d(x)
3+
end
4+
5+
6+
fun flat(my-d :: D%(is-d)):
7+
my-d.x
8+
end
9+
10+
some-d = d(10)
11+
12+
fun recur(upto):
13+
if upto == 0 block: nothing
14+
else:
15+
thing2 = flat(some-d) + 1
16+
ans = recur(upto - 1)
17+
thing = 1 + 1
18+
ans
19+
end
20+
end
21+
22+
check:
23+
recur(3000) is nothing
24+
recur(300) is nothing
25+
recur(500) is nothing
26+
recur(391) is nothing
27+
recur(5) is nothing
28+
end

0 commit comments

Comments
 (0)