Classes 

Class definitions 

Class definitions are written using CLASSDEF(...):

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

scala> val tree = (CLASSDEF("C"): Tree)
[1m[34mtree[0m: [1m[32mtreehugger.forest.Tree[0m = ClassDef(Modifiers(, , Map()),Modifiers(, , Map()),C,List(),List(),Template(List(),ValDef(Modifiers(private, , Map()),Ident(_),EmptyTree),List()))

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

scala> val tree2 = CLASSDEF("C") := BLOCK(
  VAL("x") := LIT(0)
)
[1m[34mtree2[0m: [1m[32mtreehugger.forest.ClassDef[0m = ClassDef(Modifiers(, , Map()),Modifiers(, , Map()),C,List(),List(),Template(List(),ValDef(Modifiers(private, , Map()),Ident(_),EmptyTree),List(ValDef(Modifiers(, , Map()),Ident(x),Literal(Constant(0))))))

scala> treeToString(tree2)
[1m[34mres1[0m: [1m[32mString[0m =
class C {
  val x = 0
}

The general form of the first example is:

CLASSDEF(sym|"C").empty

As with value and function names, CLASSDEF can accept either a symbol or a String.

Constructor parameters 

Primary constructor parameters are written using withParams(...) similar to function definitions. Except, it could use VAL(...) and VAR(...) in addition to PARAM(...):

scala> val tree3 = (CLASSDEF("C")
  withParams(PARAM("x", IntClass),
    VAL("y", StringClass),
    VAR("z", TYPE_LIST(StringClass))) := BLOCK(
  DEF("hi") := LIT("hi") 
))
[1m[34mtree3[0m: [1m[32mtreehugger.forest.ClassDef[0m = ClassDef(Modifiers(, , Map()),Modifiers(, , Map()),C,List(),List(ValDef(Modifiers(<param>, , Map()),Typed(Ident(x),TypeTree()),EmptyTree), ValDef(Modifiers(, , Map()),Typed(Ident(y),TypeTree()),EmptyTree), ValDef(Modifiers(<mutable>, , Map()),Typed(Ident(z),TypeTree()),EmptyTree)),Template(List(),ValDef(Modifiers(private, , Map()),Ident(_),EmptyTree),List(DefDef(Modifiers(, , Map()),hi,List(),List(),TypeTree(),Literal(Constant(hi))))))

scala> treeToString(tree3)
[1m[34mres2[0m: [1m[32mString[0m =
class C(x: Int, val y: String, var z: List[String]) {
  def hi = "hi"
}

Constructor definitions 

Auxiliary constructors are defined using DEFTHIS := BLOCK(stat, ...). Optionally, DEFTHIS may take withParams(...):

scala> val tree4 = (CLASSDEF("C")
  withParams(PARAM("s", StringClass)) := BLOCK(
  DEFTHIS withParams(PARAM("x", IntClass)) := BLOCK(
    THIS APPLY(REF("x") TOSTRING)
  )
))
[33mwarning: [0mthere was one feature warning; for details, enable `:setting -feature' or `:replay -feature'
[1m[34mtree4[0m: [1m[32mtreehugger.forest.ClassDef[0m = ClassDef(Modifiers(, , Map()),Modifiers(, , Map()),C,List(),List(ValDef(Modifiers(<param>, , Map()),Typed(Ident(s),TypeTree()),EmptyTree)),Template(List(),ValDef(Modifiers(private, , Map()),Ident(_),EmptyTree),List(DefDef(Modifiers(, , Map()),_$this,List(),List(List(ValDef(Modifiers(<param>, , Map()),Typed(Ident(x),TypeTree()),EmptyTree))),TypeTree(),Block(List(),Apply(This(),List(Select(Ident(x),toString))))))))

scala> treeToString(tree4)
[1m[34mres3[0m: [1m[32mString[0m =
class C(s: String) {
  def this(x: Int) = {
    this(x.toString)
  }
}

Extending classes 

To define classes by extending super classes use withParents(tree|typ|"T"):

scala> val tree5 = CLASSDEF("C") withParents("B") := BLOCK(
  DEF("x") := LIT(0)
)
[1m[34mtree5[0m: [1m[32mtreehugger.forest.ClassDef[0m = ClassDef(Modifiers(, , Map()),Modifiers(, , Map()),C,List(),List(),Template(List(TypeTree()),ValDef(Modifiers(private, , Map()),Ident(_),EmptyTree),List(DefDef(Modifiers(, , Map()),x,List(),List(),TypeTree(),Literal(Constant(0))))))

scala> treeToString(tree5)
[1m[34mres4[0m: [1m[32mString[0m =
class C extends B {
  def x = 0
}

Self type annotations 

To define self type annotations use withSelf(sym|"self", [typ1, ...]):

scala> val tree6 = CLASSDEF("C") withSelf("self", "T1", "T2") := BLOCK(
  VAL("x") := REF("self")
)
[1m[34mtree6[0m: [1m[32mtreehugger.forest.ClassDef[0m = ClassDef(Modifiers(, , Map()),Modifiers(, , Map()),C,List(),List(),Template(List(),ValDef(Modifiers(, , Map()),Typed(Ident(self),TypeTree()),EmptyTree),List(ValDef(Modifiers(, , Map()),Ident(x),Ident(self)))))

scala> treeToString(tree6)
[1m[34mres5[0m: [1m[32mString[0m =
class C { self: T1 with T2 =>
  val x = self
}

Early denifitions 

To define field values before supertype constructor is called add early definitions using withEarlyDefs(tree, ...):

scala> val tree7 = CLASSDEF("C") withEarlyDefs(
  VAL("name") := LIT("Bob")
) withParents("B") := BLOCK(
  LIT(0)
)
[1m[34mtree7[0m: [1m[32mtreehugger.forest.ClassDef[0m = ClassDef(Modifiers(, , Map()),Modifiers(, , Map()),C,List(),List(),Template(List(Block(List(),ValDef(Modifiers(, , Map()),Ident(name),Literal(Constant(Bob)))), TypeTree()),ValDef(Modifiers(private, , Map()),Ident(_),EmptyTree),List(Literal(Constant(0)))))

scala> treeToString(tree7)
[1m[34mres6[0m: [1m[32mString[0m =
class C extends {
  val name = "Bob"
} with B {
  0
}