pyret-lang icon indicating copy to clipboard operation
pyret-lang copied to clipboard

`ref` bindings in cases "forget" to unpack their reference in certain situations

Open molenzwiebel opened this issue 3 years ago • 2 comments

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.

molenzwiebel avatar Jun 28 '21 10:06 molenzwiebel

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?

blerner avatar Nov 15 '21 12:11 blerner

FYI: duplicate of #1142

sorawee avatar Nov 15 '21 13:11 sorawee