Symbols, Types, and Trees 

Having the scalac lineage comes with the baggage of having to deal with its data structures.


A Symbol represents an entry in the symbol table, such as values, classes, and type aliases. A compiler would eventually bind all identifiers to a symbol during Typing phase. However, since we are interested in generating the code, the use of symbols are often optional in treehugger.

For example, a unit method declaration may be defined as:




Both would yield the same source code at the end. There are several places where the use of symbols are recommended.

First, use a built-in symbol if there is one available. Built-in symbols are defined under treehugger.forest.definitions.

Second, consider defining a symbol for repeated reference to a class or a method. A new symbol may be defined off of an existing symbol as follows:

scala> object sym {
  val BasicIntQueue = RootClass.newClass("BasicIntQueue")
  val buf = BasicIntQueue.newValue("buf")  
  val A = ArrowAssocClass.newTypeParameter("A")
  val arrow = ArrowAssocClass.newMethod("->")
  val B = arrow.newTypeParameter("B")
  val T = BasicIntQueue.newAliasType("T")
defined module sym

Defining symbols for every identifiers would double the size of the code, and would likely make the experience of writing it cumbersome.


A Type represents a Scala type. Symbols of class ClassSymbols and TypeSymbols can automatically be promoted to a Type and many of the built-in symbols represent built-in classes.

VAL("foo", IntClass)

In the above code, IntClass is a symbol, but it is automatically promoted to a Type. Similarly, a String can also be promoted to a Type.

VAL("foo", "Int")

Types can also be created using type-level expressions and built-in type constructors:

TYPE_REF(REF("board") DOT "Coord")


A Tree represents a node in a Scala AST. It could be a simple expression such as a literal, or a combination of other trees.

An expression in treehugger DSL eventually evaluates to a Tree value.