on 294fdfd help sign in
243 lines 7.1 kB history raw
2Elm.Native.Signal = function(elm) {
3 'use strict';
5 elm.Native = elm.Native || {};
6 if (elm.Native.Signal) return elm.Native.Signal;
7
8 var Utils = Elm.Native.Utils(elm);
9 var Either = Elm.Either(elm);
10 var foldl1 = Elm.List(elm).foldl1;
13 function send(node, timestep, changed) {
14 var kids = node.kids;
15 for (var i = kids.length; i--; ) {
16 kids[i].recv(timestep, changed, node.id);
17 }
18 }
20 function Input(base) {
21 this.id = Utils.guid();
22 this.value = base;
23 this.kids = [];
24 this.defaultNumberOfKids = 0;
25 this.recv = function(timestep, eid, v) {
26 var changed = eid === this.id;
27 if (changed) { this.value = v; }
28 send(this, timestep, changed);
29 return changed;
30 };
31 elm.inputs.push(this);
32 }
34 function LiftN(update, args) {
35 this.id = Utils.guid();
36 this.value = update();
37 this.kids = [];
39 var n = args.length;
40 var count = 0;
41 var isChanged = false;
43 this.recv = function(timestep, changed, parentID) {
44 ++count;
45 if (changed) { isChanged = true; }
46 if (count == n) {
47 if (isChanged) { this.value = update() }
48 send(this, timestep, isChanged);
49 isChanged = false;
50 count = 0;
51 }
52 };
53 for (var i = n; i--; ) { args[i].kids.push(this); }
54 }
56 function lift(func, a) {
57 function update() { return func(a.value) }
58 return new LiftN(update, [a]);
59 }
60 function lift2(func, a, b) {
61 function update() { return A2( func, a.value, b.value ) }
62 return new LiftN(update, [a,b]);
63 }
64 function lift3(func, a, b, c) {
65 function update() { return A3( func, a.value, b.value, c.value ) }
66 return new LiftN(update, [a,b,c]);
67 }
68 function lift4(func, a, b, c, d) {
69 function update() { return A4( func, a.value, b.value, c.value, d.value ) }
70 return new LiftN(update, [a,b,c,d]);
71 }
72 function lift5(func, a, b, c, d, e) {
73 function update() { return A5( func, a.value, b.value, c.value, d.value, e.value ) }
74 return new LiftN(update, [a,b,c,d,e]);
75 }
76 function lift6(func, a, b, c, d, e, f) {
77 function update() { return A6( func, a.value, b.value, c.value, d.value, e.value, f.value ) }
78 return new LiftN(update, [a,b,c,d,e,f]);
79 }
80 function lift7(func, a, b, c, d, e, f, g) {
81 function update() { return A7( func, a.value, b.value, c.value, d.value, e.value, f.value, g.value ) }
82 return new LiftN(update, [a,b,c,d,e,f,g]);
83 }
84 function lift8(func, a, b, c, d, e, f, g, h) {
85 function update() { return A8( func, a.value, b.value, c.value, d.value, e.value, f.value, g.value, h.value ) }
86 return new LiftN(update, [a,b,c,d,e,f,g,h]);
87 }
89 function foldp(func,state,input) {
90 function update() { state = A2(func, input.value, state); return state }
91 return new LiftN(update, [input]);
92 }
94 function dropIf(pred,base,input) {
95 this.id = Utils.guid();
96 this.value = pred(input.value) ? base : input.value;
97 this.kids = [];
98 this.recv = function(timestep, changed, parentID) {
99 var chng = changed && !pred(input.value);
100 if (chng) { this.value = input.value; }
101 send(this, timestep, chng);
102 };
103 input.kids.push(this);
104 }
106 function dropRepeats(input) {
107 this.id = Utils.guid();
108 this.value = input.value;
109 this.kids = [];
110 this.recv = function(timestep, changed, parentID) {
111 var chng = changed && !Utils.eq(this.value,input.value);
112 if (chng) { this.value = input.value; }
113 send(this, timestep, chng);
114 };
115 input.kids.push(this);
116 }
118 function dropWhen(s1,b,s2) {
119 var pairs = lift2( F2(function(x,y){return {x:x,y:y}}), s1, s2 );
120 var dropped = new dropIf(function(p){return p.x},{x:true,y:b},pairs);
121 return lift(function(p){return p.y}, dropped)
122 }
124 function timestamp(a) {
125 function update() { return Utils.Tuple2(Date.now(), a.value) }
126 return new LiftN(update, [a]);
127 }
129 function SampleOn(s1,s2) {
130 this.id = Utils.guid();
131 this.value = s2.value;
132 this.kids = [];
134 var count = 0;
135 var isChanged = false;
137 this.recv = function(timestep, changed, parentID) {
138 if (parentID === s1.id) isChanged = changed;
139 ++count;
140 if (count == 2) {
141 if (isChanged) { this.value = s2.value; }
142 send(this, timestep, isChanged);
143 count = 0;
144 isChanged = false;
145 }
146 };
147 s1.kids.push(this);
148 s2.kids.push(this);
149 }
151 function sampleOn(s1,s2) { return new SampleOn(s1,s2) }
153 function delay(t,s) {
154 var delayed = new Input(s.value);
155 var firstEvent = true;
156 function update(v) {
157 if (firstEvent) { firstEvent = false; return; }
158 setTimeout(function() { elm.notify(delayed.id, v) }, t);
159 }
160 function first(a,b) { return a }
161 return new SampleOn(delayed, lift2(F2(first), delayed, lift(update,s)));
162 }
164 function Merge(s1,s2) {
165 this.id = Utils.guid();
166 this.value = s1.value;
167 this.kids = [];
169 var next = null;
170 var count = 0;
171 var isChanged = false;
173 this.recv = function(timestep, changed, parentID) {
174 ++count;
175 if (changed) {
176 isChanged = true;
177 if (parentID == s2.id && next === null) { next = s2.value; }
178 if (parentID == s1.id) { next = s1.value; }
179 }
181 if (count == 2) {
182 if (isChanged) { this.value = next; next = null; }
183 send(this, timestep, isChanged);
184 isChanged = false;
185 count = 0;
186 }
187 };
188 s1.kids.push(this);
189 s2.kids.push(this);
190 }
192 function merge(s1,s2) { return new Merge(s1,s2) }
193 function merges(ss) { return A2(foldl1, F2(merge), ss) }
194 function mergeEither(s1,s2) {return new Merge(A2(lift, Either.Left , s1),
195 A2(lift, Either.Right, s2))}
197 function average(sampleSize, s) {
198 var sample = new Array(sampleSize);
199 var i = sampleSize;
200 while (i--) { sample[i] = 0; }
201 i = 0;
202 var full = false;
203 var total = 0;
204 function f(n) {
205 total += n - sample[i];
206 sample[i] = n;
207 var avg = total / Math.max(1, full ? sampleSize : i);
208 if (++i == sampleSize) { full = true; i = 0; }
209 return avg;
210 }
211 return lift(f,s);pp
212 }
214 return elm.Native.Signal = {
215 constant : function(v) { return new Input(v); },
216 lift : F2(lift ),
217 lift2 : F3(lift2),
218 lift3 : F4(lift3),
219 lift4 : F5(lift4),
220 lift5 : F6(lift5),
221 lift6 : F7(lift6),
222 lift7 : F8(lift7),
223 lift8 : F9(lift8),
224 foldp : F3(foldp),
225 delay : delay,
226 merge : F2(merge),
227 merges : merges,
228 mergeEither : F2(mergeEither),
229 average : F2(average),
230 count : function(s) { return foldp(F2(function(_,c) { return c+1 }), 0, s) },
231 countIf : F2(function(pred,s) {
232 return foldp(F2(function(x,c){return pred(x) ? c+1 : c}), 0, s)}),
233 keepIf : F3(function(pred,base,sig) {
234 return new dropIf(function(x) {return !pred(x)},base,sig) }),
235 dropIf : F3(function(pred,base,sig) { return new dropIf(pred,base,sig) }),
236 keepWhen : F3(function(s1,b,s2) {
237 return dropWhen(lift(function(b){return !b;},s1), b, s2) }),
238 dropWhen : F3(dropWhen),
239 dropRepeats : function(s) { return new dropRepeats(s);},
240 sampleOn : F2(sampleOn),
241 timestamp : timestamp
242 };
243};