aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/scala/async/iterators/Async.scala
blob: 897bc8eba0c30be57480d5d5bce3c4aee95a7e3c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package scala.async.iterators

import scala.language.experimental.macros

import scala.reflect.macros.Context
import scala.async.{ AsyncBase, FutureSystem }
import scala.concurrent.{ Promise, Future, ExecutionContext }
import scala.util.Try

object Async extends AsyncBase {

  lazy val futureSystem = IteratorsFutureSystem
  type FS = IteratorsFutureSystem.type

  def async[T](body: T) = macro asyncImpl[T]

  override def asyncImpl[T: c.WeakTypeTag](c: Context)(body: c.Expr[T]): c.Expr[IteratorState[T]] = super.asyncImpl[T](c)(body)

}

object IteratorsFutureSystem extends FutureSystem {
  type Prom[A]   = IteratorState[A]
  type Fut[A]    = IteratorState[A]
  type Result[A] = Try[A]
  type ExecContext = Unit

  def mkOps(context: Context): Ops { val c: context.type } = new Ops {
    val c: context.type = context
    import c.universe._

    def promType[A: WeakTypeTag]: Type = c.weakTypeOf[Prom[A]]

    def stateMachineType[A: WeakTypeTag]: Type =
      // The generated state machine will extend trait `IteratorState`
      c.weakTypeOf[scala.async.iterators.IteratorState[A]]

    def execContextType: Type = c.weakTypeOf[Unit]
    def resultType[A: WeakTypeTag]: Type = c.weakTypeOf[Result[A]]

    /**
     * @param tree ident referring to state machine
     */
    override def spawn(tree: Tree): Tree = {
      // don't call future here, but return state machine
      tree
    }

    def execContext: Expr[ExecContext] = c.literalUnit

    def castTo[A: WeakTypeTag](future: Expr[Fut[Any]]): Expr[Fut[A]] = ???

    def completeProm[A: WeakTypeTag](prom: Expr[Prom[A]], value: Expr[A]): Expr[Unit] = reify {
      prom.splice.result = value.splice
    }

    def completePromWithExceptionTopLevel[A: WeakTypeTag](prom: Expr[Prom[A]], exception: Expr[Throwable]): Expr[Unit] =
      reify { ??? }

    def completePromWithFailedResult[A: WeakTypeTag](prom: Expr[Prom[A]], resultName: TermName): Expr[Unit] =
      reify { () }

    def createProm[A: WeakTypeTag]: Expr[Prom[A]] = ???

    def createPromTree[A: WeakTypeTag](stateMachine: Tree): Tree = {
      // return `this` state machine
      This(tpnme.EMPTY)
    }

    def future[A: WeakTypeTag](a: Expr[A])(execContext: Expr[ExecContext]): Expr[Fut[A]] =
      reify { ??? }

    def onComplete[A, U](future: Expr[Fut[A]], fun: Expr[Result[A] => U],
                         execContext: Expr[ExecContext]): Expr[Unit] = reify {
      /* do nothing */
    }

    def promiseToFuture[A: WeakTypeTag](prom: Expr[Prom[A]]): Expr[Fut[A]] = prom

    /** `methodSym( (_: Foo).bar(null: A, null: B)` will return the symbol of `bar`, after overload resolution. */
    private def methodSym(apply: c.Expr[Any]): Symbol = {
      val tree2: Tree = c.typeCheck(apply.tree)
      tree2.collect {
        case s: SymTree if s.symbol.isMethod => s.symbol
      }.headOption.getOrElse(sys.error(s"Unable to find a method symbol in ${apply.tree}"))
    }

    lazy val Try_isFailure = methodSym(reify((null: scala.util.Try[Any]).isFailure))
    lazy val Try_get       = methodSym(reify((null: scala.util.Try[Any]).get))

    def isFailedResult(name: TermName): Expr[Boolean] =
      c.Expr[Boolean](Select(Ident(name), Try_isFailure))

    def resultValue(name: TermName, resultType: Type): Tree =
      TypeApply(Select(Select(Ident(name), Try_get), newTermName("asInstanceOf")), List(TypeTree(resultType)))

/*
    lazy val IS_result = methodSym(reify((null: scala.async.iterators.IteratorState[Any]).result))
    lazy val IS_isFailed = methodSym(reify((null: scala.async.iterators.IteratorState[Any]).isFailed))

    // <resultName> = name.result.asInstanceOf[<resultType>]
    def resultValue(name: TermName, resultType: Type): Tree =
      TypeApply(Select(Select(Ident(name), IS_result), newTermName("asInstanceOf")), List(TypeTree(resultType)))

    def isFailedResult(name: TermName): Expr[Boolean] =
      c.Expr[Boolean](Select(Ident(name), IS_isFailed))
*/
  }

}