Skip to content

Fix a code example in tasty-reflect.md #10932

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

Merged
merged 4 commits into from
Jan 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions docs/docs/reference/metaprogramming/tasty-inspect.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: "TASTy Inspection"
---

```scala
libraryDependencies += "ch.epfl.lamp" %% "scala3-tasty-inspector" % scalaVersion.value
libraryDependencies += "org.scala-lang" %% "scala3-tasty-inspector" % scalaVersion.value
```

TASTy files contain the full typed tree of a class including source positions
Expand All @@ -13,7 +13,6 @@ information from the code. To avoid the hassle of working directly with the TAST
file we provide the `TastyInspector` which loads the contents and exposes it
through the TASTy reflect API.


## Inspecting TASTy files

To inspect the TASTy Reflect trees of a TASTy file a consumer can be defined in
Expand Down Expand Up @@ -46,10 +45,12 @@ scalac -d out Test.scala
scala -with-compiler -classpath out Test
```


## Template project

Using sbt version `1.1.5+`, do:
```

```shell
sbt new scala/scala3-tasty-inspector.g8
```

in the folder where you want to clone the template.
53 changes: 27 additions & 26 deletions docs/docs/reference/metaprogramming/tasty-reflect.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ types (`quoted.Type`) from [Macros](./macros.md) or on full TASTy files.
If you are writing macros, please first read [Macros](./macros.md).
You may find all you need without using TASTy Reflect.


## API: From quotes and splices to TASTy reflect trees and back

With `quoted.Expr` and `quoted.Type` we can compute code but also analyze code
Expand All @@ -19,9 +18,9 @@ generation of code will be type-correct. Using TASTy Reflect will break these
guarantees and may fail at macro expansion time, hence additional explicit
checks must be done.

To provide reflection capabilities in macros we need to add an implicit
parameter of type `scala.quoted.Quotes` and import `quotes.reflect._` from it in
the scope where it is used.
To provide reflection capabilities in macros we need to add an implicit parameter
of type `scala.quoted.Quotes` and import `quotes.reflect._` from it in the scope
where it is used.

```scala
import scala.quoted._
Expand All @@ -35,8 +34,8 @@ def natConstImpl(x: Expr[Int])(using Quotes): Expr[Int] =

### Extractors

`import quotes.reflect._` will provide all extractors and methods on TASTy Reflect
trees. For example the `Literal(_)` extractor used below.
`import quotes.reflect._` will provide all extractors and methods on TASTy
Reflect trees. For example the `Literal(_)` extractor used below.

```scala
def natConstImpl(x: Expr[Int])(using Quotes): Expr[Int] =
Expand All @@ -54,32 +53,33 @@ def natConstImpl(x: Expr[Int])(using Quotes): Expr[Int] =
'{0}
```

We can easily know which extractors are needed using `Printer.TreeStructure.show`, which returns the string representation the structure of the tree. Other printers can also be found in the `Printer` module.
We can easily know which extractors are needed using `Printer.TreeStructure.show`,
which returns the string representation the structure of the tree. Other printers
can also be found in the `Printer` module.

```scala
xTree.show(using Printer.TreeStructure)
// or
Printer.TreeStructure.show(xTree)
```


The methods `quotes.reflect.Term.{asExpr, asExprOf}` provide a way to go back to a `quoted.Expr`.
Note that `asExpr` returns a `Expr[Any]`.
On the other hand `asExprOf[T]` returns a `Expr[T]`, if the type does not conform to it an exception will be thrown at runtime.

The methods `quotes.reflect.Term.{asExpr, asExprOf}` provide a way to go back to
a `quoted.Expr`. Note that `asExpr` returns a `Expr[Any]`. On the other hand
`asExprOf[T]` returns a `Expr[T]`, if the type does not conform to it an exception
will be thrown at runtime.

### Positions

The `ast` in the context provides a `rootPosition` value. It corresponds to
the expansion site for macros. The macro authors can obtain various information about that
expansion site. The example below shows how we can obtain position information
such as the start line, the end line or even the source code at the expansion
point.
The `Position` in the context provides an `ofMacroExpansion` value. It corresponds
to the expansion site for macros. The macro authors can obtain various information
about that expansion site. The example below shows how we can obtain position
information such as the start line, the end line or even the source code at the
expansion point.

```scala
def macroImpl()(quotes: Quotes): Expr[Unit] =
import quotes.reflect._
val pos = rootPosition
val pos = Position.ofMacroExpansion

val path = pos.sourceFile.jpath.toString
val start = pos.start
Expand All @@ -99,15 +99,15 @@ transformation.

`TreeAccumulator` ties the knot of a traversal. By calling `foldOver(x, tree))`
we can dive into the `tree` node and start accumulating values of type `X` (e.g.,
of type List[Symbol] if we want to collect symbols). The code below, for
of type `List[Symbol]` if we want to collect symbols). The code below, for
example, collects the pattern variables of a tree.

```scala
def collectPatternVariables(tree: Tree)(implicit ctx: Context): List[Symbol] =
def collectPatternVariables(tree: Tree)(using ctx: Context): List[Symbol] =
val acc = new TreeAccumulator[List[Symbol]]:
def apply(syms: List[Symbol], tree: Tree)(implicit ctx: Context) = tree match
def apply(syms: List[Symbol], tree: Tree)(using ctx: Context): List[Symbol] = tree match
case Bind(_, body) => apply(tree.symbol :: syms, body)
case _ => foldOver(syms, tree)
case _ => foldOver(syms, tree)
acc(Nil, tree)
```

Expand All @@ -116,10 +116,10 @@ but without returning any value. Finally a `TreeMap` performs a transformation.

#### Let

`scala.tasty.Reflection` also offers a method `let` that allows us
to bind the `rhs` (right-hand side) to a `val` and use it in `body`. Additionally, `lets` binds
the given `terms` to names and allows to use them in the `body`. Their type definitions
are shown below:
`scala.tasty.Reflection` also offers a method `let` that allows us to bind the
`rhs` (right-hand side) to a `val` and use it in `body`. Additionally, `lets`
binds the given `terms` to names and allows to use them in the `body`. Their type
definitions are shown below:

```scala
def let(rhs: Term)(body: Ident => Term): Term = ...
Expand All @@ -130,3 +130,4 @@ def lets(terms: List[Term])(body: List[Term] => Term): Term = ...
## More Examples

* Start experimenting with TASTy Reflect ([link](https://github.com/nicolasstucki/tasty-reflection-exercise))
(outdated, need update)
2 changes: 1 addition & 1 deletion docs/docs/reference/other-new-features/indentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ at the top-level, inside braces `{...}`, but not inside parentheses `(...)`, pat

### Optional Braces Around Template Bodies

The Scala grammar uses the term _template body_ for the definitions of a class, trait, or object that are normally enclosed in braces. The braces around a template body can also be omitted by means of the following rule
The Scala grammar uses the term _template body_ for the definitions of a class, trait, or object that are normally enclosed in braces. The braces around a template body can also be omitted by means of the following rule.

If at the point where a template body can start there is a `:` that occurs at the end
of a line, and that is followed by at least one indented statement, the recognized
Expand Down