Quantcast

macros

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

macros

marcos rebelo
Hy all,

I'm willing to transform my case classes to a Squema at compile time.

Basically I need to get a Tree.

The case classes that I want to generate

====================================
package common

import scala.language.implicitConversions
import scala.language.higherKinds
import scala.language.experimental.macros

sealed trait SQLSchema[T]
case class RawSQLSchema[T](typ: String) extends SQLSchema[T]
case class RecordSQLSchema[T](subfields: List[(String, SQLSchema[_])]) extends SQLSchema[T]

object SQLSchema {
  def toSQLSchema[A]: SQLSchema[A] = macro SQLSchemaImpl.toSQLSchemaImpl[A]

  def implictFor[A](implicit sqlSchema: SQLSchema[A]): SQLSchema[A] = sqlSchema

  implicit object SQLSchemaInt extends RawSQLSchema[Int]("INTEGER")
  implicit object SQLSchemaString extends RawSQLSchema[String]("STRING")
}

====================================

I would like to do code like:

====================================

object Sub {
    implicit val sqlSchema: SQLSchema[Sub] = SQLSchema.toSQLSchema[Sub]
}
case class Sub(i:Int, s:String)

====================================

with
Sub.sqlSchema == RecordSQLSchema[Sub](List(
   "i" -> SQLSchema.SQLSchemaInt,
   "s" -> SQLSchema.SQLSchemaString,
))


Lets look the ugly part. If I try to generate a RawSQLSchema I can do:

====================================
object SQLSchemaImpl {
  def toSQLSchemaImplRaw[A: c.WeakTypeTag](c: blackbox.Context): c.Expr[SQLSchema[A]] = {
    import c.universe._

    val typeSymbol = weakTypeOf[A].typeSymbol

    val value = "not what I want"
    val codeRaw = q"RawSQLSchema[$typeSymbol]($value)"

    c.Expr[SQLSchema[A]](codeRaw)
  }
   ...
}

====================================

But this is not what I need. I would need the following code to work

====================================
object SQLSchemaImpl {
  def toSQLSchemaImplComplex[A: c.WeakTypeTag](c: blackbox.Context): c.Expr[SQLSchema[A]] = {
    import c.universe._

    val typeSymbol = weakTypeOf[A].typeSymbol

    val parts = for {
      member <- typeSymbol.typeSignature.members.toList
      if member.isTerm
      term = member.asTerm
      if term.isCaseAccessor
      if term.isGetter
      name = term.name.toString
      typeName = term.typeSignature.typeSymbol.fullName
    } yield q""" Tuple2($name, SQLSchema.implictFor[$typeName]) :: l"""

    val code1 = q"RecordSQLSchema[${weakTypeOf[A].typeSymbol}]($parts)"
    println(s" >>>>> code1: $code1")

//    val code2 = q"RecordSQLSchema[${weakTypeOf[A].typeSymbol}](...${List(parts)})"
//    println(s" >>>>> code2: $code2")

//    val code3 = q"RecordSQLSchema[${weakTypeOf[A].typeSymbol}](List.apply(...$parts))"
//    println(s" >>>>> code3: $code3")

//    val listApply = typeOf[List[SQLSchema[_]]].member(TermName("apply"))
//    val code4 = q"RecordSQLSchema[${weakTypeOf[A].typeSymbol}]($listApply ...$parts)"
//    println(s" >>>>> code4: $code4")

    c.Expr[SQLSchema[A]](code1)
  }
}
====================================

Whatever I tried failed :(

How can I build that List on the RecordSQLSchema?

Thanks for any help

Best Regards
Marcos

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: macros

Rafał Krzewski
Have you considered using Shapeless for that? It will do all the dirty macro work for you while you can concentrate on the interesting bits.
Here's an excellent short book that describes how to use Shapeless to do automatic typeclass derivation for your own types, which is exactly what you want, if I understood your use case correctly :)
https://github.com/underscoreio/shapeless-guide 

Cheers,
Rafał

W dniu sobota, 22 kwietnia 2017 20:25:10 UTC+2 użytkownik marcos rebelo napisał:
Hy all,

I'm willing to transform my case classes to a Squema at compile time.

Basically I need to get a Tree.

The case classes that I want to generate

====================================
package common

import scala.language.implicitConversions
import scala.language.higherKinds
import scala.language.experimental.macros

sealed trait SQLSchema[T]
case class RawSQLSchema[T](typ: String) extends SQLSchema[T]
case class RecordSQLSchema[T](subfields: List[(String, SQLSchema[_])]) extends SQLSchema[T]

object SQLSchema {
  def toSQLSchema[A]: SQLSchema[A] = macro SQLSchemaImpl.toSQLSchemaImpl[A]

  def implictFor[A](implicit sqlSchema: SQLSchema[A]): SQLSchema[A] = sqlSchema

  implicit object SQLSchemaInt extends RawSQLSchema[Int]("INTEGER")
  implicit object SQLSchemaString extends RawSQLSchema[String]("STRING")
}

====================================

I would like to do code like:

====================================

object Sub {
    implicit val sqlSchema: SQLSchema[Sub] = SQLSchema.toSQLSchema[Sub]
}
case class Sub(i:Int, s:String)

====================================

with
Sub.sqlSchema == RecordSQLSchema[Sub](List(
   "i" -> SQLSchema.SQLSchemaInt,
   "s" -> SQLSchema.SQLSchemaString,
))


Lets look the ugly part. If I try to generate a RawSQLSchema I can do:

====================================
object SQLSchemaImpl {
  def toSQLSchemaImplRaw[A: c.WeakTypeTag](c: blackbox.Context): c.Expr[SQLSchema[A]] = {
    import c.universe._

    val typeSymbol = weakTypeOf[A].typeSymbol

    val value = "not what I want"
    val codeRaw = q"RawSQLSchema[$typeSymbol]($value)"

    c.Expr[SQLSchema[A]](codeRaw)
  }
   ...
}

====================================

But this is not what I need. I would need the following code to work

====================================
object SQLSchemaImpl {
  def toSQLSchemaImplComplex[A: c.WeakTypeTag](c: blackbox.Context): c.Expr[SQLSchema[A]] = {
    import c.universe._

    val typeSymbol = weakTypeOf[A].typeSymbol

    val parts = for {
      member <- typeSymbol.typeSignature.members.toList
      if member.isTerm
      term = member.asTerm
      if term.isCaseAccessor
      if term.isGetter
      name = term.name.toString
      typeName = term.typeSignature.typeSymbol.fullName
    } yield q""" Tuple2($name, SQLSchema.implictFor[$typeName]) :: l"""

    val code1 = q"RecordSQLSchema[${weakTypeOf[A].typeSymbol}]($parts)"
    println(s" >>>>> code1: $code1")

//    val code2 = q"RecordSQLSchema[${weakTypeOf[A].typeSymbol}](...${List(parts)})"
//    println(s" >>>>> code2: $code2")

//    val code3 = q"RecordSQLSchema[${weakTypeOf[A].typeSymbol}](List.apply(...$parts))"
//    println(s" >>>>> code3: $code3")

//    val listApply = typeOf[List[SQLSchema[_]]].member(TermName("apply"))
//    val code4 = q"RecordSQLSchema[${weakTypeOf[A].typeSymbol}]($listApply ...$parts)"
//    println(s" >>>>> code4: $code4")

    c.Expr[SQLSchema[A]](code1)
  }
}
====================================

Whatever I tried failed :(

How can I build that List on the RecordSQLSchema?

Thanks for any help

Best Regards
Marcos

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Loading...