Skip to content

Instantly share code, notes, and snippets.

@skrat
Created December 9, 2014 12:14
Show Gist options
  • Save skrat/39b9532c4d06a2f4fda2 to your computer and use it in GitHub Desktop.
Save skrat/39b9532c4d06a2f4fda2 to your computer and use it in GitHub Desktop.
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* https://raw.github.com/facebook/regenerator/master/LICENSE file. An
* additional grant of patent rights can be found in the PATENTS file in
* the same directory.
*/
!(function() {
var hasOwn = Object.prototype.hasOwnProperty;
var undefined; // More compressible than void 0.
var iteratorSymbol =
typeof Symbol === "function" && Symbol.iterator || "@@iterator";
// Make a reasonable attempt to provide a Promise polyfill.
if (typeof Promise === "undefined") try {
Promise = require("promise");
} catch (ignored) {}
if (typeof regeneratorRuntime === "object") {
return;
}
var runtime = regeneratorRuntime =
typeof exports === "undefined" ? {} : exports;
function wrap(innerFn, outerFn, self, tryList) {
return new Generator(innerFn, outerFn, self || null, tryList || []);
}
runtime.wrap = wrap;
var GenStateSuspendedStart = "suspendedStart";
var GenStateSuspendedYield = "suspendedYield";
var GenStateExecuting = "executing";
var GenStateCompleted = "completed";
// Returning this object from the innerFn has the same effect as
// breaking out of the dispatch switch statement.
var ContinueSentinel = {};
// Dummy constructor that we use as the .constructor property for
// functions that return Generator objects.
function GeneratorFunction() {}
var Gp = Generator.prototype;
var GFp = GeneratorFunction.prototype = Object.create(Function.prototype);
GFp.constructor = GeneratorFunction;
GFp.prototype = Gp;
Gp.constructor = GFp;
// Ensure isGeneratorFunction works when Function#name not supported.
if (GeneratorFunction.name !== "GeneratorFunction") {
GeneratorFunction.name = "GeneratorFunction";
}
if (GeneratorFunction.name !== "GeneratorFunction") {
throw new Error("GeneratorFunction renamed?");
}
runtime.isGeneratorFunction = function(genFun) {
var ctor = genFun && genFun.constructor;
return ctor ? GeneratorFunction.name === ctor.name : false;
};
runtime.mark = function(genFun) {
genFun.__proto__ = GFp;
genFun.prototype = Object.create(Gp);
return genFun;
};
runtime.async = function(innerFn, outerFn, self, tryList) {
return new Promise(function(resolve, reject) {
var generator = wrap(innerFn, outerFn, self, tryList);
var callNext = step.bind(generator.next);
var callThrow = step.bind(generator.throw);
function step(arg) {
try {
var info = this(arg);
var value = info.value;
} catch (error) {
return reject(error);
}
if (info.done) {
resolve(value);
} else {
Promise.resolve(value).then(callNext, callThrow);
}
}
callNext();
});
};
function Generator(innerFn, outerFn, self, tryList) {
var generator = outerFn ? Object.create(outerFn.prototype) : this;
var context = new Context(tryList);
var state = GenStateSuspendedStart;
function invoke(method, arg) {
if (state === GenStateExecuting) {
throw new Error("Generator is already running");
}
if (state === GenStateCompleted) {
throw new Error("Generator has already finished");
}
while (true) {
var delegate = context.delegate;
if (delegate) {
try {
var info = delegate.iterator[method](arg);
// Delegate generator ran and handled its own exceptions so
// regardless of what the method was, we continue as if it is
// "next" with an undefined arg.
method = "next";
arg = undefined;
} catch (uncaught) {
context.delegate = null;
// Like returning generator.throw(uncaught), but without the
// overhead of an extra function call.
method = "throw";
arg = uncaught;
continue;
}
if (info.done) {
context[delegate.resultName] = info.value;
context.next = delegate.nextLoc;
} else {
state = GenStateSuspendedYield;
return info;
}
context.delegate = null;
}
if (method === "next") {
if (state === GenStateSuspendedStart &&
typeof arg !== "undefined") {
// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume
throw new TypeError(
"attempt to send " + JSON.stringify(arg) + " to newborn generator"
);
}
if (state === GenStateSuspendedYield) {
context.sent = arg;
} else {
delete context.sent;
}
} else if (method === "throw") {
if (state === GenStateSuspendedStart) {
state = GenStateCompleted;
throw arg;
}
if (context.dispatchException(arg)) {
// If the dispatched exception was caught by a catch block,
// then let that catch block handle the exception normally.
method = "next";
arg = undefined;
}
} else if (method === "return") {
context.abrupt("return", arg);
}
state = GenStateExecuting;
try {
var value = innerFn.call(self, context);
// If an exception is thrown from innerFn, we leave state ===
// GenStateExecuting and loop back for another invocation.
state = context.done
? GenStateCompleted
: GenStateSuspendedYield;
var info = {
value: value,
done: context.done
};
if (value === ContinueSentinel) {
if (context.delegate && method === "next") {
// Deliberately forget the last sent value so that we don't
// accidentally pass it on to the delegate.
arg = undefined;
}
} else {
return info;
}
} catch (thrown) {
state = GenStateCompleted;
if (method === "next") {
context.dispatchException(thrown);
} else {
arg = thrown;
}
}
}
}
generator.next = invoke.bind(generator, "next");
generator.throw = invoke.bind(generator, "throw");
generator.return = invoke.bind(generator, "return");
return generator;
}
Gp[iteratorSymbol] = function() {
return this;
};
Gp.toString = function() {
return "[object Generator]";
};
function pushTryEntry(triple) {
var entry = { tryLoc: triple[0] };
if (1 in triple) {
entry.catchLoc = triple[1];
}
if (2 in triple) {
entry.finallyLoc = triple[2];
}
this.tryEntries.push(entry);
}
function resetTryEntry(entry, i) {
var record = entry.completion || {};
record.type = i === 0 ? "normal" : "return";
delete record.arg;
entry.completion = record;
}
function Context(tryList) {
// The root entry object (effectively a try statement without a catch
// or a finally block) gives us a place to store values thrown from
// locations where there is no enclosing try statement.
this.tryEntries = [{ tryLoc: "root" }];
tryList.forEach(pushTryEntry, this);
this.reset();
}
runtime.keys = function(object) {
var keys = [];
for (var key in object) {
keys.push(key);
}
keys.reverse();
// Rather than returning an object with a next method, we keep
// things simple and return the next function itself.
return function next() {
while (keys.length) {
var key = keys.pop();
if (key in object) {
next.value = key;
next.done = false;
return next;
}
}
// To avoid creating an additional object, we just hang the .value
// and .done properties off the next function object itself. This
// also ensures that the minifier will not anonymize the function.
next.done = true;
return next;
};
};
function values(iterable) {
var iterator = iterable;
if (iteratorSymbol in iterable) {
iterator = iterable[iteratorSymbol]();
} else if (!isNaN(iterable.length)) {
var i = -1;
iterator = function next() {
while (++i < iterable.length) {
if (i in iterable) {
next.value = iterable[i];
next.done = false;
return next;
}
};
next.done = true;
return next;
};
iterator.next = iterator;
}
return iterator;
}
runtime.values = values;
Context.prototype = {
constructor: Context,
reset: function() {
this.prev = 0;
this.next = 0;
this.sent = undefined;
this.done = false;
this.delegate = null;
this.tryEntries.forEach(resetTryEntry);
// Pre-initialize at least 20 temporary variables to enable hidden
// class optimizations for simple generators.
for (var tempIndex = 0, tempName;
hasOwn.call(this, tempName = "t" + tempIndex) || tempIndex < 20;
++tempIndex) {
this[tempName] = null;
}
},
stop: function() {
this.done = true;
var rootEntry = this.tryEntries[0];
var rootRecord = rootEntry.completion;
if (rootRecord.type === "throw") {
throw rootRecord.arg;
}
return this.rval;
},
dispatchException: function(exception) {
if (this.done) {
throw exception;
}
var context = this;
function handle(loc, caught) {
record.type = "throw";
record.arg = exception;
context.next = loc;
return !!caught;
}
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
var record = entry.completion;
if (entry.tryLoc === "root") {
// Exception thrown outside of any try block that could handle
// it, so set the completion value of the entire function to
// throw the exception.
return handle("end");
}
if (entry.tryLoc <= this.prev) {
var hasCatch = hasOwn.call(entry, "catchLoc");
var hasFinally = hasOwn.call(entry, "finallyLoc");
if (hasCatch && hasFinally) {
if (this.prev < entry.catchLoc) {
return handle(entry.catchLoc, true);
} else if (this.prev < entry.finallyLoc) {
return handle(entry.finallyLoc);
}
} else if (hasCatch) {
if (this.prev < entry.catchLoc) {
return handle(entry.catchLoc, true);
}
} else if (hasFinally) {
if (this.prev < entry.finallyLoc) {
return handle(entry.finallyLoc);
}
} else {
throw new Error("try statement without catch or finally");
}
}
}
},
_findFinallyEntry: function(finallyLoc) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.tryLoc <= this.prev &&
hasOwn.call(entry, "finallyLoc") && (
entry.finallyLoc === finallyLoc ||
this.prev < entry.finallyLoc)) {
return entry;
}
}
},
abrupt: function(type, arg) {
var entry = this._findFinallyEntry();
var record = entry ? entry.completion : {};
record.type = type;
record.arg = arg;
if (entry) {
this.next = entry.finallyLoc;
} else {
this.complete(record);
}
return ContinueSentinel;
},
complete: function(record) {
if (record.type === "throw") {
throw record.arg;
}
if (record.type === "break" ||
record.type === "continue") {
this.next = record.arg;
} else if (record.type === "return") {
this.rval = record.arg;
this.next = "end";
}
return ContinueSentinel;
},
finish: function(finallyLoc) {
var entry = this._findFinallyEntry(finallyLoc);
return this.complete(entry.completion);
},
"catch": function(tryLoc) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i];
if (entry.tryLoc === tryLoc) {
var record = entry.completion;
if (record.type === "throw") {
var thrown = record.arg;
resetTryEntry(entry, i);
}
return thrown;
}
}
// The context.catch method must only be called with a location
// argument that corresponds to a known catch block.
throw new Error("illegal catch attempt");
},
delegateYield: function(iterable, resultName, nextLoc) {
this.delegate = {
iterator: values(iterable),
resultName: resultName,
nextLoc: nextLoc
};
return ContinueSentinel;
}
};
})();
"use strict";
require = (function e(t, n, r) {
function s(o, u) {
if (!n[o]) {
if (!t[o]) {
var a = typeof require == "function" && require;if (!u && a) return a(o, !0);if (i) return i(o, !0);throw new Error("Cannot find module '" + o + "'");
}var f = n[o] = { exports: {} };t[o][0].call(f.exports, function (e) {
var n = t[o][1][e];return s(n ? n : e);
}, f, f.exports, e, t, n, r);
}return n[o].exports;
}var i = typeof require == "function" && require;for (var o = 0; o < r.length; o++) s(r[o]);return s;
})({ 1: [function (require, module, exports) {
"use strict";
var buffers = require("./impl/buffers");
var channels = require("./impl/channels");
var select = require("./impl/select");
var process = require("./impl/process");
var timers = require("./impl/timers");
function spawn(gen, returnChannel) {
if (returnChannel) {
var ch = channels.chan(buffers.fixed(1));
(new process.Process(gen, function (value) {
process.put_then_callback(ch, value, function (ok) {
ch.close();
});
})).run();
return ch;
} else {
(new process.Process(gen)).run();
return null;
}
};
function go(f, args, returnChannel) {
var gen = f.apply(null, args);
return spawn(gen, returnChannel);
};
function chan(bufferOrNumber) {
var buf;
if (bufferOrNumber === 0) {
bufferOrNumber = null;
}
if (typeof bufferOrNumber === "number") {
buf = buffers.fixed(bufferOrNumber);
} else {
buf = bufferOrNumber;
}
return channels.chan(buf);
};
module.exports = {
buffers: {
fixed: buffers.fixed,
dropping: buffers.dropping,
sliding: buffers.sliding
},
spawn: spawn,
go: go,
chan: chan,
DEFAULT: select.DEFAULT,
CLOSED: channels.CLOSED,
put: process.put,
take: process.take,
sleep: process.sleep,
alts: process.alts,
putAsync: process.put_then_callback,
takeAsync: process.take_then_callback,
timeout: timers.timeout
};
}, { "./impl/buffers": 5, "./impl/channels": 6, "./impl/process": 8, "./impl/select": 9, "./impl/timers": 10 }], i2jwt0: [function (require, module, exports) {
"use strict";
var csp = require("./csp.core");
var operations = require("./csp.operations");
csp.operations = operations;
module.exports = csp;
}, { "./csp.core": 1, "./csp.operations": 4 }], csp: [function (require, module, exports) {
module.exports = require("i2jwt0");
}, {}], 4: [function (require, module, exports) {
var mapcat = regeneratorRuntime.mark(function mapcat(f, src, dst) {
var value, seq, length, i;
return regeneratorRuntime.wrap(function mapcat$(_context2) {
while (true) switch (_context2.prev = _context2.next) {
case 0:
if (!true) {
_context2.next = 22;
break;
}
_context2.next = 3;
return take(src);
case 3: value = _context2.sent;
if (!(value === CLOSED)) {
_context2.next = 9;
break;
}
dst.close();
return _context2.abrupt("break", 22);
case 9: seq = f(value);
length = seq.length;
i = 0;
case 12:
if (!(i < length)) {
_context2.next = 18;
break;
}
_context2.next = 15;
return put(dst, seq[i]);
case 15: i++;
_context2.next = 12;
break;
case 18:
if (!dst.is_closed()) {
_context2.next = 20;
break;
}
return _context2.abrupt("break", 22);
case 20: _context2.next = 0;
break;
case 22:
case "end": return _context2.stop();
}
}, mapcat, this);
});
"use strict";
var Box = require("./impl/channels").Box;
var csp = require("./csp.core"), go = csp.go, take = csp.take, put = csp.put, takeAsync = csp.takeAsync, putAsync = csp.putAsync, alts = csp.alts, chan = csp.chan, CLOSED = csp.CLOSED;
function noOp(v) {}
function mapFrom(f, ch) {
return {
is_closed: function () {
return ch.is_closed();
},
close: function () {
ch.close();
},
_put: function (value, handler) {
return ch._put(value, handler);
},
_take: function (handler) {
var result = ch._take({
is_active: function () {
return handler.is_active();
},
commit: function () {
var take_cb = handler.commit();
return function (value) {
return take_cb(value === CLOSED ? CLOSED : f(value));
};
}
});
if (result) {
var value = result.value;
return new Box(value === CLOSED ? CLOSED : f(value));
} else {
return null;
}
}
};
}
function mapInto(f, ch) {
return {
is_closed: function () {
return ch.is_closed();
},
close: function () {
ch.close();
},
_put: function (value, handler) {
return ch._put(f(value), handler);
},
_take: function (handler) {
return ch._take(handler);
}
};
}
function filterFrom(p, ch, bufferOrN) {
var out = chan(bufferOrN);
go(regeneratorRuntime.mark(function _callee() {
var value;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (true) switch (_context.prev = _context.next) {
case 0:
if (!true) {
_context.next = 12;
break;
}
_context.next = 3;
return take(ch);
case 3: value = _context.sent;
if (!(value === CLOSED)) {
_context.next = 7;
break;
}
out.close();
return _context.abrupt("break", 12);
case 7:
if (!p(value)) {
_context.next = 10;
break;
}
_context.next = 10;
return put(out, value);
case 10: _context.next = 0;
break;
case 12:
case "end": return _context.stop();
}
}, _callee, this);
}));
return out;
}
function filterInto(p, ch) {
return {
is_closed: function () {
return ch.is_closed();
},
close: function () {
ch.close();
},
_put: function (value, handler) {
if (p(value)) {
return ch._put(value, handler);
} else {
return new Box(!ch.is_closed());
}
},
_take: function (handler) {
return ch._take(handler);
}
};
}
function removeFrom(p, ch) {
return filterFrom(function (value) {
return !p(value);
}, ch);
}
function removeInto(p, ch) {
return filterInto(function (value) {
return !p(value);
}, ch);
}
function mapcatFrom(f, ch, bufferOrN) {
var out = chan(bufferOrN);
go(mapcat, [f, ch, out]);
return out;
}
function mapcatInto(f, ch, bufferOrN) {
var src = chan(bufferOrN);
go(mapcat, [f, src, ch]);
return src;
}
function pipe(src, dst, keepOpen) {
go(regeneratorRuntime.mark(function _callee2() {
var value;
return regeneratorRuntime.wrap(function _callee2$(_context3) {
while (true) switch (_context3.prev = _context3.next) {
case 0:
if (!true) {
_context3.next = 13;
break;
}
_context3.next = 3;
return take(src);
case 3: value = _context3.sent;
if (!(value === CLOSED)) {
_context3.next = 7;
break;
}
if (!keepOpen) {
dst.close();
}
return _context3.abrupt("break", 13);
case 7: _context3.next = 9;
return put(dst, value);
case 9:
if (_context3.sent) {
_context3.next = 11;
break;
}
return _context3.abrupt("break", 13);
case 11: _context3.next = 0;
break;
case 13:
case "end": return _context3.stop();
}
}, _callee2, this);
}));
return dst;
}
function split(p, ch, trueBufferOrN, falseBufferOrN) {
var tch = chan(trueBufferOrN);
var fch = chan(falseBufferOrN);
go(regeneratorRuntime.mark(function _callee3() {
var value;
return regeneratorRuntime.wrap(function _callee3$(_context4) {
while (true) switch (_context4.prev = _context4.next) {
case 0:
if (!true) {
_context4.next = 12;
break;
}
_context4.next = 3;
return take(ch);
case 3: value = _context4.sent;
if (!(value === CLOSED)) {
_context4.next = 8;
break;
}
tch.close();
fch.close();
return _context4.abrupt("break", 12);
case 8: _context4.next = 10;
return put(p(value) ? tch : fch, value);
case 10: _context4.next = 0;
break;
case 12:
case "end": return _context4.stop();
}
}, _callee3, this);
}));
return [tch, fch];
}
function reduce(f, init, ch) {
return go(regeneratorRuntime.mark(function _callee4() {
var result, value;
return regeneratorRuntime.wrap(function _callee4$(_context5) {
while (true) switch (_context5.prev = _context5.next) {
case 0: result = init;
case 1:
if (!true) {
_context5.next = 12;
break;
}
_context5.next = 4;
return take(ch);
case 4: value = _context5.sent;
if (!(value === CLOSED)) {
_context5.next = 9;
break;
}
return _context5.abrupt("return", result);
case 9:
result = f(result, value);
case 10: _context5.next = 1;
break;
case 12:
case "end": return _context5.stop();
}
}, _callee4, this);
}), [], true);
}
function onto(ch, coll, keepOpen) {
return go(regeneratorRuntime.mark(function _callee5() {
var length, i;
return regeneratorRuntime.wrap(function _callee5$(_context6) {
while (true) switch (_context6.prev = _context6.next) {
case 0: length = coll.length;
i = 0;
case 2:
if (!(i < length)) {
_context6.next = 8;
break;
}
_context6.next = 5;
return put(ch, coll[i]);
case 5: i++;
_context6.next = 2;
break;
case 8:
if (!keepOpen) {
ch.close();
}
case 9:
case "end": return _context6.stop();
}
}, _callee5, this);
}));
}
// TODO: Bounded?
function fromColl(coll) {
var ch = chan(coll.length);
onto(ch, coll);
return ch;
}
function map(f, chs, bufferOrN) {
var out = chan(bufferOrN);
var length = chs.length;
// Array holding 1 round of values
var values = new Array(length);
// TODO: Not sure why we need a size-1 buffer here
var dchan = chan(1);
// How many more items this round
var dcount;
// put callbacks for each channel
var dcallbacks = new Array(length);
for (var i = 0; i < length; i++) {
dcallbacks[i] = (function (i) {
return function (value) {
values[i] = value;
dcount--;
if (dcount === 0) {
putAsync(dchan, values.slice(0), noOp);
}
};
}(i));
}
go(regeneratorRuntime.mark(function _callee6() {
var i, values;
return regeneratorRuntime.wrap(function _callee6$(_context7) {
while (true) switch (_context7.prev = _context7.next) {
case 0:
if (!true) {
_context7.next = 18;
break;
}
dcount = length;
// We could just launch n goroutines here, but for effciency we
// don't
for (i = 0; i < length; i++) {
try {
takeAsync(chs[i], dcallbacks[i]);
} catch (e) {
// FIX: Hmm why catching here?
dcount--;
}
}
_context7.next = 5;
return take(dchan);
case 5: values = _context7.sent;
i = 0;
case 7:
if (!(i < length)) {
_context7.next = 14;
break;
}
if (!(values[i] === CLOSED)) {
_context7.next = 11;
break;
}
out.close();
return _context7.abrupt("return");
case 11: i++;
_context7.next = 7;
break;
case 14: _context7.next = 16;
return put(out, f.apply(null, values));
case 16: _context7.next = 0;
break;
case 18:
case "end": return _context7.stop();
}
}, _callee6, this);
}));
return out;
}
function merge(chs, bufferOrN) {
var out = chan(bufferOrN);
var actives = chs.slice(0);
go(regeneratorRuntime.mark(function _callee7() {
var r, value, i;
return regeneratorRuntime.wrap(function _callee7$(_context8) {
while (true) switch (_context8.prev = _context8.next) {
case 0:
if (!true) {
_context8.next = 15;
break;
}
if (!(actives.length === 0)) {
_context8.next = 3;
break;
}
return _context8.abrupt("break", 15);
case 3: _context8.next = 5;
return alts(actives);
case 5: r = _context8.sent;
value = r.value;
if (!(value === CLOSED)) {
_context8.next = 11;
break;
}
i = actives.indexOf(r.channel);
actives.splice(i, 1);
return _context8.abrupt("continue", 0);
case 11: _context8.next = 13;
return put(out, value);
case 13: _context8.next = 0;
break;
case 15:
out.close();
case 16:
case "end": return _context8.stop();
}
}, _callee7, this);
}));
return out;
}
function into(coll, ch) {
var result = coll.slice(0);
return reduce(function (result, item) {
result.push(item);
return result;
}, result, ch);
}
function takeN(n, ch, bufferOrN) {
var out = chan(bufferOrN);
go(regeneratorRuntime.mark(function _callee8() {
var i, value;
return regeneratorRuntime.wrap(function _callee8$(_context9) {
while (true) switch (_context9.prev = _context9.next) {
case 0: i = 0;
case 1:
if (!(i < n)) {
_context9.next = 12;
break;
}
_context9.next = 4;
return take(ch);
case 4: value = _context9.sent;
if (!(value === CLOSED)) {
_context9.next = 7;
break;
}
return _context9.abrupt("break", 12);
case 7: _context9.next = 9;
return put(out, value);
case 9: i++;
_context9.next = 1;
break;
case 12:
out.close();
case 13:
case "end": return _context9.stop();
}
}, _callee8, this);
}));
return out;
}
var NOTHING = {};
function unique(ch, bufferOrN) {
var out = chan(bufferOrN);
var last = NOTHING;
go(regeneratorRuntime.mark(function _callee9() {
var value;
return regeneratorRuntime.wrap(function _callee9$(_context10) {
while (true) switch (_context10.prev = _context10.next) {
case 0:
if (!true) {
_context10.next = 13;
break;
}
_context10.next = 3;
return take(ch);
case 3: value = _context10.sent;
if (!(value === CLOSED)) {
_context10.next = 6;
break;
}
return _context10.abrupt("break", 13);
case 6:
if (!(value === last)) {
_context10.next = 8;
break;
}
return _context10.abrupt("continue", 0);
case 8:
last = value;
_context10.next = 11;
return put(out, value);
case 11: _context10.next = 0;
break;
case 13:
out.close();
case 14:
case "end": return _context10.stop();
}
}, _callee9, this);
}));
return out;
}
function partitionBy(f, ch, bufferOrN) {
var out = chan(bufferOrN);
var part = [];
var last = NOTHING;
go(regeneratorRuntime.mark(function _callee10() {
var value, newItem;
return regeneratorRuntime.wrap(function _callee10$(_context11) {
while (true) switch (_context11.prev = _context11.next) {
case 0:
if (!true) {
_context11.next = 23;
break;
}
_context11.next = 3;
return take(ch);
case 3: value = _context11.sent;
if (!(value === CLOSED)) {
_context11.next = 12;
break;
}
if (!(part.length > 0)) {
_context11.next = 8;
break;
}
_context11.next = 8;
return put(out, part);
case 8:
out.close();
return _context11.abrupt("break", 23);
case 12: newItem = f(value);
if (!(newItem === last || last === NOTHING)) {
_context11.next = 17;
break;
}
part.push(value);
_context11.next = 20;
break;
case 17: _context11.next = 19;
return put(out, part);
case 19:
part = [value];
case 20:
last = newItem;
case 21: _context11.next = 0;
break;
case 23:
case "end": return _context11.stop();
}
}, _callee10, this);
}));
return out;
}
function partition(n, ch, bufferOrN) {
var out = chan(bufferOrN);
go(regeneratorRuntime.mark(function _callee11() {
var part, i, value;
return regeneratorRuntime.wrap(function _callee11$(_context12) {
while (true) switch (_context12.prev = _context12.next) {
case 0:
if (!true) {
_context12.next = 21;
break;
}
part = new Array(n);
i = 0;
case 3:
if (!(i < n)) {
_context12.next = 17;
break;
}
_context12.next = 6;
return take(ch);
case 6: value = _context12.sent;
if (!(value === CLOSED)) {
_context12.next = 13;
break;
}
if (!(i > 0)) {
_context12.next = 11;
break;
}
_context12.next = 11;
return put(out, part.slice(0, i));
case 11:
out.close();
return _context12.abrupt("return");
case 13:
part[i] = value;
case 14: i++;
_context12.next = 3;
break;
case 17: _context12.next = 19;
return put(out, part);
case 19: _context12.next = 0;
break;
case 21:
case "end": return _context12.stop();
}
}, _callee11, this);
}));
return out;
}
module.exports = {
mapFrom: mapFrom,
mapInto: mapInto,
filterFrom: filterFrom,
filterInto: filterInto,
removeFrom: removeFrom,
removeInto: removeInto,
mapcatFrom: mapcatFrom,
mapcatInto: mapcatInto,
pipe: pipe,
split: split,
reduce: reduce,
onto: onto,
fromColl: fromColl,
map: map,
merge: merge,
into: into,
take: takeN,
unique: unique,
partition: partition,
partitionBy: partitionBy
};
// Possible "fluid" interfaces:
// thread(
// [fromColl, [1, 2, 3, 4]],
// [mapFrom, inc],
// [into, []]
// )
// thread(
// [fromColl, [1, 2, 3, 4]],
// [mapFrom, inc, _],
// [into, [], _]
// )
// wrap()
// .fromColl([1, 2, 3, 4])
// .mapFrom(inc)
// .into([])
// .unwrap();
}, { "./csp.core": 1, "./impl/channels": 6 }], 5: [function (require, module, exports) {
"use strict";
// TODO: Consider EmptyError & FullError to avoid redundant bound
// checks, to improve performance (may need benchmarks)
function acopy(src, src_start, dst, dst_start, length) {
var count = 0;
while (true) {
if (count >= length) {
break;
}
dst[dst_start + count] = src[src_start + count];
count++;
}
}
var EMPTY = {
toString: function () {
return "[object EMPTY]";
}
};
var RingBuffer = function (head, tail, length, array) {
this.length = length;
this.array = array;
this.head = head;
this.tail = tail;
};
// Internal method, callers must do bound check
RingBuffer.prototype._unshift = function (item) {
var array = this.array;
var head = this.head;
array[head] = item;
this.head = (head + 1) % array.length;
this.length++;
};
RingBuffer.prototype._resize = function () {
var array = this.array;
var new_length = 2 * array.length;
var new_array = new Array(new_length);
var head = this.head;
var tail = this.tail;
var length = this.length;
if (tail < head) {
acopy(array, tail, new_array, 0, length);
this.tail = 0;
this.head = length;
this.array = new_array;
} else if (tail > head) {
acopy(array, tail, new_array, 0, array.length - tail);
acopy(array, 0, new_array, array.length - tail, head);
this.tail = 0;
this.head = length;
this.array = new_array;
} else if (tail === head) {
this.tail = 0;
this.head = 0;
this.array = new_array;
}
};
RingBuffer.prototype.unbounded_unshift = function (item) {
if (this.length + 1 === this.array.length) {
this._resize();
}
this._unshift(item);
};
RingBuffer.prototype.pop = function () {
if (this.length === 0) {
return EMPTY;
}
var array = this.array;
var tail = this.tail;
var item = array[tail];
array[tail] = null;
this.tail = (tail + 1) % array.length;
this.length--;
return item;
};
RingBuffer.prototype.cleanup = function (predicate) {
var length = this.length;
for (var i = 0; i < length; i++) {
var item = this.pop();
if (predicate(item)) {
this._unshift(item);
}
}
};
var FixedBuffer = function (buf, n) {
this.buf = buf;
this.n = n;
};
FixedBuffer.prototype.is_full = function () {
return this.buf.length == this.n;
};
FixedBuffer.prototype.remove = function () {
return this.buf.pop();
};
FixedBuffer.prototype.add = function (item) {
if (this.is_full()) {
throw new Error("Can't add to a full buffer");
}
this.buf._unshift(item);
};
FixedBuffer.prototype.count = function () {
return this.buf.length;
};
var DroppingBuffer = function (buf, n) {
this.buf = buf;
this.n = n;
};
DroppingBuffer.prototype.is_full = function () {
return false;
};
DroppingBuffer.prototype.remove = function () {
return this.buf.pop();
};
DroppingBuffer.prototype.add = function (item) {
if (this.buf.length < this.n) {
this.buf._unshift(item);
}
};
DroppingBuffer.prototype.count = function () {
return this.buf.length;
};
var SlidingBuffer = function (buf, n) {
this.buf = buf;
this.n = n;
};
SlidingBuffer.prototype.is_full = function () {
return false;
};
SlidingBuffer.prototype.remove = function () {
return this.buf.pop();
};
SlidingBuffer.prototype.add = function (item) {
if (this.buf.length === this.n) {
this.buf.pop();
}
this.buf._unshift(item);
};
SlidingBuffer.prototype.count = function () {
return this.buf.length;
};
var ring = exports.ring = function ring_buffer(n) {
return new RingBuffer(0, 0, 0, new Array(n));
};
exports.fixed = function fixed_buffer(n) {
return new FixedBuffer(ring(n), n);
};
exports.dropping = function dropping_buffer(n) {
return new DroppingBuffer(ring(n), n);
};
exports.sliding = function sliding_buffer(n) {
return new SlidingBuffer(ring(n), n);
};
exports.EMPTY = EMPTY;
}, {}], 6: [function (require, module, exports) {
"use strict";
var buffers = require("./buffers");
var dispatch = require("./dispatch");
var MAX_DIRTY = 64;
var MAX_QUEUE_SIZE = 1024;
var CLOSED = null;
var Box = function (value) {
this.value = value;
};
var PutBox = function (handler, value) {
this.handler = handler;
this.value = value;
};
var Channel = function (takes, puts, buf) {
this.buf = buf;
this.takes = takes;
this.puts = puts;
this.dirty_takes = 0;
this.dirty_puts = 0;
this.closed = false;
};
Channel.prototype._put = function (value, handler) {
if (value === CLOSED) {
throw new Error("Cannot put CLOSED on a channel.");
}
if (this.closed || !handler.is_active()) {
return new Box(!this.closed);
}
while (true) {
var taker = this.takes.pop();
if (taker !== buffers.EMPTY) {
if (taker.is_active()) {
var callback = taker.commit();
handler.commit();
dispatch.run(function () {
callback(value);
});
return new Box(true);
} else {
continue;
}
} else {
if (this.buf && !this.buf.is_full()) {
handler.commit();
this.buf.add(value);
return new Box(true);
} else {
if (this.dirty_puts > MAX_DIRTY) {
this.puts.cleanup(function (putter) {
return putter.handler.is_active();
});
this.dirty_puts = 0;
} else {
this.dirty_puts++;
}
if (this.puts.length >= MAX_QUEUE_SIZE) {
throw new Error("No more than " + MAX_QUEUE_SIZE + " pending puts are allowed on a single channel.");
}
this.puts.unbounded_unshift(new PutBox(handler, value));
}
}
break;
}
return null;
};
Channel.prototype._take = function (handler) {
if (!handler.is_active()) {
return null;
}
if (this.buf && this.buf.count() > 0) {
handler.commit();
return new Box(this.buf.remove());
}
while (true) {
var putter = this.puts.pop();
if (putter !== buffers.EMPTY) {
var put_handler = putter.handler;
if (put_handler.is_active()) {
handler.commit();
var callback = put_handler.commit();
dispatch.run(function () {
callback(true);
});
return new Box(putter.value);
} else {
continue;
}
} else {
if (this.closed) {
handler.commit();
return new Box(CLOSED);
} else {
if (this.dirty_takes > MAX_DIRTY) {
this.takes.cleanup(function (handler) {
return handler.is_active();
});
this.dirty_takes = 0;
} else {
this.dirty_takes++;
}
if (this.takes.length >= MAX_QUEUE_SIZE) {
throw new Error("No more than " + MAX_QUEUE_SIZE + " pending takes are allowed on a single channel.");
}
this.takes.unbounded_unshift(handler);
}
}
break;
}
return null;
};
Channel.prototype.close = function () {
if (this.closed) {
return;
}
this.closed = true;
while (true) {
var taker = this.takes.pop();
if (taker === buffers.EMPTY) {
break;
}
if (taker.is_active()) {
var callback = taker.commit();
dispatch.run(function () {
callback(CLOSED);
});
}
}
// TODO: Tests
while (true) {
var putter = this.puts.pop();
if (putter === buffers.EMPTY) {
break;
}
if (putter.handler.is_active()) {
var put_callback = putter.handler.commit();
dispatch.run(function () {
put_callback(false);
});
}
}
};
Channel.prototype.is_closed = function () {
return this.closed;
};
exports.chan = function (buf) {
return new Channel(buffers.ring(32), buffers.ring(32), buf);
};
exports.Box = Box;
exports.CLOSED = CLOSED;
}, { "./buffers": 5, "./dispatch": 7 }], 7: [function (require, module, exports) {
"use strict";
// TODO: Use process.nextTick if it's available since it's more
// efficient
// http://howtonode.org/understanding-process-next-tick
// Maybe we don't even need to queue ourselves in that case?
// XXX: But http://blog.nodejs.org/2013/03/11/node-v0-10-0-stable/
// Looks like it will blow up the stack (or is that just about
// pre-empting IO (but that's already bad enough IMO)?)
// Looks like
// http://nodejs.org/api/process.html#process_process_nexttick_callback
// is the equivalent of our TASK_BATCH_SIZE
var buffers = require("./buffers");
var TASK_BATCH_SIZE = 1024;
var tasks = buffers.ring(32);
var running = false;
var queued = false;
var queue_dispatcher;
function process_messages() {
running = true;
queued = false;
var count = 0;
while (true) {
var task = tasks.pop();
if (task === buffers.EMPTY) {
break;
}
// TODO: Don't we need a try/finally here?
task();
if (count >= TASK_BATCH_SIZE) {
break;
}
count++;
}
running = false;
if (tasks.length > 0) {
queue_dispatcher();
}
}
if (typeof MessageChannel !== "undefined") {
var message_channel = new MessageChannel();
message_channel.port1.onmessage = function (_) {
process_messages();
};
queue_dispatcher = function () {
if (!(queued && running)) {
queued = true;
message_channel.port2.postMessage(0);
}
};
} else if (typeof setImmediate !== "undefined") {
queue_dispatcher = function () {
if (!(queued && running)) {
queued = true;
setImmediate(process_messages);
}
};
} else {
queue_dispatcher = function () {
if (!(queued && running)) {
queued = true;
setTimeout(process_messages, 0);
}
};
}
exports.run = function (f) {
tasks.unbounded_unshift(f);
queue_dispatcher();
};
exports.queue_delay = function (f, delay) {
setTimeout(f, delay);
};
}, { "./buffers": 5 }], 8: [function (require, module, exports) {
"use strict";
var dispatch = require("./dispatch");
var select = require("./select");
var FnHandler = function (f) {
this.f = f;
};
FnHandler.prototype.is_active = function () {
return true;
};
FnHandler.prototype.commit = function () {
return this.f;
};
function put_then_callback(channel, value, callback) {
var result = channel._put(value, new FnHandler(callback));
if (result) {
callback(result.value);
}
}
function take_then_callback(channel, callback) {
var result = channel._take(new FnHandler(callback));
if (result) {
callback(result.value);
}
}
var Process = function (gen, onFinish) {
this.gen = gen;
this.finished = false;
this.onFinish = onFinish;
};
var Instruction = function (op, data) {
this.op = op;
this.data = data;
};
var TAKE = "take";
var PUT = "put";
var SLEEP = "sleep";
var ALTS = "alts";
// TODO FIX XXX: This is a (probably) temporary hack to avoid blowing
// up the stack, but it means double queueing when the value is not
// immediately available
Process.prototype._continue = function (response) {
var self = this;
dispatch.run(function () {
self.run(response);
});
};
Process.prototype._done = function (value) {
if (!this.finished) {
this.finished = true;
var onFinish = this.onFinish;
if (typeof onFinish === "function") {
dispatch.run(function () {
onFinish(value);
});
}
}
};
Process.prototype.run = function (response) {
if (this.finished) {
return;
}
// TODO: Shouldn't we (optionally) stop error propagation here (and
// signal the error through a channel or something)? Otherwise the
// uncaught exception will crash some runtimes (e.g. Node)
var iter = this.gen.next(response);
if (iter.done) {
this._done(iter.value);
return;
}
var ins = iter.value;
if (ins instanceof Instruction) {
var self = this;
switch (ins.op) {
case PUT:
var data = ins.data;
put_then_callback(data.channel, data.value, function (ok) {
self._continue(ok);
});
break;
case TAKE:
var channel = ins.data;
take_then_callback(channel, function (value) {
self._continue(value);
});
break;
case SLEEP:
var msecs = ins.data;
dispatch.queue_delay(function () {
self.run(null);
}, msecs);
break;
case ALTS:
select.do_alts(ins.data.operations, function (result) {
self._continue(result);
}, ins.data.options);
break;
}
} else {
this._continue(ins);
}
};
function take(channel) {
return new Instruction(TAKE, channel);
}
function put(channel, value) {
return new Instruction(PUT, {
channel: channel,
value: value
});
}
function sleep(msecs) {
return new Instruction(SLEEP, msecs);
}
function alts(operations, options) {
return new Instruction(ALTS, {
operations: operations,
options: options
});
}
exports.put_then_callback = put_then_callback;
exports.take_then_callback = take_then_callback;
exports.put = put;
exports.take = take;
exports.sleep = sleep;
exports.alts = alts;
exports.Process = Process;
}, { "./dispatch": 7, "./select": 9 }], 9: [function (require, module, exports) {
"use strict";
var Box = require("./channels").Box;
var AltHandler = function (flag, f) {
this.f = f;
this.flag = flag;
};
AltHandler.prototype.is_active = function () {
return this.flag.value;
};
AltHandler.prototype.commit = function () {
this.flag.value = false;
return this.f;
};
var AltResult = function (value, channel) {
this.value = value;
this.channel = channel;
};
function rand_int(n) {
return Math.floor(Math.random() * (n + 1));
}
function random_array(n) {
var a = new Array(n);
var i;
for (i = 0; i < n; i++) {
a[i] = 0;
}
for (i = 1; i < n; i++) {
var j = rand_int(i);
a[i] = a[j];
a[j] = i;
}
return a;
}
var hasOwnProperty = Object.prototype.hasOwnProperty;
var DEFAULT = {
toString: function () {
return "[object DEFAULT]";
}
};
// TODO: Accept a priority function or something
exports.do_alts = function (operations, callback, options) {
var length = operations.length;
// XXX Hmm
if (length === 0) {
throw new Error("Empty alt list");
}
var priority = (options && options.priority) ? true : false;
if (!priority) {
var indexes = random_array(length);
}
var flag = new Box(true);
for (var i = 0; i < length; i++) {
var operation = operations[priority ? i : indexes[i]];
var port, result;
// XXX Hmm
if (operation instanceof Array) {
var value = operation[1];
port = operation[0];
result = port._put(value, (function (port) {
return new AltHandler(flag, function (ok) {
callback(new AltResult(ok, port));
});
})(port));
} else {
port = operation;
result = port._take((function (port) {
return new AltHandler(flag, function (value) {
callback(new AltResult(value, port));
});
})(port));
}
// XXX Hmm
if (result instanceof Box) {
callback(new AltResult(result.value, port));
break;
}
}
if (!(result instanceof Box) && options && hasOwnProperty.call(options, "default")) {
if (flag.value) {
flag.value = false;
callback(new AltResult(options["default"], DEFAULT));
}
}
};
exports.DEFAULT = DEFAULT;
}, { "./channels": 6 }], 10: [function (require, module, exports) {
"use strict";
var dispatch = require("./dispatch");
var channels = require("./channels");
exports.timeout = function timeout_channel(msecs) {
var chan = channels.chan();
dispatch.queue_delay(function () {
chan.close();
}, msecs);
return chan;
};
}, { "./channels": 6, "./dispatch": 7 }] }, {}, ["i2jwt0"]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment