From 2fb5b569d30ac09cfda7ce6450c54d0fff6f32ae Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Sun, 5 Nov 2017 06:24:14 -0800 Subject: Re-organize `forge/` folder according to ordering of build phases: target definition, target discovery, and target evaluation --- .../src/main/scala/forge/discover/Discovered.scala | 62 ++++++++++++++++++++++ core/src/main/scala/forge/discover/Labelled.scala | 8 +++ 2 files changed, 70 insertions(+) create mode 100644 core/src/main/scala/forge/discover/Discovered.scala create mode 100644 core/src/main/scala/forge/discover/Labelled.scala (limited to 'core/src/main/scala/forge/discover') diff --git a/core/src/main/scala/forge/discover/Discovered.scala b/core/src/main/scala/forge/discover/Discovered.scala new file mode 100644 index 00000000..964732be --- /dev/null +++ b/core/src/main/scala/forge/discover/Discovered.scala @@ -0,0 +1,62 @@ +package forge.discover + +import forge.define.Target + +import play.api.libs.json.Format + +import scala.language.experimental.macros +import scala.reflect.macros.blackbox.Context + +class Discovered[T](val value: Seq[(Seq[String], Format[_], T => Target[_])]){ + def apply(t: T) = value.map{case (a, f, b) => (a, f, b(t)) } + +} +object Discovered { + def makeTuple[T, V](path: Seq[String], func: T => Target[V])(implicit f: Format[V]) = { + (path, f, func) + } + + + def mapping[T: Discovered](t: T): Map[Target[_], Labelled[_]] = { + implicitly[Discovered[T]].apply(t) + .map(x => x._3 -> Labelled(x._3.asInstanceOf[Target[Any]], x._2.asInstanceOf[Format[Any]], x._1)) + .toMap + } + + implicit def apply[T]: Discovered[T] = macro applyImpl[T] + + def applyImpl[T: c.WeakTypeTag](c: Context): c.Expr[Discovered[T]] = { + import c.universe._ + val tpe = c.weakTypeTag[T].tpe + def rec(segments: List[String], t: c.Type): Seq[Seq[String]] = for { + m <- t.members.toSeq + if + (m.isTerm && (m.asTerm.isGetter || m.asTerm.isLazy)) || + m.isModule || + (m.isMethod && m.typeSignature.paramLists.isEmpty && m.typeSignature.resultType <:< c.weakTypeOf[Target[_]]) + + res <- { + val extendedSegments = m.name.toString :: segments + val self = + if (m.typeSignature.resultType <:< c.weakTypeOf[Target[_]]) Seq(extendedSegments) + else Nil + val children = rec(extendedSegments, m.typeSignature) + self ++ children + } + } yield res + + val reversedPaths = rec(Nil, tpe) + + val result = for(reversedPath <- reversedPaths.toList) yield { + val base = q"${TermName(c.freshName())}" + val segments = reversedPath.reverse.toList + val ident = segments.foldLeft[Tree](base)((prefix, name) => + q"$prefix.${TermName(name)}" + ) + + q"forge.discover.Discovered.makeTuple($segments, ($base: $tpe) => $ident)" + } + + c.Expr[Discovered[T]](q"new _root_.forge.discover.Discovered($result)") + } +} diff --git a/core/src/main/scala/forge/discover/Labelled.scala b/core/src/main/scala/forge/discover/Labelled.scala new file mode 100644 index 00000000..25c74e9f --- /dev/null +++ b/core/src/main/scala/forge/discover/Labelled.scala @@ -0,0 +1,8 @@ +package forge.discover + +import forge.define.Target +import play.api.libs.json.Format + +case class Labelled[T](target: Target[T], + format: Format[T], + segments: Seq[String]) -- cgit v1.2.3