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.
commita9da9b37628dc63dd0b1a2ee722f33d4f05ec12c authorevancz <info@elm-lang.org> dateThu 28 Jun 2012, 03:52 (14 years ago) parent9332a8a
14 files changed+2255−106
.gitignore+4−1 elm/changelog.txt+17 elm/elm-runtime-0.3.5.js+2081 elm/src/Ast.hs+3−5 elm/src/Compiler.hs+14−13 elm/src/Gen/CompileToJS.hs+14−14 elm/src/Gen/GenerateHtml.hs+9−5 elm/src/Initialize.hs+15−11 elm/src/Parse/ParseForeign.hs+14−27 elm/src/Parse/ParseLib.hs+2−1 elm/src/Parse/ParseTypes.hs+14−8 elm/src/Parse/Parser.hs+2−3 elm/src/Types/Hints.hs+57−18 elm/src/Types/Types.hs+9
.gitignore+4−1
@@ -5,4 +5,7 @@ cabal-dev
55*.chi
66*.chs.h
77*.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+
118Release 0.3.0
219=============
320
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('"', "&#34;");
105+ str.replace("&", "&#38;");
106+ str.replace("'", "&#39;");
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)
66import Types
77import Guid
88
9−data Module = Module [String] Exports Imports Defs [JSFFI]
9+data Module = Module [String] Exports Imports Defs JSFFI
1010
1111type Exports = [String]
1212
@@ -15,10 +15,8 @@ data ImportMethod = As String | Hiding [String] | Importing [String]
1515
1616type Defs = [(String,Expr)]
1717
18−data JSFFI = ImportValue String String Type
19− | ExportValue String String Type
20− | ImportEvent String String Expr Type
21− | ExportEvent String String Type
18+type JSFFI = ( [(String, Expr, String, Type)]
19+ , [(String, String, Type)] )
2220
2321
2422data Pattern = PData String [Pattern] | PVar String | PAnything
elm/src/Compiler.hs+14−13
@@ -20,38 +20,39 @@ data ELM =
2020 , runtime :: Maybe FilePath
2121 , separate_js :: Bool
2222 , only_js :: Bool
23−-- , verbose_js :: Bool
23+ , import_js :: [FilePath]
2424 }
2525 deriving (Data,Typeable,Show,Eq)
2626
2727elm = ELM { make = False &= help "automatically compile dependencies."
2828 , files = def &= args &= typ "FILES"
29− , runtime = Nothing &= typ "FILE" &=
29+ , runtime = Nothing &= typFile &=
3030 help "Specify a custom location for Elm's runtime system."
3131 , separate_js = False &= help "Compile to separate HTML and JS files."
3232 , 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."
3434 } &=
3535 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"
3737
3838main = do
3939 args <- cmdArgs elm
40− mini <- getDataFileName "elm-runtime-0.3.0.js"
40+ mini <- getDataFileName "elm-runtime-0.3.5.js"
4141 compileArgs mini args
4242
43−compileArgs mini (ELM _ [] _ _ _) =
43+compileArgs mini (ELM _ [] _ _ _ _) =
4444 putStrLn "Usage: elm [OPTIONS] [FILES]\nFor more help: elm --help"
45−compileArgs mini (ELM make files rtLoc split only) =
46− mapM_ (fileTo get what $ fromMaybe mini rtLoc) files
45+compileArgs mini (ELM make files rtLoc split only js) =
46+ mapM_ (fileTo get what js $ fromMaybe mini rtLoc) files
4747 where get = if make then getModules [] else getModule
4848 what = if only then JS else
4949 if split then Split else HTML
5050
5151data What = JS | HTML | Split
5252
53−fileTo get what rtLoc file = do
53+fileTo get what jsFiles rtLoc file = do
5454 ems <- get file
55+ jss <- concat `fmap` mapM readFile jsFiles
5556 case ems of
5657 Left err -> putStrLn $ "Error while compiling " ++ file ++ ":\n" ++ err
5758 Right ms ->
@@ -59,18 +60,18 @@ fileTo get what rtLoc file = do
5960 js = name ++ ".js"
6061 html = name ++ ".html"
6162 in case what of
62− JS -> writeFile js $ concatMap jsModule ms
63− HTML -> writeFile html . renderHtml $ modulesToHtml rtLoc ms
63+ JS -> writeFile js $ jss ++ concatMap jsModule ms
64+ HTML -> writeFile html . renderHtml $ modulesToHtml "" rtLoc jss ms
6465 Split -> do
6566 writeFile html . renderHtml $ linkedHtml rtLoc js ms
66− writeFile js $ concatMap jsModule ms
67+ writeFile js $ jss ++ concatMap jsModule ms
6768
6869getModules :: [String] -> FilePath -> IO (Either String [Module])
6970getModules uses file = do
7071 code <- readFile file
7172 case initialize code of
7273 Left err -> return . Left $ "Error in " ++ file ++ ":\n" ++ err
73− Right modul@(Module _ _ imports _) ->
74+ Right modul@(Module _ _ imports _ _) ->
7475 let imps = filter (`notElem` builtInModules) $ map fst imports in
7576 case intersect uses imps of
7677 x:_ -> return . Left $ "Error: Cyclic dependency. Module " ++
elm/src/Gen/CompileToJS.hs+14−14
@@ -14,9 +14,9 @@ showErr :: String -> String
1414showErr err = mainEquals $ "text(monospace(" ++ msg ++ "))"
1515 where msg = show . concatMap (++"<br>") . lines $ err
1616
17−parens = ("("++) . (++")")
18−braces = ("{"++) . (++"}")
19−jsList = ("["++) . (++"]") . intercalate ","
17+parens s = "(" ++ s ++ ")"
18+braces s = "{" ++ s ++ "}"
19+jsList ss = "["++ intercalate "," ss ++"]"
2020jsFunc args body = "function(" ++ args ++ "){" ++ body ++ "}"
2121assign x e = "\nvar " ++ x ++ "=" ++ e ++ ";"
2222ret e = "\nreturn "++ e ++";"
@@ -38,14 +38,14 @@ tryBlock names e =
3838 ]
3939
4040
41−jsModule (Module names exports imports defs (ims,exs)) =
41+jsModule (Module names exports imports defs foreigns) =
4242 tryBlock (tail modNames) $ concat
4343 [ concatMap (\n -> globalAssign n $ n ++ " || {}") .
4444 map (intercalate ".") . drop 2 . inits $
4545 take (length modNames - 1) modNames
4646 , "\nif (" ++ modName ++ ") throw \"Module name collision, '" ++
4747 intercalate "." (tail modNames) ++ "' is already defined.\"; "
48− , globalAssign modName $ jsFunc "" (includes++body++export)++"()"
48+ , globalAssign modName $ jsFunc "" (includes++ims++body++exs++export)++"()"
4949 , mainEquals $ modName ++ ".main" ]
5050 where modNames = if null names then ["ElmCode", "Main"] else "ElmCode" : names
5151 modName = intercalate "." modNames
@@ -57,23 +57,23 @@ jsModule (Module names exports imports defs (ims,exs)) =
5757 getNames (x,_) =
5858 let y = reverse . tail . dropWhile isDigit $ reverse x in
5959 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)
6062
61−ffi (ImportValue js elm _) = assign elm js
62−ffi (ExportValue js elm _) = assign js elm
63−ffi (ImportEvent js elm base _) =
63+importEvent (js,base,elm,_) =
6464 concat [ "var " ++ elm ++ " = Elm.Input(" ++ toJS base ++ ");"
6565 , "Signal.addListener(document, '" ++ js
6666 , "', function(e) { Dispatcher.notify(" ++ elm
67− , ".id, e); });" ]
68−ffi (ExportEvent js elm base _) =
67+ , ".id, e.value); });" ]
68+exportEvent (js,elm,_) =
6969 concat [ "lift (function(v) { var e = document.createEvent('Event');"
7070 , "e.initEvent('" ++ js ++ "', true, true);"
71− , "e.elmValue = v;"
72− , "document.disspatchEvent(e); return v; })(" ++ elm ++ ")"
71+ , "e.value = v;"
72+ , "document.dispatchEvent(e); return v; })(" ++ elm ++ ")"
7373 ]
7474
7575jsImport (modul, how) =
76− concat [ "\ntry{" ++ modul ++ "} catch(e) {throw \"Module '"
76+ concat [ "\ntry{" ++ modul ++ " instanceof Object} catch(e) {throw \"Module '"
7777 , drop 1 (dropWhile (/='.') modul)
7878 , "' is missing. Compile with --make flag or load missing "
7979 , "module in a separate JavaScript file.\";}" ] ++
@@ -96,7 +96,7 @@ toJS expr =
9696 Number n -> show n
9797 Var x -> x
9898 Chr c -> show c
99− Str s -> toJS . list $ map Chr s
99+ Str s -> "Value.str" ++ parens (show s)
100100 Boolean b -> if b then "true" else "false"
101101 Range lo hi -> jsRange (toJS lo) (toJS hi)
102102 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
4444generateHtml libLoc title source =
4545 case initialize source of
4646 Left err -> createHtml libLoc title (Right $ showErr err) (H.noscript "")
47− Right modul -> modulesToHtml libLoc [modul]
47+ Right modul -> modulesToHtml title libLoc [] [modul]
4848
4949
50−modulesToHtml libLoc modules = createHtml libLoc title js noscript
51− where title = (\(Module names _ _ _) -> intercalate "." names) $ last modules
52− js = Right $ concatMap jsModule modules
50+modulesToHtml title libLoc jss modules = createHtml libLoc title' js noscript
51+ where js = Right $ jss ++ concatMap jsModule modules
5352 noscript = extract $ last modules
53+ title' = if null title then altTitle else title
54+ altTitle = (\(Module names _ _ _ _) -> intercalate "." names) $
55+ last modules
56+
5457
5558linkedHtml rtLoc jsLoc modules =
5659 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
5862
5963
6064createHtml libLoc title js noscript =
elm/src/Initialize.hs+15−11
@@ -1,6 +1,7 @@
11module Initialize (initialize) where
22
33import Control.Monad.Error
4+import Data.List (lookup)
45
56import Ast
67import Parser (parseProgram)
@@ -10,18 +11,21 @@ import Rename
1011import Optimize
1112
1213initialize str = do
13− (Module name ex im defs jsffi, tipes) <- parseProgram str
14− let expr = rename . Let defs $ Var "_"
15− let allHints = liftM2 (\a b -> a ++ b ++ map ffiHint jsffi) hints tipes
16− subs <- unify allHints expr
17− let Let defs' _ = optimize expr
14+ (Module name ex im defs (ims,exs), tipes) <- parseProgram str
15+ let (Let ds _) = rename . Let defs $ Var "_"
16+ let dict n = maybe n id . lookup n $ zip (map fst defs) (map fst ds)
17+ let allHints = liftM2 (\a b -> a ++ b ++ ffiHints (ims,exs)) hints tipes
18+ subs <- unify allHints . Let ds $ checkFFI dict ims exs
19+ let Let defs' _ = optimize (Let ds $ Var "_")
1820 let im' = if any ((=="Prelude") . fst) im then im else
1921 ("Prelude", Importing []):im
20− return (subs `seq` Module name ex im' defs' jsffi)
22+ let exs' = map (\(js,n,t) -> (js,dict n,t)) exs
23+ return (subs `seq` Module name ex im' defs' (ims,exs'))
2124
2225
23−ffiHint x = case x of
24− ImportValue _ n t -> (n,t)
25− ExportValue _ n t -> (n,t)
26− ImportEvent _ n _ t -> (n,t)
27− ExportEvent _ n t -> (n,t)
26+ffiHints (ims,exs) =
27+ map (\(_,_,n,t) -> (n,t)) ims ++ map (\(_,n,t) -> (n,t)) exs
28+
29+checkFFI dict ims exs = list $ ims' ++ exs'
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)
1111import ParseTypes
1212
1313
14−foreignDefs = option [] $ do
15− f <- commitIf (reserved "foreign") foreign
14+foreignDefs = do
15+ f <- foreign --commitIf (reserved "foreign") foreign
1616 fs <- many (commitIf (freshLine >> reserved "foreign") (freshLine >> foreign))
17− return (f:fs)
17+ return . partitionEithers $ f:fs
1818
1919
20−foreign = do reserved "foreign" ; whitespace ; (jsEvent <|> jsValue)
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
20+foreign = do try (reserved "foreign") ; whitespace
21+ Left <$> importEvent <|> Right <$> exportEvent
3622
3723exportEvent = do
38− try (reserved "export" >> whitespace >> reserved "jsEvent" >> whitespace)
24+ try (reserved "export" >> whitespace >> reserved "jsevent" >> whitespace)
3925 js <- jsVar ; whitespace
4026 elm <- lowVar ; whitespace
4127 string "::" ; whitespace
4228 tipe <- typeExpr
4329 case tipe of
4430 ADTPT "Signal" [pt] ->
45− either fail (return . ExportEvent js elm) (toForeignType pt)
31+ either fail (return . (,,) js elm) (toForeignType pt)
4632 _ -> fail "When exporting events, the exported value must be a Signal."
4733
4834importEvent = do
49− try (reserved "import" >> whitespace >> reserved "jsEvent" >> whitespace)
50− js <- jsVar ; whitespace
51− base <- term ; whitespace
52− elm <- lowVar ; whitespace
53− string "::" ; whitespace
35+ try (reserved "import" >> whitespace >> reserved "jsevent" >> whitespace)
36+ js <- jsVar ; whitespace
37+ base <- term <?> "Base case for imported signal (signals cannot be undefined)"
38+ whitespace
39+ elm <- lowVar <?> "Name of imported signal"
40+ whitespace ; string "::" ; whitespace
5441 tipe <- typeExpr
5542 case tipe of
5643 ADTPT "Signal" [pt] ->
57− either fail (return . ImportEvent js elm base) (toForeignType pt)
44+ either fail (return . (,,,) js base elm) (toForeignType pt)
5845 _ -> fail "When importing events, the imported value must be a Signal."
5946
6047
elm/src/Parse/ParseLib.hs+2−1
@@ -11,7 +11,8 @@ reserveds = [ "if", "then", "else"
1111 , "case", "of", "data"
1212 , "let", "in"
1313 , "module", "where"
14− , "import", "as", "hiding" ]
14+ , "import", "as", "hiding"
15+ , "export", "foreign" ]
1516
1617expecting = flip (<?>)
1718
elm/src/Parse/ParseTypes.hs+14−8
@@ -83,14 +83,20 @@ toType pairs outType (name,args) =
8383 _ -> ADT x []
8484
8585toForeignType (LambdaPT t1 t2) =
86− LambdaT <$> toForeignType t1 <*> toForeignType t2
87−toForeignType (ADTPT name args) = do
88− case name == "JSArray" of
89− True -> ADT name <$> mapM toForeignType args
90− False -> Left $ "'" ++ name ++
91− "' is not an exportable type constructor. Only 'JSArray' is exportable."
86+ fail $ "Elm's JavaScript event interface does not yet handle functions. " ++
87+ "Only simple values can be imported and exported in this release."
88+ --LambdaT <$> toForeignType t1 <*> toForeignType t2
89+toForeignType (ADTPT name args)
90+ | isJsStructure name = ADT name <$> mapM toForeignType args
91+ | otherwise =
92+ Left $ "'" ++ name ++ "' is not an exportable type " ++
93+ "constructor. Only 'JSArray' and 'JSTupleN' are exportable."
94+
9295toForeignType (VarPT x@(c:_))
9396 | isLower c =
9497 Left "All exported types must be concrete types (JSNumber, JSString, etc.)"
95− | x `elem` [ "JSString", "JSNumber", "JSElement" ] = Right (ADT x [])
96− | otherwise = Left $ "'" ++ x ++ "' is not an exportable type. JSNumber, JSString, JSElement, and (JSArray a) are exportable."
98+ | x `elem` ["JSString","JSNumber","JSElement","JSBool"] = Right (ADT x [])
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
2727
2828program = do
2929 optional freshLine
30− (names,exports) <- option ([],[]) (moduleDef `followedBy` freshLine)
30+ (names,exports) <- option (["Main"],[]) (moduleDef `followedBy` freshLine)
3131 is <- (do try (lookAhead $ reserved "import")
3232 imports `followedBy` freshLine) <|> return []
33− jsffi <- foreignDefs
34− freshLine
33+ jsffi <- foreignDefs `followedBy` freshLine <|> return ([],[])
3534 (vs,es,ts) <- defs
3635 optional freshLine ; optional spaces ; eof
3736 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
4949 ] ++ hasType (IntT ==> IntT ==> point ==> shape) ["ngon","rect","oval"]
5050
5151
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+
5281-------- Signals --------
5382
5483sig ts = fn ts ==> fn (map signalOf ts)
@@ -62,22 +91,29 @@ signals = sequence
6291 , do ts <- vars 5 ; "lift4" -:: sig ts
6392 , do [a,b] <- vars 2
6493 "foldp" -:: (a ==> b ==> b) ==> b ==> signalOf a ==> signalOf b
94+ , do a <- var ; "randomize" -:: IntT ==> IntT ==> signalOf a ==> signalOf IntT
6595 ]
6696
67−concreteSignals =
68− [ "Mouse.position" -: signalOf point
69− , "Mouse.x" -: signalOf IntT
70− , "Mouse.y" -: signalOf IntT
71− , "Mouse.isDown" -: signalOf BoolT
72− , "Mouse.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]
77− , "Input.password" -: string ==> tupleOf [element, signalOf string]
78− , "Input.textArea" -: IntT ==> IntT ==> tupleOf [element, signalOf string]
79− , "Input.stringDropDown" -: listOf string ==> tupleOf [element, signalOf string]
80− ]
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
105+ , "position" -: signalOf point
106+ , "x" -: signalOf IntT
107+ , "y" -: signalOf IntT
108+ , "isDown" -: signalOf BoolT
109+ , "isClicked" -: signalOf BoolT
110+ , "textField" -: string ==> tupleOf [element, signalOf string]
111+ , "password" -: string ==> 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]
115+ , "stringDropDown" -: listOf string ==> tupleOf [element, signalOf string]
116+ ]
81117
82118-------- Math and Binops --------
83119
@@ -111,7 +147,7 @@ funcs = sequence
111147 , do [a,b,c] <- vars 3 ; "." -:: (b ==> c) ==> (a ==> b) ==> (a ==> c)
112148 , do [a,b] <- vars 2 ; "$" -:: (a ==> b) ==> a ==> b
113149 , 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
115151 , do a <- var ; "Cons" -:: a ==> listOf a ==> listOf a
116152 , do a <- var ; "Nil" -:: listOf a
117153 , do a <- var ; "Just" -:: a ==> ADT "Maybe" [a]
@@ -121,7 +157,7 @@ funcs = sequence
121157
122158ints = map (-: (listOf IntT ==> IntT)) [ "sum","product","maximum","minimum" ]
123159
124−lists = liftM (map (first ("List."++)) . (++ints)) . sequence $
160+lists = liftM (++ints) . sequence $
125161 [ "and" -:: listOf BoolT ==> BoolT
126162 , "or" -:: listOf BoolT ==> BoolT
127163 , "sort" -:: listOf IntT ==> listOf IntT
@@ -136,6 +172,9 @@ lists = liftM (map (first ("List."++)) . (++ints)) . sequence $
136172 , do a <- var ; "exists" -:: (a ==> BoolT) ==> listOf a ==> BoolT
137173 , do a <- var ; "concat" -:: listOf (listOf a) ==> listOf a
138174 , 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]
139178 , do a <- var ; "intersperse" -:: a ==> listOf a ==> listOf a
140179 , do a <- var ; "intercalate" -:: listOf a ==> listOf(listOf a) ==> listOf a
141180 , 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 $
152191-------- Everything --------
153192
154193hints = do
155− fs <- funcs ; ls <- lists ; ss <- signals
194+ fs <- funcs ; ls <- lists ; ss <- signals ; pcasts <- polyCasts
156195 return $ concat [ fs, ls, ss, math, bool, str2elem, textAttrs
157196 , elements, directions, colors, lineTypes, shapes
158− , concreteSignals
197+ , concreteSignals, casts, pcasts
159198 ]
elm/src/Types/Types.hs+9
@@ -30,7 +30,16 @@ point = tupleOf [IntT,IntT]
3030listOf t = ADT "List" [t]
3131signalOf t = ADT "Signal" [t]
3232tupleOf ts = ADT ("Tuple" ++ show (length ts)) ts
33+maybeOf t = ADT "Maybe" [t]
3334string = 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
3443
3544infixr ==>
3645t1 ==> t2 = LambdaT t1 t2