aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Pretty <jon.pretty@propensive.com>2017-11-05 11:43:55 +0100
committerJon Pretty <jon.pretty@propensive.com>2017-11-05 11:43:55 +0100
commit2a65718d3dd0a4921b90d2d6c1e35cc921d50a43 (patch)
tree2c3e2dea0677512cbdd2576ac44cea2f836b3c7d
parenta44c4a1ec9295e41f0de560808acd832191835e8 (diff)
downloadmagnolia-2a65718d3dd0a4921b90d2d6c1e35cc921d50a43.tar.gz
magnolia-2a65718d3dd0a4921b90d2d6c1e35cc921d50a43.tar.bz2
magnolia-2a65718d3dd0a4921b90d2d6c1e35cc921d50a43.zip
Codegen size improvements
-rw-r--r--core/src/main/scala/magnolia.scala63
1 files changed, 29 insertions, 34 deletions
diff --git a/core/src/main/scala/magnolia.scala b/core/src/main/scala/magnolia.scala
index b875e7e..1029d0c 100644
--- a/core/src/main/scala/magnolia.scala
+++ b/core/src/main/scala/magnolia.scala
@@ -6,25 +6,37 @@ import language.existentials
import language.higherKinds
import language.experimental.macros
-trait Subclass[Tc[_], T] {
+abstract class Subclass[Tc[_], T](label: String) {
type S <: T
def typeclass: Tc[S]
- def label: String
def cast: PartialFunction[T, S]
}
+object Param {
+ def apply[Tc[_], T, S1](name: String, tc: Tc[S1], deref: T => S1) = new Param[Tc, T] {
+ type S = S1
+ def label = name
+ def typeclass: Tc[S] = tc
+ def dereference(t: T): S = deref(t)
+ }
+}
+
trait Param[Tc[_], T] {
type S
- def typeclass: Tc[S]
def label: String
+ def typeclass: Tc[S]
def dereference(param: T): S
}
-trait JoinContext[Tc[_], T] {
- def construct[R](param: ((Param[Tc, T]) => Any)): T
- def typeName: String
- def parameters: List[Param[Tc, T]]
- def isObject: Boolean
+object JoinContext {
+ def apply[Tc[_], T](name: String, obj: Boolean, params: Array[Param[Tc, T]], constructor: (Param[Tc, T] => Any) => T) =
+ new JoinContext[Tc, T](name, obj, params) {
+ def construct(param: Param[Tc, T] => Any): T = constructor(param)
+ }
+}
+
+abstract class JoinContext[Tc[_], T](val typeName: String, val isObject: Boolean, val parameters: Array[Param[Tc, T]]) {
+ def construct(param: ((Param[Tc, T]) => Any)): T
}
object Magnolia {
@@ -117,12 +129,7 @@ object Magnolia {
val obj = termSym.asTerm
val className = obj.name.toString
val impl = q"""
- ${c.prefix}.join(new _root_.magnolia.JoinContext[$typeConstructor, $genericType] {
- def construct[R](fn: ((Param[${typeConstructor}, $genericType]) => Any)): $genericType = $obj
- def typeName: _root_.java.lang.String = $className
- def parameters: _root_.scala.List[Param[$typeConstructor, $genericType]] = _root_.scala.List()
- def isObject = true
- })
+ ${c.prefix}.join(_root_.magnolia.JoinContext[$typeConstructor, $genericType]($className, true, _root_.scala.Array(), $obj))
"""
Some(impl)
} else if(isCaseClass) {
@@ -146,27 +153,17 @@ object Magnolia {
}.to[List]
val callables = typeclasses.map { case (param, typeclass, paramType) =>
- q"""new _root_.magnolia.Param[$typeConstructor, ${genericType}] {
- type S = ${paramType}
- def typeclass: ${appliedType(typeConstructor, paramType)} = $typeclass
- def label: _root_.java.lang.String = ${param.name.toString}
- def dereference(param: ${genericType}): ${paramType} =
- param.${TermName(param.name.toString)}
- }"""
+ q"""_root_.magnolia.Param[$typeConstructor, $genericType, $paramType](${param.name.toString}, $typeclass, p => p.${TermName(param.name.toString)})"""
}
Some {
q"""
- ${c.prefix}.join(new _root_.magnolia.JoinContext[$typeConstructor, $genericType] {
- def construct[R](fn: ((Param[${typeConstructor}, $genericType]) => Any)): $genericType =
- new $genericType(..${typeclasses.zipWithIndex.map { case (typeclass, idx) =>
- q"fn(parameters($idx)).asInstanceOf[${typeclass._3}]"
- } })
- def typeName: _root_.java.lang.String = $className
- def parameters: _root_.scala.List[Param[$typeConstructor, $genericType]] =
- _root_.scala.List(..$callables)
- def isObject = false
- })
+ val parameters: _root_.scala.Array[Param[$typeConstructor, $genericType]] = _root_.scala.Array(..$callables)
+ ${c.prefix}.join(_root_.magnolia.JoinContext[$typeConstructor, $genericType]($className, false, parameters,
+ (fn: (Param[$typeConstructor, $genericType] => Any)) => new $genericType(..${typeclasses.zipWithIndex.map { case (typeclass, idx) =>
+ q"fn(parameters($idx)).asInstanceOf[${typeclass._3}]"
+ } })
+ ))
"""
}
} else if(isSealedTrait) {
@@ -193,15 +190,13 @@ object Magnolia {
c.abort(c.enclosingPosition, s"failed to get implicit for type $searchType")
}
}.map { case (typ, typeclass) =>
- val caseClause = cq"(t: $typ) => t"
val pf = q"""new _root_.scala.PartialFunction[$genericType, $typ] {
def isDefinedAt(t: $genericType): Boolean = t.isInstanceOf[$typ]
def apply(t: $genericType): $typ = t.asInstanceOf[$typ]
}"""
- q"""new _root_.magnolia.Subclass[$typeConstructor, $genericType] {
+ q"""new _root_.magnolia.Subclass[$typeConstructor, $genericType](${typ.typeSymbol.name.toString}) {
type S = $typ
- def label: _root_.java.lang.String = ${typ.typeSymbol.name.toString}
def typeclass: ${appliedType(typeConstructor, typ)} = $typeclass
def cast: _root_.scala.PartialFunction[$genericType, $typ] = $pf
}"""