Functions 

Abstract function declarations 

Abstract function declarations are written using DEF(...) or PROC(...). Optionally, parameter lists can be specified using withParams(PARAM(...), ...) and type parameters can be specified using withTypeParams(TYPEVAR(...), ...):

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

scala> val tree = DEF("get", IntClass).tree
tree: treehugger.forest.DefDef = DefDef(Modifiers(, , Map()),get,List(),List(),TypeTree(),EmptyTree)

scala> val tree2 = (DEF("sideEffect", UnitClass) withParams()).tree
tree2: treehugger.forest.DefDef = DefDef(Modifiers(, , Map()),sideEffect,List(),List(List()),TypeTree(),EmptyTree)

scala> val tree3 = (PROC("put") withParams(PARAM("x", IntClass))).tree
tree3: treehugger.forest.ProcDef = ProcDef(Modifiers(, , Map()),put,List(),List(List(ValDef(Modifiers(<param>, , Map()),Typed(Ident(x),TypeTree()),EmptyTree))),EmptyTree)

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

scala> val tree4 = (DEF("compare", BooleanClass)
  withTypeParams(TYPEVAR(sym.A))
  withParams(PARAM("a", sym.A) := LIT(0))
  withParams(PARAM("b", sym.A) := LIT(0)): Tree)
tree4: treehugger.forest.Tree = DefDef(Modifiers(, , Map()),compare,List(TypeDef(Modifiers(, , Map()),A,List(),EmptyTree)),List(List(ValDef(Modifiers(<param>, , Map()),Typed(Ident(a),TypeTree()),Literal(Constant(0)))), List(ValDef(Modifiers(<param>, , Map()),Typed(Ident(b),TypeTree()),Literal(Constant(0))))),TypeTree(),EmptyTree)

The above examples print as:

scala> treeToString(tree)
res0: String = def get: Int

scala> treeToString(tree2)
res1: String = def sideEffect(): Unit

scala> treeToString(tree3)
res2: String = def put(x: Int)

scala> treeToString(tree4)
res3: String = def compare[A](a: A = 0)(b: A = 0): Boolean

In genral, for functions with return type:

(DEF("get"|sym, typ)
  [withParams(PARAM("x"|sym, typ|"C")[ := arg], ...)]*
  [withTypeParams(TYPEVAR(...), ...)]).tree

For procedures:

(PROC("get"|sym)
  [withParams(PARAM("x"|sym, typ|"C")[ := arg], ...)]*
  [withTypeParams(TYPEVAR(...), ...)]).tree

Function definition 

Function definitions are written by appending right-hand side tree after := as follows:

scala> val tree5 = DEF("get", IntClass) := LIT(0)
tree5: treehugger.forest.DefDef = DefDef(Modifiers(, , Map()),get,List(),List(),TypeTree(),Literal(Constant(0)))

scala> treeToString(tree5)
res4: String = def get: Int = 0

The result type can be omitted using DEF(...) as follows:

scala> val tree6 = DEF("get") := LIT(0)
tree6: treehugger.forest.DefDef = DefDef(Modifiers(, , Map()),get,List(),List(),TypeTree(),Literal(Constant(0)))

scala> treeToString(tree6)
res5: String = def get = 0

When rhs is a BLOCK(tree, ...) you need to use DEFINFER(...) to differentiate from procedures (PROC was added in 0.4.0).

scala> val tree7 = DEFINFER("get") := BLOCK(LIT(0))
tree7: treehugger.forest.DefDef = DefDef(Modifiers(, , Map()),get,List(),List(),TypeTree(),Block(List(),Literal(Constant(0))))

scala> treeToString(tree7)
res6: String = 
def get = {
  0
}

Procedures 

Procedure definitions are written using PROC(...) with BLOCK(tree, ...) for the rhs:

scala> val tree8 = PROC("write") withParams(PARAM("str", StringClass)) := BLOCK(
  LIT(0)
)
tree8: treehugger.forest.ProcDef = ProcDef(Modifiers(, , Map()),write,List(),List(List(ValDef(Modifiers(<param>, , Map()),Typed(Ident(str),TypeTree()),EmptyTree))),Block(List(),Literal(Constant(0))))

scala> treeToString(tree8)
res7: String = 
def write(str: String) {
  0
}

Currying 

Note withParams(...) clause may be added multiple times, each forming a parameter list:

scala> val tree9 = (DEF("compare")
  withTypeParams(TYPEVAR(sym.A))
  withParams(PARAM("a", sym.A))
  withParams(PARAM("b", sym.A))) := FALSE
tree9: treehugger.forest.DefDef = DefDef(Modifiers(, , Map()),compare,List(TypeDef(Modifiers(, , Map()),A,List(),EmptyTree)),List(List(ValDef(Modifiers(<param>, , Map()),Typed(Ident(a),TypeTree()),EmptyTree)), List(ValDef(Modifiers(<param>, , Map()),Typed(Ident(b),TypeTree()),EmptyTree))),TypeTree(),Literal(Constant(false)))

scala> treeToString(tree9)
res8: String = def compare[A](a: A)(b: A) = false

Default parameters 

Similar to VAL(...), PARAM(...) can be followed by := and rhs to specify the default argument:

scala> val tree10 = (DEF("compare")
  withTypeParams(TYPEVAR(sym.A))
  withParams(PARAM("a", sym.A) := LIT(0))
  withParams(PARAM("b", sym.A) := LIT(0))) := FALSE
tree10: treehugger.forest.DefDef = DefDef(Modifiers(, , Map()),compare,List(TypeDef(Modifiers(, , Map()),A,List(),EmptyTree)),List(List(ValDef(Modifiers(<param>, , Map()),Typed(Ident(a),TypeTree()),Literal(Constant(0)))), List(ValDef(Modifiers(<param>, , Map()),Typed(Ident(b),TypeTree()),Literal(Constant(0))))),TypeTree(),Literal(Constant(false)))

scala> treeToString(tree10)
res9: String = def compare[A](a: A = 0)(b: A = 0) = false

By-name parameters 

By-name parameters are written using TYPE_BYNAME(typ) as follows:

scala> val tree11 = (PROC("whileLoop")
  withParams(PARAM("cond", TYPE_BYNAME(BooleanClass)))
  withParams(PARAM("stat", TYPE_BYNAME(UnitClass))): Tree)
tree11: treehugger.forest.Tree = ProcDef(Modifiers(, , Map()),whileLoop,List(),List(List(ValDef(Modifiers(<param>, , Map()),Typed(Ident(cond),TypeTree()),EmptyTree)), List(ValDef(Modifiers(<param>, , Map()),Typed(Ident(stat),TypeTree()),EmptyTree))),EmptyTree)

scala> treeToString(tree11)
res10: String = def whileLoop(cond: => Boolean)(stat: => Unit)

Repeated parameters 

Repeated parameters are written using TYPE_*(typ) as follows:

scala> val tree12 = (DEF("sum", IntClass)
  withParams(PARAM("args", TYPE_*(IntClass))): Tree)
tree12: treehugger.forest.Tree = DefDef(Modifiers(, , Map()),sum,List(),List(List(ValDef(Modifiers(<param>, , Map()),Typed(Ident(args),TypeTree()),EmptyTree))),TypeTree(),EmptyTree)

scala> treeToString(tree12)
res11: String = def sum(args: Int*): Int