-
Notifications
You must be signed in to change notification settings - Fork 17
Scala AST reference
This document is not a formal reference for the AST created by the Scala compiler. It provides several examples for the kinds of nodes in the AST that we may encounter.
-
All the types (say
X
) should be prefixed byglobal.X
when used in a case statement. -
Type names (like Int, Map, etc) either belong to a class called
TypeName_S
orTypeName_R
. But these are private members of the classNames
so we cannot pattern match against them. However, any AST node that is a type name has the flagisTypeName
set totrue
. This could be used to identify type names. Below, all type names are represented by the stringnewTypeName("<some-name>")
.
Types are identified by either Ident
, Select
or AppliedTypeTree
. See notes on Select
below.
Here are some examples.
Scala type | AST case class |
---|---|
Int |
Ident(newTypeName("Int")) |
String |
Ident(newTypeName("String")) |
Foo |
Ident(newTypeName("Foo")) |
java.util.Random |
Select(Select(Ident(newTermName("java")), newTermName("util")), newTypeName("Random")) |
scala.util.Random |
Select(Select(Ident(newTermName("scala")), newTermName("util")), newTypeName("Random")) |
Set[String] |
AppliedTypeTree(Ident(newTypeName("Set")),List(Ident(newTypeName("String")))) |
Map[String, Int] |
AppliedTypeTree(Ident(newTypeName("Map")), List(Ident(newTypeName("String")), Ident(newTypeName("Int")))) |
(String, Int) |
AppliedTypeTree(Select(Ident(scala), newTypeName("Tuple2")), List(Ident(newTypeName("String")), Ident(newTypeName("Int")))) |
(String, Int, Double) |
AppliedTypeTree(Select(Ident(scala), newTypeName("Tuple3")), List(Ident(newTypeName("String")), Ident(newTypeName("Int")), Ident(newTypeName("Double")))) |
String => Double |
AppliedTypeTree(Select(Select(Ident(nme.ROOTPKG), scala), newTypeName("Function1")), List(Ident(newTypeName("String")), Ident(newTypeName("Double")))) |
(String, Int) => Double |
AppliedTypeTree(Select(Select(Ident(nme.ROOTPKG), scala), newTypeName("Function2")), List(Ident(newTypeName("String")), Ident(newTypeName("Int")), Ident(newTypeName("Double"))) |
(String, Int, Boolean) => Double |
AppliedTypeTree(Select(Select(Ident(nme.ROOTPKG), scala), newTypeName("Function3")), List(Ident(newTypeName("String")), Ident(newTypeName("Int")), Ident(newTypeName("Boolean")), Ident(newTypeName("Double")))) |
String => Int => Double |
AppliedTypeTree(Select(Select(Ident(nme.ROOTPKG), scala), newTypeName("Function1")), List(Ident(newTypeName("String")), AppliedTypeTree(Select(Select(Ident(nme.ROOTPKG), scala), newTypeName("Function1")), List(Ident(newTypeName("Int")), Ident(newTypeName("Double")))))) |
Notes
- In general,
AppliedTypeTree
takes two arguments. The first argument tells us about the type and the second argument is a list that gives information about the types of parameters used to construct the types. -
Select
is used to pick a member of a type or an object. We will see more of this below too. - Some
Ident
s take the word scala as a parameter. Most likely, we won't be using this. So, for now, let's ignore them. Ditto fornme.ROOTPKG
.
New types defined using the type
construction are represented by TypeDef
nodes in the AST. TypeDef
takes four arguments:
- Modifiers, which indicates whether the new type is public/private/etc. We won't be needing this for now.
- The name of the new type
- A list of parameters for the type (eg, for cases like
type Foo[T, S] = Map[T, S]
. Not sure if we will need this. - The RHS which should be a valid type expression (that is, it should be something like what is defined in the Types section above.
Scala expression | AST case class |
---|---|
type Foo1 = Int |
TypeDef(Modifiers(), newTypeName("Foo1"), List(), Ident(newTypeName("Int"))) |
type Foo3 = Set[String] |
TypeDef(Modifiers(), newTypeName("Foo3"), List(), AppliedTypeTree(Ident(newTypeName("Set")), List(Ident(newTypeName("String"))))) |
type Foo8 = Foo |
TypeDef(Modifiers(), newTypeName("Foo3"), List(), AppliedTypeTree(Ident(newTypeName("Set")), List(Ident(newTypeName("String"))))) |
type Foo12[T] = Set[T] |
TypeDef(Modifiers(), newTypeName("Foo12"), List(TypeDef(Modifiers(PARAM), newTypeName("T"), List(), TypeBoundsTree(Select(Select(Ident(nme.ROOTPKG), scala), newTypeName("Nothing")), Select(Select(Ident(nme.ROOTPKG), scala), newTypeName("Any"))))), AppliedTypeTree(Ident(newTypeName("Set")), List(Ident(newTypeName("T"))))) |
Scala objects are either literals (integers, strings, etc) or are created by calling a constructor.
Scala object | AST case class |
---|---|
1 |
Literal(Constant(1)) |
"wolfe" |
Literal(Constant("wolfe")) |
1.3 |
Literal(Constant("wolfe")) |
true |
Literal(Constant(true)) |
new Foo |
Apply(Select(New(Ident(newTypeName("Foo"))), nme.CONSTRUCTOR), List()) |
new Foo(a, b) |
Apply(Select(New(Ident(newTypeName("Foo"))), nme.CONSTRUCTOR), List(Ident(newTermName("a")), Ident(newTermName("b")))) |
new some.where.Foo |
Apply(Select(New(Select(Select(Ident(newTermName("some")), newTermName("where")), newTypeName("Foo"))), nme.CONSTRUCTOR), List()) |
new some.where.Foo(a,b) |
Apply(Select(New(Select(Select(Ident(newTermName("some")), newTermName("where")), newTypeName("Foo"))), nme.CONSTRUCTOR), List(Ident(newTermName("a")), Ident(newTermName("b")))) |
Assignment to a val
is represented using the ValDef
case class, which takes four arguments:
- Modifier, representing private/public/etc, which we won't use for now
- The name of the new term
- The type of the new term (if explicitly stated), as a type node (see section on Types)
- The right hand side (which could represent any expression)
Some examples below
Scala statement | AST case class |
---|---|
val num = 1 |
ValDef(Modifiers(), newTermName("num"), TypeTree(), Literal(Constant(1))) |
private val dbl: Double = 1.3 |
ValDef(Modifiers(), newTermName("num"), TypeTree(), Literal(Constant(1))) |
val foo = new Foo |
ValDef(Modifiers(), newTermName("num"), TypeTree(), Literal(Constant(1))) |
val fooab = new Foo(a, b) |
ValDef(Modifiers(), newTermName("fooab"), TypeTree(), Apply(Select(New(Ident(newTypeName("Foo"))), nme.CONSTRUCTOR), List(Ident(newTermName("a")), Ident(newTermName("b"))))) |