aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Pretty <jon.pretty@propensive.com>2017-11-04 20:11:53 +0100
committerJon Pretty <jon.pretty@propensive.com>2017-11-04 20:11:53 +0100
commitfdd207e848e24fd6fb449a93e024f0405eab3299 (patch)
treeab4f419791f277d43ec834ff2f12bdcbfb42e67b
parent4d957fd5a35f1d7eed8643b22132b65696c80c8a (diff)
downloadmagnolia-fdd207e848e24fd6fb449a93e024f0405eab3299.tar.gz
magnolia-fdd207e848e24fd6fb449a93e024f0405eab3299.tar.bz2
magnolia-fdd207e848e24fd6fb449a93e024f0405eab3299.zip
Start of performance-enhancing refactoring
-rw-r--r--build.sbt3
-rw-r--r--core/src/main/scala/magnolia.scala34
-rw-r--r--examples/src/main/scala/typeclasses.scala24
-rw-r--r--tests/src/main/scala/adt.scala2
-rw-r--r--tests/src/main/scala/tests.scala4
5 files changed, 34 insertions, 33 deletions
diff --git a/build.sbt b/build.sbt
index 6ae8750..0b97238 100644
--- a/build.sbt
+++ b/build.sbt
@@ -9,6 +9,7 @@ lazy val core = crossProject(JSPlatform, JVMPlatform, NativePlatform)
.settings(buildSettings: _*)
.settings(publishSettings: _*)
.settings(scalaMacroDependencies: _*)
+ .settings(examplesDependencies)
.settings(moduleName := "magnolia")
.nativeSettings(nativeSettings)
@@ -149,7 +150,7 @@ lazy val scalaMacroDependencies: Seq[Setting[_]] = Seq(
lazy val examplesDependencies: Seq[Setting[_]] = Seq(
libraryDependencies += "org.typelevel" %% "cats-core" % "0.9.0",
- libraryDependencies += "com.propensive" %% "estrapade" % "1.0.0",
+ libraryDependencies += "com.propensive" %% "estrapade" % "1.0.2",
libraryDependencies += "com.propensive" %% "contextual-data" % "1.0.3"
)
diff --git a/core/src/main/scala/magnolia.scala b/core/src/main/scala/magnolia.scala
index 4d3d3d3..9d345ac 100644
--- a/core/src/main/scala/magnolia.scala
+++ b/core/src/main/scala/magnolia.scala
@@ -78,11 +78,7 @@ object Magnolia {
val genericTypeName: String = genericType.typeSymbol.name.encodedName.toString.toLowerCase
val assignedName: TermName = TermName(c.freshName(s"${genericTypeName}Typeclass"))
recurse(ChainedImplicit(genericType.toString), genericType, assignedName) {
- val inferredImplicit = c.inferImplicitValue(searchType, false, false)
- q"""{
- def $assignedName: $searchType = $inferredImplicit
- $assignedName
- }"""
+ c.inferImplicitValue(searchType, false, false)
}.get
}.toOption.orElse(directInferImplicit(genericType, typeConstructor))
}
@@ -116,7 +112,7 @@ object Magnolia {
val resultType = appliedType(typeConstructor, genericType)
// FIXME: Handle AnyVals
- if(isCaseObject) {
+ val result = if(isCaseObject) {
val termSym = genericType.typeSymbol.companionSymbol
val obj = termSym.asTerm
val className = obj.name.toString
@@ -128,11 +124,7 @@ object Magnolia {
def isObject = true
})
"""
-
- Some(q"""
- def $assignedName: $resultType = $impl
- $assignedName
- """)
+ Some(impl)
} else if(isCaseClass) {
val caseClassParameters = genericType.decls.collect {
case m: MethodSymbol if m.isCaseAccessor => m.asMethod
@@ -171,7 +163,7 @@ object Magnolia {
q"fn($call).asInstanceOf[${imp._3}]"
} })"""
- val impl = q"""
+ q"""
${c.prefix}.join(new _root_.magnolia.JoinContext[$typeConstructor, $genericType] {
def construct[R](fn: ((Param[${typeConstructor}, $genericType]) => Any)): $genericType = $constructor
def typeName: _root_.java.lang.String = $className
@@ -180,11 +172,6 @@ object Magnolia {
def isObject = false
})
"""
-
- q"""
- def $assignedName: $resultType = $impl
- $assignedName
- """
}
} else if(isSealedTrait) {
val genericSubtypes = classType.get.knownDirectSubclasses.to[List]
@@ -224,16 +211,19 @@ object Magnolia {
}"""
}
- val impl = q"""{
+ q"""{
${c.prefix}.split(_root_.scala.collection.immutable.List[_root_.magnolia.Subclass[$typeConstructor, $genericType]](..$subclasses))
}"""
- q"""
- def $assignedName: $resultType = $impl
- $assignedName
- """
}
} else None
+
+ result.map { r =>
+ q"""{
+ def $assignedName: $resultType = $r
+ $assignedName
+ }"""
+ }
}
val genericType: Type = weakTypeOf[T]
diff --git a/examples/src/main/scala/typeclasses.scala b/examples/src/main/scala/typeclasses.scala
index b4af6d0..c79a6d7 100644
--- a/examples/src/main/scala/typeclasses.scala
+++ b/examples/src/main/scala/typeclasses.scala
@@ -13,9 +13,11 @@ import scala.annotation.unchecked.uncheckedVariance
object Show {
type Typeclass[T] = Show[String, T]
- def join[T](context: JoinContext[Typeclass, T])(value: T): String = context.parameters.map { param =>
- s"${param.label}=${param.typeclass.show(param.dereference(value))}"
- }.mkString(s"${context.typeName.split("\\.").last}(", ",", ")")
+ def join[T](context: JoinContext[Typeclass, T]): Show[String, T] = new Show[String, T] {
+ def show(value: T) = context.parameters.map { param =>
+ s"${param.label}=${param.typeclass.show(param.dereference(value))}"
+ }.mkString(s"${context.typeName.split("\\.").last}(", ",", ")")
+ }
def split[T](subclasses: List[Subclass[Typeclass, T]])(value: T): String =
subclasses.map { sub => sub.cast.andThen { value =>
@@ -31,13 +33,17 @@ trait Show[Out, T] { def show(value: T): Out }
object Eq {
type Typeclass[T] = Eq[T]
- def join[T](context: JoinContext[Eq, T])(value1: T, value2: T): Boolean =
- context.parameters.forall { param => param.typeclass.equal(param.dereference(value1), param.dereference(value2)) }
+ def join[T](context: JoinContext[Eq, T]): Eq[T] = new Eq[T] {
+ def equal(value1: T, value2: T) =
+ context.parameters.forall { param => param.typeclass.equal(param.dereference(value1), param.dereference(value2)) }
+ }
- def split[T](subclasses: List[Subclass[Eq, T]])(value1: T, value2: T): Boolean =
- subclasses.map { case subclass =>
- subclass.cast.andThen { value => subclass.typeclass.equal(subclass.cast(value1), subclass.cast(value2)) }
- }.reduce(_ orElse _)(value1)
+ def split[T](subclasses: List[Subclass[Eq, T]]): Eq[T] = new Eq[T] {
+ def equal(value1: T, value2: T) =
+ subclasses.map { case subclass =>
+ subclass.cast.andThen { value => subclass.typeclass.equal(subclass.cast(value1), subclass.cast(value2)) }
+ }.reduce(_ orElse _)(value1)
+ }
implicit val string: Eq[String] = _ == _
implicit val int: Eq[Int] = _ == _
diff --git a/tests/src/main/scala/adt.scala b/tests/src/main/scala/adt.scala
index 75316aa..6d8a276 100644
--- a/tests/src/main/scala/adt.scala
+++ b/tests/src/main/scala/adt.scala
@@ -3,5 +3,5 @@ package adt
import magnolia._, examples._
object Gen {
- Eq.generic[Alphabet]
+ Show.generic[Alphabet]
}
diff --git a/tests/src/main/scala/tests.scala b/tests/src/main/scala/tests.scala
index 64d6594..f269643 100644
--- a/tests/src/main/scala/tests.scala
+++ b/tests/src/main/scala/tests.scala
@@ -13,6 +13,8 @@ object Tests extends TestApp {
def tests() = {
import examples._
+ compileTimeRestart()
+
test("construct a Show product instance") {
import examples._
Show.generic[Person].show(Person("John Smith", 34))
@@ -86,6 +88,8 @@ object Tests extends TestApp {
//test("construct a decoder") {
//Decoder.generic[Tree[String]].decode("string")
//}.assert(_ == (Leaf("something"): Tree[String]))
+
+ compileTimeReport()
}
}