gentyl
Version:
A Generator That You'll Love
352 lines (351 loc) • 14.2 kB
JavaScript
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 = {}));