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
.
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"
}
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)
}
}
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
}
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
}
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
}