Write down that the left operand decides integer or float arithmetic

No behaviour change, by decision. `A# * 0.45` is 0 and `0.45 * A#` is 1.35,
because every operator branches on `self->valuetype` and converts the right
operand to match. It is inherited from the Go reference, a C128 promotes to
float instead, and this interpreter is at least consistent about it -- so a
dialect saying the left operand wins is a defensible position, and changing it
to promotion would alter the result of every mixed expression in every existing
program.

**The defect was that nobody said so.** Chapter 3's "Numbers" did not mention
it, Chapter 13 did not list it among the differences, and nothing fails when a
program gets it wrong -- it computes something else and carries on. The game in
examples/ lost its per-level speed increase to `5.6 + LEVEL# * 0.45` evaluating
to a flat 5.6, and bled velocity out of every bounce through `0 - BLVX%(B#)`
quantising to whole pixels. Both read correctly. Neither produced a diagnostic.

Now said in three places: a section in Chapter 3 with the demonstration and the
two rules that keep a program out of it (put the float on the left, put the
answer somewhere with a `%` on it), a row in Chapter 13 naming it as the
difference from 7.0 most likely to turn a working listing into a quietly wrong
one, and the reasoning on value.h where the operators are declared.

tests/value_arithmetic.c pins it in both directions across multiply and
subtract, with a comment saying it is the documented contract rather than an
accident -- so promotion becomes a decision somebody takes deliberately rather
than a change that could slip in under a passing suite.

TODO.md section 9 item 4, struck as a documentation outcome.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-02 00:23:20 -04:00
parent d5f3c3ef5b
commit c8b917d205
5 changed files with 139 additions and 2 deletions

27
TODO.md
View File

@@ -2667,7 +2667,19 @@ reduced against `build/basic`, the stdio build, unless it says otherwise.
The tee half is three lines and is worth doing whatever is decided about the rest.
4. **Mixed-type arithmetic is decided by the left operand alone, and nothing says so.**
4. ~~**Mixed-type arithmetic is decided by the left operand alone, and nothing says so.**~~
**Done, as documentation, by decision.** The behaviour is unchanged: a dialect is
allowed to say the left operand wins and this one is consistent about it, and promotion
would change the result of every mixed expression in every existing program. What was
missing was anybody saying so. Now: a section in `docs/03-the-language.md` with the
two-line demonstration and the two rules that keep a program out of it, a row in
`docs/13-differences.md` naming it as the difference from 7.0 most likely to turn a
working listing into a quietly wrong one, and the reasoning on `include/akbasic/value.h`
where the operators are declared.
`tests/value_arithmetic.c` pins it in both directions, so **promotion is now a decision
somebody has to take deliberately** rather than a change that could slip in. The
original report:
```basic
A# = 3
@@ -2700,7 +2712,18 @@ reduced against `build/basic`, the stdio build, unless it says otherwise.
The cheap fix is documentation: a paragraph in chapter 3 and a row in chapter 13. The other
fix is promotion, which would be a real change of semantics and wants its own decision.
5. **A drawing that spans a 256-line batch boundary is torn, not merely transient.** §5 and
5. ~~**A drawing that spans a 256-line batch boundary is torn, not merely transient.**~~
**Done, as documentation.** No fix is possible without changing what a host owns -- the
budget is the host's and the present is the host's -- so what was needed was for the
consequence to be written down beside the advice it qualifies. `docs/13-differences.md`
now says that "redraw it every frame" is not sufficient on its own and carries the
measured numbers, `docs/06-graphics.md` says it where `SSHAPE` is introduced, and
`docs/14-architecture.md` explains the mechanism from the step loop's side and points at
the `TI#` synchronisation a program has to build.
**Untested, and deliberately:** it needs the real frontend, a clock and a timing
window, and a test that reproduced it would be reproducing a race. Said here rather than
left looking like an oversight. The original report: §5 and
chapter 13 record that drawing does not persist across frames. What neither says is that a
single uninterrupted sequence of drawing verbs longer than one `akbasic_runtime_run()` budget
comes back **half drawn**, because the present in the middle of it discards the buffer — so