Type-Level Expressions 

Type references 

Use TYPE_REF(tree|sym|"C") to explicitly convert symbols, names, and trees into types:

(VAL("pos", TYPE_REF(REF("board") DOT "Coord")): Tree)

This prints as:

val pos: board.Coord

Applied types 

Applied types are written by calling TYPE_OF(typ|"C", ...) on a type:

REF("x") withType(ListClass TYPE_OF IntClass)

This prints as:

(x: List[Int])

Type constructors 

treehugger DSL provides built-in type constructors, which will be covered more later:

REF("x") withType(TYPE_LIST(IntClass))
REF("y") withType(TYPE_TUPLE(IntClass, IntClass))
REF("z") withType(IntClass TYPE_=> IntClass)

These examples print as:

(x: List[Int])
(y: (Int, Int))
(z: Int => Int)

Refined types 

Refined types are written by calling TYPE_WITH (typ|"C", ...) on a type:

(VAL("x", TYPE_REF("A") TYPE_WITH "B"): Tree)

This prints as:

val x: A with B

Singleton types 

Singleton type are written using TYPE_SINGLETON(tree):

(VAL("x", TYPE_SINGLETON(THIS)): Tree)

This prints as:

val x: this.type

Structural types 

Structural types are written using TYPE_STRUCT(tree, ...):

REF("x") withType(TYPE_STRUCT(
  DEF("close", UnitClass)
))

This prints as:

(x: ({ def close: Unit }))

Type projections 

Type projections are written by calling TYPE_# (typ|"C") on a type:

REF("x") withType(TYPE_STRUCT(
  TYPEVAR("L") withTypeParams(TYPEVAR("A")) :=
    REF("Const") APPLYTYPE ("M", "A")
) TYPE_#("L"))

This prints as:

(foo: ({ type L[A] = Const[M, A] })#L)

Existential types 

Existential types are written by calling TYPE_FORSOME(tree, ...) on a type:

(DEF("foo")
  withParams(PARAM("arg", TYPE_LIST(
    TYPE_REF(REF("x") DOT "T")) TYPE_FORSOME(
    VAL("x", "Outer")
)))).tree

This prints as:

def foo(arg: List[x.T] forSome { val x: Outer })