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:
@@ -42,6 +42,18 @@ There is no escape character.
|
||||
Integers are 64-bit and floats are IEEE doubles, so `PRINT 1.5` gives `1.500000`. A
|
||||
leading zero is not octal; `0x` is hexadecimal.
|
||||
|
||||
### Mixed arithmetic follows the left operand, not the wider type
|
||||
|
||||
**A C128 promotes to float. This does not.** An integer on the left converts the right
|
||||
operand to an integer and throws its fraction away, so `A# * 0.45` is `0` where
|
||||
`0.45 * A#` is `1.35`. It is consistent, it is inherited from the Go interpreter this was
|
||||
ported from, and **nothing fails when you get it wrong** — the program computes something
|
||||
else and carries on.
|
||||
|
||||
[Chapter 3](03-the-language.md#the-left-operand-decides-whether-the-arithmetic-is-integer-or-float)
|
||||
has the two rules that keep you out of it. This is the difference from 7.0 most likely to
|
||||
turn a working listing into a quietly wrong one.
|
||||
|
||||
### Structures are an addition
|
||||
|
||||
BASIC 7.0 has no records at all. `TYPE`/`END TYPE`, `DIM X@ AS T`, the `@` suffix, `.` and
|
||||
@@ -133,6 +145,16 @@ interpreter's error code, which bears no relation to a Commodore error number. P
|
||||
- **Drawing does not persist across frames.** The verbs draw straight to the renderer,
|
||||
so anything drawn is overwritten on the next frame unless the program redraws it.
|
||||
This is a defect, not a design.
|
||||
- **And a redraw has to *fit*.** The host runs a fixed number of source lines and then
|
||||
presents the frame, and presenting discards the drawing buffer — so a sequence of
|
||||
drawing verbs longer than one batch comes back **half drawn**, with an `SSHAPE` at the
|
||||
end capturing only what was issued since the present. "Redraw it every frame" is
|
||||
therefore not sufficient advice on its own. Measured against the standalone frontend's
|
||||
256 lines a batch: after synchronising to a jiffy edge, 220 lines of drawing survive a
|
||||
capture and 250 do not. The only way a program can see the boundary is to watch `TI#`,
|
||||
which is refreshed once per batch — so the step on which it changes is the first step
|
||||
of one. [Chapter 18](18-tutorial-breakout-artwork.md#step-4-find-the-frame-boundary)
|
||||
builds a pacing routine out of exactly that.
|
||||
- **`CHAR` ignores its colour argument** and needs a text device with a cursor.
|
||||
|
||||
## Sound
|
||||
|
||||
Reference in New Issue
Block a user