pyret-lang
pyret-lang copied to clipboard
`ref` bindings in cases "forget" to unpack their reference in certain situations
Example:
data MultiBox:
| mbox(ref v1 :: Number, ref v2 :: Number, ref v3 :: Number, v4 :: Number)
where:
mb = mbox(1, 2, 3, 4)
cases(MultiBox) mb block:
| mbox(ref v1, ref v2, ref v3, v4) =>
v1 is 1 # Commenting any of these three lines
v2 is 2 # will cause the remaining two tests to
v3 is 3 # work properly.
end
end
This should pass, but all tests fail. Commenting out any of the tests will suddenly cause the other two tests to pass. Looking at the generated code, it seems that the ref v#
bindings are not actually extracing the underlying value if all three checks are present. When one of them is commented out, the codegen is suddenly correct.
It seems that this is really inconsistent in general. For example, this slight adjustment:
data MultiBox:
| mbox(ref v1 :: Number, ref v2 :: Number, ref v3 :: Number, v4 :: Number)
where:
mb = mbox(1, 2, 3, 4)
cases(MultiBox) mb block:
| mbox(ref v1, ref v2, ref v3, v4) =>
print(v1)
print(v2)
print(v3)
v1 is 1
v2 is 2
v3 is 3
end
end
will only work if at least two of the checks are commented out.
There are two codepaths used when compiling cases: one of them inlines the case body right where it's used, and the other delegates out to a separate function. There's a size threshold used to choose which approach is used. It seems likely that the larger cases are triggering the separate-function compilation and failing for some reason, while the smaller cases are inlined and seem to work.
Where it chooses: https://github.com/brownplt/pyret-lang/blob/horizon/src/arr/compiler/anf-loop-compiler.arr#L1181 Helper function: https://github.com/brownplt/pyret-lang/blob/horizon/src/arr/compiler/anf-loop-compiler.arr#L1189-L1199 Inlined: https://github.com/brownplt/pyret-lang/blob/horizon/src/arr/compiler/anf-loop-compiler.arr#L1249-L1255 Where the variant constructor gets its list of which fields are mutable: https://github.com/brownplt/pyret-lang/blob/horizon/src/arr/compiler/anf-loop-compiler.arr#L1899
There's a mismatch here between "which bindings are refs in the cases" and "which fields are mutable in the constructor definition", and I wonder if that's causing the issue?
FYI: duplicate of #1142