Macro compilation error on non-trivial lambda - scala

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?

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* and c.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
Macro untypecheck required
What is wrong with this def macro?
How to use a `universe.Tree` created and type-checked in one Scala macro execution, in another macro execution?

Related

Get sequence of types from HList in macro

Context: I'm trying to write a macro that is statically aware of an non-fixed number of types. I'm trying to pass these types as a single type parameter using an HList. It would be called as m[ConcreteType1 :: ConcreteType2 :: ... :: HNil](). The macro then builds a match statement which requires some implicits to be found at compile time, a bit like how a json serialiser might demand implicit encoders. I've got a working implementation of the macro when used on a fixed number of type parameters, as follows:
def m[T1, T2](): Int = macro mImpl[T1, T2]
def mImpl[T1: c.WeakTypeTag, T2: c.WeakTypeTag](c: Context)(): c.Expr[Int] = {
import c.universe._
val t = Seq(
weakTypeOf[T1],
weakTypeOf[T2]
).map(c => cq"a: $c => externalGenericCallRequiringImplicitsAndReturningInt(a)")
val cases = q"input match { case ..$t }"
c.Expr[Int](cases)
}
Question: If I have a WeakTypeTag[T] for some T <: HList, is there any way to turn that into a Seq[Type]?
def hlistToSeq[T <: HList](hlistType: WeakTypeTag[T]): Seq[Type] = ???
My instinct is to write a recursive match which turns each T <: HList into either H :: T or HNil, but I don't think that kind of matching exists in scala.
I'd like to hear of any other way to get a list of arbitrary size of types into a macro, bearing in mind that I would need a Seq[Type], not Expr[Seq[Type]], as I need to map over them in macro code.
A way of writing a similar 'macro' in Dotty would be interesting too - I'm hoping it'll be simpler there, but haven't fully investigated yet.
Edit (clarification): The reason I'm using a macro is that I want a user of the library I'm writing to provide a collection of types (perhaps in the form of an HList), which the library can iterate over and expect implicits relating to. I say library, but it will be compiled together with the uses, in order for the macros to run; in any case it should be reusable with different collections of types. It's a bit confusing, but I think I've worked this bit out - I just need to be able to build macros that can operate on lists of types.
Currently you seem not to need macros. It seems type classes or shapeless.Poly can be enough.
def externalGenericCallRequiringImplicitsAndReturningInt[C](a: C)(implicit
mtc: MyTypeclass[C]): Int = mtc.anInt
trait MyTypeclass[C] {
def anInt: Int
}
object MyTypeclass {
implicit val mtc1: MyTypeclass[ConcreteType1] = new MyTypeclass[ConcreteType1] {
override val anInt: Int = 1
}
implicit val mtc2: MyTypeclass[ConcreteType2] = new MyTypeclass[ConcreteType2] {
override val anInt: Int = 2
}
//...
}
val a1: ConcreteType1 = null
val a2: ConcreteType2 = null
externalGenericCallRequiringImplicitsAndReturningInt(a1) //1
externalGenericCallRequiringImplicitsAndReturningInt(a2) //2

Scala Macros: get vals from object

I use scala macros for extract all object from package, and then i would like get some values from object:
package example
trait A {}
object B extends A { val test = "test" }
//macro
object Macro
def getVals(packageName: String) = macro getValsImpl
def getValsImpl(c: Context)(packageName: c.Expr[String]): c.Expr[Unit] = {
import c.universe._
val pkg = from.tree match {
case Literal(Constant(name: String)) => c.mirror.staticPackage(name)
}
val objects = pkg.typeSignature.members.collect {
//get all objects which a subtype of `A`
case x if (x.isModule && x.typeSignature <:< typeOf[A]) => x
}.toList
val o = objects(0)
println(o.test)
reify {}
}
}
But i got error
value test is not a member of c.universe.ModuleSymbol
You are mistaking compile time artifacts for actual runtime values.
Macro implementation is invoked at compile time. The actual objects you are trying to access don't yet exist (only the language Symbols that represent them). That is why you are getting a ModuleSymbol when you expect the B object.
In other words, you simply can't access B in macro implementation.
Macros are meant to analyze, transform and generate code (represented as Exprs and Trees). So, what you can do is - having a ModuleSymbol that represents an object - generate code that, when compiled and finally executed in runtime, will evaluate to that object. But I don't know if this is what you want here.

