UNPKG

axos

Version:

JIT-friendly, multiparadigm asynchronous programming

350 lines (309 loc) 8.55 kB
(function() { var CATCH, Cell, ERROR, FINAL_ERROR, FINAL_VALUE, NO_MORE, Operator, Strategy, TRY, VALUE, afterIO, axos, current_receiver, drain, draining, io_send, mq, receive, ref, ref1, schedule, scheduled, send, throwingFunction, tryingFunction, hasProp = {}.hasOwnProperty; Strategy = (function() { function Strategy(opts) { var k; if (opts == null) { opts = {}; } this.kind = opts.kind; this.initState = opts.initState; this.onReceive = opts.onReceive; this.onDispose = opts.onDispose; for (k in opts) { if (!hasProp.call(opts, k)) continue; if (!this.hasOwnProperty(k)) { throw new TypeError("invalid Strategy option: " + k); } } } Strategy.prototype.cell = function() { var cell, initState; cell = new Cell(this.kind, this); if (initState = this.initState) { cell.state = initState.apply(cell, arguments); } return cell; }; Strategy.prototype.withKind = function(kind) { this.kind = kind; return this; }; return Strategy; })(); Cell = (function() { function Cell(kind1, strategy, state) { this.kind = kind1; this.strategy = strategy; this.state = state; this.op = this.arg = this.sink = this.tag = null; this.length = 0; } Cell.prototype.setValue = function(val) { return this.set(VALUE, val); }; Cell.prototype.setError = function(err) { return this.set(ERROR, err); }; Cell.prototype.finish = function(val) { return this.set(FINAL_VALUE, val); }; Cell.prototype.abort = function(err) { return this.set(FINAL_ERROR, err); }; Cell.prototype.set = function(op, arg) { var ref; if (this !== current_receiver) { throw new TypeError("set() must be called from onReceive() or onRecalc()"); } if ((ref = this.op) != null ? ref.isFinal : void 0) { return; } this.op = op; this.arg = arg; }; Cell.prototype.hasSink = function(cell, tag) { var any_tag, c, i, j, len; if (this.sink == null) { return false; } any_tag = arguments.length < 2; if (this.sink === cell && (any_tag || this.tag === tag)) { return true; } if (!this.length) { return false; } for (i = j = 0, len = this.length; j < len; i = j += 2) { c = this[i]; if (c === cell && (any_tag || this[i + 1] === tag)) { return true; } } return false; }; Cell.prototype.addSink = function(cell, tag) { var ref; if (this.sink != null) { this[this.length++] = cell; this[this.length++] = tag; } else { this.sink = cell; this.tag = tag; } if ((ref = this.op) != null ? ref.isFinal : void 0) { return send(cell, tag, this.op, this.arg); } }; Cell.prototype.removeSink = function(cell, tag) { var any_tag, c, i, j, len, out; if (this.sink == null) { return; } any_tag = arguments.length < 2; out = 0; if (this.sink === cell && (any_tag || this.tag === tag)) { out = -2; } if (this.length) { for (i = j = 0, len = this.length; j < len; i = j += 2) { c = this[i]; if (c === cell && (any_tag || this[i + 1] === tag)) { continue; } if (out < 0) { this.sink = c; this.tag = this[i + 1]; out = 0; } else { this[out++] = c; this[out++] = this[i + 1]; } } } if (out < 0) { this.sink = this.tag = null; out = 0; } return this.length = out; }; Cell.prototype.notify = function() { var arg, c, i, isFinal, j, len, op, out; op = this.op; arg = this.arg; isFinal = op != null ? op.isFinal : void 0; out = 0; if (receive(this.sink, this.tag, op, arg) === NO_MORE || isFinal) { out = -2; } if (this.length) { for (i = j = 0, len = this.length; j < len; i = j += 2) { c = this[i]; if (receive(c, this[i + 1], op, arg) === NO_MORE || isFinal) { if (out < 0) { this.sink = c; this.tag = this[i + 1]; out = 0; } else { this[out++] = c; this[out++] = this[i + 1]; } } } } if (out < 0) { this.sink = this.tag = null; out = 0; } this.length = isFinal ? 0 : out; }; return Cell; })(); afterIO = (ref = (ref1 = typeof process !== "undefined" && process !== null ? process.nextTick : void 0) != null ? ref1 : setImmediate) != null ? ref : function(fn) { return setTimeout(fn, 0); }; mq = []; scheduled = draining = false; send = function(cell, tag, op, arg) { mq[mq.length] = cell; mq[mq.length] = tag; mq[mq.length] = op; mq[mq.length] = arg; if (!(scheduled || draining)) { return schedule(); } }; schedule = function() { if (!scheduled) { axos.afterIO(drain); } return scheduled = true; }; drain = function() { scheduled = false; return io_send(); }; io_send = function() { var pos; if (draining) { throw new Error("io_send() must be invoked in a Zalgo-safe way"); } draining = true; if (arguments.length) { send.apply(null, arguments); } pos = 0; while (pos < mq.length) { receive(mq[pos++], mq[pos++], mq[pos++], mq[pos++]); } mq.length = 0; return draining = false; }; current_receiver = null; receive = function(cell, tag, op, arg) { var old_receiver, rcv, ref2; if ((ref2 = cell.op) != null ? ref2.isFinal : void 0) { return NO_MORE; } old_receiver = current_receiver; current_receiver = cell; if ((rcv = cell.strategy.onReceive) != null) { rcv = rcv.call(cell.state, cell, tag, op, arg); } else { cell.set(op, arg); } if ((cell.op != null) && (cell.sink != null)) { cell.notify(); } current_receiver = old_receiver; return rcv; }; Operator = (function() { function Operator(opts) { var isError, isFinal, isValue, ref2, ref3, ref4; if (opts == null) { opts = {}; } this.isValue = isValue = (ref2 = opts.isValue) != null ? ref2 : false; this.isError = isError = (ref3 = opts.isError) != null ? ref3 : !isError; this.isFinal = isFinal = (ref4 = opts.isFinal) != null ? ref4 : false; this.final = this.isFinal ? this : opts.final; this.nonFinal = this.isFinal ? opts.nonFinal : this; this.value = this.isValue ? this : opts.value; this.error = this.isError ? this : opts.error; if (this.value == null) { this.value = new Operator({ isValue: true, isError: false, isFinal: isFinal, error: this }); } if (this.error == null) { this.error = new Operator({ isValue: false, isError: true, isFinal: isFinal, value: this }); } if (isError) { if (this.final == null) { this.final = this.value.final.error; } } if (this.final == null) { this.final = new Operator({ isValue: isValue, isError: isError, isFinal: true, nonFinal: this }); } if (isError) { if (this.nonFinal == null) { this.nonFinal = this.value.nonFinal.error; } } } return Operator; })(); ERROR = new Operator(); VALUE = ERROR.value; FINAL_ERROR = ERROR.final; FINAL_VALUE = VALUE.final; NO_MORE = {}; throwingFunction = function() {}; TRY = function(fn) { throwingFunction = fn; return tryingFunction; }; CATCH = { err: null }; tryingFunction = function() { var e; try { return throwingFunction.apply(this, arguments); } catch (_error) { e = _error; CATCH.err = e; return CATCH; } }; module.exports = axos = { Strategy: Strategy, Cell: Cell, TRY: TRY, CATCH: CATCH, send: send, io_send: io_send, afterIO: afterIO, ERROR: ERROR, VALUE: VALUE, FINAL_ERROR: FINAL_ERROR, FINAL_VALUE: FINAL_VALUE, NO_MORE: NO_MORE }; }).call(this);