@bilig/formula 0.7.8 → 0.8.1

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.
Files changed (57) hide show
  1. package/dist/binder-wasm-arity.d.ts +1 -0
  2. package/dist/binder-wasm-arity.js +541 -0
  3. package/dist/binder-wasm-arity.js.map +1 -0
  4. package/dist/binder-wasm-rules.d.ts +1 -2
  5. package/dist/binder-wasm-rules.js +2 -540
  6. package/dist/binder-wasm-rules.js.map +1 -1
  7. package/dist/builtins/cell-value-utils.d.ts +9 -0
  8. package/dist/builtins/cell-value-utils.js +63 -0
  9. package/dist/builtins/cell-value-utils.js.map +1 -0
  10. package/dist/builtins/datetime.d.ts +2 -10
  11. package/dist/builtins/datetime.js +5 -261
  12. package/dist/builtins/datetime.js.map +1 -1
  13. package/dist/builtins/excel-date.d.ts +16 -0
  14. package/dist/builtins/excel-date.js +199 -0
  15. package/dist/builtins/excel-date.js.map +1 -0
  16. package/dist/builtins/lookup-core-helpers.d.ts +50 -0
  17. package/dist/builtins/lookup-core-helpers.js +342 -0
  18. package/dist/builtins/lookup-core-helpers.js.map +1 -0
  19. package/dist/builtins/lookup.d.ts +3 -25
  20. package/dist/builtins/lookup.js +3 -341
  21. package/dist/builtins/lookup.js.map +1 -1
  22. package/dist/formula-reference-translation.d.ts +20 -0
  23. package/dist/formula-reference-translation.js +273 -0
  24. package/dist/formula-reference-translation.js.map +1 -0
  25. package/dist/formula-serializer.d.ts +2 -0
  26. package/dist/formula-serializer.js +74 -0
  27. package/dist/formula-serializer.js.map +1 -0
  28. package/dist/formula-sheet-rename.d.ts +14 -0
  29. package/dist/formula-sheet-rename.js +243 -0
  30. package/dist/formula-sheet-rename.js.map +1 -0
  31. package/dist/formula-structural-rewrite.d.ts +14 -0
  32. package/dist/formula-structural-rewrite.js +511 -0
  33. package/dist/formula-structural-rewrite.js.map +1 -0
  34. package/dist/formula-template-key.d.ts +2 -0
  35. package/dist/formula-template-key.js +58 -0
  36. package/dist/formula-template-key.js.map +1 -1
  37. package/dist/js-evaluator-cell-values.d.ts +5 -0
  38. package/dist/js-evaluator-cell-values.js +14 -0
  39. package/dist/js-evaluator-cell-values.js.map +1 -0
  40. package/dist/js-evaluator-context-special-calls.js +72 -0
  41. package/dist/js-evaluator-context-special-calls.js.map +1 -1
  42. package/dist/js-evaluator-runtime-helpers.d.ts +39 -0
  43. package/dist/js-evaluator-runtime-helpers.js +453 -0
  44. package/dist/js-evaluator-runtime-helpers.js.map +1 -0
  45. package/dist/js-evaluator-types.d.ts +178 -0
  46. package/dist/js-evaluator-types.js +2 -0
  47. package/dist/js-evaluator-types.js.map +1 -0
  48. package/dist/js-evaluator.d.ts +4 -178
  49. package/dist/js-evaluator.js +3 -463
  50. package/dist/js-evaluator.js.map +1 -1
  51. package/dist/translation-reference-utils.d.ts +42 -0
  52. package/dist/translation-reference-utils.js +178 -0
  53. package/dist/translation-reference-utils.js.map +1 -0
  54. package/dist/translation.d.ts +6 -32
  55. package/dist/translation.js +14 -1300
  56. package/dist/translation.js.map +1 -1
  57. package/package.json +2 -2
@@ -1,37 +1,13 @@
1
- import { ErrorCode, FormulaMode } from '@bilig/protocol';
2
- import { formatRangeAddress, parseCellAddress, parseRangeAddress } from './addressing.js';
3
- import { compileFormulaAst, } from './compiler.js';
1
+ import { FormulaMode } from '@bilig/protocol';
2
+ import { parseRangeAddress } from './addressing.js';
4
3
  import { parseFormula } from './parser.js';
5
- const CELL_REF_RE = /^(\$?)([A-Z]+)(\$?)([1-9][0-9]*)$/;
6
- const COLUMN_REF_RE = /^(\$?)([A-Z]+)$/;
7
- const ROW_REF_RE = /^(\$?)([1-9][0-9]*)$/;
8
- const BINARY_PRECEDENCE = {
9
- '=': 1,
10
- '<>': 1,
11
- '>': 1,
12
- '>=': 1,
13
- '<': 1,
14
- '<=': 1,
15
- '&': 2,
16
- '+': 3,
17
- '-': 3,
18
- '*': 4,
19
- '/': 4,
20
- '^': 5,
21
- };
22
- function assertNever(value) {
23
- throw new Error(`Unexpected value: ${String(value)}`);
24
- }
25
- const ERROR_LITERAL_TEXT = {
26
- [ErrorCode.Ref]: '#REF!',
27
- [ErrorCode.Name]: '#NAME?',
28
- [ErrorCode.Div0]: '#DIV/0!',
29
- [ErrorCode.NA]: '#N/A',
30
- [ErrorCode.Value]: '#VALUE!',
31
- [ErrorCode.Cycle]: '#CYCLE!',
32
- [ErrorCode.Spill]: '#SPILL!',
33
- [ErrorCode.Blocked]: '#BLOCKED!',
34
- };
4
+ import { serializeFormula } from './formula-serializer.js';
5
+ import { buildRelativeFormulaTemplateAstKey } from './formula-template-key.js';
6
+ import { renameCompiledFormulaSheetReferenceMetadata as renameCompiledFormulaSheetReferenceMetadataImpl, renameCompiledFormulaSheetReferenceMetadataInPlace as renameCompiledFormulaSheetReferenceMetadataInPlaceImpl, renameCompiledFormulaSheetReferences as renameCompiledFormulaSheetReferencesImpl, renameFormulaSheetReferences as renameFormulaSheetReferencesImpl, } from './formula-sheet-rename.js';
7
+ import { buildTranslatedCellReferenceMap, buildTranslatedRangeReferenceMap, formatParsedCellReference, formatParsedDependencyReference, formatParsedLocalCellReference, formatParsedRangeReference, translatedCellInstructionKey, translatedRangeInstructionKey, translateCellReference, translateColumnReference, translateParsedCellReference, translateParsedDependencyReference, translateParsedRangeReference, translateQualifiedCellReference, translateQualifiedDependencyReference, translateQualifiedRangeReference, translateRangeAddress, translateRowReference, } from './formula-reference-translation.js';
8
+ import { quoteSheetNameIfNeeded } from './translation-reference-utils.js';
9
+ export { rewriteAddressForStructuralTransform, rewriteCompiledFormulaForStructuralTransform, rewriteFormulaForStructuralTransform, rewriteRangeForStructuralTransform, } from './formula-structural-rewrite.js';
10
+ export { serializeFormula } from './formula-serializer.js';
35
11
  export function translateFormulaReferences(source, rowDelta, colDelta) {
36
12
  const ast = parseFormula(source);
37
13
  return serializeFormula(translateNode(ast, rowDelta, colDelta));
@@ -40,7 +16,7 @@ export function buildRelativeFormulaTemplateKey(source, ownerRow, ownerCol) {
40
16
  return buildRelativeFormulaTemplateKeyFromAst(parseFormula(source), ownerRow, ownerCol);
41
17
  }
42
18
  export function buildRelativeFormulaTemplateKeyFromAst(node, ownerRow, ownerCol) {
43
- return buildRelativeFormulaTemplateKeyInternal(node, ownerRow, ownerCol);
19
+ return buildRelativeFormulaTemplateAstKey(node, ownerRow, ownerCol);
44
20
  }
45
21
  export function canTranslateCompiledFormulaWithoutAst(compiled) {
46
22
  return ((compiled.symbolicRanges.length === 0 || compiled.directAggregateCandidate !== undefined) &&
@@ -110,220 +86,17 @@ export function translateCompiledFormula(compiled, rowDelta, colDelta, sourceOve
110
86
  },
111
87
  };
112
88
  }
113
- export function rewriteFormulaForStructuralTransform(source, ownerSheetName, targetSheetName, transform) {
114
- const ast = parseFormula(source);
115
- return serializeFormula(rewriteNodeForStructuralTransform(ast, ownerSheetName, targetSheetName, transform));
116
- }
117
- export function rewriteCompiledFormulaForStructuralTransform(compiled, ownerSheetName, targetSheetName, transform) {
118
- const currentAst = compiled.astMatchesSource === false ? parseFormula(compiled.source) : compiled.ast;
119
- const currentOptimizedAst = compiled.astMatchesSource === false ? currentAst : compiled.optimizedAst === compiled.ast ? currentAst : compiled.optimizedAst;
120
- const rewrittenAst = rewriteNodeForStructuralTransform(currentAst, ownerSheetName, targetSheetName, transform);
121
- const rewrittenOptimizedAst = currentOptimizedAst === currentAst
122
- ? rewrittenAst
123
- : rewriteNodeForStructuralTransform(currentOptimizedAst, ownerSheetName, targetSheetName, transform);
124
- const source = serializeFormula(rewrittenAst);
125
- if (!nodeStructuralShapeEqual(currentOptimizedAst, rewrittenOptimizedAst)) {
126
- return {
127
- source,
128
- compiled: compileFormulaAst(source, rewrittenOptimizedAst, {
129
- originalAst: rewrittenAst,
130
- symbolicNames: compiled.symbolicNames,
131
- symbolicTables: compiled.symbolicTables,
132
- symbolicSpills: compiled.symbolicSpills,
133
- }),
134
- reusedProgram: false,
135
- };
136
- }
137
- return {
138
- source,
139
- compiled: {
140
- ...compiled,
141
- source,
142
- ast: rewrittenAst,
143
- optimizedAst: rewrittenOptimizedAst,
144
- astMatchesSource: true,
145
- deps: compiled.deps.map((dependency) => rewriteQualifiedDependencyReference(dependency, ownerSheetName, targetSheetName, transform)),
146
- symbolicRefs: compiled.symbolicRefs.map((ref) => rewriteQualifiedCellReference(ref, ownerSheetName, targetSheetName, transform)),
147
- symbolicRanges: compiled.symbolicRanges.map((range) => rewriteQualifiedRangeReference(range, ownerSheetName, targetSheetName, transform)),
148
- jsPlan: compiled.jsPlan.map((instruction) => rewriteJsPlanInstruction(instruction, ownerSheetName, targetSheetName, transform)),
149
- ...(compiled.parsedDeps
150
- ? {
151
- parsedDeps: compiled.parsedDeps.map((dependency) => rewriteParsedDependencyReference(dependency, ownerSheetName, targetSheetName, transform)),
152
- }
153
- : {}),
154
- ...(compiled.parsedSymbolicRefs
155
- ? {
156
- parsedSymbolicRefs: compiled.parsedSymbolicRefs.map((ref) => rewriteParsedCellReference(ref, ownerSheetName, targetSheetName, transform)),
157
- }
158
- : {}),
159
- ...(compiled.parsedSymbolicRanges
160
- ? {
161
- parsedSymbolicRanges: compiled.parsedSymbolicRanges.map((range) => rewriteParsedRangeReference(range, ownerSheetName, targetSheetName, transform)),
162
- }
163
- : {}),
164
- },
165
- reusedProgram: true,
166
- };
167
- }
168
89
  export function renameFormulaSheetReferences(source, oldSheetName, newSheetName) {
169
- const ast = parseFormula(source);
170
- return serializeFormula(renameNodeSheetReferences(ast, oldSheetName, newSheetName));
90
+ return renameFormulaSheetReferencesImpl(source, oldSheetName, newSheetName);
171
91
  }
172
92
  export function renameCompiledFormulaSheetReferences(compiled, oldSheetName, newSheetName) {
173
- const currentAst = compiled.astMatchesSource === false ? parseFormula(compiled.source) : compiled.ast;
174
- const currentOptimizedAst = compiled.astMatchesSource === false ? currentAst : compiled.optimizedAst === compiled.ast ? currentAst : compiled.optimizedAst;
175
- const renamedAst = renameNodeSheetReferences(currentAst, oldSheetName, newSheetName);
176
- const renamedOptimizedAst = currentOptimizedAst === currentAst ? renamedAst : renameNodeSheetReferences(currentOptimizedAst, oldSheetName, newSheetName);
177
- const source = serializeFormula(renamedAst);
178
- return {
179
- source,
180
- compiled: {
181
- ...compiled,
182
- source,
183
- ast: renamedAst,
184
- optimizedAst: renamedOptimizedAst,
185
- astMatchesSource: true,
186
- deps: compiled.deps.map((dependency) => renameQualifiedReferenceSheet(dependency, oldSheetName, newSheetName)),
187
- ...(compiled.parsedDeps
188
- ? {
189
- parsedDeps: compiled.parsedDeps.map((dependency) => renameParsedDependencySheet(dependency, oldSheetName, newSheetName)),
190
- }
191
- : {}),
192
- jsPlan: renameJsPlanSheetReferences(compiled.jsPlan, oldSheetName, newSheetName),
193
- symbolicRefs: compiled.symbolicRefs.map((reference) => renameQualifiedReferenceSheet(reference, oldSheetName, newSheetName)),
194
- ...(compiled.parsedSymbolicRefs
195
- ? {
196
- parsedSymbolicRefs: compiled.parsedSymbolicRefs.map((reference) => renameParsedCellReferenceSheet(reference, oldSheetName, newSheetName)),
197
- }
198
- : {}),
199
- symbolicRanges: compiled.symbolicRanges.map((reference) => renameQualifiedReferenceSheet(reference, oldSheetName, newSheetName)),
200
- ...(compiled.parsedSymbolicRanges
201
- ? {
202
- parsedSymbolicRanges: compiled.parsedSymbolicRanges.map((reference) => renameParsedRangeReferenceSheet(reference, oldSheetName, newSheetName)),
203
- }
204
- : {}),
205
- },
206
- reusedProgram: true,
207
- };
208
- }
209
- function renameArraySheetReferences(values, rename) {
210
- let changed = false;
211
- const next = values.map((value) => {
212
- const renamed = rename(value);
213
- if (renamed !== value) {
214
- changed = true;
215
- }
216
- return renamed;
217
- });
218
- return { values: next, changed };
93
+ return renameCompiledFormulaSheetReferencesImpl(compiled, oldSheetName, newSheetName);
219
94
  }
220
95
  export function renameCompiledFormulaSheetReferenceMetadata(compiled, oldSheetName, newSheetName) {
221
- const deps = renameArraySheetReferences(compiled.deps, (dependency) => renameQualifiedReferenceSheet(dependency, oldSheetName, newSheetName));
222
- const symbolicRefs = renameArraySheetReferences(compiled.symbolicRefs, (reference) => renameQualifiedReferenceSheet(reference, oldSheetName, newSheetName));
223
- const symbolicRanges = renameArraySheetReferences(compiled.symbolicRanges, (reference) => renameQualifiedReferenceSheet(reference, oldSheetName, newSheetName));
224
- const parsedDeps = compiled.parsedDeps
225
- ? renameArraySheetReferences(compiled.parsedDeps, (dependency) => renameParsedDependencySheet(dependency, oldSheetName, newSheetName))
226
- : undefined;
227
- const parsedSymbolicRefs = compiled.parsedSymbolicRefs
228
- ? renameArraySheetReferences(compiled.parsedSymbolicRefs, (reference) => renameParsedCellReferenceSheet(reference, oldSheetName, newSheetName))
229
- : undefined;
230
- const parsedSymbolicRanges = compiled.parsedSymbolicRanges
231
- ? renameArraySheetReferences(compiled.parsedSymbolicRanges, (reference) => renameParsedRangeReferenceSheet(reference, oldSheetName, newSheetName))
232
- : undefined;
233
- const jsPlan = renameJsPlanSheetReferences(compiled.jsPlan, oldSheetName, newSheetName);
234
- return {
235
- compiled: {
236
- ...compiled,
237
- astMatchesSource: false,
238
- deps: deps.values,
239
- ...(parsedDeps ? { parsedDeps: parsedDeps.values } : {}),
240
- jsPlan,
241
- symbolicRefs: symbolicRefs.values,
242
- ...(parsedSymbolicRefs ? { parsedSymbolicRefs: parsedSymbolicRefs.values } : {}),
243
- symbolicRanges: symbolicRanges.values,
244
- ...(parsedSymbolicRanges ? { parsedSymbolicRanges: parsedSymbolicRanges.values } : {}),
245
- },
246
- sourceChanged: deps.changed ||
247
- symbolicRefs.changed ||
248
- symbolicRanges.changed ||
249
- (parsedDeps?.changed ?? false) ||
250
- (parsedSymbolicRefs?.changed ?? false) ||
251
- (parsedSymbolicRanges?.changed ?? false),
252
- };
96
+ return renameCompiledFormulaSheetReferenceMetadataImpl(compiled, oldSheetName, newSheetName);
253
97
  }
254
98
  export function renameCompiledFormulaSheetReferenceMetadataInPlace(compiled, oldSheetName, newSheetName) {
255
- let sourceChanged = false;
256
- const renameStringArrayInPlace = (values) => {
257
- for (let index = 0; index < values.length; index += 1) {
258
- const value = values[index];
259
- const renamed = renameQualifiedReferenceSheet(value, oldSheetName, newSheetName);
260
- if (renamed !== value) {
261
- values[index] = renamed;
262
- sourceChanged = true;
263
- }
264
- }
265
- };
266
- renameStringArrayInPlace(compiled.deps);
267
- renameStringArrayInPlace(compiled.symbolicRefs);
268
- renameStringArrayInPlace(compiled.symbolicRanges);
269
- compiled.parsedDeps?.forEach((dependency) => {
270
- const previousSheetName = dependency.sheetName;
271
- if (previousSheetName === oldSheetName) {
272
- dependency.sheetName = newSheetName;
273
- sourceChanged = true;
274
- }
275
- });
276
- compiled.parsedSymbolicRefs?.forEach((reference) => {
277
- if (reference.sheetName === oldSheetName) {
278
- reference.sheetName = newSheetName;
279
- sourceChanged = true;
280
- }
281
- });
282
- compiled.parsedSymbolicRanges?.forEach((reference) => {
283
- if (reference.sheetName === oldSheetName) {
284
- reference.sheetName = newSheetName;
285
- sourceChanged = true;
286
- }
287
- });
288
- if (compiled.jsPlan.length > 0) {
289
- compiled.jsPlan = renameJsPlanSheetReferences(compiled.jsPlan, oldSheetName, newSheetName);
290
- }
291
- if (sourceChanged) {
292
- compiled.astMatchesSource = false;
293
- }
294
- return sourceChanged;
295
- }
296
- export function rewriteAddressForStructuralTransform(address, transform) {
297
- const parsed = parseCellReferenceParts(address);
298
- if (!parsed) {
299
- throw new Error(`Invalid cell reference '${address}'`);
300
- }
301
- const nextRow = transform.axis === 'row' ? mapPointIndex(parsed.row, transform) : parsed.row;
302
- const nextCol = transform.axis === 'column' ? mapPointIndex(parsed.col, transform) : parsed.col;
303
- if (nextRow === undefined || nextCol === undefined) {
304
- return undefined;
305
- }
306
- return formatCellReference(parsed, nextRow, nextCol);
307
- }
308
- export function rewriteRangeForStructuralTransform(startAddress, endAddress, transform) {
309
- const start = parseCellReferenceParts(startAddress);
310
- const end = parseCellReferenceParts(endAddress);
311
- if (!start || !end) {
312
- throw new Error(`Invalid range reference '${startAddress}:${endAddress}'`);
313
- }
314
- const nextRows = transform.axis === 'row'
315
- ? mapInterval(Math.min(start.row, end.row), Math.max(start.row, end.row), transform)
316
- : { start: Math.min(start.row, end.row), end: Math.max(start.row, end.row) };
317
- const nextCols = transform.axis === 'column'
318
- ? mapInterval(Math.min(start.col, end.col), Math.max(start.col, end.col), transform)
319
- : { start: Math.min(start.col, end.col), end: Math.max(start.col, end.col) };
320
- if (!nextRows || !nextCols) {
321
- return undefined;
322
- }
323
- return {
324
- startAddress: formatCellReference(start, nextRows.start, nextCols.start),
325
- endAddress: formatCellReference(end, nextRows.end, nextCols.end),
326
- };
99
+ return renameCompiledFormulaSheetReferenceMetadataInPlaceImpl(compiled, oldSheetName, newSheetName);
327
100
  }
328
101
  function translateNode(node, rowDelta, colDelta) {
329
102
  switch (node.kind) {
@@ -392,754 +165,6 @@ function translateNode(node, rowDelta, colDelta) {
392
165
  };
393
166
  }
394
167
  }
395
- function buildRelativeFormulaTemplateKeyInternal(node, ownerRow, ownerCol) {
396
- switch (node.kind) {
397
- case 'NumberLiteral':
398
- return `n:${node.value}`;
399
- case 'BooleanLiteral':
400
- return node.value ? 'b:1' : 'b:0';
401
- case 'StringLiteral':
402
- return `s:${JSON.stringify(node.value)}`;
403
- case 'ErrorLiteral':
404
- return `e:${node.code}`;
405
- case 'NameRef':
406
- return `name:${node.name}`;
407
- case 'StructuredRef':
408
- return `table:${node.tableName}[${node.columnName}]`;
409
- case 'CellRef':
410
- return `cell:${templateSheetKey(node.sheetName)}:${buildRelativeCellReferenceKey(node.ref, ownerRow, ownerCol)}`;
411
- case 'SpillRef':
412
- return `spill:${templateSheetKey(node.sheetName)}:${buildRelativeCellReferenceKey(node.ref, ownerRow, ownerCol)}`;
413
- case 'ColumnRef':
414
- return `col:${templateSheetKey(node.sheetName)}:${buildRelativeAxisReferenceKey(node.ref, ownerCol, 'column')}`;
415
- case 'RowRef':
416
- return `row:${templateSheetKey(node.sheetName)}:${buildRelativeAxisReferenceKey(node.ref, ownerRow, 'row')}`;
417
- case 'RangeRef':
418
- return `range:${node.refKind}:${templateSheetKey(node.sheetName)}:${buildRelativeRangeReferenceKey(node, ownerRow, ownerCol)}`;
419
- case 'UnaryExpr':
420
- return `unary:${node.operator}:${buildRelativeFormulaTemplateKeyInternal(node.argument, ownerRow, ownerCol)}`;
421
- case 'BinaryExpr':
422
- return `binary:${node.operator}:${buildRelativeFormulaTemplateKeyInternal(node.left, ownerRow, ownerCol)}:${buildRelativeFormulaTemplateKeyInternal(node.right, ownerRow, ownerCol)}`;
423
- case 'CallExpr':
424
- return `call:${node.callee}:${node.args.map((arg) => buildRelativeFormulaTemplateKeyInternal(arg, ownerRow, ownerCol)).join('|')}`;
425
- case 'InvokeExpr':
426
- return `invoke:${buildRelativeFormulaTemplateKeyInternal(node.callee, ownerRow, ownerCol)}:${node.args.map((arg) => buildRelativeFormulaTemplateKeyInternal(arg, ownerRow, ownerCol)).join('|')}`;
427
- }
428
- }
429
- function rewriteNodeForStructuralTransform(node, ownerSheetName, targetSheetName, transform) {
430
- switch (node.kind) {
431
- case 'NumberLiteral':
432
- case 'BooleanLiteral':
433
- case 'StringLiteral':
434
- case 'ErrorLiteral':
435
- case 'NameRef':
436
- case 'StructuredRef':
437
- return node;
438
- case 'CellRef':
439
- return rewriteCellLikeNode(node, ownerSheetName, targetSheetName, transform);
440
- case 'SpillRef':
441
- return rewriteCellLikeNode(node, ownerSheetName, targetSheetName, transform);
442
- case 'ColumnRef':
443
- if (!targetsSheet(node.sheetName, ownerSheetName, targetSheetName) || transform.axis !== 'column') {
444
- return node;
445
- }
446
- return rewriteAxisNode(node, transform);
447
- case 'RowRef':
448
- if (!targetsSheet(node.sheetName, ownerSheetName, targetSheetName) || transform.axis !== 'row') {
449
- return node;
450
- }
451
- return rewriteAxisNode(node, transform);
452
- case 'RangeRef':
453
- return rewriteRangeNode(node, ownerSheetName, targetSheetName, transform);
454
- case 'UnaryExpr':
455
- return {
456
- ...node,
457
- argument: rewriteNodeForStructuralTransform(node.argument, ownerSheetName, targetSheetName, transform),
458
- };
459
- case 'BinaryExpr':
460
- return {
461
- ...node,
462
- left: rewriteNodeForStructuralTransform(node.left, ownerSheetName, targetSheetName, transform),
463
- right: rewriteNodeForStructuralTransform(node.right, ownerSheetName, targetSheetName, transform),
464
- };
465
- case 'CallExpr':
466
- return {
467
- ...node,
468
- args: node.args.map((arg) => rewriteNodeForStructuralTransform(arg, ownerSheetName, targetSheetName, transform)),
469
- };
470
- case 'InvokeExpr':
471
- return {
472
- ...node,
473
- callee: rewriteNodeForStructuralTransform(node.callee, ownerSheetName, targetSheetName, transform),
474
- args: node.args.map((arg) => rewriteNodeForStructuralTransform(arg, ownerSheetName, targetSheetName, transform)),
475
- };
476
- }
477
- }
478
- function templateSheetKey(sheetName) {
479
- return sheetName === undefined ? '.' : JSON.stringify(sheetName);
480
- }
481
- function buildRelativeCellReferenceKey(ref, ownerRow, ownerCol) {
482
- const parsed = parseCellReferenceParts(ref);
483
- if (!parsed) {
484
- return `invalid:${ref}`;
485
- }
486
- const colKey = parsed.colAbsolute ? `ac${parsed.col}` : `rc${parsed.col - ownerCol}`;
487
- const rowKey = parsed.rowAbsolute ? `ar${parsed.row}` : `rr${parsed.row - ownerRow}`;
488
- return `${colKey}:${rowKey}`;
489
- }
490
- function buildRelativeAxisReferenceKey(ref, ownerIndex, kind) {
491
- const parsed = parseAxisReferenceParts(ref, kind);
492
- if (!parsed) {
493
- return `invalid:${ref}`;
494
- }
495
- return parsed.absolute ? `a${parsed.index}` : `r${parsed.index - ownerIndex}`;
496
- }
497
- function buildRelativeRangeReferenceKey(node, ownerRow, ownerCol) {
498
- switch (node.refKind) {
499
- case 'cells':
500
- return `${buildRelativeCellReferenceKey(node.start, ownerRow, ownerCol)}:${buildRelativeCellReferenceKey(node.end, ownerRow, ownerCol)}`;
501
- case 'rows':
502
- return `${buildRelativeAxisReferenceKey(node.start, ownerRow, 'row')}:${buildRelativeAxisReferenceKey(node.end, ownerRow, 'row')}`;
503
- case 'cols':
504
- return `${buildRelativeAxisReferenceKey(node.start, ownerCol, 'column')}:${buildRelativeAxisReferenceKey(node.end, ownerCol, 'column')}`;
505
- }
506
- }
507
- function nodeStructuralShapeEqual(left, right) {
508
- if (left.kind !== right.kind) {
509
- return false;
510
- }
511
- switch (left.kind) {
512
- case 'NumberLiteral':
513
- return right.kind === 'NumberLiteral' && left.value === right.value;
514
- case 'BooleanLiteral':
515
- return right.kind === 'BooleanLiteral' && left.value === right.value;
516
- case 'StringLiteral':
517
- return right.kind === 'StringLiteral' && left.value === right.value;
518
- case 'ErrorLiteral':
519
- return right.kind === 'ErrorLiteral' && left.code === right.code;
520
- case 'NameRef':
521
- return right.kind === 'NameRef' && left.name === right.name;
522
- case 'StructuredRef':
523
- return right.kind === 'StructuredRef' && left.tableName === right.tableName && left.columnName === right.columnName;
524
- case 'CellRef':
525
- case 'SpillRef':
526
- case 'ColumnRef':
527
- case 'RowRef':
528
- return true;
529
- case 'RangeRef':
530
- return right.kind === 'RangeRef' && left.refKind === right.refKind;
531
- case 'UnaryExpr':
532
- return right.kind === 'UnaryExpr' && left.operator === right.operator && nodeStructuralShapeEqual(left.argument, right.argument);
533
- case 'BinaryExpr':
534
- return (right.kind === 'BinaryExpr' &&
535
- left.operator === right.operator &&
536
- nodeStructuralShapeEqual(left.left, right.left) &&
537
- nodeStructuralShapeEqual(left.right, right.right));
538
- case 'CallExpr':
539
- return (right.kind === 'CallExpr' &&
540
- left.callee === right.callee &&
541
- left.args.length === right.args.length &&
542
- left.args.every((arg, index) => nodeStructuralShapeEqual(arg, right.args[index])));
543
- case 'InvokeExpr':
544
- return (right.kind === 'InvokeExpr' &&
545
- left.args.length === right.args.length &&
546
- nodeStructuralShapeEqual(left.callee, right.callee) &&
547
- left.args.every((arg, index) => nodeStructuralShapeEqual(arg, right.args[index])));
548
- }
549
- }
550
- function renameNodeSheetReferences(node, oldSheetName, newSheetName) {
551
- switch (node.kind) {
552
- case 'NumberLiteral':
553
- case 'BooleanLiteral':
554
- case 'StringLiteral':
555
- case 'ErrorLiteral':
556
- case 'NameRef':
557
- case 'StructuredRef':
558
- return node;
559
- case 'CellRef':
560
- case 'SpillRef':
561
- case 'RowRef':
562
- case 'ColumnRef':
563
- case 'RangeRef':
564
- return {
565
- ...node,
566
- ...(node.sheetName === oldSheetName ? { sheetName: newSheetName } : {}),
567
- };
568
- case 'UnaryExpr':
569
- return {
570
- ...node,
571
- argument: renameNodeSheetReferences(node.argument, oldSheetName, newSheetName),
572
- };
573
- case 'BinaryExpr':
574
- return {
575
- ...node,
576
- left: renameNodeSheetReferences(node.left, oldSheetName, newSheetName),
577
- right: renameNodeSheetReferences(node.right, oldSheetName, newSheetName),
578
- };
579
- case 'CallExpr':
580
- return {
581
- ...node,
582
- args: node.args.map((arg) => renameNodeSheetReferences(arg, oldSheetName, newSheetName)),
583
- };
584
- case 'InvokeExpr':
585
- return {
586
- ...node,
587
- callee: renameNodeSheetReferences(node.callee, oldSheetName, newSheetName),
588
- args: node.args.map((arg) => renameNodeSheetReferences(arg, oldSheetName, newSheetName)),
589
- };
590
- }
591
- }
592
- function renameQualifiedReferenceSheet(reference, oldSheetName, newSheetName) {
593
- const oldPrefix = `${quoteSheetNameIfNeeded(oldSheetName)}!`;
594
- if (!reference.startsWith(oldPrefix)) {
595
- return reference;
596
- }
597
- return `${quoteSheetNameIfNeeded(newSheetName)}!${reference.slice(oldPrefix.length)}`;
598
- }
599
- function renameParsedCellReferenceSheet(reference, oldSheetName, newSheetName) {
600
- return reference.sheetName === oldSheetName ? { ...reference, sheetName: newSheetName } : reference;
601
- }
602
- function renameParsedRangeReferenceSheet(reference, oldSheetName, newSheetName) {
603
- return reference.sheetName === oldSheetName
604
- ? {
605
- ...reference,
606
- sheetName: newSheetName,
607
- address: formatQualifiedRangeReference(newSheetName, reference.startAddress, reference.endAddress),
608
- }
609
- : reference;
610
- }
611
- function renameParsedDependencySheet(dependency, oldSheetName, newSheetName) {
612
- return dependency.kind === 'cell'
613
- ? renameParsedCellReferenceSheet(dependency, oldSheetName, newSheetName)
614
- : renameParsedRangeReferenceSheet(dependency, oldSheetName, newSheetName);
615
- }
616
- function renameReferenceOperandSheet(operand, oldSheetName, newSheetName) {
617
- return operand?.sheetName === oldSheetName ? { ...operand, sheetName: newSheetName } : operand;
618
- }
619
- function renameJsPlanSheetReferences(plan, oldSheetName, newSheetName) {
620
- return plan.map((instruction) => {
621
- switch (instruction.opcode) {
622
- case 'push-cell':
623
- case 'push-range':
624
- case 'lookup-exact-match':
625
- case 'lookup-approximate-match':
626
- return instruction.sheetName === oldSheetName ? { ...instruction, sheetName: newSheetName } : instruction;
627
- case 'push-lambda':
628
- return { ...instruction, body: renameJsPlanSheetReferences(instruction.body, oldSheetName, newSheetName) };
629
- case 'call':
630
- return instruction.argRefs
631
- ? {
632
- ...instruction,
633
- argRefs: instruction.argRefs.map((operand) => renameReferenceOperandSheet(operand, oldSheetName, newSheetName)),
634
- }
635
- : instruction;
636
- case 'begin-scope':
637
- case 'binary':
638
- case 'bind-name':
639
- case 'end-scope':
640
- case 'invoke':
641
- case 'jump':
642
- case 'jump-if-false':
643
- case 'push-boolean':
644
- case 'push-error':
645
- case 'push-name':
646
- case 'push-number':
647
- case 'push-string':
648
- case 'return':
649
- case 'unary':
650
- return instruction;
651
- default:
652
- return instruction;
653
- }
654
- });
655
- }
656
- function rewriteCellLikeNode(node, ownerSheetName, targetSheetName, transform) {
657
- if (!targetsSheet(node.sheetName, ownerSheetName, targetSheetName)) {
658
- return node;
659
- }
660
- const parsed = parseCellReferenceParts(node.ref);
661
- if (!parsed) {
662
- return { kind: 'ErrorLiteral', code: ErrorCode.Ref };
663
- }
664
- const nextRow = transform.axis === 'row' ? mapPointIndex(parsed.row, transform) : parsed.row;
665
- const nextCol = transform.axis === 'column' ? mapPointIndex(parsed.col, transform) : parsed.col;
666
- if (nextRow === undefined || nextCol === undefined) {
667
- return { kind: 'ErrorLiteral', code: ErrorCode.Ref };
668
- }
669
- return {
670
- ...node,
671
- ref: formatCellReference(parsed, nextRow, nextCol),
672
- };
673
- }
674
- function rewriteAxisNode(node, transform) {
675
- const parsed = parseAxisReferenceParts(node.ref, node.kind === 'RowRef' ? 'row' : 'column');
676
- if (!parsed) {
677
- return { kind: 'ErrorLiteral', code: ErrorCode.Ref };
678
- }
679
- const nextIndex = mapPointIndex(parsed.index, transform);
680
- if (nextIndex === undefined) {
681
- return { kind: 'ErrorLiteral', code: ErrorCode.Ref };
682
- }
683
- return {
684
- ...node,
685
- ref: formatAxisReference(parsed.absolute, nextIndex, node.kind === 'RowRef' ? 'row' : 'column'),
686
- };
687
- }
688
- function rewriteRangeNode(node, ownerSheetName, targetSheetName, transform) {
689
- if (!targetsSheet(node.sheetName, ownerSheetName, targetSheetName)) {
690
- return node;
691
- }
692
- if ((node.refKind === 'rows' && transform.axis === 'column') || (node.refKind === 'cols' && transform.axis === 'row')) {
693
- return node;
694
- }
695
- if (node.refKind === 'cells') {
696
- const start = parseCellReferenceParts(node.start);
697
- const end = parseCellReferenceParts(node.end);
698
- if (!start || !end) {
699
- return { kind: 'ErrorLiteral', code: ErrorCode.Ref };
700
- }
701
- const nextRows = transform.axis === 'row'
702
- ? mapInterval(Math.min(start.row, end.row), Math.max(start.row, end.row), transform)
703
- : { start: Math.min(start.row, end.row), end: Math.max(start.row, end.row) };
704
- const nextCols = transform.axis === 'column'
705
- ? mapInterval(Math.min(start.col, end.col), Math.max(start.col, end.col), transform)
706
- : { start: Math.min(start.col, end.col), end: Math.max(start.col, end.col) };
707
- if (!nextRows || !nextCols) {
708
- return { kind: 'ErrorLiteral', code: ErrorCode.Ref };
709
- }
710
- return {
711
- ...node,
712
- start: formatCellReference(start, nextRows.start, nextCols.start),
713
- end: formatCellReference(end, nextRows.end, nextCols.end),
714
- };
715
- }
716
- const start = parseAxisReferenceParts(node.start, node.refKind === 'rows' ? 'row' : 'column');
717
- const end = parseAxisReferenceParts(node.end, node.refKind === 'rows' ? 'row' : 'column');
718
- if (!start || !end) {
719
- return { kind: 'ErrorLiteral', code: ErrorCode.Ref };
720
- }
721
- const nextInterval = mapInterval(Math.min(start.index, end.index), Math.max(start.index, end.index), transform);
722
- if (!nextInterval) {
723
- return { kind: 'ErrorLiteral', code: ErrorCode.Ref };
724
- }
725
- return {
726
- ...node,
727
- start: formatAxisReference(start.absolute, nextInterval.start, node.refKind === 'rows' ? 'row' : 'column'),
728
- end: formatAxisReference(end.absolute, nextInterval.end, node.refKind === 'rows' ? 'row' : 'column'),
729
- };
730
- }
731
- function rewriteParsedCellReference(reference, ownerSheetName, targetSheetName, transform) {
732
- const sheetName = reference.sheetName ?? ownerSheetName;
733
- if (sheetName !== targetSheetName) {
734
- return reference;
735
- }
736
- const nextAddress = rewriteAddressForStructuralTransform(reference.address, transform);
737
- if (!nextAddress) {
738
- return reference;
739
- }
740
- const parsed = parseCellAddress(nextAddress, sheetName);
741
- return {
742
- ...reference,
743
- address: parsed.text,
744
- ...(reference.sheetName !== undefined ? { sheetName: parsed.sheetName } : {}),
745
- ...(reference.row !== undefined ? { row: parsed.row } : {}),
746
- ...(reference.col !== undefined ? { col: parsed.col } : {}),
747
- };
748
- }
749
- function rewriteParsedRangeReference(reference, ownerSheetName, targetSheetName, transform) {
750
- const explicitSheetName = reference.sheetName;
751
- if (!targetsSheet(explicitSheetName, ownerSheetName, targetSheetName)) {
752
- return reference;
753
- }
754
- const nextRange = rewriteRangeAddressForStructuralTransform(parseRangeAddress(formatQualifiedRangeReference(explicitSheetName, reference.startAddress, reference.endAddress)), transform);
755
- if (!nextRange) {
756
- return reference;
757
- }
758
- const bounds = nextRange.kind === 'cells'
759
- ? {
760
- startRow: nextRange.start.row,
761
- endRow: nextRange.end.row,
762
- startCol: nextRange.start.col,
763
- endCol: nextRange.end.col,
764
- }
765
- : nextRange.kind === 'rows'
766
- ? {
767
- startRow: nextRange.start.row,
768
- endRow: nextRange.end.row,
769
- startCol: 0,
770
- endCol: 0,
771
- }
772
- : {
773
- startRow: 0,
774
- endRow: 0,
775
- startCol: nextRange.start.col,
776
- endCol: nextRange.end.col,
777
- };
778
- return {
779
- ...reference,
780
- address: formatQualifiedRangeReference(explicitSheetName, nextRange.start.text, nextRange.end.text),
781
- refKind: nextRange.kind,
782
- startAddress: nextRange.start.text,
783
- endAddress: nextRange.end.text,
784
- ...bounds,
785
- };
786
- }
787
- function rewriteParsedDependencyReference(reference, ownerSheetName, targetSheetName, transform) {
788
- return reference.kind === 'cell'
789
- ? rewriteParsedCellReference(reference, ownerSheetName, targetSheetName, transform)
790
- : rewriteParsedRangeReference(reference, ownerSheetName, targetSheetName, transform);
791
- }
792
- function translateParsedCellReference(reference, rowDelta, colDelta) {
793
- const parts = reference.rowAbsolute !== undefined && reference.colAbsolute !== undefined && reference.row !== undefined && reference.col !== undefined
794
- ? {
795
- row: reference.row,
796
- col: reference.col,
797
- rowAbsolute: reference.rowAbsolute,
798
- colAbsolute: reference.colAbsolute,
799
- }
800
- : parseCellReferenceParts(reference.address);
801
- if (!parts) {
802
- return reference;
803
- }
804
- const nextRow = parts.rowAbsolute ? parts.row : parts.row + rowDelta;
805
- const nextCol = parts.colAbsolute ? parts.col : parts.col + colDelta;
806
- const nextLocalAddress = formatCellReference(parts, nextRow, nextCol);
807
- const nextAddress = reference.explicitSheet || reference.sheetName !== undefined
808
- ? formatQualifiedCellReference(reference.sheetName, nextLocalAddress)
809
- : nextLocalAddress;
810
- return {
811
- ...reference,
812
- address: nextAddress,
813
- ...(reference.sheetName !== undefined ? { sheetName: reference.sheetName } : {}),
814
- ...(reference.explicitSheet !== undefined ? { explicitSheet: reference.explicitSheet } : {}),
815
- ...(reference.row !== undefined ? { row: nextRow } : {}),
816
- ...(reference.col !== undefined ? { col: nextCol } : {}),
817
- ...(reference.rowAbsolute !== undefined ? { rowAbsolute: parts.rowAbsolute } : {}),
818
- ...(reference.colAbsolute !== undefined ? { colAbsolute: parts.colAbsolute } : {}),
819
- };
820
- }
821
- function translateParsedRangeReference(reference, rowDelta, colDelta) {
822
- const nextRange = translateParsedRangeReferenceInfo(reference, rowDelta, colDelta);
823
- const bounds = nextRange.refKind === 'cells'
824
- ? {
825
- startRow: nextRange.startRow,
826
- endRow: nextRange.endRow,
827
- startCol: nextRange.startCol,
828
- endCol: nextRange.endCol,
829
- }
830
- : nextRange.refKind === 'rows'
831
- ? {
832
- startRow: nextRange.startRow,
833
- endRow: nextRange.endRow,
834
- startCol: 0,
835
- endCol: 0,
836
- }
837
- : {
838
- startRow: 0,
839
- endRow: 0,
840
- startCol: nextRange.startCol,
841
- endCol: nextRange.endCol,
842
- };
843
- return {
844
- ...reference,
845
- address: formatParsedRangeReference(nextRange),
846
- refKind: nextRange.refKind,
847
- startAddress: nextRange.startAddress,
848
- endAddress: nextRange.endAddress,
849
- ...bounds,
850
- ...(reference.explicitSheet !== undefined ? { explicitSheet: reference.explicitSheet } : {}),
851
- };
852
- }
853
- function translateParsedDependencyReference(reference, rowDelta, colDelta) {
854
- return reference.kind === 'cell'
855
- ? translateParsedCellReference(reference, rowDelta, colDelta)
856
- : translateParsedRangeReference(reference, rowDelta, colDelta);
857
- }
858
- function translateQualifiedCellReference(raw, rowDelta, colDelta) {
859
- const explicitlyQualified = raw.includes('!');
860
- const parsed = parseCellAddress(raw);
861
- const nextAddress = translateCellReference(parsed.text, rowDelta, colDelta);
862
- return explicitlyQualified ? formatQualifiedCellReference(parsed.sheetName, nextAddress) : nextAddress;
863
- }
864
- function formatParsedCellReference(reference) {
865
- const localAddress = formatParsedLocalCellReference(reference);
866
- return reference.explicitSheet || reference.sheetName !== undefined
867
- ? formatQualifiedCellReference(reference.sheetName, localAddress)
868
- : localAddress;
869
- }
870
- function formatParsedLocalCellReference(reference) {
871
- const parts = reference.row !== undefined && reference.col !== undefined && reference.rowAbsolute !== undefined && reference.colAbsolute !== undefined
872
- ? {
873
- row: reference.row,
874
- col: reference.col,
875
- rowAbsolute: reference.rowAbsolute,
876
- colAbsolute: reference.colAbsolute,
877
- }
878
- : parseCellReferenceParts(reference.address);
879
- if (!parts) {
880
- return stripSheetQualifier(reference.address);
881
- }
882
- return formatCellReference(parts, parts.row, parts.col);
883
- }
884
- function formatParsedRangeReference(reference) {
885
- return formatQualifiedRangeReference(reference.explicitSheet ? reference.sheetName : undefined, reference.startAddress, reference.endAddress);
886
- }
887
- function stripSheetQualifier(reference) {
888
- const bang = reference.lastIndexOf('!');
889
- return bang === -1 ? reference : reference.slice(bang + 1);
890
- }
891
- function translatedCellInstructionKey(sheetName, address) {
892
- return `${sheetName ?? ''}\t${address}`;
893
- }
894
- function translatedRangeInstructionKey(sheetName, refKind, start, end) {
895
- return `${sheetName ?? ''}\t${refKind}\t${start}\t${end}`;
896
- }
897
- function buildTranslatedCellReferenceMap(original, translated) {
898
- const output = new Map();
899
- if (!original || !translated || original.length !== translated.length) {
900
- return output;
901
- }
902
- for (let index = 0; index < original.length; index += 1) {
903
- const source = original[index];
904
- const target = translated[index];
905
- if (!source || !target) {
906
- continue;
907
- }
908
- output.set(translatedCellInstructionKey(source.sheetName, formatParsedLocalCellReference(source)), target);
909
- }
910
- return output;
911
- }
912
- function buildTranslatedRangeReferenceMap(original, translated) {
913
- const output = new Map();
914
- if (!original || !translated || original.length !== translated.length) {
915
- return output;
916
- }
917
- for (let index = 0; index < original.length; index += 1) {
918
- const source = original[index];
919
- const target = translated[index];
920
- if (!source || !target) {
921
- continue;
922
- }
923
- output.set(translatedRangeInstructionKey(source.sheetName, source.refKind, source.startAddress, source.endAddress), target);
924
- }
925
- return output;
926
- }
927
- function formatParsedDependencyReference(reference) {
928
- return reference.kind === 'cell' ? formatParsedCellReference(reference) : formatParsedRangeReference(reference);
929
- }
930
- function translateQualifiedDependencyReference(raw, rowDelta, colDelta) {
931
- if (!raw.includes(':')) {
932
- return translateQualifiedCellReference(raw, rowDelta, colDelta);
933
- }
934
- return translateQualifiedRangeReference(raw, rowDelta, colDelta);
935
- }
936
- function translateQualifiedRangeReference(raw, rowDelta, colDelta) {
937
- const explicitlyQualified = raw.includes('!');
938
- const parsed = parseRangeAddress(raw);
939
- const nextRange = translateRangeAddress(parsed, rowDelta, colDelta);
940
- if (explicitlyQualified) {
941
- return formatRangeAddress(nextRange);
942
- }
943
- return `${nextRange.start.text}:${nextRange.end.text}`;
944
- }
945
- function translateRangeAddress(range, rowDelta, colDelta) {
946
- switch (range.kind) {
947
- case 'cells': {
948
- const startAddress = translateCellReference(range.start.text, rowDelta, colDelta);
949
- const endAddress = translateCellReference(range.end.text, rowDelta, colDelta);
950
- return parseRangeAddress(formatQualifiedRangeReference(range.sheetName, startAddress, endAddress));
951
- }
952
- case 'rows': {
953
- const start = translateRowReference(range.start.text, rowDelta);
954
- const end = translateRowReference(range.end.text, rowDelta);
955
- return parseRangeAddress(formatQualifiedRangeReference(range.sheetName, start, end));
956
- }
957
- case 'cols': {
958
- const start = translateColumnReference(range.start.text, colDelta);
959
- const end = translateColumnReference(range.end.text, colDelta);
960
- return parseRangeAddress(formatQualifiedRangeReference(range.sheetName, start, end));
961
- }
962
- }
963
- }
964
- function translateParsedRangeReferenceInfo(reference, rowDelta, colDelta) {
965
- if (reference.refKind === 'cells') {
966
- const startRow = (reference.startRowAbsolute ?? false) ? reference.startRow : reference.startRow + rowDelta;
967
- const endRow = (reference.endRowAbsolute ?? false) ? reference.endRow : reference.endRow + rowDelta;
968
- const startCol = (reference.startColAbsolute ?? false) ? reference.startCol : reference.startCol + colDelta;
969
- const endCol = (reference.endColAbsolute ?? false) ? reference.endCol : reference.endCol + colDelta;
970
- const startAddress = formatCellReference({
971
- row: reference.startRow,
972
- col: reference.startCol,
973
- rowAbsolute: reference.startRowAbsolute ?? false,
974
- colAbsolute: reference.startColAbsolute ?? false,
975
- }, startRow, startCol);
976
- const endAddress = formatCellReference({
977
- row: reference.endRow,
978
- col: reference.endCol,
979
- rowAbsolute: reference.endRowAbsolute ?? false,
980
- colAbsolute: reference.endColAbsolute ?? false,
981
- }, endRow, endCol);
982
- return {
983
- ...reference,
984
- startAddress,
985
- endAddress,
986
- startRow,
987
- endRow,
988
- startCol,
989
- endCol,
990
- };
991
- }
992
- if (reference.refKind === 'rows') {
993
- const startRow = (reference.startRowAbsolute ?? false) ? reference.startRow : reference.startRow + rowDelta;
994
- const endRow = (reference.endRowAbsolute ?? false) ? reference.endRow : reference.endRow + rowDelta;
995
- return {
996
- ...reference,
997
- startAddress: formatAxisReference(reference.startRowAbsolute ?? false, startRow, 'row'),
998
- endAddress: formatAxisReference(reference.endRowAbsolute ?? false, endRow, 'row'),
999
- startRow,
1000
- endRow,
1001
- startCol: 0,
1002
- endCol: 0,
1003
- };
1004
- }
1005
- const startCol = (reference.startColAbsolute ?? false) ? reference.startCol : reference.startCol + colDelta;
1006
- const endCol = (reference.endColAbsolute ?? false) ? reference.endCol : reference.endCol + colDelta;
1007
- return {
1008
- ...reference,
1009
- startAddress: formatAxisReference(reference.startColAbsolute ?? false, startCol, 'column'),
1010
- endAddress: formatAxisReference(reference.endColAbsolute ?? false, endCol, 'column'),
1011
- startRow: 0,
1012
- endRow: 0,
1013
- startCol,
1014
- endCol,
1015
- };
1016
- }
1017
- function rewriteQualifiedCellReference(raw, ownerSheetName, targetSheetName, transform) {
1018
- const explicitlyQualified = raw.includes('!');
1019
- const parsed = parseCellAddress(raw, ownerSheetName);
1020
- if (parsed.sheetName !== targetSheetName) {
1021
- return raw;
1022
- }
1023
- const nextAddress = rewriteAddressForStructuralTransform(parsed.text, transform);
1024
- if (!nextAddress) {
1025
- return raw;
1026
- }
1027
- return explicitlyQualified ? formatQualifiedCellReference(parsed.sheetName, nextAddress) : nextAddress;
1028
- }
1029
- function rewriteQualifiedDependencyReference(raw, ownerSheetName, targetSheetName, transform) {
1030
- if (!raw.includes(':')) {
1031
- return rewriteQualifiedCellReference(raw, ownerSheetName, targetSheetName, transform);
1032
- }
1033
- return rewriteQualifiedRangeReference(raw, ownerSheetName, targetSheetName, transform);
1034
- }
1035
- function rewriteQualifiedRangeReference(raw, ownerSheetName, targetSheetName, transform) {
1036
- const explicitlyQualified = raw.includes('!');
1037
- const parsed = parseRangeAddress(raw, ownerSheetName);
1038
- const sheetName = parsed.sheetName ?? ownerSheetName;
1039
- if (sheetName !== targetSheetName) {
1040
- return raw;
1041
- }
1042
- const nextRange = rewriteRangeAddressForStructuralTransform(parsed, transform);
1043
- if (!nextRange) {
1044
- return raw;
1045
- }
1046
- if (explicitlyQualified) {
1047
- return formatRangeAddress(nextRange);
1048
- }
1049
- return `${nextRange.start.text}:${nextRange.end.text}`;
1050
- }
1051
- function rewriteRangeAddressForStructuralTransform(range, transform) {
1052
- switch (range.kind) {
1053
- case 'cells': {
1054
- const nextRange = rewriteRangeForStructuralTransform(range.start.text, range.end.text, transform);
1055
- if (!nextRange) {
1056
- return undefined;
1057
- }
1058
- return parseRangeAddress(formatQualifiedRangeReference(range.sheetName, nextRange.startAddress, nextRange.endAddress));
1059
- }
1060
- case 'rows':
1061
- if (transform.axis !== 'row') {
1062
- return range;
1063
- }
1064
- return rewriteAxisRangeAddress(range, transform);
1065
- case 'cols':
1066
- if (transform.axis !== 'column') {
1067
- return range;
1068
- }
1069
- return rewriteAxisRangeAddress(range, transform);
1070
- }
1071
- }
1072
- function rewriteAxisRangeAddress(range, transform) {
1073
- const startIndex = range.kind === 'rows' ? range.start.row : range.start.col;
1074
- const endIndex = range.kind === 'rows' ? range.end.row : range.end.col;
1075
- const nextInterval = mapInterval(startIndex, endIndex, transform);
1076
- if (!nextInterval) {
1077
- return undefined;
1078
- }
1079
- const prefix = range.sheetName ? `${quoteSheetNameIfNeeded(range.sheetName)}!` : '';
1080
- const startText = range.kind === 'rows' ? formatAxisReference(false, nextInterval.start, 'row') : formatAxisReference(false, nextInterval.start, 'column');
1081
- const endText = range.kind === 'rows' ? formatAxisReference(false, nextInterval.end, 'row') : formatAxisReference(false, nextInterval.end, 'column');
1082
- return parseRangeAddress(`${prefix}${startText}:${endText}`);
1083
- }
1084
- function rewriteJsPlanInstruction(instruction, ownerSheetName, targetSheetName, transform) {
1085
- switch (instruction.opcode) {
1086
- case 'push-cell':
1087
- return {
1088
- ...instruction,
1089
- address: rewriteReferenceOperandAddress(instruction.sheetName, instruction.address, ownerSheetName, targetSheetName, transform),
1090
- };
1091
- case 'push-range': {
1092
- const nextRange = rewritePlanRangeInstruction(instruction.sheetName, instruction.start, instruction.end, instruction.refKind, ownerSheetName, targetSheetName, transform);
1093
- return nextRange ? { ...instruction, ...nextRange } : instruction;
1094
- }
1095
- case 'lookup-exact-match':
1096
- case 'lookup-approximate-match': {
1097
- const nextRange = rewritePlanRangeInstruction(instruction.sheetName, instruction.start, instruction.end, instruction.refKind, ownerSheetName, targetSheetName, transform);
1098
- if (!nextRange) {
1099
- return instruction;
1100
- }
1101
- const parsed = parseRangeAddress(formatQualifiedRangeReference(instruction.sheetName, nextRange.start, nextRange.end));
1102
- if (parsed.kind !== 'cells') {
1103
- return instruction;
1104
- }
1105
- return {
1106
- ...instruction,
1107
- ...nextRange,
1108
- startRow: parsed.start.row,
1109
- endRow: parsed.end.row,
1110
- startCol: parsed.start.col,
1111
- endCol: parsed.end.col,
1112
- };
1113
- }
1114
- case 'call':
1115
- return instruction.argRefs
1116
- ? {
1117
- ...instruction,
1118
- argRefs: instruction.argRefs.map((argRef) => argRef ? rewriteReferenceOperand(argRef, ownerSheetName, targetSheetName, transform) : argRef),
1119
- }
1120
- : instruction;
1121
- case 'push-lambda':
1122
- return {
1123
- ...instruction,
1124
- body: instruction.body.map((step) => rewriteJsPlanInstruction(step, ownerSheetName, targetSheetName, transform)),
1125
- };
1126
- case 'push-number':
1127
- case 'push-boolean':
1128
- case 'push-string':
1129
- case 'push-error':
1130
- case 'push-name':
1131
- case 'unary':
1132
- case 'binary':
1133
- case 'invoke':
1134
- case 'begin-scope':
1135
- case 'bind-name':
1136
- case 'end-scope':
1137
- case 'jump-if-false':
1138
- case 'jump':
1139
- case 'return':
1140
- return instruction;
1141
- }
1142
- }
1143
168
  function translateJsPlanInstruction(instruction, rowDelta, colDelta) {
1144
169
  switch (instruction.opcode) {
1145
170
  case 'push-cell':
@@ -1262,27 +287,6 @@ function translateJsPlanInstructionWithoutAst(instruction, translatedCellMap, tr
1262
287
  return instruction;
1263
288
  }
1264
289
  }
1265
- function rewriteReferenceOperand(operand, ownerSheetName, targetSheetName, transform) {
1266
- switch (operand.kind) {
1267
- case 'cell':
1268
- return operand.address
1269
- ? {
1270
- ...operand,
1271
- address: rewriteReferenceOperandAddress(operand.sheetName, operand.address, ownerSheetName, targetSheetName, transform),
1272
- }
1273
- : operand;
1274
- case 'range': {
1275
- if (!operand.start || !operand.end || !operand.refKind) {
1276
- return operand;
1277
- }
1278
- const nextRange = rewritePlanRangeInstruction(operand.sheetName, operand.start, operand.end, operand.refKind, ownerSheetName, targetSheetName, transform);
1279
- return nextRange ? { ...operand, ...nextRange } : operand;
1280
- }
1281
- case 'row':
1282
- case 'col':
1283
- return operand;
1284
- }
1285
- }
1286
290
  function translateReferenceOperand(operand, rowDelta, colDelta) {
1287
291
  switch (operand.kind) {
1288
292
  case 'cell':
@@ -1349,37 +353,6 @@ function translateReferenceOperandWithoutAst(operand, translatedCellMap, transla
1349
353
  return translateReferenceOperand(operand, rowDelta, colDelta);
1350
354
  }
1351
355
  }
1352
- function rewriteReferenceOperandAddress(explicitSheetName, address, ownerSheetName, targetSheetName, transform) {
1353
- if ((explicitSheetName ?? ownerSheetName) !== targetSheetName) {
1354
- return address;
1355
- }
1356
- return rewriteAddressForStructuralTransform(address, transform) ?? address;
1357
- }
1358
- function rewritePlanRangeInstruction(explicitSheetName, start, end, refKind, ownerSheetName, targetSheetName, transform) {
1359
- if ((explicitSheetName ?? ownerSheetName) !== targetSheetName) {
1360
- return undefined;
1361
- }
1362
- if (refKind === 'cells') {
1363
- const nextRange = rewriteRangeForStructuralTransform(start, end, transform);
1364
- return nextRange
1365
- ? {
1366
- start: nextRange.startAddress,
1367
- end: nextRange.endAddress,
1368
- }
1369
- : undefined;
1370
- }
1371
- if ((refKind === 'rows' && transform.axis !== 'row') || (refKind === 'cols' && transform.axis !== 'column')) {
1372
- return undefined;
1373
- }
1374
- const parsed = parseRangeAddress(formatQualifiedRangeReference(explicitSheetName, start, end));
1375
- const nextRange = rewriteRangeAddressForStructuralTransform(parsed, transform);
1376
- return nextRange
1377
- ? {
1378
- start: nextRange.start.text,
1379
- end: nextRange.end.text,
1380
- }
1381
- : undefined;
1382
- }
1383
356
  function translatePlanRangeInstruction(explicitSheetName, start, end, rowDelta, colDelta) {
1384
357
  const parsed = parseRangeAddress(formatQualifiedRangeReference(explicitSheetName, start, end));
1385
358
  const nextRange = translateRangeAddress(parsed, rowDelta, colDelta);
@@ -1388,267 +361,8 @@ function translatePlanRangeInstruction(explicitSheetName, start, end, rowDelta,
1388
361
  end: nextRange.end.text,
1389
362
  };
1390
363
  }
1391
- function formatQualifiedCellReference(sheetName, address) {
1392
- if (!sheetName) {
1393
- return address;
1394
- }
1395
- const parsed = parseCellAddress(address, sheetName);
1396
- return `${quoteSheetNameIfNeeded(sheetName)}!${parsed.text}`;
1397
- }
1398
364
  function formatQualifiedRangeReference(sheetName, start, end) {
1399
365
  const prefix = sheetName ? `${quoteSheetNameIfNeeded(sheetName)}!` : '';
1400
366
  return `${prefix}${start}:${end}`;
1401
367
  }
1402
- function translateCellReference(ref, rowDelta, colDelta) {
1403
- const parsed = parseCellReferenceParts(ref);
1404
- if (!parsed) {
1405
- throw new Error(`Invalid cell reference '${ref}'`);
1406
- }
1407
- const nextCol = parsed.colAbsolute ? parsed.col : parsed.col + colDelta;
1408
- const nextRow = parsed.rowAbsolute ? parsed.row : parsed.row + rowDelta;
1409
- if (nextCol < 0 || nextRow < 0) {
1410
- throw new Error(`Translated reference moved outside worksheet bounds: ${ref}`);
1411
- }
1412
- return formatCellReference(parsed, nextRow, nextCol);
1413
- }
1414
- function translateColumnReference(ref, colDelta) {
1415
- const parsed = parseAxisReferenceParts(ref, 'column');
1416
- if (!parsed) {
1417
- throw new Error(`Invalid column reference '${ref}'`);
1418
- }
1419
- const nextCol = parsed.absolute ? parsed.index : parsed.index + colDelta;
1420
- if (nextCol < 0) {
1421
- throw new Error(`Translated reference moved outside worksheet bounds: ${ref}`);
1422
- }
1423
- return formatAxisReference(parsed.absolute, nextCol, 'column');
1424
- }
1425
- function translateRowReference(ref, rowDelta) {
1426
- const parsed = parseAxisReferenceParts(ref, 'row');
1427
- if (!parsed) {
1428
- throw new Error(`Invalid row reference '${ref}'`);
1429
- }
1430
- const nextRow = parsed.absolute ? parsed.index : parsed.index + rowDelta;
1431
- if (nextRow < 0) {
1432
- throw new Error(`Translated reference moved outside worksheet bounds: ${ref}`);
1433
- }
1434
- return formatAxisReference(parsed.absolute, nextRow, 'row');
1435
- }
1436
- export function serializeFormula(node, parentPrecedence = 0, parentAssociativity = null) {
1437
- switch (node.kind) {
1438
- case 'NumberLiteral':
1439
- return String(node.value);
1440
- case 'BooleanLiteral':
1441
- return node.value ? 'TRUE' : 'FALSE';
1442
- case 'StringLiteral':
1443
- return `"${node.value.replaceAll('"', '""')}"`;
1444
- case 'ErrorLiteral':
1445
- return ERROR_LITERAL_TEXT[node.code] ?? '#ERROR!';
1446
- case 'NameRef':
1447
- return node.name;
1448
- case 'StructuredRef':
1449
- return `${node.tableName}[${node.columnName}]`;
1450
- case 'CellRef':
1451
- return `${formatSheetPrefix(node.sheetName)}${node.ref}`;
1452
- case 'SpillRef':
1453
- return `${formatSheetPrefix(node.sheetName)}${node.ref}#`;
1454
- case 'ColumnRef':
1455
- return `${formatSheetPrefix(node.sheetName)}${node.ref}`;
1456
- case 'RowRef':
1457
- return `${formatSheetPrefix(node.sheetName)}${node.ref}`;
1458
- case 'RangeRef':
1459
- return `${formatSheetPrefix(node.sheetName)}${node.start}:${node.end}`;
1460
- case 'UnaryExpr':
1461
- return `${node.operator}${serializeFormula(node.argument, 6)}`;
1462
- case 'CallExpr':
1463
- return `${node.callee}(${node.args.map((arg) => serializeFormula(arg)).join(',')})`;
1464
- case 'InvokeExpr': {
1465
- const callee = node.callee.kind === 'CallExpr' || node.callee.kind === 'InvokeExpr'
1466
- ? serializeFormula(node.callee)
1467
- : `(${serializeFormula(node.callee)})`;
1468
- return `${callee}(${node.args.map((arg) => serializeFormula(arg)).join(',')})`;
1469
- }
1470
- case 'BinaryExpr': {
1471
- const precedence = BINARY_PRECEDENCE[node.operator];
1472
- const isRightAssociative = node.operator === '^';
1473
- const left = serializeFormula(node.left, precedence, 'left');
1474
- const right = serializeFormula(node.right, precedence, 'right');
1475
- const output = `${left}${node.operator}${right}`;
1476
- const needsParens = precedence < parentPrecedence ||
1477
- (precedence === parentPrecedence &&
1478
- ((parentAssociativity === 'left' && isRightAssociative) || (parentAssociativity === 'right' && !isRightAssociative)));
1479
- return needsParens ? `(${output})` : output;
1480
- }
1481
- }
1482
- }
1483
- function formatSheetPrefix(sheetName) {
1484
- if (!sheetName) {
1485
- return '';
1486
- }
1487
- return `${quoteSheetNameIfNeeded(sheetName)}!`;
1488
- }
1489
- function quoteSheetNameIfNeeded(sheetName) {
1490
- return /^[A-Za-z0-9_.$]+$/.test(sheetName) ? sheetName : `'${sheetName.replaceAll("'", "''")}'`;
1491
- }
1492
- function columnToIndex(column) {
1493
- let value = 0;
1494
- for (const char of column) {
1495
- value = value * 26 + (char.charCodeAt(0) - 64);
1496
- }
1497
- return value - 1;
1498
- }
1499
- function indexToColumn(index) {
1500
- let current = index + 1;
1501
- let output = '';
1502
- while (current > 0) {
1503
- const remainder = (current - 1) % 26;
1504
- output = String.fromCharCode(65 + remainder) + output;
1505
- current = Math.floor((current - 1) / 26);
1506
- }
1507
- return output;
1508
- }
1509
- function targetsSheet(explicitSheetName, ownerSheetName, targetSheetName) {
1510
- return (explicitSheetName ?? ownerSheetName) === targetSheetName;
1511
- }
1512
- function parseCellReferenceParts(ref) {
1513
- const match = CELL_REF_RE.exec(ref.toUpperCase());
1514
- if (!match) {
1515
- return undefined;
1516
- }
1517
- const [, colAbsolute, columnText, rowAbsolute, rowText] = match;
1518
- return {
1519
- colAbsolute: colAbsolute === '$',
1520
- rowAbsolute: rowAbsolute === '$',
1521
- col: columnToIndex(columnText),
1522
- row: Number.parseInt(rowText, 10) - 1,
1523
- };
1524
- }
1525
- function formatCellReference(parts, row, col) {
1526
- return `${parts.colAbsolute ? '$' : ''}${indexToColumn(col)}${parts.rowAbsolute ? '$' : ''}${row + 1}`;
1527
- }
1528
- function parseAxisReferenceParts(ref, kind) {
1529
- const match = (kind === 'row' ? ROW_REF_RE : COLUMN_REF_RE).exec(ref.toUpperCase());
1530
- if (!match) {
1531
- return undefined;
1532
- }
1533
- return kind === 'row'
1534
- ? {
1535
- absolute: match[1] === '$',
1536
- index: Number.parseInt(match[2], 10) - 1,
1537
- }
1538
- : {
1539
- absolute: match[1] === '$',
1540
- index: columnToIndex(match[2]),
1541
- };
1542
- }
1543
- function formatAxisReference(absolute, index, kind) {
1544
- const prefix = absolute ? '$' : '';
1545
- return kind === 'row' ? `${prefix}${index + 1}` : `${prefix}${indexToColumn(index)}`;
1546
- }
1547
- function mapPointIndex(index, transform) {
1548
- switch (transform.kind) {
1549
- case 'insert':
1550
- return index >= transform.start ? index + transform.count : index;
1551
- case 'delete':
1552
- if (index < transform.start) {
1553
- return index;
1554
- }
1555
- if (index >= transform.start + transform.count) {
1556
- return index - transform.count;
1557
- }
1558
- return undefined;
1559
- case 'move':
1560
- if (transform.target < transform.start) {
1561
- if (index >= transform.target && index < transform.start) {
1562
- return index + transform.count;
1563
- }
1564
- }
1565
- else if (transform.target > transform.start) {
1566
- if (index >= transform.start + transform.count && index < transform.target + transform.count) {
1567
- return index - transform.count;
1568
- }
1569
- }
1570
- if (index >= transform.start && index < transform.start + transform.count) {
1571
- return transform.target + (index - transform.start);
1572
- }
1573
- return index;
1574
- default:
1575
- return assertNever(transform);
1576
- }
1577
- }
1578
- function mapInterval(start, end, transform) {
1579
- switch (transform.kind) {
1580
- case 'insert': {
1581
- if (transform.start <= start) {
1582
- return { start: start + transform.count, end: end + transform.count };
1583
- }
1584
- if (transform.start <= end) {
1585
- return { start, end: end + transform.count };
1586
- }
1587
- return { start, end };
1588
- }
1589
- case 'delete': {
1590
- const deleteEnd = transform.start + transform.count - 1;
1591
- if (deleteEnd < start) {
1592
- return { start: start - transform.count, end: end - transform.count };
1593
- }
1594
- if (transform.start > end) {
1595
- return { start, end };
1596
- }
1597
- const survivingStart = start < transform.start ? start : deleteEnd + 1;
1598
- const survivingEnd = end > deleteEnd ? end : transform.start - 1;
1599
- if (survivingStart > survivingEnd) {
1600
- return undefined;
1601
- }
1602
- const nextStart = mapPointIndex(survivingStart, transform);
1603
- const nextEnd = mapPointIndex(survivingEnd, transform);
1604
- return nextStart === undefined || nextEnd === undefined ? undefined : { start: nextStart, end: nextEnd };
1605
- }
1606
- case 'move': {
1607
- const segments = transform.target < transform.start
1608
- ? [
1609
- { start: 0, end: transform.target - 1, delta: 0 },
1610
- { start: transform.target, end: transform.start - 1, delta: transform.count },
1611
- {
1612
- start: transform.start,
1613
- end: transform.start + transform.count - 1,
1614
- delta: transform.target - transform.start,
1615
- },
1616
- { start: transform.start + transform.count, end: Number.MAX_SAFE_INTEGER, delta: 0 },
1617
- ]
1618
- : [
1619
- { start: 0, end: transform.start - 1, delta: 0 },
1620
- {
1621
- start: transform.start,
1622
- end: transform.start + transform.count - 1,
1623
- delta: transform.target - transform.start,
1624
- },
1625
- {
1626
- start: transform.start + transform.count,
1627
- end: transform.target + transform.count - 1,
1628
- delta: -transform.count,
1629
- },
1630
- { start: transform.target + transform.count, end: Number.MAX_SAFE_INTEGER, delta: 0 },
1631
- ];
1632
- let nextStart;
1633
- let nextEnd;
1634
- segments.forEach((segment) => {
1635
- const overlapStart = Math.max(start, segment.start);
1636
- const overlapEnd = Math.min(end, segment.end);
1637
- if (overlapStart > overlapEnd) {
1638
- return;
1639
- }
1640
- const mappedStart = overlapStart + segment.delta;
1641
- const mappedEnd = overlapEnd + segment.delta;
1642
- nextStart = nextStart === undefined ? mappedStart : Math.min(nextStart, mappedStart);
1643
- nextEnd = nextEnd === undefined ? mappedEnd : Math.max(nextEnd, mappedEnd);
1644
- });
1645
- if (nextStart === undefined || nextEnd === undefined) {
1646
- return undefined;
1647
- }
1648
- return { start: nextStart, end: nextEnd };
1649
- }
1650
- default:
1651
- return assertNever(transform);
1652
- }
1653
- }
1654
368
  //# sourceMappingURL=translation.js.map