Cover the operator path into the divide-by-zero error
resolve has two callers and only equals was tested. An operator commits the pending division just as equals does, so `1 / 0 +` errors on the plus — and pressing divide itself must not error, since it only sets the pending op. Also pins the implied-operand cases, 0/0 and a negative zero divisor, which IEEE equality catches but nothing stated. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
208eb39 parent: d1e3be7 modified
tests/tcalculator.nim +18 -0 | @@ -45,6 +45,24 @@ suite "calculator": | ||
| 45 | 45 | check c.reason == "" # cleared along with the error |
| 46 | 46 | check c.press(7) == "7" # usable again |
| 47 | 47 | |
| 48 | + test "an operator commits the pending divide, so it errors there too": | |
| 49 | + # The error surfaces on the key that commits the division, which is the | |
| 50 | + # next operator just as much as it is equals. | |
| 51 | + var c = fresh() | |
| 52 | + check c.press(1, IdDiv, 0, IdAdd) == "Error" | |
| 53 | + check c.reason == "Cannot divide by zero" | |
| 54 | + | |
| 55 | + test "pressing divide is not itself an error": | |
| 56 | + var c = fresh() | |
| 57 | + check c.press(1, IdDiv) == "1" | |
| 58 | + check not c.failed | |
| 59 | + | |
| 60 | + test "dividing by an implied zero operand is caught": | |
| 61 | + var c = fresh() | |
| 62 | + check c.press(0, IdDiv, IdEquals) == "Error" # 0 / 0 | |
| 63 | + c = fresh() | |
| 64 | + check c.press(0, IdSign, 1, IdDiv, 0, IdSign, IdEquals) == "Error" # -0 | |
| 65 | + | |
| 48 | 66 | test "a result too large to represent says so, rather than showing inf": |
| 49 | 67 | var c = fresh() |
| 50 | 68 | # Each pass multiplies by ~1e18; float64 gives up a little past 1e308. |
| @@ -45,6 +45,24 @@ suite "calculator": | |||
| 45 | check c.reason == "" # cleared along with the error | 45 | check c.reason == "" # cleared along with the error |
| 46 | check c.press(7) == "7" # usable again | 46 | check c.press(7) == "7" # usable again |
| 47 | 47 | ||
| 48 | + test "an operator commits the pending divide, so it errors there too": | ||
| 49 | + # The error surfaces on the key that commits the division, which is the | ||
| 50 | + # next operator just as much as it is equals. | ||
| 51 | + var c = fresh() | ||
| 52 | + check c.press(1, IdDiv, 0, IdAdd) == "Error" | ||
| 53 | + check c.reason == "Cannot divide by zero" | ||
| 54 | + | ||
| 55 | + test "pressing divide is not itself an error": | ||
| 56 | + var c = fresh() | ||
| 57 | + check c.press(1, IdDiv) == "1" | ||
| 58 | + check not c.failed | ||
| 59 | + | ||
| 60 | + test "dividing by an implied zero operand is caught": | ||
| 61 | + var c = fresh() | ||
| 62 | + check c.press(0, IdDiv, IdEquals) == "Error" # 0 / 0 | ||
| 63 | + c = fresh() | ||
| 64 | + check c.press(0, IdSign, 1, IdDiv, 0, IdSign, IdEquals) == "Error" # -0 | ||
| 65 | + | ||
| 48 | test "a result too large to represent says so, rather than showing inf": | 66 | test "a result too large to represent says so, rather than showing inf": |
| 49 | var c = fresh() | 67 | var c = fresh() |
| 50 | # Each pass multiplies by ~1e18; float64 gives up a little past 1e308. | 68 | # Each pass multiplies by ~1e18; float64 gives up a little past 1e308. |