Skip to content

Commit 18d8cb6

Browse files
committed
All done except implicit search for Coder[F].
1 parent a7bde0e commit 18d8cb6

File tree

5 files changed

+254
-198
lines changed

5 files changed

+254
-198
lines changed

scala-macros-usage/src/main/scala/com/github/fpopic/scalamacros/DefMacroCoderUsage.scala

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
package com.github.fpopic.scalamacros
22

3-
import org.apache.beam.sdk.coders.Coder
4-
5-
import java.io.{ByteArrayInputStream, ByteArrayOutputStream}
6-
7-
case class Pojo(i: Int, s: Option[Int], l: List[Int])
3+
import com.github.fpopic.scalamacros.beam.DefMacroCoder
84

95
object DefMacroCoderUsage {
106

7+
import org.apache.beam.sdk.coders.Coder
8+
import java.io.{ByteArrayInputStream, ByteArrayOutputStream}
9+
1110
def main(args: Array[String]): Unit = {
1211

1312
import com.github.fpopic.scalamacros.beam.DefMacroCoder._
13+
import com.github.fpopic.scalamacros.beam.DefMacroCoder.{stringCoder, intCoder, listCoder}
14+
case class Pojo(s: String, i: Int, l: List[Int])
15+
// TODO try with nested class
1416

15-
val coder: Coder[Pojo] = implicitly
17+
val coder: Coder[Pojo] = DefMacroCoder.of[Pojo]
1618

17-
val pojo = Pojo(1, Some(2), List(3, 4))
19+
val pojo = Pojo("4", 1, List(2, 3))
1820

1921
val encoded = {
2022
val os = new ByteArrayOutputStream()
Lines changed: 53 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,53 @@
1-
package com.github.fpopic.scalamacros
2-
3-
import scala.annotation.{StaticAnnotation, compileTimeOnly}
4-
import scala.reflect.api.Trees
5-
import scala.reflect.macros.blackbox
6-
7-
// Quasiquotes Syntax:
8-
// https://docs.scala-lang.org/overviews/quasiquotes/syntax-summary.html
9-
10-
// 1. Provide macro impl.
11-
object Macros {
12-
13-
// annottees -> all thing where we put @identity
14-
def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
15-
import c.universe._
16-
val helper = new MacrosHelper[c.type](c)
17-
18-
println("\nAnnotationMacro:")
19-
20-
// To extract annotation parameter
21-
val i: Int = c.prefix.tree match {
22-
case q @ q"new identity(i=$i)" =>
23-
helper.evalTree[Int](i)
24-
case _ => 0
25-
}
26-
27-
println(s"Parameter i:$i")
28-
29-
val inputs = annottees.toList
30-
31-
val (annottee, expandees) = inputs match {
32-
case (param: ValDef) :: (rest @ _ :: _) =>
33-
(param, rest)
34-
35-
case (param: TypeDef) :: (rest @ _ :: _) =>
36-
(param, rest)
37-
38-
case _ =>
39-
(EmptyTree, inputs)
40-
}
41-
42-
println("XX" + (annottee, expandees))
43-
44-
Block(expandees, Literal(Constant(())))
45-
}
46-
47-
}
48-
49-
// 0. Define anotation
50-
@compileTimeOnly("enable macro paradise to expand macro annotations")
51-
class identity(i: Int) extends StaticAnnotation {
52-
def macroTransform(annottees: Any*): Any = macro Macros.impl
53-
}
1+
//package com.github.fpopic.scalamacros
2+
//
3+
//import scala.annotation.{StaticAnnotation, compileTimeOnly}
4+
//import scala.reflect.api.Trees
5+
//import scala.reflect.macros.blackbox
6+
//
7+
//// Quasiquotes Syntax:
8+
//// https://docs.scala-lang.org/overviews/quasiquotes/syntax-summary.html
9+
//
10+
//// 1. Provide macro impl.
11+
//object Macros {
12+
//
13+
// // annottees -> all thing where we put @identity
14+
// def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
15+
// import c.universe._
16+
// val helper = new MacrosHelper[c.type](c)
17+
//
18+
// println("\nAnnotationMacro:")
19+
//
20+
// // To extract annotation parameter
21+
// val i: Int = c.prefix.tree match {
22+
// case q @ q"new identity(i=$i)" =>
23+
// helper.evalTree[Int](i)
24+
// case _ => 0
25+
// }
26+
//
27+
// println(s"Parameter i:$i")
28+
//
29+
// val inputs = annottees.toList
30+
//
31+
// val (annottee, expandees) = inputs match {
32+
// case (param: ValDef) :: (rest @ _ :: _) =>
33+
// (param, rest)
34+
//
35+
// case (param: TypeDef) :: (rest @ _ :: _) =>
36+
// (param, rest)
37+
//
38+
// case _ =>
39+
// (EmptyTree, inputs)
40+
// }
41+
//
42+
// println("XX" + (annottee, expandees))
43+
//
44+
// Block(expandees, Literal(Constant(())))
45+
// }
46+
//
47+
//}
48+
//
49+
//// 0. Define anotation
50+
//@compileTimeOnly("enable macro paradise to expand macro annotations")
51+
//class identity(i: Int) extends StaticAnnotation {
52+
// def macroTransform(annottees: Any*): Any = macro Macros.impl
53+
//}
Lines changed: 93 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,93 @@
1-
package com.github.fpopic.scalamacros
2-
3-
import scala.reflect.macros.blackbox
4-
5-
// 0. Define Type Class
6-
trait ToMap[T] {
7-
8-
def toMap(t: T): Map[String, Any]
9-
10-
}
11-
12-
object ToMap extends ToMapLowPriorityImplicits {
13-
// 2. Implicit method that triggers the macro
14-
15-
// HighPriorityImplicits
16-
// I can now only make implicits for whole case class but not for fields,
17-
// for them i need a new type class or in pattern matching in mapEntries code add cases
18-
19-
// LowPriorityMacros
20-
implicit def caseClassMappable[T]: ToMap[T] = macro materializeMappableImpl[T]
21-
22-
// 1. Caller initiates type class implicits resolution
23-
def mapify[T](t: T)(implicit m: ToMap[T]): Map[String, Any] = m.toMap(t)
24-
}
25-
26-
trait ToMapLowPriorityImplicits {
27-
28-
// 3. Macro that generates for any case class ToMap implementation
29-
def materializeMappableImpl[T: c.WeakTypeTag](c: blackbox.Context): c.Expr[ToMap[T]] = {
30-
import c.universe._
31-
val helper = new MacrosHelper[c.type](c)
32-
33-
val tpe = weakTypeOf[T]
34-
println(s"\nDefMacro: $tpe")
35-
36-
// For each constructor field genrate tree that repr. tuple ("name" -> value)
37-
val mapEntries: Seq[c.Tree] =
38-
helper.getPrimaryConstructorMembers(tpe).map { field =>
39-
val fName = field.name.decodedName.toString
40-
val fTerm = field.name.toTermName
41-
42-
field.annotations.foreach { a =>
43-
println("Annotations in def macro: " + a.tree.tpe.toString)
44-
a
45-
}
46-
47-
// doesn't work with tType.decl(field.name).typeSignature
48-
val fType = field.typeSignature
49-
fType match {
50-
case t if t =:= weakTypeOf[Int] =>
51-
println(s"$fName : $fType")
52-
q"$fName -> (t.$fTerm + 100)"
53-
case t if t =:= weakTypeOf[Some[Int]] =>
54-
println(s"$fName : $fType")
55-
q"$fName -> t.$fTerm.get"
56-
case t if t <:< weakTypeOf[Option[_]] =>
57-
// FIXME
58-
q"""if ($fTerm.isDefined)
59-
$fName -> $fTerm.get
60-
else ""
61-
"""
62-
case t if t =:= weakTypeOf[List[Int]] =>
63-
println(s"$fName : $fType")
64-
q"$fName -> t.$fTerm"
65-
// in case field is nested case class
66-
case n if n.baseClasses.contains(weakTypeOf[Product].typeSymbol) =>
67-
println(s"$fName : $fType")
68-
q"$fName -> mapify(t.$fTerm)"
69-
case t =>
70-
try {
71-
// default ones
72-
} catch {
73-
case _: Exception => c.abort(c.enclosingPosition, s"Type $t is not supported.")
74-
}
75-
q""
76-
}
77-
}
78-
79-
val ret =
80-
q"""new ToMap[$tpe] {
81-
def toMap(t: $tpe): Map[String, Any] = Map(..$mapEntries)
82-
}
83-
"""
84-
85-
println(s"Ret: $ret")
86-
87-
c.Expr[ToMap[T]](ret)
88-
}
89-
90-
}
91-
92-
// check byte code
93-
// javap -c scala-macros-usage/target/scala-2.13.0-M3/classes/com/github/fpopic/scalamacros/A\$.class
1+
//package com.github.fpopic.scalamacros
2+
//
3+
//import scala.reflect.macros.blackbox
4+
//
5+
//// 0. Define Type Class
6+
//trait ToMap[T] {
7+
//
8+
// def toMap(t: T): Map[String, Any]
9+
//
10+
//}
11+
//
12+
//object ToMap extends ToMapLowPriorityImplicits {
13+
// // 2. Implicit method that triggers the macro
14+
//
15+
// // HighPriorityImplicits
16+
// // I can now only make implicits for whole case class but not for fields,
17+
// // for them i need a new type class or in pattern matching in mapEntries code add cases
18+
//
19+
// // LowPriorityMacros
20+
// implicit def caseClassMappable[T]: ToMap[T] = macro materializeMappableImpl[T]
21+
//
22+
// // 1. Caller initiates type class implicits resolution
23+
// def mapify[T](t: T)(implicit m: ToMap[T]): Map[String, Any] = m.toMap(t)
24+
//}
25+
//
26+
//trait ToMapLowPriorityImplicits {
27+
//
28+
// // 3. Macro that generates for any case class ToMap implementation
29+
// def materializeMappableImpl[T: c.WeakTypeTag](c: blackbox.Context): c.Expr[ToMap[T]] = {
30+
// import c.universe._
31+
// val helper = new MacrosHelper[c.type](c)
32+
//
33+
// val tpe = weakTypeOf[T]
34+
// println(s"\nDefMacro: $tpe")
35+
//
36+
// // For each constructor field genrate tree that repr. tuple ("name" -> value)
37+
// val mapEntries: Seq[c.Tree] =
38+
// helper.getPrimaryConstructorMembers(tpe).map { field =>
39+
// val fName = field.name.decodedName.toString
40+
// val fTerm = field.name.toTermName
41+
//
42+
// field.annotations.foreach { a =>
43+
// println("Annotations in def macro: " + a.tree.tpe.toString)
44+
// a
45+
// }
46+
//
47+
// // doesn't work with tType.decl(field.name).typeSignature
48+
// val fType = field.typeSignature
49+
// fType match {
50+
// case t if t =:= weakTypeOf[Int] =>
51+
// println(s"$fName : $fType")
52+
// q"$fName -> (t.$fTerm + 100)"
53+
// case t if t =:= weakTypeOf[Some[Int]] =>
54+
// println(s"$fName : $fType")
55+
// q"$fName -> t.$fTerm.get"
56+
// case t if t <:< weakTypeOf[Option[_]] =>
57+
// // FIXME
58+
// q"""if ($fTerm.isDefined)
59+
// $fName -> $fTerm.get
60+
// else ""
61+
// """
62+
// case t if t =:= weakTypeOf[List[Int]] =>
63+
// println(s"$fName : $fType")
64+
// q"$fName -> t.$fTerm"
65+
// // in case field is nested case class
66+
// case n if n.baseClasses.contains(weakTypeOf[Product].typeSymbol) =>
67+
// println(s"$fName : $fType")
68+
// q"$fName -> mapify(t.$fTerm)"
69+
// case t =>
70+
// try {
71+
// // default ones
72+
// } catch {
73+
// case _: Exception => c.abort(c.enclosingPosition, s"Type $t is not supported.")
74+
// }
75+
// q""
76+
// }
77+
// }
78+
//
79+
// val ret =
80+
// q"""new ToMap[$tpe] {
81+
// def toMap(t: $tpe): Map[String, Any] = Map(..$mapEntries)
82+
// }
83+
// """
84+
//
85+
// println(s"Ret: $ret")
86+
//
87+
// c.Expr[ToMap[T]](ret)
88+
// }
89+
//
90+
//}
91+
//
92+
//// check byte code
93+
//// javap -c scala-macros-usage/target/scala-2.13.0-M3/classes/com/github/fpopic/scalamacros/A\$.class

0 commit comments

Comments
 (0)