I was not able to reuse withSource to just print the source and value and return the value. The withSource macro cannot be used from the same object (therefore, I cannot just add my slightly modified version of withSource in this file), and I cannot call withSource from a subclass of WithSourceHelper , restricting reuse through inheritance.
In case anyone is interested, here is an addition to Senya's answer, just to register the value with the source and return the value so that the rest of the calculations can happen.
def logValueImpl[T](c: Context): c.Expr[T] = { import c.universe._ val source = c.prefix.tree match { case Apply(_, List(s)) => s case _ => c.abort(c.enclosingPosition, "can't find source") } val freshName = newTermName(c.fresh("logValue$")) val valDef = ValDef(Modifiers(), freshName, TypeTree(source.tpe), source) val ident = Ident(freshName) val print = reify{ println(c.literal(show(source)).splice + ": " + c.Expr[T](ident).splice) } c.Expr[T](Block(List(valDef, print.tree), ident)) }
Then I define it as an implicit conversion to def p = macro Debug.logValueImpl[T] . Then I can use it like this:
List(1, 2, 3).reverse.p.head // prints: immutable.this.List.apply[Int](1, 2, 3).reverse: List(3, 2, 1)
The funny thing is that I can apply it twice:
List(1, 2, 3).reverse.pp
And he will show me what the logValueImpl macro logValueImpl :
{ val logValue$7: List[Int] = immutable.this.List.apply[Int](1, 2, 3).reverse; Predef.println("immutable.this.List.apply[Int](1, 2, 3).reverse: ".+(logValue$7)); logValue$7 }
It seems to work with other macros too:
f"float ${1.3f}%3.2f; str ${"foo".reverse}%s%n".p` //prints: { val arg$1: Float = 1.3; val arg$2: Any = scala.this.Predef.augmentString("foo").reverse; scala.this.Predef.augmentString("float %3.2f; str %s%%n").format(arg$1, arg$2) }: float 1.30; str oof%n
Even more interesting, if I used showRaw instead of show , I even see an extended macro tree, which may be useful for determining how to write other macros.