UNPKG

@effectful/transducers-loose

Version:

@effectful/transducers built with faster generators

755 lines (721 loc) 18 kB
"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; }