-
Notifications
You must be signed in to change notification settings - Fork 58
[Bug][Parsing] Mutual recursion fails to parse inside an if branch #446
Comments
We now seem to have the restriction that the body of function must be LeafExpr, IIRC. Probably we can improve it with a better error msg. |
If you mean the branches of Edit: If you mean that |
The restriction is that return is not allowed in true/false branch of if. Not related to recursion. import tvm
from tvm.script import relax as R
@tvm.script.ir_module
class ControlFlowExample:
@R.function
def a(x: R.Object) -> R.Object:
y: R.Tensor((), dtype="bool") = R.const(True, dtype="bool")
if y:
r = b(x)
else:
r = c(x)
return r
@R.function
def b(x: R.Object) -> R.Object:
return a(x)
@R.function
def c(x: R.Object) -> R.Object:
return a(x) |
If we would like to support multiple return like the following example in Relax Function, one option is to introduce a tag member like @R.function
def foo(x: R.Tensor) -> R.Tensor:
y: R.Tensor((), dtype="bool") = R.const(True, dtype="bool")
if y:
return R.add(x, x)
else:
return R.multiply(x, x) |
To keep IR constrained for now, let us not update the IR. this can be sugared to assigning values to global then return. So the only question is do we want to support this syntax in parser and sugar to that IR |
Thanks TQ! I don't have a preference on if we need this syntax, a better err message should be good for me. |
Okay, thanks for the update. I think the workaround is fine for my purposes. It would be nice for the parser to have syntactic sugar for it and at minimum a better error message. |
@tqchen @slyubomirsky I have updated the error message in apache/tvm#14123. I agree it would be nice to have this syntactic sugar (more pythonic style). I can work on adding this sugar. |
What if the |
Then the code should look like this: @R.function
def foo(x: R.Tensor) -> R.Tensor:
y: R.Tensor((), dtype="bool") = R.const(True, dtype="bool")
if y:
return R.add(x, x)
else:
r = R.multiply(x, x)
return r |
Shouldn't we first define what |
return is not in the IR explicitly, currently by default the |
Yeah, This is actually opening a pretty tough can of worms for parsing, now that I think of it. We could indeed make our lives simpler by requiring both branches to contain a return if either does. |
Another case is it has no false branch, it may require the member @R.function
def foo(x: R.Tensor) -> R.Tensor:
y: R.Tensor((), dtype="bool") = R.const(True, dtype="bool")
if y:
return R.add(x, x)
# no false branch
return R.multiply(x, x) |
The Relax AST does not permit omitting the false branch, so how would we parse it? (Even without a return) |
Omitting the false branch is not allowed now, a SeqExpr will be constructed for the false branch during parsing. |
Hmm.. So in the example below, does the @R.function
def foo(x: R.Tensor) -> R.Tensor:
y: R.Tensor((), dtype="bool") = R.const(True, dtype="bool")
if y:
return R.add(x, x)
else:
return R.mul(x, x)
... |
I think we should parse that to |
Maybe the easiest thing to do would be to disallow Edit: The motivation here is that the behavior of |
from the if node. |
Yeah, this is a bit of the dilemma we run into with this parser. We're trying to fit a square peg (Python's statement-based grammar) into a round hole (Relax's expression-based grammar). It would be nice for common patterns from Python to work smoothly, but we do have room to say that we don't support some things. I'm fine with asking for return values to be outside the |
I encounter a parse error on the following test case:
The resulting error complains of a violated invariant in the parser:
The text was updated successfully, but these errors were encountered: