Skip to content

Scala AST reference

Vivek Srikumar edited this page Jan 2, 2014 · 52 revisions

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.

General notes

  • All the types (say X) should be prefixed by global.X when used in a case statement.

  • Type names (like Int, Map, etc) either belong to a class called TypeName_S or TypeName_R. But these are private members of the class Names so we cannot pattern match against them. However, any AST node that is a type name has the flag isTypeName set to true. This could be used to identify type names. Below, all type names are represented by the string newTypeName("<some-name>").

Types

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 Idents take the word scala as a parameter. Most likely, we won't be using this. So, for now, let's ignore them. Ditto for nme.ROOTPKG.

Aliasing new types

New types defined using the type construction are represented by TypeDef nodes in the AST. TypeDef takes four arguments:

  1. Modifiers, which indicates whether the new type is public/private/etc. We won't be needing this for now.
  2. The name of the new type
  3. 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.
  4. 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")))))

Creating objects

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"))))
Clone this wiki locally