Skip to content

Commit b0a4fdf

Browse files
committed
Merge pull request #42 from retronym/topic/hooks
Hooks for custom async implementations
2 parents 72848bd + 3250057 commit b0a4fdf

File tree

4 files changed

+58
-12
lines changed

4 files changed

+58
-12
lines changed

src/main/scala/scala/async/internal/AsyncId.scala

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ object IdentityFutureSystem extends FutureSystem {
5050

5151
type Fut[A] = A
5252
type ExecContext = Unit
53+
type Tryy[A] = scala.util.Try[A]
5354

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

6162
def promType[A: WeakTypeTag]: Type = weakTypeOf[Prom[A]]
63+
def tryType[A: WeakTypeTag]: Type = weakTypeOf[scala.util.Try[A]]
6264
def execContextType: Type = weakTypeOf[Unit]
6365

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

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

74-
def onComplete[A, U](future: Expr[Fut[A]], fun: Expr[scala.util.Try[A] => U],
76+
def onComplete[A, U](future: Expr[Fut[A]], fun: Expr[Tryy[A] => U],
7577
execContext: Expr[ExecContext]): Expr[Unit] = reify {
7678
fun.splice.apply(util.Success(future.splice))
7779
Expr[Unit](Literal(Constant(()))).splice
7880
}
7981

80-
def completeProm[A](prom: Expr[Prom[A]], value: Expr[scala.util.Try[A]]): Expr[Unit] = reify {
82+
def completeProm[A](prom: Expr[Prom[A]], value: Expr[Tryy[A]]): Expr[Unit] = reify {
8183
prom.splice.a = value.splice.get
8284
Expr[Unit](Literal(Constant(()))).splice
8385
}
86+
87+
def tryyIsFailure[A](tryy: Expr[Tryy[A]]): Expr[Boolean] = reify {
88+
tryy.splice.isFailure
89+
}
90+
91+
def tryyGet[A](tryy: Expr[Tryy[A]]): Expr[A] = reify {
92+
tryy.splice.get
93+
}
94+
def tryySuccess[A: WeakTypeTag](a: Expr[A]): Expr[Tryy[A]] = reify {
95+
scala.util.Success[A](a.splice)
96+
}
97+
def tryyFailure[A: WeakTypeTag](a: Expr[Throwable]): Expr[Tryy[A]] = reify {
98+
scala.util.Failure[A](a.splice)
99+
}
84100
}
85101
}

src/main/scala/scala/async/internal/AsyncTransform.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ trait AsyncTransform {
2020
// Transform to A-normal form:
2121
// - no await calls in qualifiers or arguments,
2222
// - if/match only used in statement position.
23-
val anfTree: Block = anfTransform(body)
23+
val anfTree0: Block = anfTransform(body)
24+
25+
val anfTree = futureSystemOps.postAnfTransform(anfTree0)
2426

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

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

src/main/scala/scala/async/internal/ExprBuilder.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ trait ExprBuilder {
8989
val tryGetTree =
9090
Assign(
9191
Ident(awaitable.resultName),
92-
TypeApply(Select(Select(Ident(symLookup.applyTrParam), Try_get), newTermName("asInstanceOf")), List(TypeTree(awaitable.resultType)))
92+
TypeApply(Select(futureSystemOps.tryyGet[T](Expr[futureSystem.Tryy[T]](Ident(symLookup.applyTrParam))).tree, newTermName("asInstanceOf")), List(TypeTree(awaitable.resultType)))
9393
)
9494

9595
/* if (tr.isFailure)
@@ -101,12 +101,12 @@ trait ExprBuilder {
101101
* }
102102
*/
103103
val ifIsFailureTree =
104-
If(Select(Ident(symLookup.applyTrParam), Try_isFailure),
104+
If(futureSystemOps.tryyIsFailure(Expr[futureSystem.Tryy[T]](Ident(symLookup.applyTrParam))).tree,
105105
futureSystemOps.completeProm[T](
106106
Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)),
107-
Expr[scala.util.Try[T]](
107+
Expr[futureSystem.Tryy[T]](
108108
TypeApply(Select(Ident(symLookup.applyTrParam), newTermName("asInstanceOf")),
109-
List(TypeTree(weakTypeOf[scala.util.Try[T]]))))).tree,
109+
List(TypeTree(futureSystemOps.tryType[T]))))).tree,
110110
Block(List(tryGetTree, mkStateTree(nextState, symLookup)), mkResumeApply(symLookup))
111111
)
112112

