diff --git a/build.sbt b/build.sbt index d3e3308..95cb7ba 100644 --- a/build.sbt +++ b/build.sbt @@ -3,7 +3,7 @@ import xerial.sbt.Sonatype._ lazy val commonSettings = Seq( scalaVersion := "2.12.12", organization := "io.github.dos65", - version := "0.0.35-SNAPSHOT", + version := "0.1.0-SNAPSHOT", crossScalaVersions := Seq("2.12.12", "2.13.3"), libraryDependencies ++= { if (is213(scalaVersion.value)) @@ -37,8 +37,6 @@ lazy val make = project.in(file("modules/core")) name := "make", scalacOptions ++= Seq( "-language:experimental.macros", - //"-Xprint:all", - //"-Ydebug" ), sourceGenerators in Compile += (sourceManaged in Compile).map(dir => Boilerplate.gen(dir)).taskValue, libraryDependencies ++= Seq( @@ -47,7 +45,6 @@ lazy val make = project.in(file("modules/core")) "org.typelevel" %% "cats-core" % "2.1.1", "com.chuusai" %% "shapeless" % "2.3.3" % "test", "org.typelevel" %% "cats-effect" % "2.1.3" % "test", - "com.lihaoyi" %% "pprint" % "0.5.6" ), ) diff --git a/modules/core/src/main/scala/make/Graph.scala b/modules/core/src/main/scala/make/Graph.scala index 2b683d7..f70032d 100644 --- a/modules/core/src/main/scala/make/Graph.scala +++ b/modules/core/src/main/scala/make/Graph.scala @@ -15,12 +15,9 @@ final class Graph[F[_], A]( targetId: Graph.Id )(implicit F: Monad[F]) { - def x: Map[Graph.Id, Graph.RawEntry[F]] = entries - def initEff: F[A] = { val order = initOrder val init = F.pure(Map.empty[Graph.Id, Any]) - println(s"Enries: ${entries.mkString("\n")}") val rs = order.foldLeft(init) { case (rs, id) => F.flatMap(rs)(depsMap => { @@ -83,30 +80,32 @@ object Graph { type HandleOut = (List[Any] => F[Any], List[Id], List[Make[F, Any]]) - def handleNode(v: Make[F, Any]): HandleOut = v match { - case Make.Value(v, tag) => - ((_: List[Any]) => v(), List.empty, List.empty) - case Make.Bind(prev, f, tag) => - val func = (in: List[Any]) => f(in(0)) - val deps = List(Id.fromTag(prev.tag)) - val other = List(prev) - (func, deps, other) - case Make.Ap(prev, op, tag) => - val func = - (in: List[Any]) => { - val a = in(0) - val aToB = in(1).asInstanceOf[Any => Any] - Applicative[F].pure[Any](aToB(a)) - } - val deps = List( - Id.fromTag(prev.tag), - Id.fromTag(op.tag) - ) - val other = List( - prev, - op.asInstanceOf[Make[F, Any]] - ) - (func, deps, other) + def handleNode(v: Make[F, Any]): HandleOut = { + v match { + case Make.Value(v, tag) => + ((_: List[Any]) => v(), List.empty, List.empty) + case x @ Make.Bind(prev, f, tag) => + val func = (in: List[Any]) => f(in(0)) + val deps = List(Id.fromTag(prev.tag)) + val other = List(prev) + (func, deps, other) + case Make.Ap(prev, op, tag) => + val func = + (in: List[Any]) => { + val a = in(0) + val aToB = in(1).asInstanceOf[Any => Any] + Applicative[F].pure[Any](aToB(a)) + } + val deps = List( + Id.fromTag(prev.tag), + Id.fromTag(op.tag) + ) + val other = List( + prev, + op.asInstanceOf[Make[F, Any]] + ) + (func, deps, other) + } } def handleMake(make: Make[F, Any]): (RawEntry[F], List[Make[F, Any]]) = { diff --git a/modules/core/src/main/scala/make/Make.scala b/modules/core/src/main/scala/make/Make.scala index 457dc4b..48ccbf5 100644 --- a/modules/core/src/main/scala/make/Make.scala +++ b/modules/core/src/main/scala/make/Make.scala @@ -13,7 +13,7 @@ sealed abstract class Make[F[_], A] { object Make extends ContraMakeInstances with MakeTupleInstances with LowPrioMake { - def of[F[_], A](implicit m: Dep[F, A]): Make[F, A] = m.value + def of[F[_], A](implicit m: Make[F, A]): Make[F, A] = m final private[make] case class Value[F[_], A]( v: () => F[A], @@ -57,4 +57,4 @@ trait ContraMakeInstances { trait LowPrioMake { implicit def debugInstance[F[_], A](implicit x: Debug[Make[F, A]]): Make[F, A] = x.v -} \ No newline at end of file +} diff --git a/modules/core/src/main/scala/make/internal/DepMacro.scala b/modules/core/src/main/scala/make/internal/DepMacro.scala index d609e54..7aafbda 100644 --- a/modules/core/src/main/scala/make/internal/DepMacro.scala +++ b/modules/core/src/main/scala/make/internal/DepMacro.scala @@ -36,7 +36,6 @@ class DepMacro(val c: whitebox.Context) { } if (root) { - //println(state.cache.mkString("\n")) c.internal.removeAttachment[State](c.macroApplication) val clsName = TypeName(c.freshName("Dep")) @@ -76,7 +75,6 @@ class DepMacro(val c: whitebox.Context) { } _root_.make.Dep.apply[${ftpe.tpe}, ${atpe.tpe}]((new $clsName).$primaryName) """ - //pprint.pprintln(tree, 100, Int.MaxValue) c.Expr[Dep[F, A]](tree) } else { out diff --git a/modules/core/src/main/scala/make/internal/MakeMacro.scala b/modules/core/src/main/scala/make/internal/MakeMacro.scala index fbe430f..b0e94ff 100644 --- a/modules/core/src/main/scala/make/internal/MakeMacro.scala +++ b/modules/core/src/main/scala/make/internal/MakeMacro.scala @@ -5,7 +5,7 @@ import make.Make import make.Debug import scala.collection.mutable -class MakeMacro(val ctx: whitebox.Context) extends DebugStateMacro(ctx){ +class MakeMacro(val ctx: whitebox.Context) extends DebugStateMacro(ctx) { import c.universe._ @@ -23,15 +23,11 @@ class MakeMacro(val ctx: whitebox.Context) extends DebugStateMacro(ctx){ out match { case EmptyTree => val st = extractInstanceSt(atpe.tpe, debugState.reverseTraces) - //println(s"ST: ${st}") val message = renderInstanceSt(st) c.abort(c.enclosingPosition, s"Make for ${atpe.tpe} not found\n" + message) case tree => val message = s"Debug: OK!\n\tMake instance for ${atpe.tpe} exists.\n\nRemove debug usage." c.info(c.enclosingPosition, message, true) - // println("---???? FROM DEBUG ---- ") - // println(tree.toString().size) - // println(tree.toString().grouped(300).mkString("\n\t")) c.Expr[Make[F, A]](tree) } } diff --git a/modules/core/src/test/scala/make/MakeTest.scala b/modules/core/src/test/scala/make/MakeTest.scala index 19e7753..4bb2391 100644 --- a/modules/core/src/test/scala/make/MakeTest.scala +++ b/modules/core/src/test/scala/make/MakeTest.scala @@ -16,155 +16,140 @@ import shapeless.test.illTyped class MakeTest extends FunSuite { - // test("annotated") { - // @autoMake - // class Anno(@anno.Sample a: Int) + test("annotated") { + @autoMake + class Anno(@anno.Sample a: Int) - // import make.annotated._ - // implicit val a = Make.pure[IO, Int :@: anno.Sample](42.annotated[anno.Sample]) - // Make.of[IO, Anno] - // } + import make.annotated._ + implicit val a = Make.pure[IO, Int :@: anno.Sample](42.annotated[anno.Sample]) + Make.of[IO, Anno] + } - // test("zero parameters autoMake") { - // @autoMake - // class ZeroArg { - // def hello: String = "hello" - // } - // val out = Make.of[IO, ZeroArg].make.unsafeRunSync.hello - // assertEquals(out, "hello") - // } + test("zero parameters autoMake") { + @autoMake + class ZeroArg { + def hello: String = "hello" + } + val out = Make.of[IO, ZeroArg].make.unsafeRunSync.hello + assertEquals(out, "hello") + } - // test("instantiate once") { + test("instantiate once") { - // case class Y[F[_]](value: String) - // case class Z[F[_]](value: String) + case class Y[F[_]](value: String) + case class Z[F[_]](value: String) - // case class X[G[_]](z: Z[G], y: Y[G]) - // case class W[F[_]](y: Y[F], x: X[F]) + case class X[G[_]](z: Z[G], y: Y[G]) + case class W[F[_]](y: Y[F], x: X[F]) - // @autoMake - // case class Foo(w: W[IO], z: Z[IO]) + @autoMake + case class Foo(w: W[IO], z: Z[IO]) - // val rnd = new Random() + val rnd = new Random() - // implicit def yMake[F[_]: Applicative: Tag.TCTag]: Make[F, Y[F]] = - // Make.pure(Y(rnd.nextString(20))) + implicit def yMake[F[_]: Applicative: Tag.TCTag]: Make[F, Y[F]] = + Make.pure(Y(rnd.nextString(20))) - // implicit def zMake[F[_]: Applicative: Tag.TCTag]: Make[F, Z[F]] = - // Make.pure(Z(rnd.nextString(20))) + implicit def zMake[F[_]: Applicative: Tag.TCTag]: Make[F, Z[F]] = + Make.pure(Z(rnd.nextString(20))) - // implicit def xMake[G[_]: Applicative: Tag.TCTag](implicit deps: Make[G, (Z[G], Y[G])]): Make[G, X[G]] = - // deps.mapN((z, y) => X(z, y)) + implicit def xMake[G[_]: Applicative: Tag.TCTag](implicit deps: Make[G, (Z[G], Y[G])]): Make[G, X[G]] = + deps.mapN((z, y) => X(z, y)) - // implicit def wMake[F[_]: Applicative: Tag.TCTag](implicit deps: Make[F, (Y[F], X[F])]): Make[F, W[F]] = - // deps.mapN((y, x) => W(y, x)) + implicit def wMake[F[_]: Applicative: Tag.TCTag](implicit deps: Make[F, (Y[F], X[F])]): Make[F, W[F]] = + deps.mapN((y, x) => W(y, x)) - // val resolve = Make.of[IO, (W[IO], X[IO], Foo)] + val resolve = Make.of[IO, (W[IO], X[IO], Foo)] - // val (w, x, foo) = resolve.make.unsafeRunSync() + val (w, x, foo) = resolve.make.unsafeRunSync() - // assert(w.x == x) - // assert(foo.w == w) - // assert(foo.z == w.x.z) - // } + assert(w.x == x) + assert(foo.w == w) + assert(foo.z == w.x.z) + } - // test("higher kind tags 1") { + test("higher kind tags 1") { - // case class A[F[_]](value: F[String]) - // case class C[F[_]](a: A[F]) - // case class D[F[_], G[_]](b: C[F], c: C[G]) + case class A[F[_]](value: F[String]) + case class C[F[_]](a: A[F]) + case class D[F[_], G[_]](b: C[F], c: C[G]) - // implicit def aMake[F[_]: Applicative, Z[_]: Applicative: Tag.TCTag]: Make[F, A[Z]] = Make.pure(A(Applicative[Z].pure("42"))) + implicit def aMake[F[_]: Applicative, Z[_]: Applicative: Tag.TCTag]: Make[F, A[Z]] = Make.pure(A(Applicative[Z].pure("42"))) - // implicit def cMake[F[_]: Applicative, G[_]: Applicative: Tag.TCTag]( - // implicit a: Make[F, A[G]] - // ): Make[F, C[G]] = - // a.map(a => C(a)) + implicit def cMake[F[_]: Applicative, G[_]: Applicative: Tag.TCTag]( + implicit a: Make[F, A[G]] + ): Make[F, C[G]] = + a.map(a => C(a)) - // implicit def dMake[F[_]: Applicative, G[_]: Applicative: Tag.TCTag, H[_]: Applicative: Tag.TCTag]( - // implicit deps: Make[F, (C[G], C[H])] - // ): Make[F, D[G, H]] = - // deps.mapN(D(_, _)) + implicit def dMake[F[_]: Applicative, G[_]: Applicative: Tag.TCTag, H[_]: Applicative: Tag.TCTag]( + implicit deps: Make[F, (C[G], C[H])] + ): Make[F, D[G, H]] = + deps.mapN(D(_, _)) - // import enableDebug._ + import enableDebug._ - // val resolved = Make.debugOf[IO, D[Option, IO]] - // val d = resolved.make.unsafeRunSync() - // assertEquals(d.b, C(A("42".some))) - // assertEquals(d.c.a.value.unsafeRunSync(), "42") - // } + val resolved = Make.debugOf[IO, D[Option, IO]] + val d = resolved.make.unsafeRunSync() + assertEquals(d.b, C(A("42".some))) + assertEquals(d.c.a.value.unsafeRunSync(), "42") + } - // test("higher kind tags 2") { + test("higher kind tags 2") { - // case class A[F[_]](value: F[String]) - // case class B(a: String) + case class A[F[_]](value: F[String]) + case class B(a: String) - // implicit def aMake[F[_]: Applicative, Z[_]: Applicative: Tag.TCTag]: Make[F, A[Z]] = Make.pure(A(Applicative[Z].pure("42"))) + implicit def aMake[F[_]: Applicative, Z[_]: Applicative: Tag.TCTag]: Make[F, A[Z]] = Make.pure(A(Applicative[Z].pure("42"))) - // implicit def bMake[F[_]: Applicative: Tag.TCTag]( - // implicit a: Make[F, A[F]] - // ): Make[F, B] = - // a.mapF(a => a.value.map(v => B(v))) + implicit def bMake[F[_]: Applicative: Tag.TCTag]( + implicit a: Make[F, A[F]] + ): Make[F, B] = + a.mapF(a => a.value.map(v => B(v))) - // // import enableDebug._ + // import enableDebug._ - // val resolved = Make.of[IO, B] - // assertEquals(resolved.make.unsafeRunSync(), B("42")) - // } + val resolved = Make.of[IO, B] + assertEquals(resolved.make.unsafeRunSync(), B("42")) + } - // test("diverging implicit(tuples)") { + test("diverging implicit(tuples)") { - // case class A[F[_]](value: F[String]) - // case class B(a: String, i: Int) + case class A[F[_]](value: F[String]) + case class B(a: String, i: Int) - // @autoMake - // case class C(b: B) + case class C(b: B) - // implicit def cMake[F[_]: Applicative]( - // implicit dep: Dep[F, B] - // ): Make[F, C] = dep.value.map(C(_)) + implicit def cMake[F[_]: Applicative]( + implicit dep: Dep[F, B] + ): Make[F, C] = dep.value.map(C(_)) - // implicit def bMake[F[_]: Applicative]( - // implicit - // deps: Dep[F, (Int, A[F])], - // ): Make[F, B] = - // deps.value.mapFN((i, a) => a.value.map(v => B(v, i))) + implicit def bMake[F[_]: Applicative]( + implicit + deps: Dep[F, (Int, A[F])], + ): Make[F, B] = + deps.value.mapFN((i, a) => a.value.map(v => B(v, i))) - // import enableDebug._ + import enableDebug._ - // implicit val aMake:Make[IO, A[IO]] = Make.pure[IO, A[IO]](A(IO("42"))) - // implicit val intMake = Make.pure[IO, Int](42) + implicit val aMake:Make[IO, A[IO]] = Make.pure[IO, A[IO]](A(IO("42"))) + implicit val intMake = Make.pure[IO, Int](42) - // val resolved = Make.debugOf[IO, (C, B)] - // assertEquals(resolved.make.unsafeRunSync(), (C(B("42", 42)), B("42", 42))) - // } - - // test("doesn't allow cycles") { - // illTyped( - // """ - // @autoMake - // case class A(b: B) - // @autoMake - // case class B(a: A) - // Make.of[IO, B] - // """ - // ) - // } - - test("sample debug") { - case class A(i: Int) - object A { - implicit def aMake[F[_]:Applicative](implicit iMake: Make[F, Int]):Make [F, A] = iMake.map(A(_)) - //implicit def aMake(implicit iMake: Make[IO, Int]):Make[IO, A] = iMake.map(A(_)) - } - @autoMake - case class B(a: A) - implicit val intMake: Make[IO, Int] = Make.pure(1) + val resolved = Make.debugOf[IO, (C, B)] + assertEquals(resolved.make.unsafeRunSync(), (C(B("42", 42)), B("42", 42))) + } - val make = Make.of[IO, B] - println(make.make.unsafeRunSync) + test("doesn't allow cycles") { + illTyped( + """ + @autoMake + case class A(b: B) + @autoMake + case class B(a: A) + Make.of[IO, B] + """ + ) } }