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 are written by calling TYPE_OF(typ|"C", ...)
on a type:
REF("x") withType(ListClass TYPE_OF IntClass)
This prints as:
(x: List[Int])
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 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 type are written using TYPE_SINGLETON(tree)
:
(VAL("x", TYPE_SINGLETON(THIS)): Tree)
This prints as:
val x: this.type
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 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 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 })