on master help sign in
Introduce basic optimizations.

Reduces the size of string-heavy code dramatically! 70% decrease in the size of the the elm-lang.org home page.

commite33d3290e3b1b1e6d2ae2a51d5606c3716b4345e authorevancz <info@elm-lang.org> dateTue 22 May 2012, 18:07 (14 years ago) parent7875f20
5 files changed+1729−259
core-js/String.js+1 core-js/Text.js+52−51 elm-mini.js+1565−45 src/CompileToJS.hs+3 src/Initialize.hs+108−163
core-js/String.js+1
@@ -9,6 +9,7 @@ var String = function() {
99 };
1010
1111 var toText = function(elmList) {
12+ if (typeof elmList === "string") return elmList;
1213 var a = [];
1314 while (elmList[0] === "Cons") {
1415 a.push(elmList[1]);
core-js/Text.js+52−51
@@ -1,52 +1,53 @@
1−
2−var Text = function() {
3− var fromString = function(elmList) {
4− var a = [];
5− while (elmList[0] === "Cons") {
6− a.push(elmList[1]);
7− elmList = elmList[2];
8− }
9− return String.properEscape(a.join(''));
10− };
11−
12− var addTag = function(tag) { return function(text) {
13− return '<' + tag + '>' + text + '</' + tag + '>';
14− };
15− };
16− var addStyle = function(style, value) { return function(text) {
17− return "<span style='" + style + ":" + value + "'>" + text + "</span>";
18− };
19− };
20−
21− var typeface = function(name) { return addStyle('font-family', name); };
22− var size = function(px) {
23− return addStyle('font-size', px + 'px');
24− };
25− var header = addTag('h1');
26− var height = function(h) { return addStyle('font-size', h+'em'); }
27− var italic = addStyle('font-style', 'italic');
28− var bold = addTag('b');
29− var color = function(c) {
30− return addStyle('color', Color.Internal.extract(c));
31− };
32− var underline = addStyle('text-decoration', 'underline');
33− var overline = addStyle('text-decoration', 'overline');
34− var strikeThrough = addStyle('text-decoration', 'line-through');
35− var link = function(href) { return function(text) {
36− return "<a href='" + fromString(href) + "'>" + text + "</a>";
37− };
38− };
39−
40− return {fromString : fromString,
41− toText: fromString,
42− header : header,
43− height : height,
44− italic : italic,
45− bold : bold,
46− underline : underline,
47− overline : overline,
48− strikeThrough : strikeThrough,
49− monospace : typeface('monospace'),
50− color : color,
51− link : link };
1+
2+var Text = function() {
3+ var fromString = function(elmList) {
4+ if (typeof elmList === "string") return elmList;
5+ var a = [];
6+ while (elmList[0] === "Cons") {
7+ a.push(elmList[1]);
8+ elmList = elmList[2];
9+ }
10+ return String.properEscape(a.join(''));
11+ };
12+
13+ var addTag = function(tag) { return function(text) {
14+ return '<' + tag + '>' + text + '</' + tag + '>';
15+ };
16+ };
17+ var addStyle = function(style, value) { return function(text) {
18+ return "<span style='" + style + ":" + value + "'>" + text + "</span>";
19+ };
20+ };
21+
22+ var typeface = function(name) { return addStyle('font-family', name); };
23+ var size = function(px) {
24+ return addStyle('font-size', px + 'px');
25+ };
26+ var header = addTag('h1');
27+ var height = function(h) { return addStyle('font-size', h+'em'); }
28+ var italic = addStyle('font-style', 'italic');
29+ var bold = addTag('b');
30+ var color = function(c) {
31+ return addStyle('color', Color.Internal.extract(c));
32+ };
33+ var underline = addStyle('text-decoration', 'underline');
34+ var overline = addStyle('text-decoration', 'overline');
35+ var strikeThrough = addStyle('text-decoration', 'line-through');
36+ var link = function(href) { return function(text) {
37+ return "<a href='" + fromString(href) + "'>" + text + "</a>";
38+ };
39+ };
40+
41+ return {fromString : fromString,
42+ toText: fromString,
43+ header : header,
44+ height : height,
45+ italic : italic,
46+ bold : bold,
47+ underline : underline,
48+ overline : overline,
49+ strikeThrough : strikeThrough,
50+ monospace : typeface('monospace'),
51+ color : color,
52+ link : link };
5253}();
elm-mini.js+1565−45
@@ -1,45 +1,1565 @@
1−var Guid=function(){var c=0;return{guid:function(){return c+=1}}}(),Value=function(){var c=function(a){if("boolean"===typeof a)return a?"True":"False";if("number"!==typeof a&&a[0]){if("Tuple"===a[0].substring(0,5)){for(var b="",d=a.length;--d;)b=","+c(a[d])+b;","===b[0]&&(b=b.substring(1));return"("+b+")"}if("Cons"===a[0])for(var d="string"===typeof a[1]?'"':"]",e="string"===typeof a[1]?"":",",b=("string"===typeof a[1]?'"':"[")+c(a[1]),a=a[2];;)if("Cons"===a[0])b+=e+c(a[1]),a=a[2];else return b+d;
2−else{if("Nil"===a[0])return"[]";b="";for(d=a.length;--d;)b=" "+c(a[d])+b;b=a[0]+b;return 1<a.length?"("+b+")":b}}return a+""};return{show:function(a){return Text.monospace(String.properEscape(c(a)))},Tuple:function(){var a=arguments.length,b=Array(a+1);for(b[0]="Tuple"+arguments.length;a--;)b[a+1]=arguments[a];return b},append:function(a,b){if("string"===typeof a&&"string"===typeof b)return a.concat(b);if("Nil"===a[0])return b;for(var d=["Cons",a[1],["Nil"]],c=d,a=a[2];"Cons"===a[0];)c[2]=["Cons",
3−a[1],["Nil"]],a=a[2],c=c[2];c[2]=b;return d}}}(),String=function(){return{toText:function(c){for(var a=[];"Cons"===c[0];)a.push(c[1]),c=c[2];return String.properEscape(a.join(""))},properEscape:function(c){c.replace('"',"&#34;");c.replace("&","&#38;");c.replace("'","&#39;");c.replace("<","&#60;");c.replace(">","&#62;");return c}}}(),Color=function(){var c=function(a,b,c,e){return{r:Math.round(255*a),g:Math.round(255*b),b:Math.round(255*c),a:e}};return{black:c(0,0,0,1),white:c(1,1,1,1),red:c(1,0,0,
4−1),green:c(0,1,0,1),blue:c(0,0,1,1),rgba:function(a){return function(b){return function(d){return function(e){return c(a,b,d,e)}}}},rgb:function(a){return function(b){return function(d){return c(a,b,d,1)}}},Internal:{extract:function(a){return 1===a.a?"rgb("+a.r+","+a.g+","+a.b+")":"rgba("+a.r+","+a.g+","+a.b+","+a.a+")"}}}}(),Element=function(){var c=function(a){a=document.createElement(a);a.id=Guid.guid();return a},a=function(a){var b=c("div");b.appendChild(a);return b},b=function(a){return function(b){return function(d){var e=
5−c("div");e.isElmText=!0;e.innerHTML=d;e.style.textAlign=b;0<a&&(e.style.width=a+"px");e.isElmLeaf=!0;e.style.visibility="hidden";e.style.styleFloat="left";e.style.cssFloat="left";document.body.appendChild(e);d=window.getComputedStyle(e);0>=a&&(e.style.width=d.getPropertyValue("width"));e.style.height=d.getPropertyValue("height");document.body.removeChild(e);e.style.visibility="visible";e.style.styleFloat="none";e.style.cssFloat="none";return e}}},d=b(0)("left"),e=b(0)("justify"),g=b(0)("center"),
6−f=function(b){return"DIV"===b.tagName?b:a(b)},h=function(a){a.style.styleFloat="left";a.style.cssFloat="left";return a},j=function(a){a.style.position="absolute";return a},i=function(a,b,d){for(var e=c("div"),g=d.length;g--;){var j=b(d[g]);e.appendChild(j)}e.elmFlowDirection=a;return e},k=function(a){return function(b){for(var d=[];"Cons"===b[0];)d.push(b[1]),b=b[2];3<=a&&d.reverse();b=a%3;if(0==b)return i("Y",f,d);if(1==b)return i("X",h,d);if(2==b)return i("Z",j,d)}},l=function(a){return function(d){if("A"===
7−d.tagName)return l(a)(d.firstChild),d;if(d.hasOwnProperty("isElmText")){var c=b(a)(d.style.textAlign)(d.innerHTML);d.style.height=c.style.height}d.style.width=a+"px";return d}};return{text:d,image:function(a){var b=c("img");b.isElmLeaf=!0;b.onload=function(){""===b.style.width&&0<this.width&&(b.style.width=b.width=this.width+"px");""===b.style.height&&0<this.height&&(b.style.height=b.height=this.height+"px");Dispatcher.adjust()};b.src=String.toText(a);b.name=b.src;return b},video:function(a){var a=
8−String.toText(a),b=c("video");b.controls="controls";var d=c("source");d.src=a;d.type="video/"+a.substring(a.length-3,a.length);b.appendChild(d);b.isElmLeaf=!0;return b},audio:function(a){var a=String.toString(a),b=c("video");b.controls="controls";var d=c("source");d.src=a;d.type="audio/"+a.substring(a.length-3,a.length);b.appendChild(d);b.isElmLeaf=!0;return b},collage:function(a){return function(b){return function(d){var e=c("canvas");e.style.width=a+"px";e.style.height=b+"px";e.width=a;e.height=
9−b;if(e.getContext){var g=e.getContext("2d");for(g.clearRect(0,0,e.width,e.height);"Cons"===d[0];)g=d[1](g),d=d[2];return e}e.innerHTML="Your browser does not support the canvas element.";e.isElmLeaf=!0;return e}}},flow:k,layers:k(2),beside:function(a){return function(b){return k(1)(["Cons",a,["Cons",b,["Nil"]]])}},above:function(a){return function(b){return k(0)(["Cons",a,["Cons",b,["Nil"]]])}},below:function(a){return function(b){return k(3)(["Cons",a,["Cons",b,["Nil"]]])}},box:function(a){return function(b){b.style.position=
10−"absolute";b.style.margin="auto";var d=(a-1)%3,e=(a-1)/3;2>d&&(b.style.left=0);0<d&&(b.style.right=0);2>e&&(b.style.top=0);0<e&&(b.style.bottom=0);d=c("div");d.style.position="relative";d.appendChild(b);return d}},width:l,height:function(a){return function(b){("A"===b.tagName?b.firstChild:b).style.height=a+"px";return b}},size:function(a){return function(b){return function(d){var e="A"===d.tagName?d.firstChild:d;e.style.width=a+"px";e.style.height=b+"px";return d}}},color:function(a){return function(b){b.style.backgroundColor=
11−Color.Internal.extract(a);return b}},opacity:function(a){return function(b){b.style.opacity=a;return b}},link:function(b){return function(d){var e=c("a");e.href=Text.fromString(b);e.appendChild(d);return a(e)}},asText:function(a){return b(0)("left")(Value.show(a))},plainText:function(a){return b(0)("left")(String.toText(a))},justifiedText:e,centeredText:g,up:0,left:1,inward:2,down:3,right:4,outward:5}}(),Text=function(){var c=function(a){for(var b=[];"Cons"===a[0];)b.push(a[1]),a=a[2];return String.properEscape(b.join(""))},
12−a=function(a){return function(b){return"<"+a+">"+b+"</"+a+">"}},b=function(a,b){return function(d){return"<span style='"+a+":"+b+"'>"+d+"</span>"}},d=a("h1"),e=b("font-style","italic"),a=a("b"),g=b("text-decoration","underline"),f=b("text-decoration","overline"),h=b("text-decoration","line-through");return{fromString:c,toText:c,header:d,height:function(a){return b("font-size",a+"em")},italic:e,bold:a,underline:g,overline:f,strikeThrough:h,monospace:b("font-family","monospace"),color:function(a){return b("color",
13−Color.Internal.extract(a))},link:function(a){return function(b){return"<a href='"+c(a)+"'>"+b+"</a>"}}}}(),Shape=function(){var c=function(a,d,e,c){return{center:a,points:d,theta:e,scale:c}},a=function(a){return function(d){return function(e){return function(c){c.save();c.translate(e.center[0],e.center[1]);c.rotate(e.theta);c.scale(e.scale,e.scale);c.beginPath();var f=e.points;c.moveTo(f[0][0],f[0][1]);for(var h=f.length;h--;)c.lineTo(f[h][0],f[h][1]);c.closePath();a?(c.fillStyle=Color.Internal.extract(d),
14−c.fill()):(c.strokeStyle=Color.Internal.extract(d),c.stroke());c.restore();return c}}}};return{polygon:function(a){return function(d){for(var e=[];"Cons"===a[0];)e.push([a[1][1],a[1][2]]),a=a[2];d=[d[1],d[2]];return c(d,e,0,1)}},ngon:function(a){return function(d){return function(e){for(var g=[],f=a;f--;)g.push([d*Math.cos(2*Math.PI*f/a),d*Math.sin(2*Math.PI*f/a)]);e=[e[1],e[2]];return c(e,g,0,1)}}},rect:function(a){return function(d){return function(e){var g=[[-a/2,-d/2],[a/2,-d/2],[a/2,d/2],[-a/
15−2,d/2]],e=[e[1],e[2]];return c(e,g,0,1)}}},oval:function(a){return function(d){return function(e){for(var g=[],f=2*Math.PI;0<f;f-=Math.PI/50)g.push([a/2*Math.cos(f),d/2*Math.sin(f)]);e=[e[1],e[2]];return c(e,g,0,1)}}},move:function(a){return function(d){return function(e){return c([a+e.center[0],d+e.center[1]],e.points,e.theta,e.scale)}}},rotate:function(a){return function(d){return c(d.center,d.points,d.theta+2*Math.PI*a,d.scale)}},scale:function(a){return function(d){return c(d.center,d.points,
16−d.theta,d.scale*a)}},filled:a(!0),outlined:a(!1),customOutline:function(a){return function(d){return function(c){c.points.push(c.points[0]);return Line.customLine(a)(d)(c)}}}}}(),Line=function(){var c=function(a){return function(b){return function(d){if("string"===typeof a[0]){for(var c=[];"Cons"===a[0];)c.push(a[1]),a=a[2];a=c}0===a.length&&(a=[8,4]);return function(c){c.save();c.beginPath();c.translate(d.center[0],d.center[1]);c.rotate(d.theta);c.scale(d.scale,d.scale);var e=a,h=d.points,j=h.length-
17−1,i=h[j][0],k=h[j][1],l=0,p=0,m=0,n=0,o=0,r=0,t=e.length,s=!0,q=e[0];for(c.moveTo(i,k);j--;){l=h[j][0];p=h[j][1];m=l-i;n=p-k;for(o=Math.sqrt(m*m+n*n);q<=o;)i+=m*q/o,k+=n*q/o,c[s?"lineTo":"moveTo"](i,k),m=l-i,n=p-k,o=Math.sqrt(m*m+n*n),s=!s,r=(r+1)%t,q=e[r];0<o&&(c[s?"lineTo":"moveTo"](l,p),q-=o);i=l;k=p}c.strokeStyle=Color.Internal.extract(b);c.stroke();c.restore();return c}}}};return{line:function(a){for(var b=[];"Cons"===a[0];)b.push([a[1][1],a[1][2]]),a=a[2];return{center:[0,0],points:b,theta:0,
18−scale:1}},customLine:c,solid:function(a){return function(b){return function(d){d.save();d.beginPath();d.translate(b.center[0],b.center[1]);d.rotate(b.theta);d.scale(b.scale,b.scale);var c=b.points,g=c.length;for(d.moveTo(c[g-1][0],c[g-1][1]);g--;)d.lineTo(c[g][0],c[g][1]);d.strokeStyle=Color.Internal.extract(a);d.stroke();d.restore();return d}}},dashed:c([8,4]),dotted:c([3,3])}}(),Elm=function(){var c=function(a){this.id=Guid.guid();this.value=a;this.step=function(a,b){var c=a===this.id;c&&(this.value=
19−b);return c}},a=function(a,b){this.id=Guid.guid();this.value=null;b.reverse();this.recalc=function(){for(var c=a,f=b.length;f--;)c=c(b[f].value);this.value=c};this.recalc();this.step=function(a,c){if(this.hasOwnProperty(a))return!1;for(var d=!1,j=b.length;j--;)d=b[j].step(a,c)||d;d?this.recalc():this[a]=!0;return d}},b=function(a,b,c){this.id=Guid.guid();this.value=b;this.step=function(b,e){if(this.hasOwnProperty(b))return!1;var j=c.step(b,e);j?this.value=a(c.value)(this.value):this[b]=!0;return j}};
20−return{Input:function(a){return new c(a)},Lift:function(b,c){return new a(b,c)},Fold:function(a,c,g){return new b(a,c,g)}}}(),Dispatcher=function(){var c=null,a=function(b){var c=b.childNodes,e=c.length;if(b.hasOwnProperty("isElmLeaf")){var c=""===b.style.width?0:b.style.width.slice(0,-2)-0,g=""===b.style.height?0:b.style.height.slice(0,-2)-0;return[c,g]}if(1===e){var f=a(c[0]);""!==b.style.width&&(f[0]=b.style.width.slice(0,-2)-0);""!==b.style.height&&(f[1]=b.style.height.slice(0,-2)-0);0!==f[0]&&
21−(b.style.width=f[0]+"px");0!==f[1]&&(b.style.height=f[1]+"px");return f}for(var h=0,j=g=0,i=0,k=!0,l=!0;e--;)f=a(c[e]),h=Math.max(h,f[0]),g=Math.max(g,f[1]),j+=f[0],i+=f[1],k=k&&0<f[0],l=l&&0<f[1];c=h;e=b.elmFlowDirection;"X"===e&&(c=k?j:0);"Y"===e&&(g=l?i:0);0<c&&(b.style.width=c+"px");0<g&&(b.style.height=g+"px");return[c,g]};return{initialize:function(){try{c=main()}catch(b){throw document.body.innerHTML="An Error Occured: Better Messages to come.",b;}c.hasOwnProperty("step")||(c=Elm.Input(c));
22−var d=document.getElementById("content");d.appendChild(c.value);a(d);d=document.getElementById("widthChecker").offsetWidth;d!==window.innerWidth&&Dispatcher.notify(Window.dimensions.id,Value.Tuple(d,window.innerHeight))},notify:function(b,d){if(c.step(b,d)){var e=document.getElementById("content");e.replaceChild(c.value,e.children[0]);a(e)}},adjust:function(){var b=document.getElementById("content");a(b)}}}(),Signal=function(){function c(a){for(var b=["Nil"],c=a.length;c--;)b=["Cons",a[c],b];return b}
23−var a=function(){return document.addEventListener?function(a,b,c){a.addEventListener(b,c,!1)}:function(a,b,c){a.attachEvent("on"+b,c)}}(),b=function(){function b(a){var c=0,d=0;a||(a=window.event);if(a.pageX||a.pageY)c=a.pageX,d=a.pageY;else if(a.clientX||a.clientY)c=a.clientX+document.body.scrollLeft+document.documentElement.scrollLeft,d=a.clientY+document.body.scrollTop+document.documentElement.scrollTop;return Value.Tuple(c,d)}var c=Elm.Input(Value.Tuple(0,0)),d=Elm.Input(!1),e=Elm.Input(!1);a(document,
24−"click",function(){Dispatcher.notify(e.id,!0);Dispatcher.notify(e.id,!1)});a(document,"mousedown",function(){Dispatcher.notify(d.id,!0)});a(document,"mouseup",function(){Dispatcher.notify(d.id,!1)});a(document,"mousemove",function(a){Dispatcher.notify(c.id,b(a))});return{position:c,x:Elm.Lift(function(a){return a[1]},[c]),y:Elm.Lift(function(a){return a[2]},[c]),isClicked:e,isDown:d,clickedOn:function(b){var c=Elm.Input(!1);a(b,"click",function(){Dispatcher.notify(c.id,!0);Dispatcher.notify(c.id,
25−!1)});return Value.Tuple(b,c)}}}(),d=function(){return{every:function(a){var a=1E3*a,b=Elm.Input(0),c=0;setInterval(function(){c+=a;Dispatcher.notify(b.id,c/1E3)},a);return b},after:function(a){var a=1E3*a,b=Elm.Input(!1);setTimeout(function(){Dispatcher.notify(b.id,!0)},a);return b},before:function(a){var a=1E3*a,b=Elm.Input(!0);setTimeout(function(){Dispatcher.notify(b.id,!1)},a);return b}}}(),e=function(){var b=Elm.Input(Value.Tuple(window.innerWidth,window.innerHeight));a(window,"resize",function(){var a=
26−document.getElementById("widthChecker").offsetWidth;Dispatcher.notify(b.id,Value.Tuple(a,window.innerHeight))});return{dimensions:b,width:Elm.Lift(function(a){return a[1]},[b]),height:Elm.Lift(function(a){return a[2]},[b])}}(),g=function(){var a=function(a){return function(b){var d=Elm.Input(["Waiting"]),e={};window.XMLHttpRequest?e=new XMLHttpRequest:window.ActiveXObject&&(e=new ActiveXObject("Microsoft.XMLHTTP"));e.onreadystatechange=function(){4===e.readyState&&Dispatcher.notify(d.id,200===e.status?
27−["Success",c(e.responseText)]:["Failure",e.status,c(e.statusText)])};e.open(a,String.toText(b),!0);e.send(null);return d}},b=function(a){return function(b){var d=Elm.Input(["Nothing"]),b=Elm.Lift(function(b){if("Just"!==b[0]){try{Dispatcher.notify(d.id,["Nothing"])}catch(e){}return[]}try{Dispatcher.notify(d.id,["Just",["Waiting"]])}catch(l){d.value=["Just",["Waiting"]]}var f={};window.XMLHttpRequest?f=new XMLHttpRequest:window.ActiveXObject&&(f=new ActiveXObject("Microsoft.XMLHTTP"));f.onreadystatechange=
28−function(){4===f.readyState&&Dispatcher.notify(d.id,["Just",200===f.status?["Success",c(f.responseText)]:["Failure",f.status,c(f.statusText)]])};f.open(a,String.toText(b[1]),!0);f.send(null);return[]},[b]);return Elm.Lift(function(a){return function(){return a}},[d,b])}};return{get:a("GET"),post:a("POST"),gets:b("GET"),posts:b("POST")}}(),f=function(){return{inRange:function(a){return function(b){return Elm.Input(Math.floor(Math.random()*(b-a+1))+a)}},randomize:function(a){return function(b){return function(c){return Elm.Lift(function(){return Math.floor(Math.random()*
29−(b-a+1))+a},[c])}}}}}(),h=function(){var b=function(b){b.isElmLeaf=!0;var d=Elm.Input(["Nil"]);a(b,"keyup",function(){Dispatcher.notify(d.id,c(b.value));b.focus()});return Value.Tuple(b,d)},d=function(a){a=document.createElement(a);a.id=Guid.guid();return a},e=function(b){for(var c=d("select"),e=[];"Cons"===b[0];){var f=d("option"),g=Text.toText(b[1][1]);f.value=g;f.innerHTML=g;c.appendChild(f);e.push(b[1][2]);b=b[2]}var h=Elm.Input(e[0]);a(c,"change",function(){Dispatcher.notify(h.id,e[c.selectedIndex])});
30−return Value.Tuple(c,h)};return{textArea:function(a){return function(c){var e=d("textarea");e.rows=c;e.cols=a;return b(e,"")}},textField:function(a){var c=d("input");c.type="text";return b(c,a)},password:function(a){var c=d("input");c.type="password";return b(c,a)},checkbox:function(b){var c=d("input");c.type="checkbox";c.checked=b;var e=Elm.Input(b);a(c,"change",function(){Dispatcher.notify(e.id,c.checked)});return Value.Tuple(c,e)},dropDown:e,stringDropDown:function(a){return e(List.map(function(a){return Value.Tuple(a,
31−a)})(a))},button:function(b){var c=d("input");c.type="button";c.value=Text.toText(b);var e=Elm.Input(!1);a(c,"click",function(){Dispatcher.notify(e.id,!0);Dispatcher.notify(e.id,!1)});return Value.Tuple(c,e)}}}();return{Mouse:b,Time:d,Window:e,HTTP:g,Random:f,Input:h}}(),List=function(){function c(a){return function(b){if("Nil"===b[0])return b;"Cons"!==b[0]&&i();for(var c=["Cons",a(b[1]),["Nil"]],d=c,b=b[2];"Cons"===b[0];)d[2]=["Cons",a(b[1]),["Nil"]],b=b[2],d=d[2];return c}}function a(a){return function(b){return function(c){var d=
32−b;if("Nil"===c[0])return d;for("Cons"!==c[0]&&i();"Cons"===c[0];)d=a(c[1])(d),c=c[2];return d}}}function b(a){return function(b){return function(c){var d=b;if("Nil"===c[0])return d;"Cons"!==c[0]&&i();for(var e=[];"Cons"===c[0];)e.push(c[1]),c=c[2];for(c=e.length;c--;)d=a(e[c])(d);return d}}}function d(b){return function(c){var d;"Cons"!==c[0]?d=void 0:(d=c[1],c=c[2],d=a(b)(d)(c));return d}}function e(a){return function(b){return function(c){if("Nil"===c[0])return["Cons",b,["Nil"]];"Cons"!==c[0]&&
33−i();for(var d=[b];"Cons"===c[0];)b=a(c[1])(b),d.push(b),c=c[2];for(var c=["Nil"],e=d.length;e--;)c=["Cons",d[e],c];return c}}}function g(a){return function(b){return function(){for(var c=[function(a){return"Nil"!==a[0]?void 0:["Tuple2",["Nil"],["Nil"]]},function(b){if("Cons"===b[0]){var c=b[1],b=b[2];var d=g(a)(b);"Tuple2"!==d[0]?c=void 0:(b=d[1],d=d[2],c=a(c)?["Tuple2",["Cons",c,b],d]:["Tuple2",b,["Cons",c,d]]);return c}}],d=c.length;d--;){var e=c[d](b);if(void 0!==e)return e}}()}}function f(a){return function(){for(var b=
34−[function(a){return"Nil"!==a[0]?void 0:["Tuple2",["Nil"],["Nil"]]},function(a){if("Cons"!==a[0])a=void 0;else if(a=["Tuple2",a[1],f(a[2])],"Tuple2"!==a[0]||"Tuple2"!==a[1][0])a=void 0;else var b=a[1][1],c=a[1][2],a="Tuple2"!==a[2][0]?void 0:["Tuple2",["Cons",b,a[2][1]],["Cons",c,a[2][2]]];return a}],c=b.length;c--;){var d=b[c](a);if(void 0!==d)return d}}()}function h(a){return function(b){return function(){for(var c=[function(a){return"Nil"!==a[0]?void 0:["Nil"]},function(a){if("Cons"===a[0]){var b=
35−a[1];return"Nil"!==a[2][0]?void 0:["Cons",b,["Nil"]]}},function(b){if("Cons"===b[0]){var c=b[1];if("Cons"===b[2][0]){var d=b[2][1],b=b[2][2];return["Cons",c,["Cons",a,h(a)(["Cons",d,b])]]}}}],d=c.length;d--;){var e=c[d](b);if(void 0!==e)return e}}()}}function j(a){return function(b){return function(){for(var c=[function(a){return"Nil"!==a[0]?void 0:["Nil"]},function(a){if("Cons"===a[0]){var b=a[1];return"Nil"!==a[2][0]?void 0:b}},function(b){if("Cons"===b[0]){var c=b[1];if("Cons"===b[2][0]){var d=
36−b[2][1],b=b[2][2];return Value.append(c,Value.append(a,j(a)(["Cons",d,b])))}}}],d=c.length;d--;){var e=c[d](b);if(void 0!==e)return e}}()}}var i=function(){throw"Function expecting a list!";},k=a(function(a){return function(b){return["Cons",a,b]}})(["Nil"]),l=b(function(a){return function(b){return Value.append(a,b)}})(["Nil"]),p=a(function(a){return function(b){return a&&b}})(!0),m=a(function(a){return function(b){return a||b}})(!1),n=a(function(a){return function(b){return a+b}})(0),o=a(function(a){return function(b){return a*
37−b}})(1),r=d(function(a){return function(b){return Math.max(a,b)}}),t=d(function(a){return function(b){return Math.min(a,b)}});return{head:function(a){if("Cons"!==a[0])throw"Error: 'head' only accepts lists of length greater than one.";return a[1]},tail:function(a){if("Cons"!==a[0])throw"Error: 'tail' only accepts lists of length greater than one.";return a[2]},map:c,foldl:a,foldr:b,foldl1:d,foldr1:function(a){return function(c){var d;"Cons"!==c[0]?d=void 0:(d=c[1],c=c[2],d=b(a)(d)(c));return d}},
38−scanl:e,scanl1:function(a){return function(b){if("Cons"!==b[0])throw"Error: 'scanl1' requires a list of at least length 1.";return e(a)(b[1])(b[2])}},filter:function(a){return function(b){if("Nil"===b[0])return b;"Cons"!==b[0]&&i();for(var c=[];"Cons"===b[0];)a(b[1])&&c.push(b[1]),b=b[2];for(var b=["Nil"],d=c.length;d--;)b=["Cons",c[d],b];return b}},length:function(a){for(var b=0;"Cons"===a[0];)b+=1,a=a[2];return b},reverse:k,concat:l,concatMap:function(a){return function(b){return l(c(a)(b))}},and:p,
39−or:m,forall:function(b){return a(function(a){return function(c){return c&&b(a)}})(!0)},exists:function(b){return a(function(a){return function(c){return c||b(a)}})(!1)},sum:n,product:o,maximum:r,minimum:t,partition:g,zipWith:function(a){return function(b){return function(c){if("Nil"===b[0]||"Nil"===c[0])return b;("Cons"!==b[0]||"Cons"!==c[0])&&i();for(var d=[];"Cons"===b[0]&&"Cons"===c[0];)d.push(a(b[1])(c[1])),b=b[2],c=c[2];for(var c=["Nil"],e=d.length;e--;)c=["Cons",d[e],c];return c}}},zip:function(a){return function(b){if("Nil"===
40−a[0]||"Nil"===b[0])return a;("Cons"!==a[0]||"Cons"!==b[0])&&i();for(var c=[];"Cons"===a[0]&&"Cons"===b[0];)c.push(["Tuple2",a[1],b[1]]),a=a[2],b=b[2];for(var b=["Nil"],d=c.length;d--;)b=["Cons",c[d],b];return b}},unzip:f,intersperse:h,intercalate:j,sort:function(a){if("Nil"===a[0])return a;"Cons"!==a[0]&&i();for(var b=[];"Cons"===a[0];)b.push(a[1]),a=a[2];b.sort(function(a,b){return a-b});for(var a=["Nil"],c=b.length;c--;)a=["Cons",b[c],a];return a}}}(),id=function(c){return c},not=function(c){return!c},
41−sqrt=function(c){return Math.sqrt(c)},rem=function(c){return function(a){return c%a}},mod=function(c){return function(a){var b=c%a,b=0==c?0:0<a?0<=c?b:b+a:-mod(-c)(-a);return b==a?0:b}},abs=function(c){return Math.abs(c)},logBase=function(c){return function(a){return Math.log(a)/Math.log(c)}},min=function(c){return function(a){return Math.min(c,a)}},max=function(c){return function(a){return Math.max(c,a)}},clamp=function(c){return function(a){return function(b){return Math.min(a,Math.max(c,b))}}},
42−sin=Math.sin,cos=Math.cos,tan=Math.tan,asin=Math.asin,acos=Math.acos,atan=Math.atan,flip=function(c){return function(a){return function(b){return c(b)(a)}}},Just=function(c){return["Just",c]},Nothing=["Nothing"];function constant(c){return Elm.Input(c)}function lift(c){return function(a){return Elm.Lift(c,[a])}}function lift2(c){return function(a){return function(b){return Elm.Lift(c,[a,b])}}}
43−function lift3(c){return function(a){return function(b){return function(d){return Elm.Lift(c,[a,b,d])}}}}function lift4(c){return function(a){return function(b){return function(d){return function(e){return Elm.Lift(c,[a,b,d,e])}}}}}function foldp(c){return function(a){return function(b){return Elm.Fold(c,a,b)}}}var includeGlobal=this;
44−(function(){var c=function(a){for(var c in a)if("Internal"!==c)try{includeGlobal[c]=a[c]}catch(e){"length"===c&&(includeGlobal.execScript("var length;"),length=a[c])}},a=function(a){return function(c){includeGlobal[a]=includeGlobal[a]||{};for(var e in c)"Internal"!==e&&(includeGlobal[a][e]=c[e])}};c(Element);c(Text);color=Element.color;height=Element.height;show=Value.show;a("Time")(Signal.Time);a("Mouse")(Signal.Mouse);a("Window")(Signal.Window);a("HTTP")(Signal.HTTP);a("Input")(Signal.Input);a("Random")(Signal.Random);
45−c(Color);c(Shape);c(Line)})();
1+
2+var Guid = function() {
3+ var counter = 0;
4+ var guid = function() { counter += 1; return counter; };
5+ return {guid : guid};
6+}();
7+var Value = function(){
8+ var Tuple = function() {
9+ var len = arguments.length;
10+ var arr = new Array(len+1);
11+ arr[0] = "Tuple" + arguments.length;
12+ for (var i = len; i--; ) {
13+ arr[i+1] = arguments[i];
14+ }
15+ return arr;
16+ };
17+
18+ var toString = function(v) {
19+ if (typeof v === "boolean") {
20+ return v ? "True" : "False";
21+ } else if (typeof v === "number") {
22+ return v+"";
23+ } else if (v[0]) {
24+ if (v[0].substring(0,5) === "Tuple") {
25+ var output = "";
26+ for (var i = v.length; --i; ) {
27+ output = "," + toString(v[i]) + output;
28+ }
29+ if (output[0] === ",") output = output.substring(1);
30+ return "("+output+")";
31+ } else if (v[0] === "Cons") {
32+ var start = (typeof v[1] === "string") ? '"' : "[";
33+ var end = (typeof v[1] === "string") ? '"' : "]";
34+ var div = (typeof v[1] === "string") ? "" : ",";
35+ var output = start + toString(v[1]);
36+ v = v[2];
37+ while (true) {
38+ if (v[0] === "Cons") {
39+ output += div + toString(v[1]);
40+ v = v[2];
41+ } else {
42+ return output + end;
43+ }
44+ }
45+ } else if (v[0] === "Nil") {
46+ return "[]";
47+ } else {
48+ var output = "";
49+ for (var i = v.length; --i; ) {
50+ output = " " + toString(v[i]) + output
51+ }
52+ output = v[0] + output;
53+ return (v.length > 1) ? "(" + output + ")" : output;
54+ }
55+ }
56+ return v+"";
57+ };
58+ var show = function(v) {
59+ return Text.monospace(String.properEscape(toString(v)));
60+ };
61+ var append = function(xs,ys) {
62+ if (typeof xs === "string" && typeof ys === "string") {
63+ return xs.concat(ys);
64+ }
65+ if (xs[0] === "Nil") {
66+ return ys;
67+ }
68+ var root = ["Cons", xs[1], ["Nil"]];
69+ var curr = root;
70+ xs = xs[2];
71+ while (xs[0]==="Cons") {
72+ curr[2] = ["Cons", xs[1], ["Nil"]];
73+ xs = xs[2];
74+ curr = curr[2];
75+ }
76+ curr[2] = ys;
77+ return root;
78+ };
79+ return {show:show, Tuple:Tuple, append:append};
80+}();var String = function() {
81+ var properEscape = function(str) {
82+ str.replace('"', "&#34;");
83+ str.replace("&", "&#38;");
84+ str.replace("'", "&#39;");
85+ str.replace("<", "&#60;");
86+ str.replace(">", "&#62;");
87+ return str;
88+ };
89+
90+ var toText = function(elmList) {
91+ if (typeof elmList === "string") return elmList;
92+ var a = [];
93+ while (elmList[0] === "Cons") {
94+ a.push(elmList[1]);
95+ elmList = elmList[2];
96+ }
97+ return String.properEscape(a.join(''));
98+ };
99+
100+ return {toText : toText,
101+ properEscape : properEscape };
102+}();
103+var Color = function() {
104+
105+ var create = function(r,g,b,a) {
106+ return { r: Math.round(255*r),
107+ g: Math.round(255*g),
108+ b: Math.round(255*b),
109+ a: a };
110+ };
111+
112+ var extract = function(c) {
113+ if (c.a === 1) {
114+ return 'rgb(' + c.r + ',' + c.g + ',' + c.b + ')';
115+ }
116+ return 'rgba(' + c.r + ',' + c.g + ',' + c.b + ',' + c.a + ')';
117+ };
118+
119+ var rgba = function(r) { return function(g) { return function(b) {
120+ return function(a) { return create(r,g,b,a); }; }; };
121+ };
122+
123+ var rgb = function(r) { return function(g) { return function(b) {
124+ return create(r,g,b,1); }; };
125+ };
126+ return {black: create(0,0,0,1),
127+ white: create(1,1,1,1),
128+ red : create(1,0,0,1),
129+ green: create(0,1,0,1),
130+ blue : create(0,0,1,1),
131+ rgba : rgba,
132+ rgb : rgb,
133+ Internal : { extract:extract }
134+ };
135+}();
136+var Element = function() {
137+ var newElement = function(elementType) {
138+ var e = document.createElement(elementType);
139+ e.id = Guid.guid();
140+ //e.timesAdded = 0;
141+ return e;
142+ };
143+ var addTo = function(container, elem) {
144+ container.appendChild(clone(elem));
145+ //elem.timesAdded += 1;
146+ };
147+ var clone = function(e) {
148+ return e;
149+ /*if (e.timesAdded === 0) { return e; }
150+ if (e.tagName === "CANVAS") {
151+ var newCanvas = e.cloneNode(true);
152+ var ctx = newCanvas.getContext('2d');
153+ ctx.drawImage(e, 0, 0);
154+ return newCanvas;
155+ } else if (e.tagName === "IMG") {
156+ d = image([]);
157+ d.src = e.src;
158+ d.name = e.name;
159+ if (e.style.width !== "") { d.style.width = d.width = e.style.width; }
160+ if (e.style.height !== ""){d.style.height = d.height = e.style.height;}
161+ return d;
162+ } else if (e.hasOwnProperty('isElmLeaf')) {
163+ return e.cloneNode(true);
164+ } else {
165+ d = e.cloneNode(false);
166+ var kids = e.childNodes;
167+ var len = kids.length;
168+ for (var i = 0; i < len; i++) {
169+ d.appendChild(clone(kids[i]));
170+ }
171+ return d;
172+ }*/
173+ };
174+ var divify = function(e) {
175+ var div = newElement('div');
176+ addTo(div, e);
177+ return div;
178+ };
179+ var makeText = function(w) { return function(pos) { return function(txt) {
180+ var e = newElement('div');
181+ e.isElmText = true;
182+ e.innerHTML = txt;
183+ e.style.textAlign = pos;
184+ if (w > 0) e.style.width = w + "px";
185+ e.isElmLeaf = true;
186+ e.style.visibility = "hidden";
187+ e.style.styleFloat = "left";
188+ e.style.cssFloat = "left";
189+ document.body.appendChild(e);
190+ var cStyle = window.getComputedStyle(e);
191+ if (w <= 0) e.style.width = cStyle.getPropertyValue("width");
192+ e.style.height = cStyle.getPropertyValue("height");
193+ document.body.removeChild(e);
194+ e.style.visibility = "visible"
195+ e.style.styleFloat = "none";
196+ e.style.cssFloat = "none";
197+ return e;
198+ };
199+ };
200+ };
201+ var link = function (href) { return function (e) {
202+ var a = newElement('a');
203+ a.href = Text.fromString(href);
204+ addTo(a,e);
205+ return divify(a);
206+ };
207+ };
208+
209+ var text = makeText(0)('left');
210+ var plainText = function(str) {
211+ return makeText(0)("left")(String.toText(str)); };
212+ var justifiedText = makeText(0)('justify');
213+ var centeredText = makeText(0)('center');
214+ var asText = function(v) { return makeText(0)("left")(Value.show(v)); };
215+
216+ var image = function(src) {
217+ var img = newElement('img');
218+ img.isElmLeaf = true;
219+ img.onload = function() {
220+ if (img.style.width === "" && this.width > 0) {
221+ img.style.width = img.width = this.width + "px";
222+ }
223+ if (img.style.height === "" && this.height > 0) {
224+ img.style.height = img.height = this.height + "px";
225+ }
226+ Dispatcher.adjust()
227+ };
228+ img.src = String.toText(src);
229+ img.name = img.src;
230+ return img;
231+ };
232+ var video = function(src) {
233+ src = String.toText(src);
234+ var e = newElement('video');
235+ e.controls = "controls";
236+ var source = newElement('source');
237+ source.src = src;
238+ source.type = "video/" + src.substring(src.length - 3, src.length);
239+ addTo(e, source);
240+ e.isElmLeaf = true;
241+ return e;
242+ };
243+ var audio = function(src) {
244+ src = String.toString(src);
245+ var e = newElement('video');
246+ e.controls = "controls";
247+ var source = newElement('source');
248+ source.src = src;
249+ source.type = "audio/" + src.substring(src.length - 3, src.length);
250+ addTo(e, source);
251+ e.isElmLeaf = true;
252+ return e;
253+ };
254+ var collage = function(w) { return function(h) { return function(cflist) {
255+ var canvas = newElement('canvas');
256+ canvas.style.width = w + 'px';
257+ canvas.style.height = h + 'px';
258+ canvas.width = w;
259+ canvas.height = h;
260+ if (canvas.getContext) {
261+ var ctx = canvas.getContext('2d');
262+ ctx.clearRect(0,0, canvas.width, canvas.height);
263+ while (cflist[0] === "Cons") {
264+ ctx = cflist[1](ctx);
265+ cflist = cflist[2];
266+ }
267+ return canvas;
268+ }
269+ canvas.innerHTML = "Your browser does not support the canvas element.";
270+ canvas.isElmLeaf = true;
271+ return canvas;
272+ };
273+ };
274+ };
275+
276+ var goDown = function(e) {
277+ return e.tagName === "DIV" ? e : divify(e);
278+ };
279+ var goRight = function(e) {
280+ e.style.styleFloat = "left";
281+ e.style.cssFloat = "left";
282+ return e;
283+ };
284+ var goIn = function(e) {
285+ e.style.position = 'absolute';
286+ return e;
287+ };
288+ var flowWith = function(dir, f, elist) {
289+ var container = newElement('div');
290+ for (var i = elist.length; i--; ) {
291+ addTo(container, f(elist[i]));
292+ }
293+ container.elmFlowDirection = dir;
294+ return container;
295+ };
296+
297+ var flow = function(direction) { return function(elist) {
298+ var arr = [];
299+ while (elist[0] === "Cons") {
300+ arr.push(elist[1]);
301+ elist = elist[2];
302+ }
303+ if (direction >= 3) arr.reverse();
304+ var f = function(x) { return x; };
305+ var dir = direction % 3;
306+ if (dir == 0) return flowWith("Y", goDown , arr);
307+ if (dir == 1) return flowWith("X", goRight, arr);
308+ if (dir == 2) return flowWith("Z", goIn , arr);
309+ };
310+ };
311+
312+ var beside = function(a) { return function(b) {
313+ return flow(1)(["Cons",a,["Cons",b,["Nil"]]]); }; };
314+ var above = function(a) { return function(b) {
315+ return flow(0)(["Cons",a,["Cons",b,["Nil"]]]); }; };
316+ var below = function(a) { return function(b) {
317+ return flow(3)(["Cons",a,["Cons",b,["Nil"]]]); }; };
318+
319+ var box = function(pos) { return function(e) {
320+ e.style.position = "absolute";
321+ e.style.margin = "auto";
322+ var x = (pos - 1) % 3;
323+ var y = (pos - 1) / 3;
324+ if (x < 2) e.style.left = 0;
325+ if (x > 0) e.style.right = 0;
326+ if (y < 2) e.style.top = 0;
327+ if (y > 0) e.style.bottom = 0;
328+ var div = newElement('div');
329+ div.style.position = "relative";
330+ addTo(div,e);
331+ return div;
332+ };
333+ };
334+
335+ var width = function(w) { return function(e) {
336+ if (e.tagName === "A") {
337+ width(w)(e.firstChild);
338+ return e;
339+ }
340+ if (e.hasOwnProperty('isElmText')) {
341+ var d = makeText(w)(e.style.textAlign)(e.innerHTML);
342+ e.style.height = d.style.height;
343+ }
344+ e.style.width = w + "px";
345+ return e;
346+ };
347+ };
348+ var height = function(h) { return function(e) {
349+ (e.tagName === "A" ? e.firstChild : e).style.height = h + "px";
350+ return e;
351+ };
352+ };
353+ var size = function(w) { return function(h) { return function(e) {
354+ var d = e.tagName === "A" ? e.firstChild : e;
355+ d.style.width = w + "px";
356+ d.style.height = h + "px";
357+ return e;
358+ };
359+ };
360+ };
361+
362+ var color = function(c) { return function(e) {
363+ e.style.backgroundColor = Color.Internal.extract(c);
364+ return e;
365+ };
366+ };
367+ var opacity = function(value) { return function(e) {
368+ e.style.opacity = value;
369+ return e;
370+ };
371+ };
372+
373+ return {text : text,
374+ image : image,
375+ video : video,
376+ audio : audio,
377+ collage : collage,
378+ flow : flow,
379+ layers : flow(2),
380+
381+ beside : beside,
382+ above : above,
383+ below : below,
384+ box : box,
385+
386+ width : width,
387+ height : height,
388+ size : size,
389+ color : color,
390+ opacity : opacity,
391+
392+ link : link,
393+ asText : asText,
394+ plainText : plainText,
395+ justifiedText : justifiedText,
396+ centeredText : centeredText,
397+
398+ // directions
399+ up : 0,
400+ left : 1,
401+ inward : 2,
402+ down : 3,
403+ right : 4,
404+ outward : 5
405+ };
406+}();
407+
408+
409+
410+var Text = function() {
411+ var fromString = function(elmList) {
412+ if (typeof elmList === "string") return elmList;
413+ var a = [];
414+ while (elmList[0] === "Cons") {
415+ a.push(elmList[1]);
416+ elmList = elmList[2];
417+ }
418+ return String.properEscape(a.join(''));
419+ };
420+
421+ var addTag = function(tag) { return function(text) {
422+ return '<' + tag + '>' + text + '</' + tag + '>';
423+ };
424+ };
425+ var addStyle = function(style, value) { return function(text) {
426+ return "<span style='" + style + ":" + value + "'>" + text + "</span>";
427+ };
428+ };
429+
430+ var typeface = function(name) { return addStyle('font-family', name); };
431+ var size = function(px) {
432+ return addStyle('font-size', px + 'px');
433+ };
434+ var header = addTag('h1');
435+ var height = function(h) { return addStyle('font-size', h+'em'); }
436+ var italic = addStyle('font-style', 'italic');
437+ var bold = addTag('b');
438+ var color = function(c) {
439+ return addStyle('color', Color.Internal.extract(c));
440+ };
441+ var underline = addStyle('text-decoration', 'underline');
442+ var overline = addStyle('text-decoration', 'overline');
443+ var strikeThrough = addStyle('text-decoration', 'line-through');
444+ var link = function(href) { return function(text) {
445+ return "<a href='" + fromString(href) + "'>" + text + "</a>";
446+ };
447+ };
448+
449+ return {fromString : fromString,
450+ toText: fromString,
451+ header : header,
452+ height : height,
453+ italic : italic,
454+ bold : bold,
455+ underline : underline,
456+ overline : overline,
457+ strikeThrough : strikeThrough,
458+ monospace : typeface('monospace'),
459+ color : color,
460+ link : link };
461+}();
462+var Shape = function() {
463+
464+ var create = function(center, ps, theta, s) {
465+ return { center: center, points: ps, theta: theta, scale: s };
466+ };
467+
468+ //// Construction ////
469+
470+ var polygon = function(ps) { return function(center) {
471+ var parr = [];
472+ while (ps[0] === "Cons") {
473+ parr.push([ps[1][1], ps[1][2]]);
474+ ps = ps[2];
475+ }
476+ center = [center[1], center[2]];
477+ return create(center, parr, 0, 1);
478+ };
479+};
480+ var ngon = function(n) { return function(r) { return function(center) {
481+ var ps = [];
482+ for (var i = n; i--;) {
483+ ps.push([r * Math.cos(Math.PI * 2 * i/n),
484+ r * Math.sin(Math.PI * 2 * i/n)]);
485+ }
486+ center = [center[1], center[2]];
487+ return create(center, ps, 0, 1);
488+ };
489+ };
490+};
491+ var rect = function(w) { return function(h) { return function(center) {
492+ var ps = [[- w/2, - h/2],
493+ [ w/2, - h/2],
494+ [ w/2, h/2],
495+ [- w/2, h/2]];
496+ center = [center[1], center[2]];
497+ return create(center, ps, 0, 1);
498+ };
499+ };
500+ };
501+ var oval = function(w) { return function(h) { return function(center) {
502+ var ps = [];
503+ for (var theta = 2 * Math.PI; theta > 0; theta -= Math.PI /50) {
504+ ps.push([w/2 * Math.cos(theta), h/2 * Math.sin(theta)]);
505+ }
506+ center = [center[1], center[2]];
507+ return create(center, ps, 0, 1);
508+ };
509+ };
510+ };
511+
512+//// Transforms ////
513+
514+ var move = function(x) { return function(y) { return function(shape) {
515+ var newCenter = [x + shape.center[0],y + shape.center[1]];
516+ return create(newCenter, shape.points, shape.theta, shape.scale);
517+ };
518+ };
519+ };
520+ var rotate = function(theta) { return function(shape) {
521+ var newTheta = shape.theta + 2 * Math.PI * theta;
522+ return create(shape.center, shape.points, newTheta, shape.scale);
523+ };
524+ };
525+ var scale = function(s) { return function(shape) {
526+ return create(shape.center, shape.points, shape.theta, shape.scale * s);
527+ };
528+ };
529+
530+
531+ //// Atomize ////
532+
533+ var draw = function(fill) {
534+ return function(color) { return function(shape) { return function(ctx) {
535+ ctx.save();
536+ ctx.translate(shape.center[0], shape.center[1]);
537+ ctx.rotate(shape.theta);
538+ ctx.scale(shape.scale, shape.scale);
539+ ctx.beginPath();
540+ var points = shape.points;
541+ ctx.moveTo(points[0][0], points[0][1]);
542+ for (var i = points.length; i--; ) {
543+ ctx.lineTo(points[i][0], points[i][1]);
544+ }
545+ ctx.closePath();
546+ if (fill) {
547+ ctx.fillStyle = Color.Internal.extract(color);
548+ ctx.fill();
549+ } else {
550+ ctx.strokeStyle = Color.Internal.extract(color);
551+ ctx.stroke();
552+ }
553+ ctx.restore();
554+ return ctx;
555+ };
556+ };
557+ };
558+ };
559+
560+ var customOutline = function(p) {
561+ return function(c) { return function(shape) {
562+ shape.points.push(shape.points[0]);
563+ return Line.customLine(p)(c)(shape);
564+ };
565+ };
566+ };
567+ return {polygon:polygon, ngon:ngon, rect:rect, oval:oval,
568+ move:move, rotate:rotate, scale:scale,
569+ filled:draw(true), outlined:draw(false), customOutline:customOutline };
570+}();
571+var Line = function() {
572+
573+ var pair = function(a,b) { return [a,b]; };
574+
575+ var create = function(center, ps, theta, s) {
576+ return { center: center, points: ps, theta: theta, scale: s };
577+ };
578+
579+
580+ //// Construction ////
581+
582+ var line = function(ps) {
583+ var parr = [];
584+ while (ps[0] === "Cons") {
585+ parr.push(pair(ps[1][1], ps[1][2]));
586+ ps = ps[2];
587+ }
588+ return create(pair(0,0), parr, 0, 1);
589+ };
590+
591+ //// Atomize ////
592+
593+ var solid = function(color) { return function(line) { return function(ctx) {
594+ ctx.save();
595+ ctx.beginPath();
596+ ctx.translate(line.center[0], line.center[1]);
597+ ctx.rotate(line.theta);
598+ ctx.scale(line.scale, line.scale);
599+ var points = line.points;
600+ var i = points.length;
601+ ctx.moveTo(points[i-1][0], points[i-1][1]);
602+ while (i--) {
603+ ctx.lineTo(points[i][0], points[i][1]);
604+ }
605+ ctx.strokeStyle = Color.Internal.extract(color);
606+ ctx.stroke();
607+ ctx.restore();
608+ return ctx;
609+ };
610+ };
611+ };
612+
613+ var customLine = function(pattern) {
614+ return function(color) { return function(line) {
615+ if (typeof pattern[0] === "string") {
616+ var temp = [];
617+ while (pattern[0] === "Cons") {
618+ temp.push(pattern[1]);
619+ pattern = pattern[2];
620+ }
621+ pattern = temp;
622+ }
623+ if (pattern.length === 0) { pattern = [8,4]; }
624+ return function(ctx) {
625+ ctx.save();
626+ ctx.beginPath();
627+ ctx.translate(line.center[0], line.center[1]);
628+ ctx.rotate(line.theta);
629+ ctx.scale(line.scale, line.scale);
630+ customLineHelp(ctx, pattern, line.points);
631+ ctx.strokeStyle = Color.Internal.extract(color);
632+ ctx.stroke();
633+ ctx.restore();
634+ return ctx;
635+ };
636+ };
637+ };
638+ };
639+ var customLineHelp = function(ctx, pattern, points) {
640+ var i = points.length - 1;
641+ var x0 = points[i][0], y0 = points[i][1];
642+ var x1=0, y1=0, dx=0, dy=0, remaining=0, nx=0, ny=0;
643+ var pindex = 0, plen = pattern.length;
644+ var draw = true, segmentLength = pattern[0];
645+ ctx.moveTo(x0,y0);
646+ while (i--) {
647+ x1 = points[i][0]; y1 = points[i][1];
648+ dx = x1 - x0; dy = y1 - y0;
649+ remaining = Math.sqrt(dx * dx + dy * dy);
650+ while (segmentLength <= remaining) {
651+ x0 += dx * segmentLength / remaining;
652+ y0 += dy * segmentLength / remaining;
653+ ctx[draw ? 'lineTo' : 'moveTo'](x0, y0);
654+ // update starting position
655+ dx = x1 - x0; dy = y1 - y0;
656+ remaining = Math.sqrt(dx * dx + dy * dy);
657+ // update pattern
658+ draw = !draw;
659+ pindex = (pindex + 1) % plen;
660+ segmentLength = pattern[pindex];
661+ }
662+ if (remaining > 0) {
663+ ctx[draw ? 'lineTo' : 'moveTo'](x1, y1);
664+ segmentLength -= remaining;
665+ }
666+ x0 = x1; y0 = y1;
667+ }
668+ };
669+
670+ return {line:line, customLine:customLine, solid:solid,
671+ dashed: customLine([8,4]), dotted: customLine([3,3]) };
672+}();
673+
674+var Elm = function() {
675+ var input = function(base) {
676+ this.id = Guid.guid();
677+ this.value = base;
678+ this.step = function(eid,v) {
679+ var changed = eid === this.id;
680+ if (changed) { this.value = v; }
681+ return changed;
682+ };
683+ };
684+ var lift = function(func,args) {
685+ this.id = Guid.guid();
686+ this.value = null;
687+
688+ args.reverse();
689+ this.recalc = function() {
690+ var f = func;
691+ for (var i = args.length; i--; ) {
692+ f = f(args[i].value);
693+ }
694+ this.value = f;
695+ };
696+ this.recalc();
697+
698+ this.step = function(id,v) {
699+ if (this.hasOwnProperty(id)) return false;
700+ var changed = false;
701+ for (var i = args.length; i--; ) {
702+ // Must not short-circuit!
703+ // All arguments need to be steped forward!
704+ changed = args[i].step(id,v) || changed;
705+ }
706+ changed ? (this.recalc()) : (this[id] = true);
707+ return changed;
708+ };
709+ };
710+ var fold = function(func,base,input) {
711+ this.id = Guid.guid();
712+ this.value = base;
713+ this.step = function(id,v) {
714+ if (this.hasOwnProperty(id)) return false;
715+ var changed = input.step(id,v);
716+ if (changed) { this.value = func(input.value)(this.value); }
717+ else { this[id] = true; }
718+ return changed;
719+ };
720+ };
721+ return {Input: function(x) {return new input(x);},
722+ Lift: function(f,xs){return new lift(f,xs);},
723+ Fold: function(f,b,x){return new fold(f,b,x);}
724+ };
725+}();
726+
727+var Dispatcher = function() {
728+ var program = null;
729+ var correctSize = function(e) {
730+ var kids = e.childNodes;
731+ var len = kids.length;
732+ if (e.hasOwnProperty('isElmLeaf')) {
733+ var w = e.style.width === "" ?
734+ 0 : e.style.width.slice(0,-2) - 0;
735+ var h = e.style.height === "" ?
736+ 0 : e.style.height.slice(0,-2) - 0;
737+ return [w, h];
738+ }
739+ if (len === 1) {
740+ var dim = correctSize(kids[0]);
741+ if (e.style.width !== "") { dim[0] = e.style.width.slice(0,-2) - 0; }
742+ if (e.style.height !== "") { dim[1] = e.style.height.slice(0,-2) - 0; }
743+ if (dim[0] !== 0) { e.style.width = dim[0] + "px"; }
744+ if (dim[1] !== 0) { e.style.height = dim[1] + "px"; }
745+ return dim;
746+ }
747+ var wmax = 0, hmax = 0, wsum = 0, hsum = 0;
748+ var hasWidth = true, hasHeight = true, dim = null;
749+ while (len--) {
750+ dim = correctSize(kids[len]);
751+ wmax = Math.max(wmax, dim[0]);
752+ hmax = Math.max(hmax, dim[1]);
753+ wsum += dim[0];
754+ hsum += dim[1];
755+ hasWidth = hasWidth && dim[0] > 0;
756+ hasHeight = hasHeight && dim[1] > 0;
757+ }
758+ var w = wmax, h = hmax, dir = e.elmFlowDirection;
759+ if (dir === "X") { w = hasWidth ? wsum : 0; }
760+ if (dir === "Y") { h = hasHeight ? hsum : 0; }
761+ if (w > 0) e.style.width = w + "px";
762+ if (h > 0) e.style.height = h + "px";
763+ return [w,h];
764+ };
765+
766+ var initialize = function() {
767+ try { program = main(); } catch (e) {
768+ document.body.innerHTML = "An Error Occured: Better Messages to come.";
769+ throw e;
770+ }
771+ if (!program.hasOwnProperty('step')) {
772+ program = Elm.Input(program);
773+ }
774+ var content = document.getElementById('content');
775+ content.appendChild(program.value);
776+ correctSize(content);
777+ var w = document.getElementById('widthChecker').offsetWidth;
778+ if (w !== window.innerWidth) {
779+ Dispatcher.notify(Window.dimensions.id, Value.Tuple(w, window.innerHeight));
780+ }
781+ };
782+ var adjust = function() {
783+ var content = document.getElementById('content');
784+ correctSize(content);
785+ }
786+ var notify = function(id, v) {
787+ if (program.step(id,v)) {
788+ var content = document.getElementById('content');
789+ content.replaceChild(program.value, content.children[0]);
790+ correctSize(content);
791+ }
792+ };
793+ return {initialize:initialize, notify:notify, adjust:adjust};
794+}();
795+var Signal = function() {
796+ function toElmString(str) {
797+ var out = ["Nil"];
798+ for (var i = str.length; i--; ) {
799+ out = ["Cons", str[i], out];
800+ }
801+ return out;
802+ }
803+ var addListener = function() {
804+ if(document.addEventListener) {
805+ return function(element, event, handler) {
806+ element.addEventListener(event, handler, false);
807+ };
808+ }
809+ else {
810+ return function(element, event, handler) {
811+ element.attachEvent('on' + event, handler);
812+ };
813+ }
814+ }();
815+
816+ var Mouse = function() {
817+ var position = Elm.Input(Value.Tuple(0,0));
818+ var isDown = Elm.Input(false);
819+ var isClicked = Elm.Input(false);
820+
821+ function getXY(e) {
822+ var posx = 0;
823+ var posy = 0;
824+ if (!e) var e = window.event;
825+ if (e.pageX || e.pageY) {
826+ posx = e.pageX;
827+ posy = e.pageY;
828+ } else if (e.clientX || e.clientY) {
829+ posx = e.clientX + document.body.scrollLeft +
830+ document.documentElement.scrollLeft;
831+ posy = e.clientY + document.body.scrollTop +
832+ document.documentElement.scrollTop;
833+ }
834+ return Value.Tuple(posx, posy);
835+ }
836+
837+ addListener(document, 'click', function(e) {
838+ Dispatcher.notify(isClicked.id, true);
839+ Dispatcher.notify(isClicked.id, false);
840+ });
841+ addListener(document, 'mousedown', function(e) {
842+ Dispatcher.notify(isDown.id, true); });
843+ addListener(document, 'mouseup', function(e) {
844+ Dispatcher.notify(isDown.id, false); });
845+ addListener(document, 'mousemove', function(e) {
846+ Dispatcher.notify(position.id, getXY(e)); });
847+ var clickedOn = function(elem) {
848+ var click = Elm.Input(false);
849+ addListener(elem, 'click', function(e) {
850+ Dispatcher.notify(click.id, true);
851+ Dispatcher.notify(click.id, false);
852+ });
853+ return Value.Tuple(elem, click);
854+ };
855+ return {position: position,
856+ x: Elm.Lift(function(p){return p[1];},[position]),
857+ y: Elm.Lift(function(p){return p[2];},[position]),
858+ isClicked: isClicked,
859+ isDown: isDown,
860+ clickedOn: clickedOn
861+ };
862+ }();
863+
864+ var Time = function() {
865+ var every = function(t) {
866+ t *= 1000;
867+ var clock = Elm.Input(0);
868+ var time = 0;
869+ setInterval(function() {
870+ time += t;
871+ Dispatcher.notify(clock.id, time/1000);
872+ }, t);
873+ return clock;
874+ };
875+ var after = function(t) {
876+ t *= 1000;
877+ var thread = Elm.Input(false);
878+ setTimeout(function() { Dispatcher.notify(thread.id, true); }, t);
879+ return thread;
880+ };
881+ var before = function(t) {
882+ t *= 1000;
883+ var thread = Elm.Input(true);
884+ setTimeout(function() { Dispatcher.notify(thread.id, false); }, t);
885+ return thread;
886+ };
887+ return {every:every,after:after,before:before};
888+ }();
889+
890+ var Window = function() {
891+ var dimensions = Elm.Input(Value.Tuple(window.innerWidth,window.innerHeight));
892+ addListener(window, 'resize', function(e) {
893+ var w = document.getElementById('widthChecker').offsetWidth;
894+ Dispatcher.notify(dimensions.id, Value.Tuple(w, window.innerHeight));
895+ });
896+ return {dimensions:dimensions,
897+ width : Elm.Lift(function(p){return p[1];},[dimensions]),
898+ height: Elm.Lift(function(p){return p[2];},[dimensions]) };
899+ }();
900+
901+ var HTTP = function() {
902+ var fetch = function(how) { return function(url) {
903+ var thread = Elm.Input(["Waiting"]);
904+ var request = {};
905+ if (window.XMLHttpRequest) { request = new XMLHttpRequest(); }
906+ else if (window.ActiveXObject) { request = new ActiveXObject("Microsoft.XMLHTTP"); }
907+ request.onreadystatechange = function(e) {
908+ if (request.readyState === 4) {
909+ Dispatcher.notify(thread.id,
910+ request.status === 200
911+ ? ["Success", toElmString(request.responseText)]
912+ : ["Failure", request.status, toElmString(request.statusText)]);
913+ }
914+ };
915+ request.open(how, String.toText(url), true);
916+ request.send(null);
917+ return thread;
918+ };
919+ };
920+ var fetches = function(how) { return function(input) {
921+ var output = Elm.Input(["Nothing"]);
922+ var fetcher = Elm.Lift(update, [input]);
923+ var combine = Elm.Lift(function(x) { return function(y) { return x; } }, [output,fetcher]);
924+ function update(strOpt) {
925+ if (strOpt[0] !== "Just") {
926+ try { Dispatcher.notify(output.id, ["Nothing"]); } catch(e) {}
927+ return [];
928+ }
929+ try {
930+ Dispatcher.notify(output.id, ["Just", ["Waiting"]]);
931+ } catch(e) { output.value = ["Just", ["Waiting"]]; }
932+ var request = {};
933+ if (window.XMLHttpRequest) { request = new XMLHttpRequest(); }
934+ else if (window.ActiveXObject) { request = new ActiveXObject("Microsoft.XMLHTTP"); }
935+ request.onreadystatechange = function(e) {
936+ if (request.readyState === 4) {
937+ Dispatcher.notify(output.id,
938+ ["Just", request.status === 200
939+ ? ["Success", toElmString(request.responseText)]
940+ : ["Failure", request.status, toElmString(request.statusText)]]);
941+ }
942+ };
943+ request.open(how, String.toText(strOpt[1]), true);
944+ request.send(null);
945+ return [];
946+ }
947+ return combine;
948+ };
949+ };
950+ return {get : fetch("GET"), post : fetch("POST"),
951+ gets : fetches("GET"), posts : fetches("POST") };
952+ }();
953+ var Random = function() {
954+ var inRange = function(min) { return function(max) {
955+ return Elm.Input(Math.floor(Math.random() * (max-min+1)) + min);
956+ };
957+ };
958+ var randomize = function(min) { return function(max) { return function(signal) {
959+ return Elm.Lift(function(x) { return Math.floor(Math.random() * (max-min+1)) + min;},[signal]);
960+ };
961+ };
962+ };
963+ return { inRange:inRange, randomize:randomize };
964+ }();
965+ var Input = function() {
966+ var newTextInput = function(elem, ghostText) {
967+ elem.isElmLeaf = true;
968+ var str = Elm.Input(["Nil"]);
969+ addListener(elem, 'keyup', function(e) {
970+ Dispatcher.notify(str.id, toElmString(elem.value));
971+ elem.focus();
972+ });
973+ return Value.Tuple(elem, str);
974+ };
975+ var newElement = function(name) {
976+ var e = document.createElement(name);
977+ e.id = Guid.guid();
978+ return e;
979+ };
980+ var textArea = function(cols) { return function(rows) {
981+ var textarea = newElement('textarea');
982+ textarea.rows = rows;
983+ textarea.cols = cols;
984+ return newTextInput(textarea, "");
985+ };
986+ };
987+ var textField = function(ghostText) {
988+ var field = newElement('input');
989+ field.type = 'text';
990+ return newTextInput(field, ghostText);
991+ };
992+ var password = function(ghostText) {
993+ var field = newElement('input');
994+ field.type = 'password';
995+ return newTextInput(field, ghostText);
996+ };
997+ var checkbox = function(checked) {
998+ var box = newElement('input');
999+ box.type = 'checkbox';
1000+ box.checked = checked;
1001+ var status = Elm.Input(checked);
1002+ addListener(box, 'change', function(e) {
1003+ Dispatcher.notify(status.id, box.checked);
1004+ });
1005+ return Value.Tuple(box, status);
1006+ };
1007+ var dropDown = function(options) {
1008+ var slct = newElement('select');
1009+ var opts = [];
1010+ while (options[0] === "Cons") {
1011+ var opt = newElement('option');
1012+ var str = Text.toText(options[1][1]);
1013+ opt.value = str;
1014+ opt.innerHTML = str;
1015+ slct.appendChild(opt);
1016+ opts.push(options[1][2]);
1017+ options = options[2];
1018+ }
1019+ var status = Elm.Input(opts[0]);
1020+ addListener(slct, 'change', function(e) {
1021+ Dispatcher.notify(status.id, opts[slct.selectedIndex]);
1022+ });
1023+ return Value.Tuple(slct, status);
1024+ };
1025+ var stringDropDown = function(opts) {
1026+ return dropDown(List.map (function(x) {return Value.Tuple(x,x);}) (opts));
1027+ };
1028+ var button = function(name) {
1029+ var b = newElement('input');
1030+ b.type = "button";
1031+ b.value = Text.toText(name);
1032+ var press = Elm.Input(false);
1033+ addListener(b, 'click', function(e) {
1034+ Dispatcher.notify(press.id, true);
1035+ Dispatcher.notify(press.id, false);
1036+ });
1037+ return Value.Tuple(b,press);
1038+ };
1039+ return {textArea:textArea, textField:textField,
1040+ password:password, checkbox:checkbox,
1041+ dropDown:dropDown, stringDropDown:stringDropDown,
1042+ button:button};
1043+ }();
1044+
1045+ return {Mouse:Mouse, Time:Time, Window:Window,
1046+ HTTP:HTTP, Random:Random, Input:Input };
1047+}();var List = function() {
1048+
1049+ var throwError = function() { throw "Function expecting a list!"; }
1050+
1051+ function length(xs) {
1052+ var out = 0;
1053+ while (xs[0] === "Cons") {
1054+ out += 1;
1055+ xs = xs[2];
1056+ }
1057+ return out;
1058+ };
1059+ var reverse = foldl(function(x_72) {
1060+ return function(y_73) {
1061+ return["Cons", x_72, y_73]
1062+ }
1063+ })(["Nil"]);
1064+ var concat = foldr(function(x_74) {
1065+ return function(y_75) {
1066+ return Value.append(x_74, y_75)
1067+ }
1068+ })(["Nil"]);
1069+ var and = foldl(function(x_77) {
1070+ return function(y_78) {
1071+ return x_77 && y_78
1072+ }
1073+ })(true);
1074+ var or = foldl(function(x_79) {
1075+ return function(y_80) {
1076+ return x_79 || y_80
1077+ }
1078+ })(false);
1079+ var sum = foldl(function(x_89) {
1080+ return function(y_90) {
1081+ return x_89 + y_90
1082+ }
1083+ })(0);
1084+ var product = foldl(function(x_91) {
1085+ return function(y_92) {
1086+ return x_91 * y_92
1087+ }
1088+ })(1);
1089+ var maximum = foldl1(function(x) { return function(y) { return Math.max(x,y) } });
1090+ var minimum = foldl1(function(x) { return function(y) { return Math.min(x,y) } });
1091+ function head(v) {
1092+ if (v[0] !== "Cons") {
1093+ throw "Error: 'head' only accepts lists of length greater than one.";
1094+ }
1095+ return v[1];
1096+ }
1097+ function tail(v) {
1098+ if (v[0] !== "Cons") {
1099+ throw "Error: 'tail' only accepts lists of length greater than one.";
1100+ }
1101+ return v[2];
1102+ }
1103+ function map(f) {
1104+ return function(xs) {
1105+ if (xs[0] === "Nil") { return xs; }
1106+ if (xs[0] !== "Cons") { throwError(); }
1107+ var root = ["Cons", f(xs[1]), ["Nil"]];
1108+ var curr = root;
1109+ xs = xs[2];
1110+ while (xs[0]==="Cons") {
1111+ curr[2] = ["Cons", f(xs[1]), ["Nil"]];
1112+ xs = xs[2];
1113+ curr = curr[2];
1114+ }
1115+ return root;
1116+ }
1117+ }
1118+ function foldl(f) {
1119+ return function(b) {
1120+ return function(xs) {
1121+ var acc = b;
1122+ if (xs[0] === "Nil") { return acc; }
1123+ if (xs[0] !== "Cons") { throwError(); }
1124+ while (xs[0] === "Cons") {
1125+ acc = f(xs[1])(acc);
1126+ xs = xs[2];
1127+ }
1128+ return acc;
1129+ }
1130+ }
1131+ }
1132+ function foldr(f) {
1133+ return function(b) {
1134+ return function(xs) {
1135+ var acc = b;
1136+ if (xs[0] === "Nil") { return acc; }
1137+ if (xs[0] !== "Cons") { throwError(); }
1138+ var arr = [];
1139+ while (xs[0] === "Cons") {
1140+ arr.push(xs[1]);
1141+ xs = xs[2];
1142+ }
1143+ for (var i = arr.length; i--; ) {
1144+ acc = f(arr[i])(acc);
1145+ }
1146+ return acc;
1147+ }
1148+ }
1149+ }
1150+ function foldl1(f_49) {
1151+ return function(_temp_50) {
1152+ return function(v) {
1153+ if("Cons" !== v[0]) {
1154+ return undefined
1155+ }else {
1156+ var x_51 = v[1];
1157+ var xs_52 = v[2];
1158+ return foldl(f_49)(x_51)(xs_52)
1159+ }
1160+ }(_temp_50)
1161+ }
1162+ }
1163+ function foldr1(f_53) {
1164+ return function(_temp_54) {
1165+ return function(v) {
1166+ if("Cons" !== v[0]) {
1167+ return undefined
1168+ }else {
1169+ var x_55 = v[1];
1170+ var xs_56 = v[2];
1171+ return foldr(f_53)(x_55)(xs_56)
1172+ }
1173+ }(_temp_54)
1174+ }
1175+ }
1176+ function scanl(f) {
1177+ return function(b) {
1178+ return function(xs) {
1179+ if (xs[0] === "Nil") { return ["Cons",b,["Nil"]]; }
1180+ if (xs[0] !== "Cons") { throwError(); }
1181+ var arr = [b];
1182+ while (xs[0] === "Cons") {
1183+ b = f(xs[1])(b);
1184+ arr.push(b);
1185+ xs = xs[2];
1186+ }
1187+ var out = ["Nil"];
1188+ for (var i = arr.length; i--; ) {
1189+ out = ["Cons", arr[i], out];
1190+ }
1191+ return out;
1192+ }
1193+ }
1194+ }
1195+ function scanl1(f) {
1196+ return function(xs) {
1197+ if (xs[0] !== "Cons") {
1198+ throw "Error: 'scanl1' requires a list of at least length 1.";
1199+ }
1200+ return scanl(f)(xs[1])(xs[2]);
1201+ }
1202+ }
1203+ function filter(pred) {
1204+ return function(xs) {
1205+ if (xs[0] === "Nil") { return xs; }
1206+ if (xs[0] !== "Cons") { throwError(); }
1207+ var arr = [];
1208+ while (xs[0] === "Cons") {
1209+ if (pred(xs[1])) { arr.push(xs[1]); }
1210+ xs = xs[2];
1211+ }
1212+ var out = ["Nil"];
1213+ for (var i = arr.length; i--; ) {
1214+ out = ["Cons", arr[i], out];
1215+ }
1216+ return out;
1217+ }
1218+ }
1219+ function concatMap(f_76) {
1220+ return function(x) {
1221+ return concat(map(f_76)(x))
1222+ }
1223+ }
1224+ function forall(pred) {
1225+ return foldl(function(x) { return function(acc) {
1226+ return acc && pred(x);
1227+ };})(true);
1228+ }
1229+ function exists(pred) {
1230+ return foldl(function(x) { return function(acc) {
1231+ return acc || pred(x);
1232+ };})(false);
1233+ }
1234+ function partition(pred_93) {
1235+ return function(lst_94) {
1236+ return function() {
1237+ var v = lst_94;
1238+ var c = [function(v) {
1239+ if("Nil" !== v[0]) {
1240+ return undefined
1241+ }else {
1242+ return["Tuple2", ["Nil"], ["Nil"]]
1243+ }
1244+ }, function(v) {
1245+ if("Cons" !== v[0]) {
1246+ return undefined
1247+ }else {
1248+ var x_95 = v[1];
1249+ var xs_96 = v[2];
1250+ return function(v) {
1251+ if("Tuple2" !== v[0]) {
1252+ return undefined
1253+ }else {
1254+ var as_97 = v[1];
1255+ var bs_98 = v[2];
1256+ return pred_93(x_95) ? ["Tuple2", ["Cons", x_95, as_97], bs_98] : ["Tuple2", as_97, ["Cons", x_95, bs_98]]
1257+ }
1258+ }(partition(pred_93)(xs_96))
1259+ }
1260+ }];
1261+ for(var i = c.length;i--;) {
1262+ var r = c[i](v);
1263+ if(r !== undefined) {
1264+ return r
1265+ }
1266+ }
1267+ }()
1268+ }
1269+ }
1270+ function zipWith(f) {
1271+ return function(listA) {
1272+ return function(listB) {
1273+ if (listA[0] === "Nil" || listB[0] === "Nil") { return listA; }
1274+ if (listA[0] !== "Cons" || listB[0] !== "Cons") { throwError(); }
1275+ var arr = [];
1276+ while (listA[0] === "Cons" && listB[0] === "Cons") {
1277+ arr.push(f(listA[1])(listB[1]));
1278+ listA = listA[2];
1279+ listB = listB[2];
1280+ }
1281+ var out = ["Nil"];
1282+ for (var i = arr.length; i--; ) {
1283+ out = ["Cons", arr[i], out];
1284+ }
1285+ return out;
1286+ }
1287+ }
1288+ }
1289+ function zip(listA) {
1290+ return function(listB) {
1291+ if (listA[0] === "Nil" || listB[0] === "Nil") { return listA; }
1292+ if (listA[0] !== "Cons" || listB[0] !== "Cons") { throwError(); }
1293+ var arr = [];
1294+ while (listA[0] === "Cons" && listB[0] === "Cons") {
1295+ arr.push(["Tuple2", listA[1], listB[1]]);
1296+ listA = listA[2];
1297+ listB = listB[2];
1298+ }
1299+ var out = ["Nil"];
1300+ for (var i = arr.length; i--; ) {
1301+ out = ["Cons", arr[i], out];
1302+ }
1303+ return out;
1304+ }
1305+ }
1306+ function unzip(pairs_112) {
1307+ return function() {
1308+ var v = pairs_112;
1309+ var c = [function(v) {
1310+ if("Nil" !== v[0]) {
1311+ return undefined
1312+ }else {
1313+ return["Tuple2", ["Nil"], ["Nil"]]
1314+ }
1315+ }, function(v) {
1316+ if("Cons" !== v[0]) {
1317+ return undefined
1318+ }else {
1319+ var p_113 = v[1];
1320+ var ps_114 = v[2];
1321+ return function(v) {
1322+ if("Tuple2" !== v[0]) {
1323+ return undefined
1324+ }else {
1325+ if("Tuple2" !== v[1][0]) {
1326+ return undefined
1327+ }else {
1328+ var x_115 = v[1][1];
1329+ var y_116 = v[1][2];
1330+ if("Tuple2" !== v[2][0]) {
1331+ return undefined
1332+ }else {
1333+ var xs_117 = v[2][1];
1334+ var ys_118 = v[2][2];
1335+ return["Tuple2", ["Cons", x_115, xs_117], ["Cons", y_116, ys_118]]
1336+ }
1337+ }
1338+ }
1339+ }(["Tuple2", p_113, unzip(ps_114)])
1340+ }
1341+ }];
1342+ for(var i = c.length;i--;) {
1343+ var r = c[i](v);
1344+ if(r !== undefined) {
1345+ return r
1346+ }
1347+ }
1348+ }()
1349+ }
1350+ function intersperse(sep_119) {
1351+ return function(xs_120) {
1352+ return function() {
1353+ var v = xs_120;
1354+ var c = [function(v) {
1355+ if("Nil" !== v[0]) {
1356+ return undefined
1357+ }else {
1358+ return["Nil"]
1359+ }
1360+ }, function(v) {
1361+ if("Cons" !== v[0]) {
1362+ return undefined
1363+ }else {
1364+ var a_124 = v[1];
1365+ if("Nil" !== v[2][0]) {
1366+ return undefined
1367+ }else {
1368+ return["Cons", a_124, ["Nil"]]
1369+ }
1370+ }
1371+ }, function(v) {
1372+ if("Cons" !== v[0]) {
1373+ return undefined
1374+ }else {
1375+ var a_121 = v[1];
1376+ if("Cons" !== v[2][0]) {
1377+ return undefined
1378+ }else {
1379+ var b_122 = v[2][1];
1380+ var cs_123 = v[2][2];
1381+ return["Cons", a_121, ["Cons", sep_119, intersperse(sep_119)(["Cons", b_122, cs_123])]]
1382+ }
1383+ }
1384+ }];
1385+ for(var i = c.length;i--;) {
1386+ var r = c[i](v);
1387+ if(r !== undefined) {
1388+ return r
1389+ }
1390+ }
1391+ }()
1392+ }
1393+ }
1394+ function intercalate(sep_125) {
1395+ return function(xs_126) {
1396+ return function() {
1397+ var v = xs_126;
1398+ var c = [function(v) {
1399+ if("Nil" !== v[0]) {
1400+ return undefined
1401+ }else {
1402+ return["Nil"]
1403+ }
1404+ }, function(v) {
1405+ if("Cons" !== v[0]) {
1406+ return undefined
1407+ }else {
1408+ var a_130 = v[1];
1409+ if("Nil" !== v[2][0]) {
1410+ return undefined
1411+ }else {
1412+ return a_130
1413+ }
1414+ }
1415+ }, function(v) {
1416+ if("Cons" !== v[0]) {
1417+ return undefined
1418+ }else {
1419+ var a_127 = v[1];
1420+ if("Cons" !== v[2][0]) {
1421+ return undefined
1422+ }else {
1423+ var b_128 = v[2][1];
1424+ var cs_129 = v[2][2];
1425+ return Value.append(a_127, Value.append(sep_125, intercalate(sep_125)(["Cons", b_128, cs_129])))
1426+ }
1427+ }
1428+ }];
1429+ for(var i = c.length;i--;) {
1430+ var r = c[i](v);
1431+ if(r !== undefined) {
1432+ return r
1433+ }
1434+ }
1435+ }()
1436+ }
1437+ }
1438+ function sort(xs) {
1439+ if (xs[0] === "Nil") { return xs; }
1440+ if (xs[0] !== "Cons") { throwError(); }
1441+ var arr = [];
1442+ while (xs[0] === "Cons") {
1443+ arr.push(xs[1]);
1444+ xs = xs[2];
1445+ }
1446+ arr.sort(function(a,b) { return a - b});
1447+ var out = ["Nil"];
1448+ for (var i = arr.length; i--; ) {
1449+ out = [ "Cons", arr[i], out ];
1450+ }
1451+ return out;
1452+ }
1453+ return {head:head,
1454+ tail:tail,
1455+ map:map,
1456+ foldl:foldl,
1457+ foldr:foldr,
1458+ foldl1:foldl1,
1459+ foldr1:foldr1,
1460+ scanl:scanl,
1461+ scanl1:scanl1,
1462+ filter:filter,
1463+ length:length,
1464+ reverse:reverse,
1465+ concat:concat,
1466+ concatMap:concatMap,
1467+ and:and,
1468+ or:or,
1469+ forall:forall,
1470+ exists:exists,
1471+ sum:sum,
1472+ product:product,
1473+ maximum:maximum,
1474+ minimum:minimum,
1475+ partition:partition,
1476+ zipWith:zipWith,
1477+ zip:zip,
1478+ unzip:unzip,
1479+ intersperse:intersperse,
1480+ intercalate:intercalate,
1481+ sort:sort};
1482+}();
1483+var id = function(x) { return x; };
1484+var not = function(exp) { return !exp; };
1485+
1486+var sqrt = function(x) { return Math.sqrt(x); };
1487+var rem = function(x) { return function(y) { return x % y; }; };
1488+var mod = function(x) { return function(y) {
1489+ var r = x % y;
1490+ var m = x==0 ? 0 : (y>0 ? (x>=0 ? r : r+y) : -mod(-x)(-y));
1491+ return m == y ? 0 : m;
1492+}; };
1493+var abs = function(x) { return Math.abs(x); };
1494+var logBase = function(base) { return function(x) { return Math.log(x) / Math.log(base); }; };
1495+
1496+var min = function(x) { return function(y) { return Math.min(x,y); }; };
1497+var max = function(x) { return function(y) { return Math.max(x,y); }; };
1498+var clamp = function(lo) { return function(hi) {
1499+ return function(x) { return Math.min(hi, Math.max(lo, x)); };
1500+ };
1501+};
1502+
1503+var sin = Math.sin, cos = Math.cos, tan = Math.tan;
1504+var asin = Math.asin, acos = Math.acos, atan = Math.atan;
1505+
1506+var flip = function(f){return function(x){return function(y){return f(y)(x);};};};
1507+
1508+var Just = function(x) { return ["Just",x]; };
1509+var Nothing = ["Nothing"];
1510+
1511+function constant(v) { return Elm.Input(v); }
1512+function lift(f) { return function(e) { return Elm.Lift(f, [e]); }; }
1513+function lift2(f) { return function(e1) { return function(e2) {
1514+ return Elm.Lift(f, [e1,e2]); }; }; }
1515+function lift3(f) { return function(e1) { return function(e2) {
1516+ return function(e3) { return Elm.Lift(f, [e1,e2,e3]); }; }; }; }
1517+function lift4(f) { return function(e1) { return function(e2) {
1518+ return function(e3) { return function(e4) {
1519+ return Elm.Lift(f, [e1,e2,e3,e4]); }; }; }; }; }
1520+function foldp(f) { return function(b) { return function(e) {
1521+ return Elm.Fold(f,b,e); }; }; }
1522+
1523+
1524+var includeGlobal = this;
1525+(function() {
1526+ var include = function(library) {
1527+ for (var i in library) {
1528+ if (i === 'Internal') continue;
1529+ try {
1530+ includeGlobal[i] = library[i];
1531+ } catch (err) {
1532+ if (i === 'length') {
1533+ includeGlobal.execScript('var length;');
1534+ length = library[i];
1535+ continue;
1536+ }
1537+ }
1538+ }
1539+ };
1540+ var includeAs = function(name) { return function(library) {
1541+ includeGlobal[name] = includeGlobal[name] || {};
1542+ for (var i in library) {
1543+ if (i === 'Internal') continue;
1544+ includeGlobal[name][i] = library[i];
1545+ }
1546+ };
1547+ };
1548+ include (Element);
1549+ include (Text);
1550+
1551+ color = Element.color;
1552+ height = Element.height;
1553+ show = Value.show;
1554+
1555+ includeAs ('Time') (Signal.Time);
1556+ includeAs ('Mouse') (Signal.Mouse);
1557+ includeAs ('Window') (Signal.Window);
1558+ includeAs ('HTTP') (Signal.HTTP);
1559+ includeAs ('Input') (Signal.Input);
1560+ includeAs ('Random') (Signal.Random);
1561+
1562+ include (Color);
1563+ include (Shape);
1564+ include (Line);
1565+}());
src/CompileToJS.hs+3
@@ -34,6 +34,9 @@ toJS expr =
3434 Binop op e1 e2 -> binop op (toJS e1) (toJS e2)
3535 If eb et ef -> parens $ iff (toJS eb) (toJS et) (toJS ef)
3636 Lambda v e -> jsFunc v $ ret (toJS e)
37+ App (Var "toText") (Str s) -> show s
38+ App (Var "link") (Str s) -> "link(" ++ show s ++ ")"
39+ App (Var "plainText") (Str s) -> "plainText(" ++ show s ++ ")"
3740 App e1 e2 -> toJS e1 ++ parens (toJS e2)
3841 Let defs e -> jsLet defs e
3942 Case e cases -> jsCase e cases
src/Initialize.hs+108−163
@@ -1,164 +1,109 @@
1−module Initialize (initialize) where
2−
3−import Ast
4−import Control.Arrow (first)
5−import Control.Monad
6−import Data.Char (isAlpha)
7−import Data.Maybe (mapMaybe)
8−import Data.Either (rights)
9−import FreeVar
10−import Lexer
11−import Parser (toExpr,toDefs)
12−import Rename (rename)
13−import Replace
14−
15−import Unify
16−import Hints
17−
18−initialize str = do
19− (expr, hints') <- toDefs =<< tokenize str
20− let expr' = rename expr
21− subs <- unify (liftM2 (++) hints hints') expr'
22− return (seq subs expr')
23−
24−{--
25−initialize' str = do
26− expr <- toDefs =<< tokenize str
27−-- let rexpr = rename expr
28−-- let init = simp_loop rexpr
29−-- return $ if depth init < depth rexpr then init else rexpr
30− return $ rename expr
31−--}
32−{--
33−simp_loop exp = if exp == exp' then exp' else simp_loop exp'
34− where exp' = simp exp
35−
36−simp expr =
37− let f = simp in
38− case expr of
39− Range e1 e2 -> simp_range (f e1) (f e2)
40− Binop op e1 e2 -> simp_binop op (f e1) (f e2)
41− Lambda x e -> Lambda x (f e)
42− App e1 e2 -> simp_app (f e1) (f e2)
43− If e1 e2 e3 -> simp_if (f e1) (f e2) (f e3)
44− Lift e es -> Lift (f e) $ map f es
45− Fold e1 e2 e3 -> Fold (f e1) (f e2) (f e3)
46− Async e -> Async (f e)
47− Let x e1 e2 -> simp_let x (f e1) (f e2)
48− Data name es -> Data name (map f es)
49− Case e cases -> simp_case (f e) cases
50− _ -> expr
51−
52−data Status = NoMatch | Quit deriving (Show,Eq)
53−
54−simp_case v cases =
55− case v of
56− Data _ _ -> case rights $ map (\(p,e) -> match p v e) cases of
57− { v:_ -> v; _ -> Case v cases }
58− _ -> Case v cases
59−
60−match p v hole =
61− case p of PAnything -> return hole
62− PVar x -> return $ Let x v hole
63− PData pn ps ->
64− case v of
65− Data vn vs -> if pn /= vn then Left NoMatch else
66− foldM (flip ($)) hole (zipWith match ps vs)
67− _ -> Left Quit
68−
69−simp_let x e1 e2
70− | not (x `freeIn` e2) = e2
71− | isValue e1 = Let x e1 (replace x e1 e2)
72− | otherwise = Let x e1 e2
73−
74−simp_app e1 e2 =
75− case e1 of
76− Let x s e -> if x `freeIn` e2 then error "Overlapping names!" else
77− Let x s (App e e2)
78− Lambda x e -> Let x e2 e
79−{--
80− Var "constant" -> App (Lambda "v" (Lift (Var "v") [])) e2
81− Var "async" -> Async e2
82− Var "foldp" -> Lambda "b" . Lambda "s" $ (Fold e2 (Var "b") (Var "s"))
83− Var "lift" -> Lambda "s" (Lift e2 [Var "s"])
84− Var "lift2" -> Lambda "s1" . Lambda "s2" $ (Lift e2 [Var "s1",Var "s2"])
85−--}
86− _ -> App e1 e2
87−
88−simp_if (Boolean b) e2 e3 = if b then e2 else e3
89−simp_if a b c = If a b c
90−
91−isValue expr =
92− case expr of
93− Number _ -> True
94− Chr _ -> True
95− Boolean _ -> True
96− Range _ _ -> True
97− Lambda _ _ -> True
98− Data _ _ -> True
99− Var _ -> True
100− _ -> False
101−
102−simp_range lo hi = toAST (parse code)
103− where toAST = either (error "Compilation Failure") (\f -> App (App f lo) hi)
104− parse str = toExpr =<< tokenize str
105− code = "let range xs lo hi = \
106− \if hi < lo then xs else range (hi:xs) lo (hi-1) in\
107− \ \\x y -> range [] x y"
108−
109−simp_binop "mod" (Number n) (Number m) = Number (mod n m)
110−simp_binop "mod" e1 e2 = Binop "mod" e1 e2
111−simp_binop str e1 e2
112− | isAlpha (head str) || '_' == head str =
113− App (App (Var str) e1) e2
114− | otherwise = binop str e1 e2
115−
116−binop op (Number n) (Number m) = f n m
117− where f a b = case op of
118− { "+" -> Number $ (+) a b
119− ; "-" -> Number $ (-) a b
120− ; "*" -> Number $ (*) a b
121− --; "/" -> Number $ div a b
122− ; "<" -> Boolean $ a < b
123− ; ">" -> Boolean $ a < b
124− ; "<=" -> Boolean $ a <= b
125− ; ">=" -> Boolean $ a >= b
126− ; "==" -> Boolean $ a == b
127− ; "/=" -> Boolean $ a /= b
128− ; _ -> Binop op (Number n) (Number m) }
129−
130−binop "-" e (Number 0) = e
131−binop "+" (Number 0) e = e
132−binop "+" (Number n) (Binop "+" (Number m) e) = binop "+" (Number (n+m)) e
133−binop "+" (Number n) (Binop "+" e (Number m)) = binop "+" (Number (n+m)) e
134−
135−binop "/" e (Number 1) = e
136−binop "*" (Number 0) e = Number 0
137−binop "*" (Number 1) e = e
138−binop "*" (Number n) (Binop "*" (Number m) e) = binop "*" (Number (n*m)) e
139−binop "*" (Number n) (Binop "*" e (Number m)) = binop "*" (Number (n*m)) e
140−
141−binop "+" e (Number n) = binop "+" (Number n) e
142−binop "*" e (Number n) = binop "*" (Number n) e
143−
144−binop op (Boolean n) (Boolean m) = f n m
145− where f a b = case op of { "&&" -> Boolean $ (&&) n m
146− ; "||" -> Boolean $ (||) n m
147− ; _ -> Binop op (Boolean n) (Boolean m) }
148−
149−binop "&&" (Boolean True) e = e
150−binop "&&" (Boolean False) e = Boolean False
151−binop "||" (Boolean True) e = Boolean True
152−binop "||" (Boolean False) e = e
153−
154−binop op e (Boolean n) = binop op (Boolean n) e
155−
156−binop ":" h t = cons h t
157−binop "++" (Data "Nil" []) e = e
158−binop "++" e (Data "Nil" []) = e
159−binop "++" (Data "Cons" [h,t]) e = Data "Cons" [h, binop "++" t e]
160−
161−binop "$" e1 e2 = App e1 e2
162−
163−binop op e1 e2 = Binop op e1 e2
1+module Initialize (initialize) where
2+
3+import Ast
4+import Control.Arrow (first, second)
5+import Control.Monad
6+import Data.Char (isAlpha)
7+import Data.Maybe (mapMaybe)
8+import Data.Either (rights)
9+import FreeVar
10+import Lexer
11+import Parser (toExpr,toDefs)
12+import Rename (rename)
13+import Replace
14+
15+import Unify
16+import Hints
17+
18+{--
19+initialize str = do
20+ (expr, hints') <- toDefs =<< tokenize str
21+ let expr' = rename expr
22+ subs <- unify (liftM2 (++) hints hints') expr'
23+ return (seq subs expr')
24+--}
25+
26+initialize str = do
27+ (expr, hints') <- toDefs =<< tokenize str
28+ let expr' = rename expr
29+ subs <- unify (liftM2 (++) hints hints') expr'
30+ let init = simp_loop expr'
31+ return (seq subs init)
32+
33+simp_loop exp = if exp == exp' then exp' else simp_loop exp'
34+ where exp' = simp exp
35+
36+simp expr =
37+ let f = simp in
38+ case expr of
39+ Range e1 e2 -> Range (f e1) (f e2)
40+ Binop op e1 e2 -> simp_binop op (f e1) (f e2)
41+ Lambda x e -> Lambda x (f e)
42+ App e1 e2 -> App (f e1) (f e2)
43+ If e1 e2 e3 -> simp_if (f e1) (f e2) (f e3)
44+ Let defs e -> Let (map (second f) defs) (f e)
45+ Data name es -> Data name (map f es)
46+ Case e cases -> Case (f e) (map (second f) cases)
47+ _ -> expr
48+
49+simp_if (Boolean b) e2 e3 = if b then e2 else e3
50+simp_if a b c = If a b c
51+
52+simp_binop "mod" (Number n) (Number m) = Number (mod n m)
53+simp_binop "mod" e1 e2 = Binop "mod" e1 e2
54+simp_binop str e1 e2
55+ | isAlpha (head str) || '_' == head str = App (App (Var str) e1) e2
56+ | otherwise = binop str e1 e2
57+
58+binop op (Number n) (Number m) = f n m
59+ where f a b = case op of
60+ { "+" -> Number $ (+) a b
61+ ; "-" -> Number $ (-) a b
62+ ; "*" -> Number $ (*) a b
63+ --; "/" -> Number $ div a b
64+ ; "<" -> Boolean $ a < b
65+ ; ">" -> Boolean $ a < b
66+ ; "<=" -> Boolean $ a <= b
67+ ; ">=" -> Boolean $ a >= b
68+ ; "==" -> Boolean $ a == b
69+ ; "/=" -> Boolean $ a /= b
70+ ; _ -> Binop op (Number n) (Number m) }
71+
72+binop "-" e (Number 0) = e
73+binop "+" (Number 0) e = e
74+binop "+" (Number n) (Binop "+" (Number m) e) = binop "+" (Number (n+m)) e
75+binop "+" (Number n) (Binop "+" e (Number m)) = binop "+" (Number (n+m)) e
76+
77+binop "/" e (Number 1) = e
78+binop "*" (Number 0) e = Number 0
79+binop "*" (Number 1) e = e
80+binop "*" (Number n) (Binop "*" (Number m) e) = binop "*" (Number (n*m)) e
81+binop "*" (Number n) (Binop "*" e (Number m)) = binop "*" (Number (n*m)) e
82+
83+binop "+" e (Number n) = binop "+" (Number n) e
84+binop "*" e (Number n) = binop "*" (Number n) e
85+
86+binop op (Boolean n) (Boolean m) = f n m
87+ where f a b = case op of { "&&" -> Boolean $ (&&) n m
88+ ; "||" -> Boolean $ (||) n m
89+ ; _ -> Binop op (Boolean n) (Boolean m) }
90+
91+binop "&&" (Boolean True) e = e
92+binop "&&" (Boolean False) e = Boolean False
93+binop "||" (Boolean True) e = Boolean True
94+binop "||" (Boolean False) e = e
95+
96+binop op e (Boolean n) = binop op (Boolean n) e
97+
98+binop ":" h t = cons h t
99+binop "++" (Str s1) (Str s2) = Str $ s1 ++ s2
100+binop "++" (Str s1) (Binop "++" (Str s2) e) = Binop "++" (Str $ s1 ++ s2) e
101+binop "++" (Binop "++" e (Str s1)) (Str s2) = Binop "++" e (Str $ s1 ++ s2)
102+binop "++" (Data "Nil" []) e = e
103+binop "++" e (Data "Nil" []) = e
104+binop "++" (Data "Cons" [h,t]) e = Data "Cons" [h, binop "++" t e]
105+
106+binop "$" e1 e2 = App e1 e2
107+
108+binop op e1 e2 = Binop op e1 e2
164109--}