@bilig/formula 0.1.75 → 0.1.76
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/dist/compiler.d.ts +39 -13
- package/dist/compiler.js +166 -4
- package/dist/compiler.js.map +1 -1
- package/dist/formula-template-key.d.ts +1 -0
- package/dist/formula-template-key.js +161 -0
- package/dist/formula-template-key.js.map +1 -0
- package/dist/generated/formula-inventory.d.ts +154 -154
- package/dist/generated/formula-inventory.js +154 -154
- package/dist/generated/formula-inventory.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/runtime-inventory.js +18 -2
- package/dist/runtime-inventory.js.map +1 -1
- package/dist/translation.d.ts +16 -0
- package/dist/translation.js +936 -1
- package/dist/translation.js.map +1 -1
- package/package.json +2 -2
package/dist/translation.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { ErrorCode } from "@bilig/protocol";
|
|
1
|
+
import { ErrorCode, FormulaMode } from "@bilig/protocol";
|
|
2
|
+
import { formatRangeAddress, parseCellAddress, parseRangeAddress } from "./addressing.js";
|
|
3
|
+
import { compileFormulaAst, } from "./compiler.js";
|
|
2
4
|
import { parseFormula } from "./parser.js";
|
|
3
5
|
const CELL_REF_RE = /^(\$?)([A-Z]+)(\$?)([1-9][0-9]*)$/;
|
|
4
6
|
const COLUMN_REF_RE = /^(\$?)([A-Z]+)$/;
|
|
@@ -34,10 +36,141 @@ export function translateFormulaReferences(source, rowDelta, colDelta) {
|
|
|
34
36
|
const ast = parseFormula(source);
|
|
35
37
|
return serializeFormula(translateNode(ast, rowDelta, colDelta));
|
|
36
38
|
}
|
|
39
|
+
export function buildRelativeFormulaTemplateKey(source, ownerRow, ownerCol) {
|
|
40
|
+
return buildRelativeFormulaTemplateKeyFromAst(parseFormula(source), ownerRow, ownerCol);
|
|
41
|
+
}
|
|
42
|
+
export function buildRelativeFormulaTemplateKeyFromAst(node, ownerRow, ownerCol) {
|
|
43
|
+
return buildRelativeFormulaTemplateKeyInternal(node, ownerRow, ownerCol);
|
|
44
|
+
}
|
|
45
|
+
export function canTranslateCompiledFormulaWithoutAst(compiled) {
|
|
46
|
+
return ((compiled.symbolicRanges.length === 0 || compiled.directAggregateCandidate !== undefined) &&
|
|
47
|
+
compiled.symbolicNames.length === 0 &&
|
|
48
|
+
compiled.symbolicTables.length === 0 &&
|
|
49
|
+
compiled.symbolicSpills.length === 0 &&
|
|
50
|
+
!compiled.jsPlan.some((instruction) => instruction.opcode === "lookup-exact-match" ||
|
|
51
|
+
instruction.opcode === "lookup-approximate-match"));
|
|
52
|
+
}
|
|
53
|
+
export function translateCompiledFormulaWithoutAst(compiled, rowDelta, colDelta, sourceOverride) {
|
|
54
|
+
const translatedParsedDeps = compiled.parsedDeps?.map((dependency) => translateParsedDependencyReference(dependency, rowDelta, colDelta));
|
|
55
|
+
const translatedParsedSymbolicRefs = compiled.parsedSymbolicRefs?.map((reference) => translateParsedCellReference(reference, rowDelta, colDelta));
|
|
56
|
+
const translatedParsedSymbolicRanges = compiled.parsedSymbolicRanges?.map((range) => translateParsedRangeReference(range, rowDelta, colDelta));
|
|
57
|
+
const source = sourceOverride ?? compiled.source;
|
|
58
|
+
const translatedCellMap = buildTranslatedCellReferenceMap(compiled.parsedSymbolicRefs, translatedParsedSymbolicRefs);
|
|
59
|
+
const translatedRangeMap = buildTranslatedRangeReferenceMap(compiled.parsedSymbolicRanges, translatedParsedSymbolicRanges);
|
|
60
|
+
return {
|
|
61
|
+
source,
|
|
62
|
+
compiled: {
|
|
63
|
+
...compiled,
|
|
64
|
+
source,
|
|
65
|
+
astMatchesSource: false,
|
|
66
|
+
deps: translatedParsedDeps?.map((dependency) => formatParsedDependencyReference(dependency)) ??
|
|
67
|
+
compiled.deps.map((dependency) => translateQualifiedDependencyReference(dependency, rowDelta, colDelta)),
|
|
68
|
+
symbolicRefs: translatedParsedSymbolicRefs?.map((reference) => formatParsedCellReference(reference)) ??
|
|
69
|
+
compiled.symbolicRefs.map((ref) => translateQualifiedCellReference(ref, rowDelta, colDelta)),
|
|
70
|
+
symbolicRanges: translatedParsedSymbolicRanges?.map((range) => formatParsedRangeReference(range)) ??
|
|
71
|
+
compiled.symbolicRanges.map((range) => translateQualifiedRangeReference(range, rowDelta, colDelta)),
|
|
72
|
+
jsPlan: compiled.symbolicRanges.length === 0 && compiled.mode === FormulaMode.WasmFastPath
|
|
73
|
+
? compiled.jsPlan
|
|
74
|
+
: compiled.jsPlan.map((instruction) => translateJsPlanInstructionWithoutAst(instruction, translatedCellMap, translatedRangeMap, rowDelta, colDelta)),
|
|
75
|
+
...(translatedParsedDeps ? { parsedDeps: translatedParsedDeps } : {}),
|
|
76
|
+
...(translatedParsedSymbolicRefs ? { parsedSymbolicRefs: translatedParsedSymbolicRefs } : {}),
|
|
77
|
+
...(translatedParsedSymbolicRanges
|
|
78
|
+
? { parsedSymbolicRanges: translatedParsedSymbolicRanges }
|
|
79
|
+
: {}),
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export function translateCompiledFormula(compiled, rowDelta, colDelta, sourceOverride) {
|
|
84
|
+
const translatedAst = translateNode(compiled.ast, rowDelta, colDelta);
|
|
85
|
+
const translatedOptimizedAst = compiled.optimizedAst === compiled.ast
|
|
86
|
+
? translatedAst
|
|
87
|
+
: translateNode(compiled.optimizedAst, rowDelta, colDelta);
|
|
88
|
+
const translatedParsedDeps = compiled.parsedDeps?.map((dependency) => translateParsedDependencyReference(dependency, rowDelta, colDelta));
|
|
89
|
+
const translatedParsedSymbolicRefs = compiled.parsedSymbolicRefs?.map((reference) => translateParsedCellReference(reference, rowDelta, colDelta));
|
|
90
|
+
const translatedParsedSymbolicRanges = compiled.parsedSymbolicRanges?.map((range) => translateParsedRangeReference(range, rowDelta, colDelta));
|
|
91
|
+
const source = sourceOverride ?? serializeFormula(translatedAst);
|
|
92
|
+
return {
|
|
93
|
+
source,
|
|
94
|
+
compiled: {
|
|
95
|
+
...compiled,
|
|
96
|
+
source,
|
|
97
|
+
ast: translatedAst,
|
|
98
|
+
optimizedAst: translatedOptimizedAst,
|
|
99
|
+
astMatchesSource: true,
|
|
100
|
+
deps: translatedParsedDeps?.map((dependency) => formatParsedDependencyReference(dependency)) ??
|
|
101
|
+
compiled.deps.map((dependency) => translateQualifiedDependencyReference(dependency, rowDelta, colDelta)),
|
|
102
|
+
symbolicRefs: translatedParsedSymbolicRefs?.map((reference) => formatParsedCellReference(reference)) ??
|
|
103
|
+
compiled.symbolicRefs.map((ref) => translateQualifiedCellReference(ref, rowDelta, colDelta)),
|
|
104
|
+
symbolicRanges: translatedParsedSymbolicRanges?.map((range) => formatParsedRangeReference(range)) ??
|
|
105
|
+
compiled.symbolicRanges.map((range) => translateQualifiedRangeReference(range, rowDelta, colDelta)),
|
|
106
|
+
jsPlan: compiled.jsPlan.map((instruction) => translateJsPlanInstruction(instruction, rowDelta, colDelta)),
|
|
107
|
+
...(translatedParsedDeps ? { parsedDeps: translatedParsedDeps } : {}),
|
|
108
|
+
...(translatedParsedSymbolicRefs ? { parsedSymbolicRefs: translatedParsedSymbolicRefs } : {}),
|
|
109
|
+
...(translatedParsedSymbolicRanges
|
|
110
|
+
? { parsedSymbolicRanges: translatedParsedSymbolicRanges }
|
|
111
|
+
: {}),
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
37
115
|
export function rewriteFormulaForStructuralTransform(source, ownerSheetName, targetSheetName, transform) {
|
|
38
116
|
const ast = parseFormula(source);
|
|
39
117
|
return serializeFormula(rewriteNodeForStructuralTransform(ast, ownerSheetName, targetSheetName, transform));
|
|
40
118
|
}
|
|
119
|
+
export function rewriteCompiledFormulaForStructuralTransform(compiled, ownerSheetName, targetSheetName, transform) {
|
|
120
|
+
const currentAst = compiled.astMatchesSource === false ? parseFormula(compiled.source) : compiled.ast;
|
|
121
|
+
const currentOptimizedAst = compiled.astMatchesSource === false
|
|
122
|
+
? currentAst
|
|
123
|
+
: compiled.optimizedAst === compiled.ast
|
|
124
|
+
? currentAst
|
|
125
|
+
: compiled.optimizedAst;
|
|
126
|
+
const rewrittenAst = rewriteNodeForStructuralTransform(currentAst, ownerSheetName, targetSheetName, transform);
|
|
127
|
+
const rewrittenOptimizedAst = currentOptimizedAst === currentAst
|
|
128
|
+
? rewrittenAst
|
|
129
|
+
: rewriteNodeForStructuralTransform(currentOptimizedAst, ownerSheetName, targetSheetName, transform);
|
|
130
|
+
const source = serializeFormula(rewrittenAst);
|
|
131
|
+
if (!nodeStructuralShapeEqual(currentOptimizedAst, rewrittenOptimizedAst)) {
|
|
132
|
+
return {
|
|
133
|
+
source,
|
|
134
|
+
compiled: compileFormulaAst(source, rewrittenOptimizedAst, {
|
|
135
|
+
originalAst: rewrittenAst,
|
|
136
|
+
symbolicNames: compiled.symbolicNames,
|
|
137
|
+
symbolicTables: compiled.symbolicTables,
|
|
138
|
+
symbolicSpills: compiled.symbolicSpills,
|
|
139
|
+
}),
|
|
140
|
+
reusedProgram: false,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
source,
|
|
145
|
+
compiled: {
|
|
146
|
+
...compiled,
|
|
147
|
+
source,
|
|
148
|
+
ast: rewrittenAst,
|
|
149
|
+
optimizedAst: rewrittenOptimizedAst,
|
|
150
|
+
astMatchesSource: true,
|
|
151
|
+
deps: compiled.deps.map((dependency) => rewriteQualifiedDependencyReference(dependency, ownerSheetName, targetSheetName, transform)),
|
|
152
|
+
symbolicRefs: compiled.symbolicRefs.map((ref) => rewriteQualifiedCellReference(ref, ownerSheetName, targetSheetName, transform)),
|
|
153
|
+
symbolicRanges: compiled.symbolicRanges.map((range) => rewriteQualifiedRangeReference(range, ownerSheetName, targetSheetName, transform)),
|
|
154
|
+
jsPlan: compiled.jsPlan.map((instruction) => rewriteJsPlanInstruction(instruction, ownerSheetName, targetSheetName, transform)),
|
|
155
|
+
...(compiled.parsedDeps
|
|
156
|
+
? {
|
|
157
|
+
parsedDeps: compiled.parsedDeps.map((dependency) => rewriteParsedDependencyReference(dependency, ownerSheetName, targetSheetName, transform)),
|
|
158
|
+
}
|
|
159
|
+
: {}),
|
|
160
|
+
...(compiled.parsedSymbolicRefs
|
|
161
|
+
? {
|
|
162
|
+
parsedSymbolicRefs: compiled.parsedSymbolicRefs.map((ref) => rewriteParsedCellReference(ref, ownerSheetName, targetSheetName, transform)),
|
|
163
|
+
}
|
|
164
|
+
: {}),
|
|
165
|
+
...(compiled.parsedSymbolicRanges
|
|
166
|
+
? {
|
|
167
|
+
parsedSymbolicRanges: compiled.parsedSymbolicRanges.map((range) => rewriteParsedRangeReference(range, ownerSheetName, targetSheetName, transform)),
|
|
168
|
+
}
|
|
169
|
+
: {}),
|
|
170
|
+
},
|
|
171
|
+
reusedProgram: true,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
41
174
|
export function renameFormulaSheetReferences(source, oldSheetName, newSheetName) {
|
|
42
175
|
const ast = parseFormula(source);
|
|
43
176
|
return serializeFormula(renameNodeSheetReferences(ast, oldSheetName, newSheetName));
|
|
@@ -141,6 +274,40 @@ function translateNode(node, rowDelta, colDelta) {
|
|
|
141
274
|
};
|
|
142
275
|
}
|
|
143
276
|
}
|
|
277
|
+
function buildRelativeFormulaTemplateKeyInternal(node, ownerRow, ownerCol) {
|
|
278
|
+
switch (node.kind) {
|
|
279
|
+
case "NumberLiteral":
|
|
280
|
+
return `n:${node.value}`;
|
|
281
|
+
case "BooleanLiteral":
|
|
282
|
+
return node.value ? "b:1" : "b:0";
|
|
283
|
+
case "StringLiteral":
|
|
284
|
+
return `s:${JSON.stringify(node.value)}`;
|
|
285
|
+
case "ErrorLiteral":
|
|
286
|
+
return `e:${node.code}`;
|
|
287
|
+
case "NameRef":
|
|
288
|
+
return `name:${node.name}`;
|
|
289
|
+
case "StructuredRef":
|
|
290
|
+
return `table:${node.tableName}[${node.columnName}]`;
|
|
291
|
+
case "CellRef":
|
|
292
|
+
return `cell:${templateSheetKey(node.sheetName)}:${buildRelativeCellReferenceKey(node.ref, ownerRow, ownerCol)}`;
|
|
293
|
+
case "SpillRef":
|
|
294
|
+
return `spill:${templateSheetKey(node.sheetName)}:${buildRelativeCellReferenceKey(node.ref, ownerRow, ownerCol)}`;
|
|
295
|
+
case "ColumnRef":
|
|
296
|
+
return `col:${templateSheetKey(node.sheetName)}:${buildRelativeAxisReferenceKey(node.ref, ownerCol, "column")}`;
|
|
297
|
+
case "RowRef":
|
|
298
|
+
return `row:${templateSheetKey(node.sheetName)}:${buildRelativeAxisReferenceKey(node.ref, ownerRow, "row")}`;
|
|
299
|
+
case "RangeRef":
|
|
300
|
+
return `range:${node.refKind}:${templateSheetKey(node.sheetName)}:${buildRelativeRangeReferenceKey(node, ownerRow, ownerCol)}`;
|
|
301
|
+
case "UnaryExpr":
|
|
302
|
+
return `unary:${node.operator}:${buildRelativeFormulaTemplateKeyInternal(node.argument, ownerRow, ownerCol)}`;
|
|
303
|
+
case "BinaryExpr":
|
|
304
|
+
return `binary:${node.operator}:${buildRelativeFormulaTemplateKeyInternal(node.left, ownerRow, ownerCol)}:${buildRelativeFormulaTemplateKeyInternal(node.right, ownerRow, ownerCol)}`;
|
|
305
|
+
case "CallExpr":
|
|
306
|
+
return `call:${node.callee}:${node.args.map((arg) => buildRelativeFormulaTemplateKeyInternal(arg, ownerRow, ownerCol)).join("|")}`;
|
|
307
|
+
case "InvokeExpr":
|
|
308
|
+
return `invoke:${buildRelativeFormulaTemplateKeyInternal(node.callee, ownerRow, ownerCol)}:${node.args.map((arg) => buildRelativeFormulaTemplateKeyInternal(arg, ownerRow, ownerCol)).join("|")}`;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
144
311
|
function rewriteNodeForStructuralTransform(node, ownerSheetName, targetSheetName, transform) {
|
|
145
312
|
switch (node.kind) {
|
|
146
313
|
case "NumberLiteral":
|
|
@@ -192,6 +359,82 @@ function rewriteNodeForStructuralTransform(node, ownerSheetName, targetSheetName
|
|
|
192
359
|
};
|
|
193
360
|
}
|
|
194
361
|
}
|
|
362
|
+
function templateSheetKey(sheetName) {
|
|
363
|
+
return sheetName === undefined ? "." : JSON.stringify(sheetName);
|
|
364
|
+
}
|
|
365
|
+
function buildRelativeCellReferenceKey(ref, ownerRow, ownerCol) {
|
|
366
|
+
const parsed = parseCellReferenceParts(ref);
|
|
367
|
+
if (!parsed) {
|
|
368
|
+
return `invalid:${ref}`;
|
|
369
|
+
}
|
|
370
|
+
const colKey = parsed.colAbsolute ? `ac${parsed.col}` : `rc${parsed.col - ownerCol}`;
|
|
371
|
+
const rowKey = parsed.rowAbsolute ? `ar${parsed.row}` : `rr${parsed.row - ownerRow}`;
|
|
372
|
+
return `${colKey}:${rowKey}`;
|
|
373
|
+
}
|
|
374
|
+
function buildRelativeAxisReferenceKey(ref, ownerIndex, kind) {
|
|
375
|
+
const parsed = parseAxisReferenceParts(ref, kind);
|
|
376
|
+
if (!parsed) {
|
|
377
|
+
return `invalid:${ref}`;
|
|
378
|
+
}
|
|
379
|
+
return parsed.absolute ? `a${parsed.index}` : `r${parsed.index - ownerIndex}`;
|
|
380
|
+
}
|
|
381
|
+
function buildRelativeRangeReferenceKey(node, ownerRow, ownerCol) {
|
|
382
|
+
switch (node.refKind) {
|
|
383
|
+
case "cells":
|
|
384
|
+
return `${buildRelativeCellReferenceKey(node.start, ownerRow, ownerCol)}:${buildRelativeCellReferenceKey(node.end, ownerRow, ownerCol)}`;
|
|
385
|
+
case "rows":
|
|
386
|
+
return `${buildRelativeAxisReferenceKey(node.start, ownerRow, "row")}:${buildRelativeAxisReferenceKey(node.end, ownerRow, "row")}`;
|
|
387
|
+
case "cols":
|
|
388
|
+
return `${buildRelativeAxisReferenceKey(node.start, ownerCol, "column")}:${buildRelativeAxisReferenceKey(node.end, ownerCol, "column")}`;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
function nodeStructuralShapeEqual(left, right) {
|
|
392
|
+
if (left.kind !== right.kind) {
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
395
|
+
switch (left.kind) {
|
|
396
|
+
case "NumberLiteral":
|
|
397
|
+
return right.kind === "NumberLiteral" && left.value === right.value;
|
|
398
|
+
case "BooleanLiteral":
|
|
399
|
+
return right.kind === "BooleanLiteral" && left.value === right.value;
|
|
400
|
+
case "StringLiteral":
|
|
401
|
+
return right.kind === "StringLiteral" && left.value === right.value;
|
|
402
|
+
case "ErrorLiteral":
|
|
403
|
+
return right.kind === "ErrorLiteral" && left.code === right.code;
|
|
404
|
+
case "NameRef":
|
|
405
|
+
return right.kind === "NameRef" && left.name === right.name;
|
|
406
|
+
case "StructuredRef":
|
|
407
|
+
return (right.kind === "StructuredRef" &&
|
|
408
|
+
left.tableName === right.tableName &&
|
|
409
|
+
left.columnName === right.columnName);
|
|
410
|
+
case "CellRef":
|
|
411
|
+
case "SpillRef":
|
|
412
|
+
case "ColumnRef":
|
|
413
|
+
case "RowRef":
|
|
414
|
+
return true;
|
|
415
|
+
case "RangeRef":
|
|
416
|
+
return right.kind === "RangeRef" && left.refKind === right.refKind;
|
|
417
|
+
case "UnaryExpr":
|
|
418
|
+
return (right.kind === "UnaryExpr" &&
|
|
419
|
+
left.operator === right.operator &&
|
|
420
|
+
nodeStructuralShapeEqual(left.argument, right.argument));
|
|
421
|
+
case "BinaryExpr":
|
|
422
|
+
return (right.kind === "BinaryExpr" &&
|
|
423
|
+
left.operator === right.operator &&
|
|
424
|
+
nodeStructuralShapeEqual(left.left, right.left) &&
|
|
425
|
+
nodeStructuralShapeEqual(left.right, right.right));
|
|
426
|
+
case "CallExpr":
|
|
427
|
+
return (right.kind === "CallExpr" &&
|
|
428
|
+
left.callee === right.callee &&
|
|
429
|
+
left.args.length === right.args.length &&
|
|
430
|
+
left.args.every((arg, index) => nodeStructuralShapeEqual(arg, right.args[index])));
|
|
431
|
+
case "InvokeExpr":
|
|
432
|
+
return (right.kind === "InvokeExpr" &&
|
|
433
|
+
left.args.length === right.args.length &&
|
|
434
|
+
nodeStructuralShapeEqual(left.callee, right.callee) &&
|
|
435
|
+
left.args.every((arg, index) => nodeStructuralShapeEqual(arg, right.args[index])));
|
|
436
|
+
}
|
|
437
|
+
}
|
|
195
438
|
function renameNodeSheetReferences(node, oldSheetName, newSheetName) {
|
|
196
439
|
switch (node.kind) {
|
|
197
440
|
case "NumberLiteral":
|
|
@@ -310,6 +553,698 @@ function rewriteRangeNode(node, ownerSheetName, targetSheetName, transform) {
|
|
|
310
553
|
end: formatAxisReference(end.absolute, nextInterval.end, node.refKind === "rows" ? "row" : "column"),
|
|
311
554
|
};
|
|
312
555
|
}
|
|
556
|
+
function rewriteParsedCellReference(reference, ownerSheetName, targetSheetName, transform) {
|
|
557
|
+
const sheetName = reference.sheetName ?? ownerSheetName;
|
|
558
|
+
if (sheetName !== targetSheetName) {
|
|
559
|
+
return reference;
|
|
560
|
+
}
|
|
561
|
+
const nextAddress = rewriteAddressForStructuralTransform(reference.address, transform);
|
|
562
|
+
if (!nextAddress) {
|
|
563
|
+
return reference;
|
|
564
|
+
}
|
|
565
|
+
const parsed = parseCellAddress(nextAddress, sheetName);
|
|
566
|
+
return {
|
|
567
|
+
...reference,
|
|
568
|
+
address: parsed.text,
|
|
569
|
+
...(reference.sheetName !== undefined ? { sheetName: parsed.sheetName } : {}),
|
|
570
|
+
...(reference.row !== undefined ? { row: parsed.row } : {}),
|
|
571
|
+
...(reference.col !== undefined ? { col: parsed.col } : {}),
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
function rewriteParsedRangeReference(reference, ownerSheetName, targetSheetName, transform) {
|
|
575
|
+
const explicitSheetName = reference.sheetName;
|
|
576
|
+
if (!targetsSheet(explicitSheetName, ownerSheetName, targetSheetName)) {
|
|
577
|
+
return reference;
|
|
578
|
+
}
|
|
579
|
+
const nextRange = rewriteRangeAddressForStructuralTransform(parseRangeAddress(formatQualifiedRangeReference(explicitSheetName, reference.startAddress, reference.endAddress)), transform);
|
|
580
|
+
if (!nextRange) {
|
|
581
|
+
return reference;
|
|
582
|
+
}
|
|
583
|
+
const bounds = nextRange.kind === "cells"
|
|
584
|
+
? {
|
|
585
|
+
startRow: nextRange.start.row,
|
|
586
|
+
endRow: nextRange.end.row,
|
|
587
|
+
startCol: nextRange.start.col,
|
|
588
|
+
endCol: nextRange.end.col,
|
|
589
|
+
}
|
|
590
|
+
: nextRange.kind === "rows"
|
|
591
|
+
? {
|
|
592
|
+
startRow: nextRange.start.row,
|
|
593
|
+
endRow: nextRange.end.row,
|
|
594
|
+
startCol: 0,
|
|
595
|
+
endCol: 0,
|
|
596
|
+
}
|
|
597
|
+
: {
|
|
598
|
+
startRow: 0,
|
|
599
|
+
endRow: 0,
|
|
600
|
+
startCol: nextRange.start.col,
|
|
601
|
+
endCol: nextRange.end.col,
|
|
602
|
+
};
|
|
603
|
+
return {
|
|
604
|
+
...reference,
|
|
605
|
+
address: formatQualifiedRangeReference(explicitSheetName, nextRange.start.text, nextRange.end.text),
|
|
606
|
+
refKind: nextRange.kind,
|
|
607
|
+
startAddress: nextRange.start.text,
|
|
608
|
+
endAddress: nextRange.end.text,
|
|
609
|
+
...bounds,
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
function rewriteParsedDependencyReference(reference, ownerSheetName, targetSheetName, transform) {
|
|
613
|
+
return reference.kind === "cell"
|
|
614
|
+
? rewriteParsedCellReference(reference, ownerSheetName, targetSheetName, transform)
|
|
615
|
+
: rewriteParsedRangeReference(reference, ownerSheetName, targetSheetName, transform);
|
|
616
|
+
}
|
|
617
|
+
function translateParsedCellReference(reference, rowDelta, colDelta) {
|
|
618
|
+
const parts = reference.rowAbsolute !== undefined &&
|
|
619
|
+
reference.colAbsolute !== undefined &&
|
|
620
|
+
reference.row !== undefined &&
|
|
621
|
+
reference.col !== undefined
|
|
622
|
+
? {
|
|
623
|
+
row: reference.row,
|
|
624
|
+
col: reference.col,
|
|
625
|
+
rowAbsolute: reference.rowAbsolute,
|
|
626
|
+
colAbsolute: reference.colAbsolute,
|
|
627
|
+
}
|
|
628
|
+
: parseCellReferenceParts(reference.address);
|
|
629
|
+
if (!parts) {
|
|
630
|
+
return reference;
|
|
631
|
+
}
|
|
632
|
+
const nextRow = parts.rowAbsolute ? parts.row : parts.row + rowDelta;
|
|
633
|
+
const nextCol = parts.colAbsolute ? parts.col : parts.col + colDelta;
|
|
634
|
+
const nextLocalAddress = formatCellReference(parts, nextRow, nextCol);
|
|
635
|
+
const nextAddress = reference.explicitSheet || reference.sheetName !== undefined
|
|
636
|
+
? formatQualifiedCellReference(reference.sheetName, nextLocalAddress)
|
|
637
|
+
: nextLocalAddress;
|
|
638
|
+
return {
|
|
639
|
+
...reference,
|
|
640
|
+
address: nextAddress,
|
|
641
|
+
...(reference.sheetName !== undefined ? { sheetName: reference.sheetName } : {}),
|
|
642
|
+
...(reference.explicitSheet !== undefined ? { explicitSheet: reference.explicitSheet } : {}),
|
|
643
|
+
...(reference.row !== undefined ? { row: nextRow } : {}),
|
|
644
|
+
...(reference.col !== undefined ? { col: nextCol } : {}),
|
|
645
|
+
...(reference.rowAbsolute !== undefined ? { rowAbsolute: parts.rowAbsolute } : {}),
|
|
646
|
+
...(reference.colAbsolute !== undefined ? { colAbsolute: parts.colAbsolute } : {}),
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
function translateParsedRangeReference(reference, rowDelta, colDelta) {
|
|
650
|
+
const nextRange = translateParsedRangeReferenceInfo(reference, rowDelta, colDelta);
|
|
651
|
+
const bounds = nextRange.refKind === "cells"
|
|
652
|
+
? {
|
|
653
|
+
startRow: nextRange.startRow,
|
|
654
|
+
endRow: nextRange.endRow,
|
|
655
|
+
startCol: nextRange.startCol,
|
|
656
|
+
endCol: nextRange.endCol,
|
|
657
|
+
}
|
|
658
|
+
: nextRange.refKind === "rows"
|
|
659
|
+
? {
|
|
660
|
+
startRow: nextRange.startRow,
|
|
661
|
+
endRow: nextRange.endRow,
|
|
662
|
+
startCol: 0,
|
|
663
|
+
endCol: 0,
|
|
664
|
+
}
|
|
665
|
+
: {
|
|
666
|
+
startRow: 0,
|
|
667
|
+
endRow: 0,
|
|
668
|
+
startCol: nextRange.startCol,
|
|
669
|
+
endCol: nextRange.endCol,
|
|
670
|
+
};
|
|
671
|
+
return {
|
|
672
|
+
...reference,
|
|
673
|
+
address: formatParsedRangeReference(nextRange),
|
|
674
|
+
refKind: nextRange.refKind,
|
|
675
|
+
startAddress: nextRange.startAddress,
|
|
676
|
+
endAddress: nextRange.endAddress,
|
|
677
|
+
...bounds,
|
|
678
|
+
...(reference.explicitSheet !== undefined ? { explicitSheet: reference.explicitSheet } : {}),
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
function translateParsedDependencyReference(reference, rowDelta, colDelta) {
|
|
682
|
+
return reference.kind === "cell"
|
|
683
|
+
? translateParsedCellReference(reference, rowDelta, colDelta)
|
|
684
|
+
: translateParsedRangeReference(reference, rowDelta, colDelta);
|
|
685
|
+
}
|
|
686
|
+
function translateQualifiedCellReference(raw, rowDelta, colDelta) {
|
|
687
|
+
const explicitlyQualified = raw.includes("!");
|
|
688
|
+
const parsed = parseCellAddress(raw);
|
|
689
|
+
const nextAddress = translateCellReference(parsed.text, rowDelta, colDelta);
|
|
690
|
+
return explicitlyQualified
|
|
691
|
+
? formatQualifiedCellReference(parsed.sheetName, nextAddress)
|
|
692
|
+
: nextAddress;
|
|
693
|
+
}
|
|
694
|
+
function formatParsedCellReference(reference) {
|
|
695
|
+
const localAddress = formatParsedLocalCellReference(reference);
|
|
696
|
+
return reference.explicitSheet || reference.sheetName !== undefined
|
|
697
|
+
? formatQualifiedCellReference(reference.sheetName, localAddress)
|
|
698
|
+
: localAddress;
|
|
699
|
+
}
|
|
700
|
+
function formatParsedLocalCellReference(reference) {
|
|
701
|
+
const parts = reference.row !== undefined &&
|
|
702
|
+
reference.col !== undefined &&
|
|
703
|
+
reference.rowAbsolute !== undefined &&
|
|
704
|
+
reference.colAbsolute !== undefined
|
|
705
|
+
? {
|
|
706
|
+
row: reference.row,
|
|
707
|
+
col: reference.col,
|
|
708
|
+
rowAbsolute: reference.rowAbsolute,
|
|
709
|
+
colAbsolute: reference.colAbsolute,
|
|
710
|
+
}
|
|
711
|
+
: parseCellReferenceParts(reference.address);
|
|
712
|
+
if (!parts) {
|
|
713
|
+
return stripSheetQualifier(reference.address);
|
|
714
|
+
}
|
|
715
|
+
return formatCellReference(parts, parts.row, parts.col);
|
|
716
|
+
}
|
|
717
|
+
function formatParsedRangeReference(reference) {
|
|
718
|
+
return formatQualifiedRangeReference(reference.explicitSheet ? reference.sheetName : undefined, reference.startAddress, reference.endAddress);
|
|
719
|
+
}
|
|
720
|
+
function stripSheetQualifier(reference) {
|
|
721
|
+
const bang = reference.lastIndexOf("!");
|
|
722
|
+
return bang === -1 ? reference : reference.slice(bang + 1);
|
|
723
|
+
}
|
|
724
|
+
function translatedCellInstructionKey(sheetName, address) {
|
|
725
|
+
return `${sheetName ?? ""}\t${address}`;
|
|
726
|
+
}
|
|
727
|
+
function translatedRangeInstructionKey(sheetName, refKind, start, end) {
|
|
728
|
+
return `${sheetName ?? ""}\t${refKind}\t${start}\t${end}`;
|
|
729
|
+
}
|
|
730
|
+
function buildTranslatedCellReferenceMap(original, translated) {
|
|
731
|
+
const output = new Map();
|
|
732
|
+
if (!original || !translated || original.length !== translated.length) {
|
|
733
|
+
return output;
|
|
734
|
+
}
|
|
735
|
+
for (let index = 0; index < original.length; index += 1) {
|
|
736
|
+
const source = original[index];
|
|
737
|
+
const target = translated[index];
|
|
738
|
+
if (!source || !target) {
|
|
739
|
+
continue;
|
|
740
|
+
}
|
|
741
|
+
output.set(translatedCellInstructionKey(source.sheetName, formatParsedLocalCellReference(source)), target);
|
|
742
|
+
}
|
|
743
|
+
return output;
|
|
744
|
+
}
|
|
745
|
+
function buildTranslatedRangeReferenceMap(original, translated) {
|
|
746
|
+
const output = new Map();
|
|
747
|
+
if (!original || !translated || original.length !== translated.length) {
|
|
748
|
+
return output;
|
|
749
|
+
}
|
|
750
|
+
for (let index = 0; index < original.length; index += 1) {
|
|
751
|
+
const source = original[index];
|
|
752
|
+
const target = translated[index];
|
|
753
|
+
if (!source || !target) {
|
|
754
|
+
continue;
|
|
755
|
+
}
|
|
756
|
+
output.set(translatedRangeInstructionKey(source.sheetName, source.refKind, source.startAddress, source.endAddress), target);
|
|
757
|
+
}
|
|
758
|
+
return output;
|
|
759
|
+
}
|
|
760
|
+
function formatParsedDependencyReference(reference) {
|
|
761
|
+
return reference.kind === "cell"
|
|
762
|
+
? formatParsedCellReference(reference)
|
|
763
|
+
: formatParsedRangeReference(reference);
|
|
764
|
+
}
|
|
765
|
+
function translateQualifiedDependencyReference(raw, rowDelta, colDelta) {
|
|
766
|
+
if (!raw.includes(":")) {
|
|
767
|
+
return translateQualifiedCellReference(raw, rowDelta, colDelta);
|
|
768
|
+
}
|
|
769
|
+
return translateQualifiedRangeReference(raw, rowDelta, colDelta);
|
|
770
|
+
}
|
|
771
|
+
function translateQualifiedRangeReference(raw, rowDelta, colDelta) {
|
|
772
|
+
const explicitlyQualified = raw.includes("!");
|
|
773
|
+
const parsed = parseRangeAddress(raw);
|
|
774
|
+
const nextRange = translateRangeAddress(parsed, rowDelta, colDelta);
|
|
775
|
+
if (explicitlyQualified) {
|
|
776
|
+
return formatRangeAddress(nextRange);
|
|
777
|
+
}
|
|
778
|
+
return `${nextRange.start.text}:${nextRange.end.text}`;
|
|
779
|
+
}
|
|
780
|
+
function translateRangeAddress(range, rowDelta, colDelta) {
|
|
781
|
+
switch (range.kind) {
|
|
782
|
+
case "cells": {
|
|
783
|
+
const startAddress = translateCellReference(range.start.text, rowDelta, colDelta);
|
|
784
|
+
const endAddress = translateCellReference(range.end.text, rowDelta, colDelta);
|
|
785
|
+
return parseRangeAddress(formatQualifiedRangeReference(range.sheetName, startAddress, endAddress));
|
|
786
|
+
}
|
|
787
|
+
case "rows": {
|
|
788
|
+
const start = translateRowReference(range.start.text, rowDelta);
|
|
789
|
+
const end = translateRowReference(range.end.text, rowDelta);
|
|
790
|
+
return parseRangeAddress(formatQualifiedRangeReference(range.sheetName, start, end));
|
|
791
|
+
}
|
|
792
|
+
case "cols": {
|
|
793
|
+
const start = translateColumnReference(range.start.text, colDelta);
|
|
794
|
+
const end = translateColumnReference(range.end.text, colDelta);
|
|
795
|
+
return parseRangeAddress(formatQualifiedRangeReference(range.sheetName, start, end));
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
function translateParsedRangeReferenceInfo(reference, rowDelta, colDelta) {
|
|
800
|
+
if (reference.refKind === "cells") {
|
|
801
|
+
const startRow = (reference.startRowAbsolute ?? false) ? reference.startRow : reference.startRow + rowDelta;
|
|
802
|
+
const endRow = (reference.endRowAbsolute ?? false) ? reference.endRow : reference.endRow + rowDelta;
|
|
803
|
+
const startCol = (reference.startColAbsolute ?? false) ? reference.startCol : reference.startCol + colDelta;
|
|
804
|
+
const endCol = (reference.endColAbsolute ?? false) ? reference.endCol : reference.endCol + colDelta;
|
|
805
|
+
const startAddress = formatCellReference({
|
|
806
|
+
row: reference.startRow,
|
|
807
|
+
col: reference.startCol,
|
|
808
|
+
rowAbsolute: reference.startRowAbsolute ?? false,
|
|
809
|
+
colAbsolute: reference.startColAbsolute ?? false,
|
|
810
|
+
}, startRow, startCol);
|
|
811
|
+
const endAddress = formatCellReference({
|
|
812
|
+
row: reference.endRow,
|
|
813
|
+
col: reference.endCol,
|
|
814
|
+
rowAbsolute: reference.endRowAbsolute ?? false,
|
|
815
|
+
colAbsolute: reference.endColAbsolute ?? false,
|
|
816
|
+
}, endRow, endCol);
|
|
817
|
+
return {
|
|
818
|
+
...reference,
|
|
819
|
+
startAddress,
|
|
820
|
+
endAddress,
|
|
821
|
+
startRow,
|
|
822
|
+
endRow,
|
|
823
|
+
startCol,
|
|
824
|
+
endCol,
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
if (reference.refKind === "rows") {
|
|
828
|
+
const startRow = (reference.startRowAbsolute ?? false) ? reference.startRow : reference.startRow + rowDelta;
|
|
829
|
+
const endRow = (reference.endRowAbsolute ?? false) ? reference.endRow : reference.endRow + rowDelta;
|
|
830
|
+
return {
|
|
831
|
+
...reference,
|
|
832
|
+
startAddress: formatAxisReference(reference.startRowAbsolute ?? false, startRow, "row"),
|
|
833
|
+
endAddress: formatAxisReference(reference.endRowAbsolute ?? false, endRow, "row"),
|
|
834
|
+
startRow,
|
|
835
|
+
endRow,
|
|
836
|
+
startCol: 0,
|
|
837
|
+
endCol: 0,
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
const startCol = (reference.startColAbsolute ?? false) ? reference.startCol : reference.startCol + colDelta;
|
|
841
|
+
const endCol = (reference.endColAbsolute ?? false) ? reference.endCol : reference.endCol + colDelta;
|
|
842
|
+
return {
|
|
843
|
+
...reference,
|
|
844
|
+
startAddress: formatAxisReference(reference.startColAbsolute ?? false, startCol, "column"),
|
|
845
|
+
endAddress: formatAxisReference(reference.endColAbsolute ?? false, endCol, "column"),
|
|
846
|
+
startRow: 0,
|
|
847
|
+
endRow: 0,
|
|
848
|
+
startCol,
|
|
849
|
+
endCol,
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
function rewriteQualifiedCellReference(raw, ownerSheetName, targetSheetName, transform) {
|
|
853
|
+
const explicitlyQualified = raw.includes("!");
|
|
854
|
+
const parsed = parseCellAddress(raw, ownerSheetName);
|
|
855
|
+
if (parsed.sheetName !== targetSheetName) {
|
|
856
|
+
return raw;
|
|
857
|
+
}
|
|
858
|
+
const nextAddress = rewriteAddressForStructuralTransform(parsed.text, transform);
|
|
859
|
+
if (!nextAddress) {
|
|
860
|
+
return raw;
|
|
861
|
+
}
|
|
862
|
+
return explicitlyQualified
|
|
863
|
+
? formatQualifiedCellReference(parsed.sheetName, nextAddress)
|
|
864
|
+
: nextAddress;
|
|
865
|
+
}
|
|
866
|
+
function rewriteQualifiedDependencyReference(raw, ownerSheetName, targetSheetName, transform) {
|
|
867
|
+
if (!raw.includes(":")) {
|
|
868
|
+
return rewriteQualifiedCellReference(raw, ownerSheetName, targetSheetName, transform);
|
|
869
|
+
}
|
|
870
|
+
return rewriteQualifiedRangeReference(raw, ownerSheetName, targetSheetName, transform);
|
|
871
|
+
}
|
|
872
|
+
function rewriteQualifiedRangeReference(raw, ownerSheetName, targetSheetName, transform) {
|
|
873
|
+
const explicitlyQualified = raw.includes("!");
|
|
874
|
+
const parsed = parseRangeAddress(raw, ownerSheetName);
|
|
875
|
+
const sheetName = parsed.sheetName ?? ownerSheetName;
|
|
876
|
+
if (sheetName !== targetSheetName) {
|
|
877
|
+
return raw;
|
|
878
|
+
}
|
|
879
|
+
const nextRange = rewriteRangeAddressForStructuralTransform(parsed, transform);
|
|
880
|
+
if (!nextRange) {
|
|
881
|
+
return raw;
|
|
882
|
+
}
|
|
883
|
+
if (explicitlyQualified) {
|
|
884
|
+
return formatRangeAddress(nextRange);
|
|
885
|
+
}
|
|
886
|
+
return `${nextRange.start.text}:${nextRange.end.text}`;
|
|
887
|
+
}
|
|
888
|
+
function rewriteRangeAddressForStructuralTransform(range, transform) {
|
|
889
|
+
switch (range.kind) {
|
|
890
|
+
case "cells": {
|
|
891
|
+
const nextRange = rewriteRangeForStructuralTransform(range.start.text, range.end.text, transform);
|
|
892
|
+
if (!nextRange) {
|
|
893
|
+
return undefined;
|
|
894
|
+
}
|
|
895
|
+
return parseRangeAddress(formatQualifiedRangeReference(range.sheetName, nextRange.startAddress, nextRange.endAddress));
|
|
896
|
+
}
|
|
897
|
+
case "rows":
|
|
898
|
+
if (transform.axis !== "row") {
|
|
899
|
+
return range;
|
|
900
|
+
}
|
|
901
|
+
return rewriteAxisRangeAddress(range, transform);
|
|
902
|
+
case "cols":
|
|
903
|
+
if (transform.axis !== "column") {
|
|
904
|
+
return range;
|
|
905
|
+
}
|
|
906
|
+
return rewriteAxisRangeAddress(range, transform);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
function rewriteAxisRangeAddress(range, transform) {
|
|
910
|
+
const startIndex = range.kind === "rows" ? range.start.row : range.start.col;
|
|
911
|
+
const endIndex = range.kind === "rows" ? range.end.row : range.end.col;
|
|
912
|
+
const nextInterval = mapInterval(startIndex, endIndex, transform);
|
|
913
|
+
if (!nextInterval) {
|
|
914
|
+
return undefined;
|
|
915
|
+
}
|
|
916
|
+
const prefix = range.sheetName ? `${quoteSheetNameIfNeeded(range.sheetName)}!` : "";
|
|
917
|
+
const startText = range.kind === "rows"
|
|
918
|
+
? formatAxisReference(false, nextInterval.start, "row")
|
|
919
|
+
: formatAxisReference(false, nextInterval.start, "column");
|
|
920
|
+
const endText = range.kind === "rows"
|
|
921
|
+
? formatAxisReference(false, nextInterval.end, "row")
|
|
922
|
+
: formatAxisReference(false, nextInterval.end, "column");
|
|
923
|
+
return parseRangeAddress(`${prefix}${startText}:${endText}`);
|
|
924
|
+
}
|
|
925
|
+
function rewriteJsPlanInstruction(instruction, ownerSheetName, targetSheetName, transform) {
|
|
926
|
+
switch (instruction.opcode) {
|
|
927
|
+
case "push-cell":
|
|
928
|
+
return {
|
|
929
|
+
...instruction,
|
|
930
|
+
address: rewriteReferenceOperandAddress(instruction.sheetName, instruction.address, ownerSheetName, targetSheetName, transform),
|
|
931
|
+
};
|
|
932
|
+
case "push-range": {
|
|
933
|
+
const nextRange = rewritePlanRangeInstruction(instruction.sheetName, instruction.start, instruction.end, instruction.refKind, ownerSheetName, targetSheetName, transform);
|
|
934
|
+
return nextRange ? { ...instruction, ...nextRange } : instruction;
|
|
935
|
+
}
|
|
936
|
+
case "lookup-exact-match":
|
|
937
|
+
case "lookup-approximate-match": {
|
|
938
|
+
const nextRange = rewritePlanRangeInstruction(instruction.sheetName, instruction.start, instruction.end, instruction.refKind, ownerSheetName, targetSheetName, transform);
|
|
939
|
+
if (!nextRange) {
|
|
940
|
+
return instruction;
|
|
941
|
+
}
|
|
942
|
+
const parsed = parseRangeAddress(formatQualifiedRangeReference(instruction.sheetName, nextRange.start, nextRange.end));
|
|
943
|
+
if (parsed.kind !== "cells") {
|
|
944
|
+
return instruction;
|
|
945
|
+
}
|
|
946
|
+
return {
|
|
947
|
+
...instruction,
|
|
948
|
+
...nextRange,
|
|
949
|
+
startRow: parsed.start.row,
|
|
950
|
+
endRow: parsed.end.row,
|
|
951
|
+
startCol: parsed.start.col,
|
|
952
|
+
endCol: parsed.end.col,
|
|
953
|
+
};
|
|
954
|
+
}
|
|
955
|
+
case "call":
|
|
956
|
+
return instruction.argRefs
|
|
957
|
+
? {
|
|
958
|
+
...instruction,
|
|
959
|
+
argRefs: instruction.argRefs.map((argRef) => argRef
|
|
960
|
+
? rewriteReferenceOperand(argRef, ownerSheetName, targetSheetName, transform)
|
|
961
|
+
: argRef),
|
|
962
|
+
}
|
|
963
|
+
: instruction;
|
|
964
|
+
case "push-lambda":
|
|
965
|
+
return {
|
|
966
|
+
...instruction,
|
|
967
|
+
body: instruction.body.map((step) => rewriteJsPlanInstruction(step, ownerSheetName, targetSheetName, transform)),
|
|
968
|
+
};
|
|
969
|
+
case "push-number":
|
|
970
|
+
case "push-boolean":
|
|
971
|
+
case "push-string":
|
|
972
|
+
case "push-error":
|
|
973
|
+
case "push-name":
|
|
974
|
+
case "unary":
|
|
975
|
+
case "binary":
|
|
976
|
+
case "invoke":
|
|
977
|
+
case "begin-scope":
|
|
978
|
+
case "bind-name":
|
|
979
|
+
case "end-scope":
|
|
980
|
+
case "jump-if-false":
|
|
981
|
+
case "jump":
|
|
982
|
+
case "return":
|
|
983
|
+
return instruction;
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
function translateJsPlanInstruction(instruction, rowDelta, colDelta) {
|
|
987
|
+
switch (instruction.opcode) {
|
|
988
|
+
case "push-cell":
|
|
989
|
+
return {
|
|
990
|
+
...instruction,
|
|
991
|
+
address: translateCellReference(instruction.address, rowDelta, colDelta),
|
|
992
|
+
};
|
|
993
|
+
case "push-range": {
|
|
994
|
+
const nextRange = translatePlanRangeInstruction(instruction.sheetName, instruction.start, instruction.end, rowDelta, colDelta);
|
|
995
|
+
return { ...instruction, ...nextRange };
|
|
996
|
+
}
|
|
997
|
+
case "lookup-exact-match":
|
|
998
|
+
case "lookup-approximate-match": {
|
|
999
|
+
const nextRange = translatePlanRangeInstruction(instruction.sheetName, instruction.start, instruction.end, rowDelta, colDelta);
|
|
1000
|
+
const parsed = parseRangeAddress(formatQualifiedRangeReference(instruction.sheetName, nextRange.start, nextRange.end));
|
|
1001
|
+
if (parsed.kind !== "cells") {
|
|
1002
|
+
return instruction;
|
|
1003
|
+
}
|
|
1004
|
+
return {
|
|
1005
|
+
...instruction,
|
|
1006
|
+
...nextRange,
|
|
1007
|
+
startRow: parsed.start.row,
|
|
1008
|
+
endRow: parsed.end.row,
|
|
1009
|
+
startCol: parsed.start.col,
|
|
1010
|
+
endCol: parsed.end.col,
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
case "call":
|
|
1014
|
+
return instruction.argRefs
|
|
1015
|
+
? {
|
|
1016
|
+
...instruction,
|
|
1017
|
+
argRefs: instruction.argRefs.map((argRef) => argRef ? translateReferenceOperand(argRef, rowDelta, colDelta) : argRef),
|
|
1018
|
+
}
|
|
1019
|
+
: instruction;
|
|
1020
|
+
case "push-lambda":
|
|
1021
|
+
return {
|
|
1022
|
+
...instruction,
|
|
1023
|
+
body: instruction.body.map((step) => translateJsPlanInstruction(step, rowDelta, colDelta)),
|
|
1024
|
+
};
|
|
1025
|
+
case "push-number":
|
|
1026
|
+
case "push-boolean":
|
|
1027
|
+
case "push-string":
|
|
1028
|
+
case "push-error":
|
|
1029
|
+
case "push-name":
|
|
1030
|
+
case "unary":
|
|
1031
|
+
case "binary":
|
|
1032
|
+
case "invoke":
|
|
1033
|
+
case "begin-scope":
|
|
1034
|
+
case "bind-name":
|
|
1035
|
+
case "end-scope":
|
|
1036
|
+
case "jump-if-false":
|
|
1037
|
+
case "jump":
|
|
1038
|
+
case "return":
|
|
1039
|
+
return instruction;
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
function translateJsPlanInstructionWithoutAst(instruction, translatedCellMap, translatedRangeMap, rowDelta, colDelta) {
|
|
1043
|
+
switch (instruction.opcode) {
|
|
1044
|
+
case "push-cell": {
|
|
1045
|
+
const translated = translatedCellMap.get(translatedCellInstructionKey(instruction.sheetName, instruction.address));
|
|
1046
|
+
return translated
|
|
1047
|
+
? {
|
|
1048
|
+
...instruction,
|
|
1049
|
+
address: formatParsedLocalCellReference(translated),
|
|
1050
|
+
}
|
|
1051
|
+
: translateJsPlanInstruction(instruction, rowDelta, colDelta);
|
|
1052
|
+
}
|
|
1053
|
+
case "push-range": {
|
|
1054
|
+
const translated = translatedRangeMap.get(translatedRangeInstructionKey(instruction.sheetName, instruction.refKind, instruction.start, instruction.end));
|
|
1055
|
+
return translated
|
|
1056
|
+
? {
|
|
1057
|
+
...instruction,
|
|
1058
|
+
start: translated.startAddress,
|
|
1059
|
+
end: translated.endAddress,
|
|
1060
|
+
}
|
|
1061
|
+
: translateJsPlanInstruction(instruction, rowDelta, colDelta);
|
|
1062
|
+
}
|
|
1063
|
+
case "lookup-exact-match":
|
|
1064
|
+
case "lookup-approximate-match": {
|
|
1065
|
+
const translated = translatedRangeMap.get(translatedRangeInstructionKey(instruction.sheetName, instruction.refKind, instruction.start, instruction.end));
|
|
1066
|
+
if (!translated || translated.refKind !== "cells") {
|
|
1067
|
+
return translateJsPlanInstruction(instruction, rowDelta, colDelta);
|
|
1068
|
+
}
|
|
1069
|
+
return {
|
|
1070
|
+
...instruction,
|
|
1071
|
+
start: translated.startAddress,
|
|
1072
|
+
end: translated.endAddress,
|
|
1073
|
+
startRow: translated.startRow,
|
|
1074
|
+
endRow: translated.endRow,
|
|
1075
|
+
startCol: translated.startCol,
|
|
1076
|
+
endCol: translated.endCol,
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
case "call":
|
|
1080
|
+
return instruction.argRefs
|
|
1081
|
+
? {
|
|
1082
|
+
...instruction,
|
|
1083
|
+
argRefs: instruction.argRefs.map((argRef) => argRef
|
|
1084
|
+
? translateReferenceOperandWithoutAst(argRef, translatedCellMap, translatedRangeMap, rowDelta, colDelta)
|
|
1085
|
+
: argRef),
|
|
1086
|
+
}
|
|
1087
|
+
: instruction;
|
|
1088
|
+
case "push-lambda":
|
|
1089
|
+
return {
|
|
1090
|
+
...instruction,
|
|
1091
|
+
body: instruction.body.map((step) => translateJsPlanInstructionWithoutAst(step, translatedCellMap, translatedRangeMap, rowDelta, colDelta)),
|
|
1092
|
+
};
|
|
1093
|
+
case "push-number":
|
|
1094
|
+
case "push-boolean":
|
|
1095
|
+
case "push-string":
|
|
1096
|
+
case "push-error":
|
|
1097
|
+
case "push-name":
|
|
1098
|
+
case "unary":
|
|
1099
|
+
case "binary":
|
|
1100
|
+
case "invoke":
|
|
1101
|
+
case "begin-scope":
|
|
1102
|
+
case "bind-name":
|
|
1103
|
+
case "end-scope":
|
|
1104
|
+
case "jump-if-false":
|
|
1105
|
+
case "jump":
|
|
1106
|
+
case "return":
|
|
1107
|
+
return instruction;
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
function rewriteReferenceOperand(operand, ownerSheetName, targetSheetName, transform) {
|
|
1111
|
+
switch (operand.kind) {
|
|
1112
|
+
case "cell":
|
|
1113
|
+
return operand.address
|
|
1114
|
+
? {
|
|
1115
|
+
...operand,
|
|
1116
|
+
address: rewriteReferenceOperandAddress(operand.sheetName, operand.address, ownerSheetName, targetSheetName, transform),
|
|
1117
|
+
}
|
|
1118
|
+
: operand;
|
|
1119
|
+
case "range": {
|
|
1120
|
+
if (!operand.start || !operand.end || !operand.refKind) {
|
|
1121
|
+
return operand;
|
|
1122
|
+
}
|
|
1123
|
+
const nextRange = rewritePlanRangeInstruction(operand.sheetName, operand.start, operand.end, operand.refKind, ownerSheetName, targetSheetName, transform);
|
|
1124
|
+
return nextRange ? { ...operand, ...nextRange } : operand;
|
|
1125
|
+
}
|
|
1126
|
+
case "row":
|
|
1127
|
+
case "col":
|
|
1128
|
+
return operand;
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
function translateReferenceOperand(operand, rowDelta, colDelta) {
|
|
1132
|
+
switch (operand.kind) {
|
|
1133
|
+
case "cell":
|
|
1134
|
+
return operand.address
|
|
1135
|
+
? {
|
|
1136
|
+
...operand,
|
|
1137
|
+
address: translateCellReference(operand.address, rowDelta, colDelta),
|
|
1138
|
+
}
|
|
1139
|
+
: operand;
|
|
1140
|
+
case "range":
|
|
1141
|
+
if (!operand.start || !operand.end || !operand.refKind) {
|
|
1142
|
+
return operand;
|
|
1143
|
+
}
|
|
1144
|
+
return {
|
|
1145
|
+
...operand,
|
|
1146
|
+
...translatePlanRangeInstruction(operand.sheetName, operand.start, operand.end, rowDelta, colDelta),
|
|
1147
|
+
};
|
|
1148
|
+
case "row":
|
|
1149
|
+
return operand.address
|
|
1150
|
+
? {
|
|
1151
|
+
...operand,
|
|
1152
|
+
address: translateRowReference(operand.address, rowDelta),
|
|
1153
|
+
}
|
|
1154
|
+
: operand;
|
|
1155
|
+
case "col":
|
|
1156
|
+
return operand.address
|
|
1157
|
+
? {
|
|
1158
|
+
...operand,
|
|
1159
|
+
address: translateColumnReference(operand.address, colDelta),
|
|
1160
|
+
}
|
|
1161
|
+
: operand;
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
function translateReferenceOperandWithoutAst(operand, translatedCellMap, translatedRangeMap, rowDelta, colDelta) {
|
|
1165
|
+
switch (operand.kind) {
|
|
1166
|
+
case "cell": {
|
|
1167
|
+
if (!operand.address) {
|
|
1168
|
+
return operand;
|
|
1169
|
+
}
|
|
1170
|
+
const translated = translatedCellMap.get(translatedCellInstructionKey(operand.sheetName, operand.address));
|
|
1171
|
+
return translated
|
|
1172
|
+
? {
|
|
1173
|
+
...operand,
|
|
1174
|
+
address: formatParsedLocalCellReference(translated),
|
|
1175
|
+
}
|
|
1176
|
+
: translateReferenceOperand(operand, rowDelta, colDelta);
|
|
1177
|
+
}
|
|
1178
|
+
case "range": {
|
|
1179
|
+
if (!operand.start || !operand.end || !operand.refKind) {
|
|
1180
|
+
return operand;
|
|
1181
|
+
}
|
|
1182
|
+
const translated = translatedRangeMap.get(translatedRangeInstructionKey(operand.sheetName, operand.refKind, operand.start, operand.end));
|
|
1183
|
+
return translated
|
|
1184
|
+
? {
|
|
1185
|
+
...operand,
|
|
1186
|
+
start: translated.startAddress,
|
|
1187
|
+
end: translated.endAddress,
|
|
1188
|
+
refKind: translated.refKind,
|
|
1189
|
+
}
|
|
1190
|
+
: translateReferenceOperand(operand, rowDelta, colDelta);
|
|
1191
|
+
}
|
|
1192
|
+
case "row":
|
|
1193
|
+
case "col":
|
|
1194
|
+
return translateReferenceOperand(operand, rowDelta, colDelta);
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
function rewriteReferenceOperandAddress(explicitSheetName, address, ownerSheetName, targetSheetName, transform) {
|
|
1198
|
+
if ((explicitSheetName ?? ownerSheetName) !== targetSheetName) {
|
|
1199
|
+
return address;
|
|
1200
|
+
}
|
|
1201
|
+
return rewriteAddressForStructuralTransform(address, transform) ?? address;
|
|
1202
|
+
}
|
|
1203
|
+
function rewritePlanRangeInstruction(explicitSheetName, start, end, refKind, ownerSheetName, targetSheetName, transform) {
|
|
1204
|
+
if ((explicitSheetName ?? ownerSheetName) !== targetSheetName) {
|
|
1205
|
+
return undefined;
|
|
1206
|
+
}
|
|
1207
|
+
if (refKind === "cells") {
|
|
1208
|
+
const nextRange = rewriteRangeForStructuralTransform(start, end, transform);
|
|
1209
|
+
return nextRange
|
|
1210
|
+
? {
|
|
1211
|
+
start: nextRange.startAddress,
|
|
1212
|
+
end: nextRange.endAddress,
|
|
1213
|
+
}
|
|
1214
|
+
: undefined;
|
|
1215
|
+
}
|
|
1216
|
+
if ((refKind === "rows" && transform.axis !== "row") ||
|
|
1217
|
+
(refKind === "cols" && transform.axis !== "column")) {
|
|
1218
|
+
return undefined;
|
|
1219
|
+
}
|
|
1220
|
+
const parsed = parseRangeAddress(formatQualifiedRangeReference(explicitSheetName, start, end));
|
|
1221
|
+
const nextRange = rewriteRangeAddressForStructuralTransform(parsed, transform);
|
|
1222
|
+
return nextRange
|
|
1223
|
+
? {
|
|
1224
|
+
start: nextRange.start.text,
|
|
1225
|
+
end: nextRange.end.text,
|
|
1226
|
+
}
|
|
1227
|
+
: undefined;
|
|
1228
|
+
}
|
|
1229
|
+
function translatePlanRangeInstruction(explicitSheetName, start, end, rowDelta, colDelta) {
|
|
1230
|
+
const parsed = parseRangeAddress(formatQualifiedRangeReference(explicitSheetName, start, end));
|
|
1231
|
+
const nextRange = translateRangeAddress(parsed, rowDelta, colDelta);
|
|
1232
|
+
return {
|
|
1233
|
+
start: nextRange.start.text,
|
|
1234
|
+
end: nextRange.end.text,
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
function formatQualifiedCellReference(sheetName, address) {
|
|
1238
|
+
if (!sheetName) {
|
|
1239
|
+
return address;
|
|
1240
|
+
}
|
|
1241
|
+
const parsed = parseCellAddress(address, sheetName);
|
|
1242
|
+
return `${quoteSheetNameIfNeeded(sheetName)}!${parsed.text}`;
|
|
1243
|
+
}
|
|
1244
|
+
function formatQualifiedRangeReference(sheetName, start, end) {
|
|
1245
|
+
const prefix = sheetName ? `${quoteSheetNameIfNeeded(sheetName)}!` : "";
|
|
1246
|
+
return `${prefix}${start}:${end}`;
|
|
1247
|
+
}
|
|
313
1248
|
function translateCellReference(ref, rowDelta, colDelta) {
|
|
314
1249
|
const parsed = parseCellReferenceParts(ref);
|
|
315
1250
|
if (!parsed) {
|