@trebco/treb 37.0.0 → 37.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/package.json +119 -0
- package/build/treb-base-types/src/api_types.d.ts +11 -0
- package/build/treb-base-types/src/api_types.js +22 -0
- package/build/treb-base-types/src/api_types.js.map +1 -0
- package/build/treb-base-types/src/area-utils.d.ts +9 -0
- package/build/treb-base-types/src/area-utils.js +50 -0
- package/build/treb-base-types/src/area-utils.js.map +1 -0
- package/build/treb-base-types/src/area.d.ts +182 -0
- package/build/treb-base-types/src/area.js +715 -0
- package/build/treb-base-types/src/area.js.map +1 -0
- package/build/treb-base-types/src/basic_types.d.ts +20 -0
- package/build/treb-base-types/src/basic_types.js +22 -0
- package/build/treb-base-types/src/basic_types.js.map +1 -0
- package/build/treb-base-types/src/cell.d.ts +167 -0
- package/build/treb-base-types/src/cell.js +432 -0
- package/build/treb-base-types/src/cell.js.map +1 -0
- package/build/treb-base-types/src/cells.d.ts +251 -0
- package/build/treb-base-types/src/cells.js +1136 -0
- package/build/treb-base-types/src/cells.js.map +1 -0
- package/build/treb-base-types/src/color.d.ts +35 -0
- package/build/treb-base-types/src/color.js +162 -0
- package/build/treb-base-types/src/color.js.map +1 -0
- package/build/treb-base-types/src/dom-utilities.d.ts +70 -0
- package/build/treb-base-types/src/dom-utilities.js +144 -0
- package/build/treb-base-types/src/dom-utilities.js.map +1 -0
- package/build/treb-base-types/src/evaluate-options.d.ts +35 -0
- package/build/treb-base-types/src/evaluate-options.js +22 -0
- package/build/treb-base-types/src/evaluate-options.js.map +1 -0
- package/build/treb-base-types/src/font-stack.d.ts +37 -0
- package/build/treb-base-types/src/font-stack.js +93 -0
- package/build/treb-base-types/src/font-stack.js.map +1 -0
- package/build/treb-base-types/src/gradient.d.ts +18 -0
- package/build/treb-base-types/src/gradient.js +86 -0
- package/build/treb-base-types/src/gradient.js.map +1 -0
- package/build/treb-base-types/src/import.d.ts +48 -0
- package/build/treb-base-types/src/import.js +22 -0
- package/build/treb-base-types/src/import.js.map +1 -0
- package/build/treb-base-types/src/index-standalone.d.ts +6 -0
- package/build/treb-base-types/src/index-standalone.js +27 -0
- package/build/treb-base-types/src/index-standalone.js.map +1 -0
- package/build/treb-base-types/src/index.d.ts +22 -0
- package/build/treb-base-types/src/index.js +45 -0
- package/build/treb-base-types/src/index.js.map +1 -0
- package/build/treb-base-types/src/layout.d.ts +22 -0
- package/build/treb-base-types/src/layout.js +22 -0
- package/build/treb-base-types/src/layout.js.map +1 -0
- package/build/treb-base-types/src/localization.d.ts +37 -0
- package/build/treb-base-types/src/localization.js +157 -0
- package/build/treb-base-types/src/localization.js.map +1 -0
- package/build/treb-base-types/src/rectangle.d.ts +51 -0
- package/build/treb-base-types/src/rectangle.js +123 -0
- package/build/treb-base-types/src/rectangle.js.map +1 -0
- package/build/treb-base-types/src/render_text.d.ts +34 -0
- package/build/treb-base-types/src/render_text.js +22 -0
- package/build/treb-base-types/src/render_text.js.map +1 -0
- package/build/treb-base-types/src/style.d.ts +214 -0
- package/build/treb-base-types/src/style.js +373 -0
- package/build/treb-base-types/src/style.js.map +1 -0
- package/build/treb-base-types/src/table.d.ts +58 -0
- package/build/treb-base-types/src/table.js +27 -0
- package/build/treb-base-types/src/table.js.map +1 -0
- package/build/treb-base-types/src/text_part.d.ts +26 -0
- package/build/treb-base-types/src/text_part.js +47 -0
- package/build/treb-base-types/src/text_part.js.map +1 -0
- package/build/treb-base-types/src/theme.d.ts +120 -0
- package/build/treb-base-types/src/theme.js +460 -0
- package/build/treb-base-types/src/theme.js.map +1 -0
- package/build/treb-base-types/src/union.d.ts +73 -0
- package/build/treb-base-types/src/union.js +61 -0
- package/build/treb-base-types/src/union.js.map +1 -0
- package/build/treb-base-types/src/value-type.d.ts +86 -0
- package/build/treb-base-types/src/value-type.js +168 -0
- package/build/treb-base-types/src/value-type.js.map +1 -0
- package/build/treb-base-types/src/worker-proxy.d.ts +95 -0
- package/build/treb-base-types/src/worker-proxy.js +221 -0
- package/build/treb-base-types/src/worker-proxy.js.map +1 -0
- package/build/treb-calculator/src/calculator.d.ts +249 -0
- package/build/treb-calculator/src/calculator.js +2755 -0
- package/build/treb-calculator/src/calculator.js.map +1 -0
- package/build/treb-calculator/src/complex-math.d.ts +75 -0
- package/build/treb-calculator/src/complex-math.js +559 -0
- package/build/treb-calculator/src/complex-math.js.map +1 -0
- package/build/treb-calculator/src/dag/array-vertex.d.ts +71 -0
- package/build/treb-calculator/src/dag/array-vertex.js +156 -0
- package/build/treb-calculator/src/dag/array-vertex.js.map +1 -0
- package/build/treb-calculator/src/dag/calculation_leaf_vertex.d.ts +48 -0
- package/build/treb-calculator/src/dag/calculation_leaf_vertex.js +84 -0
- package/build/treb-calculator/src/dag/calculation_leaf_vertex.js.map +1 -0
- package/build/treb-calculator/src/dag/graph.d.ts +134 -0
- package/build/treb-calculator/src/dag/graph.js +842 -0
- package/build/treb-calculator/src/dag/graph.js.map +1 -0
- package/build/treb-calculator/src/dag/spreadsheet_vertex.d.ts +58 -0
- package/build/treb-calculator/src/dag/spreadsheet_vertex.js +232 -0
- package/build/treb-calculator/src/dag/spreadsheet_vertex.js.map +1 -0
- package/build/treb-calculator/src/dag/spreadsheet_vertex_base.d.ts +20 -0
- package/build/treb-calculator/src/dag/spreadsheet_vertex_base.js +25 -0
- package/build/treb-calculator/src/dag/spreadsheet_vertex_base.js.map +1 -0
- package/build/treb-calculator/src/dag/state_leaf_vertex.d.ts +43 -0
- package/build/treb-calculator/src/dag/state_leaf_vertex.js +81 -0
- package/build/treb-calculator/src/dag/state_leaf_vertex.js.map +1 -0
- package/build/treb-calculator/src/dag/vertex.d.ts +71 -0
- package/build/treb-calculator/src/dag/vertex.js +274 -0
- package/build/treb-calculator/src/dag/vertex.js.map +1 -0
- package/build/treb-calculator/src/descriptors.d.ts +189 -0
- package/build/treb-calculator/src/descriptors.js +22 -0
- package/build/treb-calculator/src/descriptors.js.map +1 -0
- package/build/treb-calculator/src/expression-calculator.d.ts +127 -0
- package/build/treb-calculator/src/expression-calculator.js +1033 -0
- package/build/treb-calculator/src/expression-calculator.js.map +1 -0
- package/build/treb-calculator/src/function-error.d.ts +35 -0
- package/build/treb-calculator/src/function-error.js +85 -0
- package/build/treb-calculator/src/function-error.js.map +1 -0
- package/build/treb-calculator/src/function-library.d.ts +22 -0
- package/build/treb-calculator/src/function-library.js +96 -0
- package/build/treb-calculator/src/function-library.js.map +1 -0
- package/build/treb-calculator/src/functions/base-functions.d.ts +7 -0
- package/build/treb-calculator/src/functions/base-functions.js +2611 -0
- package/build/treb-calculator/src/functions/base-functions.js.map +1 -0
- package/build/treb-calculator/src/functions/beta.d.ts +17 -0
- package/build/treb-calculator/src/functions/beta.js +201 -0
- package/build/treb-calculator/src/functions/beta.js.map +1 -0
- package/build/treb-calculator/src/functions/checkbox.d.ts +3 -0
- package/build/treb-calculator/src/functions/checkbox.js +128 -0
- package/build/treb-calculator/src/functions/checkbox.js.map +1 -0
- package/build/treb-calculator/src/functions/complex-functions.d.ts +2 -0
- package/build/treb-calculator/src/functions/complex-functions.js +217 -0
- package/build/treb-calculator/src/functions/complex-functions.js.map +1 -0
- package/build/treb-calculator/src/functions/date-utils.d.ts +3 -0
- package/build/treb-calculator/src/functions/date-utils.js +59 -0
- package/build/treb-calculator/src/functions/date-utils.js.map +1 -0
- package/build/treb-calculator/src/functions/finance-functions.d.ts +2 -0
- package/build/treb-calculator/src/functions/finance-functions.js +547 -0
- package/build/treb-calculator/src/functions/finance-functions.js.map +1 -0
- package/build/treb-calculator/src/functions/fp.d.ts +2 -0
- package/build/treb-calculator/src/functions/fp.js +463 -0
- package/build/treb-calculator/src/functions/fp.js.map +1 -0
- package/build/treb-calculator/src/functions/function-utilities.d.ts +2 -0
- package/build/treb-calculator/src/functions/function-utilities.js +36 -0
- package/build/treb-calculator/src/functions/function-utilities.js.map +1 -0
- package/build/treb-calculator/src/functions/gamma.d.ts +20 -0
- package/build/treb-calculator/src/functions/gamma.js +142 -0
- package/build/treb-calculator/src/functions/gamma.js.map +1 -0
- package/build/treb-calculator/src/functions/information-functions.d.ts +2 -0
- package/build/treb-calculator/src/functions/information-functions.js +71 -0
- package/build/treb-calculator/src/functions/information-functions.js.map +1 -0
- package/build/treb-calculator/src/functions/lambda-functions.d.ts +2 -0
- package/build/treb-calculator/src/functions/lambda-functions.js +85 -0
- package/build/treb-calculator/src/functions/lambda-functions.js.map +1 -0
- package/build/treb-calculator/src/functions/matrix-functions.d.ts +2 -0
- package/build/treb-calculator/src/functions/matrix-functions.js +144 -0
- package/build/treb-calculator/src/functions/matrix-functions.js.map +1 -0
- package/build/treb-calculator/src/functions/normal.d.ts +2 -0
- package/build/treb-calculator/src/functions/normal.js +32 -0
- package/build/treb-calculator/src/functions/normal.js.map +1 -0
- package/build/treb-calculator/src/functions/regex-functions.d.ts +2 -0
- package/build/treb-calculator/src/functions/regex-functions.js +188 -0
- package/build/treb-calculator/src/functions/regex-functions.js.map +1 -0
- package/build/treb-calculator/src/functions/sparkline.d.ts +37 -0
- package/build/treb-calculator/src/functions/sparkline.js +264 -0
- package/build/treb-calculator/src/functions/sparkline.js.map +1 -0
- package/build/treb-calculator/src/functions/statistics-functions.d.ts +6 -0
- package/build/treb-calculator/src/functions/statistics-functions.js +989 -0
- package/build/treb-calculator/src/functions/statistics-functions.js.map +1 -0
- package/build/treb-calculator/src/functions/students-t.d.ts +3 -0
- package/build/treb-calculator/src/functions/students-t.js +64 -0
- package/build/treb-calculator/src/functions/students-t.js.map +1 -0
- package/build/treb-calculator/src/functions/text-functions.d.ts +3 -0
- package/build/treb-calculator/src/functions/text-functions.js +320 -0
- package/build/treb-calculator/src/functions/text-functions.js.map +1 -0
- package/build/treb-calculator/src/index.d.ts +2 -0
- package/build/treb-calculator/src/index.js +22 -0
- package/build/treb-calculator/src/index.js.map +1 -0
- package/build/treb-calculator/src/notifier-types.d.ts +26 -0
- package/build/treb-calculator/src/notifier-types.js +22 -0
- package/build/treb-calculator/src/notifier-types.js.map +1 -0
- package/build/treb-calculator/src/primitives.d.ts +15 -0
- package/build/treb-calculator/src/primitives.js +398 -0
- package/build/treb-calculator/src/primitives.js.map +1 -0
- package/build/treb-calculator/src/utilities.d.ts +68 -0
- package/build/treb-calculator/src/utilities.js +324 -0
- package/build/treb-calculator/src/utilities.js.map +1 -0
- package/build/treb-charts/src/chart-functions.d.ts +8 -0
- package/build/treb-charts/src/chart-functions.js +209 -0
- package/build/treb-charts/src/chart-functions.js.map +1 -0
- package/build/treb-charts/src/chart-types.d.ts +233 -0
- package/build/treb-charts/src/chart-types.js +57 -0
- package/build/treb-charts/src/chart-types.js.map +1 -0
- package/build/treb-charts/src/chart-utils.d.ts +106 -0
- package/build/treb-charts/src/chart-utils.js +1060 -0
- package/build/treb-charts/src/chart-utils.js.map +1 -0
- package/build/treb-charts/src/chart.d.ts +23 -0
- package/build/treb-charts/src/chart.js +94 -0
- package/build/treb-charts/src/chart.js.map +1 -0
- package/build/treb-charts/src/default-chart-renderer.d.ts +16 -0
- package/build/treb-charts/src/default-chart-renderer.js +533 -0
- package/build/treb-charts/src/default-chart-renderer.js.map +1 -0
- package/build/treb-charts/src/index.d.ts +5 -0
- package/build/treb-charts/src/index.js +24 -0
- package/build/treb-charts/src/index.js.map +1 -0
- package/build/treb-charts/src/main.d.ts +1 -0
- package/build/treb-charts/src/main.js +34 -0
- package/build/treb-charts/src/main.js.map +1 -0
- package/build/treb-charts/src/quicksort.d.ts +1 -0
- package/build/treb-charts/src/quicksort.js +49 -0
- package/build/treb-charts/src/quicksort.js.map +1 -0
- package/build/treb-charts/src/rectangle.d.ts +18 -0
- package/build/treb-charts/src/rectangle.js +41 -0
- package/build/treb-charts/src/rectangle.js.map +1 -0
- package/build/treb-charts/src/renderer-type.d.ts +24 -0
- package/build/treb-charts/src/renderer-type.js +22 -0
- package/build/treb-charts/src/renderer-type.js.map +1 -0
- package/build/treb-charts/src/renderer.d.ts +127 -0
- package/build/treb-charts/src/renderer.js +1518 -0
- package/build/treb-charts/src/renderer.js.map +1 -0
- package/build/treb-charts/src/util.d.ts +18 -0
- package/build/treb-charts/src/util.js +71 -0
- package/build/treb-charts/src/util.js.map +1 -0
- package/build/treb-data-model/src/annotation.d.ts +167 -0
- package/build/treb-data-model/src/annotation.js +120 -0
- package/build/treb-data-model/src/annotation.js.map +1 -0
- package/build/treb-data-model/src/conditional_format.d.ts +155 -0
- package/build/treb-data-model/src/conditional_format.js +62 -0
- package/build/treb-data-model/src/conditional_format.js.map +1 -0
- package/build/treb-data-model/src/data-validation.d.ts +28 -0
- package/build/treb-data-model/src/data-validation.js +22 -0
- package/build/treb-data-model/src/data-validation.js.map +1 -0
- package/build/treb-data-model/src/data_model.d.ts +173 -0
- package/build/treb-data-model/src/data_model.js +637 -0
- package/build/treb-data-model/src/data_model.js.map +1 -0
- package/build/treb-data-model/src/index.d.ts +13 -0
- package/build/treb-data-model/src/index.js +28 -0
- package/build/treb-data-model/src/index.js.map +1 -0
- package/build/treb-data-model/src/language-model.d.ts +22 -0
- package/build/treb-data-model/src/language-model.js +22 -0
- package/build/treb-data-model/src/language-model.js.map +1 -0
- package/build/treb-data-model/src/named.d.ts +124 -0
- package/build/treb-data-model/src/named.js +372 -0
- package/build/treb-data-model/src/named.js.map +1 -0
- package/build/treb-data-model/src/serialize_options.d.ts +49 -0
- package/build/treb-data-model/src/serialize_options.js +22 -0
- package/build/treb-data-model/src/serialize_options.js.map +1 -0
- package/build/treb-data-model/src/sheet.d.ts +499 -0
- package/build/treb-data-model/src/sheet.js +2904 -0
- package/build/treb-data-model/src/sheet.js.map +1 -0
- package/build/treb-data-model/src/sheet_collection.d.ts +58 -0
- package/build/treb-data-model/src/sheet_collection.js +112 -0
- package/build/treb-data-model/src/sheet_collection.js.map +1 -0
- package/build/treb-data-model/src/sheet_selection.d.ts +42 -0
- package/build/treb-data-model/src/sheet_selection.js +39 -0
- package/build/treb-data-model/src/sheet_selection.js.map +1 -0
- package/build/treb-data-model/src/sheet_types.d.ts +104 -0
- package/build/treb-data-model/src/sheet_types.js +22 -0
- package/build/treb-data-model/src/sheet_types.js.map +1 -0
- package/build/treb-data-model/src/types.d.ts +59 -0
- package/build/treb-data-model/src/types.js +22 -0
- package/build/treb-data-model/src/types.js.map +1 -0
- package/build/treb-embed/src/custom-element/spreadsheet-constructor.d.ts +75 -0
- package/build/treb-embed/src/custom-element/spreadsheet-constructor.js +1144 -0
- package/build/treb-embed/src/custom-element/spreadsheet-constructor.js.map +1 -0
- package/build/treb-embed/src/custom-element/treb-global.d.ts +36 -0
- package/build/treb-embed/src/custom-element/treb-global.js +64 -0
- package/build/treb-embed/src/custom-element/treb-global.js.map +1 -0
- package/build/treb-embed/src/custom-element/treb-spreadsheet-element.d.ts +1 -0
- package/build/treb-embed/src/custom-element/treb-spreadsheet-element.js +61 -0
- package/build/treb-embed/src/custom-element/treb-spreadsheet-element.js.map +1 -0
- package/build/treb-embed/src/embedded-spreadsheet.d.ts +1358 -0
- package/build/treb-embed/src/embedded-spreadsheet.js +5205 -0
- package/build/treb-embed/src/embedded-spreadsheet.js.map +1 -0
- package/build/treb-embed/src/index.d.ts +12 -0
- package/build/treb-embed/src/index.js +34 -0
- package/build/treb-embed/src/index.js.map +1 -0
- package/build/treb-embed/src/options.d.ts +266 -0
- package/build/treb-embed/src/options.js +56 -0
- package/build/treb-embed/src/options.js.map +1 -0
- package/build/treb-embed/src/plugin.d.ts +9 -0
- package/build/treb-embed/src/plugin.js +22 -0
- package/build/treb-embed/src/plugin.js.map +1 -0
- package/build/treb-embed/src/progress-dialog.d.ts +49 -0
- package/build/treb-embed/src/progress-dialog.js +178 -0
- package/build/treb-embed/src/progress-dialog.js.map +1 -0
- package/build/treb-embed/src/selection-state.d.ts +15 -0
- package/build/treb-embed/src/selection-state.js +22 -0
- package/build/treb-embed/src/selection-state.js.map +1 -0
- package/build/treb-embed/src/spinner.d.ts +8 -0
- package/build/treb-embed/src/spinner.js +40 -0
- package/build/treb-embed/src/spinner.js.map +1 -0
- package/build/treb-embed/src/toolbar-message.d.ts +72 -0
- package/build/treb-embed/src/toolbar-message.js +22 -0
- package/build/treb-embed/src/toolbar-message.js.map +1 -0
- package/build/treb-embed/src/types.d.ts +185 -0
- package/build/treb-embed/src/types.js +45 -0
- package/build/treb-embed/src/types.js.map +1 -0
- package/build/treb-embed/tsconfig.tsbuildinfo +1 -0
- package/build/treb-export/src/address-type.d.ts +34 -0
- package/build/treb-export/src/address-type.js +53 -0
- package/build/treb-export/src/address-type.js.map +1 -0
- package/build/treb-export/src/base-template.d.ts +1 -0
- package/build/treb-export/src/base-template.js +22 -0
- package/build/treb-export/src/base-template.js.map +1 -0
- package/build/treb-export/src/column-width.d.ts +2 -0
- package/build/treb-export/src/column-width.js +80 -0
- package/build/treb-export/src/column-width.js.map +1 -0
- package/build/treb-export/src/drawing/bubble-chart-template.d.ts +514 -0
- package/build/treb-export/src/drawing/bubble-chart-template.js +544 -0
- package/build/treb-export/src/drawing/bubble-chart-template.js.map +1 -0
- package/build/treb-export/src/drawing/chart-template-components2.d.ts +365 -0
- package/build/treb-export/src/drawing/chart-template-components2.js +386 -0
- package/build/treb-export/src/drawing/chart-template-components2.js.map +1 -0
- package/build/treb-export/src/drawing/chart.d.ts +26 -0
- package/build/treb-export/src/drawing/chart.js +247 -0
- package/build/treb-export/src/drawing/chart.js.map +1 -0
- package/build/treb-export/src/drawing/column-chart-template2.d.ts +490 -0
- package/build/treb-export/src/drawing/column-chart-template2.js +518 -0
- package/build/treb-export/src/drawing/column-chart-template2.js.map +1 -0
- package/build/treb-export/src/drawing/donut-chart-template2.d.ts +272 -0
- package/build/treb-export/src/drawing/donut-chart-template2.js +293 -0
- package/build/treb-export/src/drawing/donut-chart-template2.js.map +1 -0
- package/build/treb-export/src/drawing/drawing.d.ts +49 -0
- package/build/treb-export/src/drawing/drawing.js +193 -0
- package/build/treb-export/src/drawing/drawing.js.map +1 -0
- package/build/treb-export/src/drawing/embedded-image.d.ts +12 -0
- package/build/treb-export/src/drawing/embedded-image.js +54 -0
- package/build/treb-export/src/drawing/embedded-image.js.map +1 -0
- package/build/treb-export/src/drawing/scatter-chart-template2.d.ts +520 -0
- package/build/treb-export/src/drawing/scatter-chart-template2.js +551 -0
- package/build/treb-export/src/drawing/scatter-chart-template2.js.map +1 -0
- package/build/treb-export/src/export.d.ts +72 -0
- package/build/treb-export/src/export.js +2039 -0
- package/build/treb-export/src/export.js.map +1 -0
- package/build/treb-export/src/import-export-messages.d.ts +31 -0
- package/build/treb-export/src/import-export-messages.js +22 -0
- package/build/treb-export/src/import-export-messages.js.map +1 -0
- package/build/treb-export/src/import.d.ts +33 -0
- package/build/treb-export/src/import.js +1258 -0
- package/build/treb-export/src/import.js.map +1 -0
- package/build/treb-export/src/index.worker.d.ts +1 -0
- package/build/treb-export/src/index.worker.js +93 -0
- package/build/treb-export/src/index.worker.js.map +1 -0
- package/build/treb-export/src/metadata.d.ts +51 -0
- package/build/treb-export/src/metadata.js +153 -0
- package/build/treb-export/src/metadata.js.map +1 -0
- package/build/treb-export/src/ooxml.d.ts +7 -0
- package/build/treb-export/src/ooxml.js +41 -0
- package/build/treb-export/src/ooxml.js.map +1 -0
- package/build/treb-export/src/relationship.d.ts +8 -0
- package/build/treb-export/src/relationship.js +27 -0
- package/build/treb-export/src/relationship.js.map +1 -0
- package/build/treb-export/src/shared-strings.d.ts +11 -0
- package/build/treb-export/src/shared-strings.js +105 -0
- package/build/treb-export/src/shared-strings.js.map +1 -0
- package/build/treb-export/src/template-2.d.ts +1 -0
- package/build/treb-export/src/template-2.js +22 -0
- package/build/treb-export/src/template-2.js.map +1 -0
- package/build/treb-export/src/unescape_xml.d.ts +1 -0
- package/build/treb-export/src/unescape_xml.js +61 -0
- package/build/treb-export/src/unescape_xml.js.map +1 -0
- package/build/treb-export/src/workbook-sheet.d.ts +75 -0
- package/build/treb-export/src/workbook-sheet.js +128 -0
- package/build/treb-export/src/workbook-sheet.js.map +1 -0
- package/build/treb-export/src/workbook-style.d.ts +110 -0
- package/build/treb-export/src/workbook-style.js +1134 -0
- package/build/treb-export/src/workbook-style.js.map +1 -0
- package/build/treb-export/src/workbook-theme.d.ts +13 -0
- package/build/treb-export/src/workbook-theme.js +85 -0
- package/build/treb-export/src/workbook-theme.js.map +1 -0
- package/build/treb-export/src/workbook.d.ts +123 -0
- package/build/treb-export/src/workbook.js +644 -0
- package/build/treb-export/src/workbook.js.map +1 -0
- package/build/treb-export/src/xml-test.d.ts +9 -0
- package/build/treb-export/src/xml-test.js +52 -0
- package/build/treb-export/src/xml-test.js.map +1 -0
- package/build/treb-export/src/xml-utils.d.ts +76 -0
- package/build/treb-export/src/xml-utils.js +223 -0
- package/build/treb-export/src/xml-utils.js.map +1 -0
- package/build/treb-export/src/zip-wrapper.d.ts +22 -0
- package/build/treb-export/src/zip-wrapper.js +93 -0
- package/build/treb-export/src/zip-wrapper.js.map +1 -0
- package/build/treb-format/src/format.d.ts +130 -0
- package/build/treb-format/src/format.js +805 -0
- package/build/treb-format/src/format.js.map +1 -0
- package/build/treb-format/src/format_cache.d.ts +55 -0
- package/build/treb-format/src/format_cache.js +166 -0
- package/build/treb-format/src/format_cache.js.map +1 -0
- package/build/treb-format/src/format_parser.d.ts +70 -0
- package/build/treb-format/src/format_parser.js +618 -0
- package/build/treb-format/src/format_parser.js.map +1 -0
- package/build/treb-format/src/index.d.ts +4 -0
- package/build/treb-format/src/index.js +25 -0
- package/build/treb-format/src/index.js.map +1 -0
- package/build/treb-format/src/number_format_section.d.ts +58 -0
- package/build/treb-format/src/number_format_section.js +78 -0
- package/build/treb-format/src/number_format_section.js.map +1 -0
- package/build/treb-format/src/value_parser.d.ts +48 -0
- package/build/treb-format/src/value_parser.js +244 -0
- package/build/treb-format/src/value_parser.js.map +1 -0
- package/build/treb-grid/src/editors/autocomplete.d.ts +39 -0
- package/build/treb-grid/src/editors/autocomplete.js +316 -0
- package/build/treb-grid/src/editors/autocomplete.js.map +1 -0
- package/build/treb-grid/src/editors/autocomplete_matcher.d.ts +74 -0
- package/build/treb-grid/src/editors/autocomplete_matcher.js +212 -0
- package/build/treb-grid/src/editors/autocomplete_matcher.js.map +1 -0
- package/build/treb-grid/src/editors/editor.d.ts +214 -0
- package/build/treb-grid/src/editors/editor.js +879 -0
- package/build/treb-grid/src/editors/editor.js.map +1 -0
- package/build/treb-grid/src/editors/external_editor.d.ts +11 -0
- package/build/treb-grid/src/editors/external_editor.js +118 -0
- package/build/treb-grid/src/editors/external_editor.js.map +1 -0
- package/build/treb-grid/src/editors/formula_bar.d.ts +85 -0
- package/build/treb-grid/src/editors/formula_bar.js +444 -0
- package/build/treb-grid/src/editors/formula_bar.js.map +1 -0
- package/build/treb-grid/src/editors/overlay_editor.d.ts +85 -0
- package/build/treb-grid/src/editors/overlay_editor.js +353 -0
- package/build/treb-grid/src/editors/overlay_editor.js.map +1 -0
- package/build/treb-grid/src/index.d.ts +12 -0
- package/build/treb-grid/src/index.js +28 -0
- package/build/treb-grid/src/index.js.map +1 -0
- package/build/treb-grid/src/layout/base_layout.d.ts +346 -0
- package/build/treb-grid/src/layout/base_layout.js +2050 -0
- package/build/treb-grid/src/layout/base_layout.js.map +1 -0
- package/build/treb-grid/src/layout/grid_layout.d.ts +19 -0
- package/build/treb-grid/src/layout/grid_layout.js +235 -0
- package/build/treb-grid/src/layout/grid_layout.js.map +1 -0
- package/build/treb-grid/src/layout/mock-layout.d.ts +10 -0
- package/build/treb-grid/src/layout/mock-layout.js +37 -0
- package/build/treb-grid/src/layout/mock-layout.js.map +1 -0
- package/build/treb-grid/src/render/selection-renderer.d.ts +97 -0
- package/build/treb-grid/src/render/selection-renderer.js +315 -0
- package/build/treb-grid/src/render/selection-renderer.js.map +1 -0
- package/build/treb-grid/src/render/svg_header_overlay.d.ts +20 -0
- package/build/treb-grid/src/render/svg_header_overlay.js +76 -0
- package/build/treb-grid/src/render/svg_header_overlay.js.map +1 -0
- package/build/treb-grid/src/render/svg_selection_block.d.ts +27 -0
- package/build/treb-grid/src/render/svg_selection_block.js +106 -0
- package/build/treb-grid/src/render/svg_selection_block.js.map +1 -0
- package/build/treb-grid/src/render/tile_renderer.d.ts +121 -0
- package/build/treb-grid/src/render/tile_renderer.js +1609 -0
- package/build/treb-grid/src/render/tile_renderer.js.map +1 -0
- package/build/treb-grid/src/types/border_constants.d.ts +9 -0
- package/build/treb-grid/src/types/border_constants.js +34 -0
- package/build/treb-grid/src/types/border_constants.js.map +1 -0
- package/build/treb-grid/src/types/clipboard_data.d.ts +11 -0
- package/build/treb-grid/src/types/clipboard_data.js +22 -0
- package/build/treb-grid/src/types/clipboard_data.js.map +1 -0
- package/build/treb-grid/src/types/clipboard_data2.d.ts +46 -0
- package/build/treb-grid/src/types/clipboard_data2.js +22 -0
- package/build/treb-grid/src/types/clipboard_data2.js.map +1 -0
- package/build/treb-grid/src/types/drag_mask.d.ts +10 -0
- package/build/treb-grid/src/types/drag_mask.js +78 -0
- package/build/treb-grid/src/types/drag_mask.js.map +1 -0
- package/build/treb-grid/src/types/external_editor_config.d.ts +33 -0
- package/build/treb-grid/src/types/external_editor_config.js +22 -0
- package/build/treb-grid/src/types/external_editor_config.js.map +1 -0
- package/build/treb-grid/src/types/grid.d.ts +806 -0
- package/build/treb-grid/src/types/grid.js +6410 -0
- package/build/treb-grid/src/types/grid.js.map +1 -0
- package/build/treb-grid/src/types/grid_base.d.ts +442 -0
- package/build/treb-grid/src/types/grid_base.js +3523 -0
- package/build/treb-grid/src/types/grid_base.js.map +1 -0
- package/build/treb-grid/src/types/grid_command.d.ts +408 -0
- package/build/treb-grid/src/types/grid_command.js +75 -0
- package/build/treb-grid/src/types/grid_command.js.map +1 -0
- package/build/treb-grid/src/types/grid_events.d.ts +93 -0
- package/build/treb-grid/src/types/grid_events.js +36 -0
- package/build/treb-grid/src/types/grid_events.js.map +1 -0
- package/build/treb-grid/src/types/grid_options.d.ts +50 -0
- package/build/treb-grid/src/types/grid_options.js +34 -0
- package/build/treb-grid/src/types/grid_options.js.map +1 -0
- package/build/treb-grid/src/types/scale-control.d.ts +21 -0
- package/build/treb-grid/src/types/scale-control.js +148 -0
- package/build/treb-grid/src/types/scale-control.js.map +1 -0
- package/build/treb-grid/src/types/set_range_options.d.ts +24 -0
- package/build/treb-grid/src/types/set_range_options.js +22 -0
- package/build/treb-grid/src/types/set_range_options.js.map +1 -0
- package/build/treb-grid/src/types/tab_bar.d.ts +84 -0
- package/build/treb-grid/src/types/tab_bar.js +426 -0
- package/build/treb-grid/src/types/tab_bar.js.map +1 -0
- package/build/treb-grid/src/types/tile.d.ts +29 -0
- package/build/treb-grid/src/types/tile.js +22 -0
- package/build/treb-grid/src/types/tile.js.map +1 -0
- package/build/treb-grid/src/types/update_flags.d.ts +48 -0
- package/build/treb-grid/src/types/update_flags.js +22 -0
- package/build/treb-grid/src/types/update_flags.js.map +1 -0
- package/build/treb-grid/src/util/fontmetrics.d.ts +21 -0
- package/build/treb-grid/src/util/fontmetrics.js +82 -0
- package/build/treb-grid/src/util/fontmetrics.js.map +1 -0
- package/build/treb-grid/src/util/ua.d.ts +33 -0
- package/build/treb-grid/src/util/ua.js +86 -0
- package/build/treb-grid/src/util/ua.js.map +1 -0
- package/build/treb-parser/src/csv-parser.d.ts +13 -0
- package/build/treb-parser/src/csv-parser.js +107 -0
- package/build/treb-parser/src/csv-parser.js.map +1 -0
- package/build/treb-parser/src/index.d.ts +4 -0
- package/build/treb-parser/src/index.js +25 -0
- package/build/treb-parser/src/index.js.map +1 -0
- package/build/treb-parser/src/md-parser.d.ts +97 -0
- package/build/treb-parser/src/md-parser.js +403 -0
- package/build/treb-parser/src/md-parser.js.map +1 -0
- package/build/treb-parser/src/parser-types.d.ts +345 -0
- package/build/treb-parser/src/parser-types.js +53 -0
- package/build/treb-parser/src/parser-types.js.map +1 -0
- package/build/treb-parser/src/parser.d.ts +422 -0
- package/build/treb-parser/src/parser.js +2418 -0
- package/build/treb-parser/src/parser.js.map +1 -0
- package/build/treb-utils/src/event_source.d.ts +34 -0
- package/build/treb-utils/src/event_source.js +110 -0
- package/build/treb-utils/src/event_source.js.map +1 -0
- package/build/treb-utils/src/ievent_source.d.ts +9 -0
- package/build/treb-utils/src/ievent_source.js +22 -0
- package/build/treb-utils/src/ievent_source.js.map +1 -0
- package/build/treb-utils/src/index.d.ts +6 -0
- package/build/treb-utils/src/index.js +30 -0
- package/build/treb-utils/src/index.js.map +1 -0
- package/build/treb-utils/src/measurement.d.ts +42 -0
- package/build/treb-utils/src/measurement.js +145 -0
- package/build/treb-utils/src/measurement.js.map +1 -0
- package/build/treb-utils/src/scale.d.ts +16 -0
- package/build/treb-utils/src/scale.js +106 -0
- package/build/treb-utils/src/scale.js.map +1 -0
- package/build/treb-utils/src/serialize_html.d.ts +5 -0
- package/build/treb-utils/src/serialize_html.js +128 -0
- package/build/treb-utils/src/serialize_html.js.map +1 -0
- package/build/treb-utils/src/validate_uri.d.ts +20 -0
- package/build/treb-utils/src/validate_uri.js +55 -0
- package/build/treb-utils/src/validate_uri.js.map +1 -0
- package/dist/{chunk-XD5PEZBZ.mjs → chunk-A2NJA5VB.mjs} +1 -1
- package/dist/treb-export-worker.mjs +2 -2
- package/dist/treb-spreadsheet.mjs +4 -4
- package/dist/treb.d.ts +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,1033 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of TREB.
|
|
3
|
+
*
|
|
4
|
+
* TREB is free software: you can redistribute it and/or modify it under the
|
|
5
|
+
* terms of the GNU General Public License as published by the Free Software
|
|
6
|
+
* Foundation, either version 3 of the License, or (at your option) any
|
|
7
|
+
* later version.
|
|
8
|
+
*
|
|
9
|
+
* TREB is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
10
|
+
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
11
|
+
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
12
|
+
* details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU General Public License along
|
|
15
|
+
* with TREB. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
*
|
|
17
|
+
* Copyright 2022-2026 trebco, llc.
|
|
18
|
+
* info@treb.app
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
import { ValueType, GetValueType, Area } from 'treb-base-types';
|
|
22
|
+
import { NameError, ReferenceError, ExpressionError, UnknownError, SpillError, ValueError, ArgumentError } from './function-error';
|
|
23
|
+
import * as Primitives from './primitives';
|
|
24
|
+
// FIXME: move
|
|
25
|
+
// FIXME: this is sloppy
|
|
26
|
+
export const UnionIsExpressionUnit = (test /*UnionOrArray*/) => {
|
|
27
|
+
return !Array.isArray(test)
|
|
28
|
+
&& test.type === ValueType.object
|
|
29
|
+
&& (!!test.value.type);
|
|
30
|
+
};
|
|
31
|
+
// FIXME: move
|
|
32
|
+
// FIXME: this is sloppy
|
|
33
|
+
export const UnionIsMetadata = (test /*UnionOrArray*/) => {
|
|
34
|
+
return test.type === ValueType.object && test.key === 'metadata';
|
|
35
|
+
};
|
|
36
|
+
export class ExpressionCalculator {
|
|
37
|
+
data_model;
|
|
38
|
+
library;
|
|
39
|
+
parser;
|
|
40
|
+
context = {
|
|
41
|
+
address: { row: -1, column: -1 },
|
|
42
|
+
volatile: false,
|
|
43
|
+
bindings: [],
|
|
44
|
+
};
|
|
45
|
+
// --- public API -----------------------------------------------------------
|
|
46
|
+
constructor(data_model, library, parser) {
|
|
47
|
+
this.data_model = data_model;
|
|
48
|
+
this.library = library;
|
|
49
|
+
this.parser = parser;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* there's a case where we are calling this from within a function
|
|
53
|
+
* (which is weird, but hey) and to do that we need to preserve flags.
|
|
54
|
+
*/
|
|
55
|
+
Calculate(expr, addr, area, preserve_flags = false) {
|
|
56
|
+
if (!preserve_flags) {
|
|
57
|
+
this.context.address = addr;
|
|
58
|
+
this.context.volatile = false;
|
|
59
|
+
this.context.area = area;
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
value: this.CalculateExpression(expr),
|
|
63
|
+
volatile: this.context.volatile,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
// --- /public API ----------------------------------------------------------
|
|
67
|
+
/**
|
|
68
|
+
* resolve value from cell. returns a function bound to specific cell.
|
|
69
|
+
*/
|
|
70
|
+
CellFunction2(expr) {
|
|
71
|
+
if (!expr.sheet_id) {
|
|
72
|
+
if (expr.sheet) {
|
|
73
|
+
expr.sheet_id = this.data_model.sheets.ID(expr.sheet) || 0;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
return () => ReferenceError();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const cells = this.data_model.sheets.Find(expr.sheet_id)?.cells;
|
|
80
|
+
if (!cells) {
|
|
81
|
+
console.warn('missing cells reference @ ' + expr.sheet_id);
|
|
82
|
+
return () => ReferenceError();
|
|
83
|
+
}
|
|
84
|
+
// reference
|
|
85
|
+
const cell = cells.GetCell(expr);
|
|
86
|
+
// this is not an error, just a reference to an empty cell
|
|
87
|
+
// FIXME: should this be 0? probably
|
|
88
|
+
if (!cell) {
|
|
89
|
+
return () => {
|
|
90
|
+
return { type: ValueType.number, value: 0 };
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (expr.spill && cell.spill && cell.spill.start.row === expr.row && cell.spill.start.column === expr.column) {
|
|
94
|
+
return () => {
|
|
95
|
+
return cell.spill ? cells.GetRange4(cell.spill.start, cell.spill.end, true) || ReferenceError() : SpillError();
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// close
|
|
99
|
+
return () => cell.GetValue4();
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* returns range as union type. returns a single value for a single cell,
|
|
103
|
+
* or a 2d array (never a 1d array)
|
|
104
|
+
*/
|
|
105
|
+
CellFunction4(start, end) {
|
|
106
|
+
if (!start.sheet_id) {
|
|
107
|
+
return ReferenceError();
|
|
108
|
+
// throw new Error('missing sheet id in CellFunction4');
|
|
109
|
+
}
|
|
110
|
+
const cells = this.data_model.sheets.Find(start.sheet_id)?.cells;
|
|
111
|
+
return cells?.GetRange4(start, end, true) || ReferenceError();
|
|
112
|
+
}
|
|
113
|
+
/** breaking this out to de-dupe */
|
|
114
|
+
GetMetadata(arg, transform) {
|
|
115
|
+
// FIXME: we used to restrict this to non-cell functions, now
|
|
116
|
+
// we are using it for the cell function (we used to use address,
|
|
117
|
+
// which just returns the label)
|
|
118
|
+
let address;
|
|
119
|
+
let range;
|
|
120
|
+
switch (arg.type) {
|
|
121
|
+
case 'address':
|
|
122
|
+
if (arg.spill) {
|
|
123
|
+
let sheet;
|
|
124
|
+
if (arg.sheet_id) {
|
|
125
|
+
sheet = this.data_model.sheets.Find(arg.sheet_id);
|
|
126
|
+
}
|
|
127
|
+
if (!sheet) {
|
|
128
|
+
console.error('missing sheet [da6]');
|
|
129
|
+
return ReferenceError();
|
|
130
|
+
}
|
|
131
|
+
const cell_data = sheet.CellData(arg);
|
|
132
|
+
if (cell_data.spill) {
|
|
133
|
+
range = cell_data.spill;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
address = arg;
|
|
138
|
+
}
|
|
139
|
+
break;
|
|
140
|
+
case 'range':
|
|
141
|
+
range = arg;
|
|
142
|
+
break;
|
|
143
|
+
case 'structured-reference':
|
|
144
|
+
{
|
|
145
|
+
const resolved = this.data_model.ResolveStructuredReference(arg, this.context.address);
|
|
146
|
+
if (resolved) {
|
|
147
|
+
if (resolved.type === 'address') {
|
|
148
|
+
address = resolved;
|
|
149
|
+
}
|
|
150
|
+
else if (resolved.type === 'range') {
|
|
151
|
+
range = resolved;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
break;
|
|
156
|
+
case 'identifier':
|
|
157
|
+
{
|
|
158
|
+
const named_range = this.data_model.GetName(arg.name, this.context.address.sheet_id || 0);
|
|
159
|
+
if (named_range?.type === 'range') {
|
|
160
|
+
if (named_range.area.count === 1) {
|
|
161
|
+
address = named_range.area.start; // FIXME: range?
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
range = named_range.area;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
case 'call':
|
|
170
|
+
// we need a way to cascade the 'metadata' flag down
|
|
171
|
+
// through calls so we can use indirect/offset addressing...
|
|
172
|
+
// at the same time you don't want to cascade down indefinitely,
|
|
173
|
+
// otherwise the function call itself won't work properly...
|
|
174
|
+
// [how to resolve?]
|
|
175
|
+
{
|
|
176
|
+
const result = this.CalculateExpression(arg, true) /*UnionOrArray*/;
|
|
177
|
+
if (UnionIsExpressionUnit(result)) {
|
|
178
|
+
if (result.value.type === 'address') {
|
|
179
|
+
address = result.value;
|
|
180
|
+
}
|
|
181
|
+
else if (result.value.type === 'range') {
|
|
182
|
+
range = result.value;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else
|
|
189
|
+
return result;
|
|
190
|
+
}
|
|
191
|
+
break;
|
|
192
|
+
default:
|
|
193
|
+
return this.CalculateExpression(arg); // as UnionOrArray;
|
|
194
|
+
}
|
|
195
|
+
if (address) {
|
|
196
|
+
// don't we have a map? [...] only for names?
|
|
197
|
+
let sheet;
|
|
198
|
+
if (address.sheet_id) {
|
|
199
|
+
sheet = this.data_model.sheets.Find(address.sheet_id);
|
|
200
|
+
}
|
|
201
|
+
if (!sheet) {
|
|
202
|
+
console.error('missing sheet [ac8]');
|
|
203
|
+
return ReferenceError();
|
|
204
|
+
}
|
|
205
|
+
const cell_data = sheet.CellData(address);
|
|
206
|
+
const value = cell_data.calculated_type ? cell_data.calculated : cell_data.value;
|
|
207
|
+
const metadata = {
|
|
208
|
+
type: 'metadata',
|
|
209
|
+
// metadata is expecting a parse expression instead of an addresss.
|
|
210
|
+
// note we're not setting the label properly here, which could be
|
|
211
|
+
// an issue? not sure who's calling it in this case
|
|
212
|
+
// UPDATE: "Cell" is calling it, so it needs a label
|
|
213
|
+
address: {
|
|
214
|
+
...address,
|
|
215
|
+
position: 0,
|
|
216
|
+
id: 0,
|
|
217
|
+
type: 'address',
|
|
218
|
+
label: new Area(address).spreadsheet_label,
|
|
219
|
+
},
|
|
220
|
+
value,
|
|
221
|
+
format: cell_data.style ? cell_data.style.number_format : undefined,
|
|
222
|
+
...transform(cell_data, address),
|
|
223
|
+
};
|
|
224
|
+
return { type: ValueType.object, value: metadata, key: 'metadata' };
|
|
225
|
+
}
|
|
226
|
+
else if (range) {
|
|
227
|
+
if (range.start.row === Infinity || range.start.column === Infinity) {
|
|
228
|
+
return ReferenceError();
|
|
229
|
+
}
|
|
230
|
+
let sheet;
|
|
231
|
+
if (range.start.sheet_id) {
|
|
232
|
+
sheet = this.data_model.sheets.Find(range.start.sheet_id);
|
|
233
|
+
}
|
|
234
|
+
if (!sheet) {
|
|
235
|
+
throw new Error('missing sheet [ac9]');
|
|
236
|
+
}
|
|
237
|
+
const range_result = [];
|
|
238
|
+
for (let column = range.start.column; column <= range.end.column; column++) {
|
|
239
|
+
const column_result = [];
|
|
240
|
+
for (let row = range.start.row; row <= range.end.row; row++) {
|
|
241
|
+
const cell_data = sheet.CellData({ row, column });
|
|
242
|
+
address = { ...range.start, row, column };
|
|
243
|
+
const value = cell_data.calculated_type ? cell_data.calculated : cell_data.value;
|
|
244
|
+
const metadata = {
|
|
245
|
+
type: 'metadata',
|
|
246
|
+
address,
|
|
247
|
+
value,
|
|
248
|
+
format: cell_data.style ? cell_data.style.number_format : undefined,
|
|
249
|
+
...transform(cell_data, address),
|
|
250
|
+
};
|
|
251
|
+
column_result.push({
|
|
252
|
+
type: ValueType.object,
|
|
253
|
+
value: metadata,
|
|
254
|
+
key: 'metadata',
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
range_result.push(column_result);
|
|
258
|
+
}
|
|
259
|
+
return { type: ValueType.array, value: range_result };
|
|
260
|
+
}
|
|
261
|
+
return this.CalculateExpression(arg); /*UnionOrArray*/
|
|
262
|
+
}
|
|
263
|
+
RewriteMacro(unit, names) {
|
|
264
|
+
let expr;
|
|
265
|
+
switch (unit.type) {
|
|
266
|
+
case 'identifier':
|
|
267
|
+
expr = names[unit.name.toUpperCase()];
|
|
268
|
+
if (expr) {
|
|
269
|
+
return JSON.parse(JSON.stringify(expr));
|
|
270
|
+
}
|
|
271
|
+
break;
|
|
272
|
+
case 'binary':
|
|
273
|
+
unit.left = this.RewriteMacro(unit.left, names);
|
|
274
|
+
unit.right = this.RewriteMacro(unit.right, names);
|
|
275
|
+
break;
|
|
276
|
+
case 'unary':
|
|
277
|
+
unit.operand = this.RewriteMacro(unit.operand, names);
|
|
278
|
+
break;
|
|
279
|
+
case 'group':
|
|
280
|
+
unit.elements = unit.elements.map(element => this.RewriteMacro(element, names));
|
|
281
|
+
break;
|
|
282
|
+
case 'call':
|
|
283
|
+
unit.args = unit.args.map(arg => this.RewriteMacro(arg, names));
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
return unit;
|
|
287
|
+
}
|
|
288
|
+
CallMacro(outer, macro) {
|
|
289
|
+
if (!macro.expression) {
|
|
290
|
+
return () => ExpressionError();
|
|
291
|
+
}
|
|
292
|
+
const text_expr = JSON.stringify(macro.expression);
|
|
293
|
+
const names = {};
|
|
294
|
+
const upper_case_names = macro.argument_names?.map(name => name.toUpperCase()) || [];
|
|
295
|
+
return (expr) => {
|
|
296
|
+
const clone = JSON.parse(text_expr);
|
|
297
|
+
for (let i = 0; i < upper_case_names.length; i++) {
|
|
298
|
+
names[upper_case_names[i]] = expr.args[i] || { type: 'missing', id: 0 };
|
|
299
|
+
}
|
|
300
|
+
return this.CalculateExpression(this.RewriteMacro(clone, names));
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* split out from ImplicitCall so we can reuse
|
|
305
|
+
*/
|
|
306
|
+
ImplicitCallTail(result, args) {
|
|
307
|
+
const value = result.value;
|
|
308
|
+
if (!value.func || !value.bindings) {
|
|
309
|
+
return ExpressionError();
|
|
310
|
+
}
|
|
311
|
+
const frame = {};
|
|
312
|
+
for (let i = 0; i < value.bindings.length; i++) {
|
|
313
|
+
const name = value.bindings[i];
|
|
314
|
+
if (name?.type === 'identifier') {
|
|
315
|
+
frame[name.name.toUpperCase()] = args[i] || { type: 'missing' };
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
// should not happen, error
|
|
319
|
+
return ExpressionError();
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
const munged = JSON.parse(JSON.stringify(value.func));
|
|
323
|
+
this.parser.Walk2(munged, (unit) => {
|
|
324
|
+
if (unit.type === 'identifier') {
|
|
325
|
+
const upper_case = unit.name.toUpperCase();
|
|
326
|
+
const binding = frame[upper_case];
|
|
327
|
+
if (binding) {
|
|
328
|
+
return JSON.parse(JSON.stringify(binding));
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return true;
|
|
332
|
+
});
|
|
333
|
+
return this.CalculateExpression(munged);
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* an FP call will need to set bindings and call an expression,
|
|
337
|
+
* possibly multiple times. this is a support function for that.
|
|
338
|
+
*/
|
|
339
|
+
Apply(fn, args) {
|
|
340
|
+
// kind of going backwards here, converting values to expressions...
|
|
341
|
+
// the reason is that we rewrite lambdas to support recursion
|
|
342
|
+
const mapped = args.map(arg => {
|
|
343
|
+
switch (arg.type) {
|
|
344
|
+
case ValueType.number:
|
|
345
|
+
case ValueType.boolean:
|
|
346
|
+
case ValueType.string:
|
|
347
|
+
return {
|
|
348
|
+
type: 'literal', value: arg.value, id: 0, position: 0,
|
|
349
|
+
};
|
|
350
|
+
case ValueType.error:
|
|
351
|
+
return {
|
|
352
|
+
type: 'literal', value: '#' + arg.value, id: 0, position: 0,
|
|
353
|
+
};
|
|
354
|
+
case ValueType.array:
|
|
355
|
+
{
|
|
356
|
+
const values = [];
|
|
357
|
+
for (let c = 0; c < arg.value.length; c++) {
|
|
358
|
+
const col = arg.value[c];
|
|
359
|
+
const mapped_col = [];
|
|
360
|
+
for (let r = 0; r < col.length; r++) {
|
|
361
|
+
const val = col[r];
|
|
362
|
+
switch (val.type) {
|
|
363
|
+
case ValueType.boolean:
|
|
364
|
+
case ValueType.number:
|
|
365
|
+
case ValueType.string:
|
|
366
|
+
mapped_col.push(val.value || undefined);
|
|
367
|
+
break;
|
|
368
|
+
default:
|
|
369
|
+
console.warn('unhandled array value', val);
|
|
370
|
+
mapped_col.push(undefined);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
values.push(mapped_col);
|
|
374
|
+
}
|
|
375
|
+
return {
|
|
376
|
+
type: 'array',
|
|
377
|
+
values,
|
|
378
|
+
id: 0, position: 0,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
case ValueType.undefined:
|
|
382
|
+
return {
|
|
383
|
+
type: 'missing', id: 0,
|
|
384
|
+
};
|
|
385
|
+
default:
|
|
386
|
+
// this (logging) is a problem in a simulation because
|
|
387
|
+
// it can bog down. we probably should only log once.
|
|
388
|
+
// or perhaps not at all?
|
|
389
|
+
console.warn('unhandled parameter value', arg);
|
|
390
|
+
}
|
|
391
|
+
return { type: 'missing', id: 0 };
|
|
392
|
+
});
|
|
393
|
+
return this.ImplicitCallTail(fn, mapped);
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* this method can take a `call` type if it looked like a call at
|
|
397
|
+
* the parsing stage, it's a simple translation between the two
|
|
398
|
+
*/
|
|
399
|
+
ImplicitCall() {
|
|
400
|
+
return (expr) => {
|
|
401
|
+
if (expr.type === 'call') {
|
|
402
|
+
expr = {
|
|
403
|
+
type: 'implicit-call',
|
|
404
|
+
args: expr.args,
|
|
405
|
+
call: {
|
|
406
|
+
type: 'identifier',
|
|
407
|
+
name: expr.name,
|
|
408
|
+
position: expr.position,
|
|
409
|
+
id: 0,
|
|
410
|
+
},
|
|
411
|
+
position: expr.position,
|
|
412
|
+
id: 0,
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
const result = this.CalculateExpression(expr.call);
|
|
416
|
+
if (result.type === ValueType.function) {
|
|
417
|
+
return this.ImplicitCallTail(result, expr.args);
|
|
418
|
+
}
|
|
419
|
+
return ExpressionError();
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
NormalizeBindings(context) {
|
|
423
|
+
const frame = {};
|
|
424
|
+
for (const [key, value] of Object.entries(context)) {
|
|
425
|
+
frame[key.toUpperCase()] = value;
|
|
426
|
+
}
|
|
427
|
+
return frame;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* excute a function call
|
|
431
|
+
*/
|
|
432
|
+
CallExpression(outer, return_reference = false) {
|
|
433
|
+
// get the function descriptor, which won't change.
|
|
434
|
+
// we can bind in closure (also short-circuit check for
|
|
435
|
+
// invalid name)
|
|
436
|
+
const func = this.library.Get(outer.name);
|
|
437
|
+
if (!func) {
|
|
438
|
+
const upper_case = outer.name.toUpperCase();
|
|
439
|
+
const binding = this.LookupBinding(upper_case);
|
|
440
|
+
if (binding) {
|
|
441
|
+
return this.ImplicitCall();
|
|
442
|
+
}
|
|
443
|
+
const named = this.data_model.GetName(upper_case, this.context.address.sheet_id || 0);
|
|
444
|
+
if (named) {
|
|
445
|
+
return this.ImplicitCall();
|
|
446
|
+
}
|
|
447
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
448
|
+
console.info('(dev) missing function', outer.name);
|
|
449
|
+
}
|
|
450
|
+
return () => NameError();
|
|
451
|
+
}
|
|
452
|
+
return (expr) => {
|
|
453
|
+
// set context volatile if this function is volatile. it will bubble
|
|
454
|
+
// through nested function calls, so the entire cell will be volatile
|
|
455
|
+
// if there's a volatile function in there somewhere
|
|
456
|
+
this.context.volatile = this.context.volatile || (!!func.volatile);
|
|
457
|
+
// we recurse calculation, but in the specific case of IF functions
|
|
458
|
+
// we can short-circuit and skip the unused code path. doesn't apply
|
|
459
|
+
// anywhere else atm
|
|
460
|
+
const if_function = outer.name.toLowerCase() === 'if';
|
|
461
|
+
let skip_argument_index = -1;
|
|
462
|
+
let argument_error;
|
|
463
|
+
// possibly create a binding frame. if we do that we may need
|
|
464
|
+
// to adjust the arguments as well (and the descriptors)
|
|
465
|
+
let args = expr.args;
|
|
466
|
+
let argument_descriptors = func.arguments || []; // map
|
|
467
|
+
let binding;
|
|
468
|
+
if (func.create_binding_context) {
|
|
469
|
+
// if this does not return a binding frame, it's an error.
|
|
470
|
+
binding = func.create_binding_context.call(0, {
|
|
471
|
+
args: expr.args,
|
|
472
|
+
descriptors: argument_descriptors,
|
|
473
|
+
});
|
|
474
|
+
if (binding) {
|
|
475
|
+
args = binding.args;
|
|
476
|
+
if (binding.argument_descriptors) {
|
|
477
|
+
argument_descriptors = binding.argument_descriptors;
|
|
478
|
+
}
|
|
479
|
+
this.context.bindings.unshift(this.NormalizeBindings(binding.context));
|
|
480
|
+
}
|
|
481
|
+
else {
|
|
482
|
+
argument_error = ArgumentError();
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
const mapped_args = args.map((arg, arg_index) => {
|
|
486
|
+
// short circuit
|
|
487
|
+
if (argument_error) {
|
|
488
|
+
return undefined;
|
|
489
|
+
}
|
|
490
|
+
// get descriptor. if the number of arguments exceeds
|
|
491
|
+
// the number of descriptors, recycle the last one
|
|
492
|
+
// FIXME: we have a repeat flag, so we should repeat the
|
|
493
|
+
// correct argument(s). I guess we could default to this
|
|
494
|
+
// behavior.
|
|
495
|
+
const descriptor = argument_descriptors[Math.min(arg_index, argument_descriptors.length - 1)] || {};
|
|
496
|
+
// new for lambdas
|
|
497
|
+
if (descriptor.passthrough) {
|
|
498
|
+
return arg;
|
|
499
|
+
}
|
|
500
|
+
// if function, wrong branch
|
|
501
|
+
if (arg_index === skip_argument_index) {
|
|
502
|
+
return descriptor.boxed ? { type: ValueType.undefined } : undefined;
|
|
503
|
+
}
|
|
504
|
+
// note on type here: we're iterating over the arguments
|
|
505
|
+
// described by the parse expression, not the values. although
|
|
506
|
+
// in this case, wouldn't this be a missing type? (...)
|
|
507
|
+
if (typeof arg === 'undefined') {
|
|
508
|
+
if (if_function && arg_index === 0) {
|
|
509
|
+
skip_argument_index = 1;
|
|
510
|
+
}
|
|
511
|
+
return descriptor.boxed ? { type: ValueType.undefined } : undefined;
|
|
512
|
+
}
|
|
513
|
+
// FIXME (address): what about named ranges (actually those will work),
|
|
514
|
+
// constructed references (we don't support them atm)?
|
|
515
|
+
// NOTE: named ranges will _not_ work, because the address will be an
|
|
516
|
+
// object, not a string. so FIXME.
|
|
517
|
+
if (descriptor.address) {
|
|
518
|
+
return descriptor.boxed ? {
|
|
519
|
+
type: ValueType.string,
|
|
520
|
+
value: this.parser.Render(arg).replace(/\$/g, ''),
|
|
521
|
+
} : this.parser.Render(arg).replace(/\$/g, '');
|
|
522
|
+
}
|
|
523
|
+
else if (descriptor.metadata) {
|
|
524
|
+
return this.GetMetadata(arg, () => { return {}; }); // type is UnionOrArray
|
|
525
|
+
}
|
|
526
|
+
else {
|
|
527
|
+
const result = this.CalculateExpression(arg);
|
|
528
|
+
if (result.type === ValueType.error) { // array check is implicit since array is a type
|
|
529
|
+
if (descriptor.allow_error) {
|
|
530
|
+
return result; // always boxed
|
|
531
|
+
}
|
|
532
|
+
argument_error = result;
|
|
533
|
+
return undefined; // argument not used, so don't bother boxing
|
|
534
|
+
}
|
|
535
|
+
// can't shortcut if you have an array (or we need to test all the values)
|
|
536
|
+
if (if_function && arg_index === 0 && result.type !== ValueType.array) {
|
|
537
|
+
let result_truthy = false;
|
|
538
|
+
if (result.type === ValueType.string) {
|
|
539
|
+
const lowercase = result.value.toLowerCase().trim();
|
|
540
|
+
result_truthy = lowercase !== 'false' && lowercase !== 'f';
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
result_truthy = !!result.value;
|
|
544
|
+
}
|
|
545
|
+
skip_argument_index = result_truthy ? 2 : 1;
|
|
546
|
+
}
|
|
547
|
+
if (descriptor.boxed) {
|
|
548
|
+
return result;
|
|
549
|
+
}
|
|
550
|
+
if (result.type === ValueType.array) {
|
|
551
|
+
return result.value.map(row => row.map(value => value.value));
|
|
552
|
+
}
|
|
553
|
+
else {
|
|
554
|
+
return result.value; // unboxing
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
if (binding) {
|
|
559
|
+
this.context.bindings.shift();
|
|
560
|
+
}
|
|
561
|
+
if (argument_error) {
|
|
562
|
+
return argument_error;
|
|
563
|
+
}
|
|
564
|
+
// cloning, out of an abundance of caution
|
|
565
|
+
// const ctx = JSON.parse(JSON.stringify({ address: this.context.address, area: this.context.area }));
|
|
566
|
+
const ctx = {
|
|
567
|
+
address: { ...this.context.address },
|
|
568
|
+
area: this.context.area ? {
|
|
569
|
+
start: { ...this.context.area.start, },
|
|
570
|
+
end: { ...this.context.area.end, },
|
|
571
|
+
} : undefined,
|
|
572
|
+
apply: func.fp ? this.Apply.bind(this) : undefined,
|
|
573
|
+
};
|
|
574
|
+
const result = func.fn.apply(ctx, mapped_args);
|
|
575
|
+
if (func.return_type === 'reference') {
|
|
576
|
+
if (return_reference) {
|
|
577
|
+
return result;
|
|
578
|
+
}
|
|
579
|
+
if (UnionIsExpressionUnit(result)) {
|
|
580
|
+
if (result.value.type === 'address') {
|
|
581
|
+
return this.CellFunction2(result.value)();
|
|
582
|
+
}
|
|
583
|
+
else if (result.value.type === 'range') {
|
|
584
|
+
return this.CellFunction4(result.value.start, result.value.end);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
return result; // error?
|
|
588
|
+
}
|
|
589
|
+
return result; // func.fn.apply(ctx, mapped_args);
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
ResolveStructuredReference(expr) {
|
|
593
|
+
// basically our approach here is to resolve the structured reference
|
|
594
|
+
// to a concrete reference.
|
|
595
|
+
//
|
|
596
|
+
// if the structured reference changes, then it will get recalculated
|
|
597
|
+
// (and hence rebuilt). if the table name or a referenced column name
|
|
598
|
+
// changes, the cell will get rewritten so again, it will get recalculated.
|
|
599
|
+
//
|
|
600
|
+
// the case we have to worry about is if the table layout changes: if a
|
|
601
|
+
// column is added or removed. because in that case, our reference will
|
|
602
|
+
// be out of date but we won't be notified about it.
|
|
603
|
+
//
|
|
604
|
+
// so we will have to make sure that if a table layout changes, columns
|
|
605
|
+
// or rows added or deleted, then we invalidate the entire table. if we
|
|
606
|
+
// do that this should all work out.
|
|
607
|
+
const resolved = this.data_model.ResolveStructuredReference(expr, this.context.address);
|
|
608
|
+
if (resolved) {
|
|
609
|
+
if (resolved.type === 'address') {
|
|
610
|
+
return this.CellFunction2(resolved);
|
|
611
|
+
}
|
|
612
|
+
else if (resolved.type === 'range') {
|
|
613
|
+
return () => this.CellFunction4(resolved.start, resolved.end);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
return () => ReferenceError();
|
|
617
|
+
}
|
|
618
|
+
ResolveDimensionedQuantity() {
|
|
619
|
+
return (expr) => {
|
|
620
|
+
const expression = this.CalculateExpression(expr.expression);
|
|
621
|
+
return {
|
|
622
|
+
type: ValueType.dimensioned_quantity,
|
|
623
|
+
value: {
|
|
624
|
+
value: expression.value,
|
|
625
|
+
unit: expr.unit.name,
|
|
626
|
+
},
|
|
627
|
+
};
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
UnaryExpression(x, return_reference = false) {
|
|
631
|
+
// there are basically three code paths here: negate, identity, and error.
|
|
632
|
+
// they have very different semantics so we're going to do them completely
|
|
633
|
+
// separately.
|
|
634
|
+
switch (x.operator) {
|
|
635
|
+
case '+':
|
|
636
|
+
return (expr) => {
|
|
637
|
+
return this.CalculateExpression(expr.operand);
|
|
638
|
+
};
|
|
639
|
+
case '-':
|
|
640
|
+
{
|
|
641
|
+
const func = Primitives.Subtract;
|
|
642
|
+
const zero = { type: ValueType.number, value: 0 };
|
|
643
|
+
return (expr) => {
|
|
644
|
+
const operand = this.CalculateExpression(expr.operand);
|
|
645
|
+
if (operand.type === ValueType.array) {
|
|
646
|
+
return {
|
|
647
|
+
type: ValueType.array,
|
|
648
|
+
value: operand.value.map(column => column.map(value => func(zero, value))),
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
return func(zero, operand);
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
case '@':
|
|
655
|
+
return (expr) => {
|
|
656
|
+
// if the operand is a range, then we need to do implicit intersection.
|
|
657
|
+
// otherwise, calculate the expression and return the first value
|
|
658
|
+
// if it's an array.
|
|
659
|
+
let address;
|
|
660
|
+
switch (expr.operand.type) {
|
|
661
|
+
case 'address':
|
|
662
|
+
if (expr.operand.spill) {
|
|
663
|
+
// we need to calculate the result so we know how large the
|
|
664
|
+
// range is... perhaps there's a way to look this up without
|
|
665
|
+
// calculating? (TODO/FIXME)
|
|
666
|
+
const calculated = this.CellFunction2(expr.operand)();
|
|
667
|
+
if (calculated.type === ValueType.array) {
|
|
668
|
+
const row = this.context.address.row ?? -1;
|
|
669
|
+
const column = this.context.address.column ?? -1;
|
|
670
|
+
// for this verison we already have the result, so unless
|
|
671
|
+
// we're trying to preserve the address, we could just
|
|
672
|
+
// return it
|
|
673
|
+
if (row >= expr.operand.row && row < expr.operand.row + calculated.value[0]?.length && calculated.value.length === 1) {
|
|
674
|
+
if (!return_reference) {
|
|
675
|
+
return calculated.value[0][row - expr.operand.row];
|
|
676
|
+
}
|
|
677
|
+
address = {
|
|
678
|
+
...expr.operand,
|
|
679
|
+
row,
|
|
680
|
+
spill: false,
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
else if (column >= expr.operand.column && column < expr.operand.column + calculated.value.length && calculated.value[0]?.length === 1) {
|
|
684
|
+
if (!return_reference) {
|
|
685
|
+
return calculated.value[column - expr.operand.column][0];
|
|
686
|
+
}
|
|
687
|
+
address = {
|
|
688
|
+
...expr.operand,
|
|
689
|
+
column,
|
|
690
|
+
spill: false,
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
else {
|
|
694
|
+
return ValueError(); // out of range
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
// return { type: ValueType.string, value: 'implicit (spill)' };
|
|
698
|
+
}
|
|
699
|
+
break;
|
|
700
|
+
case 'range':
|
|
701
|
+
{
|
|
702
|
+
// how do we intersect, if at all?
|
|
703
|
+
const row = this.context.address.row ?? -1;
|
|
704
|
+
const column = this.context.address.column ?? -1;
|
|
705
|
+
if (row >= expr.operand.start.row && row <= expr.operand.end.row && expr.operand.start.column === expr.operand.end.column) {
|
|
706
|
+
address = {
|
|
707
|
+
...expr.operand.start,
|
|
708
|
+
row,
|
|
709
|
+
spill: false,
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
else if (column >= expr.operand.start.column && column <= expr.operand.end.column && expr.operand.start.row === expr.operand.end.row) {
|
|
713
|
+
address = {
|
|
714
|
+
...expr.operand.start,
|
|
715
|
+
column,
|
|
716
|
+
spill: false,
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
else {
|
|
720
|
+
return ValueError(); // out of range
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
if (address) {
|
|
725
|
+
if (return_reference) {
|
|
726
|
+
return { type: ValueType.object, value: address,
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
return this.CellFunction2(address)();
|
|
730
|
+
}
|
|
731
|
+
const operand = this.CalculateExpression(expr.operand);
|
|
732
|
+
if (operand.type === ValueType.array) {
|
|
733
|
+
return operand.value[0][0];
|
|
734
|
+
}
|
|
735
|
+
return operand;
|
|
736
|
+
};
|
|
737
|
+
default:
|
|
738
|
+
return () => {
|
|
739
|
+
console.warn('unexpected unary operator:', x.operator);
|
|
740
|
+
return ExpressionError();
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* expands the size of an array by recycling values in columns and rows
|
|
746
|
+
*
|
|
747
|
+
* FIXME: seems like this is more a generic thing, -> utils lib
|
|
748
|
+
*
|
|
749
|
+
* @param arr 2d array
|
|
750
|
+
* @param columns target columns
|
|
751
|
+
* @param rows target rows
|
|
752
|
+
*/
|
|
753
|
+
RecycleArray(arr, columns, rows) {
|
|
754
|
+
// NOTE: recycle rows first, more efficient. do it in place?
|
|
755
|
+
if (arr[0].length < rows) {
|
|
756
|
+
const len = arr[0].length;
|
|
757
|
+
for (const column of arr) {
|
|
758
|
+
for (let r = len; r < rows; r++) {
|
|
759
|
+
column[r] = column[r % len];
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
if (arr.length < columns) {
|
|
764
|
+
const len = arr.length;
|
|
765
|
+
for (let c = len; c < columns; c++)
|
|
766
|
+
arr[c] = arr[c % len].slice(0);
|
|
767
|
+
}
|
|
768
|
+
return arr;
|
|
769
|
+
}
|
|
770
|
+
ElementwiseBinaryExpression(fn, left, right) {
|
|
771
|
+
const columns = Math.max(left.value.length, right.value.length);
|
|
772
|
+
const rows = Math.max(left.value[0].length, right.value[0].length);
|
|
773
|
+
const left_values = this.RecycleArray(left.value, columns, rows);
|
|
774
|
+
const right_values = this.RecycleArray(right.value, columns, rows);
|
|
775
|
+
const value = [];
|
|
776
|
+
for (let c = 0; c < columns; c++) {
|
|
777
|
+
const col = [];
|
|
778
|
+
for (let r = 0; r < rows; r++) {
|
|
779
|
+
// handle undefineds. this is unfortunate. shouldn't the recycle
|
|
780
|
+
// function do that? ...CHECK/TODO/FIXME
|
|
781
|
+
col[r] = fn(left_values[c][r] || { type: ValueType.undefined }, right_values[c][r] || { type: ValueType.undefined });
|
|
782
|
+
}
|
|
783
|
+
value.push(col);
|
|
784
|
+
}
|
|
785
|
+
return { type: ValueType.array, value };
|
|
786
|
+
}
|
|
787
|
+
/**
|
|
788
|
+
* convert expr to a cell address, possibly calculating the contents.
|
|
789
|
+
* returns single address only (ranges with len > 1 will fail)
|
|
790
|
+
*/
|
|
791
|
+
AsReference(expr) {
|
|
792
|
+
switch (expr.type) {
|
|
793
|
+
case 'address':
|
|
794
|
+
return expr;
|
|
795
|
+
case 'range':
|
|
796
|
+
if (expr.start.row === expr.end.row && expr.start.column === expr.end.column) {
|
|
797
|
+
return expr.start;
|
|
798
|
+
}
|
|
799
|
+
break;
|
|
800
|
+
default:
|
|
801
|
+
{
|
|
802
|
+
const union = this.CalculateExpression(expr, true);
|
|
803
|
+
if (UnionIsExpressionUnit(union)) {
|
|
804
|
+
if (union.value.type === 'address') {
|
|
805
|
+
return union.value;
|
|
806
|
+
}
|
|
807
|
+
if (union.value.type === 'range' && union.value.start.row === union.value.end.row && union.value.start.column === union.value.end.column) {
|
|
808
|
+
return union.value.start;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
break;
|
|
813
|
+
}
|
|
814
|
+
return undefined;
|
|
815
|
+
}
|
|
816
|
+
BinaryExpression(x) {
|
|
817
|
+
// we are constructing and caching functions for binary expressions.
|
|
818
|
+
// this should simplify calls when parameters change. eventually I'd
|
|
819
|
+
// like to do this for other dynamic calls as well...
|
|
820
|
+
// the idea is that we can start composing compound expressions. still
|
|
821
|
+
// not sure if that will work (or if it's a good idea).
|
|
822
|
+
// NOTE (for the future?) if one or both of the operands is a literal,
|
|
823
|
+
// we can bind that directly. literals in the expression won't change
|
|
824
|
+
// unless the expression changes, which will discard the generated
|
|
825
|
+
// function (along with the expression itself).
|
|
826
|
+
// pulling out concat so we can bind the model for language values
|
|
827
|
+
const fn = x.operator === '&' ? (a, b) => {
|
|
828
|
+
// this works, but it's not volatile so it doesn't update on
|
|
829
|
+
// a language change; maybe language change should force a recalc? (...)
|
|
830
|
+
if (a.type === ValueType.error) {
|
|
831
|
+
return a;
|
|
832
|
+
}
|
|
833
|
+
if (b.type === ValueType.error) {
|
|
834
|
+
return b;
|
|
835
|
+
}
|
|
836
|
+
const strings = [a, b].map(x => {
|
|
837
|
+
if (x.type === ValueType.undefined) {
|
|
838
|
+
return '';
|
|
839
|
+
}
|
|
840
|
+
if (x.type === ValueType.boolean) {
|
|
841
|
+
if (x.value) {
|
|
842
|
+
return this.data_model.language_model?.boolean_true || 'TRUE';
|
|
843
|
+
}
|
|
844
|
+
else {
|
|
845
|
+
return this.data_model.language_model?.boolean_false || 'FALSE';
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
return x.value;
|
|
849
|
+
});
|
|
850
|
+
return {
|
|
851
|
+
type: ValueType.string,
|
|
852
|
+
value: `${strings[0]}${strings[1]}`,
|
|
853
|
+
};
|
|
854
|
+
} : Primitives.MapOperator(x.operator);
|
|
855
|
+
if (!fn) {
|
|
856
|
+
// support dynamically-constructed ranges, as long as the
|
|
857
|
+
// arguments are both addresses (we might see ranges, but
|
|
858
|
+
// if they are 1x1 then we can accept them)
|
|
859
|
+
if (x.operator === ':') {
|
|
860
|
+
return (expr) => {
|
|
861
|
+
const start = this.AsReference(expr.left);
|
|
862
|
+
const end = this.AsReference(expr.right);
|
|
863
|
+
if (start && end) {
|
|
864
|
+
return this.CellFunction4(start, end);
|
|
865
|
+
}
|
|
866
|
+
return ExpressionError();
|
|
867
|
+
};
|
|
868
|
+
}
|
|
869
|
+
return () => {
|
|
870
|
+
console.info(`(unexpected binary operator: ${x.operator})`);
|
|
871
|
+
return ExpressionError();
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
else {
|
|
875
|
+
return (expr) => {
|
|
876
|
+
// sloppy typing, to support operators? (...)
|
|
877
|
+
const left = this.CalculateExpression(expr.left);
|
|
878
|
+
const right = this.CalculateExpression(expr.right);
|
|
879
|
+
// check for arrays. do elementwise operations.
|
|
880
|
+
if (left.type === ValueType.array) {
|
|
881
|
+
if (right.type === ValueType.array) {
|
|
882
|
+
return this.ElementwiseBinaryExpression(fn, left, right);
|
|
883
|
+
}
|
|
884
|
+
return this.ElementwiseBinaryExpression(fn, left, { type: ValueType.array, value: [[right]] });
|
|
885
|
+
}
|
|
886
|
+
else if (right.type === ValueType.array) {
|
|
887
|
+
return this.ElementwiseBinaryExpression(fn, { type: ValueType.array, value: [[left]] }, right);
|
|
888
|
+
}
|
|
889
|
+
return fn(left, right);
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
Identifier(expr) {
|
|
894
|
+
// NOTE: TRUE and FALSE don't get here -- they are converted
|
|
895
|
+
// to literals by the parser? (...)
|
|
896
|
+
// the function we create here binds the name because
|
|
897
|
+
// this is a literal identifier. if the value were to change,
|
|
898
|
+
// the expression would be discarded.
|
|
899
|
+
// however we have to do the lookup dynamically because the
|
|
900
|
+
// underlying reference (in the named range map) might change.
|
|
901
|
+
// although it's worth noting that, atm at least, that wouldn't
|
|
902
|
+
// trigger an update because it's not considered a value change.
|
|
903
|
+
// you'd have to recalc, which would rebuild the expression anyway.
|
|
904
|
+
// call that a FIXME? (...)
|
|
905
|
+
const identifier = expr.name;
|
|
906
|
+
// anything starting with # is an error. the only thing we should
|
|
907
|
+
// have is #REF, but maybe that will change in the future.
|
|
908
|
+
if (identifier[0] === '#') {
|
|
909
|
+
return () => ReferenceError();
|
|
910
|
+
}
|
|
911
|
+
const upper_case = identifier.toUpperCase();
|
|
912
|
+
switch (upper_case) {
|
|
913
|
+
case 'FALSE':
|
|
914
|
+
// case 'F':
|
|
915
|
+
return () => { return { value: false, type: ValueType.boolean }; };
|
|
916
|
+
case 'TRUE':
|
|
917
|
+
// case 'T':
|
|
918
|
+
return () => { return { value: true, type: ValueType.boolean }; };
|
|
919
|
+
case 'UNDEFINED':
|
|
920
|
+
return () => { return { value: undefined, type: ValueType.undefined }; }; // why do we support this?
|
|
921
|
+
}
|
|
922
|
+
return () => {
|
|
923
|
+
const binding = this.LookupBinding(upper_case);
|
|
924
|
+
if (binding) {
|
|
925
|
+
return this.CalculateExpression(binding);
|
|
926
|
+
}
|
|
927
|
+
const named = this.data_model.GetName(upper_case, this.context.address.sheet_id || 0);
|
|
928
|
+
switch (named?.type) {
|
|
929
|
+
case 'range':
|
|
930
|
+
if (named.area.count === 1) {
|
|
931
|
+
return this.CellFunction4(named.area.start, named.area.start);
|
|
932
|
+
}
|
|
933
|
+
return this.CellFunction4(named.area.start, named.area.end);
|
|
934
|
+
case 'expression':
|
|
935
|
+
return this.CalculateExpression(named.expression);
|
|
936
|
+
}
|
|
937
|
+
// console.info( '** identifier', {identifier, expr, context: this.context});
|
|
938
|
+
return NameError();
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
/**
|
|
942
|
+
* look up an identifier in any binding frames. we do LIFO binding.
|
|
943
|
+
*
|
|
944
|
+
* @param name
|
|
945
|
+
* @returns
|
|
946
|
+
*/
|
|
947
|
+
LookupBinding(name) {
|
|
948
|
+
name = name.toUpperCase();
|
|
949
|
+
for (const frame of this.context.bindings) {
|
|
950
|
+
const value = frame[name];
|
|
951
|
+
if (value) {
|
|
952
|
+
return value;
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
return undefined;
|
|
956
|
+
}
|
|
957
|
+
GroupExpression(x) {
|
|
958
|
+
// a group is an expression in parentheses, either explicit
|
|
959
|
+
// (from the user) or implicit (created to manage operation
|
|
960
|
+
// priority, order of operations, or similar).
|
|
961
|
+
// expressions nest, so there's no case where a group should
|
|
962
|
+
// have length !== 1 -- consider that an error.
|
|
963
|
+
if (!x.elements || x.elements.length !== 1) {
|
|
964
|
+
console.warn(`Can't handle group !== 1`);
|
|
965
|
+
return () => ExpressionError();
|
|
966
|
+
}
|
|
967
|
+
return (expr) => this.CalculateExpression(expr.elements[0]);
|
|
968
|
+
}
|
|
969
|
+
CalculateExpression(expr, return_reference = false) {
|
|
970
|
+
// user data is a generated function for the expression, at least
|
|
971
|
+
// for the simple ones (atm). see BinaryExpression for more. the
|
|
972
|
+
// aim is to remove as many tests and lookups as possible.
|
|
973
|
+
// may be over-optimizing here.
|
|
974
|
+
if (expr.fn) {
|
|
975
|
+
return expr.fn(expr);
|
|
976
|
+
}
|
|
977
|
+
switch (expr.type) {
|
|
978
|
+
case 'implicit-call':
|
|
979
|
+
return (expr.fn = this.ImplicitCall())(expr);
|
|
980
|
+
case 'call':
|
|
981
|
+
{
|
|
982
|
+
const macro = this.data_model.macro_functions.get(expr.name.toUpperCase());
|
|
983
|
+
if (macro) {
|
|
984
|
+
return (expr.fn = this.CallMacro(expr, macro))(expr);
|
|
985
|
+
}
|
|
986
|
+
return (expr.fn = this.CallExpression(expr, return_reference))(expr);
|
|
987
|
+
}
|
|
988
|
+
case 'address':
|
|
989
|
+
return (expr.fn = this.CellFunction2(expr))(); // check
|
|
990
|
+
case 'range':
|
|
991
|
+
return (expr.fn = (x) => this.CellFunction4(x.start, x.end))(expr); // check
|
|
992
|
+
case 'binary':
|
|
993
|
+
return (expr.fn = this.BinaryExpression(expr))(expr); // check
|
|
994
|
+
case 'unary':
|
|
995
|
+
return (expr.fn = this.UnaryExpression(expr, return_reference))(expr); // check
|
|
996
|
+
case 'identifier':
|
|
997
|
+
return (expr.fn = this.Identifier(expr))(); // check
|
|
998
|
+
case 'missing':
|
|
999
|
+
return (expr.fn = () => { return { value: undefined, type: ValueType.undefined }; })(); // check
|
|
1000
|
+
case 'dimensioned':
|
|
1001
|
+
return (expr.fn = this.ResolveDimensionedQuantity())(expr);
|
|
1002
|
+
case 'literal':
|
|
1003
|
+
{
|
|
1004
|
+
const literal = { value: expr.value, type: GetValueType(expr.value) };
|
|
1005
|
+
return (expr.fn = () => literal)(); // check
|
|
1006
|
+
}
|
|
1007
|
+
case 'group':
|
|
1008
|
+
return (expr.fn = this.GroupExpression(expr))(expr); // check
|
|
1009
|
+
case 'complex':
|
|
1010
|
+
{
|
|
1011
|
+
const literal = { value: { real: expr.real, imaginary: expr.imaginary }, type: ValueType.complex };
|
|
1012
|
+
return (expr.fn = () => literal)(); // check
|
|
1013
|
+
}
|
|
1014
|
+
case 'structured-reference':
|
|
1015
|
+
return (expr.fn = this.ResolveStructuredReference(expr))();
|
|
1016
|
+
case 'array':
|
|
1017
|
+
{
|
|
1018
|
+
return (expr.fn = () => {
|
|
1019
|
+
return {
|
|
1020
|
+
type: ValueType.array,
|
|
1021
|
+
value: expr.values.map((row) => (Array.isArray(row) ? row : [row]).map((value) => {
|
|
1022
|
+
return { type: GetValueType(value), value };
|
|
1023
|
+
})),
|
|
1024
|
+
};
|
|
1025
|
+
})();
|
|
1026
|
+
}
|
|
1027
|
+
default:
|
|
1028
|
+
console.warn('Unhandled parse expr:', expr);
|
|
1029
|
+
return UnknownError();
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
//# sourceMappingURL=expression-calculator.js.map
|