fix(evaluator): Cross-sheet ref to formula cell evaluates correctly (#161)#162
fix(evaluator): Cross-sheet ref to formula cell evaluates correctly (#161)#162
Conversation
…161) When a formula references a cell in another sheet that contains a formula without a cached value, the evaluator now recursively parses and evaluates that formula instead of returning 0. Before: `=Sheet1!A3` where A3=`=A1+A2` → 0 After: `=Sheet1!A3` where A3=`=A1+A2` → correctly evaluates A1+A2 Changes: - Add `evalCrossSheetFormula` helper in Evaluator companion object - Modify SheetRef case to detect Formula cells with `cached = None` - Add 4 test cases to CrossSheetFormulaSpec Fixes #161 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code Review - PR #162SummaryThis PR fixes a critical bug (GH-161) where cross-sheet references to formula cells without cached values incorrectly returned 0 instead of recursively evaluating the formula. The fix adds a new helper method ✅ Strengths
|
…e protection - Fix type safety violation: Replace unsafe `asInstanceOf[Either[EvalError, A]]` with proper decoder application via `flatMap` + `Cell(at, evaluatedValue)` - Add recursion depth limit (max 100) to prevent stack overflow on circular cross-sheet references - Thread depth through evaluation chain via `EvaluatorWithDepth` class - Add negative test cases for circular reference detection and parse errors Addresses code review feedback on PR #162. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
PR Review: Cross-Sheet Formula Evaluation FixSummaryThis PR successfully fixes GH-161 by implementing recursive evaluation for cross-sheet references to formula cells without cached values. The implementation is solid, well-tested, and follows XL's purity/totality principles. ✅ Strengths1. Correct Problem IdentificationThe root cause analysis is spot-on: when formulas are created via CLI (without Excel opening them), there are no cached values. The fix properly detects 2. Robust Cycle Detection
3. Type SafetyThe decoder is correctly applied to the evaluated result (line 250-251): val resultCell = Cell(at, evaluatedValue)
decode(resultCell).left.map(...)This preserves type safety through the GADT system. 4. Excellent Test Coverage6 new tests covering:
The E2E CLI verification in the PR description is thorough. 5. Follows XL Philosophy
🔍 Observations & Minor Suggestions1. Type Conversion Match Completeness (Evaluator.scala:171-179)The type conversion logic handles most cases well, but consider: case other => CellValue.Text(other.toString)Question: Can Recommendation: Add comment clarifying exhaustiveness: case other =>
// Should be unreachable - GADT constrains eval results to above types
CellValue.Text(other.toString)2. Performance: Evaluator Instance Creation (line 169)Each recursive call creates Observation: Unlikely to be a bottleneck given:
Recommendation: No change needed now, but if profiling shows this as hot path, consider passing depth as parameter instead of creating new instances. 3. Error Message Clarity (line 154-155)Current: "Cross-sheet formula recursion depth exceeded (max: $MaxCrossSheetRecursionDepth). Possible circular reference."Suggestion: Include the formula chain for debugging: s"Cross-sheet formula recursion depth exceeded (max: $MaxCrossSheetRecursionDepth) evaluating '$formulaStr'. Possible circular reference."This helps users identify which formula triggered the cycle. 4. Test Case: Depth = 100 (Missing)Tests cover circular references but not the exact boundary condition. Recommendation: Add test for depth-100 chain to verify test("GH-161: depth limit triggers at 100 levels") {
// Create 101-level chain: Sheet1!A1 -> Sheet2!A1 -> Sheet3!A1 -> ...
// Verify error message contains "recursion depth exceeded"
}5. Documentation:
|
Summary
0instead of evaluatingevalCrossSheetFormulahelper to recursively parse and evaluate uncached formulasProblem
When a formula referenced a cell in another sheet that contained a formula without a cached value, the evaluator returned
0instead of recursively evaluating the formula chain.Root Cause
TExprDecoders.decodeResolvedValuereturnedCellValue.Number(0)when a Formula cell hadcached = None. The fix detects this case in theSheetRefevaluation and recursively evaluates the formula.Test plan
CrossSheetFormulaSpecpassFixes #161
🤖 Generated with Claude Code