Type members 

Abstract type declarations 

Abstract type declarations are written using TYPEVAR(sym|"T"). Optionally, lower bounds and higher bounds can be specified:

scala> import treehugger.forest._, definitions._, treehuggerDSL._
import treehugger.forest._
import definitions._
import treehuggerDSL._

scala> val tree = (TYPEVAR("T"): Tree)
[1m[34mtree[0m: [1m[32mtreehugger.forest.Tree[0m = TypeDef(Modifiers(, , Map()),T,List(),EmptyTree)

scala> treeToString(tree)
[1m[34mres0[0m: [1m[32mString[0m = type T

scala> val tree2 = (TYPEVAR("T") LOWER(IntClass): Tree)
[1m[34mtree2[0m: [1m[32mtreehugger.forest.Tree[0m = TypeDef(Modifiers(, , Map()),T,List(),TypeTree())

scala> treeToString(tree2)
[1m[34mres1[0m: [1m[32mString[0m = type T >: Int

scala> object sym {
  val T = RootClass.newAliasType("T")
  val A = RootClass.newAliasType("A")
  val B = RootClass.newAliasType("B")
}
defined object sym

scala> val tree3 = (TYPEVAR(sym.T) UPPER(ComparableClass TYPE_OF sym.T): Tree)
[1m[34mtree3[0m: [1m[32mtreehugger.forest.Tree[0m = TypeDef(Modifiers(, , Map()),T,List(),TypeTree())

scala> treeToString(tree3)
[1m[34mres2[0m: [1m[32mString[0m = type T <: Comparable[T]

or in general:

(TYPEVAR(sym|"T") [LOWER(lo|"C")] [UPPER(hi|"D")]).tree

where lo denotes an optional lower bound type and hi upper bound type.

Type alias definitions 

Type alias definitions are written by appending := and right-hand side Type. The alias may accompany type parameters given by withTypeParams(TYPEVAR(...), ...):

scala> val tree4 = TYPEVAR("IntList") := TYPE_LIST(IntClass)
[1m[34mtree4[0m: [1m[32mtreehugger.forest.TypeDef[0m = TypeDef(Modifiers(, , Map()),IntList,List(),TypeTree())

scala> treeToString(tree4)
[1m[34mres3[0m: [1m[32mString[0m = type IntList = List[Int]

scala> val tree5 = TYPEVAR("Two") withTypeParams(TYPEVAR(sym.A)) := TYPE_TUPLE(sym.A, sym.A)
[1m[34mtree5[0m: [1m[32mtreehugger.forest.TypeDef[0m = TypeDef(Modifiers(, , Map()),Two,List(TypeDef(Modifiers(, , Map()),A,List(),EmptyTree)),TypeTree())

scala> treeToString(tree5)
[1m[34mres4[0m: [1m[32mString[0m = type Two[A] = (A, A)

or in general:

TYPEVAR(sym|"T") [withTypeParams(TYPEVAR(typ1), ...)] := typ2

Variance annotations 

Variance annotations for the type parameters are set using COVARIANT(...) and CONTRAVARIANT(...):

scala> val A = RootClass.newTypeParameter("A")
[1m[34mA[0m: [1m[32mtreehugger.forest.TypeSymbol[0m = A

scala> val tree6 = (TYPEVAR("M") withTypeParams(TYPEVAR(COVARIANT(A))): Tree)
[1m[34mtree6[0m: [1m[32mtreehugger.forest.Tree[0m = TypeDef(Modifiers(, , Map()),M,List(TypeDef(Modifiers(, , Map()),A,List(),EmptyTree)),EmptyTree)

scala> val tree7 = (TYPEVAR("M") withTypeParams(TYPEVAR(CONTRAVARIANT(A))): Tree)
[1m[34mtree7[0m: [1m[32mtreehugger.forest.Tree[0m = TypeDef(Modifiers(, , Map()),M,List(TypeDef(Modifiers(, , Map()),A,List(),EmptyTree)),EmptyTree)

The above examples print as:

scala> treeToString(tree6)
[1m[34mres5[0m: [1m[32mString[0m = type M[+A]

scala> treeToString(tree7)
[1m[34mres6[0m: [1m[32mString[0m = type M[-A]