export function dependencyTouchesSheet(dependency, sheetName) {
    if (!dependency.includes('!')) {
        return false;
    }
    const [qualifiedSheetName] = dependency.split('!');
    return qualifiedSheetName?.replace(/^'(.*)'$/, '$1') === sheetName;
}
export function rangeDependencyAxisAffected(rangeDescriptor, targetSheetId, transform) {
    if (rangeDescriptor.sheetId !== targetSheetId) {
        return false;
    }
    const start = transform.axis === 'row' ? rangeDescriptor.row1 : rangeDescriptor.col1;
    const end = transform.axis === 'row' ? rangeDescriptor.row2 : rangeDescriptor.col2;
    return !(end < transform.start || start >= transform.start + transform.count);
}
export function runtimeDirectRangeAxisAffected(targetSheetId, targetSheetName, transform, range) {
    if (!range || targetSheetId === undefined || range.sheetName !== targetSheetName) {
        return false;
    }
    return rangeDependencyAxisAffected({
        sheetId: targetSheetId,
        row1: range.rowStart,
        row2: range.rowEnd,
        col1: range.col,
        col2: range.col,
    }, targetSheetId, transform);
}
export function isStructurallyStableSimpleFormulaNode(node) {
    switch (node.kind) {
        case 'NumberLiteral':
        case 'BooleanLiteral':
        case 'StringLiteral':
        case 'ErrorLiteral':
        case 'CellRef':
            return true;
        case 'ArrayConstant':
            return node.rows.every((row) => row.every(isStructurallyStableSimpleFormulaNode));
        case 'UnaryExpr':
            return isStructurallyStableSimpleFormulaNode(node.argument);
        case 'BinaryExpr':
            return isStructurallyStableSimpleFormulaNode(node.left) && isStructurallyStableSimpleFormulaNode(node.right);
        case 'NameRef':
        case 'OmittedArgument':
        case 'StructuredRef':
        case 'SpillRef':
        case 'RowRef':
        case 'ColumnRef':
        case 'RangeRef':
        case 'CallExpr':
        case 'InvokeExpr':
            return false;
    }
}
function arrayValuesEqual(left, right) {
    if (left.length !== right.length) {
        return false;
    }
    for (let index = 0; index < left.length; index += 1) {
        if (left[index] !== right[index]) {
            return false;
        }
    }
    return true;
}
function hasStableStructuralSymbolicRangeLayout(current, next, rangeDependencyCount) {
    if (current.symbolicRanges.length !== next.symbolicRanges.length) {
        return false;
    }
    if (rangeDependencyCount !== current.symbolicRanges.length) {
        return false;
    }
    if (current.parsedSymbolicRanges === undefined || next.parsedSymbolicRanges === undefined) {
        return current.parsedSymbolicRanges === next.parsedSymbolicRanges;
    }
    if (current.parsedSymbolicRanges.length !== next.parsedSymbolicRanges.length) {
        return false;
    }
    for (let index = 0; index < current.parsedSymbolicRanges.length; index += 1) {
        if (current.parsedSymbolicRanges[index]?.refKind !== next.parsedSymbolicRanges[index]?.refKind) {
            return false;
        }
    }
    return true;
}
export function structuralRewritePreservesValue(formula, rewritten, transform) {
    return (transform.kind !== 'delete' &&
        rewritten.reusedProgram &&
        !rewritten.compiled.volatile &&
        formula.compiled.symbolicNames.length === 0 &&
        formula.compiled.symbolicTables.length === 0 &&
        formula.compiled.symbolicSpills.length === 0 &&
        formula.compiled.symbolicRanges.length === 0 &&
        formula.compiled.deps.every((dependency) => !dependency.includes(':')) &&
        formula.directLookup === undefined &&
        formula.directAggregate === undefined &&
        formula.directCriteria === undefined &&
        (formula.directScalar === undefined || transform.kind === 'insert') &&
        isStructurallyStableSimpleFormulaNode(rewritten.compiled.optimizedAst));
}
export function structuralRewritePreservesBinding(formula, rewritten, allowsRangeReuse) {
    return (rewritten.reusedProgram &&
        (formula.directAggregate !== undefined ||
            formula.directScalar !== undefined ||
            (allowsRangeReuse &&
                hasStableStructuralSymbolicRangeLayout(formula.compiled, rewritten.compiled, formula.rangeDependencies.length))) &&
        formula.compiled.symbolicNames.length === 0 &&
        formula.compiled.symbolicTables.length === 0 &&
        formula.compiled.symbolicSpills.length === 0 &&
        rewritten.compiled.symbolicNames.length === 0 &&
        rewritten.compiled.symbolicTables.length === 0 &&
        rewritten.compiled.symbolicSpills.length === 0 &&
        formula.directLookup === undefined &&
        formula.directCriteria === undefined &&
        arrayValuesEqual(formula.compiled.program, rewritten.compiled.program) &&
        arrayValuesEqual(formula.compiled.constants, rewritten.compiled.constants) &&
        formula.compiled.mode === rewritten.compiled.mode &&
        (formula.directAggregate !== undefined || rewritten.compiled.symbolicRanges.length === formula.rangeDependencies.length));
}
export function structuralDirectAggregateRewritePreservesValue(formula, rewritten, transform) {
    return ((transform.kind === 'insert' || transform.kind === 'move') &&
        formula.directAggregate !== undefined &&
        rewritten.reusedProgram &&
        !rewritten.compiled.volatile &&
        formula.compiled.symbolicNames.length === 0 &&
        formula.compiled.symbolicTables.length === 0 &&
        formula.compiled.symbolicSpills.length === 0 &&
        formula.directLookup === undefined &&
        formula.directCriteria === undefined &&
        !directAggregateMovePartiallyExtractsReferencedAxis(formula.directAggregate, transform));
}
function directAggregateMovePartiallyExtractsReferencedAxis(range, transform) {
    if (!range || transform.kind !== 'move') {
        return false;
    }
    const start = transform.axis === 'row' ? range.rowStart : range.col;
    const end = transform.axis === 'row' ? range.rowEnd : (range.colEnd ?? range.col);
    const movedStart = transform.start;
    const movedEnd = transform.start + transform.count - 1;
    const overlapsMovedAxis = start <= movedEnd && end >= movedStart;
    if (!overlapsMovedAxis) {
        return false;
    }
    return !(start >= movedStart && end <= movedEnd);
}
//# sourceMappingURL=structure-formula-rewrite-guards.js.map