From 32500577c34c2eff39e06620a7027c27be31b9e4 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 13 Nov 2013 18:28:45 +0100 Subject: Abstract over use of scala.util.Try Custom implementation of the async macro may choose to use a different data type to represent `Throwable | A`. --- src/main/scala/scala/async/internal/AsyncId.scala | 20 +++++++++++++-- .../scala/async/internal/AsyncTransform.scala | 2 +- .../scala/scala/async/internal/ExprBuilder.scala | 12 ++++----- .../scala/scala/async/internal/FutureSystem.scala | 29 ++++++++++++++++++++-- 4 files changed, 52 insertions(+), 11 deletions(-) diff --git a/src/main/scala/scala/async/internal/AsyncId.scala b/src/main/scala/scala/async/internal/AsyncId.scala index a794f93..5343a82 100644 --- a/src/main/scala/scala/async/internal/AsyncId.scala +++ b/src/main/scala/scala/async/internal/AsyncId.scala @@ -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 @@ -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 { @@ -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) + } } } diff --git a/src/main/scala/scala/async/internal/AsyncTransform.scala b/src/main/scala/scala/async/internal/AsyncTransform.scala index 043822b..352ef71 100644 --- a/src/main/scala/scala/async/internal/AsyncTransform.scala +++ b/src/main/scala/scala/async/internal/AsyncTransform.scala @@ -27,7 +27,7 @@ trait AsyncTransform { 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(()))) } diff --git a/src/main/scala/scala/async/internal/ExprBuilder.scala b/src/main/scala/scala/async/internal/ExprBuilder.scala index 16e95dd..85e0953 100644 --- a/src/main/scala/scala/async/internal/ExprBuilder.scala +++ b/src/main/scala/scala/async/internal/ExprBuilder.scala @@ -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) @@ -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)) ) @@ -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 { @@ -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)) /** diff --git a/src/main/scala/scala/async/internal/FutureSystem.scala b/src/main/scala/scala/async/internal/FutureSystem.scala index c064474..166affe 100644 --- a/src/main/scala/scala/async/internal/FutureSystem.scala +++ b/src/main/scala/scala/async/internal/FutureSystem.scala @@ -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 @@ -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 */ @@ -43,15 +46,21 @@ 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 } @@ -66,6 +75,7 @@ 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 @@ -73,6 +83,7 @@ object ScalaConcurrentFutureSystem extends FutureSystem { 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 { @@ -96,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) + } } } -- cgit v1.2.3