1
1
package scala .js
2
2
3
3
import virtualization .lms .common ._
4
- import concurrent .Future
5
- import java .io .PrintWriter
4
+ import concurrent .{Promise , Future }
6
5
7
- trait FutureOps { this : Base =>
6
+ trait FutureOps { this : Base with IfThenElse =>
8
7
9
- trait FutureOpsBase [+ A ] {
10
- def map [B : Manifest ](f : Rep [A ] => Rep [B ]): Rep [Future [B ]]
11
- def flatMap [B : Manifest ](f : Rep [A ] => Rep [Future [B ]]): Rep [Future [B ]]
12
- def foreach (f : Rep [A ] => Rep [Unit ]): Rep [Unit ]
13
- def withFilter (f : Rep [A ] => Rep [Boolean ]): Rep [Future [A ]]
8
+ def promise [A : Manifest ]: Rep [Promise [A ]]
9
+ implicit class PromiseOps [A : Manifest ](p : Rep [Promise [A ]]) extends Serializable {
10
+ def put (v : Rep [A ]) = promise_put(p, v)
11
+ def future = promise_future(p)
14
12
}
15
13
16
- type FutureOpsCls [ + A ] <: FutureOpsBase [ A ]
17
- implicit def FutureOpsCls [A : Manifest ](f : Rep [Future [A ]]): FutureOpsCls [ A ]
14
+ def promise_put [ A : Manifest ]( p : Rep [ Promise [ A ]], v : Rep [ A ]) : Rep [ Unit ]
15
+ def promise_future [A : Manifest ](p : Rep [Promise [A ]]): Rep [ Future [ A ] ]
18
16
19
- def future [A : Manifest ](a : Rep [A ]): Rep [Future [A ]] // Wrong: should be a by-name parameter
20
- }
21
-
22
- trait FutureOpsExp extends FutureOps with EffectExp {
23
-
24
- case class FuturePure [A ](a : Exp [A ]) extends Def [Future [A ]]
25
- case class FutureMap [A , B ](a : Exp [Future [A ]], x : Sym [A ], b : Block [B ]) extends Def [Future [B ]]
26
- case class FutureFlatMap [A , B ](a : Exp [Future [A ]], x : Sym [A ], b : Block [Future [B ]]) extends Def [Future [B ]]
27
- case class FutureForeach [A ](a : Exp [Future [A ]], x : Sym [A ], b : Block [Unit ]) extends Def [Unit ]
28
- case class FutureFilter [A ](a : Exp [Future [A ]], x : Sym [A ], b : Block [Boolean ]) extends Def [Future [A ]]
29
17
30
- def future [A : Manifest ](a : Rep [A ]) = FuturePure (a)
31
-
32
- implicit class FutureOpsCls [ + A : Manifest ]( a : Exp [ Future [ A ]]) extends FutureOpsBase [ A ] {
33
- def map [B : Manifest ](f : Exp [A ] => Exp [B ]) = {
34
- val x = fresh[ A ]
35
- val b = reifyEffects (f(x ))
36
- reflectEffect( FutureMap (a, x, b), summarizeEffects(b).star)
18
+ def future [A : Manifest ](a : Rep [A ]): Rep [ Future [ A ]]
19
+ implicit class FutureOps [ A : Manifest ]( fa : Rep [ Future [ A ]]) extends Serializable {
20
+ def foreach ( f : Rep [ A ] => Rep [ Unit ]) : Rep [ Unit ] = future_foreach(fa, f)
21
+ def map [B : Manifest ](f : Rep [A ] => Rep [B ]): Rep [ Future [ B ]] = {
22
+ val pb = promise[ B ]
23
+ for (a <- fa) pb.put (f(a ))
24
+ pb.future
37
25
}
38
-
39
- def flatMap [B : Manifest ](f : Exp [A ] => Exp [Future [B ]]) = {
40
- val x = fresh[A ]
41
- val b = reifyEffects(f(x))
42
- reflectEffect(FutureFlatMap (a, x, b), summarizeEffects(b).star)
26
+ def flatMap [B : Manifest ](f : Rep [A ] => Rep [Future [B ]]): Rep [Future [B ]] = {
27
+ val pb = promise[B ]
28
+ for {
29
+ a <- fa
30
+ b <- f(a)
31
+ } pb.put(b)
32
+ pb.future
43
33
}
44
-
45
- def foreach (f : Exp [A ] => Exp [Unit ]) = {
46
- val x = fresh[A ]
47
- val b = reifyEffects(f(x))
48
- reflectEffect(FutureForeach (a, x, b), summarizeEffects(b).star)
49
- }
50
-
51
- def withFilter (f : Exp [A ] => Exp [Boolean ]) = {
52
- val x = fresh[A ]
53
- val b = reifyEffects(f(x))
54
- reflectEffect(FutureFilter (a, x, b), summarizeEffects(b).star)
34
+ def withFilter (f : Rep [A ] => Rep [Boolean ]): Rep [Future [A ]] = {
35
+ val pa = promise[A ]
36
+ for (a <- fa) if (f(a)) pa.put(a)
37
+ pa.future
55
38
}
56
39
}
57
40
41
+ def future_foreach [A : Manifest ](fa : Rep [Future [A ]], f : Rep [A ] => Rep [Unit ]): Rep [Unit ]
42
+ }
43
+
44
+ trait FutureOpsExp extends FutureOps with EffectExp { this : IfThenElse with Functions =>
58
45
59
- override def syms (e : Any ) = e match {
60
- case FutureMap (a, _, b) => syms(a) ++ syms(b)
61
- case FutureFlatMap (a, _, b) => syms(a) ++ syms(b)
62
- case FutureForeach (a, _, b) => syms(a) ++ syms(b)
63
- case FutureFilter (a, _, b) => syms(a) ++ syms(b)
64
- case _ => super .syms(e)
65
- }
46
+ case class PromiseNew [A ](value : Option [Exp [A ]]) extends Def [Promise [A ]]
47
+ case class PromisePut [A ](p : Exp [Promise [A ]], v : Exp [A ]) extends Def [Unit ]
48
+ case class PromiseFuture [A ](p : Exp [Promise [A ]]) extends Def [Future [A ]]
49
+ case class FutureForeach [A ](fa : Exp [Future [A ]], f : Exp [A => Unit ]) extends Def [Unit ]
66
50
67
- override def boundSyms (e : Any ) = e match {
68
- case FutureMap (_, x, b) => x +: effectSyms(b)
69
- case FutureFlatMap (_, x, b) => x +: effectSyms(b)
70
- case FutureForeach (_, x, b) => x +: effectSyms(b)
71
- case FutureFilter (_, x, b) => x +: effectSyms(b)
72
- case _ => super .boundSyms(e)
73
- }
51
+ def promise [A : Manifest ] = reflectEffect(PromiseNew [A ](None ))
52
+ def promise_put [A : Manifest ](p : Exp [Promise [A ]], v : Exp [A ]) = reflectEffect(PromisePut (p, v))
53
+ def promise_future [A : Manifest ](p : Exp [Promise [A ]]) = PromiseFuture (p)
54
+
55
+ def future [A : Manifest ](a : Exp [A ]) = (PromiseNew (Some (a)): Exp [Promise [A ]]).future
56
+ def future_foreach [A : Manifest ](fa : Exp [Future [A ]], f : Exp [A ] => Exp [Unit ]) = reflectEffect(FutureForeach (fa, f))
74
57
75
- override def symsFreq (e : Any ) = e match {
76
- case FutureMap (a, _, b) => freqNormal(a) ++ freqNormal(b)
77
- case FutureFlatMap (a, _, b) => freqNormal(a) ++ freqNormal(b)
78
- case FutureForeach (a, _, b) => freqNormal(a) ++ freqNormal(b)
79
- case FutureFilter (a, _, b) => freqNormal(a) ++ freqNormal(b)
80
- case _ => super .symsFreq(e)
81
- }
82
58
}
83
59
84
60
trait JSGenFutureOps extends JSNestedCodegen {
85
61
val IR : FutureOpsExp
86
62
import IR ._
87
63
88
64
override def emitNode (sym : Sym [Any ], rhs : Def [Any ]) = rhs match {
89
- case FuturePure (a) =>
90
- emitValDef(sym, " new Promise(" + quote(a) + " )" )
91
- case FutureMap (a, x, b) =>
92
- emitValDef(sym, " new Promise()" )
93
- stream.println(quote(a) + " .onComplete(function (" + quote(x) + " ) {" )
94
- emitBlock(b)
95
- stream.println(quote(sym) + " .complete(" + quote(getBlockResult(b)) + " );" )
96
- stream.println(" });" )
97
- case FutureFlatMap (a, x, b) => // TODO optimize
98
- emitValDef(sym, " new Promise()" )
99
- stream.println(quote(a) + " .onComplete(function (" + quote(x) + " ) {" )
100
- emitBlock(b)
101
- stream.println(quote(getBlockResult(b)) + " .onComplete(function (v) {" )
102
- stream.println(quote(sym) + " .complete(v);" )
103
- stream.println(" });" )
104
- stream.println(" });" )
105
- case FutureForeach (a, x, b) =>
106
- stream.println(" var " + quote(sym) + " = " + quote(a) + " .onComplete(function (" + quote(x) + " ) {" )
107
- emitBlock(b)
108
- stream.println(" });" )
109
- case FutureFilter (a, x, b) =>
110
- emitValDef(sym, " new Promise()" )
111
- stream.println(quote(a) + " .onComplete(function (" + quote(x) + " ) {" )
112
- emitBlock(b)
113
- stream.println(" if (" + quote(getBlockResult(b)) + " === true) {" )
114
- stream.println(quote(sym) + " .complete(" + quote(getBlockResult(b)) + " );" )
65
+ case PromiseNew (maybeA) =>
66
+ maybeA.fold(emitValDef(sym, " { v: null, cs: [] }" ))(a => emitValDef(sym, " { v: " + quote(a) + " , cs: [] }" ))
67
+ case PromisePut (p, v) =>
68
+ val i = fresh[Int ]
69
+ val n = fresh[Int ]
70
+ stream.println(" if (" + quote(p) + " .v !== null) {" )
71
+ stream.println(" throw 'This Promise has already been completed';" )
72
+ stream.println(" } else {" )
73
+ stream.println(quote(p) + " .v = " + quote(v) + " ;" )
74
+ stream.println(" for (var " + quote(i) + " = 0, " + quote(n) + " = " + quote(p) + " .cs.length ; " + quote(i) + " < " + quote(n) + " ; " + quote(i) + " ++) {" )
75
+ stream.println(quote(p) + " .cs[" + quote(i) + " ](" + quote(v) + " );" )
115
76
stream.println(" }" )
116
- stream.println(" });" )
77
+ stream.println(" }" )
78
+ emitValDef(sym, quote(()))
79
+ case PromiseFuture (p) =>
80
+ emitValDef(sym, quote(p))
81
+ case FutureForeach (p, f) =>
82
+ stream.println(" if (" + quote(p) + " .v === null) {" )
83
+ stream.println(quote(p) + " .cs.push(" + quote(f) + " );" )
84
+ stream.println(" } else {" )
85
+ stream.println(quote(f) + " (" + quote(p) + " .v);" )
86
+ stream.println(" }" )
87
+ emitValDef(sym, quote(()))
117
88
case _ => super .emitNode(sym, rhs)
118
89
}
119
90
120
- def emitDataStructures (out : PrintWriter ) {
121
- // http://jsbin.com/ebecuk/5/edit
122
- out.println(""" var Promise = function (value) {
123
- | if (value !== undefined) {
124
- | this.value = value;
125
- | }
126
- | this.callbacks = [];
127
- |};
128
- |Promise.prototype.complete = function (value) {
129
- | if (this.value !== undefined) {
130
- | throw "This promise has already been completed";
131
- | } else {
132
- | this.value = value;
133
- | for (var i = 0, n = this.callbacks.length ; i < n ; i++) {
134
- | var callback = this.callbacks[i];
135
- | callback(value);
136
- | }
137
- | }
138
- |};
139
- |Promise.prototype.onComplete = function (callback) {
140
- | if (this.value === undefined) {
141
- | this.callbacks.push(callback);
142
- | } else {
143
- | callback(this.value);
144
- | }
145
- |};
146
- |""" .stripMargin)
147
- out.flush()
148
- }
149
-
150
91
}
0 commit comments