-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit fe2f2af
Showing
12 changed files
with
662 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
*.class | ||
*.log | ||
|
||
# sbt specific | ||
.cache | ||
.history | ||
.lib/ | ||
dist/* | ||
target/ | ||
lib_managed/ | ||
src_managed/ | ||
project/boot/ | ||
project/plugins/project/ | ||
**/.bloop | ||
|
||
# Scala-IDE specific | ||
.scala_dependencies | ||
.worksheet | ||
|
||
.idea | ||
|
||
# ENSIME specific | ||
.ensime_cache/ | ||
.ensime | ||
|
||
.metals/ | ||
metals.sbt | ||
metals/project/ | ||
|
||
.vscode/ | ||
|
||
local.* | ||
|
||
.DS_Store | ||
|
||
node_modules | ||
|
||
lib/core/metadata.js | ||
lib/core/MetadataBlog.js | ||
|
||
website/translated_docs | ||
website/build/ | ||
website/yarn.lock | ||
website/node_modules | ||
website/i18n/* | ||
!website/i18n/en.json | ||
|
||
project/metals.sbt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
lazy val core = project.in(file("modules/core")) | ||
.settings( | ||
scalaVersion := "2.12.11", | ||
libraryDependencies ++= Seq( | ||
"org.typelevel" %% "cats-core" % "2.1.1", | ||
"org.typelevel" %% "cats-effect" % "2.1.3", | ||
"com.lihaoyi" %% "sourcecode" % "0.1.9", | ||
"org.scala-lang" % "scala-reflect" % scalaVersion.value | ||
) | ||
) | ||
|
||
lazy val example = project.in(file("modules/example")) | ||
.dependsOn(core) | ||
.settings( | ||
scalaVersion := "2.12.11", | ||
//scalacOptions ++= Seq("-Ymacro-debug-lite", "-Yshow-trees-compact") | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package make | ||
|
||
import make.internal.Node | ||
import make.internal.NodeTag | ||
import cats.effect.Resource | ||
import cats.Applicative | ||
import make.internal.NodeTag.Pos | ||
import scala.reflect.classTag | ||
import scala.reflect.ClassTag | ||
import scala.language.experimental.macros | ||
import cats.Monad | ||
|
||
trait Make[F[_], A] { | ||
def node: Node[A] | ||
final def asResource(implicit x: Monad[F]): Resource[F, A] = internal.Dag.toResource[F, A](node) | ||
} | ||
|
||
object Make { | ||
|
||
def context[F[_]: Applicative]: Make.Ctx[F] = new Ctx[F] | ||
|
||
def inCtx[F[_]: Make.Ctx]: DerivePartillyApplyed[F] = | ||
new DerivePartillyApplyed[F] | ||
|
||
class DerivePartillyApplyed[F[_]] { | ||
def derive[A]: Make[F, A] = | ||
macro make.internal.DepsCtxMacros.materializeMake[F, A] | ||
} | ||
|
||
final class Ctx[F[_]: Applicative] { | ||
def pure[A: NodeTag](v: A): Make[F, A] = | ||
createFromNodeUnsafe(Node.Pure(v, NodeTag.of[A])) | ||
|
||
def effect[A: NodeTag](v: F[A]): Make[F, A] = | ||
createFromNodeUnsafe(Node.Eff(Resource.liftF(v), NodeTag.of[A])) | ||
|
||
def resource[A: NodeTag](v: Resource[F, A]): Make[F, A] = | ||
createFromNodeUnsafe(Node.Eff(v, NodeTag.of[A])) | ||
} | ||
|
||
final class DepsCtx[F[_]: Applicative, A](deps: Make[F, A]) { | ||
def pure[B: NodeTag](f: A => B): Make[F, B] = | ||
createFromNodeUnsafe(Node.Func(deps.node, f, NodeTag.of[B])) | ||
|
||
def effect[B: NodeTag](f: A => F[B]): Make[F, B] = | ||
createFromNodeUnsafe(Node.EffFunc(deps.node, (a: A) => Resource.liftF(f(a)), NodeTag.of[B])) | ||
|
||
def resource[B: NodeTag](f: A => Resource[F, B]): Make[F, B] = | ||
createFromNodeUnsafe(Node.EffFunc(deps.node, f, NodeTag.of[B])) | ||
} | ||
|
||
object DepsCtx { | ||
|
||
implicit def derive[F[_], A]: Make.DepsCtx[F, A] = | ||
macro make.internal.DepsCtxMacros.materializeDeps[F, A] | ||
} | ||
|
||
def createFromNodeUnsafe[F[_], A](v: Node[A]): Make[F, A] = | ||
new Make[F, A] { | ||
val node: Node[A] = v | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
package sdi | ||
|
||
import cats.effect.Resource | ||
import scala.reflect.macros.blackbox.Context | ||
import scala.language.experimental.macros | ||
|
||
// trait InstanceTree[F[_], A] | ||
|
||
// trait EffForInstances[F[_]] | ||
|
||
// sealed trait Instance2[A] { | ||
// def tag: Tag[A] | ||
// } | ||
// object Instance2 { | ||
|
||
// final case class Pure[A](v: A, tag: Tag[A]) extends Instance2[A] | ||
// final case class Func[In, A](prev: Instance2[In], f: In => A, tag: Tag[A]) extends Instance2[A] | ||
|
||
// sealed trait EffInstance[F[_], A] extends Instance2[A] | ||
// final case class Eff[F[_], A](v: F[A], tag: Tag[A]) extends EffInstance[F, A] | ||
// final case class EffFunc[F[_], In, A](prev: Instance2[In], f: In => Resource[F, A], tag: Tag[A]) extends EffInstance[F, A] | ||
|
||
// final case class Ap[In, A](prev: Instance2[In], f: Instance[In => A], tag: Tag[In => A]) extends Instance2[In => A] | ||
|
||
// // def deriveTree[F[_], A]: InstanceTree[F, A] = ??? | ||
|
||
// } | ||
|
||
|
||
// sealed trait Instance[A] { | ||
// def tag: Tag[A] | ||
// } | ||
|
||
// object Instance { | ||
|
||
// final case class Pure[A](v: A, tag: Tag[A]) extends Instance[A] | ||
// final case class Effect[F[_], A](v: F[A], tag: Tag[A]) extends Instance[A] | ||
// final case class Map[In, A](prev: Instance[In], f: In => A, tag: Tag[A]) extends Instance[A] | ||
// final case class Ap[In, A](prev: Instance[In], f: Instance[In => A], tag: Tag[In => A]) extends Instance[In => A] | ||
|
||
// final case class PureK[F[_], A](v: A, tag: Tag[A]) extends Instance[A] | ||
|
||
// def pure[A: Tag](v: A): Instance.Pure[A] = Instance.Pure(v, Tag.of[A]) | ||
// def effect[F[_], A: Tag](v: F[A]): Instance.Effect[F, A] = Instance.Effect(v, Tag.of[A]) | ||
|
||
// } | ||
|
||
// trait Requires[A] | ||
// object Requires { | ||
// implicit def derive[A]: Requires[A] = macro RequiresMacro.materialize[A] | ||
// } | ||
|
||
// class RequiresMacro(val c: Context) { | ||
// import c.universe._ | ||
|
||
// private val intanceTC = typeOf[Instance[_]].typeConstructor | ||
|
||
// def materialize[A: c.WeakTypeTag]: c.Expr[Requires[A]] = { | ||
// val tpe = weakTypeOf[A] | ||
// println(tpe.getClass()) | ||
// val out = resolve(tpe).orElse(tryTuple(tpe)) | ||
|
||
// out match { | ||
// case Some(tree) => c.Expr[Requires[A]](q"new Requires[$tpe]{}") | ||
// case None => | ||
// c.error(c.enclosingPosition, s"Can't find `Requires` for $tpe") | ||
// c.Expr[Requires[A]](EmptyTree) | ||
// } | ||
// } | ||
|
||
// private val tupleRegex = "scala.Tuple(\\d+)".r | ||
|
||
|
||
// private def tryTuple(tpe: Type): Option[c.Tree] = { | ||
// val name = tpe.typeSymbol.fullName | ||
|
||
// name match { | ||
// case tupleRegex(x) => | ||
// println(s"sdassa: ${x}") | ||
// println(tpe.typeArgs) | ||
|
||
// val init = List.empty[String] | ||
// val errors = tpe.typeArgs.foldLeft(init){ | ||
// case (errAcc, t) => | ||
// resolve(t) match { | ||
// case Some(_) => errAcc | ||
// case None => s"Can't find Instance for ${t}" :: errAcc | ||
// } | ||
// } | ||
// if (errors.nonEmpty) { | ||
// val x = errors.mkString("\n") | ||
// c.error(c.enclosingPosition, x) | ||
// None | ||
// } else { | ||
// Some(EmptyTree) | ||
// } | ||
// case _ => None | ||
// } | ||
// } | ||
|
||
// private def resolve(tpe: Type): Option[c.Tree] = { | ||
// c.inferImplicitValue(appliedType(intanceTC, tpe)) match { | ||
// case EmptyTree => None | ||
// case tree => Some(tree) | ||
// } | ||
// } | ||
// } | ||
|
||
|
||
// object XXx2 { | ||
|
||
// case class Args(args: List[String]) | ||
// object Args { | ||
// implicit def instance(implicit req: Requires[List[String]]): Instance[] | ||
// } | ||
|
||
// case class Abc(args: Args, out: String) | ||
// object Abc { | ||
// implicit val instance: Bind2.Func[Args, Abc] = Bind2.func(Abc(_, "default")) | ||
// } | ||
|
||
// case class Foo(args: Args) | ||
// object Foo { | ||
// implicit val instanceXXX: Bind2.Func[Args, Foo] = Bind2.func(Foo(_)) | ||
// implicit val instance2: Bind2.Func[Int, Foo] = Bind2.func(x => Foo(Args(List(x.toString())))) | ||
// } | ||
|
||
// case class End( | ||
// abc: Abc, | ||
// foo: Foo | ||
// ) { | ||
// def what: String = abc.out | ||
// } | ||
|
||
// object End { | ||
// implicit val instance: Bind2.Func[(Abc, Foo), End] = Bind2.func({ case (abc, foo) => End(abc, foo)}) | ||
// } | ||
|
||
|
||
// def main(args: Array[String]): Unit = { | ||
// import cats.implicits._ | ||
// import cats.effect.implicits._ | ||
|
||
// implicit val initArgs = Bind2.pure(args.toList) | ||
|
||
// implicit val tmp = Bind2.pure(1) | ||
// // implicit val abcOverride = Bind2.func(Abc(_, "override")) | ||
// val out = DependencyTree.of[IO, Foo] | ||
// // val rsc = Instantiate(out) | ||
|
||
// // val eff = rsc.use(value => IO.delay(println(s"HAHAHAH: ${value.what}"))) | ||
// // eff.unsafeRunSync() | ||
// } | ||
|
||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package make.internal | ||
|
||
import cats.Monad | ||
import cats.effect.Resource | ||
|
||
object Dag { | ||
|
||
case class Entry[F[_]]( | ||
tag: NodeTag[Any], | ||
create: List[Any] => Resource[F, Any], | ||
takes: Vector[NodeTag[Any]] | ||
) | ||
|
||
def toResource[F[_], A](node: Node[A])(implicit F: Monad[F]): Resource[F, A] = { | ||
|
||
def toMap( | ||
node: Node[Any], | ||
acc: Map[NodeTag[Any], Entry[F]] | ||
): Map[NodeTag[Any], Entry[F]] = { | ||
node match { | ||
case Node.Pure(v, tag) => | ||
val entry = acc.get(tag) match { | ||
case None => Entry[F](tag, _ => Resource.pure(v), Vector.empty) | ||
case Some(e) => e | ||
} | ||
acc.updated(tag, entry) | ||
case Node.Func(prev, f, tag) => | ||
val updEntry = acc.get(tag) match { | ||
case None => Entry[F](tag, lst => Resource.pure(f(lst(0))), Vector(prev.tag)) | ||
case Some(e) => e.copy(takes = e.takes :+ prev.tag) | ||
} | ||
val next = acc.updated(tag, updEntry) | ||
toMap(prev, next) | ||
case Node.Eff(v, tag) => | ||
val entry = acc.get(tag) match { | ||
case None => Entry[F](tag, _ => v.asInstanceOf[Resource[F, Any]], Vector.empty) | ||
case Some(e) => e | ||
} | ||
acc.updated(tag, entry) | ||
case Node.EffFunc(prev, f, tag) => | ||
val updEntry = acc.get(tag) match { | ||
case None => Entry[F](tag, lst => f(lst(0)).asInstanceOf[Resource[F, Any]], Vector(prev.tag)) | ||
case Some(e) => e.copy(takes = e.takes :+ prev.tag) | ||
} | ||
val next = acc.updated(tag, updEntry) | ||
toMap(prev, next) | ||
case Node.Ap(prev, op, tag) => | ||
val opAdded = toMap(op.asInstanceOf[Node[Any]], acc) | ||
val updEntry = acc.get(tag) match { | ||
case None => Entry[F]( | ||
tag, | ||
lst => { | ||
val a = lst(0) | ||
val aToB = lst(1).asInstanceOf[Any => Any] | ||
Resource.pure(aToB(a)) | ||
}, | ||
Vector(prev.tag, op.tag.asInstanceOf[NodeTag[Any]]) | ||
) | ||
case Some(e) => e.copy(takes = e.takes :+ prev.tag) | ||
} | ||
val next = opAdded.updated(tag, updEntry) | ||
toMap(prev, next) | ||
} | ||
} | ||
val empty = Map.empty[NodeTag[Any], Entry[F]] | ||
val asMap = toMap(node.asInstanceOf[Node[Any]], empty) | ||
|
||
val indexedKeys = asMap.keys.zipWithIndex.toMap | ||
val indexedMap = indexedKeys.map {case (tag, _) => | ||
val entry = asMap(tag) | ||
println(entry) | ||
entry.takes.map(indexedKeys(_)).toList | ||
}.toList | ||
|
||
|
||
val sorted = Tarjans.apply(indexedMap) | ||
|
||
val entriesWithTags = sorted.flatten.map(i => { | ||
val (tag, idx) = indexedKeys.find(_._2 == i).get | ||
val entry = asMap(tag) | ||
(entry, tag) | ||
}) | ||
|
||
|
||
case class ResourceState( | ||
map: Map[NodeTag[Any], Any] | ||
) | ||
|
||
val init = Resource.make[F, Map[NodeTag[Any], Any]](F.pure(Map.empty))(_ => F.unit) | ||
val resourcePipeline = entriesWithTags.foldLeft(init){ case (accResource, (entry, tag)) => | ||
accResource.flatMap(depsMap => { | ||
val input = entry.takes.map(depsMap(_)) | ||
val rsc = entry.create(input.toList) | ||
rsc.map(v => depsMap.updated(tag, v)) | ||
}) | ||
} | ||
|
||
resourcePipeline.map(all => { | ||
println(all) | ||
all(node.tag.asInstanceOf[NodeTag[Any]]) | ||
}).asInstanceOf[Resource[F, A]] | ||
} | ||
|
||
} |
Oops, something went wrong.