aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/scala/async/Async.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/scala/async/Async.scala')
-rw-r--r--src/main/scala/scala/async/Async.scala185
1 files changed, 0 insertions, 185 deletions
diff --git a/src/main/scala/scala/async/Async.scala b/src/main/scala/scala/async/Async.scala
deleted file mode 100644
index 35d3687..0000000
--- a/src/main/scala/scala/async/Async.scala
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2012 Typesafe Inc. <http://www.typesafe.com>
- */
-
-package scala.async
-
-import scala.language.experimental.macros
-import scala.reflect.macros.Context
-import scala.reflect.internal.annotations.compileTimeOnly
-
-object Async extends AsyncBase {
-
- import scala.concurrent.Future
-
- lazy val futureSystem = ScalaConcurrentFutureSystem
- type FS = ScalaConcurrentFutureSystem.type
-
- def async[T](body: T) = macro asyncImpl[T]
-
- override def asyncImpl[T: c.WeakTypeTag](c: Context)(body: c.Expr[T]): c.Expr[Future[T]] = super.asyncImpl[T](c)(body)
-}
-
-object AsyncId extends AsyncBase {
- lazy val futureSystem = IdentityFutureSystem
- type FS = IdentityFutureSystem.type
-
- def async[T](body: T) = macro asyncImpl[T]
-
- override def asyncImpl[T: c.WeakTypeTag](c: Context)(body: c.Expr[T]): c.Expr[T] = super.asyncImpl[T](c)(body)
-}
-
-/**
- * A base class for the `async` macro. Subclasses must provide:
- *
- * - Concrete types for a given future system
- * - Tree manipulations to create and complete the equivalent of Future and Promise
- * in that system.
- * - The `async` macro declaration itself, and a forwarder for the macro implementation.
- * (The latter is temporarily needed to workaround bug SI-6650 in the macro system)
- *
- * The default implementation, [[scala.async.Async]], binds the macro to `scala.concurrent._`.
- */
-abstract class AsyncBase {
- self =>
-
- type FS <: FutureSystem
- val futureSystem: FS
-
- /**
- * A call to `await` must be nested in an enclosing `async` block.
- *
- * A call to `await` does not block the current thread, rather it is a delimiter
- * used by the enclosing `async` macro. Code following the `await`
- * call is executed asynchronously, when the argument of `await` has been completed.
- *
- * @param awaitable the future from which a value is awaited.
- * @tparam T the type of that value.
- * @return the value.
- */
- @compileTimeOnly("`await` must be enclosed in an `async` block")
- def await[T](awaitable: futureSystem.Fut[T]): T = ???
-
- protected[async] def fallbackEnabled = false
-
- def asyncImpl[T: c.WeakTypeTag](c: Context)(body: c.Expr[T]): c.Expr[futureSystem.Fut[T]] = {
- import c.universe._
-
- val analyzer = AsyncAnalysis[c.type](c, this)
- val utils = TransformUtils[c.type](c)
- import utils.{name, defn}
-
- analyzer.reportUnsupportedAwaits(body.tree)
-
- // Transform to A-normal form:
- // - no await calls in qualifiers or arguments,
- // - if/match only used in statement position.
- val anfTree: Block = {
- val anf = AnfTransform[c.type](c)
- val restored = utils.restorePatternMatchingFunctions(body.tree)
- val stats1 :+ expr1 = anf(restored)
- val block = Block(stats1, expr1)
- c.typeCheck(block).asInstanceOf[Block]
- }
-
- // Analyze the block to find locals that will be accessed from multiple
- // states of our generated state machine, e.g. a value assigned before
- // an `await` and read afterwards.
- val renameMap: Map[Symbol, TermName] = {
- analyzer.defTreesUsedInSubsequentStates(anfTree).map {
- vd =>
- (vd.symbol, name.fresh(vd.name.toTermName))
- }.toMap
- }
-
- val builder = ExprBuilder[c.type, futureSystem.type](c, self.futureSystem, anfTree)
- import builder.futureSystemOps
- val asyncBlock: builder.AsyncBlock = builder.build(anfTree, renameMap)
- import asyncBlock.asyncStates
- logDiagnostics(c)(anfTree, asyncStates.map(_.toString))
-
- // Important to retain the original declaration order here!
- val localVarTrees = anfTree.collect {
- case vd@ValDef(_, _, tpt, _) if renameMap contains vd.symbol =>
- utils.mkVarDefTree(tpt.tpe, renameMap(vd.symbol))
- case dd@DefDef(mods, name, tparams, vparamss, tpt, rhs) if renameMap contains dd.symbol =>
- DefDef(mods, renameMap(dd.symbol), tparams, vparamss, tpt, c.resetAllAttrs(utils.substituteNames(rhs, renameMap)))
- }
-
- val onCompleteHandler = {
- Function(
- List(ValDef(Modifiers(Flag.PARAM), name.tr, TypeTree(defn.TryAnyType), EmptyTree)),
- asyncBlock.onCompleteHandler)
- }
- val resumeFunTree = asyncBlock.resumeFunTree[T]
-
- val stateMachineType = utils.applied("scala.async.StateMachine", List(futureSystemOps.promType[T], futureSystemOps.execContextType))
-
- lazy val stateMachine: ClassDef = {
- val body: List[Tree] = {
- val stateVar = ValDef(Modifiers(Flag.MUTABLE), name.state, TypeTree(definitions.IntTpe), Literal(Constant(0)))
- val result = ValDef(NoMods, name.result, TypeTree(futureSystemOps.promType[T]), futureSystemOps.createProm[T].tree)
- val execContext = ValDef(NoMods, name.execContext, TypeTree(), futureSystemOps.execContext.tree)
- val applyDefDef: DefDef = {
- val applyVParamss = List(List(ValDef(Modifiers(Flag.PARAM), name.tr, TypeTree(defn.TryAnyType), EmptyTree)))
- val applyBody = asyncBlock.onCompleteHandler
- DefDef(NoMods, name.apply, Nil, applyVParamss, TypeTree(definitions.UnitTpe), applyBody)
- }
- val apply0DefDef: DefDef = {
- // We extend () => Unit so we can pass this class as the by-name argument to `Future.apply`.
- // See SI-1247 for the the optimization that avoids creatio
- val applyVParamss = List(List(ValDef(Modifiers(Flag.PARAM), name.tr, TypeTree(defn.TryAnyType), EmptyTree)))
- val applyBody = asyncBlock.onCompleteHandler
- DefDef(NoMods, name.apply, Nil, Nil, TypeTree(definitions.UnitTpe), Apply(Ident(name.resume), Nil))
- }
- List(utils.emptyConstructor, stateVar, result, execContext) ++ localVarTrees ++ List(resumeFunTree, applyDefDef, apply0DefDef)
- }
- val template = {
- Template(List(stateMachineType), emptyValDef, body)
- }
- ClassDef(NoMods, name.stateMachineT, Nil, template)
- }
-
- def selectStateMachine(selection: TermName) = Select(Ident(name.stateMachine), selection)
-
- val code: c.Expr[futureSystem.Fut[T]] = {
- val isSimple = asyncStates.size == 1
- val tree =
- if (isSimple)
- Block(Nil, futureSystemOps.spawn(body.tree)) // generate lean code for the simple case of `async { 1 + 1 }`
- else {
- Block(List[Tree](
- stateMachine,
- ValDef(NoMods, name.stateMachine, stateMachineType, Apply(Select(New(Ident(name.stateMachineT)), nme.CONSTRUCTOR), Nil)),
- futureSystemOps.spawn(Apply(selectStateMachine(name.apply), Nil))
- ),
- futureSystemOps.promiseToFuture(c.Expr[futureSystem.Prom[T]](selectStateMachine(name.result))).tree)
- }
- c.Expr[futureSystem.Fut[T]](tree)
- }
-
- AsyncUtils.vprintln(s"async state machine transform expands to:\n ${code.tree}")
- code
- }
-
- def logDiagnostics(c: Context)(anfTree: c.Tree, states: Seq[String]) {
- def location = try {
- c.macroApplication.pos.source.path
- } catch {
- case _: UnsupportedOperationException =>
- c.macroApplication.pos.toString
- }
-
- AsyncUtils.vprintln(s"In file '$location':")
- AsyncUtils.vprintln(s"${c.macroApplication}")
- AsyncUtils.vprintln(s"ANF transform expands to:\n $anfTree")
- states foreach (s => AsyncUtils.vprintln(s))
- }
-}
-
-/** Internal class used by the `async` macro; should not be manually extended by client code */
-abstract class StateMachine[Result, EC] extends (scala.util.Try[Any] => Unit) with (() => Unit) {
- def result$async: Result
-
- def execContext$async: EC
-}