You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Not sure if this is enough, but the I would say most important overview
(and most common pitfalls, from what I noticed in my experiences and
from some submitted issues) are included.
It's tough to see in the raw .md file here, but in Scaladoc there is a
hierarchy shown, which I think helps with the readability:
<img width="350" alt="Zrzut ekranu 2025-06-17 o 20 56 25"
src="https://github.com/user-attachments/assets/9a0fee74-a6d8-4ad5-acb4-f2180e82617d"
/>
I think another improvement here could be done by specifying in
https://scala-lang.org/api/3.3_LTS/scala/quoted/Quotes$reflectModule.html#
which AST trees correspond to what code, but that's probably a little
tricky to do cleanly
The methods `quotes.reflect.Term.{asExpr, asExprOf}` provide a way to go back to
68
-
a `quoted.Expr`. Note that `asExpr` returns a `Expr[Any]`. On the other hand
69
-
`asExprOf[T]` returns a `Expr[T]`, if the type does not conform to it an exception
70
-
will be thrown at runtime.
138
+
Bear in mind that extractors and constructors for the same trees might be comprised of different arguments, e.g. for `ValDef` the `apply` method
139
+
has `(Symbol, Option[Term])` arguments and `unapply` has `(String, TypeTree, Option[Term])` (if we want to obtain the symbol directly, we can call `.symbol` on the `ValDef`).
140
+
141
+
### Symbols
142
+
To construct definition `Trees` we might have to create or use a `Symbol`. Symbols represent the "named" parts of the code, the declarations we can reference elsewhere later. Let’s try to create `val name: Int = 0` from scratch.
143
+
To create a val like this, we need to first create a `Symbol` that matches the intended `Tree` type, so for a `ValDef` we would use the `Symbol.newVal` method:
It's worth thinking about individual `Flags` more in terms of explicitly stated modifiers, instead of general attributes.
174
+
For example, while we might say that every trait is `abstract`, a symbol of a trait will not have their `abstract` flag set
175
+
(just the `trait` flag instead), simply because it does not make sense to have an `abstract trait`.
176
+
177
+
Different types of Symbols have different flags allowed to be set, as stated in the API docs for individual `Symbol` constructor methods.
178
+
179
+
### TypeReprs and TypeTrees
180
+
When writing macros, we have access to `scala.quoted.Type`, which we can use to assign types in quoted code.
181
+
In the context of the reflection api however, it won't be of much use. We can convert it into a more useful
182
+
`TypeRepr` with `TypeRepr.of[T]` (when we have a given Type[T] in scope) which we can also convert back into a `Type`, with the simplest method being:
183
+
```scala
184
+
typeRepr.asType match
185
+
case'[t] =>
186
+
// access to a given Type[t] in scope
187
+
```
188
+
189
+
`TypeRepr`s are a type representation used when assigning and reading types from `Symbols`. It can be constructed/read similarly to the Typed AST trees. E.g.:
A `TreeTraverser` extends a `TreeAccumulator[Unit]` and performs the same traversal
121
-
but without returning any value.
299
+
but without returning any value.
122
300
123
301
`TreeMap` transforms trees along the traversal, through overloading its methods it is possible to transform only trees of specific types, for example `transformStatement` only transforms `Statement`s.
124
302
125
303
126
-
####ValDef.let
304
+
### ValDef.let
127
305
128
306
The object `quotes.reflect.ValDef` also offers a method `let` that allows us to bind the `rhs` (right-hand side) to a `val` and use it in `body`.
129
307
Additionally, `lets` binds the given `terms` to names and allows to use them in the `body`.
0 commit comments