feat(v4.0.0): # keeps its high quotient on the data stack
`#` held the high quotient on the return stack across its second UM/MOD, which was the deepest point of pictured output once C! was made call-free. It now rotates it under the division on the data stack (-ROT in line: SWAP push SWAP pop). Headroom, return entries: <# #S #> 2 -> 3, the signed picture 1 -> 2. Data room is unchanged. Same 4716 checks per width at 32- and 64-bit cells, optimised and ASan+UBSan (`make test`, `make sanitize`); the headroom checks now require the new figures. Test results on the amd64 host only. This is a development check, not acceptance (JUSTIFICATION.md section 16). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
638aeb6636
commit
7a21f07ad5
@@ -452,7 +452,7 @@ All output reaches the console through `EMIT` (DEV).
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `<#` `#` `#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 3 data cells and 2 return entries; the signed picture `dup push ABS 0 <# #S pop SIGN #>` leaves 1 return entry. The deepest point is inside `#`, which holds the high quotient on the return stack across its second `UM/MOD`. `#`, `#S`, `HOLD` and `SIGN` clobber `A` and `B`. |
|
||||
| `<#` `#` `#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. |
|
||||
| `.` `.R` `U.` `U.R` `D.` `D.R` | CAP | Built on pictured output and `TYPE`. |
|
||||
| `.S` | RET | No visible stack pointer (D-2). |
|
||||
@@ -472,7 +472,8 @@ All output reaches the console through `EMIT` (DEV).
|
||||
ROOM: drop HLD b! @b -1 + dup !b jump C!
|
||||
: SIGN ( n -- ) -if L1 drop 45 jump HOLD L1: drop ;
|
||||
: # ( ud1 -- ud2 )
|
||||
0 (BASE) UM/MOD push (BASE) UM/MOD pop ROT \ qlo qhi rem
|
||||
0 (BASE) UM/MOD -ROT \ qhi lo rem1
|
||||
(BASE) UM/MOD -ROT \ qlo qhi rem
|
||||
dup -10 + -if L1 drop 48 + jump L2 L1: drop 55 + L2: jump HOLD
|
||||
: #S ( ud -- 0 0 ) L: # over over OR if L1 drop jump L L1: drop ;
|
||||
: #> ( ud -- baddr u ) drop drop HLD b! @b HEND over push inv pop + inv ;
|
||||
@@ -481,7 +482,8 @@ All output reaches the console through `EMIT` (DEV).
|
||||
`#` divides the double by the base in two `UM/MOD` steps, the high cell first and its remainder
|
||||
leading the low cell; the last remainder is the digit. `HOLD`, `SIGN` and `#` end with a jump to the
|
||||
next word rather than a call, so `C!` returns straight to their caller and two return-stack entries
|
||||
are saved. `ROT` is in line.
|
||||
are saved. `#` keeps the high quotient under the second division on the data stack, not on the
|
||||
return stack. `-ROT` is in line (`SWAP push SWAP pop`).
|
||||
|
||||
### 5.9 Strings, parsing, and input
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ static v4_cell w_swap, w_or, w_ummod, w_lshift, w_rshift, w_cstore,
|
||||
#define VGET(a) do { LIT(a); O(BANG_B); O(FETCH_B); } while (0)
|
||||
#define VSET(a) do { LIT(a); O(BANG_B); O(STORE_B); } while (0)
|
||||
#define SWAP_INLINE() do { O(OVER); O(PUSH); O(PUSH); O(DROP); O(RPOP); O(RPOP); } while (0)
|
||||
#define ROT_INLINE() do { O(PUSH); SWAP_INLINE(); O(RPOP); SWAP_INLINE(); } while (0)
|
||||
#define NROT_INLINE() do { SWAP_INLINE(); O(PUSH); SWAP_INLINE(); O(RPOP); } while (0)
|
||||
#define SUB_INLINE() do { O(PUSH); O(INV); O(RPOP); O(ADD); O(INV); } while (0)
|
||||
|
||||
/* The words pictured output rests on, as in test_foundation.c. */
|
||||
@@ -238,11 +238,14 @@ static void build_pictured(void)
|
||||
/* : # ( ud1 -- ud2 )
|
||||
* ud1 / base in two UM/MOD steps, the high cell first and its remainder
|
||||
* leading the low cell; the last remainder is the digit.
|
||||
* 0 (BASE) UM/MOD push (BASE) UM/MOD pop ROT qlo qhi rem
|
||||
* 0 (BASE) UM/MOD -ROT qhi lo rem1
|
||||
* (BASE) UM/MOD -ROT qlo qhi rem
|
||||
* The high quotient waits under the second division on the data stack,
|
||||
* not on the return stack. -ROT in line is SWAP push SWAP pop.
|
||||
* dup -10 + -if L1 drop 48 + jump L2 L1: drop 55 + L2: jump HOLD */
|
||||
w_hash = v4_asm_label(&as);
|
||||
LIT(0); CALL(w_base); CALL(w_ummod); O(PUSH);
|
||||
CALL(w_base); CALL(w_ummod); O(RPOP); ROT_INLINE();
|
||||
LIT(0); CALL(w_base); CALL(w_ummod); NROT_INLINE();
|
||||
CALL(w_base); CALL(w_ummod); NROT_INLINE();
|
||||
O(DUP); LIT(-10); O(ADD); a = FWD(MINUS_IF);
|
||||
O(DROP); LIT(48); O(ADD); b = FWD(JUMP);
|
||||
HERE_(a);
|
||||
@@ -510,9 +513,9 @@ int main(void)
|
||||
int dh, rh;
|
||||
v4_node_store(&n, BASE, 10);
|
||||
headroom("<# #S #>", t_ud, 2, 12345, 0, "12345", &dh, &rh);
|
||||
CHECK(dh >= 2 && rh >= 2, "<# #S #> leaves room");
|
||||
CHECK(dh >= 2 && rh >= 3, "<# #S #> leaves room");
|
||||
headroom("signed picture", t_signed, 1, -12345, 0, "-12345", &dh, &rh);
|
||||
CHECK(dh >= 2 && rh >= 1, "the signed picture leaves room");
|
||||
CHECK(dh >= 2 && rh >= 2, "the signed picture leaves room");
|
||||
}
|
||||
|
||||
CHECK(v4_node_guards_intact(&n), "guards intact");
|
||||
|
||||
Reference in New Issue
Block a user