summaryrefslogtreecommitdiff
path: root/src/continuations/library
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2013-12-02 17:10:35 -0800
committerAdriaan Moors <adriaan.moors@typesafe.com>2013-12-13 17:36:16 -0800
commit858a5d513779f4af6f12c0a530bdeceb7a7fd4d9 (patch)
treebecda6df1363a92c1fcdf39643433ba101de4c10 /src/continuations/library
parent7e74aa6b134bcaf158bd51aa7a63a4aaa8fee62e (diff)
downloadscala-858a5d513779f4af6f12c0a530bdeceb7a7fd4d9.tar.gz
scala-858a5d513779f4af6f12c0a530bdeceb7a7fd4d9.tar.bz2
scala-858a5d513779f4af6f12c0a530bdeceb7a7fd4d9.zip
Modularize continuations plugin.
The continuations plugin and library will still ship with 2.11 (albeit unsupported). They now reside at https://github.com/scala/scala-continuations.
Diffstat (limited to 'src/continuations/library')
-rw-r--r--src/continuations/library/scala/util/continuations/ControlContext.scala249
-rw-r--r--src/continuations/library/scala/util/continuations/package.scala187
2 files changed, 0 insertions, 436 deletions
diff --git a/src/continuations/library/scala/util/continuations/ControlContext.scala b/src/continuations/library/scala/util/continuations/ControlContext.scala
deleted file mode 100644
index c196809da9..0000000000
--- a/src/continuations/library/scala/util/continuations/ControlContext.scala
+++ /dev/null
@@ -1,249 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2010-2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.util.continuations
-
-import scala.annotation.{ Annotation, StaticAnnotation, TypeConstraint }
-
-/** This annotation is used to mark a parameter as part of a continuation
- * context.
- *
- * The type `A @cpsParam[B,C]` is desugared to `ControlContext[A,B,C]` at compile
- * time.
- *
- * @tparam B The type of computation state after computation has executed, and
- * before control is returned to the shift.
- * @tparam C The eventual return type of this delimited compuation.
- * @see scala.util.continuations.ControlContext
- */
-class cpsParam[-B,+C] extends StaticAnnotation with TypeConstraint
-
-private class cpsSym[B] extends Annotation // implementation detail
-
-private class cpsSynth extends Annotation // implementation detail
-
-private class cpsPlus extends StaticAnnotation with TypeConstraint // implementation detail
-private class cpsMinus extends Annotation // implementation detail
-
-
-/**
- * This class represent a portion of computation that has a 'hole' in it. The
- * class has the ability to compute state up until a certain point where the
- * state has the `A` type. If this context is given a function of type
- * `A => B` to move the state to the `B` type, then the entire computation can
- * be completed resulting in a value of type `C`.
- *
- * An Example: {{{
- * val cc = new ControlContext[String, String, String](
- * fun = { (f: String=>String, err: Exception => String) =>
- * val updatedState =
- * try f("State")
- * catch {
- * case e: Exception => err(e)
- * }
- * updatedState + "-Complete!"
- * },
- * x = null.asIntanceOf[String]
- * }
- * cc.foreach(_ + "-Continued") // Results in "State-Continued-Complete!"
- * }}}
- *
- * This class is used to transform calls to `shift` in the `continuations`
- * package. Direct use and instantiation is possible, but usually reserved
- * for advanced cases.
- *
- *
- * A context may either be ''trivial'' or ''non-trivial''. A ''trivial''
- * context '''just''' has a state of type `A`. When completing the computation,
- * it's only necessary to use the function of type `A => B` directly against
- * the trivial value. A ''non-trivial'' value stores a computation '''around'''
- * the state transformation of type `A => B` and cannot be short-circuited.
- *
- * @param fun The captured computation so far. The type
- * `(A => B, Exception => B) => C` is a function where:
- * - The first parameter `A=>B` represents the computation defined against
- * the current state held in the ControlContext.
- * - The second parameter `Exception => B` represents a computation to
- * perform if an exception is thrown from the first parameter's computation.
- * - The return value is the result of the entire computation contained in this
- * `ControlContext`.
- * @param x The current state stored in this context. Allowed to be null if
- * the context is non-trivial.
- * @tparam A The type of the state currently held in the context.
- * @tparam B The type of the transformed state needed to complete this computation.
- * @tparam C The return type of the entire computation stored in this context.
- * @note `fun` and `x` are allowed to be `null`.
- * @see scala.util.continutations.shiftR
- */
-final class ControlContext[+A,-B,+C](val fun: (A => B, Exception => B) => C, val x: A) extends Serializable {
-
- /*
- final def map[A1](f: A => A1): ControlContext[A1,B,C] = {
- new ControlContext((k:(A1 => B)) => fun((x:A) => k(f(x))), null.asInstanceOf[A1])
- }
-
- final def flatMap[A1,B1<:B](f: (A => ControlContext[A1,B1,B])): ControlContext[A1,B1,C] = {
- new ControlContext((k:(A1 => B1)) => fun((x:A) => f(x).fun(k)))
- }
- */
-
- /**
- * Modifies the currently captured state in this `ControlContext`.
- * @tparam A1 The new type of state in this context.
- * @param f A transformation function on the current state of the `ControlContext`.
- * @return The new `ControlContext`.
- */
- @noinline final def map[A1](f: A => A1): ControlContext[A1,B,C] = {
- if (fun eq null)
- try {
- new ControlContext[A1,B,C](null, f(x)) // TODO: only alloc if f(x) != x
- } catch {
- case ex: Exception =>
- new ControlContext((k: A1 => B, thr: Exception => B) => thr(ex).asInstanceOf[C], null.asInstanceOf[A1])
- }
- else
- new ControlContext({ (k: A1 => B, thr: Exception => B) =>
- fun( { (x:A) =>
- var done = false
- try {
- val res = f(x)
- done = true
- k(res)
- } catch {
- case ex: Exception if !done =>
- thr(ex)
- }
- }, thr)
- }, null.asInstanceOf[A1])
- }
-
-
- // it would be nice if @inline would turn the trivial path into a tail call.
- // unfortunately it doesn't, so we do it ourselves in SelectiveCPSTransform
-
- /**
- * Maps and flattens this `ControlContext` with another `ControlContext` generated from the current state.
- * @note The resulting comuptation is still the type `C`.
- * @tparam A1 The new type of the contained state.
- * @tparam B1 The new type of the state after the stored continuation has executed.
- * @tparam C1 The result type of the nested `ControlContext`. Because the nested `ControlContext` is executed within
- * the outer `ControlContext`, this type must `>: B` so that the resulting nested computation can be fed through
- * the current continuation.
- * @param f A transformation function from the current state to a nested `ControlContext`.
- * @return The transformed `ControlContext`.
- */
- @noinline final def flatMap[A1,B1,C1<:B](f: (A => ControlContext[A1,B1,C1])): ControlContext[A1,B1,C] = {
- if (fun eq null)
- try {
- f(x).asInstanceOf[ControlContext[A1,B1,C]]
- } catch {
- case ex: Exception =>
- new ControlContext((k: A1 => B1, thr: Exception => B1) => thr(ex).asInstanceOf[C], null.asInstanceOf[A1])
- }
- else
- new ControlContext({ (k: A1 => B1, thr: Exception => B1) =>
- fun( { (x:A) =>
- var done = false
- try {
- val ctxR = f(x)
- done = true
- val res: C1 = ctxR.foreachFull(k, thr) // => B1
- res
- } catch {
- case ex: Exception if !done =>
- thr(ex).asInstanceOf[B] // => B NOTE: in general this is unsafe!
- } // However, the plugin will not generate offending code
- }, thr.asInstanceOf[Exception=>B]) // => B
- }, null.asInstanceOf[A1])
- }
-
- /**
- * Runs the computation against the state stored in this `ControlContext`.
- * @param f the computation that modifies the current state of the context.
- * @note This method could throw exceptions from the computations.
- */
- final def foreach(f: A => B) = foreachFull(f, throw _)
-
- def foreachFull(f: A => B, g: Exception => B): C = {
- if (fun eq null)
- f(x).asInstanceOf[C]
- else
- fun(f, g)
- }
-
- /** @return true if this context only stores a state value and not any deferred computation. */
- final def isTrivial = fun eq null
- /** @return The current state value. */
- final def getTrivialValue = x.asInstanceOf[A]
-
- // need filter or other functions?
-
- final def flatMapCatch[A1>:A,B1<:B,C1>:C<:B1](pf: PartialFunction[Exception, ControlContext[A1,B1,C1]]): ControlContext[A1,B1,C1] = { // called by codegen from SelectiveCPSTransform
- if (fun eq null)
- this
- else {
- val fun1 = (ret1: A1 => B1, thr1: Exception => B1) => {
- val thr: Exception => B1 = { t: Exception =>
- var captureExceptions = true
- try {
- if (pf.isDefinedAt(t)) {
- val cc1 = pf(t)
- captureExceptions = false
- cc1.foreachFull(ret1, thr1) // Throw => B
- } else {
- captureExceptions = false
- thr1(t) // Throw => B1
- }
- } catch {
- case t1: Exception if captureExceptions => thr1(t1) // => E2
- }
- }
- fun(ret1, thr)// fun(ret1, thr) // => B
- }
- new ControlContext(fun1, null.asInstanceOf[A1])
- }
- }
-
- final def mapFinally(f: () => Unit): ControlContext[A,B,C] = { // called in code generated by SelectiveCPSTransform
- if (fun eq null) {
- try {
- f()
- this
- } catch {
- case ex: Exception =>
- new ControlContext((k: A => B, thr: Exception => B) => thr(ex).asInstanceOf[C], null.asInstanceOf[A])
- }
- } else {
- val fun1 = (ret1: A => B, thr1: Exception => B) => {
- val ret: A => B = { x: A =>
- var captureExceptions = true
- try {
- f()
- captureExceptions = false
- ret1(x)
- } catch {
- case t1: Exception if captureExceptions => thr1(t1)
- }
- }
- val thr: Exception => B = { t: Exception =>
- var captureExceptions = true
- try {
- f()
- captureExceptions = false
- thr1(t)
- } catch {
- case t1: Exception if captureExceptions => thr1(t1)
- }
- }
- fun(ret, thr1)
- }
- new ControlContext(fun1, null.asInstanceOf[A])
- }
- }
-
-}
diff --git a/src/continuations/library/scala/util/continuations/package.scala b/src/continuations/library/scala/util/continuations/package.scala
deleted file mode 100644
index 573fae85e7..0000000000
--- a/src/continuations/library/scala/util/continuations/package.scala
+++ /dev/null
@@ -1,187 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2010-2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.util
-
-/* TODO: better documentation of return-type modification.
- * (Especially what means "Illegal answer type modification: ... andThen ...")
- */
-
-/**
- * Delimited continuations are a feature for modifying the usual control flow
- * of a program. To use continuations, provide the option `-P:continuations:enable`
- * to the Scala compiler or REPL to activate the compiler plugin.
- *
- * Below is an example of using continuations to suspend execution while awaiting
- * user input. Similar facilities are used in so-called continuation-based web frameworks.
- *
- * {{{
- * def go =
- * reset {
- * println("Welcome!")
- * val first = ask("Please give me a number")
- * val second = ask("Please enter another number")
- * printf("The sum of your numbers is: %d\n", first + second)
- * }
- * }}}
- *
- * The `reset` is provided by this package and delimits the extent of the
- * transformation. The `ask` is a function that will be defined below. Its
- * effect is to issue a prompt and then suspend execution awaiting user input.
- * Once the user provides an input value, execution of the suspended block
- * resumes.
- *
- * {{{
- * val sessions = new HashMap[UUID, Int=>Unit]
- * def ask(prompt: String): Int @cps[Unit] =
- * shift {
- * k: (Int => Unit) => {
- * val id = uuidGen
- * printf("%s\nrespond with: submit(0x%x, ...)\n", prompt, id)
- * sessions += id -> k
- * }
- * }
- * }}}
- *
- * The type of `ask` includes a `@cps` annotation which drives the transformation.
- * The type signature `Int @cps[Unit]` means that `ask` should be used in a
- * context requiring an `Int`, but actually it will suspend and return `Unit`.
- *
- * The computation leading up to the first `ask` is executed normally. The
- * remainder of the reset block is wrapped into a closure that is passed as
- * the parameter `k` to the `shift` function, which can then decide whether
- * and how to execute the continuation. In this example, the continuation is
- * stored in a sessions map for later execution. This continuation includes a
- * second call to `ask`, which is treated likewise once the execution resumes.
- *
- * <h2>CPS Annotation</h2>
- *
- * The aforementioned `@cps[A]` annotation is an alias for the more general
- * `@cpsParam[B,C]` where `B=C`. The type `A @cpsParam[B,C]` describes a term
- * which yields a value of type `A` within an evaluation context producing a
- * value of type `B`. After the CPS transformation, this return type is
- * modified to `C`.
- *
- * The `@cpsParam` annotations are introduced by `shift` blocks, and propagate
- * via the return types to the dynamically enclosing context. The propagation
- * stops upon reaching a `reset` block.
- */
-
-package object continuations {
-
- /** An annotation that denotes a type is part of a continuation context.
- * `@cps[A]` is shorthand for `cpsParam[A,A]`.
- * @tparam A The return type of the continuation context.
- */
- type cps[A] = cpsParam[A,A]
-
- /** An annotation that denotes a type is part of a side effecting continuation context.
- * `@suspendable` is shorthand notation for `@cpsParam[Unit,Unit]` or `@cps[Unit]`.
- */
- type suspendable = cps[Unit]
-
- /**
- * The `shift` function captures the remaining computation in a `reset` block
- * and passes it to a closure provided by the user.
- *
- * For example:
- * {{{
- * reset {
- * shift { (k: Int => Int) => k(5) } + 1
- * }
- * }}}
- *
- * In this example, `shift` is used in the expression `shift ... + 1`.
- * The compiler will alter this expression so that the call
- * to `shift` becomes a parameter to a function, creating something like:
- * {{{
- * { (k: Int => Int) => k(5) } apply { _ + 1 }
- * }}}
- * The result of this expression is 6.
- *
- * There can be more than one `shift` call in a `reset` block. Each call
- * to `shift` can alter the return type of expression within the reset block,
- * but will not change the return type of the entire `reset { block }`
- * expression.
- *
- * @param fun A function where
- * - The parameter is the remainder of computation within the current
- * `reset` block. This is passed as a function `A => B`.
- * - The return is the return value of the `ControlContext` which is
- * generated from this inversion.
- * @note Must be invoked in the context of a call to `reset` This context
- * may not be far up the stack, but a call to reset is needed to
- * eventually remove the `@cps` annotations from types.
- */
- def shift[A,B,C](fun: (A => B) => C): A @cpsParam[B,C] = {
- throw new NoSuchMethodException("this code has to be compiled with the Scala continuations plugin enabled")
- }
- /** Creates a context for continuations captured within the argument closure
- * of this `reset` call and returns the result of the entire transformed
- * computation. Within an expression of the form `reset { block }`,
- * the closure expression (`block`) will be modified such that at each
- * call to `shift` the remainder of the expression is transformed into a
- * function to be passed into the shift.
- * @return The result of a block of code that uses `shift` to capture continuations.
- */
- def reset[A,C](ctx: =>(A @cpsParam[A,C])): C = {
- val ctxR = reify[A,A,C](ctx)
- if (ctxR.isTrivial)
- ctxR.getTrivialValue.asInstanceOf[C]
- else
- ctxR.foreach((x:A) => x)
- }
-
- def reset0[A](ctx: =>(A @cpsParam[A,A])): A = reset(ctx)
-
- def run[A](ctx: =>(Any @cpsParam[Unit,A])): A = {
- val ctxR = reify[Any,Unit,A](ctx)
- if (ctxR.isTrivial)
- ctxR.getTrivialValue.asInstanceOf[A]
- else
- ctxR.foreach((x:Any) => ())
- }
-
-
- // methods below are primarily implementation details and are not
- // needed frequently in client code
-
- def shiftUnit0[A,B](x: A): A @cpsParam[B,B] = {
- shiftUnit[A,B,B](x)
- }
-
- def shiftUnit[A,B,C>:B](x: A): A @cpsParam[B,C] = {
- throw new NoSuchMethodException("this code has to be compiled with the Scala continuations plugin enabled")
- }
-
- /** This method converts from the sugared `A @cpsParam[B,C]` type to the desugared
- * `ControlContext[A,B,C]` type. The underlying data is not changed.
- */
- def reify[A,B,C](ctx: =>(A @cpsParam[B,C])): ControlContext[A,B,C] = {
- throw new NoSuchMethodException("this code has to be compiled with the Scala continuations plugin enabled")
- }
-
- def shiftUnitR[A,B](x: A): ControlContext[A,B,B] = { // called in code generated by SelectiveCPSTransform
- new ControlContext[A, B, B](null, x)
- }
-
- /**
- * Captures a computation into a `ControlContext`.
- * @param fun The function which accepts the inverted computation and returns
- * a final result.
- * @see shift
- */
- def shiftR[A,B,C](fun: (A => B) => C): ControlContext[A,B,C] = { // called in code generated by SelectiveCPSTransform
- new ControlContext((f:A=>B,g:Exception=>B) => fun(f), null.asInstanceOf[A])
- }
-
- def reifyR[A,B,C](ctx: => ControlContext[A,B,C]): ControlContext[A,B,C] = { // called in code generated by SelectiveCPSTransform
- ctx
- }
-
-}