Writing a Macro to Test if Value Equals to 5
Kevin Meredith <[email protected]>
| Newsgroups | gmane.comp.lang.scala |
|---|---|
| Message-ID | <[email protected]> |
Given the following macro:
package net
import scala.language.experimental.macros
import scala.reflect.macros.Context
case class Equals5(value: Int) {
require(value == 5)
}
object Equals5 {
implicit def wrapInt(n: Int): Equals5 = macro verifyIntEquals5
def verifyIntEquals5(c: Context)(n: c.Expr[Int]): c.Expr[Equals5] = {
import c.universe._
val tree = n.tree match {
case Literal(Constant(x: Int)) if x == 5 =>
q"_root_.net.Equals5($n)"
case Literal(Constant(x: Int)) =>
c.abort(c.enclosingPosition, s"$x != 0")
case _ =>
q"_root_.net.Equals5($n)"
}
c.Expr(tree)
}
}
I wrote the following tests using scalatest:
package net
import org.scalatest.Matchers
import org.scalatest._
import org.scalatest.prop.Checkers._
class Equals5Test extends FlatSpec with Matchers {
it should "throw an IllegalArgumentException when trying to make an invalid
`Equals5` directly" in {
intercept[IllegalArgumentException] {
Equals5(-555) //
}
}
it should "not compile when using the macro constructor to build an
`Equals5` with a constant" in {
"""
import net.Equals5._; wrapInt(-555)
""".shouldNot(compile)
}
}
Both tests succeed.
But, I'd like for `Equals5.apply` to use the `Equals5.wrapInt` method - to
make use of the macro.
I believe that I could do this by making Equals5#apply to be private, and
then require a factory method (that uses the macro)
to be used in order to create an `Equals5` class.
Is there a better alternative? Can the `implicit def wrapInt` be used? Or
do implicits not get used during the macro compile-time stage?
Thanks,
Kevin
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
For more options, visit https://groups.google.com/d/optout.