Reputation: 65
I wanted to write a macro that will inspect and modify a lamba. For now macro looks like this (it doesn't do any modification):
object Macro {
def literalInt(c: blackbox.Context)(func: c.Expr[Int => Int]): c.Expr[Int => Int] = {
import c.universe._
val Function(params, body) = func.tree
c.Expr(Function(params, body))
}
def lit(func: Int => Int): Int => Int = macro literalInt
}
It works fine for trivial lambdas, like:
Macro.lit(_ + 19)
but it fails on
Macro.lit { args =>
val temp = 10
args + temp * 2
}
with error:
scalac: Error while emitting App.scala
value temp
Does anyone know what and why is going on?
Upvotes: 0
Views: 123
Reputation: 51658
Read Macrology 201 about owner chain corruptions
https://github.com/scalamacros/macrology201/tree/part1
https://github.com/scalamacros/macrology201/commits/part1 (especially step 21 and thereafter)
An easy workaround to the owner chain corruption problem is erasing the chunk of the symbol table whose corresponding code is undergoing radical transformations. After the symbols in the problematic trees are erased, post-expansion typecheck is going to recreate them from scratch, keeping the symbol table consistent. This is done by a dedicated macro API called
c.untypecheck
in Scala 2.11* andc.resetLocalAttrs
in Scala 2.10.
(*) And Scala 2.12-2.13.
Try to untypecheck incoming trees (in easy cases this should be enough)
def literalInt(c: blackbox.Context)(func: c.Expr[Int => Int]): c.Expr[Int => Int] = {
import c.universe._
val Function(params, body) = c.untypecheck(func.tree)
c.Expr(Function(params, body))
}
Using scala macro to manipulate variable declaration
What is wrong with this def macro?
Upvotes: 1