Open WiseIndian opened 4 years ago
If a function is defined outside of the coroutine body or if it doesnt contain yieldval within the body of its definition it is left as is. Note that a function must also not contain calls to functions that contain any yieldval within them in order to not be transformed.
If the function body contains yieldval or calls functions whose body contains yieldval then it is transformed to a coroutine. We will transform the function definitions to a coroutine that returns either the type that is returned by the surrounding coroutine body or that returns an expression of the type the return type of the function.
We do a first transformation phase:
We visit every expression e
of the function body to change
types to the Either type where needed. The following partial
function would be used as input to a function visiting every node of the
tree of the function body.
e match {
case '{yieldval(e)} => yieldval(Left(e))
case '{return e} => yieldval(Right(e))
}
we would also transform the last expression e
of the function body
to yieldval(Right(e))
.
Then we would need to do another transformation of the function definition:
[[ def foo(e1, ..., en): R = { Z* } ]](c) =
'{
def foo(e1, ..., en) = new Coroutine[Either[T, R]] {
def continue: Option[Either[T, R]] = [[Z*]](c)
}
${c()}
}
Class method calls are left as they are for the moment. A function call to a function definition containing yieldval could then be in principle transformed to something like this:
[[foo(e1, ..., en)]](c) =
'{
val fooCoroutine: Coroutine[Either[T,R]] = foo()
[[
val returnValue: R = null
while (!fooCoroutine.isDone()) {
val result: Either[T, R] = fooCoroutine.continue
if (result isLeft) {
yieldval(result.left.get)
} else {
returnValue = result.right.get
}
}
returnValue
]](c)
}
This would allow recursive function call and mutual function calls.
@LeDevDuDimanche Do you have use cases in mind that depend on this? Otherwise, I'd say to delay this. Just use type checking to report an error if user writes code like this. WDYT?
I didnt really have any case in mind. I guess we can delay this.
Those functions definitions should support yieldval in their body. We need to formalize this solution.