aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/src/main/scala/magnolia.scala40
-rw-r--r--examples/src/main/scala/example.scala6
2 files changed, 15 insertions, 31 deletions
diff --git a/core/src/main/scala/magnolia.scala b/core/src/main/scala/magnolia.scala
index 7b05bbf..9aafb44 100644
--- a/core/src/main/scala/magnolia.scala
+++ b/core/src/main/scala/magnolia.scala
@@ -6,17 +6,11 @@ import scala.util.Try
import language.existentials
import language.higherKinds
-abstract class Transformation[C <: whitebox.Context](val c: C) {
- def typeclassBody(genericType: c.Type, implementation: c.Tree): c.Tree
- def coproductReduction(left: c.Tree, right: c.Tree): c.Tree
-}
-
-abstract class MagnoliaMacro(val c: whitebox.Context) {
+@bundle
+class Macros(val c: whitebox.Context) {
import c.universe._
import CompileTimeState._
- protected def transformation(c: whitebox.Context): Transformation[c.type]
-
private def findType(key: c.universe.Type): Option[c.TermName] =
recursionStack(c.enclosingPosition).frames.find(_.genericType == key).map(_.termName(c))
@@ -108,11 +102,9 @@ abstract class MagnoliaMacro(val c: whitebox.Context) {
c.abort(c.enclosingPosition, s"failed to get implicit for type $genericType")
}
- val dereferencedValue = q"$dereferencerImplicit.dereference(src, ${param.name.toString})"
+ val dereferencedValue = q"$dereferencerImplicit.dereference(sourceParameter, ${param.name.toString})"
- val result = q"$dereferencerImplicit.delegate($derivedImplicit, $dereferencedValue)"
- println(result+"\n\n")
- result
+ q"$dereferencerImplicit.delegate($derivedImplicit, $dereferencedValue)"
}
Some(q"new $genericType(..$implicits)")
@@ -127,17 +119,15 @@ abstract class MagnoliaMacro(val c: whitebox.Context) {
}.getOrElse {
c.abort(c.enclosingPosition, s"failed to get implicit for type $searchType")
}
- }.reduce(transformation(c).coproductReduction)
+ }.reduce { (left, right) => q"$dereferencerImplicit.combine($left, $right)" }
- q"$dereferencerImplicit.delegate($reduction, src)"
+ q"$dereferencerImplicit.delegate($reduction, sourceParameter)"
}
} else None
construct.map { const =>
- val bodyImplementation = transformation(c).typeclassBody(genericType, const)
-
q"""{
- def $assignedName: $resultType = new $resultType { $bodyImplementation }
+ def $assignedName: $resultType = $dereferencerImplicit.construct { sourceParameter => $const }
$assignedName
}"""
}
@@ -220,22 +210,10 @@ private[magnolia] object CompileTimeState {
Map()
}
-
-@bundle
-class Macros(val context: whitebox.Context) extends MagnoliaMacro(context) {
- protected def transformation(c: whitebox.Context): Transformation[c.type] =
- new Transformation[c.type](c) {
- import c.universe._
-
- def typeclassBody(genericType: c.Type, implementation: c.Tree): c.Tree =
- q"""def extract(src: _root_.magnolia.Thing): $genericType = $implementation"""
-
- def coproductReduction(left: c.Tree, right: c.Tree): c.Tree = q"$left.orElse($right)"
- }
-}
-
trait Dereferencer[Typeclass[_]] {
type Value
def dereference(value: Value, param: String): Value
def delegate[T](typeclass: Typeclass[T], value: Value): T
+ def combine[Supertype, Right <: Supertype](left: Typeclass[_ <: Supertype], right: Typeclass[Right]): Typeclass[Supertype]
+ def construct[T](body: Value => T): Typeclass[T]
}
diff --git a/examples/src/main/scala/example.scala b/examples/src/main/scala/example.scala
index 6a6a1cc..e61f8bd 100644
--- a/examples/src/main/scala/example.scala
+++ b/examples/src/main/scala/example.scala
@@ -34,6 +34,12 @@ object Extractor extends Extractor_1 {
type Value = Thing
def dereference(value: Thing, param: String): Thing = value.access(param)
def delegate[T](extractor: Extractor[T], value: Thing): T = extractor.extract(value)
+ def combine[Supertype, Right <: Supertype](left: Extractor[_ <: Supertype],
+ right: Extractor[Right]): Extractor[Supertype] = left.orElse(right)
+
+ def construct[T](body: Thing => T): Extractor[T] = new Extractor[T] {
+ def extract(source: Thing): T = body(source)
+ }
}
}