Skip to content

Hooks for custom async implementations #42

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 20, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions src/main/scala/scala/async/internal/AsyncId.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ object IdentityFutureSystem extends FutureSystem {

type Fut[A] = A
type ExecContext = Unit
type Tryy[A] = scala.util.Try[A]

def mkOps(c: SymbolTable): Ops {val universe: c.type} = new Ops {
val universe: c.type = c
Expand All @@ -59,6 +60,7 @@ object IdentityFutureSystem extends FutureSystem {
def execContext: Expr[ExecContext] = Expr[Unit](Literal(Constant(())))

def promType[A: WeakTypeTag]: Type = weakTypeOf[Prom[A]]
def tryType[A: WeakTypeTag]: Type = weakTypeOf[scala.util.Try[A]]
def execContextType: Type = weakTypeOf[Unit]

def createProm[A: WeakTypeTag]: Expr[Prom[A]] = reify {
Expand All @@ -71,15 +73,29 @@ object IdentityFutureSystem extends FutureSystem {

def future[A: WeakTypeTag](t: Expr[A])(execContext: Expr[ExecContext]) = t

def onComplete[A, U](future: Expr[Fut[A]], fun: Expr[scala.util.Try[A] => U],
def onComplete[A, U](future: Expr[Fut[A]], fun: Expr[Tryy[A] => U],
execContext: Expr[ExecContext]): Expr[Unit] = reify {
fun.splice.apply(util.Success(future.splice))
Expr[Unit](Literal(Constant(()))).splice
}

def completeProm[A](prom: Expr[Prom[A]], value: Expr[scala.util.Try[A]]): Expr[Unit] = reify {
def completeProm[A](prom: Expr[Prom[A]], value: Expr[Tryy[A]]): Expr[Unit] = reify {
prom.splice.a = value.splice.get
Expr[Unit](Literal(Constant(()))).splice
}

def tryyIsFailure[A](tryy: Expr[Tryy[A]]): Expr[Boolean] = reify {
tryy.splice.isFailure
}

def tryyGet[A](tryy: Expr[Tryy[A]]): Expr[A] = reify {
tryy.splice.get
}
def tryySuccess[A: WeakTypeTag](a: Expr[A]): Expr[Tryy[A]] = reify {
scala.util.Success[A](a.splice)
}
def tryyFailure[A: WeakTypeTag](a: Expr[Throwable]): Expr[Tryy[A]] = reify {
scala.util.Failure[A](a.splice)
}
}
}
6 changes: 4 additions & 2 deletions src/main/scala/scala/async/internal/AsyncTransform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ trait AsyncTransform {
// Transform to A-normal form:
// - no await calls in qualifiers or arguments,
// - if/match only used in statement position.
val anfTree: Block = anfTransform(body)
val anfTree0: Block = anfTransform(body)

val anfTree = futureSystemOps.postAnfTransform(anfTree0)

val resumeFunTreeDummyBody = DefDef(Modifiers(), name.resume, Nil, List(Nil), Ident(definitions.UnitClass), Literal(Constant(())))

val applyDefDefDummyBody: DefDef = {
val applyVParamss = List(List(ValDef(Modifiers(Flag.PARAM), name.tr, TypeTree(defn.TryAnyType), EmptyTree)))
val applyVParamss = List(List(ValDef(Modifiers(Flag.PARAM), name.tr, TypeTree(futureSystemOps.tryType[Any]), EmptyTree)))
DefDef(NoMods, name.apply, Nil, applyVParamss, TypeTree(definitions.UnitTpe), Literal(Constant(())))
}

Expand Down
12 changes: 6 additions & 6 deletions src/main/scala/scala/async/internal/ExprBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ trait ExprBuilder {
val tryGetTree =
Assign(
Ident(awaitable.resultName),
TypeApply(Select(Select(Ident(symLookup.applyTrParam), Try_get), newTermName("asInstanceOf")), List(TypeTree(awaitable.resultType)))
TypeApply(Select(futureSystemOps.tryyGet[T](Expr[futureSystem.Tryy[T]](Ident(symLookup.applyTrParam))).tree, newTermName("asInstanceOf")), List(TypeTree(awaitable.resultType)))
)

/* if (tr.isFailure)
Expand All @@ -101,12 +101,12 @@ trait ExprBuilder {
* }
*/
val ifIsFailureTree =
If(Select(Ident(symLookup.applyTrParam), Try_isFailure),
If(futureSystemOps.tryyIsFailure(Expr[futureSystem.Tryy[T]](Ident(symLookup.applyTrParam))).tree,
futureSystemOps.completeProm[T](
Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)),
Expr[scala.util.Try[T]](
Expr[futureSystem.Tryy[T]](
TypeApply(Select(Ident(symLookup.applyTrParam), newTermName("asInstanceOf")),
List(TypeTree(weakTypeOf[scala.util.Try[T]]))))).tree,
List(TypeTree(futureSystemOps.tryType[T]))))).tree,
Block(List(tryGetTree, mkStateTree(nextState, symLookup)), mkResumeApply(symLookup))
)

Expand Down Expand Up @@ -325,7 +325,7 @@ trait ExprBuilder {
val lastState = asyncStates.last
val lastStateBody = Expr[T](lastState.body)
val rhs = futureSystemOps.completeProm(
Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)), reify(scala.util.Success[T](lastStateBody.splice)))
Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)), futureSystemOps.tryySuccess[T](lastStateBody))
mkHandlerCase(lastState.state, rhs.tree)
}
asyncStates.toList match {
Expand Down Expand Up @@ -368,7 +368,7 @@ trait ExprBuilder {
Apply(Ident(defn.NonFatalClass), List(Ident(name.t))), {
val t = Expr[Throwable](Ident(name.t))
futureSystemOps.completeProm[T](
Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)), reify(scala.util.Failure(t.splice))).tree
Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)), futureSystemOps.tryyFailure[T](t)).tree
})), EmptyTree))

