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