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
JavaScript
(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 = [];