fix(v4.0.0): .R U.R and D.R print no trailing space
FORTH-79's reference .R right-justifies the number in its field and prints nothing after it; v3 printed a space. . U. and D. still print their one space. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
b137678691
commit
01b5bbb23f
@@ -465,8 +465,8 @@ All output reaches the console through `EMIT` (DEV).
|
||||
| --- | --- | --- |
|
||||
| `<#` `#` `#S` `HOLD` `SIGN` `#>` | CAP | Pictured output over `UM/MOD` and a 64-byte hold buffer, filled backwards from its end `HEND` through the pointer `HLD`. Standard stack effects (v3 took its double low cell on top, and its tolerant `#>` popped `ud` only if present; neither is kept). Otherwise v3's behaviour: digits `0`–`9` then `A`–`Z`; `BASE` outside 2–36 reads as 10; 63 characters; `HOLD` of a value outside 0–255 or into a full buffer stores nothing and sets `NODE-ERROR` (D-13). Definitions below. Executed on the golden model (2026-10-03) against a C reference in bases 2, 3, 8, 10, 16, 36 and four invalid ones. `<# #S #>` leaves its caller 4 data cells and 3 return entries; the signed picture `dup push ABS 0 <# #S pop SIGN #>` leaves 2 return entries. `#`, `#S`, `HOLD` and `SIGN` clobber `A` and `B`. |
|
||||
| `HLD` | CAP | Variable: byte address of the first held character. `HLD ( -- addr )` is the variable's word address, a literal. Not a v3 word. Executed on the golden model (2026-10-03): after `<#` and each `HOLD` or `#`, `HLD @` is the address `#>` returns. |
|
||||
| `.` `.R` `U.` `U.R` `D.` `D.R` | CAP | Built on pictured output and `TYPE`; definitions below. As v3: the number in the current base, then one space; the `.R` words right-justify it in `width` columns first, print a wider number whole, and pad nothing for `width <= 0`. (The space after the `.R` words is not FORTH-79; it is what v3 prints.) Where v4 parts from v3: a double is `( lo hi )`, where v3's `D.` took the low cell on top; `D.` prints the whole double, where v3 printed `DOUBLE-OVERFLOW` unless it fitted one signed cell (they agree whenever it does); printing honours the `BASE` variable, where v3 printed in a host copy that only `DECIMAL`, `HEX` and `OCTAL` set, so `n BASE !` changed v3's input base but not its output; and the number is built in the 63-character hold buffer, so a longer one — a 64-bit cell in base 2, a large double in a small base — loses its leading characters and sets `NODE-ERROR` (D-13), where v3 printed from a private 80-character buffer. Executed on the golden model (2026-10-03) against a C reference in the ten bases of the pictured-output test and eleven field widths, and against five transcripts of the v3 binary (a sixth, the extreme cells, at 64-bit cells). Each leaves its caller 4 data cells; `U.` and `U.R` leave 3 return entries, the signed words 2, their sign waiting on the return stack. All clobber `A` and `B`. |
|
||||
| `(W)` | CAP | Variable: the field width of the `.R` words. Like `BASE` and `HLD`, it lives in node memory, so the width is on neither stack while the picture runs. |
|
||||
| `.` `.R` `U.` `U.R` `D.` `D.R` | CAP | Built on pictured output and `TYPE`; definitions below. `.`, `U.` and `D.` print the number in the current base, then one space. The `.R` words right-justify it in `width` columns, print a wider number whole, pad nothing for `width <= 0`, and print no space after it: that is FORTH-79's reference word (ruled 2026-10-04); v3 printed a space after these too. Where v4 parts from v3: a double is `( lo hi )`, where v3's `D.` took the low cell on top; `D.` prints the whole double, where v3 printed `DOUBLE-OVERFLOW` unless it fitted one signed cell (they agree whenever it does); printing honours the `BASE` variable, where v3 printed in a host copy that only `DECIMAL`, `HEX` and `OCTAL` set, so `n BASE !` changed v3's input base but not its output; and the number is built in the 63-character hold buffer, so a longer one — a 64-bit cell in base 2, a large double in a small base — loses its leading characters and sets `NODE-ERROR` (D-13), where v3 printed from a private 80-character buffer. Executed on the golden model (2026-10-03) against a C reference in the ten bases of the pictured-output test and eleven field widths, and against five transcripts of the v3 binary (a sixth, the extreme cells, at 64-bit cells). Each leaves its caller 4 data cells; `U.` and `U.R` leave 3 return entries, the signed words 2, their sign waiting on the return stack. All clobber `A` and `B`. |
|
||||
| `(W)` | CAP | Variable, 2 cells: the field width of the `.R` words, and whether a blank follows the number. Like `BASE` and `HLD`, it lives in node memory, so the width is on neither stack while the picture runs. |
|
||||
| `.S` | RET | No visible stack pointer (D-2). |
|
||||
| `?` | CAP | `( addr -- )`: `a! @ jump .` — the cell at word address `addr` (D-1), printed as `.` prints it. Executed on the golden model (2026-10-03), including a transcript of the v3 binary. Leaves its caller 4 data cells and 2 return entries. Clobbers `A` and `B`. |
|
||||
| `DUMP` | CAP | `( baddr u -- )`: `u` bytes from byte address `baddr`, sixteen to a line, in v3's format: the address in hex, `": "`, each byte as two hex digits and a space (three spaces where the line runs out), `" \|"`, the bytes as characters with `.` for anything outside 32–126, `"\|"` and a new line. Always hex, whatever `BASE` is, and `BASE` is put back. The address is two hex digits per byte of a cell — 8 at 32-bit cells, 16 at 64, which is v3's width. Nothing for `u = 0`; for `u < 0` nothing is printed and `NODE-ERROR` is set, as `TYPE` does, where v3 raised its error flag. Addresses are not range-checked (open, `node.h`). Definition below. Executed on the golden model (2026-10-03) against a C reference at six alignments and every length 0–50, and at 64-bit cells against a transcript of the v3 binary, byte for byte. Leaves its caller 4 data cells and 4 return entries. Clobbers `A` and `B`. |
|
||||
@@ -501,15 +501,18 @@ return stack. `-ROT` is in line (`SWAP push SWAP pop`).
|
||||
```forth
|
||||
\ number output. ABS is in line: -if A inv 1 + A:
|
||||
: .R ( n width -- )
|
||||
(W) b! !b dup push ABS 0 <# #S pop SIGN #> \ baddr u
|
||||
TAIL: (W) b! @b -if POS drop jump OUT \ width < 0
|
||||
POS: over - SPACES \ width - u spaces
|
||||
OUT: TYPE jump SPACE
|
||||
: . ( n -- ) 0 jump .R
|
||||
: U.R ( u width -- ) (W) b! !b 0 <# #S #> jump TAIL
|
||||
: U. ( u -- ) 0 jump U.R
|
||||
: D.R ( d width -- ) (W) b! !b dup push -if A DNEGATE A: <# #S pop SIGN #> jump TAIL
|
||||
: D. ( d -- ) 0 jump D.R
|
||||
0 (W) 1 + b! !b \ no blank after it
|
||||
BODY: (W) b! !b dup push ABS 0 <# #S pop SIGN #> \ baddr u
|
||||
TAIL: (W) b! @b -if POS drop jump OUT \ width < 0
|
||||
POS: over - SPACES \ width - u spaces
|
||||
OUT: TYPE (W) 1 + b! @b if DONE drop jump SPACE
|
||||
DONE: drop ;
|
||||
: . ( n -- ) -1 (W) 1 + b! !b 0 jump BODY \ a blank after it
|
||||
: U.R ( u width -- ) 0 (W) 1 + b! !b UBODY: (W) b! !b 0 <# #S #> jump TAIL
|
||||
: U. ( u -- ) -1 (W) 1 + b! !b 0 jump UBODY
|
||||
: D.R ( d width -- ) 0 (W) 1 + b! !b
|
||||
DBODY: (W) b! !b dup push -if A DNEGATE A: <# #S pop SIGN #> jump TAIL
|
||||
: D. ( d -- ) -1 (W) 1 + b! !b 0 jump DBODY
|
||||
```
|
||||
|
||||
```forth
|
||||
@@ -549,8 +552,8 @@ in the variable `(DP)`, so the stacks carry only what each picture and `TYPE` ne
|
||||
sits on the return stack across a call.
|
||||
|
||||
There is one picture for signed singles, one for unsigned and one for doubles; each plain word is
|
||||
its `.R` word with a width of 0, entered by a jump, and all six share one tail, which ends in a jump
|
||||
to `SPACE`. The width is tested for sign before `width - u`, which could wrap for a very negative
|
||||
its `.R` word with a width of 0 and the blank flag set, entered by a jump past where `.R` clears
|
||||
that flag, and all six share one tail, which prints the blank only when the flag is set. The width is tested for sign before `width - u`, which could wrap for a very negative
|
||||
width and print a flood of spaces.
|
||||
|
||||
### 5.9 Strings, parsing, and input
|
||||
|
||||
Reference in New Issue
Block a user