I heard you like code, so…

treehugger lets you treat Scala code as data (case classes), and data as code (treehugger DSL) so you can code while you code.

For example, here’s treehugger DSL for Hello World:

import treehugger.forest._
import definitions._
import treehuggerDSL._

val tree: Tree = Predef_println APPLY LIT("Hello, world!")

println(tree)
println(treeToString(tree))

The above code prints two lines:

Apply(Ident(println),List(Literal(Constant(Hello, world!))))
println("Hello, world!")

The first line shows the structure of the returned tree, and the second line is the Scala source code represented by the tree. Because it is responsible for formatting of the string, your code generating code would be more clear using treehugger.

Classy example

Let’s omit the import statements, and println statements from here. Here’s how treehugger DSL defines classes:

object sym {
  val IntQueue = RootClass.newClass("IntQueue")
  val BasicIntQueue = RootClass.newClass("BasicIntQueue")
  val buf = BasicIntQueue.newValue("buf")
}

CLASSDEF(sym.IntQueue) withFlags(Flags.ABSTRACT) := BLOCK(
  DEF("get", IntClass),
  DEF("put") withParams(PARAM("x", IntClass))
)

CLASSDEF(sym.BasicIntQueue) withParents(sym.IntQueue) := BLOCK(
  VAL(buf) withFlags(Flags.PRIVATE) :=
    NEW(ArrayBufferClass TYPE_OF IntClass),
  DEF("get", IntClass) := REF(sym.buf) DOT "remove" APPLY(),
  DEF("put") withParams(PARAM("x", IntClass)) := BLOCK(
    REF(buf) INFIX("+=") APPLY REF("x")
  )
)

These print as:

abstract class IntQueue {
  def get(): Int
  def put(x: Int)
}

class BasicIntQueue extends IntQueue {
  private val buf = new scala.collection.mutable.ArrayBuffer[Int]
  def get: Int = buf.remove()
  def put(x: Int) {
    buf += x
  }
}

Notice some of the symbols were defined upfront so we could avoid typing in string names.

Thanks scalac!

To be clear where the credit is due, the majority of treehugger’s code is borrowed from the Scala compiler (scalac) written by Martin Odersky, Paul Phillips, and others. treehugger just took it further to fit its needs.