diff --git a/modules/core/src/main/scala/iota/TList.scala b/modules/core/src/main/scala/iota/TList.scala index 6edd792..9f0e225 100644 --- a/modules/core/src/main/scala/iota/TList.scala +++ b/modules/core/src/main/scala/iota/TList.scala @@ -60,4 +60,17 @@ object TList { macro internal.TypeListMacros.materializeTListCompute[L, O] } + trait Gen[A] { + type Repr <: TList + } + + object Gen { + type Aux[A, R <: TList] = Gen[A] { type Repr = R } + + def apply[A](implicit ev: Gen[A]): Gen.Aux[A, ev.Repr] = ev + implicit def materializeGen[A, R <: TList]: Aux[A, R] = + macro internal.TypeListMacros.materializeTListGen[A, R] + } + + } diff --git a/modules/core/src/main/scala/iota/gen/package.scala b/modules/core/src/main/scala/iota/gen/package.scala new file mode 100644 index 0000000..bea1a1d --- /dev/null +++ b/modules/core/src/main/scala/iota/gen/package.scala @@ -0,0 +1,13 @@ +package iota + +package object gen { + + type Index[I <: SingletonInt] + type Name[N <: SingletonString] + + type Meta[ + I <: SingletonInt, + N <: SingletonString + ] = Index[I] with Name[N] + +} diff --git a/modules/core/src/main/scala/iota/internal/TypeListMacros.scala b/modules/core/src/main/scala/iota/internal/TypeListMacros.scala index 93d8714..ea804f5 100644 --- a/modules/core/src/main/scala/iota/internal/TypeListMacros.scala +++ b/modules/core/src/main/scala/iota/internal/TypeListMacros.scala @@ -17,7 +17,7 @@ package iota package internal -import scala.reflect.macros.blackbox.Context +import scala.reflect.macros.whitebox.Context private[iota] final class TypeListMacros(val c: Context) { import c.universe._ @@ -86,4 +86,41 @@ private[iota] final class TypeListMacros(val c: Context) { q"new _root_.iota.KList.Compute[$L]{ override type Out = $tpe }", true) } + def materializeTListGen[A, R <: TList]( + implicit + evA: c.WeakTypeTag[A] + ): c.Expr[TList.Gen.Aux[A, R]] = { + + val A = evA.tpe + + val aSym = A.typeSymbol + + def fieldType(symbol: MethodSymbol): Type = + internal.refinedType(List( + symbol.returnType, + appliedType( + weakTypeOf[iota.gen.Meta[_, _]], List( + internal.constantType(Constant(0)), + internal.constantType(Constant(symbol.name.encodedName.toString)))) + ), NoSymbol) + + val tpe = if (aSym.isClass) { + val aClassSym = aSym.asClass + if (aClassSym.isCaseClass) { + val accessors = A.decls + .collect { case m: MethodSymbol if m.isCaseAccessor => m.asMethod } + .toList + tb.buildTList(accessors.map(fieldType)) + } else if (aClassSym.isSealed) { + NoType + } else { + NoType + } + } else + NoType + + tb.foldAbort(Right( + q"new _root_.iota.TList.Gen[$A] { override type Repr = $tpe }")) + } + } diff --git a/modules/core/src/main/scala/iota/package.scala b/modules/core/src/main/scala/iota/package.scala index 8368eb9..56c91a5 100644 --- a/modules/core/src/main/scala/iota/package.scala +++ b/modules/core/src/main/scala/iota/package.scala @@ -74,4 +74,5 @@ package object iota { //#-2.11 private[iota] type SingletonInt = Int with Singleton + private[iota] type SingletonString = String with Singleton } diff --git a/modules/examples/src/main/scala/iotaexamples/foo.scala b/modules/examples/src/main/scala/iotaexamples/foo.scala new file mode 100644 index 0000000..dae471c --- /dev/null +++ b/modules/examples/src/main/scala/iotaexamples/foo.scala @@ -0,0 +1,35 @@ +/* + * Copyright 2016-2017 47 Degrees, LLC. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package iotaexamples + +import iota._ + +import debug.options.ShowTrees + +object Foo extends App { + + case class Dummy( + a: String, + b: Double, + c: Long) + + val gen = TList.Gen[Dummy] + + scala.Predef.println(gen) + + +}