Files
akbasic/tests/language/numeric/truth_value_arithmetic.bas

17 lines
819 B
QBasic
Raw Permalink Normal View History

Refuse an operand the numeric path cannot read math_minus, math_multiply and math_divide were `if ( INTEGER ) ... else <treat as float>`, and that else was a catch-all rather than a float branch: it read floatval from whatever it was handed. A truth value keeps its payload in boolvalue and leaves floatval zero, so a truth value on the left computed into a field nothing reads and kept its BOOLEAN type -- (A# == 1) - 1 printed true, should be -2 (A# == 1) * 3 printed true, should be -3 (A# == 1) + 1 correctly refused wrong in value and in type, and silent. math_plus escaped only because it enumerates its cases and ends in an error. The three now share one require_numeric() guard, so a type added later is refused by all of them at once instead of quietly taking the float branch in each. The two operands have different rules and that asymmetry is the point: the left one picks the branch and must be a number, while the right is read through rval_as_int(), which handles -1/0 deliberately. `5 - (A# == 1)` is 6, and that is the same property that lets AND and OR double as logical operators, so refusing a truth value on the right would have broken every condition in the language. Found by asking what a structure operand would do to this path, which is where AKBASIC_TYPE_STRUCT is about to arrive. The structures work did not create the defect; it made an already-reachable one worth chasing. Two stale comments went with it. src/value.c's header and a duplicate block above rval_as_int both cited "TODO.md section 12", which does not exist -- the defect list is section 6 -- and the duplicate described the summing behaviour item 5 had already removed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 11:22:50 -04:00
10 REM A truth value carries its payload in boolvalue, not floatval. The three
20 REM numeric operators were `if ( INTEGER ) ... else <treat as float>`, and
30 REM that else was a catch-all rather than a float branch -- so a truth value
40 REM on the LEFT computed 0 - 1 into a field nothing reads, kept its BOOLEAN
50 REM type, and printed `true` instead of -2. Silent, and wrong twice over.
60 A# = 1
70 PRINT (A# == 1)
80 REM On the RIGHT it stays legal and stays -1, which is the same property that
90 REM lets AND and OR double as logical operators. Refusing it here would have
100 REM broken every condition in the language.
110 PRINT 5 - (A# == 1)
120 PRINT 5 * (A# == 1)
130 PRINT 5 + (A# == 1)
140 PRINT 4 - (A# == 2)
150 REM And on the left it is refused by name rather than computed.
160 PRINT (A# == 1) - 1