Details for exercise 7
The VariableScope
Variable scopes are used internally by the compiler to determine what a variable, in the code, references. For example, imagine the following code:
def myMethod(String arg) { (1)
arg.toUpperCase() (2)
}
1 | a Parameter named arg |
2 | a VariableExpression named arg, referencing the Parameter arg |
The AST represents the arg
variable inside the code body as a VariableExpression
, which is a different instance from the Parameter
instance of the same name. We do this because you cannot be sure at compile time (well, depending on the compile phase) what a token represents.
Internally, the compiler will create variable scopes to resolve those variables, and in the end, the VariableExpression
will have an accessed variable set to the actual Parameter
.
Tips and tricks
-
If you feel lazy, use the
VariableScopeVisitor
class, but make sure it does not visit the same code twice, or it would be broken!
Comments
Variables are resolved at the semantic analysis
phase. That is to say that when you run an AST transformation, variables are already resolved. As a conclusion, you have to deal with the variable targets by yourself, either by specifying the accessed variable for each variable by yourself, or using the VariableScopeVisitor
(with care).
Compatibility with @TypeChecked and @CompileStatic
Writing an AST transformation is not difficult. Writing an AST transformation which is compatible with type checking (and static compilation) is trickier. In particular, you can face cryptic error messages when mixing @CompileStatic
with another AST transformation. There are various reasons for that and we will explain some ideas here.
Tips and tricks
-
Use types. If you create a field, a variable, or anything else that can have a type, define it, or your AST transformation will not be compatible
The
The problem is that the AST transform did not specify the type of |