on d9d1dfd help sign in
elk/core-js/runtime/Signal.js
260 lines 8.6 kB history raw
2Elm.Signal = function() {
3 var send = function(node, timestep, changed) {
4 var kids = node.kids;
5 for (var i = kids.length; i--; ) {
6 kids[i].recv(timestep, changed, node.id);
7 }
8 };
9 function input(base) {
10 this.id = Guid.guid();
11 this.value = base;
12 this.kids = [];
13 this.defaultNumberOfKids = 0;
14 this.recv = function(timestep, eid, v) {
15 var changed = eid === this.id;
16 if (changed) { this.value = v; }
17 send(this, timestep, changed);
18 return changed;
19 };
20 Dispatcher.inputs.push(this);
21 };
22 function lift(func,args) {
23 this.id = Guid.guid();
24 this.value = null;
25 this.kids = [];
26 this.count = 0;
27 this.changed = false;
29 args.reverse();
30 this.recalc = function() {
31 var f = func;
32 for (var i = args.length; i--; ) {
33 f = f(args[i].value);
34 }
35 this.value = f;
36 };
37 this.recalc();
39 this.recv = function(timestep, changed, parentID) {
40 this.count += 1;
41 if (changed) { this.changed = true; }
42 if (this.count == args.length) {
43 if (this.changed) { this.recalc() }
44 send(this, timestep, this.changed);
45 this.changed = false;
46 this.count = 0;
47 }
48 };
49 for (var i = args.length; i--; ) {
50 args[i].kids.push(this);
51 }
52 };
53 function fold(func,base,baseIsFunc,input) {
54 this.id = Guid.guid();
55 this.value = baseIsFunc ? base(input.value) : base;
56 this.kids = [];
57 this.recv = function(timestep, changed, parentID) {
58 if (changed) { this.value = func(input.value)(this.value); }
59 send(this, timestep, changed);
60 };
61 input.kids.push(this);
62 };
64 function dropIf(pred,base,input) {
65 this.id = Guid.guid();
66 this.value = pred(input.value) ? base : input.value;
67 this.kids = [];
68 this.recv = function(timestep, changed, parentID) {
69 var chng = changed && !pred(input.value);
70 if (chng) { this.value = input.value; }
71 send(this, timestep, chng);
72 };
73 input.kids.push(this);
74 };
76 function dropRepeats(input) {
77 this.id = Guid.guid();
78 this.value = input.value;
79 this.kids = [];
80 this.recv = function(timestep, changed, parentID) {
81 var chng = changed && !Value.eq(this.value,input.value);
82 if (chng) { this.value = input.value; }
83 send(this, timestep, chng);
84 };
85 input.kids.push(this);
86 };
88 var dropWhen = function(s1) { return function(b) { return function(s2) {
89 var pairs = new lift(function(x){return function(y){return [x,y];};},[s1,s2]);
90 var dropped = new dropIf(function(p){return p[0];},[true,b],pairs);
91 return new lift(function(p){return p[1];},[dropped]); }; };
92 };
94 function timeIndex(pair,s) {
95 this.id = Guid.guid();
96 var t = (new window.Date).getTime();
97 this.value = pair ? Value.Tuple(t,s.value) : t;
98 this.kids = [];
99 this.recv = function(timestep, changed, parentID) {
100 if (changed) this.value = pair ? Value.Tuple(timestep, s.value) : timestep;
101 send(this, timestep, changed);
102 };
103 s.kids.push(this);
104 }
106 function sampleOn(s1,s2) {
107 this.id = Guid.guid();
108 this.value = s2.value;
109 this.kids = [];
110 this.count = 0;
111 this.changed = false;
113 this.recv = function(timestep, changed, parentID) {
114 if (parentID === s1.id) this.changed = changed;
115 this.count += 1;
116 if (this.count == 2) {
117 if (this.changed) { this.value = s2.value; }
118 send(this, timestep, this.changed);
119 this.count = 0;
120 this.changed = false;
121 }
122 };
123 s1.kids.push(this);
124 s2.kids.push(this);
125 };
127 function delay(t) { return function(s) {
128 var delayed = new input(s.value);
129 var firstEvent = true;
130 function update(v) {
131 if (firstEvent) return;
132 setTimeout(function() { Dispatcher.notify(delayed.id,v); },t);
133 }
134 function first(a) { return function(b) { return a; }; }
135 var out = new sampleOn(delayed,new lift(first, [delayed, new lift(update,[s])]));
136 firstEvent = false;
137 return out;
138 };
139 }
141 function merge(s1,s2) {
142 this.id = Guid.guid();
143 this.value = s1.value;
144 this.kids = [];
145 this.next = null;
146 this.count = 0;
147 this.changed = false;
149 this.recv = function(timestep, changed, parentID) {
150 this.count += 1;
151 if (changed) {
152 this.changed = true;
153 if (parentID == s2.id && this.next === null) { this.next = s2.value; }
154 if (parentID == s1.id) { this.next = s1.value; }
155 }
157 if (this.count == 2) {
158 if (this.changed) {
159 this.value = this.next;
160 this.next = null;
161 }
162 send(this, timestep, this.changed);
163 this.changed = false;
164 this.count = 0;
165 }
166 };
167 s1.kids.push(this);
168 s2.kids.push(this);
169 };
171 function merges(ss) {
172 function mrg(x) { return function(y) { return new merge(x,y); }; }
173 return Elm.List.foldl1(mrg)(ss);
174 }
176 function mergeEither(s1) { return function(s2) {
177 function f(s) { return function(x) { return [s,x]; }; }
178 return new merge(new lift(f('Left'),[s1]), new lift(f('Right'),[s2]));
179 };
180 }
182 function average(sampleSize) { return function(s) {
183 var sample = new Array(sampleSize);
184 var i = sampleSize;
185 while (i--) sample[i] = 0;
186 i = 0;
187 var full = false;
188 var total = 0;
189 function f(n) {
190 total += n - sample[i];
191 sample[i] = n;
192 var avg = total / Math.max(1, full ? sampleSize : i);
193 if (++i == sampleSize) { full = true; i = 0; }
194 return avg;
195 }
196 return new lift(f, [s]);
197 };
198 }
200 return {
201 constant : function(v) { return new input(v); },
202 lift : function(f){return function(e){return new lift(f,[e]);};},
203 lift2 : function(f) {
204 return function(e1) { return function(e2) {
205 return new lift(f, [e1,e2]); };};},
206 lift3 : function(f) {
207 return function(e1) { return function(e2) {
208 return function(e3){return new lift(f,[e1,e2,e3]);};};};},
209 lift4 : function(f) {
210 return function(e1) { return function(e2) {
211 return function(e3) { return function(e4) {
212 return new lift(f, [e1,e2,e3,e4]);};};};};},
213 lift5 : function(f) {
214 return function(e1) { return function(e2) {
215 return function(e3) { return function(e4) {
216 return function(e5) {
217 return new lift(f, [e1,e2,e3,e4,e5]);};};};};};},
218 lift6 : function(f) { return function(e1) { return function(e2) {
219 return function(e3) { return function(e4) {
220 return function(e5) { return function(e6) {
221 return new lift(f, [e1,e2,e3,e4,e5,e6]); };};};};};};},
222 lift7 : function(f) { return function(e1) { return function(e2) {
223 return function(e3) { return function(e4) {
224 return function(e5) { return function(e6) {
225 return function(e7) {
226 return new lift(f, [e1,e2,e3,e4,e5,e6,e7]);};};};};};};};},
227 lift8 : function(f) { return function(e1) { return function(e2) {
228 return function(e3) { return function(e4) {
229 return function(e5) { return function(e6) {
230 return function(e7) { return function(e8) {
231 return new lift(f, [e1,e2,e3,e4,e5,e6,e7,e8]);};};};};};};};};},
232 foldp : function(f) { return function(b) { return function(e) {
233 return new fold(f,b,false,e); }; }; },
234 foldp$ : function(f) { return function(b) { return function(e) {
235 return new fold(f,b,true,e); }; }; },
236 foldp1 : function(f) { return function(e) {
237 return new fold(f,function(x){return x;},true,e); }; },
238 delay : delay,
239 merge : function(s1) { return function(s2) { return new merge(s1,s2)}; },
240 merges : merges,
241 mergeEither : mergeEither,
242 average : average,
243 count : function(sig) {
244 var incr = function(_){return function(c){return c+1;};};
245 return new fold(incr,0,false,sig) },
246 countIf : function(pred) { return function(sig) {
247 var incr = function(x){return function(c){return pred(x) ? c+1 : c;};};
248 return new fold(incr,0,false,sig) }; },
249 keepIf : function(pred) { return function(base) { return function(sig) {
250 return new dropIf(function(x) { return !pred(x)},base,sig); }; }; },
251 dropIf : function(pred) { return function(base) { return function(sig) {
252 return new dropIf(pred,base,sig); }; }; },
253 keepWhen : function(s) { return dropWhen(new lift(function(b){return !b;},[s])); },
254 dropWhen : dropWhen,
255 dropRepeats : function(s) { return new dropRepeats(s);},
256 sampleOn : function(s1){return function(s2){return new sampleOn(s1,s2);};},
257 timestamp : function(s) { return new timeIndex(true, s); },
258 timeOf : function(s) { return new timeIndex(false, s); }
259 };
260}();