Scala Macros: Convert/parse a Tree to a Name

This is a simplified example but the problem remains the same.
I want to achieve this using macros (scala based pseudocode):
(a: Int) => {
val z = "toShort"
a.z
}
If I reify it, I would obtain something similar to this:
Function(
List(
ValDef(
Modifiers(Flag.PARAM),
newTermName("a"),
Ident(scala.Int),
EmptyTree
)
),
Block(
List(
ValDef(
Modifiers(),
newTermName("z"),
TypeTree(),
Literal(Constant("toShort"))
)
),
Apply(
Select(
Ident(newTermName("a")),
newTermName("toShort")
),
List()
)
)
)
I dont know how to access to a value and then use it as a TermName.
I tried replacing newTermName("toShort") with newTermName(c.Expr[String](Select(Ident(newTermName("z")))).splice) but the compiler doesn't seem to like:
exception during macro expansion:
java.lang.UnsupportedOperationException: the function you're calling has not been spliced by > the compiler.
this means there is a cross-stage evaluation involved, and it needs to be invoked explicitly.
if you're sure this is not an oversight, add scala-compiler.jar to the classpath,
import scala.tools.reflect.Eval and call <your expr>.eval instead.
I've also tried 'eval' as suggested by compiler: newTermName(c.eval(c.Expr[String](...)) but neither worked.
How could I convert a tree like Select(Ident(newTermName("z"))) (which is a access to a value of a local val) to a Name a string which can be used as a parameter for newTermName? Is it possible?
UPDATE:
Here the real problem brought to you as a gist!
Thanks in advance,
I have a hard time understanding what you're trying to achieve, and why you are using Trees everywhere. Trees are really low level, hard to use, tricky, and it is very difficult to understand what the code does. Quasiquotes (http://docs.scala-lang.org/overviews/macros/quasiquotes.html) are the way to go indeed and you can use them on scala 2.10.x production release thanks to the macro paradise plugin (http://docs.scala-lang.org/overviews/macros/paradise.html). The you can simply write q"(a: Int) => {val z = "toShort"; a.z}" and you directly get the tree expression you just typed.
To answer your question, the first point is to remember that macros are evaluated at compile time. They therefore can not generate code which depends on a runtime value. This is why the compiler is complaining about your splice. But if you pass a value which can be computed at compile time, typically a literal, then you can use eval to get its value within your macro code. Eval does suffer a bug though, as indicated in scaladoc. It should only be called on untyped trees. So the way to call eval on an s: c.Expr[String] expression would be val s2 = c.eval(c.Expr[String](c.resetAllAttrs(c.tree.duplicate))) which gives you a String you can then use normally in your code, for instance q"(a: Int) => a.${newTermName(s2)}".
To put it all together, let's imagine you to create a macro that'll output a string value from an object and one of its String field. It'll give something like
def attr[A](a: A, field: String): String = macro attrImpl[A]
def attrImpl[A: c.WeakTypeTag](c: Context)(a: c.Expr[A], field: c.Expr[String]) = {
import c.universe._
val s = c.eval(c.Expr[String](c.resetAllAttrs(field.tree.duplicate)))
c.Expr[String](q"a.${newTermName(s)}")
}
REPL session test:
scala> object a { val field1 = "field1"; val field2 = "field2" }
defined module a
scala> attr(a, "field1")
res0: String = field1
scala> attr(a, "field2")
res1: String = field2
To understand the difference between compile time and runtime, you can meditate about the following result in REPL ;-)
scala> val s = "field1"; attr(a, s)
error: exception during macro expansion:
scala.tools.reflect.ToolBoxError: reflective compilation has failed:
$iw is not an enclosing class
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal.throwIfErrors(ToolBoxFactory.scala:311)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal.compile(ToolBoxFactory.scala:244)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.compile(ToolBoxFactory.scala:408)
at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.eval(ToolBoxFactory.scala:411)
at scala.reflect.macros.runtime.Evals$class.eval(Evals.scala:16)
at scala.reflect.macros.runtime.Context.eval(Context.scala:6)
at .attrImpl(<console>:14)
scala> val s = "field1"
s: String = field1
scala> attr(a, s)
res3: String = field1
Hope it helps ;))

