on master help sign in
Update compiler to parse and compile FFI imports and exports. Add type hints for Foreign.JavaScript. Fix bug where Haskell lib functions do not display title properly. Add --import-js flag.
a9da9b3evancz
.gitignore+4−1
@@ -5,4 +5,7 @@ cabal-dev
5*.chi
5*.chi
6*.chs.h
6*.chs.h
7*.aes
7*.aes
8−.DS_Store
8+.DS_Store
9+/Examples/elm-js/ChangeTitle/ChangeTitle.html
10+/Examples/elm-js/ConsoleLog/Log.html
11+/Examples/elm-js/Redirect/Redirect.html
elm/changelog.txt+17
@@ -1,3 +1,20 @@
1+Release 0.3.5
2+=============
3+
4+* Add JavaScript event interface. Allows Elm to import and export JS values
5+ and events. This makes it possible to import and export Elements, so users
6+ can use JS techniques and libraries if necessary.
7+* Add new flags to help with JavaScript event interface.
8+* Add new Signal functions:
9+ count :: Signal a -> Signal Int
10+ keepIf :: a -> (a -> Bool) -> Signal a -> Signal a
11+ dropIf :: a -> (a -> Bool) -> Signal a -> Signal a
12+ dropRepeats :: Signal a -> Signal a
13+ The keep and drop functions make it possible to filter events, which
14+ was not possible in prior releases.
15+
16+
17+
1Release 0.3.0
18Release 0.3.0
2=============
19=============
3
20
elm/elm-runtime-0.3.5.jsnew file+2081
@@ -0,0 +1,2081 @@
1+
2+var Guid = function() {
3+ var counter = 0;
4+ var guid = function() { counter += 1; return counter; };
5+ return {guid : guid};
6+}();
7+var Foreign = function() {
8+ var JavaScript = function() {
9+ function castJSBoolToBool(b) { return b; }
10+ function castBoolToJSBool(b) { return b; }
11+
12+ function castJSNumberToFloat(n) { return n; }
13+ function castFloatToJSNumber(n) { return n; }
14+
15+ function castJSNumberToInt(n) { return ~~n; }
16+ function castIntToJSNumber(n) { return n; }
17+
18+ var castJSElementToElement = Element.jsElement;
19+ function castElementToJSElement(elem) { return elem; }
20+
21+ function castJSArrayToList(arr) {
22+ var list = ["Nil"];
23+ for (var i = arr.length; i--; ) {
24+ list = [ "Cons", arr[i], list ];
25+ }
26+ return list;
27+ }
28+ function castListToJSArray(list) {
29+ var a = [];
30+ while (list[0] === "Cons") {
31+ a.push(list[1]);
32+ list = list[2];
33+ }
34+ return a;
35+ }
36+
37+ var castJSStringToString = castJSArrayToList;
38+ function castStringToJSString(str) {
39+ if (typeof str === "string") return str;
40+ return castListToJSArray(str).join('');
41+ }
42+
43+ function fromTuple(t) { return t.slice(1); }
44+ function toTuple(a) { return a.unshift("Tuple" + a.length); }
45+
46+ return {castJSBoolToBool:castJSBoolToBool,
47+ castBoolToJSBool:castBoolToJSBool,
48+ castJSNumberToFloat:castJSNumberToFloat,
49+ castFloatToJSNumber:castFloatToJSNumber,
50+ castJSNumberToInt:castJSNumberToInt,
51+ castIntToJSNumber:castIntToJSNumber,
52+ castJSElementToElement:castJSElementToElement,
53+ castElementToJSElement:castElementToJSElement,
54+ castJSArrayToList:castJSArrayToList,
55+ castListToJSArray:castListToJSArray,
56+ castJSStringToString:castJSStringToString,
57+ castStringToJSString:castStringToJSString,
58+ castTupleToJSTuple2:fromTuple,
59+ castTupleToJSTuple3:fromTuple,
60+ castTupleToJSTuple4:fromTuple,
61+ castTupleToJSTuple5:fromTuple,
62+ castJSTupleToTuple2:toTuple,
63+ castJSTupleToTuple3:toTuple,
64+ castJSTupleToTuple4:toTuple,
65+ castJSTupleToTuple5:toTuple
66+ };
67+ }();
68+ return {JavaScript:JavaScript};
69+}();
70+var Value = function(){
71+
72+ var eq = function(x,y) {
73+ if (typeof x === "object") {
74+ if (x === y) return true;
75+ if (x.length !== y.length) return false;
76+ for (var i = x.length; i--; ) {
77+ if (!eq(x[i],y[i])) return false;
78+ }
79+ return true;
80+ }
81+ return x === y;
82+ };
83+
84+ var Tuple = function() {
85+ var len = arguments.length;
86+ var arr = new Array(len+1);
87+ arr[0] = "Tuple" + arguments.length;
88+ for (var i = len; i--; ) {
89+ arr[i+1] = arguments[i];
90+ }
91+ return arr;
92+ };
93+
94+ var listToArray = function(list) {
95+ var arr = [];
96+ while (list[0] === "Cons") {
97+ arr.push(list[1]);
98+ list = list[2];
99+ }
100+ return arr;
101+ };
102+
103+ var properEscape = function(str) {
104+ str.replace('"', """);
105+ str.replace("&", "&");
106+ str.replace("'", "'");
107+ str.replace("<", "&#60;");
108+ str.replace(">", "&#62;");
109+ return str;
110+ };
111+
112+ var toText = function(elmList) {
113+ if (typeof elmList === "string") return elmList;
114+ var a = [];
115+ while (elmList[0] === "Cons") {
116+ a.push(elmList[1]);
117+ elmList = elmList[2];
118+ }
119+ return properEscape(a.join(''));
120+ };
121+
122+ var toString = function(v) {
123+ if (typeof v === "boolean") {
124+ return v ? "True" : "False";
125+ } else if (typeof v === "number") {
126+ return v+"";
127+ } else if (v[0]) {
128+ if (v[0].substring(0,5) === "Tuple") {
129+ var output = "";
130+ for (var i = v.length; --i; ) {
131+ output = "," + toString(v[i]) + output;
132+ }
133+ if (output[0] === ",") output = output.substring(1);
134+ return "("+output+")";
135+ } else if (v[0] === "Cons") {
136+ var start = (typeof v[1] === "string") ? '"' : "[";
137+ var end = (typeof v[1] === "string") ? '"' : "]";
138+ var div = (typeof v[1] === "string") ? "" : ",";
139+ var output = start + toString(v[1]);
140+ v = v[2];
141+ while (true) {
142+ if (v[0] === "Cons") {
143+ output += div + toString(v[1]);
144+ v = v[2];
145+ } else {
146+ return output + end;
147+ }
148+ }
149+ } else if (v[0] === "Nil") {
150+ return "[]";
151+ } else {
152+ var output = "";
153+ for (var i = v.length; --i; ) {
154+ output = " " + toString(v[i]) + output
155+ }
156+ output = v[0] + output;
157+ return (v.length > 1) ? "(" + output + ")" : output;
158+ }
159+ }
160+ return v+"";
161+ };
162+ var show = function(v) {
163+ return Text.monospace(properEscape(toString(v)));
164+ };
165+ var append = function(xs,ys) {
166+ if (typeof xs === "string" && typeof ys === "string") {
167+ return xs.concat(ys);
168+ }
169+ if (xs[0] === "Nil") {
170+ return ys;
171+ }
172+ var root = ["Cons", xs[1], ["Nil"]];
173+ var curr = root;
174+ xs = xs[2];
175+ while (xs[0]==="Cons") {
176+ curr[2] = ["Cons", xs[1], ["Nil"]];
177+ xs = xs[2];
178+ curr = curr[2];
179+ }
180+ curr[2] = ys;
181+ return root;
182+ };
183+
184+ var str = function(s) {
185+ var out = ["Nil"];
186+ for (var i = s.length; i--; ) {
187+ out = ["Cons", s[i], out];
188+ }
189+ return out;
190+ };
191+
192+ return {eq:eq,
193+ str:str,
194+ show:show,
195+ Tuple:Tuple,
196+ append:append,
197+ listToArray:listToArray,
198+ toText : toText,
199+ properEscape : properEscape};
200+}();var List = function() {
201+
202+ var throwError = function(f) {
203+ throw "Function '" + f + "' expecting a list!";
204+ }
205+
206+ function length(xs) {
207+ var out = 0;
208+ while (xs[0] === "Cons") {
209+ out += 1;
210+ xs = xs[2];
211+ }
212+ return out;
213+ };
214+ var reverse = foldl(function(x_72) {
215+ return function(y_73) {
216+ return["Cons", x_72, y_73]
217+ }
218+ })(["Nil"]);
219+ var concat = foldr(function(x_74) {
220+ return function(y_75) {
221+ return Value.append(x_74, y_75)
222+ }
223+ })(["Nil"]);
224+ var and = foldl(function(x_77) {
225+ return function(y_78) {
226+ return x_77 && y_78
227+ }
228+ })(true);
229+ var or = foldl(function(x_79) {
230+ return function(y_80) {
231+ return x_79 || y_80
232+ }
233+ })(false);
234+ var sum = foldl(function(x_89) {
235+ return function(y_90) {
236+ return x_89 + y_90
237+ }
238+ })(0);
239+ var product = foldl(function(x_91) {
240+ return function(y_92) {
241+ return x_91 * y_92
242+ }
243+ })(1);
244+ var maximum = foldl1(function(x) { return function(y) { return Math.max(x,y) } });
245+ var minimum = foldl1(function(x) { return function(y) { return Math.min(x,y) } });
246+ function head(v) {
247+ if (v[0] !== "Cons") {
248+ throw "Error: 'head' only accepts lists of length greater than one.";
249+ }
250+ return v[1];
251+ }
252+ function tail(v) {
253+ if (v[0] !== "Cons") {
254+ throw "Error: 'tail' only accepts lists of length greater than one.";
255+ }
256+ return v[2];
257+ }
258+ function map(f) {
259+ return function(xs) {
260+ if (xs[0] === "Nil") { return xs; }
261+ if (xs[0] !== "Cons") { throwError('map'); }
262+ var root = ["Cons", f(xs[1]), ["Nil"]];
263+ var curr = root;
264+ xs = xs[2];
265+ while (xs[0]==="Cons") {
266+ curr[2] = ["Cons", f(xs[1]), ["Nil"]];
267+ xs = xs[2];
268+ curr = curr[2];
269+ }
270+ return root;
271+ }
272+ }
273+ function foldl(f) {
274+ return function(b) {
275+ return function(xs) {
276+ var acc = b;
277+ if (xs[0] === "Nil") { return acc; }
278+ if (xs[0] !== "Cons") { throwError('foldl'); }
279+ while (xs[0] === "Cons") {
280+ acc = f(xs[1])(acc);
281+ xs = xs[2];
282+ }
283+ return acc;
284+ }
285+ }
286+ }
287+ function foldr(f) {
288+ return function(b) {
289+ return function(xs) {
290+ var acc = b;
291+ if (xs[0] === "Nil") { return acc; }
292+ if (xs[0] !== "Cons") { throwError('foldr'); }
293+ var arr = [];
294+ while (xs[0] === "Cons") {
295+ arr.push(xs[1]);
296+ xs = xs[2];
297+ }
298+ for (var i = arr.length; i--; ) {
299+ acc = f(arr[i])(acc);
300+ }
301+ return acc;
302+ }
303+ }
304+ }
305+ function foldl1(f_49) {
306+ return function(_temp_50) {
307+ return function(v) {
308+ if("Cons" !== v[0]) {
309+ return undefined
310+ }else {
311+ var x_51 = v[1];
312+ var xs_52 = v[2];
313+ return foldl(f_49)(x_51)(xs_52)
314+ }
315+ }(_temp_50)
316+ }
317+ }
318+ function foldr1(f_53) {
319+ return function(_temp_54) {
320+ return function(v) {
321+ if("Cons" !== v[0]) {
322+ return undefined
323+ }else {
324+ var x_55 = v[1];
325+ var xs_56 = v[2];
326+ return foldr(f_53)(x_55)(xs_56)
327+ }
328+ }(_temp_54)
329+ }
330+ }
331+ function scanl(f) {
332+ return function(b) {
333+ return function(xs) {
334+ if (xs[0] === "Nil") { return ["Cons",b,["Nil"]]; }
335+ if (xs[0] !== "Cons") { throwError('scanl'); }
336+ var arr = [b];
337+ while (xs[0] === "Cons") {
338+ b = f(xs[1])(b);
339+ arr.push(b);
340+ xs = xs[2];
341+ }
342+ var out = ["Nil"];
343+ for (var i = arr.length; i--; ) {
344+ out = ["Cons", arr[i], out];
345+ }
346+ return out;
347+ }
348+ }
349+ }
350+ function scanl1(f) {
351+ return function(xs) {
352+ if (xs[0] !== "Cons") {
353+ throw "Error: 'scanl1' requires a list of at least length 1.";
354+ }
355+ return scanl(f)(xs[1])(xs[2]);
356+ }
357+ }
358+ function filter(pred) {
359+ return function(xs) {
360+ if (xs[0] === "Nil") { return xs; }
361+ if (xs[0] !== "Cons") { throwError('filter'); }
362+ var arr = [];
363+ while (xs[0] === "Cons") {
364+ if (pred(xs[1])) { arr.push(xs[1]); }
365+ xs = xs[2];
366+ }
367+ var out = ["Nil"];
368+ for (var i = arr.length; i--; ) {
369+ out = ["Cons", arr[i], out];
370+ }
371+ return out;
372+ }
373+ }
374+ function concatMap(f_76) {
375+ return function(x) {
376+ return concat(map(f_76)(x))
377+ }
378+ }
379+ function forall(pred) {
380+ return foldl(function(x) { return function(acc) {
381+ return acc && pred(x);
382+ };})(true);
383+ }
384+ function exists(pred) {
385+ return foldl(function(x) { return function(acc) {
386+ return acc || pred(x);
387+ };})(false);
388+ }
389+ function partition(pred_93) {
390+ return function(lst_94) {
391+ return function() {
392+ var v = lst_94;
393+ var c = [function(v) {
394+ if("Nil" !== v[0]) {
395+ return undefined
396+ }else {
397+ return["Tuple2", ["Nil"], ["Nil"]]
398+ }
399+ }, function(v) {
400+ if("Cons" !== v[0]) {
401+ return undefined
402+ }else {
403+ var x_95 = v[1];
404+ var xs_96 = v[2];
405+ return function(v) {
406+ if("Tuple2" !== v[0]) {
407+ return undefined
408+ }else {
409+ var as_97 = v[1];
410+ var bs_98 = v[2];
411+ return pred_93(x_95) ? ["Tuple2", ["Cons", x_95, as_97], bs_98] : ["Tuple2", as_97, ["Cons", x_95, bs_98]]
412+ }
413+ }(partition(pred_93)(xs_96))
414+ }
415+ }];
416+ for(var i = c.length;i--;) {
417+ var r = c[i](v);
418+ if(r !== undefined) {
419+ return r
420+ }
421+ }
422+ }()
423+ }
424+ }
425+ function zipWith(f) {
426+ return function(listA) {
427+ return function(listB) {
428+ if (listA[0] === "Nil" || listB[0] === "Nil") { return ["Nil"]; }
429+ if (listA[0] !== "Cons" || listB[0] !== "Cons") { throwError('zipWith'); }
430+ var arr = [];
431+ while (listA[0] === "Cons" && listB[0] === "Cons") {
432+ arr.push(f(listA[1])(listB[1]));
433+ listA = listA[2];
434+ listB = listB[2];
435+ }
436+ var out = ["Nil"];
437+ for (var i = arr.length; i--; ) {
438+ out = ["Cons", arr[i], out];
439+ }
440+ return out;
441+ }
442+ }
443+ }
444+ function zip(listA) {
445+ return function(listB) {
446+ if (listA[0] === "Nil" || listB[0] === "Nil") { return ["Nil"]; }
447+ if (listA[0] !== "Cons" || listB[0] !== "Cons") { throwError('zip'); }
448+ var arr = [];
449+ while (listA[0] === "Cons" && listB[0] === "Cons") {
450+ arr.push(["Tuple2", listA[1], listB[1]]);
451+ listA = listA[2];
452+ listB = listB[2];
453+ }
454+ var out = ["Nil"];
455+ for (var i = arr.length; i--; ) {
456+ out = ["Cons", arr[i], out];
457+ }
458+ return out;
459+ }
460+ }
461+ function unzip(pairs_112) {
462+ return function() {
463+ var v = pairs_112;
464+ var c = [function(v) {
465+ if("Nil" !== v[0]) {
466+ return undefined
467+ }else {
468+ return["Tuple2", ["Nil"], ["Nil"]]
469+ }
470+ }, function(v) {
471+ if("Cons" !== v[0]) {
472+ return undefined
473+ }else {
474+ var p_113 = v[1];
475+ var ps_114 = v[2];
476+ return function(v) {
477+ if("Tuple2" !== v[0]) {
478+ return undefined
479+ }else {
480+ if("Tuple2" !== v[1][0]) {
481+ return undefined
482+ }else {
483+ var x_115 = v[1][1];
484+ var y_116 = v[1][2];
485+ if("Tuple2" !== v[2][0]) {
486+ return undefined
487+ }else {
488+ var xs_117 = v[2][1];
489+ var ys_118 = v[2][2];
490+ return["Tuple2", ["Cons", x_115, xs_117], ["Cons", y_116, ys_118]]
491+ }
492+ }
493+ }
494+ }(["Tuple2", p_113, unzip(ps_114)])
495+ }
496+ }];
497+ for(var i = c.length;i--;) {
498+ var r = c[i](v);
499+ if(r !== undefined) {
500+ return r
501+ }
502+ }
503+ }()
504+ }
505+ function intersperse(sep_119) {
506+ return function(xs_120) {
507+ return function() {
508+ var v = xs_120;
509+ var c = [function(v) {
510+ if("Nil" !== v[0]) {
511+ return undefined
512+ }else {
513+ return["Nil"]
514+ }
515+ }, function(v) {
516+ if("Cons" !== v[0]) {
517+ return undefined
518+ }else {
519+ var a_124 = v[1];
520+ if("Nil" !== v[2][0]) {
521+ return undefined
522+ }else {
523+ return["Cons", a_124, ["Nil"]]
524+ }
525+ }
526+ }, function(v) {
527+ if("Cons" !== v[0]) {
528+ return undefined
529+ }else {
530+ var a_121 = v[1];
531+ if("Cons" !== v[2][0]) {
532+ return undefined
533+ }else {
534+ var b_122 = v[2][1];
535+ var cs_123 = v[2][2];
536+ return["Cons", a_121, ["Cons", sep_119, intersperse(sep_119)(["Cons", b_122, cs_123])]]
537+ }
538+ }
539+ }];
540+ for(var i = c.length;i--;) {
541+ var r = c[i](v);
542+ if(r !== undefined) {
543+ return r
544+ }
545+ }
546+ }()
547+ }
548+ }
549+ function intercalate(sep_125) {
550+ return function(xs_126) {
551+ return function() {
552+ var v = xs_126;
553+ var c = [function(v) {
554+ if("Nil" !== v[0]) {
555+ return undefined
556+ }else {
557+ return["Nil"]
558+ }
559+ }, function(v) {
560+ if("Cons" !== v[0]) {
561+ return undefined
562+ }else {
563+ var a_130 = v[1];
564+ if("Nil" !== v[2][0]) {
565+ return undefined
566+ }else {
567+ return a_130
568+ }
569+ }
570+ }, function(v) {
571+ if("Cons" !== v[0]) {
572+ return undefined
573+ }else {
574+ var a_127 = v[1];
575+ if("Cons" !== v[2][0]) {
576+ return undefined
577+ }else {
578+ var b_128 = v[2][1];
579+ var cs_129 = v[2][2];
580+ return Value.append(a_127, Value.append(sep_125, intercalate(sep_125)(["Cons", b_128, cs_129])))
581+ }
582+ }
583+ }];
584+ for(var i = c.length;i--;) {
585+ var r = c[i](v);
586+ if(r !== undefined) {
587+ return r
588+ }
589+ }
590+ }()
591+ }
592+ }
593+ function sort(xs) {
594+ if (xs[0] === "Nil") { return xs; }
595+ if (xs[0] !== "Cons") { throwError('sort'); }
596+ var arr = [];
597+ while (xs[0] === "Cons") {
598+ arr.push(xs[1]);
599+ xs = xs[2];
600+ }
601+ arr.sort(function(a,b) { return a - b});
602+ var out = ["Nil"];
603+ for (var i = arr.length; i--; ) {
604+ out = [ "Cons", arr[i], out ];
605+ }
606+ return out;
607+ }
608+ function take(n) { return function(xs) {
609+ if (n <= 0) { return ["Nil"]; }
610+ if (xs[0] === "Nil") { return xs; }
611+ if (xs[0] !== "Cons") { throwError('take'); }
612+ var out = [ "Cons", xs[1], ["Nil"] ];
613+ var temp = out;
614+ xs = xs[2];
615+ --n;
616+ while (xs[0] === "Cons" && n > 0) {
617+ temp[2] = [ "Cons", xs[1], ["Nil"] ];
618+ temp = temp[2];
619+ xs = xs[2];
620+ --n;
621+ }
622+ return out;
623+ };
624+ }
625+ function drop(n) { return function(xs) {
626+ if (xs[0] === "Nil") { return xs; }
627+ if (xs[0] !== "Cons") { throwError('drop'); }
628+ while (xs[0] === "Cons" && n > 0) {
629+ xs = xs[2];
630+ --n;
631+ }
632+ return xs;
633+ };
634+ }
635+ return {head:head,
636+ tail:tail,
637+ map:map,
638+ foldl:foldl,
639+ foldr:foldr,
640+ foldl1:foldl1,
641+ foldr1:foldr1,
642+ scanl:scanl,
643+ scanl1:scanl1,
644+ filter:filter,
645+ length:length,
646+ reverse:reverse,
647+ concat:concat,
648+ concatMap:concatMap,
649+ and:and,
650+ or:or,
651+ forall:forall,
652+ exists:exists,
653+ sum:sum,
654+ product:product,
655+ maximum:maximum,
656+ minimum:minimum,
657+ partition:partition,
658+ zipWith:zipWith,
659+ zip:zip,
660+ unzip:unzip,
661+ intersperse:intersperse,
662+ intercalate:intercalate,
663+ sort:sort,
664+ take:take,
665+ drop:drop};
666+}();
667+var Data = function() {
668+
669+var Char = function() {
670+ return {fromCode : function(c) { return String.fromCharCode(c); },
671+ toCode : function(c) { return c.charCodeAt(0); },
672+ toUpper : function(c) { return c.toUpperCase(); },
673+ toLower : function(c) { return c.toLowerCase(); },
674+ toLocaleUpper : function(c) { return c.toLocaleUpperCase(); },
675+ toLocaleLower : function(c) { return c.toLocaleLowerCase(); }
676+ };
677+}();
678+
679+var Maybe = function() {
680+ function consMaybe(x) { return function(xs) {
681+ if (x[0] === "Just") return ["Cons", x[1], xs];
682+ return xs;
683+ };
684+ }
685+ function fromMaybe(b) { return function(m) {
686+ if (m[0] === "Just") return m[1];
687+ return b;
688+ };
689+ }
690+ function mapCons(f) { return function(y) { return function(xs) {
691+ var x = f(y);
692+ if (x[0] === "Just") return ["Cons", x[1], xs];
693+ return xs;
694+ };
695+ };
696+ }
697+ function maybe(b) { return function(f) { return function(m) {
698+ if (m[0] === "Just") return f(m[1]);
699+ return b;
700+ };
701+ };
702+ }
703+
704+ return {Just : function(x) { return ["Just",x]; },
705+ Nothing : ["Nothing"],
706+ catMaybes : List.foldr(consMaybe)(["Nil"]),
707+ isJust : function(m) { return m[0] === "Just"; },
708+ isNothing : function(m) { return m[0] === "Nothing"; },
709+ fromMaybe : fromMaybe,
710+ consMaybe : consMaybe,
711+ mapMaybe : function(f) { return List.foldr(mapCons(f))(["Nil"]); },
712+ maybe : maybe
713+ };
714+}();
715+
716+var String = function() {
717+
718+ function append(s1) { return function(s2) {
719+ return s1.concat(s2);
720+ };
721+ }
722+ function map(f) { return function(s) {
723+ for (var i = s.length; i--; ) { s[i] = f(s[i]); }
724+ };
725+ }
726+
727+ function intercalate(sep) { return function(ss) {
728+ return Value.listToArray(ss).join(sep);
729+ };
730+ }
731+ function intersperse(sep) { return function(s) {
732+ return s.split("").join(sep);
733+ };
734+ }
735+
736+ function foldl(f) { return function(b) { return function(s) {
737+ var acc = b;
738+ for (var i = 0, len = s.length; i < len; ++i) { acc = f(s[i])(acc); }
739+ return acc;
740+ };
741+ };
742+ }
743+ function foldr(f) { return function(b) { return function(s) {
744+ var acc = b;
745+ for (var i = s.length; i--; ) { acc = f(s[i])(acc); }
746+ return acc;
747+ };
748+ };
749+ }
750+
751+ function concatMap(f) { return function(s) {
752+ var a = s.split("");
753+ for (var i = a.length; i--; ) { a[i] = f(a[i]); }
754+ return a.join("");
755+ };
756+ }
757+
758+ function forall(pred) { return function(s) {
759+ for (var i = s.length; i--; ) { if (!pred(s[i])) {return false}; }
760+ return true;
761+ };
762+ }
763+ function exists(pred) { return function(s) {
764+ for (var i = s.length; i--; ) { if (pred(s[i])) {return true}; }
765+ return false;
766+ };
767+ }
768+
769+ return {cons : append,
770+ snoc : append,
771+ head : function(s) { return s[0]; },
772+ last : function(s) { return s[s.length-1]; },
773+ tail : function(s) { return s.slice(1); },
774+ length : function(s) { return s.length; },
775+ map : map,
776+ intercalate : intercalate,
777+ intersperse : intersperse,
778+ reverse : function(s) { return s.split("").reverse().join(""); },
779+ toLower : function(s) { return s.toLowerCase(); },
780+ toUpper : function(s) { return s.toUpperCase(); },
781+ foldl : foldl,
782+ foldr : foldr,
783+ concat : function(ss) { return Value.listToArray(ss).join(""); },
784+ concatMap : concatMap,
785+ forall : forall,
786+ exists : exists,
787+ /*
788+ filter : filter,
789+ take:,
790+ drop:,
791+ */
792+ toText : Value.toText,
793+ properEscape : Value.properEscape
794+ };
795+}();
796+
797+return {String: {toText:Value.toText, properEscape:Value.properEscape},
798+ Char:Char,
799+ Maybe:Maybe,
800+ List:List
801+ };
802+}();
803+var Color = function() {
804+
805+ var create = function(r,g,b,a) {
806+ return { r: r,
807+ g: g,
808+ b: b,
809+ a: a };
810+ };
811+
812+ var extract = function(c) {
813+ if (c.a === 1) {
814+ return 'rgb(' + c.r + ',' + c.g + ',' + c.b + ')';
815+ }
816+ return 'rgba(' + c.r + ',' + c.g + ',' + c.b + ',' + c.a + ')';
817+ };
818+
819+ var rgba = function(r) { return function(g) { return function(b) {
820+ return function(a) { return create(r,g,b,a); }; }; };
821+ };
822+
823+ var rgb = function(r) { return function(g) { return function(b) {
824+ return create(r,g,b,1); }; };
825+ };
826+ return {black: create( 0, 0, 0,1),
827+ white: create(255,255,255,1),
828+ red : create(255, 0, 0,1),
829+ green: create( 0,255, 0,1),
830+ blue : create( 0, 0,255,1),
831+
832+ gray : create(128,128,128,1),
833+ grey : create(128,128,128,1),
834+
835+ yellow : create(255,255, 0,1),
836+ cyan : create( 0,255,255,1),
837+ magenta : create(255, 0,255,1),
838+
839+ rgba : rgba,
840+ rgb : rgb,
841+ Internal : { extract:extract }
842+ };
843+}();
844+var Element = function() {
845+ var newElement = function(elementType) {
846+ var e = document.createElement(elementType);
847+ e.id = Guid.guid();
848+ //e.timesAdded = 0;
849+ return e;
850+ };
851+ var addTo = function(container, elem) {
852+ container.appendChild(clone(elem));
853+ //elem.timesAdded += 1;
854+ };
855+ var clone = function(e) {
856+ return e;
857+ /*if (e.timesAdded === 0) { return e; }
858+ if (e.tagName === "CANVAS") {
859+ var newCanvas = e.cloneNode(true);
860+ var ctx = newCanvas.getContext('2d');
861+ ctx.drawImage(e, 0, 0);
862+ return newCanvas;
863+ } else if (e.tagName === "IMG") {
864+ d = image([]);
865+ d.src = e.src;
866+ d.name = e.name;
867+ if (e.style.width !== "") { d.style.width = d.width = e.style.width; }
868+ if (e.style.height !== ""){d.style.height = d.height = e.style.height;}
869+ return d;
870+ } else if (e.hasOwnProperty('isElmLeaf')) {
871+ return e.cloneNode(true);
872+ } else {
873+ d = e.cloneNode(false);
874+ var kids = e.childNodes;
875+ var len = kids.length;
876+ for (var i = 0; i < len; i++) {
877+ d.appendChild(clone(kids[i]));
878+ }
879+ return d;
880+ }*/
881+ };
882+ var divify = function(e) {
883+ var div = newElement('div');
884+ addTo(div, e);
885+ return div;
886+ };
887+
888+ var rectangle = function(w) { return function(h) {
889+ var e = newElement('div');
890+ e.isElmLeaf = true;
891+ e.style.width = w + "px";
892+ e.style.height = h + "px";
893+ return e;
894+ };
895+ };
896+
897+ var makeText = function(w) { return function(pos) { return function(txt) {
898+ var e = newElement('div');
899+ e.isElmLeaf = true;
900+ e.isElmText = true;
901+ e.innerHTML = txt;
902+ e.style.textAlign = pos;
903+ if (w > 0) e.style.width = w + "px";
904+ return e;
905+ };
906+ };
907+ };
908+ var correctTextSize = function(e) {
909+ var w = e.style.width ? e.style.width.slice(0,-2) : 0;
910+
911+ var t = newElement('div');
912+ t.innerHTML = e.innerHTML;
913+ t.style.textAlign = e.style.textAlign;
914+ if (w > 0) { t.style.width = w + "px"; }
915+
916+ t.style.visibility = "hidden";
917+ t.style.styleFloat = "left";
918+ t.style.cssFloat = "left";
919+
920+ document.body.appendChild(t);
921+ var cStyle = window.getComputedStyle(t);
922+ if (w <= 0) e.style.width = cStyle.getPropertyValue("width");
923+ e.style.height = cStyle.getPropertyValue("height");
924+ document.body.removeChild(t);
925+ };
926+
927+ var link = function (href) { return function (e) {
928+ var a = newElement('a');
929+ a.href = Text.fromString(href);
930+ addTo(a,e);
931+ return divify(a);
932+ };
933+ };
934+
935+ var text = makeText(0)('left');
936+ var plainText = function(str) {
937+ return makeText(0)("left")(Data.String.toText(str)); };
938+ var justifiedText = makeText(0)('justify');
939+ var centeredText = makeText(0)('center');
940+ var rightedText = makeText(0)('right');
941+ var asText = function(v) { return makeText(0)("left")(Value.show(v)); };
942+
943+ var image = function(src) {
944+ var img = newElement('img');
945+ img.isElmLeaf = true;
946+ img.onload = function() {
947+ if (img.style.width === "" && this.width > 0) {
948+ img.style.width = img.width = this.width + "px";
949+ }
950+ if (img.style.height === "" && this.height > 0) {
951+ img.style.height = img.height = this.height + "px";
952+ }
953+ Dispatcher.adjust()
954+ };
955+ img.src = Data.String.toText(src);
956+ img.name = img.src;
957+ return img;
958+ };
959+ var fittedImage = function(w) { return function(h) { return function(src) {
960+ var canvas = newElement('canvas');
961+ canvas.style.width = w + 'px';
962+ canvas.style.height = h + 'px';
963+ canvas.width = w;
964+ canvas.height = h;
965+ canvas.innerHTML = "Your browser does not support the canvas element.";
966+ canvas.isElmLeaf = true;
967+
968+ var img = newElement('img');
969+ img.onload = function() {
970+ if (canvas.getContext) {
971+ var ctx = canvas.getContext('2d');
972+ var sx = 0, sy = 0, sWidth = this.width, sHeight = this.height;
973+ if (w / h > this.width / this.height) {
974+ sHeight = this.width * h / w;
975+ sy = (this.height - sHeight) / 2
976+ } else {
977+ sWidth = this.height * w / h;
978+ sx = (this.width - sWidth) / 2
979+ }
980+ ctx.drawImage(img, sx, sy, sWidth, sHeight,
981+ 0,0, canvas.width, canvas.height);
982+ }
983+ };
984+ img.src = Data.String.toText(src);
985+ return canvas;
986+ };
987+ };
988+ };
989+
990+ var video = function(src) {
991+ src = Data.String.toText(src);
992+ var e = newElement('video');
993+ e.controls = "controls";
994+ var source = newElement('source');
995+ source.src = src;
996+ source.type = "video/" + src.substring(src.length - 3, src.length);
997+ addTo(e, source);
998+ e.isElmLeaf = true;
999+ return e;
1000+ };
1001+ var audio = function(src) {
1002+ src = Data.String.toString(src);
1003+ var e = newElement('video');
1004+ e.controls = "controls";
1005+ var source = newElement('source');
1006+ source.src = src;
1007+ source.type = "audio/" + src.substring(src.length - 3, src.length);
1008+ addTo(e, source);
1009+ e.isElmLeaf = true;
1010+ return e;
1011+ };
1012+ var collage = function(w) { return function(h) { return function(cflist) {
1013+ var canvas = newElement('canvas');
1014+ canvas.style.width = w + 'px';
1015+ canvas.style.height = h + 'px';
1016+ canvas.width = w;
1017+ canvas.height = h;
1018+ if (canvas.getContext) {
1019+ var ctx = canvas.getContext('2d');
1020+ ctx.clearRect(0,0, canvas.width, canvas.height);
1021+ while (cflist[0] === "Cons") {
1022+ ctx = cflist[1](ctx);
1023+ cflist = cflist[2];
1024+ }
1025+ return canvas;
1026+ }
1027+ canvas.innerHTML = "Your browser does not support the canvas element.";
1028+ canvas.isElmLeaf = true;
1029+ return canvas;
1030+ };
1031+ };
1032+ };
1033+
1034+ var goDown = function(e) {
1035+ return e.tagName === "DIV" ? e : divify(e);
1036+ };
1037+ var goRight = function(e) {
1038+ e.style.styleFloat = "left";
1039+ e.style.cssFloat = "left";
1040+ return e;
1041+ };
1042+ var goIn = function(e) {
1043+ e.style.position = 'absolute';
1044+ return e;
1045+ };
1046+ var flowWith = function(dir, f, elist) {
1047+ var container = newElement('div');
1048+ for (var i = elist.length; i--; ) {
1049+ addTo(container, f(elist[i]));
1050+ }
1051+ container.elmFlowDirection = dir;
1052+ return container;
1053+ };
1054+
1055+ var flow = function(direction) { return function(elist) {
1056+ var arr = [];
1057+ while (elist[0] === "Cons") {
1058+ arr.push(elist[1]);
1059+ elist = elist[2];
1060+ }
1061+ if (direction >= 3) arr.reverse();
1062+ var f = function(x) { return x; };
1063+ var dir = direction % 3;
1064+ if (dir == 0) return flowWith("Y", goDown , arr);
1065+ if (dir == 1) return flowWith("X", goRight, arr);
1066+ if (dir == 2) return flowWith("Z", goIn , arr);
1067+ };
1068+ };
1069+
1070+ var beside = function(a) { return function(b) {
1071+ return flow(4)(["Cons",a,["Cons",b,["Nil"]]]); }; };
1072+ var above = function(a) { return function(b) {
1073+ return flow(3)(["Cons",a,["Cons",b,["Nil"]]]); }; };
1074+ var below = function(a) { return function(b) {
1075+ return flow(0)(["Cons",a,["Cons",b,["Nil"]]]); }; };
1076+
1077+ var box = function(pos) { return function(e) {
1078+ e.style.position = "absolute";
1079+ e.style.margin = "auto";
1080+ var x = (pos - 1) % 3;
1081+ var y = (pos - 1) / 3;
1082+ if (x < 2) e.style.left = 0;
1083+ if (x > 0) e.style.right = 0;
1084+ if (y < 2) e.style.top = 0;
1085+ if (y > 0) e.style.bottom = 0;
1086+ var div = newElement('div');
1087+ div.style.position = "relative";
1088+ addTo(div,e);
1089+ return div;
1090+ };
1091+ };
1092+
1093+ var width = function(w) { return function(e) {
1094+ if (e.tagName === "A") {
1095+ width(w)(e.firstChild);
1096+ return e;
1097+ }
1098+ if (e.hasOwnProperty('isElmText')) {
1099+ var d = makeText(w)(e.style.textAlign)(e.innerHTML);
1100+ e.style.height = d.style.height;
1101+ }
1102+ e.style.width = w + "px";
1103+ return e;
1104+ };
1105+ };
1106+ var height = function(h) { return function(e) {
1107+ (e.tagName === "A" ? e.firstChild : e).style.height = h + "px";
1108+ return e;
1109+ };
1110+ };
1111+ var size = function(w) { return function(h) { return function(e) {
1112+ var d = e.tagName === "A" ? e.firstChild : e;
1113+ d.style.width = w + "px";
1114+ d.style.height = h + "px";
1115+ return e;
1116+ };
1117+ };
1118+ };
1119+
1120+ var color = function(c) { return function(e) {
1121+ e.style.backgroundColor = Color.Internal.extract(c);
1122+ return e;
1123+ };
1124+ };
1125+ var opacity = function(value) { return function(e) {
1126+ e.style.opacity = value;
1127+ return e;
1128+ };
1129+ };
1130+
1131+ var jsElement = function(w) { return function(h) { return function(elem) {
1132+ var e = newElement('div');
1133+ e.isElmLeaf = true;
1134+ e.style.width = w + "px";
1135+ e.style.height = h + "px";
1136+ addTo(e,elem);
1137+ return e;
1138+ };
1139+ };
1140+ };
1141+
1142+ return {text : text,
1143+ image : image,
1144+ fittedImage : fittedImage,
1145+ video : video,
1146+ audio : audio,
1147+ collage : collage,
1148+ flow : flow,
1149+ layers : flow(2),
1150+ rectangle : rectangle,
1151+
1152+ beside : beside,
1153+ above : above,
1154+ below : below,
1155+ box : box,
1156+
1157+ width : width,
1158+ height : height,
1159+ size : size,
1160+ color : color,
1161+ opacity : opacity,
1162+
1163+ link : link,
1164+ asText : asText,
1165+ plainText : plainText,
1166+ justifiedText : justifiedText,
1167+ centeredText : centeredText,
1168+ rightedText : rightedText,
1169+
1170+ // directions
1171+ up : 0,
1172+ left : 1,
1173+ inward : 2,
1174+ down : 3,
1175+ right : 4,
1176+ outward : 5,
1177+
1178+ correctTextSize : correctTextSize,
1179+ jsElement : jsElement
1180+ };
1181+}();
1182+
1183+
1184+
1185+var Text = function() {
1186+ var fromString = function(elmList) {
1187+ if (typeof elmList === "string") return elmList;
1188+ var a = [];
1189+ while (elmList[0] === "Cons") {
1190+ a.push(elmList[1]);
1191+ elmList = elmList[2];
1192+ }
1193+ return Data.String.properEscape(a.join(''));
1194+ };
1195+
1196+ var addTag = function(tag) { return function(text) {
1197+ return '<' + tag + '>' + text + '</' + tag + '>';
1198+ };
1199+ };
1200+ var addStyle = function(style, value) { return function(text) {
1201+ return "<span style='" + style + ":" + value + "'>" + text + "</span>";
1202+ };
1203+ };
1204+
1205+ var typeface = function(name) { return addStyle('font-family', name); };
1206+ var size = function(px) {
1207+ return addStyle('font-size', px + 'px');
1208+ };
1209+ var header = addTag('h1');
1210+ var height = function(h) { return addStyle('font-size', h+'em'); }
1211+ var italic = addStyle('font-style', 'italic');
1212+ var bold = addTag('b');
1213+ var color = function(c) {
1214+ return addStyle('color', Color.Internal.extract(c));
1215+ };
1216+ var underline = addStyle('text-decoration', 'underline');
1217+ var overline = addStyle('text-decoration', 'overline');
1218+ var strikeThrough = addStyle('text-decoration', 'line-through');
1219+ var link = function(href) { return function(text) {
1220+ return "<a href='" + fromString(href) + "'>" + text + "</a>";
1221+ };
1222+ };
1223+
1224+ return {fromString : fromString,
1225+ toText: fromString,
1226+ header : header,
1227+ height : height,
1228+ italic : italic,
1229+ bold : bold,
1230+ underline : underline,
1231+ overline : overline,
1232+ strikeThrough : strikeThrough,
1233+ monospace : typeface('monospace'),
1234+ color : color,
1235+ link : link };
1236+}();
1237+var Shape = function() {
1238+
1239+ var create = function(center, ps, theta, s) {
1240+ return { center: center, points: ps, theta: theta, scale: s };
1241+ };
1242+
1243+ //// Construction ////
1244+
1245+ var polygon = function(ps) { return function(center) {
1246+ var parr = [];
1247+ while (ps[0] === "Cons") {
1248+ parr.push([ps[1][1], ps[1][2]]);
1249+ ps = ps[2];
1250+ }
1251+ center = [center[1], center[2]];
1252+ return create(center, parr, 0, 1);
1253+ };
1254+};
1255+ var ngon = function(n) { return function(r) { return function(center) {
1256+ var ps = [];
1257+ for (var i = n; i--;) {
1258+ ps.push([r * Math.cos(Math.PI * 2 * i/n),
1259+ r * Math.sin(Math.PI * 2 * i/n)]);
1260+ }
1261+ center = [center[1], center[2]];
1262+ return create(center, ps, 0, 1);
1263+ };
1264+ };
1265+};
1266+ var rect = function(w) { return function(h) { return function(center) {
1267+ var ps = [[- w/2, - h/2],
1268+ [ w/2, - h/2],
1269+ [ w/2, h/2],
1270+ [- w/2, h/2]];
1271+ center = [center[1], center[2]];
1272+ return create(center, ps, 0, 1);
1273+ };
1274+ };
1275+ };
1276+ var oval = function(w) { return function(h) { return function(center) {
1277+ var ps = [];
1278+ for (var theta = 2 * Math.PI; theta > 0; theta -= Math.PI /50) {
1279+ ps.push([w/2 * Math.cos(theta), h/2 * Math.sin(theta)]);
1280+ }
1281+ center = [center[1], center[2]];
1282+ return create(center, ps, 0, 1);
1283+ };
1284+ };
1285+ };
1286+
1287+//// Transforms ////
1288+
1289+ var move = function(x) { return function(y) { return function(shape) {
1290+ var newCenter = [x + shape.center[0],y + shape.center[1]];
1291+ return create(newCenter, shape.points, shape.theta, shape.scale);
1292+ };
1293+ };
1294+ };
1295+ var rotate = function(theta) { return function(shape) {
1296+ var newTheta = shape.theta + 2 * Math.PI * theta;
1297+ return create(shape.center, shape.points, newTheta, shape.scale);
1298+ };
1299+ };
1300+ var scale = function(s) { return function(shape) {
1301+ return create(shape.center, shape.points, shape.theta, shape.scale * s);
1302+ };
1303+ };
1304+
1305+
1306+ //// Atomize ////
1307+
1308+ var draw = function(fill) {
1309+ return function(color) { return function(shape) { return function(ctx) {
1310+ ctx.save();
1311+ ctx.translate(shape.center[0], shape.center[1]);
1312+ ctx.rotate(shape.theta);
1313+ ctx.scale(shape.scale, shape.scale);
1314+ ctx.beginPath();
1315+ var points = shape.points;
1316+ ctx.moveTo(points[0][0], points[0][1]);
1317+ for (var i = points.length; i--; ) {
1318+ ctx.lineTo(points[i][0], points[i][1]);
1319+ }
1320+ ctx.closePath();
1321+ if (fill) {
1322+ ctx.fillStyle = Color.Internal.extract(color);
1323+ ctx.fill();
1324+ } else {
1325+ ctx.strokeStyle = Color.Internal.extract(color);
1326+ ctx.stroke();
1327+ }
1328+ ctx.restore();
1329+ return ctx;
1330+ };
1331+ };
1332+ };
1333+ };
1334+
1335+ var customOutline = function(p) {
1336+ return function(c) { return function(shape) {
1337+ shape.points.push(shape.points[0]);
1338+ return Line.customLine(p)(c)(shape);
1339+ };
1340+ };
1341+ };
1342+ return {polygon:polygon, ngon:ngon, rect:rect, oval:oval,
1343+ move:move, rotate:rotate, scale:scale,
1344+ filled:draw(true), outlined:draw(false), customOutline:customOutline };
1345+}();
1346+var Line = function() {
1347+
1348+ var pair = function(a,b) { return [a,b]; };
1349+
1350+ var create = function(center, ps, theta, s) {
1351+ return { center: center, points: ps, theta: theta, scale: s };
1352+ };
1353+
1354+
1355+ //// Construction ////
1356+
1357+ var line = function(ps) {
1358+ var parr = [];
1359+ while (ps[0] === "Cons") {
1360+ parr.push(pair(ps[1][1], ps[1][2]));
1361+ ps = ps[2];
1362+ }
1363+ return create(pair(0,0), parr, 0, 1);
1364+ };
1365+
1366+ //// Atomize ////
1367+
1368+ var solid = function(color) { return function(line) { return function(ctx) {
1369+ ctx.save();
1370+ ctx.beginPath();
1371+ ctx.translate(line.center[0], line.center[1]);
1372+ ctx.rotate(line.theta);
1373+ ctx.scale(line.scale, line.scale);
1374+ var points = line.points;
1375+ var i = points.length;
1376+ ctx.moveTo(points[i-1][0], points[i-1][1]);
1377+ while (i--) {
1378+ ctx.lineTo(points[i][0], points[i][1]);
1379+ }
1380+ ctx.strokeStyle = Color.Internal.extract(color);
1381+ ctx.stroke();
1382+ ctx.restore();
1383+ return ctx;
1384+ };
1385+ };
1386+ };
1387+
1388+ var customLine = function(pattern) {
1389+ return function(color) { return function(line) {
1390+ if (typeof pattern[0] === "string") {
1391+ var temp = [];
1392+ while (pattern[0] === "Cons") {
1393+ temp.push(pattern[1]);
1394+ pattern = pattern[2];
1395+ }
1396+ pattern = temp;
1397+ }
1398+ if (pattern.length === 0) { pattern = [8,4]; }
1399+ return function(ctx) {
1400+ ctx.save();
1401+ ctx.beginPath();
1402+ ctx.translate(line.center[0], line.center[1]);
1403+ ctx.rotate(line.theta);
1404+ ctx.scale(line.scale, line.scale);
1405+ customLineHelp(ctx, pattern, line.points);
1406+ ctx.strokeStyle = Color.Internal.extract(color);
1407+ ctx.stroke();
1408+ ctx.restore();
1409+ return ctx;
1410+ };
1411+ };
1412+ };
1413+ };
1414+ var customLineHelp = function(ctx, pattern, points) {
1415+ var i = points.length - 1;
1416+ var x0 = points[i][0], y0 = points[i][1];
1417+ var x1=0, y1=0, dx=0, dy=0, remaining=0, nx=0, ny=0;
1418+ var pindex = 0, plen = pattern.length;
1419+ var draw = true, segmentLength = pattern[0];
1420+ ctx.moveTo(x0,y0);
1421+ while (i--) {
1422+ x1 = points[i][0]; y1 = points[i][1];
1423+ dx = x1 - x0; dy = y1 - y0;
1424+ remaining = Math.sqrt(dx * dx + dy * dy);
1425+ while (segmentLength <= remaining) {
1426+ x0 += dx * segmentLength / remaining;
1427+ y0 += dy * segmentLength / remaining;
1428+ ctx[draw ? 'lineTo' : 'moveTo'](x0, y0);
1429+ // update starting position
1430+ dx = x1 - x0; dy = y1 - y0;
1431+ remaining = Math.sqrt(dx * dx + dy * dy);
1432+ // update pattern
1433+ draw = !draw;
1434+ pindex = (pindex + 1) % plen;
1435+ segmentLength = pattern[pindex];
1436+ }
1437+ if (remaining > 0) {
1438+ ctx[draw ? 'lineTo' : 'moveTo'](x1, y1);
1439+ segmentLength -= remaining;
1440+ }
1441+ x0 = x1; y0 = y1;
1442+ }
1443+ };
1444+
1445+ return {line:line, customLine:customLine, solid:solid,
1446+ dashed: customLine([8,4]), dotted: customLine([3,3]) };
1447+}();
1448+
1449+var Elm = function() {
1450+ var send = function(kids, timestep, changed) {
1451+ for (var i = kids.length; i--; ) {
1452+ kids[i].recv(timestep, changed);
1453+ }
1454+ };
1455+ var input = function(base) {
1456+ this.id = Guid.guid();
1457+ this.value = base;
1458+ this.kids = [];
1459+ this.recv = function(timestep, eid, v) {
1460+ var changed = eid === this.id;
1461+ if (changed) { this.value = v; }
1462+ send(this.kids, timestep, changed);
1463+ };
1464+ Dispatcher.inputs.push(this);
1465+ };
1466+ var lift = function(func,args) {
1467+ this.id = Guid.guid();
1468+ this.value = null;
1469+ this.kids = [];
1470+ this.inbox = {};
1471+
1472+ args.reverse();
1473+ this.recalc = function() {
1474+ var f = func;
1475+ for (var i = args.length; i--; ) {
1476+ f = f(args[i].value);
1477+ }
1478+ this.value = f;
1479+ };
1480+ this.recalc();
1481+
1482+ this.recv = function(timestep, changed) {
1483+ if (!this.inbox.hasOwnProperty(timestep)) {
1484+ this.inbox[timestep] = { changed: false, count: 0 };
1485+ }
1486+ var box = this.inbox[timestep];
1487+ box.count += 1;
1488+ if (changed) { box.changed = true; }
1489+ if (box.count == args.length) {
1490+ if (box.changed) { this.recalc() }
1491+ send(this.kids, timestep, box.changed);
1492+ delete this.inbox[timestep];
1493+ }
1494+ };
1495+ for (var i = args.length; i--; ) {
1496+ args[i].kids.push(this);
1497+ }
1498+ };
1499+ var fold = function(func,base,input) {
1500+ this.id = Guid.guid();
1501+ this.value = base;
1502+ this.kids = [];
1503+ this.recv = function(timestep, changed) {
1504+ if (changed) { this.value = func(input.value)(this.value); }
1505+ send(this.kids, timestep, changed);
1506+ };
1507+ input.kids.push(this);
1508+ };
1509+
1510+ var dropIf = function(pred,base,input) {
1511+ this.id = Guid.guid();
1512+ this.value = pred(input.value) ? base : input.value;
1513+ this.kids = [];
1514+ this.recv = function(timestep, changed) {
1515+ var chng = changed && !pred(input.value);
1516+ if (chng) { this.value = input.value; }
1517+ send(this.kids, timestep, chng);
1518+ };
1519+ input.kids.push(this);
1520+ };
1521+ var dropRepeats = function(input) {
1522+ this.id = Guid.guid();
1523+ this.value = input.value;
1524+ this.kids = [];
1525+ this.recv = function(timestep, changed) {
1526+ var chng = changed && !eq(this.value,input.value);
1527+ if (chng) { this.value = input.value; }
1528+ send(this.kids, timestep, chng);
1529+ };
1530+ input.kids.push(this);
1531+ };
1532+
1533+ var dropWhen = function(s1) { return function(b) { return function(s2) {
1534+ var pairs = new lift(function(x){return function(y){return [x,y];};},[s1,s2]);
1535+ var dropped = new dropIf(function(p){return p[0];},[true,b],pairs);
1536+ return new lift(function(p){return p[1];},[dropped]); }; };
1537+ };
1538+
1539+ return {Input: function(x) {return new input(x);},
1540+ Lift: function(f,xs){return new lift(f,xs);},
1541+ Fold: function(f,b,x){return new fold(f,b,x);},
1542+ keepIf : function(pred) { return function(base) { return function(sig) {
1543+ return new dropIf(function(x) { return !pred(x)},base,sig); }; }; },
1544+ dropIf : function(pred) { return function(base) { return function(sig) {
1545+ return new dropIf(pred,base,sig); }; }; },
1546+ keepWhen : function(s) { return dropWhen(new lift(function(b){return !b;},[s])); },
1547+ dropWhen : dropWhen,
1548+ dropRepeats : function(s) { return new dropRepeats(s);}
1549+ };
1550+}();
1551+
1552+var Dispatcher = function() {
1553+ var program = null;
1554+ var timestep = 0;
1555+ var inputs = [];
1556+
1557+ var correctSize = function(e) {
1558+ var kids = e.childNodes;
1559+ var len = kids.length;
1560+ if (e.hasOwnProperty('isElmLeaf')) {
1561+ if (e.hasOwnProperty('isElmText')) { Element.correctTextSize(e); }
1562+ var w = e.style.width === "" ?
1563+ 0 : e.style.width.slice(0,-2) - 0;
1564+ var h = e.style.height === "" ?
1565+ 0 : e.style.height.slice(0,-2) - 0;
1566+ return [w, h];
1567+ }
1568+ if (len === 1) {
1569+ var dim = correctSize(kids[0]);
1570+ if (e.style.width !== "") { dim[0] = e.style.width.slice(0,-2) - 0; }
1571+ if (e.style.height !== "") { dim[1] = e.style.height.slice(0,-2) - 0; }
1572+ if (dim[0] !== 0) { e.style.width = dim[0] + "px"; }
1573+ if (dim[1] !== 0) { e.style.height = dim[1] + "px"; }
1574+ return dim;
1575+ }
1576+ var wmax = 0, hmax = 0, wsum = 0, hsum = 0;
1577+ var hasWidth = true, hasHeight = true, dim = null;
1578+ while (len--) {
1579+ dim = correctSize(kids[len]);
1580+ wmax = Math.max(wmax, dim[0]);
1581+ hmax = Math.max(hmax, dim[1]);
1582+ wsum += dim[0];
1583+ hsum += dim[1];
1584+ hasWidth = hasWidth && dim[0] > 0;
1585+ hasHeight = hasHeight && dim[1] > 0;
1586+ }
1587+ var w = wmax, h = hmax, dir = e.elmFlowDirection;
1588+ if (dir === "X") { w = hasWidth ? wsum : 0; }
1589+ if (dir === "Y") { h = hasHeight ? hsum : 0; }
1590+ if (w > 0) e.style.width = w + "px";
1591+ if (h > 0) e.style.height = h + "px";
1592+ return [w,h];
1593+ };
1594+
1595+ var initialize = function() {
1596+ program = ElmCode.main();
1597+ if (!program.hasOwnProperty('recv')) {
1598+ program = Elm.Input(program);
1599+ }
1600+ var content = document.getElementById('content');
1601+ content.appendChild(program.value);
1602+ adjust();
1603+ var w = document.getElementById('widthChecker').offsetWidth;
1604+ if (w !== window.innerWidth) {
1605+ Dispatcher.notify(Window.dimensions.id, Value.Tuple(w, window.innerHeight));
1606+ }
1607+ program = Elm.Lift(function(value) {
1608+ var content = document.getElementById('content');
1609+ var kid = content.children[0]
1610+ content.replaceChild(value, kid);
1611+ delete kid;
1612+ adjust();
1613+ return value;
1614+ }, [program]);
1615+ };
1616+ var adjust = function() {
1617+ var content = document.getElementById('content');
1618+ correctSize(content.children[0]);
1619+ }
1620+ var notify = function(id, v) {
1621+ timestep += 1;
1622+ for (var i = inputs.length; i--; ) {
1623+ inputs[i].recv(timestep, id, v);
1624+ }
1625+ };
1626+ return {initialize:initialize, notify:notify, adjust:adjust, inputs:inputs};
1627+}();
1628+var Signal = function() {
1629+ function toElmString(str) {
1630+ var out = ["Nil"];
1631+ for (var i = str.length; i--; ) {
1632+ out = ["Cons", str[i], out];
1633+ }
1634+ return out;
1635+ }
1636+ var addListener = function() {
1637+ if(document.addEventListener) {
1638+ return function(element, event, handler) {
1639+ element.addEventListener(event, handler, false);
1640+ };
1641+ }
1642+ else {
1643+ return function(element, event, handler) {
1644+ element.attachEvent('on' + event, handler);
1645+ };
1646+ }
1647+ }();
1648+
1649+ var Mouse = function() {
1650+ var position = Elm.Input(Value.Tuple(0,0));
1651+ var isDown = Elm.Input(false);
1652+ var isClicked = Elm.Input(false);
1653+
1654+ function getXY(e) {
1655+ var posx = 0;
1656+ var posy = 0;
1657+ if (!e) var e = window.event;
1658+ if (e.pageX || e.pageY) {
1659+ posx = e.pageX;
1660+ posy = e.pageY;
1661+ } else if (e.clientX || e.clientY) {
1662+ posx = e.clientX + document.body.scrollLeft +
1663+ document.documentElement.scrollLeft;
1664+ posy = e.clientY + document.body.scrollTop +
1665+ document.documentElement.scrollTop;
1666+ }
1667+ return Value.Tuple(posx, posy);
1668+ }
1669+
1670+ addListener(document, 'click', function(e) {
1671+ Dispatcher.notify(isClicked.id, true);
1672+ Dispatcher.notify(isClicked.id, false);
1673+ });
1674+ addListener(document, 'mousedown', function(e) {
1675+ Dispatcher.notify(isDown.id, true); });
1676+ addListener(document, 'mouseup', function(e) {
1677+ Dispatcher.notify(isDown.id, false); });
1678+ addListener(document, 'mousemove', function(e) {
1679+ Dispatcher.notify(position.id, getXY(e)); });
1680+ var clickedOn = function(elem) {
1681+ var click = Elm.Input(false);
1682+ addListener(elem, 'click', function(e) {
1683+ Dispatcher.notify(click.id, true);
1684+ Dispatcher.notify(click.id, false);
1685+ });
1686+ return Value.Tuple(elem, click);
1687+ };
1688+ return {position: position,
1689+ x: Elm.Lift(function(p){return p[1];},[position]),
1690+ y: Elm.Lift(function(p){return p[2];},[position]),
1691+ isClicked: isClicked,
1692+ isDown: isDown,
1693+ clickedOn: clickedOn
1694+ };
1695+ }();
1696+
1697+ var Time = function() {
1698+ var every = function(t) {
1699+ t *= 1000;
1700+ var clock = Elm.Input(0);
1701+ var time = 0;
1702+ setInterval(function() {
1703+ time += t;
1704+ Dispatcher.notify(clock.id, time/1000);
1705+ }, t);
1706+ return clock;
1707+ };
1708+ var after = function(t) {
1709+ t *= 1000;
1710+ var thread = Elm.Input(false);
1711+ setTimeout(function() { Dispatcher.notify(thread.id, true); }, t);
1712+ return thread;
1713+ };
1714+ var before = function(t) {
1715+ t *= 1000;
1716+ var thread = Elm.Input(true);
1717+ setTimeout(function() { Dispatcher.notify(thread.id, false); }, t);
1718+ return thread;
1719+ };
1720+ return {every:every,after:after,before:before};
1721+ }();
1722+
1723+ var Window = function() {
1724+ var dimensions = Elm.Input(Value.Tuple(window.innerWidth,window.innerHeight));
1725+ addListener(window, 'resize', function(e) {
1726+ var w = document.getElementById('widthChecker').offsetWidth;
1727+ Dispatcher.notify(dimensions.id, Value.Tuple(w, window.innerHeight));
1728+ });
1729+ return {dimensions:dimensions,
1730+ width : Elm.Lift(function(p){return p[1];},[dimensions]),
1731+ height: Elm.Lift(function(p){return p[2];},[dimensions]) };
1732+ }();
1733+
1734+ var Keyboard = { Raw : function() {
1735+ var keysDown = Elm.Input(["Nil"]);
1736+ var charPressed = Elm.Input(["Nothing"]);
1737+ function remove(x,xs) {
1738+ if (xs[0] === "Nil") return xs;
1739+ if (xs[1] === x) return xs[2];
1740+ return ["Cons", xs[1], remove(x,xs[2])];
1741+ }
1742+ function has(x,xs) {
1743+ while (xs[0] !== "Nil") {
1744+ if (xs[1] === x) return true;
1745+ xs = xs[2];
1746+ }
1747+ return false;
1748+ }
1749+ addListener(document, 'keydown', function(e) {
1750+ if (has(e.keyCode, keysDown.value)) return;
1751+ Dispatcher.notify(keysDown.id, ["Cons", e.keyCode, keysDown.value]);
1752+ });
1753+ addListener(document, 'keyup', function(e) {
1754+ var codes = remove(e.keyCode, keysDown.value)
1755+ Dispatcher.notify(keysDown.id, codes);
1756+ });
1757+ addListener(window, 'blur', function(e) {
1758+ Dispatcher.notify(keysDown.id, ["Nil"]);
1759+ });
1760+ addListener(document, 'keypress', function(e) {
1761+ Dispatcher.notify(charPressed.id, ["Just",e.charCode || e.keyCode]);
1762+ Dispatcher.notify(charPressed.id, ["Nothing"]);
1763+ });
1764+ return {keysDown:keysDown,
1765+ charPressed:charPressed};
1766+ }()
1767+ };
1768+
1769+ var HTTP = function() {
1770+ var fetch = function(how) { return function(url) {
1771+ var thread = Elm.Input(["Waiting"]);
1772+ var request = {};
1773+ if (window.XMLHttpRequest) { request = new XMLHttpRequest(); }
1774+ else if (window.ActiveXObject) { request = new ActiveXObject("Microsoft.XMLHTTP"); }
1775+ request.onreadystatechange = function(e) {
1776+ if (request.readyState === 4) {
1777+ Dispatcher.notify(thread.id,
1778+ request.status === 200
1779+ ? ["Success", toElmString(request.responseText)]
1780+ : ["Failure", request.status, toElmString(request.statusText)]);
1781+ }
1782+ };
1783+ request.open(how, Data.String.toText(url), true);
1784+ request.send(null);
1785+ return thread;
1786+ };
1787+ };
1788+ var fetches = function(how) { return function(input) {
1789+ var output = Elm.Input(["Nothing"]);
1790+ var fetcher = Elm.Lift(update, [input]);
1791+ var combine = Elm.Lift(function(x) { return function(y) { return x; } }, [output,fetcher]);
1792+ function update(strOpt) {
1793+ if (strOpt[0] !== "Just") {
1794+ try { Dispatcher.notify(output.id, ["Nothing"]); } catch(e) {}
1795+ return [];
1796+ }
1797+ try {
1798+ Dispatcher.notify(output.id, ["Just", ["Waiting"]]);
1799+ } catch(e) { output.value = ["Just", ["Waiting"]]; }
1800+ var request = {};
1801+ if (window.XMLHttpRequest) { request = new XMLHttpRequest(); }
1802+ else if (window.ActiveXObject) { request = new ActiveXObject("Microsoft.XMLHTTP"); }
1803+ request.onreadystatechange = function(e) {
1804+ if (request.readyState === 4) {
1805+ Dispatcher.notify(output.id,
1806+ ["Just", request.status === 200
1807+ ? ["Success", toElmString(request.responseText)]
1808+ : ["Failure", request.status, toElmString(request.statusText)]]);
1809+ }
1810+ };
1811+ request.open(how, Data.String.toText(strOpt[1]), true);
1812+ request.send(null);
1813+ return [];
1814+ }
1815+ return combine;
1816+ };
1817+ };
1818+ return {get : fetch("GET"), post : fetch("POST"),
1819+ gets : fetches("GET"), posts : fetches("POST") };
1820+ }();
1821+ var Random = function() {
1822+ var inRange = function(min) { return function(max) {
1823+ return Elm.Input(Math.floor(Math.random() * (max-min+1)) + min);
1824+ };
1825+ };
1826+ var randomize = function(min) { return function(max) { return function(signal) {
1827+ return Elm.Lift(function(x) { return Math.floor(Math.random() * (max-min+1)) + min;},[signal]);
1828+ };
1829+ };
1830+ };
1831+ return { inRange:inRange, randomize:randomize };
1832+ }();
1833+ var Input = function() {
1834+ var newTextInput = function(elem, ghostText) {
1835+ elem.isElmLeaf = true;
1836+ var str = Elm.Input(["Nil"]);
1837+ addListener(elem, 'keyup', function(e) {
1838+ Dispatcher.notify(str.id, toElmString(elem.value));
1839+ elem.focus();
1840+ });
1841+ return Value.Tuple(elem, str);
1842+ };
1843+ var newElement = function(name) {
1844+ var e = document.createElement(name);
1845+ e.id = Guid.guid();
1846+ return e;
1847+ };
1848+ var textArea = function(cols) { return function(rows) {
1849+ var textarea = newElement('textarea');
1850+ textarea.rows = rows;
1851+ textarea.cols = cols;
1852+ return newTextInput(textarea, "");
1853+ };
1854+ };
1855+ var textField = function(ghostText) {
1856+ var field = newElement('input');
1857+ field.type = 'text';
1858+ return newTextInput(field, ghostText);
1859+ };
1860+ var password = function(ghostText) {
1861+ var field = newElement('input');
1862+ field.type = 'password';
1863+ return newTextInput(field, ghostText);
1864+ };
1865+ var checkbox = function(checked) {
1866+ var box = newElement('input');
1867+ box.type = 'checkbox';
1868+ box.checked = checked;
1869+ var status = Elm.Input(checked);
1870+ addListener(box, 'change', function(e) {
1871+ Dispatcher.notify(status.id, box.checked);
1872+ });
1873+ return Value.Tuple(box, status);
1874+ };
1875+ var dropDown = function(options) {
1876+ var slct = newElement('select');
1877+ var opts = [];
1878+ while (options[0] === "Cons") {
1879+ var opt = newElement('option');
1880+ var str = Text.toText(options[1][1]);
1881+ opt.value = str;
1882+ opt.innerHTML = str;
1883+ slct.appendChild(opt);
1884+ opts.push(options[1][2]);
1885+ options = options[2];
1886+ }
1887+ var status = Elm.Input(opts[0]);
1888+ addListener(slct, 'change', function(e) {
1889+ Dispatcher.notify(status.id, opts[slct.selectedIndex]);
1890+ });
1891+ return Value.Tuple(slct, status);
1892+ };
1893+ var stringDropDown = function(opts) {
1894+ return dropDown(List.map (function(x) {return Value.Tuple(x,x);}) (opts));
1895+ };
1896+ var button = function(name) {
1897+ var b = newElement('input');
1898+ b.type = "button";
1899+ b.value = Text.toText(name);
1900+ var press = Elm.Input(false);
1901+ addListener(b, 'click', function(e) {
1902+ Dispatcher.notify(press.id, true);
1903+ Dispatcher.notify(press.id, false);
1904+ });
1905+ return Value.Tuple(b,press);
1906+ };
1907+ return {textArea:textArea, textField:textField,
1908+ password:password, checkbox:checkbox,
1909+ dropDown:dropDown, stringDropDown:stringDropDown,
1910+ button:button};
1911+ }();
1912+
1913+ return {Mouse:Mouse,
1914+ Keyboard:Keyboard,
1915+ Time:Time,
1916+ Window:Window,
1917+ HTTP:HTTP,
1918+ Random:Random,
1919+ Input:Input,
1920+ constant : function(v) { return Elm.Input(v); },
1921+ lift : function(f){return function(e){return Elm.Lift(f,[e]);};},
1922+ lift2 : function(f) { return function(e1) { return function(e2) {
1923+ return Elm.Lift(f, [e1,e2]); }; }; },
1924+ lift3 : function(f) { return function(e1) { return function(e2) {
1925+ return function(e3){return Elm.Lift(f,[e1,e2,e3]);};};};},
1926+ lift4 : function(f) { return function(e1) { return function(e2) {
1927+ return function(e3) { return function(e4) {
1928+ return Elm.Lift(f, [e1,e2,e3,e4]); }; }; }; }; },
1929+ foldp : function(f) { return function(b) { return function(e) {
1930+ return Elm.Fold(f,b,e); }; }; },
1931+ count : function(sig){return Elm.fold(function(c){return c+1},0,sig)},
1932+ keepIf : Elm.keepIf,
1933+ dropIf : Elm.dropIf,
1934+ keepWhen : Elm.keepWhen,
1935+ dropWhen : Elm.dropWhen,
1936+ dropRepeats : Elm.dropRepeats
1937+ };
1938+}();
1939+var Prelude = function() {
1940+ var mod = function(x) { return function(y) {
1941+ var r = x % y;
1942+ var m = x==0 ? 0 : (y>0 ? (x>=0 ? r : r+y) : -mod(-x)(-y));
1943+ return m == y ? 0 : m;
1944+ }; };
1945+
1946+ var min = function(x) { return function(y) { return Math.min(x,y); }; };
1947+ var max = function(x) { return function(y) { return Math.max(x,y); }; };
1948+
1949+ var flip=function(f){return function(x){return function(y){return f(y)(x);};};};
1950+ var clamp = function(lo) { return function(hi) {
1951+ return function(x) { return Math.min(hi, Math.max(lo, x)); };
1952+ };
1953+ };
1954+ var curry = function(f) { return function(x) { return function(y) {
1955+ return f(["Tuple2",x,y]); }; };
1956+ };
1957+ var uncurry = function(f) { return function(p) {
1958+ if (p[0] !== "Tuple2") {
1959+ throw "Function was uncurry'd but was not given a pair.";
1960+ }
1961+ return f(p[1])(p[2]); };
1962+ };
1963+
1964+ var logBase=function(b){return function(x){return Math.log(x)/Math.log(b);};};
1965+
1966+ return {id : function(x) { return x; },
1967+ not : function(b) { return !b; },
1968+ fst : function(p) { return p[1]; },
1969+ snd : function(p) { return p[2]; },
1970+ rem : function(x) { return function(y) { return x % y; }; },
1971+ sqrt : Math.sqrt,
1972+ abs : Math.abs,
1973+ pi : Math.PI,
1974+ sin : Math.sin,
1975+ cos : Math.cos,
1976+ tan : Math.tan,
1977+ asin : Math.asin,
1978+ acos : Math.acos,
1979+ atan : Math.atan,
1980+ mod : mod,
1981+ min : min,
1982+ max : max,
1983+ flip : flip,
1984+ clamp : clamp,
1985+ curry : curry,
1986+ uncurry : uncurry,
1987+ logBase : logBase,
1988+ Just : Data.Maybe.Just,
1989+ Nothing : Data.Maybe.Nothing,
1990+ maybe : Data.Maybe.maybe,
1991+ map : Data.List.map,
1992+ filter : Data.List.filter,
1993+ head : Data.List.head,
1994+ tail : Data.List.tail,
1995+ length : Data.List.length,
1996+ reverse : Data.List.reverse,
1997+ foldr : Data.List.foldr,
1998+ foldr1 : Data.List.foldr1,
1999+ foldl : Data.List.foldl,
2000+ foldl1 : Data.List.foldl1,
2001+ and : Data.List.and,
2002+ or : Data.List.or,
2003+ forall : Data.List.forall,
2004+ exists : Data.List.exists,
2005+ sum : Data.List.sum,
2006+ product : Data.List.product,
2007+ concat : Data.List.concat,
2008+ concatMap : Data.List.concatMap,
2009+ maximum : Data.List.maximum,
2010+ minimum : Data.List.minimum,
2011+ scanl : Data.List.scanl,
2012+ scanl1 : Data.List.scanl1,
2013+ take : Data.List.take,
2014+ drop : Data.List.drop,
2015+ lift : Signal.lift,
2016+ lift2 : Signal.lift2,
2017+ lift3 : Signal.lift3,
2018+ lift4 : Signal.lift4,
2019+ foldp : Signal.foldp,
2020+ constant : Signal.constant,
2021+ count : Signal.count,
2022+ keepIf : Signal.keepIf,
2023+ dropIf : Signal.dropIf,
2024+ keepWhen : Signal.keepWhen,
2025+ dropWhen : Signal.dropWhen,
2026+ dropRepeats : Signal.dropRepeats
2027+ };
2028+}();
2029+var eq = Value.eq;
2030+
2031+var includeGlobal = this;
2032+(function() {
2033+ var include = function(library) {
2034+ for (var i in library) {
2035+ if (i === 'Internal') continue;
2036+ try {
2037+ includeGlobal[i] = library[i];
2038+ } catch (err) {
2039+ if (i === 'length') {
2040+ includeGlobal.execScript('var length;');
2041+ length = library[i];
2042+ continue;
2043+ }
2044+ }
2045+ }
2046+ };
2047+ var includeAs = function(name) { return function(library) {
2048+ includeGlobal[name] = includeGlobal[name] || {};
2049+ for (var i in library) {
2050+ if (i === 'Internal') continue;
2051+ includeGlobal[name][i] = library[i];
2052+ }
2053+ };
2054+ };
2055+ include (Element);
2056+ include (Text);
2057+
2058+ color = Element.color;
2059+ height = Element.height;
2060+ show = Value.show;
2061+
2062+ include (Color);
2063+ include (Shape);
2064+ include (Line);
2065+
2066+ includeAs ('Time') (Signal.Time);
2067+ includeAs ('Mouse') (Signal.Mouse);
2068+ includeAs ('Keyboard') (Signal.Keyboard);
2069+ includeAs ('Window') (Signal.Window);
2070+ includeAs ('HTTP') (Signal.HTTP);
2071+ includeAs ('Input') (Signal.Input);
2072+ includeAs ('Random') (Signal.Random);
2073+
2074+}());
2075+
2076+var ElmCode = {};
2077+ElmCode.Data = Data;
2078+ElmCode.Signal = Signal;
2079+ElmCode.Data.List = List;
2080+ElmCode.Foreign = Foreign;
2081+ElmCode.Prelude = Prelude;
elm/src/Ast.hs+3−5
@@ -6,7 +6,7 @@ import Data.List (intercalate)
6import Types
6import Types
7import Guid
7import Guid
8
8
9−data Module = Module [String] Exports Imports Defs [JSFFI]
9+data Module = Module [String] Exports Imports Defs JSFFI
10
10
11type Exports = [String]
11type Exports = [String]
12
12
@@ -15,10 +15,8 @@ data ImportMethod = As String | Hiding [String] | Importing [String]
15
15
16type Defs = [(String,Expr)]
16type Defs = [(String,Expr)]
17
17
18−data JSFFI = ImportValue String String Type
19− | ExportValue String String Type
20− | ImportEvent String String Expr Type
18+type JSFFI = ( [(String, Expr, String, Type)]
21− | ExportEvent String String Type
19+ , [(String, String, Type)] )
22
20
23
21
24data Pattern = PData String [Pattern] | PVar String | PAnything
22data Pattern = PData String [Pattern] | PVar String | PAnything
elm/src/Compiler.hs+14−13
@@ -20,38 +20,39 @@ data ELM =
20 , runtime :: Maybe FilePath
20 , runtime :: Maybe FilePath
21 , separate_js :: Bool
21 , separate_js :: Bool
22 , only_js :: Bool
22 , only_js :: Bool
23−-- , verbose_js :: Bool
23+ , import_js :: [FilePath]
24 }
24 }
25 deriving (Data,Typeable,Show,Eq)
25 deriving (Data,Typeable,Show,Eq)
26
26
27elm = ELM { make = False &= help "automatically compile dependencies."
27elm = ELM { make = False &= help "automatically compile dependencies."
28 , files = def &= args &= typ "FILES"
28 , files = def &= args &= typ "FILES"
29− , runtime = Nothing &= typ "FILE" &=
29+ , runtime = Nothing &= typFile &=
30 help "Specify a custom location for Elm's runtime system."
30 help "Specify a custom location for Elm's runtime system."
31 , separate_js = False &= help "Compile to separate HTML and JS files."
31 , separate_js = False &= help "Compile to separate HTML and JS files."
32 , only_js = False &= help "Compile only to JavaScript."
32 , only_js = False &= help "Compile only to JavaScript."
33−-- , verbose_js = False &= help "Produce JavaScript that may be easier to debug."
33+ , import_js = [] &= typFile &= help "Include a JavaScript file before the body of the Elm program. Can be used many times. Files will be included in the given order."
34 } &=
34 } &=
35 help "Compile Elm programs to HTML, CSS, and JavaScript." &=
35 help "Compile Elm programs to HTML, CSS, and JavaScript." &=
36− summary "The Elm Compiler v0.3.0, (c) Evan Czaplicki"
36+ summary "The Elm Compiler v0.3.5, (c) Evan Czaplicki"
37
37
38main = do
38main = do
39 args <- cmdArgs elm
39 args <- cmdArgs elm
40− mini <- getDataFileName "elm-runtime-0.3.0.js"
40+ mini <- getDataFileName "elm-runtime-0.3.5.js"
41 compileArgs mini args
41 compileArgs mini args
42
42
43−compileArgs mini (ELM _ [] _ _ _) =
43+compileArgs mini (ELM _ [] _ _ _ _) =
44 putStrLn "Usage: elm [OPTIONS] [FILES]\nFor more help: elm --help"
44 putStrLn "Usage: elm [OPTIONS] [FILES]\nFor more help: elm --help"
45−compileArgs mini (ELM make files rtLoc split only) =
45+compileArgs mini (ELM make files rtLoc split only js) =
46− mapM_ (fileTo get what $ fromMaybe mini rtLoc) files
46+ mapM_ (fileTo get what js $ fromMaybe mini rtLoc) files
47 where get = if make then getModules [] else getModule
47 where get = if make then getModules [] else getModule
48 what = if only then JS else
48 what = if only then JS else
49 if split then Split else HTML
49 if split then Split else HTML
50
50
51data What = JS | HTML | Split
51data What = JS | HTML | Split
52
52
53−fileTo get what rtLoc file = do
53+fileTo get what jsFiles rtLoc file = do
54 ems <- get file
54 ems <- get file
55+ jss <- concat `fmap` mapM readFile jsFiles
55 case ems of
56 case ems of
56 Left err -> putStrLn $ "Error while compiling " ++ file ++ ":\n" ++ err
57 Left err -> putStrLn $ "Error while compiling " ++ file ++ ":\n" ++ err
57 Right ms ->
58 Right ms ->
@@ -59,18 +60,18 @@ fileTo get what rtLoc file = do
59 js = name ++ ".js"
60 js = name ++ ".js"
60 html = name ++ ".html"
61 html = name ++ ".html"
61 in case what of
62 in case what of
62− JS -> writeFile js $ concatMap jsModule ms
63+ JS -> writeFile js $ jss ++ concatMap jsModule ms
63− HTML -> writeFile html . renderHtml $ modulesToHtml rtLoc ms
64+ HTML -> writeFile html . renderHtml $ modulesToHtml "" rtLoc jss ms
64 Split -> do
65 Split -> do
65 writeFile html . renderHtml $ linkedHtml rtLoc js ms
66 writeFile html . renderHtml $ linkedHtml rtLoc js ms
66− writeFile js $ concatMap jsModule ms
67+ writeFile js $ jss ++ concatMap jsModule ms
67
68
68getModules :: [String] -> FilePath -> IO (Either String [Module])
69getModules :: [String] -> FilePath -> IO (Either String [Module])
69getModules uses file = do
70getModules uses file = do
70 code <- readFile file
71 code <- readFile file
71 case initialize code of
72 case initialize code of
72 Left err -> return . Left $ "Error in " ++ file ++ ":\n" ++ err
73 Left err -> return . Left $ "Error in " ++ file ++ ":\n" ++ err
73− Right modul@(Module _ _ imports _) ->
74+ Right modul@(Module _ _ imports _ _) ->
74 let imps = filter (`notElem` builtInModules) $ map fst imports in
75 let imps = filter (`notElem` builtInModules) $ map fst imports in
75 case intersect uses imps of
76 case intersect uses imps of
76 x:_ -> return . Left $ "Error: Cyclic dependency. Module " ++
77 x:_ -> return . Left $ "Error: Cyclic dependency. Module " ++
elm/src/Gen/CompileToJS.hs+14−14
@@ -14,9 +14,9 @@ showErr :: String -> String
14showErr err = mainEquals $ "text(monospace(" ++ msg ++ "))"
14showErr err = mainEquals $ "text(monospace(" ++ msg ++ "))"
15 where msg = show . concatMap (++"<br>") . lines $ err
15 where msg = show . concatMap (++"<br>") . lines $ err
16
16
17−parens = ("("++) . (++")")
17+parens s = "(" ++ s ++ ")"
18−braces = ("{"++) . (++"}")
18+braces s = "{" ++ s ++ "}"
19−jsList = ("["++) . (++"]") . intercalate ","
19+jsList ss = "["++ intercalate "," ss ++"]"
20jsFunc args body = "function(" ++ args ++ "){" ++ body ++ "}"
20jsFunc args body = "function(" ++ args ++ "){" ++ body ++ "}"
21assign x e = "\nvar " ++ x ++ "=" ++ e ++ ";"
21assign x e = "\nvar " ++ x ++ "=" ++ e ++ ";"
22ret e = "\nreturn "++ e ++";"
22ret e = "\nreturn "++ e ++";"
@@ -38,14 +38,14 @@ tryBlock names e =
38 ]
38 ]
39
39
40
40
41−jsModule (Module names exports imports defs (ims,exs)) =
41+jsModule (Module names exports imports defs foreigns) =
42 tryBlock (tail modNames) $ concat
42 tryBlock (tail modNames) $ concat
43 [ concatMap (\n -> globalAssign n $ n ++ " || {}") .
43 [ concatMap (\n -> globalAssign n $ n ++ " || {}") .
44 map (intercalate ".") . drop 2 . inits $
44 map (intercalate ".") . drop 2 . inits $
45 take (length modNames - 1) modNames
45 take (length modNames - 1) modNames
46 , "\nif (" ++ modName ++ ") throw \"Module name collision, '" ++
46 , "\nif (" ++ modName ++ ") throw \"Module name collision, '" ++
47 intercalate "." (tail modNames) ++ "' is already defined.\"; "
47 intercalate "." (tail modNames) ++ "' is already defined.\"; "
48− , globalAssign modName $ jsFunc "" (includes++body++export)++"()"
48+ , globalAssign modName $ jsFunc "" (includes++ims++body++exs++export)++"()"
49 , mainEquals $ modName ++ ".main" ]
49 , mainEquals $ modName ++ ".main" ]
50 where modNames = if null names then ["ElmCode", "Main"] else "ElmCode" : names
50 where modNames = if null names then ["ElmCode", "Main"] else "ElmCode" : names
51 modName = intercalate "." modNames
51 modName = intercalate "." modNames
@@ -57,23 +57,23 @@ jsModule (Module names exports imports defs (ims,exs)) =
57 getNames (x,_) =
57 getNames (x,_) =
58 let y = reverse . tail . dropWhile isDigit $ reverse x in
58 let y = reverse . tail . dropWhile isDigit $ reverse x in
59 if y `elem` exps then Just $ y ++ ":" ++ x else Nothing
59 if y `elem` exps then Just $ y ++ ":" ++ x else Nothing
60+ (ims,exs) = let (i,e) = foreigns in
61+ (concatMap importEvent i, concatMap exportEvent e)
60
62
61−ffi (ImportValue js elm _) = assign elm js
63+importEvent (js,base,elm,_) =
62−ffi (ExportValue js elm _) = assign js elm
63−ffi (ImportEvent js elm base _) =
64 concat [ "var " ++ elm ++ " = Elm.Input(" ++ toJS base ++ ");"
64 concat [ "var " ++ elm ++ " = Elm.Input(" ++ toJS base ++ ");"
65 , "Signal.addListener(document, '" ++ js
65 , "Signal.addListener(document, '" ++ js
66 , "', function(e) { Dispatcher.notify(" ++ elm
66 , "', function(e) { Dispatcher.notify(" ++ elm
67− , ".id, e); });" ]
67+ , ".id, e.value); });" ]
68−ffi (ExportEvent js elm base _) =
68+exportEvent (js,elm,_) =
69 concat [ "lift (function(v) { var e = document.createEvent('Event');"
69 concat [ "lift (function(v) { var e = document.createEvent('Event');"
70 , "e.initEvent('" ++ js ++ "', true, true);"
70 , "e.initEvent('" ++ js ++ "', true, true);"
71− , "e.elmValue = v;"
71+ , "e.value = v;"
72− , "document.disspatchEvent(e); return v; })(" ++ elm ++ ")"
72+ , "document.dispatchEvent(e); return v; })(" ++ elm ++ ")"
73 ]
73 ]
74
74
75jsImport (modul, how) =
75jsImport (modul, how) =
76− concat [ "\ntry{" ++ modul ++ "} catch(e) {throw \"Module '"
76+ concat [ "\ntry{" ++ modul ++ " instanceof Object} catch(e) {throw \"Module '"
77 , drop 1 (dropWhile (/='.') modul)
77 , drop 1 (dropWhile (/='.') modul)
78 , "' is missing. Compile with --make flag or load missing "
78 , "' is missing. Compile with --make flag or load missing "
79 , "module in a separate JavaScript file.\";}" ] ++
79 , "module in a separate JavaScript file.\";}" ] ++
@@ -96,7 +96,7 @@ toJS expr =
96 Number n -> show n
96 Number n -> show n
97 Var x -> x
97 Var x -> x
98 Chr c -> show c
98 Chr c -> show c
99− Str s -> toJS . list $ map Chr s
99+ Str s -> "Value.str" ++ parens (show s)
100 Boolean b -> if b then "true" else "false"
100 Boolean b -> if b then "true" else "false"
101 Range lo hi -> jsRange (toJS lo) (toJS hi)
101 Range lo hi -> jsRange (toJS lo) (toJS hi)
102 Access e lbl -> toJS e ++ "." ++ lbl
102 Access e lbl -> toJS e ++ "." ++ lbl
elm/src/Gen/GenerateHtml.hs+9−5
@@ -44,17 +44,21 @@ generateHtml :: String -- ^ Location of elm-min.js as expected by the browser
44generateHtml libLoc title source =
44generateHtml libLoc title source =
45 case initialize source of
45 case initialize source of
46 Left err -> createHtml libLoc title (Right $ showErr err) (H.noscript "")
46 Left err -> createHtml libLoc title (Right $ showErr err) (H.noscript "")
47− Right modul -> modulesToHtml libLoc [modul]
47+ Right modul -> modulesToHtml title libLoc [] [modul]
48
48
49
49
50−modulesToHtml libLoc modules = createHtml libLoc title js noscript
50+modulesToHtml title libLoc jss modules = createHtml libLoc title' js noscript
51− where title = (\(Module names _ _ _) -> intercalate "." names) $ last modules
52− js = Right $ concatMap jsModule modules
51+ where js = Right $ jss ++ concatMap jsModule modules
53 noscript = extract $ last modules
52 noscript = extract $ last modules
53+ title' = if null title then altTitle else title
54+ altTitle = (\(Module names _ _ _ _) -> intercalate "." names) $
55+ last modules
56+
54
57
55linkedHtml rtLoc jsLoc modules =
58linkedHtml rtLoc jsLoc modules =
56 createHtml rtLoc title (Left jsLoc) (H.noscript "")
59 createHtml rtLoc title (Left jsLoc) (H.noscript "")
57− where title = (\(Module names _ _ _) -> intercalate "." names) $ last modules
60+ where title = (\(Module names _ _ _ _) -> intercalate "." names) $
61+ last modules
58
62
59
63
60createHtml libLoc title js noscript =
64createHtml libLoc title js noscript =
elm/src/Initialize.hs+15−11
@@ -1,6 +1,7 @@
1module Initialize (initialize) where
1module Initialize (initialize) where
2
2
3import Control.Monad.Error
3import Control.Monad.Error
4+import Data.List (lookup)
4
5
5import Ast
6import Ast
6import Parser (parseProgram)
7import Parser (parseProgram)
@@ -10,18 +11,21 @@ import Rename
10import Optimize
11import Optimize
11
12
12initialize str = do
13initialize str = do
13− (Module name ex im defs jsffi, tipes) <- parseProgram str
14+ (Module name ex im defs (ims,exs), tipes) <- parseProgram str
14− let expr = rename . Let defs $ Var "_"
15+ let (Let ds _) = rename . Let defs $ Var "_"
16+ let dict n = maybe n id . lookup n $ zip (map fst defs) (map fst ds)
15− let allHints = liftM2 (\a b -> a ++ b ++ map ffiHint jsffi) hints tipes
17+ let allHints = liftM2 (\a b -> a ++ b ++ ffiHints (ims,exs)) hints tipes
16− subs <- unify allHints expr
18+ subs <- unify allHints . Let ds $ checkFFI dict ims exs
17− let Let defs' _ = optimize expr
19+ let Let defs' _ = optimize (Let ds $ Var "_")
18 let im' = if any ((=="Prelude") . fst) im then im else
20 let im' = if any ((=="Prelude") . fst) im then im else
19 ("Prelude", Importing []):im
21 ("Prelude", Importing []):im
22+ let exs' = map (\(js,n,t) -> (js,dict n,t)) exs
20− return (subs `seq` Module name ex im' defs' jsffi)
23+ return (subs `seq` Module name ex im' defs' (ims,exs'))
21
24
22
25
23−ffiHint x = case x of
26+ffiHints (ims,exs) =
24− ImportValue _ n t -> (n,t)
27+ map (\(_,_,n,t) -> (n,t)) ims ++ map (\(_,n,t) -> (n,t)) exs
25− ExportValue _ n t -> (n,t)
28+
26− ImportEvent _ n _ t -> (n,t)
29+checkFFI dict ims exs = list $ ims' ++ exs'
27− ExportEvent _ n t -> (n,t)
30+ where ims' = map (\(_,b,n,_)-> Binop "==" (Var n) (App (Var "constant") b)) ims
31+ exs' = map (\(_,n,_) -> Binop "==" (Var n) (Var $ dict n)) exs
elm/src/Parse/ParseForeign.hs+14−27
@@ -11,50 +11,37 @@ import ParseExpr (term)
11import ParseTypes
11import ParseTypes
12
12
13
13
14−foreignDefs = option [] $ do
14+foreignDefs = do
15− f <- commitIf (reserved "foreign") foreign
15+ f <- foreign --commitIf (reserved "foreign") foreign
16 fs <- many (commitIf (freshLine >> reserved "foreign") (freshLine >> foreign))
16 fs <- many (commitIf (freshLine >> reserved "foreign") (freshLine >> foreign))
17− return (f:fs)
17+ return . partitionEithers $ f:fs
18
18
19
19
20−foreign = do reserved "foreign" ; whitespace ; (jsEvent <|> jsValue)
20+foreign = do try (reserved "foreign") ; whitespace
21−
22−
23−jsValue = do
24− what <- try $ choice
25− [ try (reserved "import" >> whitespace >>
26− reserved "jsValue" >> whitespace >> return ImportValue)
27− , try (reserved "export" >> whitespace >>
28− reserved "jsValue" >> whitespace >> return ExportValue) ]
29− js <- jsVar ; whitespace
30− elm <- lowVar ; whitespace
31− tipe <- typeExpr
32− either fail (return . what js elm) (toForeignType tipe)
33−
34−
35−jsEvent = importEvent <|> exportEvent
21+ Left <$> importEvent <|> Right <$> exportEvent
36
22
37exportEvent = do
23exportEvent = do
38− try (reserved "export" >> whitespace >> reserved "jsEvent" >> whitespace)
24+ try (reserved "export" >> whitespace >> reserved "jsevent" >> whitespace)
39 js <- jsVar ; whitespace
25 js <- jsVar ; whitespace
40 elm <- lowVar ; whitespace
26 elm <- lowVar ; whitespace
41 string "::" ; whitespace
27 string "::" ; whitespace
42 tipe <- typeExpr
28 tipe <- typeExpr
43 case tipe of
29 case tipe of
44 ADTPT "Signal" [pt] ->
30 ADTPT "Signal" [pt] ->
45− either fail (return . ExportEvent js elm) (toForeignType pt)
31+ either fail (return . (,,) js elm) (toForeignType pt)
46 _ -> fail "When exporting events, the exported value must be a Signal."
32 _ -> fail "When exporting events, the exported value must be a Signal."
47
33
48importEvent = do
34importEvent = do
49− try (reserved "import" >> whitespace >> reserved "jsEvent" >> whitespace)
35+ try (reserved "import" >> whitespace >> reserved "jsevent" >> whitespace)
50− js <- jsVar ; whitespace
36+ js <- jsVar ; whitespace
37+ base <- term <?> "Base case for imported signal (signals cannot be undefined)"
51− base <- term ; whitespace
38+ whitespace
52− elm <- lowVar ; whitespace
39+ elm <- lowVar <?> "Name of imported signal"
53− string "::" ; whitespace
40+ whitespace ; string "::" ; whitespace
54 tipe <- typeExpr
41 tipe <- typeExpr
55 case tipe of
42 case tipe of
56 ADTPT "Signal" [pt] ->
43 ADTPT "Signal" [pt] ->
57− either fail (return . ImportEvent js elm base) (toForeignType pt)
44+ either fail (return . (,,,) js base elm) (toForeignType pt)
58 _ -> fail "When importing events, the imported value must be a Signal."
45 _ -> fail "When importing events, the imported value must be a Signal."
59
46
60
47
elm/src/Parse/ParseLib.hs+2−1
@@ -11,7 +11,8 @@ reserveds = [ "if", "then", "else"
11 , "case", "of", "data"
11 , "case", "of", "data"
12 , "let", "in"
12 , "let", "in"
13 , "module", "where"
13 , "module", "where"
14− , "import", "as", "hiding" ]
14+ , "import", "as", "hiding"
15+ , "export", "foreign" ]
15
16
16expecting = flip (<?>)
17expecting = flip (<?>)
17
18
elm/src/Parse/ParseTypes.hs+14−8
@@ -83,14 +83,20 @@ toType pairs outType (name,args) =
83 _ -> ADT x []
83 _ -> ADT x []
84
84
85toForeignType (LambdaPT t1 t2) =
85toForeignType (LambdaPT t1 t2) =
86+ fail $ "Elm's JavaScript event interface does not yet handle functions. " ++
87+ "Only simple values can be imported and exported in this release."
86− LambdaT <$> toForeignType t1 <*> toForeignType t2
88+ --LambdaT <$> toForeignType t1 <*> toForeignType t2
87−toForeignType (ADTPT name args) = do
89+toForeignType (ADTPT name args)
88− case name == "JSArray" of
89− True -> ADT name <$> mapM toForeignType args
90+ | isJsStructure name = ADT name <$> mapM toForeignType args
90− False -> Left $ "'" ++ name ++
91+ | otherwise =
92+ Left $ "'" ++ name ++ "' is not an exportable type " ++
91− "' is not an exportable type constructor. Only 'JSArray' is exportable."
93+ "constructor. Only 'JSArray' and 'JSTupleN' are exportable."
94+
92toForeignType (VarPT x@(c:_))
95toForeignType (VarPT x@(c:_))
93 | isLower c =
96 | isLower c =
94 Left "All exported types must be concrete types (JSNumber, JSString, etc.)"
97 Left "All exported types must be concrete types (JSNumber, JSString, etc.)"
95− | x `elem` [ "JSString", "JSNumber", "JSElement" ] = Right (ADT x [])
98+ | x `elem` ["JSString","JSNumber","JSElement","JSBool"] = Right (ADT x [])
96− | otherwise = Left $ "'" ++ x ++ "' is not an exportable type. JSNumber, JSString, JSElement, and (JSArray a) are exportable."
99+ | otherwise = Left $ "'" ++ x ++ "' is not an exportable type. Only JSTypes are exportable."
100+
101+isJsStructure name = name == "JSArray" || isTuple
102+ where isTuple = "JSTuple" == take 7 name && name `elem` map show [2..5]
elm/src/Parse/Parser.hs+2−3
@@ -27,11 +27,10 @@ defs = do
27
27
28program = do
28program = do
29 optional freshLine
29 optional freshLine
30− (names,exports) <- option ([],[]) (moduleDef `followedBy` freshLine)
30+ (names,exports) <- option (["Main"],[]) (moduleDef `followedBy` freshLine)
31 is <- (do try (lookAhead $ reserved "import")
31 is <- (do try (lookAhead $ reserved "import")
32 imports `followedBy` freshLine) <|> return []
32 imports `followedBy` freshLine) <|> return []
33− jsffi <- foreignDefs
33+ jsffi <- foreignDefs `followedBy` freshLine <|> return ([],[])
34− freshLine
35 (vs,es,ts) <- defs
34 (vs,es,ts) <- defs
36 optional freshLine ; optional spaces ; eof
35 optional freshLine ; optional spaces ; eof
37 return (Module names exports is (zip vs es) jsffi, zip vs `liftM` ts)
36 return (Module names exports is (zip vs es) jsffi, zip vs `liftM` ts)
elm/src/Types/Hints.hs+57−18
@@ -49,6 +49,35 @@ shapes = [ "polygon" -: listOf point ==> point ==> shape
49 ] ++ hasType (IntT ==> IntT ==> point ==> shape) ["ngon","rect","oval"]
49 ] ++ hasType (IntT ==> IntT ==> point ==> shape) ["ngon","rect","oval"]
50
50
51
51
52+-------- Foreign --------
53+
54+casts =
55+ [ "castJSBoolToBool" -: jsBool ==> BoolT
56+ , "castBoolToJSBool" -: BoolT ==> jsBool
57+ , "castJSNumberToInt" -: jsNumber ==> IntT
58+ , "castIntToJSNumber" -: IntT ==> jsNumber
59+ , "castJSElementToElement" -: jsElement ==> element
60+ , "castElementToJSElement" -: element ==> jsElement
61+ , "castJSStringToString" -: jsString ==> string
62+ , "castStringToJSString" -: string ==> jsString
63+ -- , "castJSNumberToFloat -:
64+ -- , "castFloatToJSNumber -:
65+ ]
66+
67+polyCasts = sequence
68+ [ do a <- var ; "castJSArrayToList" -:: jsArray a ==> listOf a
69+ , do a <- var ; "castListToJSArray" -:: listOf a ==> jsArray a
70+ , do vs <- vars 2 ; "castTupleToJSTuple2" -:: tupleOf vs ==> jsTuple vs
71+ , do vs <- vars 3 ; "castTupleToJSTuple3" -:: tupleOf vs ==> jsTuple vs
72+ , do vs <- vars 4 ; "castTupleToJSTuple4" -:: tupleOf vs ==> jsTuple vs
73+ , do vs <- vars 5 ; "castTupleToJSTuple5" -:: tupleOf vs ==> jsTuple vs
74+ , do vs <- vars 2 ; "castJSTupleToTuple2" -:: jsTuple vs ==> tupleOf vs
75+ , do vs <- vars 3 ; "castJSTupleToTuple3" -:: jsTuple vs ==> tupleOf vs
76+ , do vs <- vars 4 ; "castJSTupleToTuple4" -:: jsTuple vs ==> tupleOf vs
77+ , do vs <- vars 5 ; "castJSTupleToTuple5" -:: jsTuple vs ==> tupleOf vs
78+ ]
79+
80+
52-------- Signals --------
81-------- Signals --------
53
82
54sig ts = fn ts ==> fn (map signalOf ts)
83sig ts = fn ts ==> fn (map signalOf ts)
@@ -62,22 +91,29 @@ signals = sequence
62 , do ts <- vars 5 ; "lift4" -:: sig ts
91 , do ts <- vars 5 ; "lift4" -:: sig ts
63 , do [a,b] <- vars 2
92 , do [a,b] <- vars 2
64 "foldp" -:: (a ==> b ==> b) ==> b ==> signalOf a ==> signalOf b
93 "foldp" -:: (a ==> b ==> b) ==> b ==> signalOf a ==> signalOf b
94+ , do a <- var ; "randomize" -:: IntT ==> IntT ==> signalOf a ==> signalOf IntT
65 ]
95 ]
66
96
67−concreteSignals =
97+concreteSignals =
98+ [ "keysDown" -: signalOf (listOf IntT)
99+ , "charPressed" -: signalOf (maybeOf IntT)
100+ , "inRange" -: IntT ==> IntT ==> signalOf IntT
101+ , "every" -: time ==> signalOf time
102+ , "before" -: time ==> signalOf BoolT
103+ , "after" -: time ==> signalOf BoolT
104+ , "dimensions" -: signalOf point
68− [ "Mouse.position" -: signalOf point
105+ , "position" -: signalOf point
69− , "Mouse.x" -: signalOf IntT
106+ , "x" -: signalOf IntT
70− , "Mouse.y" -: signalOf IntT
107+ , "y" -: signalOf IntT
71− , "Mouse.isDown" -: signalOf BoolT
108+ , "isDown" -: signalOf BoolT
72− , "Mouse.isClicked" -: signalOf BoolT
109+ , "isClicked" -: signalOf BoolT
73− , "Window.dimensions" -: signalOf point
74− , "Window.width" -: signalOf IntT
75− , "Window.height" -: signalOf IntT
76− , "Input.textField" -: string ==> tupleOf [element, signalOf string]
110+ , "textField" -: string ==> tupleOf [element, signalOf string]
77− , "Input.password" -: string ==> tupleOf [element, signalOf string]
111+ , "password" -: string ==> tupleOf [element, signalOf string]
78− , "Input.textArea" -: IntT ==> IntT ==> tupleOf [element, signalOf string]
112+ , "textArea" -: IntT ==> IntT ==> tupleOf [element, signalOf string]
113+ , "checkBox" -: BoolT ==> tupleOf [element, signalOf BoolT]
114+ , "button" -: string ==> tupleOf [element, signalOf BoolT]
79− , "Input.stringDropDown" -: listOf string ==> tupleOf [element, signalOf string]
115+ , "stringDropDown" -: listOf string ==> tupleOf [element, signalOf string]
80− ]
116+ ]
81
117
82-------- Math and Binops --------
118-------- Math and Binops --------
83
119
@@ -111,7 +147,7 @@ funcs = sequence
111 , do [a,b,c] <- vars 3 ; "." -:: (b ==> c) ==> (a ==> b) ==> (a ==> c)
147 , do [a,b,c] <- vars 3 ; "." -:: (b ==> c) ==> (a ==> b) ==> (a ==> c)
112 , do [a,b] <- vars 2 ; "$" -:: (a ==> b) ==> a ==> b
148 , do [a,b] <- vars 2 ; "$" -:: (a ==> b) ==> a ==> b
113 , do a <- var ; ":" -:: a ==> listOf a ==> listOf a
149 , do a <- var ; ":" -:: a ==> listOf a ==> listOf a
114− , do a <- var ; "++" -:: listOf a ==> listOf a ==> listOf a
150+ , do a <- var ; "++" -:: a ==> a ==> a
115 , do a <- var ; "Cons" -:: a ==> listOf a ==> listOf a
151 , do a <- var ; "Cons" -:: a ==> listOf a ==> listOf a
116 , do a <- var ; "Nil" -:: listOf a
152 , do a <- var ; "Nil" -:: listOf a
117 , do a <- var ; "Just" -:: a ==> ADT "Maybe" [a]
153 , do a <- var ; "Just" -:: a ==> ADT "Maybe" [a]
@@ -121,7 +157,7 @@ funcs = sequence
121
157
122ints = map (-: (listOf IntT ==> IntT)) [ "sum","product","maximum","minimum" ]
158ints = map (-: (listOf IntT ==> IntT)) [ "sum","product","maximum","minimum" ]
123
159
124−lists = liftM (map (first ("List."++)) . (++ints)) . sequence $
160+lists = liftM (++ints) . sequence $
125 [ "and" -:: listOf BoolT ==> BoolT
161 [ "and" -:: listOf BoolT ==> BoolT
126 , "or" -:: listOf BoolT ==> BoolT
162 , "or" -:: listOf BoolT ==> BoolT
127 , "sort" -:: listOf IntT ==> listOf IntT
163 , "sort" -:: listOf IntT ==> listOf IntT
@@ -136,6 +172,9 @@ lists = liftM (map (first ("List."++)) . (++ints)) . sequence $
136 , do a <- var ; "exists" -:: (a ==> BoolT) ==> listOf a ==> BoolT
172 , do a <- var ; "exists" -:: (a ==> BoolT) ==> listOf a ==> BoolT
137 , do a <- var ; "concat" -:: listOf (listOf a) ==> listOf a
173 , do a <- var ; "concat" -:: listOf (listOf a) ==> listOf a
138 , do a <- var ; "reverse" -:: listOf a ==> listOf a
174 , do a <- var ; "reverse" -:: listOf a ==> listOf a
175+ , do a <- var ; "take" -:: IntT ==> listOf a ==> listOf a
176+ , do a <- var ; "drop" -:: IntT ==> listOf a ==> listOf a
177+ , do a <- var ; "partition" -:: (a==>BoolT)==>listOf a==>tupleOf [listOf a,listOf a]
139 , do a <- var ; "intersperse" -:: a ==> listOf a ==> listOf a
178 , do a <- var ; "intersperse" -:: a ==> listOf a ==> listOf a
140 , do a <- var ; "intercalate" -:: listOf a ==> listOf(listOf a) ==> listOf a
179 , do a <- var ; "intercalate" -:: listOf a ==> listOf(listOf a) ==> listOf a
141 , do [a,b] <- vars 2 ; "zip" -:: listOf a ==>listOf b ==>listOf(tupleOf [a,b])
180 , do [a,b] <- vars 2 ; "zip" -:: listOf a ==>listOf b ==>listOf(tupleOf [a,b])
@@ -152,8 +191,8 @@ lists = liftM (map (first ("List."++)) . (++ints)) . sequence $
152-------- Everything --------
191-------- Everything --------
153
192
154hints = do
193hints = do
155− fs <- funcs ; ls <- lists ; ss <- signals
194+ fs <- funcs ; ls <- lists ; ss <- signals ; pcasts <- polyCasts
156 return $ concat [ fs, ls, ss, math, bool, str2elem, textAttrs
195 return $ concat [ fs, ls, ss, math, bool, str2elem, textAttrs
157 , elements, directions, colors, lineTypes, shapes
196 , elements, directions, colors, lineTypes, shapes
158− , concreteSignals
197+ , concreteSignals, casts, pcasts
159 ]
198 ]
elm/src/Types/Types.hs+9
@@ -30,7 +30,16 @@ point = tupleOf [IntT,IntT]
30listOf t = ADT "List" [t]
30listOf t = ADT "List" [t]
31signalOf t = ADT "Signal" [t]
31signalOf t = ADT "Signal" [t]
32tupleOf ts = ADT ("Tuple" ++ show (length ts)) ts
32tupleOf ts = ADT ("Tuple" ++ show (length ts)) ts
33+maybeOf t = ADT "Maybe" [t]
33string = listOf CharT
34string = listOf CharT
35+time = IntT
36+
37+jsBool = ADT "JSBool" []
38+jsNumber = ADT "JSNumber" []
39+jsString = ADT "JSString" []
40+jsElement = ADT "JSElement" []
41+jsArray t = ADT "JSArray" [t]
42+jsTuple ts = ADT ("JSTuple" ++ show (length ts)) ts
34
43
35infixr ==>
44infixr ==>
36t1 ==> t2 = LambdaT t1 t2
45t1 ==> t2 = LambdaT t1 t2