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

Cannot return from mid-expression context

Open kengorab opened this issue 4 years ago • 0 comments

When an expression contains a return as one of its paths, the stack is not properly cleaned up if this return happens mid-expression. For example, the following code blows up:

func a(): Int[] {
  val arr = [1]
  arr.push(if false 2 else return [])
  arr
}
println(a())

The expected return value of a is [], since we hit the return [] part of the if-expr and we should bail out of the function entirely. However, this doesn't happen properly, because there are intermediate values on the stack that are not tracked as locals which must be popped prior to exiting (in this case, the arr.push method).

Here's another example:

func a(): Int[] {
  val arr = [
    1,
    2, 
    if false 3 else return [],
    4
  ]
  arr
}
println(a())

Once again, I'd expect a to return [], but it blows up since the TOS is one of the intermediate values that were pushed to the stack with the expectation of being handled.

This manifests in a relatively mundane use case when using try expressions:

func foo(): Result<Int, String> = Result.Err("a")
func bar(): Result<Int[], String> {
  val res = [1]

  for _ in range(0, 5) {
    res.push(try foo())
  }

  Result.Ok(res)
}

... this one's probably going to be tricky

kengorab avatar Sep 10 '21 03:09 kengorab