Closed fasterthanlime closed 9 years ago
Original cljs code:
(loop [i 0
j 0]
(when (< i 10)
(prn "i = " i)
(recur (inc i) j)))
Recent commits made Shin's output go from:
(function () {
var $$__i1 = 0;
var $$__j2 = 0;
var recur = null;
var $$__loopret3 = null;
while (true) {
if ($s.call(null, $$__i1, 10)) {
prn.call(null, 'i = ', $$__i1);
$$__loopret3 = recur = [
inc.call(null, $$__i1),
$$__j2
];
} else {
}
if (recur) {
$$__i1 = recur[0];
$$__j2 = recur[1];
recur = null;
continue;
} else {
}
break;
}
return $$__loopret3;
}());
to
{
var $$__i1 = 0;
var $$__j2 = 0;
var recur = null;
while (true) {
if ($s.call(null, $$__i1, 10)) {
prn.call(null, 'i = ', $$__i1);
recur = [
inc.call(null, $$__i1),
$$__j2
];
} else {
}
if (recur) {
$$__i1 = recur[0];
$$__j2 = recur[1];
recur = null;
continue;
} else {
}
break;
}
}
So we lost the (useless) outer anon-func, but we're still getting funky with the recur array so far.
{
var $$__i1 = 0;
var $$__j2 = 0;
var $$__recur_sentinel3 = true;
while ($$__recur_sentinel3) {
$$__recur_sentinel3 = false;
if ($s.call(null, $$__i1, 10)) {
prn.call(null, 'i = ', $$__i1);
{
var $$__$$__G__45 = inc.call(null, $$__i1);
var $$__$$__G__67 = $$__j2;
$$__i1 = $$__$$__G__45;
$$__j2 = $$__$$__G__67;
$$__recur_sentinel3 = true;
}
}
}
}
var i_7994 = 0;
var j_7995 = 0;
while (true) {
if ((i_7994 < 10)) {
cljs.core.prn.call(null, "i = ", i_7994); {
var G__7996 = (i_7994 + 1);
var G__7997 = j_7995;
i_7994 = G__7996;
j_7995 = G__7997;
continue;
}
} else {}
break;
}
I'm keeping the BlockStatement around the loop. I just think it's nicer to read, and I don't believe they incur a significant performance difference.
With #47 closed, we now have:
{
var $$__i1 = 0;
var $$__j2 = 0;
var $$__recur_sentinel3 = true;
while ($$__recur_sentinel3) {
$$__recur_sentinel3 = false;
if ($$__i1 < 10) {
prn.call(null, 'i = ', $$__i1);
{
var $$__$$__G__45 = inc.call(null, $$__i1);
var $$__$$__G__67 = $$__j2;
$$__i1 = $$__$$__G__45;
$$__j2 = $$__$$__G__67;
$$__recur_sentinel3 = true;
}
}
}
}
Which is pretty much as good as it gets :) vs mainline cljs:
var i_7994 = 0;
var j_7995 = 0;
while (true) {
if ((i_7994 < 10)) {
cljs.core.prn.call(null, "i = ", i_7994);
{
var G__7996 = (i_7994 + 1);
var G__7997 = j_7995;
i_7994 = G__7996;
j_7995 = G__7997;
continue;
}
} else {}
break;
}
Note: the reason we're using a sentinel to recur rather than writing out a continue
directly is macros.
Sometimes, we'll have generated code like:
while(true) {
when$_not.call(null, function() {
// some block of code
continue; // woops, there was a loop in the outer context
});
}
And V8 will straight out refuse to load that code - not even refuse to execute it, just refuse to parse/load it. So we can't write out continues everywhere like that. But oh well, our solution is elegant too and there's no reason it should be slower than the mainline cljs one :)
See #45 for reference output vs ours