/**
Expand Down
32 changes: 30 additions & 2 deletions src/main/scala/scala/async/internal/FutureSystem.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ trait FutureSystem {
type Fut[A]
/** An execution context, required to create or register an on completion callback on a Future. */
type ExecContext
/** Any data type isomorphic to scala.util.Try. */
type Tryy[T]

trait Ops {
val universe: reflect.internal.SymbolTable
Expand All @@ -31,6 +33,7 @@ trait FutureSystem {
def Expr[T: WeakTypeTag](tree: Tree): Expr[T] = universe.Expr[T](rootMirror, universe.FixedMirrorTreeCreator(rootMirror, tree))

def promType[A: WeakTypeTag]: Type
def tryType[A: WeakTypeTag]: Type
def execContextType: Type

/** Create an empty promise */
Expand All @@ -43,14 +46,23 @@ trait FutureSystem {
def future[A: WeakTypeTag](a: Expr[A])(execContext: Expr[ExecContext]): Expr[Fut[A]]

/** Register an call back to run on completion of the given future */
def onComplete[A, U](future: Expr[Fut[A]], fun: Expr[scala.util.Try[A] => U],
def onComplete[A, U](future: Expr[Fut[A]], fun: Expr[Tryy[A] => U],
execContext: Expr[ExecContext]): Expr[Unit]

/** Complete a promise with a value */
def completeProm[A](prom: Expr[Prom[A]], value: Expr[scala.util.Try[A]]): Expr[Unit]
def completeProm[A](prom: Expr[Prom[A]], value: Expr[Tryy[A]]): Expr[Unit]

def spawn(tree: Tree, execContext: Tree): Tree =
future(Expr[Unit](tree))(Expr[ExecContext](execContext)).tree

def tryyIsFailure[A](tryy: Expr[Tryy[A]]): Expr[Boolean]

def tryyGet[A](tryy: Expr[Tryy[A]]): Expr[A]
def tryySuccess[A: WeakTypeTag](a: Expr[A]): Expr[Tryy[A]]
def tryyFailure[A: WeakTypeTag](a: Expr[Throwable]): Expr[Tryy[A]]

/** A hook for custom macros to transform the tree post-ANF transform */
def postAnfTransform(tree: Block): Block = tree
}

def mkOps(c: SymbolTable): Ops { val universe: c.type }
Expand All @@ -63,13 +75,15 @@ object ScalaConcurrentFutureSystem extends FutureSystem {
type Prom[A] = Promise[A]
type Fut[A] = Future[A]
type ExecContext = ExecutionContext
type Tryy[A] = scala.util.Try[A]

def mkOps(c: SymbolTable): Ops {val universe: c.type} = new Ops {
val universe: c.type = c

import universe._

def promType[A: WeakTypeTag]: Type = weakTypeOf[Promise[A]]
def tryType[A: WeakTypeTag]: Type = weakTypeOf[scala.util.Try[A]]
def execContextType: Type = weakTypeOf[ExecutionContext]

def createProm[A: WeakTypeTag]: Expr[Prom[A]] = reify {
Expand All @@ -93,5 +107,19 @@ object ScalaConcurrentFutureSystem extends FutureSystem {
prom.splice.complete(value.splice)
Expr[Unit](Literal(Constant(()))).splice
}

def tryyIsFailure[A](tryy: Expr[scala.util.Try[A]]): Expr[Boolean] = reify {
tryy.splice.isFailure
}

def tryyGet[A](tryy: Expr[Tryy[A]]): Expr[A] = reify {
tryy.splice.get
}
def tryySuccess[A: WeakTypeTag](a: Expr[A]): Expr[Tryy[A]] = reify {
scala.util.Success[A](a.splice)
}
def tryyFailure[A: WeakTypeTag](a: Expr[Throwable]): Expr[Tryy[A]] = reify {
scala.util.Failure[A](a.splice)
}
}
}