Scala Macros, generating type parameter calls

I'm trying to generalize setting up Squeryl (Slick poses the same problems AFAIK). I want to avoid having to name every case class explicitly for a number of general methods.
table[Person]
table[Bookmark]
etc.
This also goes for generating indexes, and creating wrapper methods around the CRUD methods for every case class.
So ideally what I want to do is have a list of classes and make them into tables, add indexes and add a wrapper method:
val listOfClasses = List(classOf[Person], classOf[Bookmark])
listOfClasses.foreach(clazz => {
val tbl = table[clazz]
tbl.id is indexed
etc.
})
I thought Scala Macros would be the thing to apply here, since I don't think you can have values as type parameters. Also I need to generate methods for every type of the form:
def insert(model: Person): Person = persons.insert(model)
I've got my mits on an example on Macros but I don't know how to generate a generic datastructure.
I got this simple example to illustrate what I want:
def makeList_impl(c: Context)(clazz: c.Expr[Class[_]]): c.Expr[Unit] = {
import c.universe._
reify {
println(List[clazz.splice]()) // ERROR: error: type splice is not a member of c.Expr[Class[_]]
}
}
def makeList(clazz: Class[_]): Unit = macro makeList_impl
How do I do this? Or is Scala Macros the wrong tool?
Unfortunately, reify is not flexible enough for your use case, but there's good news. In macro paradise (and most likely in 2.11.0) we have a better tool to construct trees, called quasiquotes: http://docs.scala-lang.org/overviews/macros/quasiquotes.html.
scala> def makeList_impl(c: Context)(clazz: c.Expr[Class[_]]): c.Expr[Any] = {
| import c.universe._
| val ConstantType(Constant(tpe: Type)) = clazz.tree.tpe
| c.Expr[Any](q"List[$tpe]()")
| }
makeList_impl: (c: scala.reflect.macros.Context)(clazz: c.Expr[Class[_]])c.Expr[Any]
scala> def makeList(clazz: Class[_]): Any = macro makeList_impl
defined term macro makeList: (clazz: Class[_])Any
scala> makeList(classOf[Int])
res2: List[Int] = List()
scala> makeList(classOf[String])
res3: List[String] = List()
Quasiquotes are even available in 2.10.x with a minor tweak to the build process (http://docs.scala-lang.org/overviews/macros/paradise.html#macro_paradise_for_210x), so you might want to give them a try.
This will probably not fill all your needs here, but it may help a bit:
The signature of table method looks like this:
protected def table[T]()(implicit manifestT: Manifest[T]): Table[T]
As you can see, it takes implicit Manifest object. That object is passed automatically by the compiler and contains information about type T. This is actually what Squeryl uses to inspect database entity type.
You can just pass these manifests explicitly like this:
val listOfManifests = List(manifest[Person], manifest[Bookmark])
listOfManifests.foreach(manifest => {
val tbl = table()(manifest)
tbl.id is indexed
etc.
})
Unfortunately tbl in this code will have type similar to Table[_ <: CommonSupertypeOfAllGivenEntities] which means that all operations on it must be agnostic of concrete type of database entity.

How to write this three-liner as a one-liner?

I like the way, you can write one-liner-methods in Scala, e.g. with List(1, 2, 3).foreach(..).map(..).
But there is a certain situation, that sometimes comes up when writing Scala code, where things get a bit ugly. Example:
def foo(a: A): Int = {
// do something with 'a' which results in an integer
// e.g. 'val result = a.calculateImportantThings
// clean up object 'a'
// e.g. 'a.cleanUp'
// Return the result of the previous calculation
return result
}
In this situation we have to return a result, but can not return it directly after the calculation is done, because we have to do some clean up before returning.
I always have to write a three-liner. Is there also a possibility to write a one-liner to do this (without changing the class of A, because this may be a external library which can not be changed) ?
There are clearly side-effects involved here (otherwise the order of invocation of calculateImportantThings and cleanUp wouldn't matter) so you would be well advised to reconsider your design.
However, if that's not an option you could try something like,
scala> class A { def cleanUp {} ; def calculateImportantThings = 23 }
defined class A
scala> val a = new A
a: A = A#927eadd
scala> (a.calculateImportantThings, a.cleanUp)._1
res2: Int = 23
The tuple value (a, b) is equivalent to the application Tuple2(a, b) and the Scala specification guarantees that its arguments will be evaluated left to right, which is what you want here.
This is a perfect use-case for try/finally:
try a.calculateImportantThings finally a.cleanUp
This works because try/catch/finally is an expression in scala, meaning it returns a value, and even better, you get the cleanup whether or not the calculation throws an exception.
Example:
scala> val x = try 42 finally println("complete")
complete
x: Int = 42
There is, in fact, a Haskell operator for just such an occasion:
(<*) :: Applicative f => f a -> f b -> f a
For example:
ghci> getLine <* putStrLn "Thanks for the input!"
asdf
Thanks for the input!
"asdf"
All that remains then is to discover the same operator in scalaz, since scalaz usually replicates everything that Haskell has. You can wrap values in Identity, since Scala doesn't have IO to classify effects. The result would look something like this:
import scalaz._
import Scalaz._
def foo(a: A): Int =
(a.calculateImportantThings.pure[Identity] <* a.cleanup.pure[Identity]).value
This is rather obnoxious, though, since we have to explicitly wrap the side-effecting computations in Identity. Well the truth is, scalaz does some magic that implicitly converts to and from the Identity container, so you can just write:
def foo(a: A): Int = Identity(a.calculateImportantThings) <* a.cleanup()
You do need to hint to the compiler somehow that the leftmost thing is in the Identity monad. The above was the shortest way I could think of. Another possibility is to use Identity() *> foo <* bar, which will invoke the effects of foo and bar in that order, and then produce the value of foo.
To return to the ghci example:
scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._
scala> val x : String = Identity(readLine) <* println("Thanks for the input!")
<< input asdf and press enter >>
Thanks for the input!
x: String = asdf
Maybe you want to use a kestrel combinator? It is defined as follows:
Kxy = x
So you call it with the value you want to return and some side-effecting operation you want to execute.
You could implement it as follows:
def kestrel[A](x: A)(f: A => Unit): A = { f(x); x }
... and use it in this way:
kestrel(result)(result => a.cleanUp)
More information can be found here: debasish gosh blog.
[UPDATE] As Yaroslav correctly points out, this is not the best application of the kestrel combinator. But it should be no problem to define a similar combinator using a function without arguments, so instead:
f: A => Unit
someone could use:
f: () => Unit
class Test {
def cleanUp() {}
def getResult = 1
}
def autoCleanup[A <: Test, T](a: A)(x: => T) = {
try { x } finally { a.cleanUp }
}
def foo[A <: Test](a:A): Int = autoCleanup(a) { a.getResult }
foo(new Test)
You can take a look at scala-arm project for type class based solution.
Starting Scala 2.13, the chaining operation tap can be used to apply a side effect (in this case the cleanup of A) on any value while returning the original value untouched:
def tap[U](f: (A) => U): A
import util.chaining._
// class A { def cleanUp { println("clean up") } ; def calculateImportantThings = 23 }
// val a = new A
val x = a.calculateImportantThings.tap(_ => a.cleanUp)
// clean up
// x: Int = 23
In this case tap is a bit abused since we don't even use the value it's applied on (a.calculateImportantThings (23)) to perform the side effect (a.cleanUp).