on c19ccfe help sign in
234 lines 6.9 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;
8 var Utils = Elm.Native.Utils(elm);
9 var foldl1 = Elm.List(elm).foldl1;
11 function send(node, timestep, changed) {
12 var kids = node.kids;
13 for (var i = kids.length; i--; ) {
14 kids[i].recv(timestep, changed, node.id);
15 }
16 }
18 function Input(base) {
19 this.id = Utils.guid();
20 this.value = base;
21 this.kids = [];
22 this.defaultNumberOfKids = 0;
23 this.recv = function(timestep, eid, v) {
24 var changed = eid === this.id;
25 if (changed) { this.value = v; }
26 send(this, timestep, changed);
27 return changed;
28 };
29 elm.inputs.push(this);
30 }
32 function LiftN(update, args) {
33 this.id = Utils.guid();
34 this.value = update();
35 this.kids = [];
37 var n = args.length;
38 var count = 0;
39 var isChanged = false;
41 this.recv = function(timestep, changed, parentID) {
42 ++count;
43 if (changed) { isChanged = true; }
44 if (count == n) {
45 if (isChanged) { this.value = update(); }
46 send(this, timestep, isChanged);
47 isChanged = false;
48 count = 0;
49 }
50 };
51 for (var i = n; i--; ) { args[i].kids.push(this); }
52 }
54 function lift(func, a) {
55 function update() { return func(a.value); }
56 return new LiftN(update, [a]);
57 }
58 function lift2(func, a, b) {
59 function update() { return A2( func, a.value, b.value ); }
60 return new LiftN(update, [a,b]);
61 }
62 function lift3(func, a, b, c) {
63 function update() { return A3( func, a.value, b.value, c.value ); }
64 return new LiftN(update, [a,b,c]);
65 }
66 function lift4(func, a, b, c, d) {
67 function update() { return A4( func, a.value, b.value, c.value, d.value ); }
68 return new LiftN(update, [a,b,c,d]);
69 }
70 function lift5(func, a, b, c, d, e) {
71 function update() { return A5( func, a.value, b.value, c.value, d.value, e.value ); }
72 return new LiftN(update, [a,b,c,d,e]);
73 }
74 function lift6(func, a, b, c, d, e, f) {
75 function update() { return A6( func, a.value, b.value, c.value, d.value, e.value, f.value ); }
76 return new LiftN(update, [a,b,c,d,e,f]);
77 }
78 function lift7(func, a, b, c, d, e, f, g) {
79 function update() { return A7( func, a.value, b.value, c.value, d.value, e.value, f.value, g.value ); }
80 return new LiftN(update, [a,b,c,d,e,f,g]);
81 }
82 function lift8(func, a, b, c, d, e, f, g, h) {
83 function update() { return A8( func, a.value, b.value, c.value, d.value, e.value, f.value, g.value, h.value ); }
84 return new LiftN(update, [a,b,c,d,e,f,g,h]);
85 }
87 function Foldp(step, state, input) {
88 this.id = Utils.guid();
89 this.value = state;
90 this.kids = [];
92 this.recv = function(timestep, changed, parentID) {
93 if (changed) {
94 this.value = A2( step, input.value, this.value );
95 }
96 send(this, timestep, changed);
97 };
98 input.kids.push(this);
99 }
101 function foldp(step, state, input) {
102 return new Foldp(step, state, input);
103 }
105 function DropIf(pred,base,input) {
106 this.id = Utils.guid();
107 this.value = pred(input.value) ? base : input.value;
108 this.kids = [];
109 this.recv = function(timestep, changed, parentID) {
110 var chng = changed && !pred(input.value);
111 if (chng) { this.value = input.value; }
112 send(this, timestep, chng);
113 };
114 input.kids.push(this);
115 }
117 function DropRepeats(input) {
118 this.id = Utils.guid();
119 this.value = input.value;
120 this.kids = [];
121 this.recv = function(timestep, changed, parentID) {
122 var chng = changed && !Utils.eq(this.value,input.value);
123 if (chng) { this.value = input.value; }
124 send(this, timestep, chng);
125 };
126 input.kids.push(this);
127 }
129 function dropWhen(s1,b,s2) {
130 var pairs = lift2( F2(function(x,y){return {x:x,y:y};}), s1, s2 );
131 var dropped = new DropIf(function(p){return p.x;},{x:true,y:b},pairs);
132 return lift(function(p){return p.y;}, dropped);
133 }
135 function timestamp(a) {
136 function update() { return Utils.Tuple2(Date.now(), a.value); }
137 return new LiftN(update, [a]);
138 }
140 function SampleOn(s1,s2) {
141 this.id = Utils.guid();
142 this.value = s2.value;
143 this.kids = [];
145 var count = 0;
146 var isChanged = false;
148 this.recv = function(timestep, changed, parentID) {
149 if (parentID === s1.id) isChanged = changed;
150 ++count;
151 if (count == 2) {
152 if (isChanged) { this.value = s2.value; }
153 send(this, timestep, isChanged);
154 count = 0;
155 isChanged = false;
156 }
157 };
158 s1.kids.push(this);
159 s2.kids.push(this);
160 }
162 function sampleOn(s1,s2) { return new SampleOn(s1,s2); }
164 function delay(t,s) {
165 var delayed = new Input(s.value);
166 var firstEvent = true;
167 function update(v) {
168 if (firstEvent) { firstEvent = false; return; }
169 setTimeout(function() { elm.notify(delayed.id, v); }, t);
170 }
171 function first(a,b) { return a; }
172 return new SampleOn(delayed, lift2(F2(first), delayed, lift(update,s)));
173 }
175 function Merge(s1,s2) {
176 this.id = Utils.guid();
177 this.value = s1.value;
178 this.kids = [];
180 var next = null;
181 var count = 0;
182 var isChanged = false;
184 this.recv = function(timestep, changed, parentID) {
185 ++count;
186 if (changed) {
187 isChanged = true;
188 if (parentID == s2.id && next === null) { next = s2.value; }
189 if (parentID == s1.id) { next = s1.value; }
190 }
192 if (count == 2) {
193 if (isChanged) { this.value = next; next = null; }
194 send(this, timestep, isChanged);
195 isChanged = false;
196 count = 0;
197 }
198 };
199 s1.kids.push(this);
200 s2.kids.push(this);
201 }
203 function merge(s1,s2) { return new Merge(s1,s2); }
204 function merges(ss) { return A2(foldl1, F2(merge), ss); }
206 return elm.Native.Signal = {
207 constant : function(v) { return new Input(v); },
208 lift : F2(lift ),
209 lift2 : F3(lift2),
210 lift3 : F4(lift3),
211 lift4 : F5(lift4),
212 lift5 : F6(lift5),
213 lift6 : F7(lift6),
214 lift7 : F8(lift7),
215 lift8 : F9(lift8),
216 foldp : F3(foldp),
217 delay : F2(delay),
218 merge : F2(merge),
219 merges : merges,
220 count : function(s) { return foldp(F2(function(_,c) { return c+1; }), 0, s); },
221 countIf : F2(function(pred,s) {
222 return foldp(F2(function(x,c){
223 return pred(x) ? c+1 : c; }), 0, s)}),
224 keepIf : F3(function(pred,base,sig) {
225 return new DropIf(function(x) {return !pred(x);},base,sig); }),
226 dropIf : F3(function(pred,base,sig) { return new DropIf(pred,base,sig); }),
227 keepWhen : F3(function(s1,b,s2) {
228 return dropWhen(lift(function(b){return !b;},s1), b, s2); }),
229 dropWhen : F3(dropWhen),
230 dropRepeats : function(s) { return new DropRepeats(s);},
231 sampleOn : F2(sampleOn),
232 timestamp : timestamp
233 };
234};