UNPKG

gorillascript

Version:

GorillaScript is a compile-to-JavaScript language designed to empower the user while attempting to prevent some common errors.

1,641 lines (1,640 loc) 145 kB
(function (GLOBAL) { "use strict"; var __arrayToIter, __cmp, __create, __curry, __first, __import, __indexOfIdentical, __isArray, __iter, __owns, __slice, __throw, __toArray, __typeof, _ref, ast, AstNode, Cache, GeneratorBuilder, GeneratorState, generatorTranslate, getPos, isPrimordial, MacroHolder, Map, ParserNode, primordialsBetterWithNew, Scope, translateLispyInternal, translateLispyOperator, Type; __arrayToIter = (function () { var proto; proto = { iterator: function () { return this; }, next: function () { var array, i; i = +this.index + 1; array = this.array; if (i >= array.length) { return { done: true, value: void 0 }; } else { this.index = i; return { done: false, value: array[i] }; } } }; return function (array) { var _o; if (!__isArray(array)) { throw new TypeError("Expected array to be an Array, got " + __typeof(array)); } _o = __create(proto); _o.array = array; _o.index = -1; return _o; }; }()); __cmp = function (left, right) { var type; if (left === right) { return 0; } else { type = typeof left; if (type !== "number" && type !== "string") { throw new TypeError("Cannot compare a non-number/string: " + type); } else if (type !== typeof right) { throw new TypeError("Cannot compare elements of different types: " + type + " vs " + typeof right); } else if (left < right) { return -1; } else { return 1; } } }; __create = typeof Object.create === "function" ? Object.create : function (x) { function F() {} F.prototype = x; return new F(); }; __curry = function (numArgs, f) { var currier; if (typeof numArgs !== "number") { throw new TypeError("Expected numArgs to be a Number, got " + __typeof(numArgs)); } if (typeof f !== "function") { throw new TypeError("Expected f to be a Function, got " + __typeof(f)); } if (numArgs > 1) { currier = function (args) { var ret; if (args.length >= numArgs) { return f.apply(this, args); } else { ret = function () { if (arguments.length === 0) { return ret; } else { return currier.call(this, args.concat(__slice.call(arguments))); } }; return ret; } }; return currier([]); } else { return f; } }; __first = function (x) { return x; }; __import = function (dest, source) { var k; for (k in source) { if (__owns.call(source, k)) { dest[k] = source[k]; } } return dest; }; __indexOfIdentical = function (array, item) { var _arr, check, i, inf; if (typeof item === "number") { if (item !== item) { for (_arr = __toArray(array), i = _arr.length; i--; ) { check = _arr[i]; if (check !== check) { return i; } } return -1; } else if (item === 0) { inf = 1 / item; for (_arr = __toArray(array), i = _arr.length; i--; ) { check = _arr[i]; if (check === 0 && 1 / check === inf) { return i; } } return -1; } } return array.indexOf(item); }; __isArray = typeof Array.isArray === "function" ? Array.isArray : (function (_toString) { return function (x) { return _toString.call(x) === "[object Array]"; }; }(Object.prototype.toString)); __iter = function (iterable) { if (iterable == null) { throw new TypeError("Expected iterable to be an Object, got " + __typeof(iterable)); } else if (__isArray(iterable)) { return __arrayToIter(iterable); } else if (typeof iterable.iterator === "function") { return iterable.iterator(); } else if (typeof iterable.next === "function") { return iterable; } else { throw new Error("Expected iterable to be an Array or an Object with an 'iterator' function or an Object with a 'next' function, got " + __typeof(iterable)); } }; __owns = Object.prototype.hasOwnProperty; __slice = Array.prototype.slice; __throw = function (x) { throw x; }; __toArray = function (x) { if (x == null) { throw new TypeError("Expected an object, got " + __typeof(x)); } else if (__isArray(x)) { return x; } else if (typeof x === "string") { return x.split(""); } else if (typeof x.length === "number") { return __slice.call(x); } else { throw new TypeError("Expected an object with a length property, got " + __typeof(x)); } }; __typeof = (function () { var _toString; _toString = Object.prototype.toString; return function (o) { if (o === void 0) { return "Undefined"; } else if (o === null) { return "Null"; } else { return o.constructor && o.constructor.name || _toString.call(o).slice(8, -1); } }; }()); Map = typeof GLOBAL.Map === "function" ? GLOBAL.Map : (Map = (function () { var _Map_prototype; function Map(iterable) { var _item, _iter, _this, x; _this = this instanceof Map ? this : __create(_Map_prototype); _this._keys = []; _this._values = []; if (iterable != null) { try { for (_iter = __iter(iterable); ; ) { _item = _iter.next(); if (_item.done) { break; } x = _item.value; _this.set(x[0], x[1]); } } finally { try { _iter.close(); } catch (_e) {} } } return _this; } _Map_prototype = Map.prototype; Map.displayName = "Map"; _Map_prototype.get = function (key) { var index; index = __indexOfIdentical(this._keys, key); if (index !== -1) { return this._values[index]; } }; _Map_prototype.has = function (key) { return __indexOfIdentical(this._keys, key) !== -1; }; _Map_prototype.set = function (key, value) { var index, keys; keys = this._keys; index = __indexOfIdentical(keys, key); if (index === -1) { index = keys.length; keys[index] = key; } this._values[index] = value; }; _Map_prototype["delete"] = function (key) { var index, keys; keys = this._keys; index = __indexOfIdentical(keys, key); if (index === -1) { return false; } else { keys.splice(index, 1); return this._values.splice(index, 1); } }; _Map_prototype.keys = function () { var _arr, _e, _i, _send, _state, _step, _this, _throw, key; _this = this; _state = 0; function _close() { _state = 3; } function _step(_received) { while (true) { switch (_state) { case 0: _arr = __toArray(_this._keys); _i = _arr.length; ++_state; case 1: _state = _i-- ? 2 : 3; break; case 2: key = _arr[_i]; _state = 1; return { done: false, value: key }; case 3: return { done: true, value: void 0 }; default: throw new Error("Unknown state: " + _state); } } } function _throw(_e) { _close(); throw _e; } function _send(_received) { try { return _step(_received); } catch (_e) { _throw(_e); } } return { close: _close, iterator: function () { return this; }, next: function () { return _send(void 0); }, send: _send, "throw": function (_e) { _throw(_e); return _send(void 0); } }; }; _Map_prototype.values = function () { var _arr, _e, _i, _send, _state, _step, _this, _throw, value; _this = this; _state = 0; function _close() { _state = 3; } function _step(_received) { while (true) { switch (_state) { case 0: _arr = __toArray(_this._values); _i = _arr.length; ++_state; case 1: _state = _i-- ? 2 : 3; break; case 2: value = _arr[_i]; _state = 1; return { done: false, value: value }; case 3: return { done: true, value: void 0 }; default: throw new Error("Unknown state: " + _state); } } } function _throw(_e) { _close(); throw _e; } function _send(_received) { try { return _step(_received); } catch (_e) { _throw(_e); } } return { close: _close, iterator: function () { return this; }, next: function () { return _send(void 0); }, send: _send, "throw": function (_e) { _throw(_e); return _send(void 0); } }; }; _Map_prototype.items = function () { var _arr, _e, _send, _state, _step, _this, _throw, i, key, values; _this = this; _state = 0; function _close() { _state = 3; } function _step(_received) { while (true) { switch (_state) { case 0: values = _this._values; _arr = __toArray(_this._keys); i = _arr.length; ++_state; case 1: _state = i-- ? 2 : 3; break; case 2: key = _arr[i]; _state = 1; return { done: false, value: [key, values[i]] }; case 3: return { done: true, value: void 0 }; default: throw new Error("Unknown state: " + _state); } } } function _throw(_e) { _close(); throw _e; } function _send(_received) { try { return _step(_received); } catch (_e) { _throw(_e); } } return { close: _close, iterator: function () { return this; }, next: function () { return _send(void 0); }, send: _send, "throw": function (_e) { _throw(_e); return _send(void 0); } }; }; _Map_prototype.iterator = Map.prototype.items; return Map; }())); ast = require("./jsast"); AstNode = ast.Node; Type = require("./types"); _ref = require("./parser"); MacroHolder = _ref.MacroHolder; ParserNode = _ref.Node; _ref = null; _ref = require("./utils"); Cache = _ref.Cache; isPrimordial = _ref.isPrimordial; _ref = null; function needsCaching(item) { return !(item instanceof ast.Ident) && !(item instanceof ast.Const) && !(item instanceof ast.This) && !(item instanceof ast.Arguments); } function isNothing(node) { return node instanceof ParserNode.Symbol.nothing; } Scope = (function () { var _Scope_prototype, getId; function Scope(options, macros, bound, usedTmps, helperNames, variables, tmps) { var _this; _this = this instanceof Scope ? this : __create(_Scope_prototype); if (options == null) { options = {}; } _this.options = options; _this.macros = macros; if (bound == null) { bound = false; } _this.bound = bound; if (usedTmps == null) { usedTmps = {}; } _this.usedTmps = usedTmps; if (helperNames == null) { helperNames = {}; } _this.helperNames = helperNames; if (tmps == null) { tmps = {}; } _this.tmps = tmps; if (variables) { _this.variables = __create(variables); } else { _this.variables = {}; } _this.hasBound = false; _this.usedThis = false; _this.id = getId(); return _this; } _Scope_prototype = Scope.prototype; Scope.displayName = "Scope"; getId = (function () { var id; id = -1; return function () { return ++id; }; }()); _Scope_prototype.maybeCache = function (item, type, func) { var ident, result; if (type == null) { type = Type.any; } if (!needsCaching(item)) { return func(item, item, false); } else { ident = this.reserveIdent(item.pos, "ref", type); result = func( ast.Assign(item.pos, ident, item), ident, true ); this.releaseIdent(ident); return result; } }; _Scope_prototype.maybeCacheAccess = function (item, func, parentName, childName, save) { var _this; _this = this; if (parentName == null) { parentName = "ref"; } if (childName == null) { childName = "ref"; } if (save == null) { save = false; } if (item instanceof ast.Binary && item.op === ".") { return this.maybeCache(item.left, Type.any, function (setParent, parent, parentCached) { return _this.maybeCache(item.right, Type.any, function (setChild, child, childCached) { if (parentCached || childCached) { return func( ast.Access(item.pos, setParent, setChild), ast.Access(item.pos, parent, child), true ); } else { return func(item, item, false); } }); }); } else { return func(item, item, false); } }; _Scope_prototype.reserveIdent = function (pos, namePart, type) { var _this; _this = this; if (namePart == null) { namePart = "ref"; } if (type == null) { type = Type.any; } return (function () { var i, ident, name; for (i = 1; ; ++i) { if (i === 1) { name = "_" + namePart; } else { name = "_" + namePart + i; } if (!(name in _this.usedTmps)) { _this.usedTmps[name] = true; ident = ast.Ident(pos, name); _this.addVariable(ident, type); return ident; } } }()); }; _Scope_prototype.reserveParam = function (pos) { var _this; _this = this; return (function () { var i, name; for (i = 1; ; ++i) { if (i === 1) { name = "_p"; } else { name = "_p" + i; } if (!(name in _this.usedTmps)) { _this.usedTmps[name] = true; return ast.Ident(pos, name); } } }()); }; _Scope_prototype.getTmp = function (pos, id, name, type) { var tmp, tmps; if (type == null) { type = Type.any; } tmps = this.tmps; if (id in tmps) { tmp = tmps[id]; if (tmp instanceof ast.Ident) { return tmp; } } return tmps[id] = this.reserveIdent(pos, name || "tmp", type); }; _Scope_prototype.releaseTmp = function (id) { var _ref, _ref2; if (__owns.call(this.tmps, id)) { this.releaseIdent((_ref = (_ref2 = this.tmps)[id], delete _ref2[id], _ref)); } }; _Scope_prototype.releaseTmps = function () { var _obj, id; _obj = this.tmps; for (id in _obj) { if (__owns.call(_obj, id)) { this.releaseTmp(id); } } this.tmps = {}; }; _Scope_prototype.releaseIdent = function (ident) { if (!__owns.call(this.usedTmps, ident.name)) { throw new Error("Trying to release a non-reserved ident: " + ident.name); } delete this.usedTmps[ident.name]; }; _Scope_prototype.markAsParam = function (ident) { this.variables[ident.name].isParam = true; }; _Scope_prototype.markAsFunction = function (ident) { this.variables[ident.name].isFunction = true; }; _Scope_prototype.addHelper = function (name) { this.helperNames[name] = true; }; _Scope_prototype.fillHelperDependencies = function () { var _arr, _else, _i, dep, helperNames, name, toAdd; helperNames = this.helperNames; toAdd = {}; while (true) { for (name in helperNames) { if (__owns.call(helperNames, name) && this.macros.hasHelper(name)) { for (_arr = __toArray(this.macros.helperDependencies(name)), _i = _arr.length; _i--; ) { dep = _arr[_i]; if (!__owns.call(helperNames, dep)) { toAdd[dep] = true; } } } } _else = true; for (name in toAdd) { if (__owns.call(toAdd, name)) { _else = false; this.addHelper(name); } } if (_else) { break; } helperNames = toAdd; toAdd = {}; } }; function lowerSorter(a, b) { return __cmp(a.toLowerCase(), b.toLowerCase()); } _Scope_prototype.getHelpers = function () { var _arr, _obj, k, names; _arr = []; _obj = this.helperNames; for (k in _obj) { if (__owns.call(_obj, k)) { _arr.push(k); } } names = _arr; return names.sort(lowerSorter); }; _Scope_prototype.hasHelper = function (name) { return __owns.call(this.helperNames, name); }; _Scope_prototype.addVariable = function (ident, type, isMutable) { if (type == null) { type = Type.any; } if (isMutable == null) { isMutable = false; } this.variables[ident.name] = { type: type, isMutable: isMutable }; }; _Scope_prototype.hasVariable = function (ident) { return ident.name in this.variables && typeof this.variables[ident.name] === "object" && this.variables[ident.name] !== null; }; _Scope_prototype.hasOwnVariable = function (ident) { return __owns.call(this.variables, ident.name); }; _Scope_prototype.isVariableMutable = function (ident) { var _ref; if ((_ref = this.variables[ident.name]) != null) { return _ref.isMutable; } }; _Scope_prototype.removeVariable = function (ident) { delete this.variables[ident.name]; }; _Scope_prototype.getVariables = function () { var _arr, _obj, k, v, variables; _arr = []; _obj = this.variables; for (k in _obj) { if (__owns.call(_obj, k)) { v = _obj[k]; if (!v.isParam && !v.isFunction) { _arr.push(k); } } } variables = _arr; return variables.sort(lowerSorter); }; _Scope_prototype.clone = function (bound) { if (bound) { this.hasBound = true; } return Scope( this.options, this.macros, bound, __create(this.usedTmps), this.helperNames, this.variables, __create(this.tmps) ); }; return Scope; }()); function makeHasGeneratorNode() { var inLoopCache, inSwitchCache, normalCache, returnFreeCache; inLoopCache = Cache(); function hasInLoop(node) { var _value; _value = inLoopCache.get(node); if (_value === void 0) { _value = (function () { var FOUND; if (node.isInternalCall()) { switch (node.func.internalId) { case 39: case 21: return true; case 13: return false; } } FOUND = {}; try { node.walk(function (n) { if (hasInLoop(n)) { throw FOUND; } return n; }); } catch (e) { if (e === FOUND) { return true; } else { throw e; } } return false; }()); inLoopCache.set(node, _value); } return _value; } inSwitchCache = Cache(); function hasInSwitch(node) { var _value; _value = inSwitchCache.get(node); if (_value === void 0) { _value = (function () { var _ref, FOUND; if (_ref = inLoopCache.get(node)) { return _ref; } if (node.isInternalCall()) { switch (node.func.internalId) { case 7: case 39: case 21: return true; case 13: return false; } } FOUND = {}; try { node.walk(function (n) { var check; if (n.isInternalCall("for", "forIn")) { check = hasInLoop; } else { check = hasInSwitch; } if (check(n)) { throw FOUND; } return n; }); } catch (e) { if (e === FOUND) { return true; } else { throw e; } } return false; }()); inSwitchCache.set(node, _value); } return _value; } returnFreeCache = Cache(); normalCache = Cache(); function hasGeneratorNode(node, allowReturn) { var _ref, _value; if (allowReturn == null) { allowReturn = false; } _value = (_ref = allowReturn ? returnFreeCache : normalCache).get(node); if (_value === void 0) { _value = (function () { var _ref, FOUND; if (!allowReturn && (_ref = returnFreeCache.get(node))) { return _ref; } if (_ref = inLoopCache.get(node)) { return _ref; } if (_ref = inSwitchCache.get(node)) { return _ref; } if (node.isInternalCall()) { switch (node.func.internalId) { case 4: case 7: case 39: return true; case 21: if (!allowReturn) { return true; } break; case 13: return false; } } FOUND = {}; try { node.walk(function (n) { var check; check = hasGeneratorNode; if (n.isInternalCall()) { switch (n.func.internalId) { case 12: case 11: check = hasInLoop; break; case 24: check = hasInSwitch; break; } } if (check(n, allowReturn)) { throw FOUND; } return n; }); } catch (e) { if (e === FOUND) { return true; } else { throw e; } } return false; }()); _ref.set(node, _value); } return _value; } return hasGeneratorNode; } function uid() { return Math.random().toString(36).slice(2) + "-" + new Date().getTime(); } GeneratorState = (function () { var _GeneratorState_prototype; function GeneratorState(builder) { var _this; _this = this instanceof GeneratorState ? this : __create(_GeneratorState_prototype); _this.builder = builder; _this.nodes = []; return _this; } _GeneratorState_prototype = GeneratorState.prototype; GeneratorState.displayName = "GeneratorState"; _GeneratorState_prototype.hasGeneratorNode = function (node) { return this.builder.hasGeneratorNode(node); }; _GeneratorState_prototype.add = function (tNode) { this.nodes.push(tNode); return this; }; _GeneratorState_prototype.branch = function () { var _ref, state; state = GeneratorState(this.builder); if (this.builder.currentCatch.length) { (_ref = this.builder.currentCatch)[_ref.length - 1].push(state); } this.builder.statesOrder.push(state); return state; }; _GeneratorState_prototype.caseId = function () { return this.builder.caseId(this.getRedirect()); }; _GeneratorState_prototype.makeGoto = function (pos, tState, includeBreak) { var _this; _this = this; if (includeBreak == null) { includeBreak = false; } return function () { var assign, caseId, state; state = tState(); if (state instanceof GeneratorState) { caseId = ast.Const(pos, state.caseId()); } else if (state instanceof ast.Node) { caseId = state; } else { throw new Error("Expected a GeneratorState or Node, got " + __typeof(state)); } if (caseId instanceof ast.Const && typeof caseId.value === "number" && caseId.value === +_this.caseId() + 1) { return ast.Unary(pos, "++", _this.builder.stateIdent); } else { assign = ast.Assign(pos, _this.builder.stateIdent, caseId); if (includeBreak) { return ast.Block(pos, [assign, ast.Break(pos)]); } else { return assign; } } }; }; _GeneratorState_prototype["yield"] = function (pos, tNode) { var branch; branch = this.branch(); this.nodes.push( this.makeGoto( pos, function () { return branch; }, false ), function () { return ast.Return(pos, ast.Obj(pos, [ ast.Obj.Pair(pos, "done", ast.Const(pos, false)), ast.Obj.Pair(pos, "value", tNode()) ])); } ); return branch; }; _GeneratorState_prototype["return"] = function (pos, tNode) { var _this; _this = this; if (tNode == null) { tNode = null; } if (tNode == null) { this.goto(pos, function () { return _this.builder.stop; }); } else { this.add(this.makeGoto( pos, function () { return _this.builder.stop; }, false )); this.add(function () { var node; node = tNode(); if (!(node instanceof ast.Statement)) { return ast.Return(pos, ast.Obj(pos, [ ast.Obj.Pair(pos, "done", ast.Const(pos, true)), ast.Obj.Pair(pos, "value", node) ])); } else { return node; } }); } }; _GeneratorState_prototype.getRedirect = function () { return this.builder.getRedirect(this); }; function getCaseId(pos, value) { if (value instanceof GeneratorState) { return ast.Const(pos, value.caseId()); } else if (value instanceof ast.Node) { return value; } else { throw new TypeError("Expected a GeneratorState or Node, got " + __typeof(value)); } } _GeneratorState_prototype.goto = function (pos, tState, preventRedirect) { var nodes; if (preventRedirect == null) { preventRedirect = false; } nodes = this.nodes; if (nodes.length === 0 && !preventRedirect) { this.builder.addRedirect(this, tState); } nodes.push(this.makeGoto( pos, function () { return getCaseId(pos, tState()); }, true )); }; _GeneratorState_prototype.noop = function (pos) { var branch; if (this.nodes.length === 0) { return this; } else { branch = this.branch(); this.goto(pos, function () { return branch; }); return branch; } }; _GeneratorState_prototype.gotoIf = function (pos, tTest, tWhenTrue, tWhenFalse) { var _this; _this = this; this.goto( pos, function () { return ast.IfExpression( pos, tTest(), getCaseId(pos, tWhenTrue()), getCaseId(pos, tWhenFalse()) ); }, true ); }; _GeneratorState_prototype.pendingFinally = function (pos, tFinallyBody) { var _this, ident, scope; _this = this; scope = this.builder.scope; ident = scope.reserveIdent(pos, "finally", Type["undefined"]["function"]()); scope.markAsFunction(ident); this.builder.finallies.push(function () { return ast.Func( pos, ident, [], [], tFinallyBody() ); }); this.nodes.push(function () { return ast.Call( pos, ast.Access(pos, _this.builder.pendingFinalliesIdent, "push"), [ident] ); }); return this; }; _GeneratorState_prototype.runPendingFinally = function (pos) { var _this; _this = this; this.nodes.push(function () { return ast.Call(pos, ast.Call(pos, ast.Access(pos, _this.builder.pendingFinalliesIdent, "pop"))); }); return this; }; _GeneratorState_prototype.enterTryCatch = function (pos) { var fresh; fresh = this.noop(pos); this.builder.enterTryCatch(fresh); return fresh; }; _GeneratorState_prototype.exitTryCatch = function (pos, tIdent, tPostState) { var fresh; this.goto(pos, tPostState); fresh = this.noop(pos); this.builder.exitTryCatch(fresh, tIdent); return fresh; }; return GeneratorState; }()); GeneratorBuilder = (function () { var _GeneratorBuilder_prototype; function GeneratorBuilder(pos, scope, hasGeneratorNode) { var _this, sendScope; _this = this instanceof GeneratorBuilder ? this : __create(_GeneratorBuilder_prototype); _this.pos = pos; _this.scope = scope; _this.hasGeneratorNode = hasGeneratorNode; _this.currentCatch = []; _this.redirects = Map(); _this.start = GeneratorState(_this); _this.stop = GeneratorState(_this).add(function () { return ast.Return(pos, ast.Obj(pos, [ ast.Obj.Pair(pos, "done", ast.Const(pos, true)), ast.Obj.Pair(pos, "value", ast.Const(pos, void 0)) ])); }); _this.statesOrder = [_this.start]; if (typeof stateIdent !== "undefined" && stateIdent !== null) { _this.stateIdent = stateIdent; } else { _this.stateIdent = scope.reserveIdent(pos, "state", Type.number); } _this.pendingFinalliesIdent = scope.reserveIdent(pos, "finallies", Type["undefined"]["function"]().array()); sendScope = scope.clone(false); _this.receivedIdent = sendScope.reserveIdent(pos, "received", Type.any); sendScope.markAsParam(_this.receivedIdent); _this.finallies = []; _this.catches = []; return _this; } _GeneratorBuilder_prototype = GeneratorBuilder.prototype; GeneratorBuilder.displayName = "GeneratorBuilder"; _GeneratorBuilder_prototype.addRedirect = function (fromState, toState) { this.redirects.set(fromState, toState); }; _GeneratorBuilder_prototype.getRedirect = function (fromState) { var redirect, redirectFunc; redirectFunc = this.redirects.get(fromState); if (redirectFunc == null) { return fromState; } else if (redirectFunc instanceof GeneratorState) { return redirectFunc; } else if (typeof redirectFunc === "function") { redirect = redirectFunc(); if (redirect instanceof GeneratorState) { redirect = this.getRedirect(redirect); } else { throw new Error("Expected a GeneratorState, got " + __typeof(redirectFunc)); } this.redirects.set(fromState, redirect); return redirect; } else { throw new Error("Unknown value in redirects: " + __typeof(redirectFunc)); } }; _GeneratorBuilder_prototype._calculateCaseIds = function () { var _arr, _i, _len, caseIds, id, state; id = -1; caseIds = this.caseIds = Map(); for (_arr = __toArray(this.statesOrder), _i = 0, _len = _arr.length; _i < _len; ++_i) { state = _arr[_i]; if (!this.redirects.has(state)) { caseIds.set(state, ++id); } } }; _GeneratorBuilder_prototype.caseId = function (state) { var caseIds; caseIds = this.caseIds; if (caseIds == null) { throw new Error("_calculate-case-ids must be called first"); } if (!caseIds.has(state)) { throw new Error("case-ids does not contain state"); } return caseIds.get(state); }; _GeneratorBuilder_prototype.enterTryCatch = function (state) { this.currentCatch.push([state]); }; _GeneratorBuilder_prototype.exitTryCatch = function (state, tIdent) { var catchStates, index; if (this.currentCatch.length === 0) { throw new Error("Unable to exit-try-catch without first using enter-try-catch"); } catchStates = this.currentCatch.pop(); index = catchStates.indexOf(state); if (index !== -1) { catchStates.splice(index, 1); } this.catches.push({ tryStates: catchStates, tIdent: tIdent, catchState: state }); }; function calculateRanges(stateIds) { var _arr, i, id, lastRangeId, len, ranges, rangeStart; ranges = []; rangeStart = -1/0; lastRangeId = -1; for (_arr = __toArray(stateIds), i = 0, len = _arr.length; i < len; ++i) { id = _arr[i]; if (id !== lastRangeId + 1) { if (lastRangeId !== -1) { ranges.push({ start: rangeStart, finish: lastRangeId }); } rangeStart = id; } lastRangeId = id; } if (lastRangeId !== -1) { ranges.push({ start: rangeStart, finish: lastRangeId }); } return ranges; } _GeneratorBuilder_prototype.create = function () { var _this, body, catches, close, err, f, innerScope, send, sendTryCatch, sendTryFinally, stateIdent, step, throwIdent; _this = this; if (this.currentCatch.length) { throw new Error("Cannot create a generator if there are stray catches"); } this.statesOrder.push(this.stop); this._calculateCaseIds(); body = [ ast.Assign(this.pos, this.stateIdent, ast.Const(this.pos, this.start.caseId())) ]; close = this.scope.reserveIdent(this.pos, "close", Type["undefined"]["function"]()); this.scope.markAsFunction(close); if (this.finallies.length === 0) { this.scope.removeVariable(this.pendingFinalliesIdent); body.push(ast.Func( this.pos, close, [], [], ast.Block(this.pos, [ast.Assign(this.pos, this.stateIdent, this.stop.caseId())]) )); } else { body.push(ast.Assign(this.pos, this.pendingFinalliesIdent, ast.Arr(this.pos))); body.push.apply(body, (function () { var _arr, _arr2, _i, _len, f; _arr = []; for (_arr2 = __toArray(_this.finallies), _i = 0, _len = _arr2.length; _i < _len; ++_i) { f = _arr2[_i]; _arr.push(f()); } return _arr; }())); innerScope = this.scope.clone(false); f = innerScope.reserveIdent(this.pos, "f", Type["undefined"]["function"]().union(Type["undefined"])); body.push(ast.Func( this.pos, close, [], innerScope.getVariables(), ast.Block(this.pos, [ ast.Assign(this.pos, this.stateIdent, this.stop.caseId()), ast.Assign(this.pos, f, ast.Call(this.pos, ast.Access(this.pos, this.pendingFinalliesIdent, "pop"))), ast.If(this.pos, f, ast.TryFinally( this.pos, ast.Call(this.pos, f), ast.Call(this.pos, close) )) ]) )); } err = this.scope.reserveIdent(this.pos, "e", Type.any); catches = this.catches; stateIdent = this.stateIdent; step = this.scope.reserveIdent(this.pos, "step", Type["function"]); send = this.scope.reserveIdent(this.pos, "send", Type["function"]); throwIdent = this.scope.reserveIdent(this.pos, "throw", Type["function"]); body.push(ast.Func( this.pos, step, [this.receivedIdent], [], ast.While(this.pos, true, ast.Switch( this.pos, stateIdent, (function () { var _arr, _arr2, _arr3, _arr4, _i, _i2, _len, _len2, i, node, nodes, state, tNode; _arr = []; for (_arr2 = __toArray(_this.statesOrder), _i = 0, _len = _arr2.length; _i < _len; ++_i) { state = _arr2[_i]; if (!_this.redirects.has(state)) { _arr3 = []; for (_arr4 = __toArray(state.nodes), _i2 = 0, _len2 = _arr4.length; _i2 < _len2; ++_i2) { tNode = _arr4[_i2]; _arr3.push(tNode()); } nodes = _arr3; i = 0; for (; i < nodes.length; ++i) { node = nodes[i]; if (node instanceof ast.Func && node.name != null) { body.push(node); nodes.splice(i, 1); --i; } } if (nodes.length === 0) { throw new Error("Found state with no nodes in it"); } _arr.push(ast.Switch.Case( nodes[0].pos, ast.Const(nodes[0].pos, state.caseId()), ast.Block(nodes[0].pos, nodes) )); } } return _arr; }()), ast.Throw(this.pos, ast.Call( this.pos, ast.Ident(this.pos, "Error"), [ast.Binary(this.pos, "Unknown state: ", "+", stateIdent)], true )) )) )); body.push(ast.Func( this.pos, throwIdent, [err], [], (function () { var _arr, _f, _i, current; current = ast.Block(_this.pos, [ ast.Call(_this.pos, close, []), ast.Throw(_this.pos, err) ]); for (_arr = __toArray(catches), _i = _arr.length, _f = function (catchInfo) { var _arr, _arr2, _i, _len, _this, errIdent, state, tryStateIds, tryStateRanges; _this = this; errIdent = catchInfo.tIdent(); this.scope.addVariable(errIdent); _arr = []; for (_arr2 = __toArray(catchInfo.tryStates), _i = 0, _len = _arr2.length; _i < _len; ++_i) { state = _arr2[_i]; if (!this.redirects.has(state)) { _arr.push(state.caseId()); } } tryStateIds = _arr; tryStateIds.sort(__curry(2, function (x, y) { return __cmp(x, y); })); tryStateRanges = calculateRanges(tryStateIds); return current = ast.If( this.pos, ast.Or.apply(ast, [this.pos].concat((function () { var _arr, _i, _len, _ref, finish, start; _arr = []; for (_i = 0, _len = tryStateRanges.length; _i < _len; ++_i) { _ref = tryStateRanges[_i]; start = _ref.start; finish = _ref.finish; _ref = null; if (start === -1/0) { if (finish === 0) { _arr.push(ast.Binary(_this.pos, stateIdent, "===", ast.Const(_this.pos, 0))); } else { _arr.push(ast.Binary(_this.pos, stateIdent, "<=", ast.Const(_this.pos, finish))); } } else if (finish === start) { _arr.push(ast.Binary(_this.pos, stateIdent, "===", ast.Const(_this.pos, start))); } else if (finish === +start + 1) { _arr.push(ast.Or( _this.pos, ast.Binary(_this.pos, stateIdent, "===", ast.Const(_this.pos, start)), ast.Binary(_this.pos, stateIdent, "===", ast.Const(_this.pos, finish)) )); } else { _arr.push(ast.And( _this.pos, ast.Binary(_this.pos, stateIdent, ">=", ast.Const(_this.pos, start)), ast.Binary(_this.pos, stateIdent, "<=", ast.Const(_this.pos, finish)) )); } } return _arr; }()))), ast.Block(this.pos, [ ast.Assign(this.pos, errIdent, err), ast.Assign(this.pos, stateIdent, ast.Const(this.pos, catchInfo.catchState.caseId())) ]), current ); }; _i--; ) { _f.call(_this, _arr[_i]); } return current; }()) )); sendTryCatch = ast.TryCatch( this.pos, ast.Return(this.pos, ast.Call(this.pos, step, [this.receivedIdent])), err, ast.Call(this.pos, throwIdent, [err]) ); if (this.finallies.length === 0) { sendTryFinally = sendTryCatch; } else { sendTryFinally = ast.TryFinally(this.pos, sendTryCatch, ast.If( this.pos, ast.Binary(this.pos, stateIdent, "===", this.stop.caseId()), ast.Call(this.pos, close, []) )); } body.push(ast.Func( this.pos, send, [this.receivedIdent], [], catches.length ? ast.While(this.pos, true, sendTryFinally) : sendTryFinally )); body.push(ast.Return(this.pos, ast.Obj(this.pos, [ ast.Obj.Pair(this.pos, "close", close), ast.Obj.Pair(this.pos, "iterator", ast.Func( this.pos, null, [], [], ast.Return(this.pos, ast.This(this.pos)) )), ast.Obj.Pair(this.pos, "next", ast.Func( this.pos, null, [], [], ast.Return(this.pos, ast.Call(this.pos, send, [ast.Const(this.pos, void 0)])) )), ast.Obj.Pair(this.pos, "send", send), ast.Obj.Pair(this.pos, "throw", ast.Func( this.pos, null, [err], [], ast.Block(this.pos, [ ast.Call(this.pos, throwIdent, [err]), ast.Return(this.pos, ast.Call(this.pos, send, [ast.Const(this.pos, void 0)])) ]) )) ]))); return ast.Block(this.pos, body); }; return GeneratorBuilder; }()); function flattenSpreadArray(elements) { var _arr, _i, _len, changed, element, node, result; result = []; changed = false; for (_arr = __toArray(elements), _i = 0, _len = _arr.length; _i < _len; ++_i) { element = _arr[_i]; if (element.isInternalCall("spread")) { node = element.args[0]; if (node.isInternalCall("array")) { result.push.apply(result, __toArray(node.args)); changed = true; } else { result.push(element); } } else { result.push(element); } } if (changed) { return flattenSpreadArray(result); } else { return elements; } } function makePos(line, column, file) { var pos; if (file == null) { file = void 0; } pos = { line: line, column: column }; if (file != null) { pos.file = file; } return pos; } getPos = function (node) { throw new Error("get-pos must be overridden"); }; function parseSwitch(args) { var _end, i, len, result; result = { topic: args[0], cases: [] }; len = args.length; for (i = 1, _end = len - 1; i < _end; i += 3) { result.cases.push({ node: args[i], body: args[i + 1], fallthrough: args[i + 2] }); } result.defaultCase = args[len - 1]; return result; } function doNothing() {} generatorTranslate = (function () { var _ref, generatorTranslateExpressionLispyInternals, generatorTranslateExpressionLispyOperators, generatorTranslateLispyInternals; function memoize(func) { var _ref, result; if (typeof func !== "function") { throw new TypeError("Expected func to be a Function, got " + __typeof(func)); } if (func.memoized) { return func; } else { _ref = function () { if (func) { result = func(); func = null; } return result; }; _ref.memoized = true; return _ref; } } function same(value) { function _ref() { return value; } _ref.memoized = true; return _ref; } function maybeMemoize(value) { if (typeof value === "function") { return memoize(value); } else { return same(value); } } function handleAssign(assignTo, scope, state, tNode, cleanup) { var nodeNeedsCaching, tAssignTo, tTmp; if (cleanup == null) { cleanup = doNothing; } if (typeof assignTo === "function") { tAssignTo = memoize(assignTo); return { state: state.add(function () { var node; node = tNode(); return ast.Assign(node.pos, tAssignTo(), node); }), tNode: tAssignTo, cleanup: cleanup }; } else if (assignTo) { tNode = memoize(tNode); tTmp = memoize(function () { return scope.reserveIdent(tNode().pos, "tmp", Type.any); }); nodeNeedsCaching = memoize(function () { return tNode() === state.builder.receivedIdent || needsCaching(tNode()); }); return { state: state.add(function () { var node; node = tNode(); if (nodeNeedsCaching()) { return ast.Assign(node.pos, tTmp(), node); } else { return node; } }), tNode: function () { if (nodeNeedsCaching()) { return tTmp(); } else { return tNode(); } }, cleanup: function () { cleanup(); if (nodeNeedsCaching()) { return scope.releaseIdent(tTmp()); } } }; } else { return { state: state, tNode: tNode, cleanup: cleanup }; } } function makeTTmp(assignTo, scope, pos, name, type) { if (name == null) { name = "tmp"; } if (type == null) { type = Type.any; } if (typeof assignTo === "function") { return memoize(assignTo); } else { return same(scope.reserveIdent(pos, name, type)); } } function makeCleanup(assignTo, scope, tTmp) { if (typeof assignTo === "function") { return function () { var tmp, value; value = assignTo(); tmp = tTmp(); if (value === tmp) { return scope.releaseIdent(tmp); } }; } else { return function () { return scope.releaseIdent(tTmp()); }; } } function hasSingleNodeWithNoopsNoSpread(nodes, state) { var _i, _len, count, node; count = 0; for (_i = 0, _len = nodes.length; _i < _len; ++_i) { node = nodes[_i]; if (node.isInternalCall("spread")) { return false; } else if (state.hasGeneratorNode(node)) { ++count; if (count > 1) { return false; } } else if (!node.isNoop()) { return false; } } return count === 1; } function generatorArrayTranslate(pos, elements, scope, state, assignTo) { var _arr, _f, _i, _len, _this, element, gExpr, i, tArrayStart, translatedNodes, tTmp; _this = this; tTmp = makeTTmp( assignTo, scope, pos, "arr", Type.array ); if (hasSingleNodeWithNoopsNoSpread(elements, state)) { gExpr = (function () { var _arr, _len, element, i; for (_arr = __toArray(elements), i = 0, _len = _arr.length; i < _len; ++i) { element = _arr[i]; if (!element.isNoop()) { return generatorTranslateExpression(element, scope, state, false); } } throw new Error("Unreachable state"); }()); translatedNodes = []; for (_arr = __toArray(elements), _i = 0, _len = _arr.length; _i < _len; ++_i) { element = _arr[_i]; if (state.hasGeneratorNode(element)) { translatedNodes.push(gExpr.tNode); } else { translatedNodes.push(translate(element, scope, "expression")); } } return { tNode: function () { return ast.Arr(pos, (function () { var _arr, _i, _len, tItem; _arr = [];