Scala Macros: Accessing members with quasiquotes

Emre

I'm trying to implement an implicit materializer as described here: http://docs.scala-lang.org/overviews/macros/implicits.html

I decided to create a macro that converts a case class from and to a String using quasiquotes for prototyping purposes. For example:

case class User(id: String, name: String)
val foo = User("testid", "foo")

Converting foo to text should result in "testid foo" and vice versa.

Here is the simple trait and its companion object I have created:

trait TextConvertible[T] {
  def convertTo(obj: T): String
  def convertFrom(text: String): T
}

object TextConvertible {
  import language.experimental.macros
  import QuasiTest.materializeTextConvertible_impl
  implicit def materializeTextConvertible[T]: TextConvertible[T] = macro materializeTextConvertible_impl[T]
}

and here is the macro:

object QuasiTest {
  import reflect.macros._

  def materializeTextConvertible_impl[T: c.WeakTypeTag](c: Context): c.Expr[TextConvertible[T]] = {
    import c.universe._
    val tpe = weakTypeOf[T]

    val fields = tpe.declarations.collect {
      case field if field.isMethod && field.asMethod.isCaseAccessor => field.asMethod.accessed
    }

    val strConvertTo = fields.map {
      field => q"obj.$field"
    }.reduce[Tree] {
      case (acc, elem) => q"""$acc + " " + $elem"""
    }

    val strConvertFrom = fields.zipWithIndex map {
      case (field, index) => q"splitted($index)"
    }

    val quasi = q"""
      new TextConvertible[$tpe] {
        def convertTo(obj: $tpe) = $strConvertTo
        def convertFrom(text: String) = {
          val splitted = text.split(" ")
          new $tpe(..$strConvertFrom)
        }
      }
    """

    c.Expr[TextConvertible[T]](quasi)
  }
}

which generates

{
  final class $anon extends TextConvertible[User] {
    def <init>() = {
      super.<init>();
      ()
    };
    def convertTo(obj: User) = obj.id.$plus(" ").$plus(obj.name);
    def convertFrom(text: String) = {
      val splitted = text.split(" ");
      new User(splitted(0), splitted(1))
    }
  };
  new $anon()
}

The generated code looks fine, but yet I get the error value id in class User cannot be accessed in User in compilation while trying to use the macro.

I suspect I am using a wrong type for fields. I tried field.asMethod.accessed.name, but it results in def convertTo(obj: User) = obj.id .$plus(" ").$plus(obj.name ); (note the extra spaces after id and name), which naturally results in the error value id is not a member of User.

What am I doing wrong?

Emre

Ah, figured it out almost immediately after sending my question.

I changed the lines

val fields = tpe.declarations.collect {
  case field if field.isMethod && field.asMethod.isCaseAccessor => field.asMethod.accessed
}

to

val fields = tpe.declarations.collect {
  case field if field.isMethod && field.asMethod.isCaseAccessor => field.name
}

which solved the problem.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Unapply/pattern matching with scala macros and quasiquotes for knownDirectSubclasses

From Dev

Unapply/pattern matching with scala macros and quasiquotes for knownDirectSubclasses

From Dev

Quasiquotes and Generics in Scala

From Dev

Matching function literals with quasiquotes in Scala

From Dev

scala quasiquotes convert Tree to AppliedType

From Dev

Matching function literals with quasiquotes in Scala

From Dev

Scala maven builder doesn't understand quasiquotes

From Dev

Lifting string variable using Scala quasiquotes

From Dev

Scala implicit macros: Filter type members (tpe.decls) by sub-type

From Dev

Necessary to export Quasiquotes dependency for exported macro libraries on Scala 2.10?

From Dev

Use Scala Quasiquotes to generate a class which inherits from a known class

From Dev

How can I splice in a type and a default value in Scala quasiquotes?

From Dev

How can I splice in a type and a default value in Scala quasiquotes?

From Dev

Accessing members of mixin traits

From Dev

Accessing members like array?

From Dev

Accessing Dynamic Members on "this"

From Dev

Accessing members like array?

From Dev

Accessing Xcode LLVM Processor Macros

From Dev

Accessing Xcode LLVM Processor Macros

From Dev

scala macros generating implicits

From Dev

Can this be done with Scala macros?

From Dev

"debugging" scala annotation macros

From Dev

Debug Scala Macros with Intellij

From Dev

Accessing consecutive members with a single pointer

From Dev

java nashorn accessing superclass members

From Dev

Accessing widgets which are members of a GridLayout

From Dev

object members and accessing them in JS

From Dev

CRTP -- accessing incomplete type members

From Dev

Swift: Accessing members of tuples in Array

Related Related

  1. 1

    Unapply/pattern matching with scala macros and quasiquotes for knownDirectSubclasses

  2. 2

    Unapply/pattern matching with scala macros and quasiquotes for knownDirectSubclasses

  3. 3

    Quasiquotes and Generics in Scala

  4. 4

    Matching function literals with quasiquotes in Scala

  5. 5

    scala quasiquotes convert Tree to AppliedType

  6. 6

    Matching function literals with quasiquotes in Scala

  7. 7

    Scala maven builder doesn't understand quasiquotes

  8. 8

    Lifting string variable using Scala quasiquotes

  9. 9

    Scala implicit macros: Filter type members (tpe.decls) by sub-type

  10. 10

    Necessary to export Quasiquotes dependency for exported macro libraries on Scala 2.10?

  11. 11

    Use Scala Quasiquotes to generate a class which inherits from a known class

  12. 12

    How can I splice in a type and a default value in Scala quasiquotes?

  13. 13

    How can I splice in a type and a default value in Scala quasiquotes?

  14. 14

    Accessing members of mixin traits

  15. 15

    Accessing members like array?

  16. 16

    Accessing Dynamic Members on "this"

  17. 17

    Accessing members like array?

  18. 18

    Accessing Xcode LLVM Processor Macros

  19. 19

    Accessing Xcode LLVM Processor Macros

  20. 20

    scala macros generating implicits

  21. 21

    Can this be done with Scala macros?

  22. 22

    "debugging" scala annotation macros

  23. 23

    Debug Scala Macros with Intellij

  24. 24

    Accessing consecutive members with a single pointer

  25. 25

    java nashorn accessing superclass members

  26. 26

    Accessing widgets which are members of a GridLayout

  27. 27

    object members and accessing them in JS

  28. 28

    CRTP -- accessing incomplete type members

  29. 29

    Swift: Accessing members of tuples in Array

HotTag

Archive