UNPKG

gentyl

Version:

A Generator That You'll Love

352 lines (351 loc) 14.2 kB
var signals = require('signals'); var Gentyl; (function (Gentyl) { var ResolutionNode = (function () { function ResolutionNode(components, form, state) { if (form === void 0) { form = {}; } if (state === void 0) { state = {}; } this.depth = 0; this.isRoot = true; this.prepared = false; this.targeted = false; this.form = new Gentyl.GForm(form); var context = Gentyl.Util.deepCopy(state); this.ctx = new Gentyl.ResolutionContext(this, context, this.form.ctxmode); var inductor = this.inductComponent.bind(this); this.node = Gentyl.Util.typeCaseSplitF(inductor, inductor, null)(components); } ResolutionNode.prototype.inductComponent = function (component) { var c; if (component instanceof ResolutionNode) { c = component; } else if (component instanceof Object) { c = new ResolutionNode(component); } else { c = component; } return c; }; ResolutionNode.prototype.prepare = function (prepargs) { if (prepargs === void 0) { prepargs = null; } if (this.isAncestor) { throw Error("Ancestors cannot be prepared for resolution"); } this.ancestor = this.ancestor || this.replicate(); this.ancestor.isAncestor = true; if (!this.prepared) { this.prepared = true; this.ctx.prepare(); this.form.preparator.call(this.ctx, prepargs); this.prepareIO(); this.node = Gentyl.Util.typeCaseSplitF(this.prepareChild.bind(this, prepargs))(this.node); } else { this.ancestor = this.replicate(); this.ancestor.isAncestor = true; } return this; }; ResolutionNode.prototype.prepareChild = function (prepargs, child) { if (child instanceof ResolutionNode) { var replica = child.replicate(); replica.setParent(this); replica.prepare(prepargs); Gentyl.Util.parassoc(replica.inputNodes, this.inputNodes); Gentyl.Util.assoc(replica.outputNodes, this.outputNodes); return replica; } else { return child; } }; ResolutionNode.prototype.prepareIO = function () { this.inputNodes = {}; if (typeof (this.form.inputLabel) == 'string') { this.inputNodes[this.form.inputLabel] = [this]; } this.outputNodes = {}; if (typeof (this.form.outputLabel) == 'string') { this.outputNodes[this.form.outputLabel] = this; } }; ResolutionNode.prototype.replicate = function () { if (this.prepared) { return this.ancestor.replicate(); } else { var repl = new ResolutionNode(this.node, this.form.extract(), this.ctx.extract()); if (this.isAncestor) { repl.ancestor = this; } return repl; } }; ResolutionNode.prototype.bundle = function () { function bundler(node) { if (node instanceof ResolutionNode) { var product = node.bundle(); return product; } else { return node; } } var recurrentNodeBundle = Gentyl.Util.typeCaseSplitF(bundler, bundler, null)(this.node); var product = { node: recurrentNodeBundle, form: Gentyl.deformulate(this), state: this.ctx.extract() }; return product; }; ResolutionNode.prototype.getTargets = function (input, root) { function strtargs(targs, input, root) { var targets = {}; if (targs == undefined) { } else if (targs instanceof Array) { for (var i = 0; i < targs.length; i++) { var val = targs[i]; if (val in root.outputNodes) { targets[val] = root.outputNodes[val]; } } } else { if (targs in root.outputNodes) { targets[targs] = root.outputNodes[targs]; } } return targets; } if (typeof (this.form.targeting) == 'function') { return strtargs(this.form.targeting(input), input, root); } else { return strtargs(this.form.targeting, input, root); } }; ResolutionNode.prototype.shell = function () { if (!this.prepared) { throw new Error("unable to shell unprepared node"); } var root = this.getRoot(); root.form.inputLabel = root.form.inputLabel || "_"; root.form.outputLabel = root.form.outputLabel || "_"; root.outputNodes["_"] = root; root.inputNodes["_"] = [root]; var inpnodesmap = root.inputNodes; var outnodemap = root.outputNodes; var shell = { ins: {}, outs: {} }; for (var k in outnodemap) { shell.outs[k] = new signals.Signal(); } for (var k in inpnodesmap) { var v = { inps: inpnodesmap[k], root: root }; shell.ins[k] = function (data) { var allTargets = {}; var rootInput; for (var i = 0; i < this.inps.length; i++) { var inode = this.inps[i]; var iresult = inode.form.inputFunction.call(inode.ctx, data); if (inode == this.root) { rootInput = iresult; } var targets = inode.getTargets(data, this.root); Gentyl.Util.assoc(targets, allTargets); } if (Object.keys(allTargets).length == 0) { return; } for (var key in allTargets) { allTargets[key].targeted = true; } this.root.resolve(data); for (var key in allTargets) { allTargets[key].targeted = false; } }.bind(v); } root.signalShell = shell; return shell; }; ResolutionNode.prototype.getParent = function (toDepth) { if (toDepth === void 0) { toDepth = 1; } if (this.parent == undefined) { throw new Error("parent not set, or exceeding getParent depth"); } else if (toDepth == 1) { return this.parent; } else { return this.parent.getParent(toDepth - 1); } }; ResolutionNode.prototype.getRoot = function () { return this.isRoot ? this : this.getParent().getRoot(); }; ResolutionNode.prototype.getNominal = function (label) { if (this.form.contextLabel === label) { return this; } else { if (this.parent == undefined) { throw new Error("Required context label is not found"); } else { return this.parent.getNominal(label); } } }; ResolutionNode.prototype.setParent = function (parentNode) { this.parent = parentNode; this.isRoot = false; this.depth = this.parent.depth + 1; }; ResolutionNode.prototype.resolveArray = function (array, resolveArgs, selection) { if (selection instanceof Array) { var resolution = []; for (var i = 0; i < selection.length; i++) { resolution[i] = this.resolveNode(array[selection[i]], resolveArgs, true); } return resolution; } else { return this.resolveNode(array[selection], resolveArgs, true); } }; ResolutionNode.prototype.resolveObject = function (node, resolveArgs, selection) { if (selection instanceof Array) { var resolution = {}; for (var i = 0; i < selection.length; i++) { var k = selection[i]; resolution[k] = this.resolveNode(node[k], resolveArgs, true); } return resolution; } else { return this.resolveNode(node[selection], resolveArgs, true); } }; ResolutionNode.prototype.terminalScan = function (recursive, collection, locale) { if (recursive === void 0) { recursive = false; } if (collection === void 0) { collection = []; } if (locale === void 0) { locale = null; } var locale = locale || this; Gentyl.Util.typeCaseSplitF(function (thing, dereferent) { if (thing instanceof Gentyl.Terminal) { collection.push({ node: locale, term: thing, deref: dereferent }); } else if (recursive && thing instanceof ResolutionNode) { thing.terminalScan(true, collection, locale = thing); } })(this.node); return collection; }; ResolutionNode.prototype.checkComplete = function (recursive) { if (recursive === void 0) { recursive = false; } var result = true; Gentyl.Util.typeCaseSplitF(function (thing) { if (thing instanceof Gentyl.Terminal) { result = false; } else if (recursive && thing instanceof ResolutionNode) { thing.checkComplete(true); } })(this.node); return result; }; ResolutionNode.prototype.add = function (keyOrVal, val) { this.inductComponent(val); var al = arguments.length; var ins = null; if (!(al === 1 || al === 2)) { throw Error("Requires 1 or 2 arguments"); } else if (al === 1) { if (this.node instanceof Array) { ins = this.node.length; this.node.push(val); } else if (Gentyl.Util.isVanillaObject(this.node)) { throw Error("Requires key and value to add to object crown"); } else if (this.node instanceof Gentyl.Terminal) { if (this.node.check(val)) { this.node = val; } } else { throw Error("Unable to clobber existing value"); } } else { if (Gentyl.Util.isVanillaObject(this.node)) { ins = keyOrVal; this.node[keyOrVal] = val; } else { throw Error("Requires single arg for non object crown"); } } if (this.prepared) { this.node[ins] = this.prepareChild(null, this.node[ins]); } }; ResolutionNode.prototype.seal = function (typespec) { }; ResolutionNode.prototype.resolveNode = function (node, resolveArgs, selection) { var cut = false; if (!selection) { cut = true; } else if (selection === true && node instanceof Object) { selection = Object.keys(node); } if (node instanceof Array) { return cut ? [] : this.resolveArray(node, resolveArgs, selection); } else if (typeof (node) === "object") { if (node instanceof ResolutionNode) { return cut ? null : node.resolve(resolveArgs); } else { return cut ? {} : this.resolveObject(node, resolveArgs, selection); } } else { return cut ? null : node; } }; ResolutionNode.prototype.resolveUnderscore = function (resolver, resolveArgs) { var result = resolver.resolve(resolveArgs); return result; }; ResolutionNode.prototype.resolve = function (resolveArgs) { if (!this.prepared) { this.prepare(); } Object.freeze(resolveArgs); var carried = this.form.carrier.call(this.ctx, resolveArgs); var resolvedNode; if (this.node != undefined) { var selection = this.form.selector.call(this.ctx, Object.keys(this.node), resolveArgs); resolvedNode = this.resolveNode(this.node, carried, selection); } var result = this.form.resolver.call(this.ctx, resolvedNode, resolveArgs); if (this.targeted) { var outresult = this.form.outputFunction.call(this.ctx, result); this.getRoot().signalShell.outs[this.form.outputLabel].dispatch(outresult); } return result; }; return ResolutionNode; }()); Gentyl.ResolutionNode = ResolutionNode; })(Gentyl || (Gentyl = {}));