-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cannot call functions defined inside coroutines #20
Comments
The second test results in the following expanded code: (() => {
val x$macro$1723 = foo();
val bar = x$macro$1723;
1
}) The function definition is not copied. |
I didn't dive into it, but from what you say, it's quite likely that this is because |
It did drop the definition. I've updated my branch to copy the definition. However, this test fails compilation. The test passes, however, if |
Sounds good! |
The test at the bottom of this comment doesn't compile because the compiler can't find the However, if the function is defined either outside the scope of the coroutine or with parentheses (e.g. Do you see any obvious problems? // Test
test("defining a function with no parentheses inside of a coroutine") {
def foo(a0: Int)(b0: Int) = s"a0 = $a0, b0 = $b0"
val c = async(coroutine {() =>
var i = 0
def get = { i += 1; i }
foo(get)(await(Future(get)))
})
assert(Await.result(c, 5 seconds) == "a0 = 1, b0 = 2")
}
// Transformed source found at the end of `canonicalizeTree`
(() => {
var i = 0;
def get = {
var x$macro$60 = null.asInstanceOf[Int];
val x$macro$61 = i.$plus(1);
i = x$macro$61;
x$macro$60 = i;
x$macro$60
};
val x$macro$62 = AsyncAwaitTest.this.await[Int];
val x$macro$63 = scala.concurrent.Future;
val x$macro$64 = scala.concurrent.ExecutionContext;
val x$macro$65 = x$macro$64.Implicits;
val x$macro$66 = x$macro$65.global;
val x$macro$67 = x$macro$63.apply[Int](get)(x$macro$66);
val x$macro$68 = Predef.this.$eq$colon$eq;
val x$macro$69 = x$macro$68.tpEquals[((scala.concurrent.Future[Int], org.coroutines.AsyncAwaitTest.Cell[Int]), Int)];
val x$macro$70 = x$macro$62.apply[(scala.concurrent.Future[Int], org.coroutines.AsyncAwaitTest.Cell[Int]), Int](x$macro$67)(x$macro$69);
val x$macro$71 = foo(get)(x$macro$70);
x$macro$71
}) |
This sounds like another canonicalization case missed. On June 7, 2016 9:53:47 PM GMT+02:00, Jess Smith [email protected] wrote:
Sent from my Android device with K-9 Mail. Please excuse my brevity. |
The test passes if the calls to test("await in non-primary param section 1") {
def foo(a0: Int)(b0: Int) = s"a0 = $a0, b0 = $b0"
val c = async(coroutine {() =>
var i = 0
def get = { i += 1; i }
val call1 = get
val call2 = get
foo(call1)(await(Future(call2)))
})
assert(Await.result(c, 5 seconds) == "a0 = 1, b0 = 2")
} One way that the canonicalization fails is by not assigning the result of val x$macro$859 = get(); This happens because the function calls are to I couldn't think of an easily-implementable case that would catch function calls that do not have parentheses after them. The current case for function application requires that However, I'm still not sure why the compiler complains about not being able to find val x$macro$67 = x$macro$63.apply[Int](get)(x$macro$66); should not fail compilation because of the missing symbol I tested this in the REPL and confirmed my suspicions. Compilation seems to only fail when it is run through Coroutines. > test:console
[info] Starting scala interpreter...
[info]
Welcome to Scala version 2.11.4 (OpenJDK 64-Bit Server VM, Java 1.8.0_72).
Type in expressions to have them evaluated.
Type :help for more information.
scala> :paste
// Entering paste mode (ctrl-D to finish)
import org.coroutines._
import scala.annotation.unchecked.uncheckedVariance
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
def foo(a0: Int)(b0: Int) = s"a0 = $a0, b0 = $b0"
def anonFunc() = {
var i = 0;
def get = {
var x$macro$857 = null.asInstanceOf[Int];
val x$macro$858 = i.$plus(1);
i = x$macro$858;
x$macro$857 = i;
x$macro$857
};
val x$macro$859 = AsyncAwaitTest.await[Int];
val x$macro$860 = scala.concurrent.Future;
val x$macro$861 = scala.concurrent.ExecutionContext;
val x$macro$862 = x$macro$861.Implicits;
val x$macro$863 = x$macro$862.global;
val x$macro$864 = x$macro$860.apply[Int](get)(x$macro$863);
val x$macro$865 = Predef.$eq$colon$eq;
val x$macro$866 = x$macro$865.tpEquals[((scala.concurrent.Future[Int], org.coroutines.AsyncAwaitTest.Cell[Int]), Int)];
val x$macro$867 = x$macro$859.apply[(scala.concurrent.Future[Int], org.coroutines.AsyncAwaitTest.Cell[Int]), Int](x$macro$864)(x$macro$866);
val x$macro$868 = foo(get)(x$macro$867);
x$macro$868
}
// Exiting paste mode, now interpreting.
import org.coroutines._
import scala.annotation.unchecked.uncheckedVariance
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
foo: (a0: Int)(b0: Int)String
anonFunc: ()String
scala> |
If I remember correctly, there is a special encoding for the no args methods (called nullary methods), and you probably need to use the Tree api, instead of quasiquotes. I don't exactly remember what the encoding for nullary methods was - can you google for it? About On June 9, 2016 5:34:57 PM GMT+02:00, Jess Smith [email protected] wrote:
Sent from my Android device with K-9 Mail. Please excuse my brevity. |
How would I be able to tell if the Symbol disappeared? I can only see the pre- and post-canonicalization ASTs, and both contain a definition for |
You can print the symbols of different trees to compare them. On June 22, 2016 9:54:40 PM GMT+02:00, Jess Smith [email protected] wrote:
Sent from my Android device with K-9 Mail. Please excuse my brevity. |
Maybe I'm misunderstanding your suggestion. Inside |
The last Try printing the symbol's position to compare: Alternatively, you could print its full name to see which Finally, you could cast the https://github.com/scala/scala/blob/2.12.x/src/reflect/scala/reflect/internal/Symbols.scala#L219 The symbols that you want to print are those corresponding to the
or otherwise one of the cases that handle this Note that in this test case, you want to ensure that canonicalization stops when entering the scope of Also, you have to understand that AST canonicalization is essentially a recursive method that takes a tree (a complex expression) as an input, and returns two values:
For example, if you have:
you should get back the following list of declarations:
and a simple expression that is equivalent to the original tree when the above declarations are in scope:
That said, it could be the case that the current |
I printed the symbol for the first instance of The existing method case is definitely catching the In db52258, I stopped canonicalization of nested method definitions. Does this case look good to you? |
That is because you're printing info of the duplicated, untyped tree. You About the nested method canonicalization you disabled - that looks right. On Tue, Jul 5, 2016 at 9:41 PM, Jess Smith [email protected] wrote:
|
I got the symbols via For both |
Demo tests are available here.
A function that is defined inside a coroutine cannot be called inside that same coroutine. The code generator is not able to find the function.
Example:
The text was updated successfully, but these errors were encountered: