Skip to content

Instantly share code, notes, and snippets.

@maxtaco
Last active November 16, 2016 00:32
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maxtaco/05a1f68125ee16540e5c to your computer and use it in GitHub Desktop.
Save maxtaco/05a1f68125ee16540e5c to your computer and use it in GitHub Desktop.
IcedCoffeeScript ES6 Implementation

ES6 IcedCoffeeScript Implementation

It's been a real challenge to continuously merge my IcedCoffeeScript branch with the CoffeeScript mainline. The more progress Jeremy and the team make in master, the harder a time I have in the branch. The core issue here is the the iced transform is quite deep. It's doing a CPS translation of the entire abstract syntax tree, rendering the emitted code all but unrecognizable if iced features are at play.

Whenever ES6 is ready for primetime, yield and generators can do all of this heavy lifting, meaning the ICS patch can much simpler. Here's an example that I hand-coded. The input is the first file input.iced, which does basic ICS loops and if/else control flow exercises. The hypothetical output is output.js, which is compiled to use generators and yield, keeping the original program structure intact.

# Here's an example simple program that we're going to hand-compile
# using ES6-style yield statments. It exercises the various
# control-flow patterns we see in IcedCoffeeScript.
foo = (x, cb) ->
for i in [0...x]
console.log "+ wait #{i}"
await setTimeout defer(), 100
console.log "- wait #{i}"
if x % 2 is 0
console.log "+ if even then wait 2"
await setTimeout defer(), 2000
console.log "- done"
else
await
for j in [0...x]
amt = Math.random()*3
console.log "+ parallel wait #{amt}"
setTimeout defer(), amt*1000
console.log "- done with the wait"
cb()
foo 6, ->
console.log "done with the first foo"
foo 13, ->
console.log "done with the sescond foo"
// Here's the hand-compiled output of a hypothetical updated ICS compiler.
// Note that the output is much more in the spirit of CoffeeScript,
// in that there is nearly line-for-line correspondence between the
// input and output. Run this script with io.js or `traceur output.js`
//
// We include a stripped-down `Deferrals` class so this test is self-contained.
var Deferrals = (function () {
function Deferrals(it) {
this.count = 1;
this.it = it;
}
Deferrals.prototype.fulfill = function() {
if (--this.count == 0) {
this.it.next()
}
}
Deferrals.prototype.defer = function () {
this.count++;
var _this = this;
return function() {
_this.fulfill();
}
}
return Deferrals;
})();
function foo (x, cb) {
var __it = (function* () {
for (var i = 0; i < x; i++) {
(function (it) {
var __d = new Deferrals(it);
console.log("+ wait " + i);
setTimeout(__d.defer(), 100);
__d.fulfill()
})(__it);
yield;
console.log("- wait " + i);
}
if (x % 2 == 0) {
(function (it) {
var __d = new Deferrals(it);
console.log("+ if even then wait 2");
setTimeout(__d.defer(), 2000);
__d.fulfill();
})(__it);
yield;
console.log("- done");
} else {
(function (it) {
var __d = new Deferrals(it);
for (var j = 0; j < x; j++) {
var amt = Math.random()*3
console.log("+ parallel wait " + amt);
setTimeout(__d.defer(), amt*1000)
}
__d.fulfill();
})(__it);
yield;
console.log("- done with the wait");
}
cb()
})()
__it.next()
}
foo(6, function() {
console.log("done with first foo");
foo(13, function() {
console.log("done with second foo");
})
})
@bishtawi
Copy link

bishtawi commented Jun 1, 2016

@maxtaco Any update on this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment