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 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 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]