@effectful/transducers-loose
Version:
@effectful/transducers built with faster generators
755 lines (721 loc) • 18 kB
JavaScript
"use strict";
exports.__esModule = true;
exports.after = after;
exports.ancestors = ancestors;
exports.append = append;
exports.appendBlock = appendBlock;
exports.arr = arr;
exports.assign = assign;
exports.block = block;
exports.bool = bool;
exports.child = child;
exports.childArr = childArr;
exports.clone = clone;
exports.consume = consume;
exports.consumeRange = consumeRange;
exports.detach = detach;
exports.dft = dft;
exports.empty = empty;
exports.error = error;
exports.fromIterable = fromIterable;
exports.hier = hier;
exports.id = id;
exports.insertAfter = insertAfter;
exports.insertBefore = insertBefore;
exports.lookahead = lookahead;
exports.next = next;
exports.node = node;
exports.num = num;
exports.prepend = prepend;
exports.prev = prev;
exports.produce = produce;
exports.produceNode = produceNode;
exports.replace = replace;
exports.resetFieldInfo = resetFieldInfo;
exports.result = result;
exports.share = share;
exports.skip = skip;
exports.str = str;
exports.toArray = toArray;
exports.tok = tok;
var _types = require("./types");
var _config = require("./config");
var M = require("@effectful/es-rt/opts/loose");
/*
* drafts for the next version
*
* V2 (unlike V1) doesn't have tokens wraps all information
* is stored directly in the Value, no entering and closing tokens
*
* # DOM-like AST representation
*
* type Value = {
* pos: Pos,
* type: Type,
* node: BabelNode,
* parent: Value | null,
* id: number,
* nextSibling: Value,
* prevSibling: Value,
* // .....
* }
*
*/
let valCount = 0;
function empty() {
var res;
res = {
type: _types.Tag.Empty,
pos: _types.Tag.Empty,
id: valCount++,
level: 0,
node: null,
parent: null,
data: null
//pure: false
};
res.prevSibling = res;
res.nextSibling = res;
res.firstChild = null;
return res;
}
/**
* detaches `node` from the tree
*/
function detach(node) {
const {
nextSibling,
parent
} = node;
(nextSibling.prevSibling = node.prevSibling).nextSibling = nextSibling;
if (parent && parent.firstChild === node) {
if (nextSibling === node) parent.firstChild = null;else parent.firstChild = nextSibling;
}
node.nextSibling = node.prevSibling = node;
node.parent = null;
return node;
}
/** inserts sibling `node` after `pos` node */
function insertAfter(pos, node) {
const {
nextSibling
} = pos;
node.prevSibling = pos;
node.nextSibling = nextSibling;
nextSibling.prevSibling = pos.nextSibling = node;
node.parent = pos.parent;
return node;
}
/**
* inserts sibling `child` before `pos`
* - expects `last` of the both nodes
*/
function insertBefore(pos, node) {
const {
prevSibling
} = pos;
node.nextSibling = pos;
node.prevSibling = prevSibling;
prevSibling.nextSibling = pos.prevSibling = node;
const parent = pos.parent;
node.parent = parent;
if (parent.firstChild === pos) parent.firstChild = node;
return node;
}
/** makes `child` to be the last child of `parent` */
function append(parent, child) {
const old = parent.firstChild;
if (old) return insertAfter(old.prevSibling, child);
child.parent = parent;
return parent.firstChild = child;
}
/** makes `child` to be the first child of `parent` */
function prepend(parent, child) {
const old = parent.firstChild;
if (old) return insertBefore(old, child);
child.parent = parent;
parent.firstChild = child;
return child;
}
/**
* replaces node `from` by `to`
* - expects `last` of both
*/
function replace(from, to) {
insertAfter(from, to);
detach(from);
return to;
}
/** builds default DOM node */
function node(pos, type) {
return tok(pos, type, {
type: ""
});
}
/** builds DOM node for `=` assignments */
function assign(pos) {
return tok(pos, _types.Tag.AssignmentExpression, {
operator: "="
});
}
/** builds DOM node for an identifier with symbol */
function id(pos, sym) {
var res;
res = node(pos, _types.Tag.Identifier);
res.sym = sym;
return res;
}
/** builds DOM node for array */
function arr(pos) {
return tok(pos, _types.Tag.Array, [], null);
}
function childArr(pos, par) {
var res;
res = tok(pos, _types.Tag.Array, [], null);
append(par, res);
return res;
}
function block(pos, par) {
var res;
res = node(pos, _types.Tag.BlockStatement);
append(res, arr(_types.Tag.body));
append(par, res);
return res;
}
function appendBlock(pos, par) {
var block, res;
block = node(pos, _types.Tag.BlockStatement);
res = childArr(_types.Tag.body, block);
append(par, block);
return res;
}
/** builds DOM node for a numeric constant */
function num(pos, value) {
return tok(pos, _types.Tag.NumericLiteral, {
value
});
}
/** builds DOM node for a string constant */
function str(pos, value) {
return tok(pos, _types.Tag.StringLiteral, {
value
});
}
/** builds DOM node for a boolean constant */
function bool(pos, value) {
return tok(pos, _types.Tag.BooleanLiteral, {
value
});
}
/** builds DOM node */
function tok(pos, type, node) {
const res = empty();
res.pos = pos;
res.type = type;
res.node = node;
return res;
}
/* same as `tok` but also sets `parent` */
function child(pos, type, node, parent) {
const res = tok(pos, type, node);
res.parent = parent;
return res;
}
function Share(inner) {
this.inner = inner[Symbol.iterator]();
}
Share.prototype[Symbol.iterator] = function () {
return this;
};
Share.prototype.next = function () {
return this.inner.next();
};
/** returns same iterable which ignores `return` method call */
function share(inner) {
return new Share(inner);
}
function hierImpl(s) {
var last,
i,
level,
j,
till,
hierImpl = M.generator(),
loop,
r,
p;
hierImpl.step = hierImpl_1;
hierImpl.$step = 3;
return hierImpl;
function hierImpl_1(p) {
for (;;) {
switch (hierImpl.$cur = hierImpl.$step) {
case 3:
last = null;
loop = M.iterator(s);
hierImpl.$step = 4;
hierImpl.$step = 4;
continue;
case 4:
if (!(loop = loop.step()).done) {
i = loop.value;
level = i.level = i.parent ? i.parent.level + 1 : 0;
if (last) {
j = level;
till = last.level;
hierImpl.$step = 5;
hierImpl.$step = 5;
continue;
} else {
hierImpl.$step = 7;
hierImpl.$step = 7;
continue;
}
} else {
hierImpl.$step = 8;
hierImpl.$step = 8;
continue;
}
case 5:
if (j <= till) {
hierImpl.$step = 6;
hierImpl.value = {
start: false,
value: last
};
return hierImpl;
} else {
hierImpl.$step = 7;
hierImpl.$step = 7;
continue;
}
case 6:
++j, last = last.parent;
hierImpl.$step = 5;
hierImpl.$step = 5;
continue;
case 7:
last = i;
hierImpl.$step = 4;
hierImpl.value = {
start: true,
value: i
};
return hierImpl;
case 8:
if (last && last.pos !== _types.Tag.root) {
hierImpl.$step = 9;
hierImpl.value = {
start: false,
value: last
};
return hierImpl;
} else {
hierImpl.$step = 0;
hierImpl.value = void 0;
hierImpl.done = true;
return hierImpl;
}
case 9:
last = last.parent;
hierImpl.$step = 8;
hierImpl.$step = 8;
continue;
case 0:
hierImpl.$step = 0;
hierImpl.value = p;
hierImpl.done = true;
return hierImpl;
case 1:
hierImpl.$step = 0;
throw p;
default:
throw new Error("invalid state");
}
}
}
}
/**
* converts each element of `s:Iterable<Value>` into two elements
* `{start:boolean,value:Value}` with `start:true` on entering the token
* and `start:false` on exit
*/
function hier(inner) {
return share(hierImpl(inner));
}
function Reset(inner) {
const iter = this.inner = inner[Symbol.iterator]();
const item = iter.next();
if (item.done) {
this.first = this.buf = null;
return;
}
const buf = item.value;
const first = buf.parent;
buf.prev = first;
first.next = buf;
first.level = 0;
this.buf = buf;
this.first = first;
this.levels = [first, null];
}
Reset.prototype[Symbol.iterator] = function () {
return this;
};
Reset.prototype.next = function () {
const value = this.step();
return value ? {
done: false,
value
} : {
done: true
};
};
Reset.prototype.step = function step() {
const cur = this.buf;
if (!cur) return null;
const nextItem = this.inner.next();
const levels = this.levels;
if (nextItem.done) {
const first = this.first;
cur.nextSibling = first;
this.buf = null;
return cur;
}
const next = nextItem.value;
const level = next.parent.level + 1;
const prevSibling = levels[level];
levels[level] = cur;
if (prevSibling) {
prevSibling.nextSibling = next;
next.prevSibling = prevSibling;
} else {
next.parent.firstChild = next;
next.prevSibling = next;
}
levels[level + 1] = null;
this.buf = next;
cur.nextSibling = next;
return cur;
};
/**
* takes an iterable of values and returns another iterable
* with same elements but all the DOM fields re-calculated
* this calculates only 1 token ahead
*/
function lookahead(s) {
return new Reset(s);
}
/**
* converts AST `node` into the AST representation with
*/
function produceNode(pos, babelNode) {
var res, i, type, keys, _res, _i, v;
if (Array.isArray(babelNode)) {
res = arr(pos);
var loop = M.iterator(babelNode);
for (; !(loop = loop.step()).done;) {
i = loop.value;
append(res, i ? produceNode(_types.Tag.push, i) : tok(_types.Tag.push, _types.Tag.Null, null));
}
return res;
}
type = babelNode.type;
keys = _types.VISITOR_KEYS[type];
_res = tok(pos, _types.Tag[type], babelNode);
if (keys.length) {
var _loop = M.iterator(keys);
for (; !(_loop = _loop.step()).done;) {
_i = _loop.value;
v = babelNode[_i];
if (v != null) append(_res, produceNode(_types.Tag[_i], v));
}
}
return _res;
}
/** next node strictly after `node` */
function after(node) {
for (let i = node;;) {
const {
parent,
nextSibling
} = i;
if (!parent) return nextSibling;
if (nextSibling !== parent.firstChild) return nextSibling;
i = parent;
}
}
/** next node in DFT order after `node` */
function next(node) {
return node.firstChild || after(node);
}
/** prev node in DFT order before `node` */
function prev(node) {
const {
parent
} = node;
if (parent && parent.firstChild === node) return parent;
for (let i = node.prevSibling;;) {
const {
firstChild
} = i;
if (!firstChild) return i;
i = firstChild.prevSibling;
}
}
/** traverses range [from,to) */
function dft(from, to = from.nextSibling) {
var i,
n,
dft = M.generator(),
a,
r,
p;
dft.step = dft_1;
dft.$step = 3;
return dft;
function dft_1(p) {
for (;;) {
switch (dft.$cur = dft.$step) {
case 3:
i = from;
a = true;
dft.$step = 4;
dft.$step = 4;
continue;
case 4:
if (a) {
n = next(i);
dft.$step = 5;
dft.value = i;
return dft;
} else {
dft.$step = 0;
dft.value = void 0;
dft.done = true;
return dft;
}
case 5:
i = n;
a = i !== to;
dft.$step = 4;
dft.$step = 4;
continue;
case 0:
dft.$step = 0;
dft.value = p;
dft.done = true;
return dft;
case 1:
dft.$step = 0;
throw p;
default:
throw new Error("invalid state");
}
}
}
}
/**
* like `produce` but wraps the resulting node with `Tag.root` element
*/
function produce(babelNode) {
var root;
root = node(_types.Tag.root, _types.Tag.Root);
append(root, produceNode(_types.Tag.top, babelNode));
return root;
}
/**
* converts DOM root node into a babel AST node
*/
function consume(root) {
consumeRange(root.firstChild, root);
return root.firstChild.node;
}
/**
* resets babel AST properties in [from..to) range
*/
function consumeRange(from, to) {
var i, parent, node, ti;
var loop = M.iterator(dft(from, to));
for (; !(loop = loop.step()).done;) {
i = loop.value;
({
parent,
node
} = i);
if (parent) {
if (i.pos === _types.Tag.push) {
parent.node.push(node);
} else parent.node[(0, _types.symName)(i.pos)] = node;
}
if (i.type === _types.Tag.Array) node.length = 0;else if (i.type === _types.Tag.Null) i.node = null;else {
ti = (0, _types.symInfo)(i.type);
if (ti) {
if (ti.esType != null) i.node.type = ti.esType;
if (ti.fields) Object.assign(i.node, ti.fields);
}
}
}
}
/**
* Resets `fieldInfo` field in each `value`.
* The field descripts AST node context.
*/
function resetFieldInfo(root) {
var i, f, ti;
root.typeInfo = (0, _types.typeInfo)(root);
i = root;
do {
f = i.parent && i.parent.typeInfo;
if (f && f.fieldsMap) f = i.fieldInfo = f.fieldsMap.get(i.pos);
ti = f && f.ti || (0, _types.typeInfo)(i);
switch (i.type) {
case _types.Tag.Array:
ti = f;
break;
case _types.Tag.ArrayPattern:
ti = f && f.declVar ? _types.arrayPattern : _types.arrayAssignmentPattern;
break;
case _types.Tag.ObjectPattern:
ti = f && f.declVar ? _types.objectPattern : _types.objectAssignmentPattern;
break;
case _types.Tag.RestElement:
ti = f && f.declVar ? _types.restElement : _types.restElementAssignment;
break;
case _types.Tag.AssignmentExpression:
ti = i.node.operator === "=" ? _types.assignmentOpEq : _types.assignmentOpDefault;
break;
case _types.Tag.ObjectProperty:
if (i.node.computed) ti = ti.propAlt;else if (f && f.declVar) ti = _types.assignmentProperty;
break;
case _types.Tag.AssignmentPattern:
if (!f || !f.declVar) ti = (0, _types.symInfo)(_types.Tag.AssignmentExpression);
break;
case _types.Tag.MemberExpression:
case _types.Tag.ObjectMethod:
case _types.Tag.ClassProperty:
case _types.Tag.ClassMethod:
case _types.Tag.ClassPrivateMethod:
case _types.Tag.ClassPrivateProperty:
if (i.node.computed) ti = ti.propAlt;
break;
}
i.typeInfo = ti;
} while ((i = next(i)) !== root);
return root;
}
/** runs iterable `s` and ignores its output, returns its result */
function skip(s) {
const iter = s[Symbol.iterator]();
let item;
for (; !(item = iter.next()).done;) {}
return item.value;
}
function error(msg, doc) {
const file = _config.default.babelFile;
if (!file) return new SyntaxError(msg);
for (let i = doc; i; i = i.parent) {
if (i.node.loc || i.node._loc) return file.buildCodeFrameError(i.node, msg);
}
return file.buildCodeFrameError(doc.node, msg);
}
/** same as `Array.from` but outputs the array into `buf` and returns iterable result */
function result(s, buf) {
const iter = s[Symbol.iterator]();
let item;
while (!(item = iter.next()).done) buf.push(item.value);
return item.value;
}
/**
* same as `Array.from` but returns `s` if it is already `Array`
*/
function toArray(s) {
if (Array.isArray(s)) return s;
const res = [];
result(s, res);
return res;
}
/** converts stream to a fully calculated DOM node */
function fromIterable(s) {
const iter = lookahead(s);
while (iter.step()) {}
return iter.first;
}
/** returns all ancestors of `node` (until and including root) */
function ancestors(value) {
var i,
ancestors = M.generator(),
r,
p;
ancestors.step = ancestors_1;
ancestors.$step = 3;
return ancestors;
function ancestors_1(p) {
for (;;) {
switch (ancestors.$cur = ancestors.$step) {
case 3:
i = value.parent;
ancestors.$step = 4;
ancestors.$step = 4;
continue;
case 4:
if (i) {
ancestors.$step = 5;
ancestors.value = i;
return ancestors;
} else {
ancestors.$step = 0;
ancestors.value = void 0;
ancestors.done = true;
return ancestors;
}
case 5:
i = i.parent;
ancestors.$step = 4;
ancestors.$step = 4;
continue;
case 0:
ancestors.$step = 0;
ancestors.value = p;
ancestors.done = true;
return ancestors;
case 1:
ancestors.$step = 0;
throw p;
default:
throw new Error("invalid state");
}
}
}
}
function clone(doc) {
var i, node, data, res;
if (!doc) return doc;
i = doc;
do {
node = i.node;
i.data = {
...i,
node: Array.isArray(node) ? [...node] : {
...node
},
id: valCount++
};
} while ((i = next(i)) !== doc);
i = doc;
do {
({
data
} = i);
if (i.parent) data.parent = i.parent.data;
if (i.firstChild) data.firstChild = i.firstChild.data;
data.prevSibling = i.prevSibling.data;
data.nextSibling = i.nextSibling.data;
} while ((i = next(i)) !== doc);
res = doc.data;
do {
i.data = null;
} while ((i = next(i)) !== doc);
res.prevSibling = res.nextSibling = res;
return res;
}