aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/scala/generic.scala
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/scala/generic.scala')
-rw-r--r--core/src/main/scala/generic.scala67
1 files changed, 36 insertions, 31 deletions
diff --git a/core/src/main/scala/generic.scala b/core/src/main/scala/generic.scala
index 86b4d24..ffb2c14 100644
--- a/core/src/main/scala/generic.scala
+++ b/core/src/main/scala/generic.scala
@@ -17,7 +17,7 @@ object GlobalMutableState {
private[magnolia] var state: Map[Pos, ListMap[c.universe.Type forSome { val c: whitebox.Context }, c.universe.TermName forSome { val c: whitebox.Context }]] = Map()
private[magnolia] def push(c: whitebox.Context)(key: c.universe.Type, value: c.universe.TermName): Unit = {
- println(s"push($key)")
+ println(s"push($key, $value)")
state = state.updated(Pos(c.enclosingPosition), state.get(Pos(c.enclosingPosition)).map { m =>
m.updated(key, value)
}.getOrElse(ListMap(key -> value)))
@@ -30,11 +30,12 @@ object GlobalMutableState {
println("state = "+state)
}
- private[magnolia] def has(c: whitebox.Context)(key: c.universe.Type): Option[c.universe.TermName] =
+ private[magnolia] def has(c: whitebox.Context)(key: c.universe.Type): Option[c.universe.TermName] = {
try state(Pos(c.enclosingPosition)).get(key).asInstanceOf[Option[c.universe.TermName]] catch {
case e: Exception =>
???
}
+ }
private[magnolia] var searchType: AnyRef = null
}
@@ -70,26 +71,34 @@ abstract class GenericMacro(whiteboxContext: whitebox.Context) {
def getImplicit(genericType: c.universe.Type,
typeConstructor: c.universe.Type,
- myName: c.universe.TermName,
- count: Int): c.Tree = {
+ myName: c.universe.TermName): c.Tree = {
import c.universe._
- println(s"getImplicit1($genericType, $count)")
+ //println(s"getImplicit1($genericType)")
val x = GlobalMutableState.has(c)(genericType)
- x.foreach { y => println("y = "+y) }
val result = x.map { nm =>
q"$nm"
}.orElse {
val searchType = appliedType(typeConstructor, genericType)
if(GlobalMutableState.has(c)(genericType).isEmpty) {
GlobalMutableState.searchType = genericType
- val inferredImplicit = try Some(c.inferImplicitValue(searchType, false, false)) catch {
+ val inferredImplicit = try Some({
+ //println(s"ONE: $genericType -> $myName")
+ //GlobalMutableState.push(c)(genericType, myName)
+ val imp = c.inferImplicitValue(searchType, false, false)
+ //GlobalMutableState.pop(c)
+ q"""{
+ def $myName = $imp
+ $myName
+ }"""
+ }) catch {
case e: Exception => None
}
+
object transformer extends Transformer {
override def transform(tree: Tree): Tree = tree match {
case ta@TypeApply(Select(Literal(Constant(method: String)), TermName("asInstanceOf")), List(tpe)) =>
- println(s"Found typeapply: ${tpe}")
+ println(s"FOUND TYPEAPPLY: ${ta}")
val m = TermName(method)
q"$m"
case _ => super.transform(tree)
@@ -97,31 +106,29 @@ abstract class GenericMacro(whiteboxContext: whitebox.Context) {
}
inferredImplicit.map { imp =>
- c.resetLocalAttrs(imp)
- transformer.transform(imp)
- c.typecheck(imp)
+ val x = c.untypecheck(imp)
+ val z = c.untypecheck(transformer.transform(imp))
+ println("x: "+x+", z: "+z)
+ z
}.orElse {
- directInferImplicit(genericType, typeConstructor, count + 1)
+ directInferImplicit(genericType, typeConstructor)
}
} else {
- directInferImplicit(genericType, typeConstructor, count + 1)
+ directInferImplicit(genericType, typeConstructor)
}
}.getOrElse {
println("Really failed to find extractor for type "+genericType)
c.abort(c.enclosingPosition, "Could not find extractor for type "+genericType)
}
- //println(" = "+result)
-
result
}
def directInferImplicit(genericType: c.universe.Type,
- typeConstructor: c.universe.Type,
- count: Int): Option[c.Tree] = {
+ typeConstructor: c.universe.Type): Option[c.Tree] = {
import c.universe._
- println(s"directInferImplicit($genericType, $count)")
+ //println(s"directInferImplicit($genericType)")
val myName: TermName = TermName(c.freshName(genericType.typeSymbol.name.encodedName.toString.toLowerCase+"Extractor"))
val typeSymbol = genericType.typeSymbol
@@ -137,8 +144,9 @@ abstract class GenericMacro(whiteboxContext: whitebox.Context) {
case m: MethodSymbol if m.isCaseAccessor => m.asMethod
}.map { param =>
val returnType = param.returnType
+ println(s"TWO: $genericType -> $myName")
GlobalMutableState.push(c)(genericType, myName)
- val imp = getImplicit(returnType, typeConstructor, myName, count)
+ val imp = getImplicit(returnType, typeConstructor, myName)
GlobalMutableState.pop(c)
val dereferenced = dereferenceValue(c)(q"src", param.name.toString)
callDelegateMethod(c)(imp, dereferenced)
@@ -148,8 +156,9 @@ abstract class GenericMacro(whiteboxContext: whitebox.Context) {
} else if(isSealedTrait) {
val subtypes = classType.get.knownDirectSubclasses.to[List]
Some(subtypes.map(_.asType.toType).map { searchType =>
+ println(s"THREE: $genericType -> $myName")
GlobalMutableState.push(c)(genericType, myName)
- val res = getImplicit(searchType, typeConstructor, myName, count)
+ val res = getImplicit(searchType, typeConstructor, myName)
GlobalMutableState.pop(c)
res
}.reduce(coproductReduction(c))).map { imp =>
@@ -181,36 +190,32 @@ abstract class GenericMacro(whiteboxContext: whitebox.Context) {
def generic[T: c.WeakTypeTag, Tc: c.WeakTypeTag]: c.Tree = try {
import c.universe._
- println("Entering generic for type "+weakTypeOf[T])
+ //println("Entering generic for type "+weakTypeOf[T])
val genericType: Type = weakTypeOf[T]
val reentrant = genericType == GlobalMutableState.searchType
- println(s"LAST TYPE = ${GlobalMutableState.searchType}; THIS TYPE = $genericType")
+ //println(s"previous: ${GlobalMutableState.searchType}; THIS TYPE = $genericType")
val result: Option[c.Tree] = if(reentrant) {
- println("Reentrant.")
+ //println("Reentrant.")
throw ReentrantException()
} else if(GlobalMutableState.searchType != null) {
GlobalMutableState.has(c)(genericType) match {
case None =>
val typeConstructor: Type = weakTypeOf[Tc].typeConstructor
- directInferImplicit(genericType, typeConstructor, 0)
+ directInferImplicit(genericType, typeConstructor)
case Some(t) =>
val str = t.toString
val typeConstructor: Type = weakTypeOf[Tc].typeConstructor
val searchType = appliedType(typeConstructor, genericType)
+ println(s"$str ===>>> ${searchType}")
Some(q"$str.asInstanceOf[${searchType}]")
}
} else {
val typeConstructor: Type = weakTypeOf[Tc].typeConstructor
- directInferImplicit(genericType, typeConstructor, 0)
+ directInferImplicit(genericType, typeConstructor)
}
- println(result)
- try result.map { tree => c.typecheck(tree) } catch {
- case e: Exception =>
- println(result)
- println("Failed to typecheck because: "+e)
- }
+ println("Final result: "+result)
result.getOrElse {
println("FAIL.")