{
  "version": 3,
  "sources": ["../../../src/evaluator/evaluate-scalar-operator.ts"],
  "sourcesContent": [
    "import type { FormulaEvaluator } from \"./formula-evaluator.cjs\";\nimport {\n  FormulaError,\n  type ArethmeticEvaluator,\n  type CellAddress,\n  type CellValue,\n  type CellInRangeResult,\n  type FunctionEvaluationResult,\n  type SingleEvaluationResult,\n} from \"../core/types.cjs\";\nimport type { EvaluationContext } from \"./evaluation-context.cjs\";\n\nexport type EvaluateScalarOperatorOptions = {\n  evaluateScalar: ArethmeticEvaluator;\n  context: EvaluationContext;\n  /**\n   * for debugging messages\n   */\n  name: string;\n};\n\nfunction evaluateSingleScalarOperator(\n  leftValue: CellValue,\n  rightValue: CellValue,\n  evaluateScalar: ArethmeticEvaluator,\n  context: EvaluationContext\n): SingleEvaluationResult {\n  const result = evaluateScalar(leftValue, rightValue, context);\n  if (result.type === \"error\" || result.type === \"awaiting-evaluation\") {\n    return result;\n  }\n  return { type: \"value\", result };\n}\n\nexport function evaluateScalarOperator(\n  this: FormulaEvaluator,\n  left: FunctionEvaluationResult,\n  right: FunctionEvaluationResult,\n  options: EvaluateScalarOperatorOptions\n): FunctionEvaluationResult {\n  const { evaluateScalar, context, name } = options;\n  if (left.type === \"error\" || left.type === \"awaiting-evaluation\") {\n    return left;\n  }\n  if (right.type === \"error\" || right.type === \"awaiting-evaluation\") {\n    return right;\n  }\n\n  if (left.type === \"value\" && right.type === \"value\") {\n    const leftValue = left.result;\n    const rightValue = right.result;\n    const result = evaluateScalar(leftValue, rightValue, options.context);\n    if (result.type === \"error\" || result.type === \"awaiting-evaluation\") {\n      return result;\n    }\n    if (result) {\n      return { type: \"value\", result };\n    }\n  }\n  if (left.type === \"spilled-values\" && right.type === \"value\") {\n    return {\n      type: \"spilled-values\",\n      spillArea: (origin: CellAddress) => left.spillArea(origin),\n      source: `evaulate left spilled range onto right value in scalar operator ${name}`,\n      evaluate: (spilled, context) => {\n        const evaledLeft = left.evaluate(spilled, context);\n        if (\n          evaledLeft.type === \"error\" ||\n          evaledLeft.type === \"awaiting-evaluation\"\n        ) {\n          return evaledLeft;\n        }\n        return evaluateSingleScalarOperator(\n          evaledLeft.result,\n          right.result,\n          evaluateScalar,\n          options.context\n        );\n      },\n      evaluateAllCells: function (options) {\n        const leftResults = left.evaluateAllCells.call(this, options);\n        if (\n          leftResults.type === \"error\" ||\n          leftResults.type === \"awaiting-evaluation\"\n        ) {\n          return leftResults;\n        }\n        const results = leftResults.values.map((cellValue) => {\n          if (\n            cellValue.result.type === \"error\" ||\n            cellValue.result.type === \"awaiting-evaluation\"\n          ) {\n            return cellValue;\n          } else {\n            return {\n              result: evaluateSingleScalarOperator(\n                cellValue.result.result,\n                right.result,\n                evaluateScalar,\n                options.context\n              ),\n              relativePos: cellValue.relativePos,\n            };\n          }\n        });\n        return {\n          type: \"values\",\n          values: results,\n        };\n      },\n    };\n  }\n  if (right.type === \"spilled-values\" && left.type === \"value\") {\n    return {\n      type: \"spilled-values\",\n      spillArea: (origin: CellAddress) => right.spillArea(origin),\n      source: `evaluate right spilled range onto left value in scalar operator ${name}`,\n      evaluate: (spilled, context) => {\n        const evaledRight = right.evaluate(spilled, context);\n        if (\n          evaledRight.type === \"error\" ||\n          evaledRight.type === \"awaiting-evaluation\"\n        ) {\n          return evaledRight;\n        }\n        return evaluateSingleScalarOperator(\n          left.result,\n          evaledRight.result,\n          evaluateScalar,\n          options.context\n        );\n      },\n      evaluateAllCells: function (options) {\n        const rightResults = right.evaluateAllCells.call(this, options);\n        if (\n          rightResults.type === \"error\" ||\n          rightResults.type === \"awaiting-evaluation\"\n        ) {\n          return rightResults;\n        }\n        const results = rightResults.values.map((cellValue) => {\n          if (\n            cellValue.result.type === \"error\" ||\n            cellValue.result.type === \"awaiting-evaluation\"\n          ) {\n            return cellValue;\n          } else {\n            const result = evaluateSingleScalarOperator(\n              left.result,\n              cellValue.result.result,\n              evaluateScalar,\n              options.context\n            );\n            return {\n              result: result,\n              relativePos: cellValue.relativePos,\n            };\n          }\n        });\n        return {\n          type: \"values\",\n          values: results,\n        };\n      },\n    };\n  }\n\n  if (left.type === \"spilled-values\" && right.type === \"spilled-values\") {\n    return {\n      type: \"spilled-values\",\n      spillArea: (origin) =>\n        this.unionRanges(left.spillArea(origin), right.spillArea(origin)),\n      source: `evaluate spilled ranges in scalar operator ${name}`,\n      evaluate: (spilled, context) => {\n        const evaledLeft = left.evaluate(spilled, context);\n        if (\n          evaledLeft.type === \"error\" ||\n          evaledLeft.type === \"awaiting-evaluation\"\n        ) {\n          return evaledLeft;\n        }\n        const evaledRight = right.evaluate(spilled, context);\n        if (\n          evaledRight.type === \"error\" ||\n          evaledRight.type === \"awaiting-evaluation\"\n        ) {\n          return evaledRight;\n        }\n\n        // Check if either value is an empty cell (empty string)\n        const isLeftEmpty =\n          evaledLeft.type === \"value\" &&\n          evaledLeft.result.type === \"string\" &&\n          evaledLeft.result.value === \"\";\n        const isRightEmpty =\n          evaledRight.type === \"value\" &&\n          evaledRight.result.type === \"string\" &&\n          evaledRight.result.value === \"\";\n\n        // If either operand is empty, return #N/A\n        if (isLeftEmpty || isRightEmpty) {\n          return {\n            type: \"error\",\n            err: FormulaError.NA,\n            message: \"Empty cell in scalar operation\",\n            errAddress: options.context.dependencyNode,\n          };\n        }\n\n        return evaluateSingleScalarOperator(\n          evaledLeft.result,\n          evaledRight.result,\n          evaluateScalar,\n          options.context\n        );\n      },\n      evaluateAllCells: function (options) {\n        const leftResults = left.evaluateAllCells.call(this, options);\n        if (\n          leftResults.type === \"error\" ||\n          leftResults.type === \"awaiting-evaluation\"\n        ) {\n          return leftResults;\n        }\n        const rightResults = right.evaluateAllCells.call(this, options);\n        if (\n          rightResults.type === \"error\" ||\n          rightResults.type === \"awaiting-evaluation\"\n        ) {\n          return rightResults;\n        }\n\n        // Create position-based maps for both left and right results\n        const leftMap = new Map<string, CellInRangeResult>();\n        const rightMap = new Map<string, CellInRangeResult>();\n        const allPositions = new Set<string>();\n\n        for (const result of leftResults.values) {\n          const key = `${result.relativePos.x},${result.relativePos.y}`;\n          leftMap.set(key, result);\n          allPositions.add(key);\n        }\n\n        for (const result of rightResults.values) {\n          const key = `${result.relativePos.x},${result.relativePos.y}`;\n          rightMap.set(key, result);\n          allPositions.add(key);\n        }\n\n        const results: CellInRangeResult[] = [];\n\n        // Process each unique position\n        for (const posKey of allPositions) {\n          const leftResult = leftMap.get(posKey);\n          const rightResult = rightMap.get(posKey);\n\n          // Extract relative position from the key\n          const [x, y] = posKey.split(\",\").map(Number);\n          const relativePos = { x: x!, y: y! };\n\n          if (!leftResult && !rightResult) {\n            // Both empty - this shouldn't happen as we only iterate positions that exist\n            continue;\n          } else if (!leftResult && rightResult) {\n            // Left is empty/missing, right has value\n            if (\n              rightResult.result.type === \"error\" ||\n              rightResult.result.type === \"awaiting-evaluation\"\n            ) {\n              results.push(rightResult);\n            } else if (rightResult.result.type === \"value\") {\n              // Treat missing left as empty, which is handled by the operator\n              results.push({\n                result: {\n                  type: \"error\",\n                  err: FormulaError.NA,\n                  message: \"Left operand is empty\",\n                  errAddress: context.dependencyNode,\n                },\n                relativePos,\n              });\n            } else {\n              results.push(rightResult);\n            }\n          } else if (!rightResult && leftResult) {\n            // Right is empty/missing, left has value\n            if (\n              leftResult.result.type === \"error\" ||\n              leftResult.result.type === \"awaiting-evaluation\"\n            ) {\n              results.push(leftResult);\n            } else if (leftResult.result.type === \"value\") {\n              // Treat missing right as empty, which is handled by the operator\n              results.push({\n                result: {\n                  type: \"error\",\n                  err: FormulaError.NA,\n                  message: \"Right operand is empty\",\n                  errAddress: context.dependencyNode,\n                },\n                relativePos,\n              });\n            } else {\n              results.push(leftResult);\n            }\n          } else if (leftResult && rightResult) {\n            // Both have values\n            if (\n              leftResult.result.type === \"error\" ||\n              leftResult.result.type === \"awaiting-evaluation\"\n            ) {\n              results.push(leftResult);\n            } else if (\n              rightResult.result.type === \"error\" ||\n              rightResult.result.type === \"awaiting-evaluation\"\n            ) {\n              results.push(rightResult);\n            } else if (\n              leftResult.result.type === \"value\" &&\n              rightResult.result.type === \"value\"\n            ) {\n              results.push({\n                result: evaluateSingleScalarOperator(\n                  leftResult.result.result,\n                  rightResult.result.result,\n                  evaluateScalar,\n                  options.context\n                ),\n                relativePos: leftResult.relativePos,\n              });\n            } else {\n              // Both are awaiting-evaluation or some other state\n              results.push({\n                result: {\n                  type: \"error\",\n                  err: FormulaError.VALUE,\n                  message:\n                    \"Cannot evaluate scalar operator on non-value results\",\n                  errAddress: context.dependencyNode,\n                },\n                relativePos,\n              });\n            }\n          }\n        }\n\n        return { type: \"values\", values: results };\n      },\n    };\n  }\n\n  return {\n    type: \"error\",\n    err: FormulaError.VALUE,\n    message: `Can't evaluate (${left.type}, ${right.type}) in scalar operator ${name}`,\n    errAddress: options.context.dependencyNode,\n  };\n}\n"
  ],
  "mappings": "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",
  "debugId": "51984771264BB6A764756E2164756E21",
  "names": []
}