elliptical
Version:
Interactive natural-language interfaces
449 lines (346 loc) • 14.2 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _regenerator = require('babel-runtime/regenerator');
var _regenerator2 = _interopRequireDefault(_regenerator);
var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
var _typeof2 = require('babel-runtime/helpers/typeof');
var _typeof3 = _interopRequireDefault(_typeof2);
var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');
var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
exports.default = compile;
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _utils = require('./utils');
var _phrases = require('./phrases');
var phrases = _interopRequireWildcard(_phrases);
var _option = require('./option');
var _option2 = _interopRequireDefault(_option);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _marked = [postProcess].map(_regenerator2.default.mark);
function applyDefaults(element) {
return _lodash2.default.assign({}, element, {
props: _lodash2.default.defaults({}, element.props, element.type.defaultProps || {})
});
}
function compileAndAddToMap(subElement, process, elementMap, _ref) {
var errors = _ref.errors;
var traverse = compileNonRoot(subElement, process, { errors: errors });
elementMap.set(subElement, traverse);
return traverse;
}
function next(elementMap, process, subElement, option, _ref2) {
var errors = _ref2.errors;
var traverser = elementMap.get(subElement);
if (traverser) {
return traverser(option);
} else {
var newTraverser = compileAndAddToMap(subElement, process, elementMap, { errors: errors });
return newTraverser(option);
}
}
function compileProp(prop, process, elementMap, _ref3) {
var errors = _ref3.errors;
if (prop && prop.type && prop.props && prop.children && (_lodash2.default.isPlainObject(prop.type) || _lodash2.default.isString(prop.type)) && _lodash2.default.isPlainObject(prop.props) && _lodash2.default.isArray(prop.children)) {
// We can be pretty sure this is an element,
return compileAndAddToMap(prop, process, elementMap, { errors: errors });
} else {
return prop;
}
}
function getPhrase(element) {
return _lodash2.default.isString(element.type) ? phrases[element.type] : element.type;
}
function tryRunning(func, errors, messages) {
var defaultIfError = arguments.length <= 3 || arguments[3] === undefined ? null : arguments[3];
if (errors === 'log') {
try {
return func();
} catch (e) {
var _console;
(_console = console).error.apply(_console, (0, _toConsumableArray3.default)(messages).concat([e]));
return defaultIfError;
}
} else {
return func();
}
}
function compileNonRoot(element, process, _ref4) {
var errors = _ref4.errors;
// ignore null elements
if (element == null) return function () {
return [];
};
// assign defaultProps
element = applyDefaults(element);
if (process) {
element = tryRunning(function () {
return process(element);
}, errors, ['An error occurred processing', element]);
// allow process calls to nullify elements
if (element == null) return function () {
return [];
};
}
var phrase = getPhrase(element);
// call describe
if (phrase.describe) {
if (phrase.lazy === false) {
var description = tryRunning(function () {
return phrase.describe(element);
}, errors, ['An error occurred describing', element]);
var _traverse = compileNonRoot(description, process, { errors: errors });
return addOutbound(element, _traverse, { errors: errors });
} else {
var _ret = function () {
var subTraverse = void 0;
var traverse = function traverse(input) {
if (!subTraverse) {
var _description = tryRunning(function () {
return phrase.describe(element);
}, errors, ['An error occurred dynamically describing', element]);
subTraverse = compileNonRoot(_description, process, { errors: errors });
}
return subTraverse(input);
};
return {
v: addOutbound(element, traverse, { errors: errors })
};
}();
if ((typeof _ret === 'undefined' ? 'undefined' : (0, _typeof3.default)(_ret)) === "object") return _ret.v;
}
}
var elementMap = new Map();
// if there's no describe, check to see if any props are elements
// and compile those
_lodash2.default.forEach(element.props, function (prop) {
return compileProp(prop, process, elementMap, { errors: errors });
});
// generate the traverse thunk
_lodash2.default.forEach(element.children, function (child) {
return compileAndAddToMap(child, process, elementMap, { errors: errors });
});
var subTraverse = function subTraverse(subElem, option) {
return next(elementMap, process, subElem, option, { errors: errors });
};
var traverse = function traverse(option) {
return tryRunning(function () {
return phrase.visit(option, element, subTraverse);
}, errors, ['An error occurred visiting', element], []);
};
return addOutbound(element, traverse, { errors: errors });
}
function addOutbound(element, traverse, _ref5) {
var errors = _ref5.errors;
return _regenerator2.default.mark(function _callee(option) {
var _this = this;
var start, mods, newOption, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _loop, _iterator, _step, _ret2;
return _regenerator2.default.wrap(function _callee$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
start = option.words.length;
mods = {};
if (element.props.data != null) {
mods.data = _lodash2.default.concat(option.data, [element.props.data]);
}
newOption = _lodash2.default.assign({}, option, mods);
_iteratorNormalCompletion = true;
_didIteratorError = false;
_iteratorError = undefined;
_context2.prev = 7;
_loop = _regenerator2.default.mark(function _loop() {
var output, newResult, filterResultResult, end, mods;
return _regenerator2.default.wrap(function _loop$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
output = _step.value;
if (!(0, _utils.isComplete)(output)) {
_context.next = 7;
break;
}
if (element.type.mapResult) {
newResult = tryRunning(function () {
return element.type.mapResult(output.result, element);
}, errors, ['An error occurred in mapResult of', element], output.result);
output = _lodash2.default.assign({}, output, { result: newResult });
}
if (!element.type.filterResult) {
_context.next = 7;
break;
}
filterResultResult = tryRunning(function () {
return element.type.filterResult(output.result, element);
}, errors, ['An error occurred in filterResult of', element], true);
if (filterResultResult) {
_context.next = 7;
break;
}
return _context.abrupt('return', 'continue');
case 7:
end = output.words.length;
mods = {};
if (element.props.value != null) {
mods.result = element.props.value;
}
if (element.props.score != null) {
mods.score = element.props.score;
}
if (element.props.multiplier != null) {
mods.score = element.props.multiplier * (element.props.score == null ? output.score : element.props.score);
}
_lodash2.default.forEach([['qualifiers', 'qualifier'], ['arguments', 'argument'], ['annotations', 'annotation'], ['categories', 'category']], function (_ref6) {
var _ref7 = (0, _slicedToArray3.default)(_ref6, 2);
var plural = _ref7[0];
var singular = _ref7[1];
if (element.props[plural] != null || element.props[singular] != null) {
var theseAdditions = element.props[plural] || [element.props[singular]];
var outputAdditions = _lodash2.default.map(theseAdditions, function (addition) {
return { value: addition, start: start, end: end };
});
mods[plural] = _lodash2.default.concat(outputAdditions, output[plural]);
}
});
_context.next = 15;
return _lodash2.default.assign({}, output, mods);
case 15:
case 'end':
return _context.stop();
}
}
}, _loop, _this);
});
_iterator = traverse(newOption)[Symbol.iterator]();
case 10:
if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
_context2.next = 18;
break;
}
return _context2.delegateYield(_loop(), 't0', 12);
case 12:
_ret2 = _context2.t0;
if (!(_ret2 === 'continue')) {
_context2.next = 15;
break;
}
return _context2.abrupt('continue', 15);
case 15:
_iteratorNormalCompletion = true;
_context2.next = 10;
break;
case 18:
_context2.next = 24;
break;
case 20:
_context2.prev = 20;
_context2.t1 = _context2['catch'](7);
_didIteratorError = true;
_iteratorError = _context2.t1;
case 24:
_context2.prev = 24;
_context2.prev = 25;
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
case 27:
_context2.prev = 27;
if (!_didIteratorError) {
_context2.next = 30;
break;
}
throw _iteratorError;
case 30:
return _context2.finish(27);
case 31:
return _context2.finish(24);
case 32:
case 'end':
return _context2.stop();
}
}
}, _callee, this, [[7, 20, 24, 32], [25,, 27, 31]]);
});
}
function compile(element, process) {
var _ref8 = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
var _ref8$errors = _ref8.errors;
var errors = _ref8$errors === undefined ? 'none' : _ref8$errors;
var compiled = compileNonRoot(element, process, { errors: errors });
return function traverse(input) {
var postProcessed = postProcess(compiled, input);
var allOutputs = Array.from(postProcessed);
return _lodash2.default.sortBy(allOutputs, function (output) {
return -output.score;
});
};
}
function postProcess(compiled, input) {
var option, outputs, _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, _output, newOutput;
return _regenerator2.default.wrap(function postProcess$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
option = (0, _option2.default)({ text: input });
outputs = compiled(option);
_iteratorNormalCompletion2 = true;
_didIteratorError2 = false;
_iteratorError2 = undefined;
_context3.prev = 5;
_iterator2 = outputs[Symbol.iterator]();
case 7:
if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) {
_context3.next = 18;
break;
}
_output = _step2.value;
if (!(_output.text === '' || _output.text == null)) {
_context3.next = 15;
break;
}
_lodash2.default.forEach(_output.callbacks, function (callback) {
return callback();
});
newOutput = _lodash2.default.clone(_output);
delete newOutput.callbacks;
_context3.next = 15;
return newOutput;
case 15:
_iteratorNormalCompletion2 = true;
_context3.next = 7;
break;
case 18:
_context3.next = 24;
break;
case 20:
_context3.prev = 20;
_context3.t0 = _context3['catch'](5);
_didIteratorError2 = true;
_iteratorError2 = _context3.t0;
case 24:
_context3.prev = 24;
_context3.prev = 25;
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
case 27:
_context3.prev = 27;
if (!_didIteratorError2) {
_context3.next = 30;
break;
}
throw _iteratorError2;
case 30:
return _context3.finish(27);
case 31:
return _context3.finish(24);
case 32:
case 'end':
return _context3.stop();
}
}
}, _marked[0], this, [[5, 20, 24, 32], [25,, 27, 31]]);
}