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