Class definitions are written using CLASSDEF(...):
(CLASSDEF("C"): Tree)
CLASSDEF("C") := BLOCK(
VAL("x") := LIT(0)
)
The above examples print as:
class C
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(...):
CLASSDEF("C")
withParams(PARAM("x", IntClass),
VAL("y", StringClass),
VAR("z", TYPE_LIST(StringClass))) := BLOCK(
DEF("hi") := LIT("hi")
)
This prints as:
class C(x: Int, val y: String, var z: List[String]) {
def hi = "hi"
}
To define classes by extending super classes use withParents(tree|typ|"T"):
CLASSDEF("C") withParents("B") := BLOCK(
DEF("x") := LIT(0)
)
This prints as:
class C extends B {
def x = 0
}
To define self type annotations use withSelf(sym|"self", [typ1, ...]):
CLASSDEF("C") withSelf("self", "T1", "T2") := BLOCK(
VAL("x") := REF("self")
)
This prints as:
class C { self: T1 with T2 =>
val x = self
}
To define field values before supertype constructor is called add early definitions using withEarlyDefs(tree, ...):
CLASSDEF("C") withEarlyDefs(
VAL("name") := LIT("Bob")
) withParents("B") := BLOCK(
LIT(0)
)
This prints as:
class C extends {
val name = "Bob"
} with B {
0
}