diff --git a/zio-direct-pure/src/main/scala-3.x/zio/direct/pure/PureDsl.scala b/zio-direct-pure/src/main/scala-3.x/zio/direct/pure/PureDsl.scala index 6835086..5751b44 100644 --- a/zio-direct-pure/src/main/scala-3.x/zio/direct/pure/PureDsl.scala +++ b/zio-direct-pure/src/main/scala-3.x/zio/direct/pure/PureDsl.scala @@ -7,6 +7,7 @@ import zio.direct.directSetCall import zio.direct.directLogCall import zio.prelude.fx.ZPure import zio.direct.core.NotDeferredException +import zio.Tag // Using this plainly can possibly case a cyclical macro error? Not sure why // class deferWithParams[W, S] extends deferCall[[R, E, A] =>> ZPure[W, S, S, R, E, A], ZPure[?, ?, ?, ?, ?, ?], S, W] @@ -48,6 +49,7 @@ class deferWith[W, S] { object Wrap { def succeed[T](value: T) = ZPure.succeed[S, T](value) def attempt[T](value: T) = ZPure.attempt[S, T](value) + def service[T: Tag] = ZPure.service[S, T] } } diff --git a/zio-direct-pure/src/test/scala-3.x/zio/direct/pure/PureSpec.scala b/zio-direct-pure/src/test/scala-3.x/zio/direct/pure/PureSpec.scala index d5f4279..271dc80 100644 --- a/zio-direct-pure/src/test/scala-3.x/zio/direct/pure/PureSpec.scala +++ b/zio-direct-pure/src/test/scala-3.x/zio/direct/pure/PureSpec.scala @@ -7,7 +7,6 @@ import zio.direct.Use import zio.direct.core.util.Messages import scala.annotation.nowarn import zio.direct.DeferRunSpec -import zio.stream.ZStream import zio.Chunk import zio.prelude.fx.ZPure diff --git a/zio-direct-pure/src/test/scala-3.x/zio/direct/pure/VariaSpec.scala b/zio-direct-pure/src/test/scala-3.x/zio/direct/pure/VariaSpec.scala new file mode 100644 index 0000000..6cac9f3 --- /dev/null +++ b/zio-direct-pure/src/test/scala-3.x/zio/direct/pure/VariaSpec.scala @@ -0,0 +1,114 @@ +package zio.direct.pure + +import zio.direct.DeferRunSpec +import zio.test._ +import zio.test.Assertion._ +import zio._ +import ZIO.{unsafe => _, _} +import zio.direct.core.util.Messages +import scala.annotation.nowarn +import zio.direct.DeferRunSpec +import zio.prelude.fx.ZPure + +@nowarn +object VariaSpec extends DeferRunSpec { + val dc = deferWith[String, MyState] + import dc._ + val init = MyState("init") + + case class Config1(value: Int) + case class Config2(value: Int) + case class Config3(value: Int) + case class Config4(value: Int) + + class SomeService private (var isOpen: Boolean) { + def close(): Unit = { isOpen = false } + } + object SomeService { + def open() = new SomeService(true) + } + + val spec = suite("VariaSpec")( + suite("odd placements of defer/run")( + test("defer in defer") { + val out = + defer { + val v = defer { + val env = Wrap.service[ConfigInt].eval + env + } + v.eval.value + 1 + } + assert(out.provideState(init).provideService(ConfigInt(3)).run)(equalTo(4)) + }, + test("four services") { + val out = + defer { + val (x, y) = (Wrap.service[Config1].eval.value, Wrap.service[Config2].eval.value) + val config = Wrap.service[Config3].eval + x + config.value + y + Wrap.service[Config4].eval.value + } + val provided = + out.provideEnvironment( + ZEnvironment(Config1(1), Config2(2), Config3(3), Config4(4)) + ) + + assert(provided.provideState(init).run)(equalTo(10)) + }, + test("services with match statement") { + val out = + defer { + val configValue = + Wrap.service[Config1].eval match { + case Config1(value) => value + Wrap.service[Config2].eval.value + } + configValue + Wrap.service[Config3].eval.value + } + val provided = + out.provideEnvironment( + ZEnvironment(Config1(1), Config2(2), Config3(4)) + ) + assert(provided.provideState(init).run)(equalTo(7)) + }, + test("double tuple deconstruct") { + val out = + defer { + val (x, y) = (Wrap.succeed("foo").eval, Wrap.succeed("bar").eval) + val (x1, y1) = (Wrap.succeed("A" + x).eval, Wrap.succeed("B" + y).eval) + x + x1 + y + y1 + } + assert(out.provideState(init).run)(equalTo("fooAfoobarBbar")) + }, + test("deconstruct and import") { + class Blah(val value: Int) + val out = + defer { + val (a, a1) = eval(Wrap.succeed((1, 2))) + val blah = new Blah(3) + import blah._ + val b = eval(Wrap.succeed(value)) + a + b + } + assert(out.provideState(init).run)(equalTo(4)) + }, + test("deconstruct and multiple import") { + class Blah(val value: Int) + class Blah0(val value0: Int) + class Blah1(val value1: Int) + val out = + defer { + val blah0 = new Blah0(1) + import blah0._ + val blah1 = new Blah1(2) + import blah1._ + val (a, a1) = Wrap.succeed((value0, value1)).eval + val blah = new Blah(3) + import blah._ + val b = Wrap.succeed(value).eval + a + a1 + b + } + assert(out.provideState(init).run)(equalTo(6)) + } + ) + ) +} diff --git a/zio-direct/src/main/scala-3.x/zio/direct/core/metaprog/WithZioType.scala b/zio-direct/src/main/scala-3.x/zio/direct/core/metaprog/WithZioType.scala index 30ed699..833270c 100644 --- a/zio-direct/src/main/scala-3.x/zio/direct/core/metaprog/WithZioType.scala +++ b/zio-direct/src/main/scala-3.x/zio/direct/core/metaprog/WithZioType.scala @@ -28,23 +28,11 @@ trait WithZioType extends MacroBase { def toZioValue(zpe: ZioType) = ZioValue(expr, zpe) } - // TODO when we support non-zio values, will need to have one of these for each supported type object ZioValue { def apply(term: Term, zpe: ZioType) = new ZioValue(term, zpe) def apply(expr: Expr[_], zpe: ZioType) = new ZioValue(expr.asTerm, zpe) } - // case class ZioEffectTypeContext(zet: ZioEffectType) - // object List3Or6 { - // def unapply[T](list: List[T]) = - // list match { - // case List(a, b, c) => Some((a, b, c)) - // case List(_, _, _, a, b, c) => Some((a, b, c)) - // case _ => None - // } - // } - - // TODO At least check that the A type exists, it has to since it's a value class ZioEffectType private (val tpe: TypeRepr, val typesWithMarkers: Array[TypeRepr], val variances: Array[(MonadShape.Letter, MonadShape.Variance)]) { if (!variances.exists(_._1 == MonadShape.Letter.A)) report.errorAndAbort("List of MonadShape letters must at least include an A i.e. value-type.") diff --git a/zio-direct/src/main/scala-3.x/zio/direct/core/norm/WithReconstructTree.scala b/zio-direct/src/main/scala-3.x/zio/direct/core/norm/WithReconstructTree.scala index 1b915d8..3164e25 100644 --- a/zio-direct/src/main/scala-3.x/zio/direct/core/norm/WithReconstructTree.scala +++ b/zio-direct/src/main/scala-3.x/zio/direct/core/norm/WithReconstructTree.scala @@ -286,8 +286,8 @@ trait WithReconstructTree { CaseDef(caseDef.pattern, caseDef.guard, rhsRaw.term) }.toList - (tryBlockType.toZioType.asType, tryBlockType.e.asType, wholeTryZpe.toZioType.asType) match - case ('[zioTry], '[zioTry_E], '[zioOut]) => + wholeTryZpe.toZioType.asType match + case '[zioOut] => // A normal lambda looks something like: // Block(List( // DefDef(newMethodSymbol, terms:List[List[Tree]] => Option(body))