hyperformula-dc
Version:
HyperFormula is a JavaScript engine for efficient processing of spreadsheet-like data and formulas
414 lines (312 loc) • 15.5 kB
JavaScript
"use strict";
require("core-js/modules/es.regexp.exec.js");
require("core-js/modules/es.string.split.js");
require("core-js/modules/es.array.slice.js");
require("core-js/modules/es.function.name.js");
exports.__esModule = true;
exports.Condition = exports.CriterionFunctionCompute = void 0;
require("regenerator-runtime/runtime.js");
require("core-js/modules/es.array.map.js");
require("core-js/modules/es.array.join.js");
require("core-js/modules/web.dom-collections.for-each.js");
require("core-js/modules/es.array.from.js");
require("core-js/modules/es.string.iterator.js");
require("core-js/modules/es.symbol.iterator.js");
require("core-js/modules/es.array.iterator.js");
require("core-js/modules/es.object.to-string.js");
require("core-js/modules/web.dom-collections.iterator.js");
require("core-js/modules/es.symbol.js");
require("core-js/modules/es.symbol.description.js");
require("core-js/modules/es.map.js");
var _Cell = require("../Cell");
var _errorMessage = require("../error-message");
var _generatorUtils = require("../generatorUtils");
var _InterpreterValue = require("./InterpreterValue");
var _marked = /*#__PURE__*/regeneratorRuntime.mark(getRangeValues),
_marked2 = /*#__PURE__*/regeneratorRuntime.mark(ifFilter);
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
var findSmallerRangeForMany = function findSmallerRangeForMany(dependencyGraph, conditionRanges, valuesRange) {
if (valuesRange.end.row > valuesRange.start.row) {
var valuesRangeEndRowLess = (0, _Cell.simpleCellAddress)(valuesRange.end.sheet, valuesRange.end.col, valuesRange.end.row - 1);
var rowLessVertex = dependencyGraph.getRange(valuesRange.start, valuesRangeEndRowLess);
if (rowLessVertex !== undefined) {
return {
smallerRangeVertex: rowLessVertex,
restValuesRange: valuesRange.withStart((0, _Cell.simpleCellAddress)(valuesRange.start.sheet, valuesRange.start.col, valuesRange.end.row)),
restConditionRanges: conditionRanges.map(function (conditionRange) {
return conditionRange.withStart((0, _Cell.simpleCellAddress)(conditionRange.start.sheet, conditionRange.start.col, conditionRange.end.row));
})
};
}
}
return {
restValuesRange: valuesRange,
restConditionRanges: conditionRanges
};
};
var CriterionFunctionCompute = /*#__PURE__*/function () {
function CriterionFunctionCompute(interpreter, cacheKey, reduceInitialValue, composeFunction, mapFunction) {
_classCallCheck(this, CriterionFunctionCompute);
this.interpreter = interpreter;
this.cacheKey = cacheKey;
this.reduceInitialValue = reduceInitialValue;
this.composeFunction = composeFunction;
this.mapFunction = mapFunction;
this.dependencyGraph = this.interpreter.dependencyGraph;
}
_createClass(CriterionFunctionCompute, [{
key: "compute",
value: function compute(simpleValuesRange, conditions) {
var _this = this;
var _iterator = _createForOfIteratorHelper(conditions),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var condition = _step.value;
if (!condition.conditionRange.sameDimensionsAs(simpleValuesRange)) {
return new _Cell.CellError(_Cell.ErrorType.VALUE, _errorMessage.ErrorMessage.EqualLength);
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
var valuesRangeVertex = this.tryToGetRangeVertexForRangeValue(simpleValuesRange);
var conditionsVertices = conditions.map(function (c) {
return _this.tryToGetRangeVertexForRangeValue(c.conditionRange);
});
if (valuesRangeVertex && conditionsVertices.every(function (e) {
return e !== undefined;
})) {
var fullCriterionString = conditions.map(function (c) {
return c.criterionPackage.raw;
}).join(',');
var cachedResult = this.findAlreadyComputedValueInCache(valuesRangeVertex, this.cacheKey(conditions), fullCriterionString);
if (cachedResult !== undefined) {
this.interpreter.stats.incrementCriterionFunctionFullCacheUsed();
return cachedResult;
}
var cache = this.buildNewCriterionCache(this.cacheKey(conditions), conditions.map(function (c) {
return c.conditionRange.range;
}), simpleValuesRange.range);
if (!cache.has(fullCriterionString)) {
cache.set(fullCriterionString, [this.evaluateRangeValue(simpleValuesRange, conditions), conditions.map(function (condition) {
return condition.criterionPackage.lambda;
})]);
}
valuesRangeVertex.setCriterionFunctionValues(this.cacheKey(conditions), cache);
conditionsVertices.forEach(function (range) {
if (range !== undefined) {
range.addDependentCacheRange(valuesRangeVertex);
}
});
return cache.get(fullCriterionString)[0];
} else {
return this.evaluateRangeValue(simpleValuesRange, conditions);
}
}
}, {
key: "tryToGetRangeVertexForRangeValue",
value: function tryToGetRangeVertexForRangeValue(rangeValue) {
var maybeRange = rangeValue.range;
if (maybeRange === undefined) {
return undefined;
} else {
return this.dependencyGraph.getRange(maybeRange.start, maybeRange.end);
}
}
}, {
key: "reduceFunction",
value: function reduceFunction(iterable) {
var acc = this.reduceInitialValue;
var _iterator2 = _createForOfIteratorHelper(iterable),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var val = _step2.value;
acc = this.composeFunction(acc, val);
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
return acc;
}
}, {
key: "findAlreadyComputedValueInCache",
value: function findAlreadyComputedValueInCache(rangeVertex, cacheKey, criterionString) {
return rangeVertex.getCriterionFunctionValue(cacheKey, criterionString);
}
}, {
key: "evaluateRangeValue",
value: function evaluateRangeValue(simpleValuesRange, conditions) {
var criterionLambdas = conditions.map(function (condition) {
return condition.criterionPackage.lambda;
});
var values = Array.from(simpleValuesRange.valuesFromTopLeftCorner()).map(this.mapFunction)[Symbol.iterator]();
var conditionsIterators = conditions.map(function (condition) {
return condition.conditionRange.iterateValuesFromTopLeftCorner();
});
var filteredValues = ifFilter(criterionLambdas, conditionsIterators, values);
return this.reduceFunction(filteredValues);
}
}, {
key: "buildNewCriterionCache",
value: function buildNewCriterionCache(cacheKey, simpleConditionRanges, simpleValuesRange) {
var _this2 = this;
var currentRangeVertex = this.dependencyGraph.getRange(simpleValuesRange.start, simpleValuesRange.end);
var _findSmallerRangeForM = findSmallerRangeForMany(this.dependencyGraph, simpleConditionRanges, simpleValuesRange),
smallerRangeVertex = _findSmallerRangeForM.smallerRangeVertex,
restConditionRanges = _findSmallerRangeForM.restConditionRanges,
restValuesRange = _findSmallerRangeForM.restValuesRange;
var smallerCache;
if (smallerRangeVertex !== undefined && this.dependencyGraph.existsEdge(smallerRangeVertex, currentRangeVertex)) {
smallerCache = smallerRangeVertex.getCriterionFunctionValues(cacheKey);
} else {
smallerCache = new Map();
}
var newCache = new Map();
smallerCache.forEach(function (_ref, key) {
var _ref2 = _slicedToArray(_ref, 2),
value = _ref2[0],
criterionLambdas = _ref2[1];
var filteredValues = ifFilter(criterionLambdas, restConditionRanges.map(function (rcr) {
return getRangeValues(_this2.dependencyGraph, rcr);
}), Array.from(getRangeValues(_this2.dependencyGraph, restValuesRange)).map(_this2.mapFunction)[Symbol.iterator]());
var newCacheValue = _this2.composeFunction(value, _this2.reduceFunction(filteredValues));
_this2.interpreter.stats.incrementCriterionFunctionPartialCacheUsed();
newCache.set(key, [newCacheValue, criterionLambdas]);
});
return newCache;
}
}]);
return CriterionFunctionCompute;
}();
exports.CriterionFunctionCompute = CriterionFunctionCompute;
var Condition = function Condition(conditionRange, criterionPackage) {
_classCallCheck(this, Condition);
this.conditionRange = conditionRange;
this.criterionPackage = criterionPackage;
};
exports.Condition = Condition;
function getRangeValues(dependencyGraph, cellRange) {
var _iterator3, _step3, cellFromRange;
return regeneratorRuntime.wrap(function getRangeValues$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_iterator3 = _createForOfIteratorHelper(cellRange.addresses(dependencyGraph));
_context.prev = 1;
_iterator3.s();
case 3:
if ((_step3 = _iterator3.n()).done) {
_context.next = 9;
break;
}
cellFromRange = _step3.value;
_context.next = 7;
return (0, _InterpreterValue.getRawValue)(dependencyGraph.getScalarValue(cellFromRange));
case 7:
_context.next = 3;
break;
case 9:
_context.next = 14;
break;
case 11:
_context.prev = 11;
_context.t0 = _context["catch"](1);
_iterator3.e(_context.t0);
case 14:
_context.prev = 14;
_iterator3.f();
return _context.finish(14);
case 17:
case "end":
return _context.stop();
}
}
}, _marked, null, [[1, 11, 14, 17]]);
}
function ifFilter(criterionLambdas, conditionalIterables, computableIterable) {
var _iterator4, _step4, computable, conditionalSplits, conditionalFirsts;
return regeneratorRuntime.wrap(function ifFilter$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
_iterator4 = _createForOfIteratorHelper(computableIterable);
_context2.prev = 1;
_iterator4.s();
case 3:
if ((_step4 = _iterator4.n()).done) {
_context2.next = 15;
break;
}
computable = _step4.value;
conditionalSplits = conditionalIterables.map(function (conditionalIterable) {
return (0, _generatorUtils.split)(conditionalIterable);
});
if (conditionalSplits.every(function (cs) {
return Object.prototype.hasOwnProperty.call(cs, 'value');
})) {
_context2.next = 8;
break;
}
return _context2.abrupt("return");
case 8:
conditionalFirsts = conditionalSplits.map(function (cs) {
return cs.value;
});
if (!zip(conditionalFirsts, criterionLambdas).every(function (_ref3) {
var _ref4 = _slicedToArray(_ref3, 2),
conditionalFirst = _ref4[0],
criterionLambda = _ref4[1];
return criterionLambda(conditionalFirst);
})) {
_context2.next = 12;
break;
}
_context2.next = 12;
return computable;
case 12:
conditionalIterables = conditionalSplits.map(function (cs) {
return cs.rest;
});
case 13:
_context2.next = 3;
break;
case 15:
_context2.next = 20;
break;
case 17:
_context2.prev = 17;
_context2.t0 = _context2["catch"](1);
_iterator4.e(_context2.t0);
case 20:
_context2.prev = 20;
_iterator4.f();
return _context2.finish(20);
case 23:
case "end":
return _context2.stop();
}
}
}, _marked2, null, [[1, 17, 20, 23]]);
}
function zip(arr1, arr2) {
var result = [];
for (var i = 0; i < Math.min(arr1.length, arr2.length); i++) {
result.push([arr1[i], arr2[i]]);
}
return result;
}