| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The presentation compiler runs with `-Ymacro-expand:discard`, which
retains the macro expandee in the typechecked trees, rather than
substituting in the expansion. This mode was motivated as a means
to keep IDE functionality working (e.g. completion, navigation,
refactoring) inside macro applications.
However, if one has nested async macro applications, as reported in
the IDE ticket:
https://www.assembla.com/spaces/scala-ide/tickets/1002561
... the expansion of the outer async application was reporting
await calls enclosed by the inner async application.
This change tweaks the traversers used for this analysis to
stop whenever it sees an async.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Currently, the async transformation is performed during the typer
phase, like all other macros.
We have to levy a few artificial restrictions on whern an async
boundary may be: for instance we don't support await within a
pattern guard. A more natural home for the transform would be
after patterns have been translated.
The test case in this commit shows how to use the async transform
from a custom compiler phase after patmat.
The remainder of the commit updates the implementation to handle
the new tree shapes.
For states that correspond to a label definition, we use `-symbol.id`
as the state ID. This made it easier to emit the forward jumps to when
processing the label application before we had seen the label
definition.
I've also made the transformation more efficient in the way it checks
whether a given tree encloses an `await` call: we traverse the input
tree at the start of the macro, and decorate it with tree attachments
containig the answer to this question. Even after the ANF and state
machine transforms introduce new layers of synthetic trees, the
`containsAwait` code need only traverse shallowly through those
trees to find a child that has the cached answer from the original
traversal.
I had to special case the ANF transform for expressions that always
lead to a label jump: we avoids trying to push an assignment to a result
variable into `if (cond) jump1() else jump2()`, in trees of the form:
```
% cat sandbox/jump.scala
class Test {
def test = {
(null: Any) match {
case _: String => ""
case _ => ""
}
}
}
% qscalac -Xprint:patmat -Xprint-types sandbox/jump.scala
def test: String = {
case <synthetic> val x1: Any = (null{Null(null)}: Any){Any};
case5(){
if (x1.isInstanceOf{[T0]=> Boolean}[String]{Boolean})
matchEnd4{(x: String)String}(""{String("")}){String}
else
case6{()String}(){String}{String}
}{String};
case6(){
matchEnd4{(x: String)String}(""{String("")}){String}
}{String};
matchEnd4(x: String){
x{String}
}{String}
}{String}
```
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
|
|
|
| |
It was only working on the former.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Right now, the body of an async block suffers from diminished
IDE support: most notably hyperlinking doesn't work [1].
During the course of the blackbox/whitebox macro discussion,
we've often talked about how the former give us the latitude
to simply disable macro expansion in the IDE so we could get
these features working again, at the cost of losing domain
specific errors, such as "await must not be used under a
nested function".
But why not have our cake and eat too?
This commit detects if we are running the presentation compiler
and, after running our regular macro, returns the original macro
application. We need to annotate that tree to prevent the typechecker
from stubbornly calling our macro again.
EXPERIMENTAL NOTE: This logic shouldn't live in macros: this is
just a short term measure. If these experiments in async prove
successful, we'll roll something similar into the macro expansion
engine itself.
TODO: as a performance optimization, we could just run the
"unsupported await" checks, and avoid doing the more expensive
state machine transformation.
[1] https://www.assembla.com/spaces/scala-ide/tickets/1001449-code-navigation-fails-when-macros-are-used#/activity/ticket:
|
|
|
|
|
|
|
| |
- Adds a hook that lets a derived macro insert additional code
when zero-ing out a lifted field.
- Adds a variant of the `AsyncId` macro that logs zeroed-out fields.
- Adds a test using this mechanism
|
|
|
|
|
|
|
|
| |
- Iterative, backwards data-flow analysis
- Make sure fields captured by nested defs are never zeroed out.
This is done elegantly by declaring such fields a being live
at the exit of the final state; thus, they will never be
zeroed out.
|
|
|
|
|
|
| |
- removed outdated comments in ANF transform
- added a few comments
- removed some unnecessary imports
|
|
|
|
|
|
|
|
|
| |
- Make sure all trees are positioned
- Mark range positions for synthetic code as transparent to allow
some wiggle room for overlapping ranges.
Enables -Yrangepos for our test suite. We can't add it for
the entire build until the fix for SI-7649 lands in the compiler.
|
|
If we intend to keep CPS fallback around for any length of time
it should probably move there too.
|