@@ -325,7 +325,7 @@ trait ExprBuilder {
325325
val lastState = asyncStates.last
326326
val lastStateBody = Expr[T](lastState.body)
327327
val rhs = futureSystemOps.completeProm(
328-
Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)), reify(scala.util.Success[T](lastStateBody.splice)))
328+
Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)), futureSystemOps.tryySuccess[T](lastStateBody))
329329
mkHandlerCase(lastState.state, rhs.tree)
330330
}
331331
asyncStates.toList match {
@@ -368,7 +368,7 @@ trait ExprBuilder {
368368
Apply(Ident(defn.NonFatalClass), List(Ident(name.t))), {
369369
val t = Expr[Throwable](Ident(name.t))
370370
futureSystemOps.completeProm[T](
371-
Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)), reify(scala.util.Failure(t.splice))).tree
371+
Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)), futureSystemOps.tryyFailure[T](t)).tree
372372
})), EmptyTree))
373373

374374
/**

src/main/scala/scala/async/internal/FutureSystem.scala

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ trait FutureSystem {
2323
type Fut[A]
2424
/** An execution context, required to create or register an on completion callback on a Future. */
2525
type ExecContext
26+
/** Any data type isomorphic to scala.util.Try. */
27+
type Tryy[T]
2628

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

3335
def promType[A: WeakTypeTag]: Type
36+
def tryType[A: WeakTypeTag]: Type
3437
def execContextType: Type
3538

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

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

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

5255
def spawn(tree: Tree, execContext: Tree): Tree =
5356
future(Expr[Unit](tree))(Expr[ExecContext](execContext)).tree
57+
58+
def tryyIsFailure[A](tryy: Expr[Tryy[A]]): Expr[Boolean]
59+
60+
def tryyGet[A](tryy: Expr[Tryy[A]]): Expr[A]
61+
def tryySuccess[A: WeakTypeTag](a: Expr[A]): Expr[Tryy[A]]
62+
def tryyFailure[A: WeakTypeTag](a: Expr[Throwable]): Expr[Tryy[A]]
63+
64+
/** A hook for custom macros to transform the tree post-ANF transform */
65+
def postAnfTransform(tree: Block): Block = tree
5466
}
5567

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

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

7083
import universe._
7184

7285
def promType[A: WeakTypeTag]: Type = weakTypeOf[Promise[A]]
86+
def tryType[A: WeakTypeTag]: Type = weakTypeOf[scala.util.Try[A]]
7387
def execContextType: Type = weakTypeOf[ExecutionContext]
7488

7589
def createProm[A: WeakTypeTag]: Expr[Prom[A]] = reify {
@@ -93,5 +107,19 @@ object ScalaConcurrentFutureSystem extends FutureSystem {
93107
prom.splice.complete(value.splice)
94108
Expr[Unit](Literal(Constant(()))).splice
95109
}
110+
111+
def tryyIsFailure[A](tryy: Expr[scala.util.Try[A]]): Expr[Boolean] = reify {
112+
tryy.splice.isFailure
113+
}
114+
115+
def tryyGet[A](tryy: Expr[Tryy[A]]): Expr[A] = reify {
116+
tryy.splice.get
117+
}
118+
def tryySuccess[A: WeakTypeTag](a: Expr[A]): Expr[Tryy[A]] = reify {
119+
scala.util.Success[A](a.splice)
120+
}
121+
def tryyFailure[A: WeakTypeTag](a: Expr[Throwable]): Expr[Tryy[A]] = reify {
122+
scala.util.Failure[A](a.splice)
123+
}
96124
}
97125
}

0 commit comments

Comments
 (0)