diff --git a/Dsl/src/main/scala/com/thoughtworks/dsl/Dsl.scala b/Dsl/src/main/scala/com/thoughtworks/dsl/Dsl.scala index b06fc04be..f29efc48b 100644 --- a/Dsl/src/main/scala/com/thoughtworks/dsl/Dsl.scala +++ b/Dsl/src/main/scala/com/thoughtworks/dsl/Dsl.scala @@ -123,80 +123,7 @@ object Dsl extends LowPriorityDsl0 { ) } - type Continuation[R, +A] = (A => R) => R - - // TODO: Move to a separate library ( domains-continuation? ) - object Continuation { - @inline - def now[R, A](a: A): R !! A = _(a) - - @inline - def empty[R, A](r: R): R !! A = Function.const(r) - - @inline - def delay[R, A](a: () => A): R !! A = _(a()) - - // TODO: turn it into an inline def - // TODO: Think about package object in Scala 3 - @inline - def apply[R, A](a: => A): (R !! A) = delay(() => a) - - def toTryContinuation[LeftDomain, Value]( - task: LeftDomain !! Throwable !! Value - )(handler: Try[Value] => LeftDomain): LeftDomain = { - task { a => failureHandler => - handler(Success(a)) - } { e => - handler(Failure(e)) - } - } - - def fromTryContinuation[LeftDomain, Value]( - continuation: LeftDomain !! Try[Value] - )(successHandler: Value => LeftDomain !! Throwable)(failureHandler: Throwable => LeftDomain): LeftDomain = { - continuation( - new (Try[Value] => LeftDomain) { - def apply(result: Try[Value]): LeftDomain = { - result match { - case Success(a) => - val protectedContinuation = - try { - successHandler(a) - } catch { - case NonFatal(e) => - return failureHandler(e) - } - protectedContinuation(failureHandler) - case Failure(e) => - failureHandler(e) - } - } - } - ) - } - - } - - type !![R, +A] = Continuation[R, A] - val !! = Continuation - - @deprecated("Use bangnotation.reset instead", "Dsl.scala 2.0.0") - private[dsl] /* sealed */ trait ResetAnnotation extends Annotation with StaticAnnotation - @deprecated("Use bangnotation.reset instead", "Dsl.scala 2.0.0") - private[dsl] final class nonTypeConstraintReset extends ResetAnnotation with StaticAnnotation - - /** An annotation to explicitly perform reset control operator on a code block. - * - * @note - * This annotation can be automatically added if [[compilerplugins.ResetEverywhere ResetEverywhere]] compiler - * plug-in is enabled. - */ - @deprecated("Use bangnotation.reset instead", "Dsl.scala 2.0.0") - final class reset extends ResetAnnotation with StaticAnnotation with TypeConstraint - - /** An annotation to mark a method is a shift control operator. */ - @deprecated("Use bangnotation.reset instead", "Dsl.scala 2.0.0") - final class shift extends StaticAnnotation + private[dsl] type !![R, +A] = (A => R) => R def apply[Keyword, Domain, Value](implicit typeClass: Dsl[Keyword, Domain, Value]): Dsl[Keyword, Domain, Value] = typeClass diff --git a/build.sbt b/build.sbt index c354e1b59..766264367 100644 --- a/build.sbt +++ b/build.sbt @@ -21,12 +21,18 @@ lazy val bangnotation = `keywords-While` ) +lazy val `domains-Continuation` = + crossProject(JSPlatform, JVMPlatform) + .crossType(CrossType.Pure) + .dependsOn(bangnotation) + lazy val `domains-Task` = crossProject(JSPlatform, JVMPlatform) .crossType(CrossType.Pure) .dependsOn( `keywords-Shift`, bangnotation, + `domains-Continuation`, `keywords-In` % Test, `keywords-Fork` % Test, `keywords-Each` % Test, @@ -170,6 +176,7 @@ lazy val `keywords-Await` = .crossType(CrossType.Pure) .dependsOn( Dsl, + `domains-Continuation`, comprehension % Test, bangnotation % Test, `domains-Task` % Test, diff --git a/domains-Continuation/src/main/scala/com/thoughtworks/dsl/domains/Continuation.scala b/domains-Continuation/src/main/scala/com/thoughtworks/dsl/domains/Continuation.scala new file mode 100644 index 000000000..5093611bf --- /dev/null +++ b/domains-Continuation/src/main/scala/com/thoughtworks/dsl/domains/Continuation.scala @@ -0,0 +1,62 @@ +package com.thoughtworks.dsl +package domains + +import bangnotation._ +import scala.util._ +import scala.util.control.NonFatal + +type Continuation[R, +A] = (A => R) => R + +object Continuation { + val !! = this + type !![R, +A] = Continuation[R, A] + + + @inline + def now[R, A](a: A): R !! A = _(a) + + @inline + def empty[R, A](r: R): R !! A = Function.const(r) + + @inline + def delay[R, A](a: () => A): R !! A = _(a()) + + inline def apply[R, A](inline a: A): R !! A = { handler => + reset(handler(a)) + } + + def toTryContinuation[LeftDomain, Value]( + task: LeftDomain !! Throwable !! Value + )(handler: Try[Value] => LeftDomain): LeftDomain = { + task { a => failureHandler => + handler(Success(a)) + } { e => + handler(Failure(e)) + } + } + + def fromTryContinuation[LeftDomain, Value]( + continuation: LeftDomain !! Try[Value] + )(successHandler: Value => LeftDomain !! Throwable)(failureHandler: Throwable => LeftDomain): LeftDomain = { + continuation( + new (Try[Value] => LeftDomain) { + def apply(result: Try[Value]): LeftDomain = { + result match { + case Success(a) => + val protectedContinuation = + try { + successHandler(a) + } catch { + case NonFatal(e) => + return failureHandler(e) + } + protectedContinuation(failureHandler) + case Failure(e) => + failureHandler(e) + } + } + } + ) + } + +} diff --git a/domains-Task/.jvm/src/main/scala/com/thoughtworks/dsl/domains/TaskPlatformSpecificFunctions.scala b/domains-Task/.jvm/src/main/scala/com/thoughtworks/dsl/domains/TaskPlatformSpecificFunctions.scala index dc3b4f4d8..b86f187e8 100644 --- a/domains-Task/.jvm/src/main/scala/com/thoughtworks/dsl/domains/TaskPlatformSpecificFunctions.scala +++ b/domains-Task/.jvm/src/main/scala/com/thoughtworks/dsl/domains/TaskPlatformSpecificFunctions.scala @@ -4,7 +4,7 @@ import scala.concurrent.SyncVar import scala.util.Try import scala.util.control.TailCalls import scala.concurrent.duration.Duration -import com.thoughtworks.dsl.Dsl.Continuation +import com.thoughtworks.dsl.domains.Continuation private[domains] trait TaskPlatformSpecificFunctions { this: Task.type => def blockingAwait[A](task: Task[A], timeout: Duration = Duration.Inf): A = { diff --git a/domains-Task/.jvm/src/test/scala/com/thoughtworks/dsl/domains/RaiiSpec.scala b/domains-Task/.jvm/src/test/scala/com/thoughtworks/dsl/domains/RaiiSpec.scala index da9b4eccc..77550c8d5 100644 --- a/domains-Task/.jvm/src/test/scala/com/thoughtworks/dsl/domains/RaiiSpec.scala +++ b/domains-Task/.jvm/src/test/scala/com/thoughtworks/dsl/domains/RaiiSpec.scala @@ -1,9 +1,8 @@ package com.thoughtworks.dsl package domains -import com.thoughtworks.dsl.Dsl.{!!, Continuation} import com.thoughtworks.dsl.keywords.{Shift, Yield} -import com.thoughtworks.dsl.domains._ +import com.thoughtworks.dsl.domains._, Continuation.!! import com.thoughtworks.dsl.bangnotation._ import scala.util.control.NonFatal diff --git a/domains-Task/.jvm/src/test/scala/com/thoughtworks/dsl/domains/UsingSpec.scala b/domains-Task/.jvm/src/test/scala/com/thoughtworks/dsl/domains/UsingSpec.scala index 6aa1fe8af..74ca5329f 100644 --- a/domains-Task/.jvm/src/test/scala/com/thoughtworks/dsl/domains/UsingSpec.scala +++ b/domains-Task/.jvm/src/test/scala/com/thoughtworks/dsl/domains/UsingSpec.scala @@ -1,7 +1,7 @@ package com.thoughtworks.dsl package domains -import com.thoughtworks.dsl.Dsl.{!!, Continuation} +import Continuation.!! import com.thoughtworks.dsl.bangnotation._ import com.thoughtworks.dsl.keywords.{Using, Yield} import org.scalatest.Assertion diff --git a/domains-Task/src/main/scala/com/thoughtworks/dsl/domains/Task.scala b/domains-Task/src/main/scala/com/thoughtworks/dsl/domains/Task.scala index 9ac94bf53..f3e90285b 100644 --- a/domains-Task/src/main/scala/com/thoughtworks/dsl/domains/Task.scala +++ b/domains-Task/src/main/scala/com/thoughtworks/dsl/domains/Task.scala @@ -1,7 +1,7 @@ package com.thoughtworks.dsl package domains -import com.thoughtworks.dsl.Dsl.{!!, Continuation} +import com.thoughtworks.dsl.domains.Continuation, Continuation.!! import com.thoughtworks.dsl.keywords.Shift import com.thoughtworks.dsl.bangnotation._ diff --git a/keywords-Await/src/main/scala/com/thoughtworks/dsl/keywords/Await.scala b/keywords-Await/src/main/scala/com/thoughtworks/dsl/keywords/Await.scala index 9233b1448..fcc447d90 100644 --- a/keywords-Await/src/main/scala/com/thoughtworks/dsl/keywords/Await.scala +++ b/keywords-Await/src/main/scala/com/thoughtworks/dsl/keywords/Await.scala @@ -3,7 +3,7 @@ package keywords import Dsl.IsKeyword import Dsl.Typed import com.thoughtworks.dsl.Dsl -import com.thoughtworks.dsl.Dsl.!! +import com.thoughtworks.dsl.domains.Continuation.!! import scala.concurrent.Await.result import scala.concurrent.duration.Duration import scala.concurrent.{ExecutionContext, Future} diff --git a/keywords-Shift/src/main/scala/com/thoughtworks/dsl/keywords/Shift.scala b/keywords-Shift/src/main/scala/com/thoughtworks/dsl/keywords/Shift.scala index 333aa3890..dc8f265d1 100644 --- a/keywords-Shift/src/main/scala/com/thoughtworks/dsl/keywords/Shift.scala +++ b/keywords-Shift/src/main/scala/com/thoughtworks/dsl/keywords/Shift.scala @@ -4,7 +4,6 @@ import Dsl.IsKeyword import Dsl.Typed import com.thoughtworks.dsl.Dsl -import com.thoughtworks.dsl.Dsl.{!!, Continuation} import com.thoughtworks.dsl.keywords.Shift.{SameDomainStackSafeShiftDsl, StackSafeShiftDsl} import scala.annotation.tailrec @@ -15,7 +14,7 @@ import scala.util.control.TailCalls.TailRec /** @author * 杨博 (Yang Bo) */ -opaque type Shift[R, A] = Dsl.Continuation[R, A] +opaque type Shift[R, A] = (A => R) => R private[keywords] trait LowPriorityShift1 { @@ -151,8 +150,10 @@ object Shift extends LowPriorityShift0 { taskFlatMap(keyword.continuation, handler) } - def apply[R, A](continuation: Continuation[R, A]): Shift[R, A] = continuation + private[keywords] type !![R, +A] = (A => R) => R - extension [R, A](shift: Shift[R, A]) def continuation: Continuation[R, A] = shift + def apply[R, A](continuation: R !! A): Shift[R, A] = continuation + + extension [R, A](shift: Shift[R, A]) def continuation: R !! A = shift }