feat(v4.0.0): POST is the kernel's -- the boot feeds the cases, and nothing of the harness is on the node
The boot runs POST with the runner (v4/system/post.c) after the capsules:
it feeds the 538 cases to the node and judges them from outside. A
case's printing no longer reaches the console. What the cases define
stays in the dictionary, as in v3; the system is sealed after POST and
the boot prints PARITY:V4_SYSTEM word_count=N dict_hash=..., as v3 prints
its parity after POST.
Gone: capsules/v4/post79.4th and its blocks 7000 up; the harness words;
(CATCH) and (EMIT-HOOK), with what EMIT and the prompt loop did for them.
The generator runs v3 on the lines as the kernel sends them, without the
capsule's "T| ". One expected result follows from that: >IN.initial
prints 6, not 9.
make -C v4 test, sanitize and hosted-check pass; amd64, aarch64 and
riscv64 boot, POST 538 of 538, word_count=411, dict_hash
0x6fb1d09418b189ee on all six: logs/20261007-105118, -105335, -105651.
T{ is unknown at the prompt; RS1 prints 42 42 before and after COLD. A
scratch build with one expectation changed names the case and ends
PARITY:FAIL, POST: FAILED.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
2bf958ce3a
commit
4bdb210a99
+2
-67
@@ -1,5 +1,5 @@
|
||||
# Capsule Block Manifest — Auto-generated
|
||||
<!-- Generated by mkcapsule --manifest 2026-10-07T13:34:17Z -->
|
||||
<!-- Generated by mkcapsule --manifest 2026-10-07T14:56:10Z -->
|
||||
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
|
||||
<!-- Hand-written justifications and immutability notes live -->
|
||||
<!-- in MANIFEST.md alongside this auto-generated index. -->
|
||||
@@ -31,7 +31,6 @@
|
||||
| `user-font-demo.4th` | 4200, 4201, 4202 | `0xce1fd7d1b581a56d` | n/a |
|
||||
| `v4:forth79.4th` | 6000, 6001, 6002 | `0x4055641ee17d176b` | n/a |
|
||||
| `v4:hera.4th` | 8000, 8001, 8002, 8003, 8004 | `0x526252bfef9b722b` | n/a |
|
||||
| `v4:post79.4th` | 7000, 7001, 7002, 7003, 7004, 7005, 7006, 7007, 7008, 7009, 7010, 7011, 7012, 7013, 7014, 7015, 7016, 7017, 7018, 7019, 7020, 7021, 7022, 7023, 7024, 7025, 7026, 7027, 7028, 7029, 7030, 7031, 7032, 7033, 7034, 7035, 7036, 7037, 7038, 7039, 7040, 7041, 7042, 7043, 7044, 7045, 7046, 7047, 7048, 7049, 7050, 7051, 7052, 7053, 7054, 7055, 7056, 7057, 7058, 7059, 7060, 7061, 7062, 7063 | `0xb26d1b974884179d` | n/a |
|
||||
| `workload-0.4th` | 2200, 2201 | `0x93f86f60aeba8feb` | n/a |
|
||||
| `workload-1-lite.4th` | 5058, 5059 | `0x44a7a7e3176dcc8d` | n/a |
|
||||
| `workload-1.4th` | 4406, 4415, 4425, 4435 | `0x63e251adb0a03613` | n/a |
|
||||
@@ -372,70 +371,6 @@
|
||||
| 6000 | `v4:forth79.4th` | `0x4055641ee17d176b` | ok |
|
||||
| 6001 | `v4:forth79.4th` | `0x4055641ee17d176b` | ok |
|
||||
| 6002 | `v4:forth79.4th` | `0x4055641ee17d176b` | ok |
|
||||
| 7000 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7001 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7002 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7003 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7004 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7005 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7006 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7007 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7008 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7009 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7010 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7011 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7012 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7013 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7014 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7015 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7016 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7017 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7018 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7019 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7020 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7021 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7022 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7023 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7024 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7025 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7026 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7027 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7028 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7029 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7030 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7031 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7032 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7033 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7034 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7035 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7036 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7037 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7038 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7039 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7040 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7041 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7042 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7043 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7044 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7045 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7046 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7047 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7048 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7049 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7050 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7051 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7052 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7053 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7054 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7055 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7056 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7057 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7058 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7059 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7060 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7061 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7062 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 7063 | `v4:post79.4th` | `0xb26d1b974884179d` | ok |
|
||||
| 8000 | `v4:hera.4th` | `0x526252bfef9b722b` | ok |
|
||||
| 8001 | `v4:hera.4th` | `0x526252bfef9b722b` | ok |
|
||||
| 8002 | `v4:hera.4th` | `0x526252bfef9b722b` | ok |
|
||||
@@ -447,4 +382,4 @@
|
||||
None.
|
||||
|
||||
---
|
||||
*39 capsule(s) scanned. Re-run `mkcapsule --manifest <dir>` to refresh.*
|
||||
*38 capsule(s) scanned. Re-run `mkcapsule --manifest <dir>` to refresh.*
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
+24
-2
@@ -705,8 +705,30 @@ Each is tested, committed and pushed before the next.
|
||||
release by asking, holes. Its acceptance is to be approved before it is
|
||||
built.
|
||||
**6b. POST is the kernel's.** Ruled 2026-10-07 (section 9); design
|
||||
approved 2026-10-07, `NUCLEUS.md` 6.3 and section 7. Acceptance, as
|
||||
approved:
|
||||
approved 2026-10-07, `NUCLEUS.md` 6.3 and section 7.
|
||||
**Done 2026-10-07.**
|
||||
- *The cases* (`v4/system/post_cases.c`, written by `v4/tools/mkpost.py`):
|
||||
the same 538, checked against the capsule case by case. One expected
|
||||
result changed: `>IN.initial` prints 6 where it printed 9, because a
|
||||
case's line no longer begins with the capsule's `T| `; the generator
|
||||
now runs v3 on the lines as the kernel sends them.
|
||||
- *The runner* (`v4/system/post.c`), tested in
|
||||
`v4/tests/test_host_quit.c` with cases that must pass and cases that
|
||||
must fail.
|
||||
- *The boot* (`v4/system/boot.c`) runs it after the capsules, prints
|
||||
`PARITY:V4_SYSTEM`, and seals. `capsules/v4/post79.4th`, `(CATCH)` and
|
||||
`(EMIT-HOOK)` are gone.
|
||||
- *Verified.* `make -C v4 test`, `sanitize` and `hosted-check`; three
|
||||
bare-metal boots, `logs/20261007-105118` (amd64), `-105335`
|
||||
(aarch64), `-105651` (riscv64). On all six: POST 538 of 538,
|
||||
`word_count=411`, `dict_hash=0x6fb1d09418b189ee`. At the prompt `T{`
|
||||
is unknown, and `RS1`, which a case defines, prints `42 42` before and
|
||||
after `COLD`. A hosted program built with one case's expected output
|
||||
changed names the case and ends `PARITY:FAIL`, `POST: FAILED`.
|
||||
- What the cases define takes 1,385 cells of the dictionary space's
|
||||
5,632.
|
||||
|
||||
Acceptance, as approved:
|
||||
1. *Same verdict.* The three hosted programs and the three bare-metal
|
||||
boots print `PARITY:V4_POST tests=538 pass=538 fail=0`,
|
||||
`PARITY:V4_SYSTEM word_count=N dict_hash=0x...`, `PARITY:OK` and
|
||||
|
||||
+13
-13
@@ -33,7 +33,7 @@ standard's and not v3's.
|
||||
| `+!.negative` | `10 HERE ! -3 HERE +! HERE @ . CR` | error | unchanged | stack `empty`, prints `7 \n` | v3 raises an error FORTH-79 does not ask for: a store to HERE |
|
||||
| `+!.accumulate` | `0 HERE ! 1 HERE +! 2 HERE +! 3 HERE +! HERE @ . CR` | error | unchanged | stack `empty`, prints `6 \n` | v3 raises an error FORTH-79 does not ask for: a store to HERE |
|
||||
| `HERE.after_comma~2` | `HERE 42 , HERE SWAP - 1 CELLS = 0 SWAP /` | error | unchanged | stack `0`, prints nothing | the case divides by zero unless HERE moved by one cell; on v3 it had moved by 8 |
|
||||
| `MOVE.basic` | `HERE 65 OVER C! HERE 1+ 66 OVER C! HERE HERE 16 + 2 MOVE HERE 16 + C@ . HERE 17 + C@ . CR` | stack `302 303`, printed `65 66 \n` | `65 HERE ! 66 HERE 1+ ! HERE HERE 16 + 2 MOVE HERE 16 + @ . HERE 17 + @ . CR` | stack `empty`, prints `65 66 \n` | FORTH-79: MOVE moves cells; and v3's address unit is a byte; a v4 address unit is a cell (D-1) |
|
||||
| `MOVE.basic` | `HERE 65 OVER C! HERE 1+ 66 OVER C! HERE HERE 16 + 2 MOVE HERE 16 + C@ . HERE 17 + C@ . CR` | stack `294 295`, printed `65 66 \n` | `65 HERE ! 66 HERE 1+ ! HERE HERE 16 + 2 MOVE HERE 16 + @ . HERE 17 + @ . CR` | stack `empty`, prints `65 66 \n` | FORTH-79: MOVE moves cells; and v3's address unit is a byte; a v4 address unit is a cell (D-1) |
|
||||
| `BASE.base_store` | `16 BASE ! 255 . CR` | stack `empty`, printed `597 \n` | unchanged | stack `empty`, prints `255 \n` | 255 read in base 16 and printed in base 16 is 255; v3 printed 467 |
|
||||
| `<#.basic` | `DECIMAL 42 S>D <# #S #> TYPE CR` | stack `empty`, printed `774763251095801167872\n` | unchanged | stack `empty`, prints `42\n` | v3 prints 774763251095801167872 for 42 S>D <# #S #> |
|
||||
| `<#.empty` | `0 <# #> TYPE CR` | stack `0`, printed `\n` | `0 0 <# #> TYPE CR` | stack `empty`, prints `\n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
|
||||
@@ -51,20 +51,20 @@ standard's and not v3's.
|
||||
| `#>.empty` | `0 <# #> TYPE CR` | stack `0`, printed `\n` | `0 0 <# #> TYPE CR` | stack `empty`, prints `\n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
|
||||
| `#>.stack_effect` | `42 <# #S #> SWAP . . CR` | stack `empty`, printed `24 2 \n` | `42 0 <# #S #> SWAP DROP . CR` | stack `empty`, prints `2 \n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
|
||||
| `HOLD.basic` | `42 <# 46 HOLD #S #> TYPE CR` | stack `empty`, printed `42.\n` | `42 0 <# 46 HOLD #S #> TYPE CR` | stack `empty`, prints `42.\n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
|
||||
| `COUNT.basic` | `HERE S" Test" DROP COUNT . . CR` | stack `302`, printed `84 303 \n` | `4 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `4 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1); and S" is not FORTH-79 |
|
||||
| `COUNT.empty` | `HERE 0 OVER C! COUNT . . CR` | stack `empty`, printed `0 308 \n` | `0 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `0 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1) |
|
||||
| `COUNT.max_length` | `HERE 255 OVER C! COUNT . . CR` | stack `empty`, printed `255 308 \n` | `255 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `255 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1) |
|
||||
| `COUNT.basic~2` | `HERE S" Test" DROP C@ HERE 1+ SWAP COUNT . . CR` | stack `412 418`, printed `0 85 \n` | `4 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `4 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1) |
|
||||
| `COUNT.empty~2` | `HERE 0 OVER C! COUNT . . CR` | stack `empty`, printed `0 418 \n` | `0 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `0 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1) |
|
||||
| `COUNT.max_length~2` | `HERE 255 OVER C! COUNT . . CR` | stack `empty`, printed `255 418 \n` | `255 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `255 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1) |
|
||||
| `CMOVE.basic` | `HERE S" Test" DUP >R HERE 10 + SWAP CMOVE CR` | stack `325`, printed `\n` | `65 PAD C! 66 PAD 1+ C! PAD PAD 10 + 2 CMOVE PAD 10 + C@ . PAD 11 + C@ . CR` | stack `empty`, prints `65 66 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1); and the v3 case leaves a value on the return stack |
|
||||
| `TYPE.basic_string` | `HERE S" Hello" DUP >R HERE SWAP CMOVE HERE R> TYPE CR` | stack `400`, printed `Hello\n` | `72 PAD C! 105 PAD 1+ C! PAD 2 TYPE CR` | stack `empty`, prints `Hi\n` | v3's address unit is a byte; a v4 address unit is a cell (D-1); and FORTH-79: >R R> R@ are for use inside a definition; v4 refuses them at the prompt |
|
||||
| `TYPE.numbers` | `HERE S" 12345" DUP >R HERE SWAP CMOVE HERE R> TYPE CR` | stack `406`, printed `12345\n` | `49 PAD C! 50 PAD 1+ C! PAD 2 TYPE CR` | stack `empty`, prints `12\n` | v3's address unit is a byte; a v4 address unit is a cell (D-1); and FORTH-79: >R R> R@ are for use inside a definition; v4 refuses them at the prompt |
|
||||
| `>IN.initial` | `>IN @ . CR` | stack `empty`, printed `860486384 \n` | unchanged | stack `empty`, prints `9 \n` | FORTH-79: >IN is the offset into the input, 9 here; v3 prints an address |
|
||||
| `COUNT.basic` | `HERE S" Test" DROP COUNT . . CR` | stack `294`, printed `84 295 \n` | `4 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `4 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1); and S" is not FORTH-79 |
|
||||
| `COUNT.empty` | `HERE 0 OVER C! COUNT . . CR` | stack `empty`, printed `0 300 \n` | `0 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `0 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1) |
|
||||
| `COUNT.max_length` | `HERE 255 OVER C! COUNT . . CR` | stack `empty`, printed `255 300 \n` | `255 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `255 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1) |
|
||||
| `COUNT.basic~2` | `HERE S" Test" DROP C@ HERE 1+ SWAP COUNT . . CR` | stack `404 410`, printed `0 85 \n` | `4 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `4 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1) |
|
||||
| `COUNT.empty~2` | `HERE 0 OVER C! COUNT . . CR` | stack `empty`, printed `0 410 \n` | `0 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `0 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1) |
|
||||
| `COUNT.max_length~2` | `HERE 255 OVER C! COUNT . . CR` | stack `empty`, printed `255 410 \n` | `255 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `255 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1) |
|
||||
| `CMOVE.basic` | `HERE S" Test" DUP >R HERE 10 + SWAP CMOVE CR` | stack `317`, printed `\n` | `65 PAD C! 66 PAD 1+ C! PAD PAD 10 + 2 CMOVE PAD 10 + C@ . PAD 11 + C@ . CR` | stack `empty`, prints `65 66 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1); and the v3 case leaves a value on the return stack |
|
||||
| `TYPE.basic_string` | `HERE S" Hello" DUP >R HERE SWAP CMOVE HERE R> TYPE CR` | stack `392`, printed `Hello\n` | `72 PAD C! 105 PAD 1+ C! PAD 2 TYPE CR` | stack `empty`, prints `Hi\n` | v3's address unit is a byte; a v4 address unit is a cell (D-1); and FORTH-79: >R R> R@ are for use inside a definition; v4 refuses them at the prompt |
|
||||
| `TYPE.numbers` | `HERE S" 12345" DUP >R HERE SWAP CMOVE HERE R> TYPE CR` | stack `398`, printed `12345\n` | `49 PAD C! 50 PAD 1+ C! PAD 2 TYPE CR` | stack `empty`, prints `12\n` | v3's address unit is a byte; a v4 address unit is a cell (D-1); and FORTH-79: >R R> R@ are for use inside a definition; v4 refuses them at the prompt |
|
||||
| `>IN.initial` | `>IN @ . CR` | stack `empty`, printed `657828592 \n` | unchanged | stack `empty`, prints `6 \n` | FORTH-79: >IN is the offset into the input, 6 here; v3 prints an address |
|
||||
| `UPDATE.no_block` | `0 SCR ! UPDATE` | error | unchanged | stack `empty`, prints nothing | v3 raises an error FORTH-79 does not ask for |
|
||||
| `SCR.after_load` | `1 LOAD SCR @ . CR` | stack `empty`, printed `` | unchanged | stack `empty`, prints `1 \n` | v3 prints nothing after 1 LOAD; SCR is still 1 from the LIST before |
|
||||
| `FIND.existing` | `FIND DUP . CR` | stack `empty`, printed `860485744 \n` | unchanged | 0 value(s) left; output not compared | FORTH-79: FIND takes the next word, DUP here, and leaves its address, which is printed |
|
||||
| `FIND.user_word` | `: test5 44 ; FIND test5 . CR` | stack `empty`, printed `860812560 \n` | unchanged | 0 value(s) left; output not compared | the address FIND leaves is printed |
|
||||
| `FIND.existing` | `FIND DUP . CR` | stack `empty`, printed `657827952 \n` | unchanged | 0 value(s) left; output not compared | FORTH-79: FIND takes the next word, DUP here, and leaves its address, which is printed |
|
||||
| `FIND.user_word` | `: test5 44 ; FIND test5 . CR` | stack `empty`, printed `658154448 \n` | unchanged | 0 value(s) left; output not compared | the address FIND leaves is printed |
|
||||
| `FIND.empty` | `FIND` | error | unchanged | stack `0`, prints nothing | FORTH-79: FIND leaves 0 when there is no word; v3 raises an error |
|
||||
| `VOCABULARY.cross_vocab_access` | `VOCABULARY V1 V1 DEFINITIONS : V1WORD 11 ; FORTH V1WORD . CR` | stack `empty`, printed `11 \n` | unchanged | an error | FORTH-79: a word defined in another vocabulary is not found from FORTH; v3 finds it |
|
||||
| `VOCABULARY.duplicate` | `VOCABULARY TESTVOC VOCABULARY TESTVOC` | error | unchanged | stack `empty`, prints nothing | v3 raises an error FORTH-79 does not ask for: defining a name again |
|
||||
|
||||
+2
-2
@@ -620,8 +620,8 @@ LOADER_EXTRA_SRCS += $(KERNEL_SRC)/v4/sk_v4.c
|
||||
KERNEL_EXTRA_SRCS += $(KERNEL_SRC)/v4/sk_v4.c
|
||||
# v4/system/boot.c is the boot the hosted v4 system runs too: nucleus, then
|
||||
# the capsules from this kernel's own capsule directory, then the prompt.
|
||||
LOADER_V4_OBJS := $(patsubst v4/src/%.c,$(LOADER_OBJ_DIR)/v4engine/%.o,$(V4_ENGINE_SRCS)) $(LOADER_OBJ_DIR)/v4engine/v4_image.o $(LOADER_OBJ_DIR)/v4system/boot.o $(LOADER_OBJ_DIR)/v4system/blocks.o
|
||||
KERNEL_V4_OBJS := $(patsubst v4/src/%.c,$(KERNEL_OBJ_DIR)/v4engine/%.o,$(V4_ENGINE_SRCS)) $(KERNEL_OBJ_DIR)/v4engine/v4_image.o $(KERNEL_OBJ_DIR)/v4system/boot.o $(KERNEL_OBJ_DIR)/v4system/blocks.o
|
||||
LOADER_V4_OBJS := $(patsubst v4/src/%.c,$(LOADER_OBJ_DIR)/v4engine/%.o,$(V4_ENGINE_SRCS)) $(LOADER_OBJ_DIR)/v4engine/v4_image.o $(LOADER_OBJ_DIR)/v4system/boot.o $(LOADER_OBJ_DIR)/v4system/blocks.o $(LOADER_OBJ_DIR)/v4system/post.o $(LOADER_OBJ_DIR)/v4system/post_cases.o
|
||||
KERNEL_V4_OBJS := $(patsubst v4/src/%.c,$(KERNEL_OBJ_DIR)/v4engine/%.o,$(V4_ENGINE_SRCS)) $(KERNEL_OBJ_DIR)/v4engine/v4_image.o $(KERNEL_OBJ_DIR)/v4system/boot.o $(KERNEL_OBJ_DIR)/v4system/blocks.o $(KERNEL_OBJ_DIR)/v4system/post.o $(KERNEL_OBJ_DIR)/v4system/post_cases.o
|
||||
endif
|
||||
|
||||
LOADER_SRCS := $(LOADER_SRCS_BASE) $(LOADER_EXTRA_SRCS)
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
[2J[001;001H[=3h[2J[001;001H[2J[001;001H[8;042;160t[2J[001;001H[2J[001;001H[8;056;240t[2J[001;001HBdsDxe: loading Boot0002 "UEFI QEMU DVD-ROM QM00005 " from PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0xFFFF,0x0)
|
||||
BdsDxe: starting Boot0002 "UEFI QEMU DVD-ROM QM00005 " from PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0xFFFF,0x0)
|
||||
[2J[001;001H[=3h[2J[001;001HStarKernel UEFI Loader
|
||||
Loading kernel from ESP...
|
||||
[CKPT 001] Entered efi_main - ConOut live
|
||||
RAW SERIAL UP
|
||||
[CKPT 002] Serial (COM1) initialized
|
||||
Monolithic build - kernel linked directly
|
||||
Collecting boot information...
|
||||
CmdLine: parsed OK
|
||||
[CKPT 004] Command line parsed
|
||||
[CKPT 005] Kernel stack allocation decided
|
||||
[CKPT 006] Boot info collected (ACPI table located)
|
||||
GOP: linear framebuffer found
|
||||
[CKPT 007] GOP: linear framebuffer found
|
||||
[CKPT 008] About to enter ExitBootServices retry loop
|
||||
EBS...
|
||||
EBS OK
|
||||
Calling kernel_main (monolithic)...
|
||||
|
||||
|
||||
_____ _ _ __ _
|
||||
/ ____| | | |/ / | |
|
||||
| (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| |
|
||||
\___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ |
|
||||
____) | || (_| | | | . \ __/ | | | | | __/ |
|
||||
|_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_|
|
||||
|
||||
LithosAnanke v2.1.0
|
||||
Architecture: amd64
|
||||
Build: Oct 7 2026 10:50:50
|
||||
|
||||
UEFI BootServices: EXITED
|
||||
|
||||
=== StarKernel Boot Information ===
|
||||
Memory map entries: 131
|
||||
Total memory: 1023 MB
|
||||
Usable memory: 966 MB
|
||||
===================================
|
||||
|
||||
PMM initialized.
|
||||
PMM statistics:
|
||||
Total pages: 248741
|
||||
Free pages : 247218
|
||||
Used pages : 1523
|
||||
Total MB : 971
|
||||
Free MB : 965
|
||||
Used MB : 5
|
||||
|
||||
VMM initialized (mapped RAM, CR3 switched)
|
||||
VMM initialized (mapped RAM, CR3 switched)
|
||||
VMM self-test: mapped OK at 0xffff800000000000
|
||||
VMM self-test complete.
|
||||
|
||||
IDT installed.
|
||||
|
||||
APIC: init...
|
||||
APIC: IA32_APIC_BASE MSR=0x00000000fee00900
|
||||
APIC: stale-ISR drain: 0 EOI(s) issued
|
||||
APIC: initialized (xAPIC MMIO, TPR=0, SIVR=0x1FF, EOI-clear)
|
||||
APIC: init done
|
||||
|
||||
I/O APIC: init...
|
||||
I/O APIC: base=0xfec00000, gsi_base=0, overrides=5
|
||||
override: source=00 gsi=2 flags=0x0000
|
||||
override: source=05 gsi=5 flags=0x000d
|
||||
override: source=09 gsi=9 flags=0x000d
|
||||
override: source=0a gsi=10 flags=0x000d
|
||||
override: source=0b gsi=11 flags=0x000d
|
||||
i8042: keyboard ACKed enable-scanning
|
||||
i8042: IRQ1 enabled in controller config byte
|
||||
I/O APIC: keyboard IRQ1 routed (masked)
|
||||
|
||||
Timer: init...
|
||||
Timer: init start
|
||||
Timer: PM_TMR_BLK discovered from FADT at port 1544
|
||||
Timer: VM mode detected (hypervisor present).
|
||||
Timer: HPET calibration disabled (VM-exit MMIO would poison timing).
|
||||
Timer: WARNING: invariant TSC not present under hypervisor.
|
||||
Timer: continuing in RELATIVE mode (no determinism guarantees).
|
||||
Timer: RDTSCP not present; using RDTSC (less serialized).
|
||||
Timer: CPUID frequency unavailable; trying PM Timer...
|
||||
Timer: trust=1 (0=NONE,1=REL,2=ABS), TSC=2149499758 Hz
|
||||
Timer: init done
|
||||
|
||||
Kernel heap initialized.
|
||||
Heap statistics:
|
||||
Total bytes: 536870872
|
||||
Free bytes: 536870872
|
||||
Used bytes: 0
|
||||
Peak bytes: 0
|
||||
Heap base addr: 24641536
|
||||
Heap end addr: 561512448
|
||||
|
||||
Heartbeat: init...
|
||||
APIC Timer: calibrating...
|
||||
APIC Timer: apic_hz=1031765227, tick_hz=100, initial_count=10317652
|
||||
APIC Timer: configured (masked, ready to start)
|
||||
Heartbeat: init done
|
||||
Kernel initialization complete.
|
||||
Boot successful!
|
||||
|
||||
StarForth v4: one host node, the F18-derived engine
|
||||
V4: capsule v4:nucleus-64.f18 signature: missing (unsigned)
|
||||
PARITY:V4_NUCLEUS name=v4:nucleus-64.f18 capsule_id=0x467b3793e193b467 capsule_hash=0x467b3793e193b467 words=308
|
||||
V4: capsule v4:forth79.4th signature: missing (unsigned)
|
||||
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x4055641ee17d176b capsule_hash=0x4055641ee17d176b dict_hash=0xf268e314e12931c4
|
||||
PARITY:V4_POST tests=538 pass=538 fail=0
|
||||
PARITY:V4_SYSTEM word_count=411 dict_hash=0x6fb1d09418b189ee
|
||||
PARITY:OK
|
||||
POST: PASSED
|
||||
[32m[HADES][INFO ] [0m[KRELTSC: 0] blk: raw device LBN 2048..3071 (1024 blocks)
|
||||
PCI: init...
|
||||
PCI: ECAM mapped (amd64)
|
||||
virtio-blk: found device
|
||||
Artemis: virtio-blk attached
|
||||
[32m[HADES][INFO ] [0m[KRELTSC: 78934212] blk: disk 'StarForth Volume' v2 LBN 3072..789009 (785938 user b
|
||||
ok> : SQ DUP * ;
|
||||
ok
|
||||
ok> 7 SQ . 3 4 U* . .
|
||||
49 0 12 ok
|
||||
ok> T{
|
||||
UNKNOWN WORD: 'T{'
|
||||
ERROR
|
||||
ok> RS1
|
||||
42 42
|
||||
ok
|
||||
ok> COLD
|
||||
FORTH-79 Cold Start
|
||||
System initialized.
|
||||
ok
|
||||
ok> RS1
|
||||
42 42
|
||||
ok
|
||||
ok> 3 4 U* . .
|
||||
0 12 ok
|
||||
ok> FORGET U*
|
||||
Protected word
|
||||
ERROR
|
||||
ok> 9 KERNEL-WORD ASK9 ASK9
|
||||
Argument out of range
|
||||
ERROR
|
||||
ok> 1 BLOCK C@ . 2047 BLOCK C@ .
|
||||
0 0 ok
|
||||
ok> 2100 BLOCK 1024 BLANK 65 2100 BLOCK C! UPDATE SAVE-BUFFERS EMPTY-BUFFERS 2100 BLOCK C@ .
|
||||
65 ok
|
||||
ok> 3072 BLOCK C@ .
|
||||
0 ok
|
||||
ok> 3072 BLOCK DROP UPDATE SAVE-BUFFERS
|
||||
Storage refused
|
||||
ERROR
|
||||
ok> 9999999 BLOCK
|
||||
Block out of range
|
||||
ERROR
|
||||
ok> HERE .
|
||||
9585 ok
|
||||
ok> BYE
|
||||
BYE: cold restart
|
||||
@@ -0,0 +1,131 @@
|
||||
UEFI firmware (version 2025.11-3ubuntu7.3 built at 15:40:26 on Sep 23 2026)
|
||||
[2J[001;001H[=3h[2J[001;001H[2J[001;001H[8;031;100t[2J[001;001HBdsDxe: failed to load Boot0002 "UEFI Misc Device" from PciRoot(0x0)/Pci(0x2,0x0): Not Found
|
||||
BdsDxe: failed to load Boot0003 "UEFI QEMU QEMU USB HARDDRIVE 1-0000:00:04.0-1" from PciRoot(0x0)/Pci(0x4,0x0)/USB(0x0,0x0): Not Found
|
||||
BdsDxe: loading Boot0004 "UEFI Misc Device 2" from PciRoot(0x0)/Pci(0x6,0x0)
|
||||
BdsDxe: starting Boot0004 "UEFI Misc Device 2" from PciRoot(0x0)/Pci(0x6,0x0)
|
||||
[2J[001;001H[=3h[2J[001;001HStarKernel UEFI Loader
|
||||
Loading kernel from ESP...
|
||||
[CKPT 001] Entered efi_main - ConOut live
|
||||
Collecting boot information...
|
||||
[CKPT 004] Command line parsed
|
||||
[CKPT 005] Kernel stack allocation decided
|
||||
[CKPT 006] Boot info collected (ACPI table located)
|
||||
[CKPT 007] GOP: linear framebuffer found
|
||||
[CKPT 008] About to enter ExitBootServices retry loop
|
||||
|
||||
|
||||
_____ _ _ __ _
|
||||
/ ____| | | |/ / | |
|
||||
| (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| |
|
||||
\___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ |
|
||||
____) | || (_| | | | . \ __/ | | | | | __/ |
|
||||
|_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_|
|
||||
|
||||
LithosAnanke v2.1.0
|
||||
Architecture: aarch64
|
||||
Build: Oct 7 2026 10:53:09
|
||||
|
||||
UEFI BootServices: EXITED
|
||||
|
||||
=== StarKernel Boot Information ===
|
||||
Memory map entries: 108
|
||||
Total memory: 4093 MB
|
||||
Usable memory: 4054 MB
|
||||
===================================
|
||||
|
||||
PMM initialized.
|
||||
PMM statistics:
|
||||
Total pages: 1039357
|
||||
Free pages : 1037946
|
||||
Used pages : 1411
|
||||
Total MB : 4059
|
||||
Free MB : 4054
|
||||
Used MB : 5
|
||||
|
||||
VMM initialized (mapped RAM, CR3 switched)
|
||||
VMM initialized (mapped RAM, CR3 switched)
|
||||
VMM self-test: mapped OK at 0xffff800000000000
|
||||
VMM self-test complete.
|
||||
|
||||
AArch64: running at EL1
|
||||
IDT installed.
|
||||
|
||||
APIC: init...
|
||||
PSCI: no DTB -- using HVC (QEMU virt-machine default)
|
||||
GICv2: no DTB GIC node -- using QEMU virt-machine defaults
|
||||
GICv2: distributor+CPU interface enabled, PPI 30
|
||||
APIC: init done
|
||||
|
||||
Timer: init...
|
||||
Timer: AArch64 generic timer initialised.
|
||||
Timer: init done
|
||||
|
||||
Kernel heap initialized.
|
||||
Heap statistics:
|
||||
Total bytes: 2147483608
|
||||
Free bytes: 2147483608
|
||||
Used bytes: 0
|
||||
Peak bytes: 0
|
||||
Heap base addr: 1207959552
|
||||
Heap end addr: 3355443200
|
||||
|
||||
Heartbeat: init...
|
||||
Heartbeat: init done
|
||||
Kernel initialization complete.
|
||||
Boot successful!
|
||||
|
||||
StarForth v4: one host node, the F18-derived engine
|
||||
V4: capsule v4:nucleus-64.f18 signature: missing (unsigned)
|
||||
PARITY:V4_NUCLEUS name=v4:nucleus-64.f18 capsule_id=0x467b3793e193b467 capsule_hash=0x467b3793e193b467 words=308
|
||||
V4: capsule v4:forth79.4th signature: missing (unsigned)
|
||||
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x4055641ee17d176b capsule_hash=0x4055641ee17d176b dict_hash=0xf268e314e12931c4
|
||||
PARITY:V4_POST tests=538 pass=538 fail=0
|
||||
PARITY:V4_SYSTEM word_count=411 dict_hash=0x6fb1d09418b189ee
|
||||
PARITY:OK
|
||||
POST: PASSED
|
||||
[32m[HADES][INFO ] [0m[KRELTSC: 0] blk: raw device LBN 2048..3071 (1024 blocks)
|
||||
PCI: init...
|
||||
virtio-blk: found device
|
||||
Artemis: virtio-blk attached
|
||||
[32m[HADES][INFO ] [0m[KRELTSC: 1501177] blk: disk 'StarForth Volume' v2 LBN 3072..789009 (785938 user b
|
||||
ok> : SQ DUP * ;
|
||||
ok
|
||||
ok> 7 SQ . 3 4 U* . .
|
||||
49 0 12 ok
|
||||
ok> T{
|
||||
UNKNOWN WORD: 'T{'
|
||||
ERROR
|
||||
ok> RS1
|
||||
42 42
|
||||
ok
|
||||
ok> COLD
|
||||
FORTH-79 Cold Start
|
||||
System initialized.
|
||||
ok
|
||||
ok> RS1
|
||||
42 42
|
||||
ok
|
||||
ok> 3 4 U* . .
|
||||
0 12 ok
|
||||
ok> FORGET U*
|
||||
Protected word
|
||||
ERROR
|
||||
ok> 9 KERNEL-WORD ASK9 ASK9
|
||||
Argument out of range
|
||||
ERROR
|
||||
ok> 1 BLOCK C@ . 2047 BLOCK C@ .
|
||||
0 0 ok
|
||||
ok> 2100 BLOCK 1024 BLANK 65 2100 BLOCK C! UPDATE SAVE-BUFFERS EMPTY-BUFFERS 2100 BLOCK C@ .
|
||||
65 ok
|
||||
ok> 3072 BLOCK C@ .
|
||||
0 ok
|
||||
ok> 3072 BLOCK DROP UPDATE SAVE-BUFFERS
|
||||
Storage refused
|
||||
ERROR
|
||||
ok> 9999999 BLOCK
|
||||
Block out of range
|
||||
ERROR
|
||||
ok> HERE .
|
||||
9585 ok
|
||||
ok> BYE
|
||||
BYE: cold restart
|
||||
@@ -0,0 +1,201 @@
|
||||
|
||||
OpenSBI v1.8
|
||||
____ _____ ____ _____
|
||||
/ __ \ / ____| _ \_ _|
|
||||
| | | |_ __ ___ _ __ | (___ | |_) || |
|
||||
| | | | '_ \ / _ \ '_ \ \___ \| _ < | |
|
||||
| |__| | |_) | __/ | | |____) | |_) || |_
|
||||
\____/| .__/ \___|_| |_|_____/|____/_____|
|
||||
| |
|
||||
|_|
|
||||
|
||||
Platform Name : riscv-virtio,qemu
|
||||
Platform Features : medeleg
|
||||
Platform HART Count : 1
|
||||
Platform HART Protection : pmp
|
||||
Platform IPI Device : aclint-mswi
|
||||
Platform Timer Device : aclint-mtimer @ 10000000Hz
|
||||
Platform Console Device : uart8250
|
||||
Platform HSM Device : ---
|
||||
Platform PMU Device : ---
|
||||
Platform Reboot Device : syscon-reboot
|
||||
Platform Shutdown Device : syscon-poweroff
|
||||
Platform Suspend Device : ---
|
||||
Platform CPPC Device : ---
|
||||
Firmware Base : 0x80000000
|
||||
Firmware Size : 321 KB
|
||||
Firmware RW Offset : 0x40000
|
||||
Firmware RW Size : 65 KB
|
||||
Firmware Heap Offset : 0x47000
|
||||
Firmware Heap Size : 37 KB (total), 0 KB (reserved), 12 KB (used), 23 KB (free)
|
||||
Firmware Scratch Size : 4096 B (total), 1464 B (used), 2632 B (free)
|
||||
Runtime SBI Version : 3.0
|
||||
Standard SBI Extensions : ipi,pmu,srst,sse,hsm,rfnc,fwft,time,base,legacy,dbcn,dbtr
|
||||
Experimental SBI Extensions : none
|
||||
|
||||
Domain0 Name : root
|
||||
Domain0 Boot HART : 0
|
||||
Domain0 HARTs : 0*
|
||||
Domain0 Region00 : 0x0000000080040000-0x000000008005ffff M: (F,R,W) S/U: ()
|
||||
Domain0 Region01 : 0x0000000080000000-0x000000008003ffff M: (F,R,X) S/U: ()
|
||||
Domain0 Region02 : 0x0000000000100000-0x0000000000100fff M: (I,R,W) S/U: (R,W)
|
||||
Domain0 Region03 : 0x0000000010000000-0x0000000010000fff M: (I,R,W) S/U: (R,W)
|
||||
Domain0 Region04 : 0x0000000002000000-0x000000000200ffff M: (I,R,W) S/U: ()
|
||||
Domain0 Region05 : 0x000000000c400000-0x000000000c5fffff M: (I,R,W) S/U: (R,W)
|
||||
Domain0 Region06 : 0x000000000c000000-0x000000000c3fffff M: (I,R,W) S/U: (R,W)
|
||||
Domain0 Region07 : 0x0000000000000000-0xffffffffffffffff M: () S/U: (R,W,X)
|
||||
Domain0 Next Address : 0x0000000020000000
|
||||
Domain0 Next Arg1 : 0x00000000bfe00000
|
||||
Domain0 Next Mode : S-mode
|
||||
Domain0 SysReset : yes
|
||||
Domain0 SysSuspend : yes
|
||||
|
||||
Boot HART ID : 0
|
||||
Boot HART Domain : root
|
||||
Boot HART Priv Version : v1.12
|
||||
Boot HART Base ISA : rv64imafdch
|
||||
Boot HART ISA Extensions : sstc,zicntr,zihpm,zicboz,zicbom,sdtrig,svadu
|
||||
Boot HART PMP Count : 16
|
||||
Boot HART PMP Granularity : 2 bits
|
||||
Boot HART PMP Address Bits : 54
|
||||
Boot HART MHPM Info : 16 (0x0007fff8)
|
||||
Boot HART Debug Triggers : 2 triggers
|
||||
Boot HART MIDELEG : 0x0000000000001666
|
||||
Boot HART MEDELEG : 0x0000000000f4b509
|
||||
[2J[004D[=3h[2J[009D[2J[004D[8;031;100t[2J[016DRISC-V EDK2 firmware version 2025.11-3ubuntu7.3
|
||||
Press ESCAPE within 5 seconds for boot options ERROR: C40000002:V03051002 I0 6D33944A-EC75-4855-A54D-809C75241F6C 83FFF850
|
||||
BdsDxe: failed to load Boot0001 "UEFI Misc Device" fr
|
||||
om PciRoot(0x0)/Pci(0x1,0x0): Not Found
|
||||
[2J[001;001H[=3h[2J[009DStarKernel UEFI Loader
|
||||
Loading kernel from ESP...
|
||||
[CKPT 001] Entered efi_main - ConOut live
|
||||
Monolithic build - kernel linked directly
|
||||
Collecting boot information...
|
||||
CmdLine: parsed OK
|
||||
[CKPT 004] Command line parsed
|
||||
[CKPT 005] Kernel stack allocation decided
|
||||
[CKPT 006] Boot info collected (ACPI table located)
|
||||
GOP: linear framebuffer found
|
||||
[CKPT 007] GOP: linear framebuffer found
|
||||
[CKPT 008] About to enter ExitBootServices retry loop
|
||||
Calling kernel_main (monolithic)...
|
||||
riscv64 item 4.3.5a: satp state at kernel entry (before switch)
|
||||
satp.MODE = 0x000000000000000a
|
||||
satp.PPN = 0x00000000000bf868
|
||||
__kernel_start = 0x00000000bdca29f8
|
||||
riscv64: satp cleared -- Bare mode, explicit (item 4.3.5a)
|
||||
|
||||
|
||||
_____ _ _ __ _
|
||||
/ ____| | | |/ / | |
|
||||
| (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| |
|
||||
\___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ |
|
||||
____) | || (_| | | | . \ __/ | | | | | __/ |
|
||||
|_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_|
|
||||
|
||||
LithosAnanke v2.1.0
|
||||
Architecture: riscv64
|
||||
Build: Oct 7 2026 10:56:11
|
||||
|
||||
UEFI BootServices: EXITED
|
||||
|
||||
=== StarKernel Boot Information ===
|
||||
Memory map entries: 100
|
||||
Total memory: 1020 MB
|
||||
Usable memory: 975 MB
|
||||
===================================
|
||||
|
||||
PMM initialized.
|
||||
PMM statistics:
|
||||
Total pages: 250273
|
||||
Free pages : 249621
|
||||
Used pages : 652
|
||||
Total MB : 977
|
||||
Free MB : 975
|
||||
Used MB : 2
|
||||
|
||||
VMM initialized (mapped RAM, CR3 switched)
|
||||
VMM initialized (mapped RAM, CR3 switched)
|
||||
VMM self-test: mapped OK at 0xffff800000000000
|
||||
VMM self-test complete.
|
||||
|
||||
IDT installed.
|
||||
|
||||
APIC: init...
|
||||
PLIC: no DTB PLIC node -- using QEMU virt-machine default (base=0x0c000000)
|
||||
PLIC: init (S-mode context 1, threshold=0)
|
||||
APIC: init done
|
||||
|
||||
Timer: init...
|
||||
Timer: RISC-V time CSR @ 10000000 Hz (FALLBACK, no devicetree)
|
||||
Timer: init done
|
||||
|
||||
Kernel heap initialized.
|
||||
Heap statistics:
|
||||
Total bytes: 536870872
|
||||
Free bytes: 536870872
|
||||
Used bytes: 0
|
||||
Peak bytes: 0
|
||||
Heap base addr: 2214588416
|
||||
Heap end addr: 2751459328
|
||||
|
||||
Heartbeat: init...
|
||||
Heartbeat: init done
|
||||
Kernel initialization complete.
|
||||
Boot successful!
|
||||
|
||||
StarForth v4: one host node, the F18-derived engine
|
||||
V4: capsule v4:nucleus-64.f18 signature: missing (unsigned)
|
||||
PARITY:V4_NUCLEUS name=v4:nucleus-64.f18 capsule_id=0x467b3793e193b467 capsule_hash=0x467b3793e193b467 words=308
|
||||
V4: capsule v4:forth79.4th signature: missing (unsigned)
|
||||
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x4055641ee17d176b capsule_hash=0x4055641ee17d176b dict_hash=0xf268e314e12931c4
|
||||
PARITY:V4_POST tests=538 pass=538 fail=0
|
||||
PARITY:V4_SYSTEM word_count=411 dict_hash=0x6fb1d09418b189ee
|
||||
PARITY:OK
|
||||
POST: PASSED
|
||||
[32m[HADES][INFO ] [0m[KRELTSC: 0] blk: raw device LBN 2048..3071 (1024 blocks)
|
||||
PCI: init...
|
||||
virtio-blk: found device
|
||||
Artemis: virtio-blk attached
|
||||
[32m[HADES][INFO ] [0m[KRELTSC: 40981668] blk: disk 'StarForth Volume' v2 LBN 3072..789009 (785938 user b
|
||||
ok> : SQ DUP * ;
|
||||
ok
|
||||
ok> 7 SQ . 3 4 U* . .
|
||||
49 0 12 ok
|
||||
ok> T{
|
||||
UNKNOWN WORD: 'T{'
|
||||
ERROR
|
||||
ok> RS1
|
||||
42 42
|
||||
ok
|
||||
ok> COLD
|
||||
FORTH-79 Cold Start
|
||||
System initialized.
|
||||
ok
|
||||
ok> RS1
|
||||
42 42
|
||||
ok
|
||||
ok> 3 4 U* . .
|
||||
0 12 ok
|
||||
ok> FORGET U*
|
||||
Protected word
|
||||
ERROR
|
||||
ok> 9 KERNEL-WORD ASK9 ASK9
|
||||
Argument out of range
|
||||
ERROR
|
||||
ok> 1 BLOCK C@ . 2047 BLOCK C@ .
|
||||
0 0 ok
|
||||
ok> 2100 BLOCK 1024 BLANK 65 2100 BLOCK C! UPDATE SAVE-BUFFERS EMPTY-BUFFERS 2100 BLOCK C@ .
|
||||
65 ok
|
||||
ok> 3072 BLOCK C@ .
|
||||
0 ok
|
||||
ok> 3072 BLOCK DROP UPDATE SAVE-BUFFERS
|
||||
Storage refused
|
||||
ERROR
|
||||
ok> 9999999 BLOCK
|
||||
Block out of range
|
||||
ERROR
|
||||
ok> HERE .
|
||||
9585 ok
|
||||
ok> BYE
|
||||
BYE: cold restart
|
||||
+2
-2
@@ -139,7 +139,7 @@ CAPSULE_DIR_C := $(BINDIR)/capsule_generated.c
|
||||
|
||||
# the kernel's capsule code: find, check the hash, verify the signature,
|
||||
# split a payload into blocks
|
||||
SYSTEM_SRCS := $(HERE)/system/boot.c \
|
||||
SYSTEM_SRCS := $(HERE)/system/boot.c $(HERE)/system/post.c $(HERE)/system/post_cases.c \
|
||||
$(addprefix $(ROOT)/kernel/src/capsule/,capsule_find.c capsule_validate.c capsule_sig.c capsule_blocks.c) \
|
||||
$(ROOT)/kernel/src/hash/xxhash64.c $(ROOT)/kernel/src/crypto/x509_ed25519.c $(CRYPTO_SRCS)
|
||||
# The kernel's sources are held to the kernel's warnings, not this model's.
|
||||
@@ -169,7 +169,7 @@ $(foreach i,$(HOSTED_ISAS),$(eval $(call HOSTED_RULE,$(i))))
|
||||
|
||||
# `make post` boots the amd64 system alone, which is the quick check after a
|
||||
# change to the vocabulary: nucleus, forth79.4th, POST, prompt. `make
|
||||
# post79` writes the POST capsule, ../capsules/v4/post79.4th, again from
|
||||
# post79` writes POST's cases, system/post_cases.c, again from
|
||||
# v3's cases and tools/post79_rules.py (tools/mkpost.py); it needs the
|
||||
# hosted v3 binary.
|
||||
.PHONY: post post79
|
||||
|
||||
+14
-10
@@ -159,21 +159,25 @@ a time with POST after each, is the next step (`NUCLEUS.md` section 8).
|
||||
|
||||
## POST
|
||||
|
||||
`capsules/v4/post79.4th`: 538 cases in blocks 7000 up, covering 126 of the
|
||||
130 words of the FORTH-79 Required Word Set. 443 are v3's cases with what
|
||||
the hosted v3 binary did as the expected result. The other 107, and the 27
|
||||
v3 cases left out, are listed with reasons in `docs/v4.0.0/POST79.md`.
|
||||
POST is the kernel's, as in v3 (`MESH.md` step 6b, `NUCLEUS.md` 6.3). The
|
||||
kernel holds the cases, `v4/system/post_cases.c`: 538 of them, covering 126
|
||||
of the 130 words of the FORTH-79 Required Word Set. 431 are v3's cases with
|
||||
what the hosted v3 binary did as the expected result; every other case,
|
||||
and the v3 cases left out, are listed with reasons in
|
||||
`docs/v4.0.0/POST79.md`.
|
||||
|
||||
- `make -C v4 post` boots the amd64 system: the quick check after a change.
|
||||
- `make -C v4 hosted-check` boots all three hosted ISAs and compares them.
|
||||
- `make -C v4 post79` writes the capsule again (`tools/mkpost.py`,
|
||||
- `make -C v4 post79` writes the cases again (`tools/mkpost.py`,
|
||||
`tools/post79_rules.py`); it needs the hosted v3 binary.
|
||||
|
||||
POST is FORTH: a harness of FORTH-79 words and two nucleus hooks, `(CATCH)`
|
||||
and `(EMIT-HOOK)`. It forgets itself when it has finished. The boot passes
|
||||
only on seeing POST's tally line with `fail=0` (`v4/system/boot.c`). A colon
|
||||
definition broken on purpose (`U/MOD` without its last `SWAP`) fails five
|
||||
cases and the boot stops with `POST: FAILED`.
|
||||
The runner, `v4/system/post.c`, feeds each case to the node a line at a
|
||||
time, keeps what the node prints, reads its data stack from outside, and
|
||||
judges: an error exactly if one is expected, and otherwise the stack and
|
||||
every character printed. Nothing of POST is in the node's dictionary. What
|
||||
the cases define stays there, as in v3, and the system is sealed after
|
||||
POST. The boot then prints `PARITY:V4_SYSTEM word_count=N dict_hash=0x...`,
|
||||
and passes only if no case failed (`v4/system/boot.c`).
|
||||
|
||||
Not tested: `KEY`, `EXPECT`, `QUERY` (the keyboard) and `QUIT` (it returns
|
||||
without ` ok`).
|
||||
|
||||
+4
-10
@@ -251,18 +251,12 @@ header CMOVE
|
||||
(OUT) (OUT^) a! ! ;
|
||||
NONE: drop ;
|
||||
|
||||
\ EMIT puts the character with what has been printed, unless (EMIT-HOOK)
|
||||
\ holds the xt of a word: then that word is given it instead ( c -- ), and
|
||||
\ returns to EMIT's caller. Everything the node prints goes through EMIT,
|
||||
\ so a hook sees all of it. The hook is taken off when the text being
|
||||
\ interpreted ends (quit.v4), so that nothing can leave a node silent.
|
||||
\ POST uses it to compare what a case prints (docs/v4.0.0/NUCLEUS.md 6.3).
|
||||
\ A is kept: the words that print have always been free to use it across
|
||||
\ an EMIT. As v3, only the low 8 bits of the character are printed.
|
||||
\ EMIT puts the character with what has been printed. Everything the node
|
||||
\ prints goes through EMIT. A is kept: the words that print have always
|
||||
\ been free to use it across an EMIT. As v3, only the low 8 bits of the
|
||||
\ character are printed.
|
||||
header EMIT
|
||||
: EMIT ( c -- )
|
||||
(EMIT-HOOK) b! @b if NONE push ;
|
||||
NONE: drop
|
||||
255 and a push push \ A, and then the character, to the return stack
|
||||
(OUT^) b! @b a! pop !+ a !b \ the character goes where (OUT^) points, which moves on
|
||||
a (OUT)+256 xor if FULL drop pop a! ;
|
||||
|
||||
+3
-16
@@ -48,18 +48,10 @@ macro R-CLEAR RSTACK-DEPTH b! a !b endmacro
|
||||
\ structures. A definition that was under way stays hidden.
|
||||
: (RESET) 0 STATE a! ! (CG-RESET) CFBASE (CFP) a! ! ;
|
||||
|
||||
\ CATCHING A LINE'S ERROR. While the variable (CATCH) is not zero, a line
|
||||
\ that ends in an error -- a fault, or a code in NODE-ERROR -- does not say
|
||||
\ ERROR: (CATCH) is set to -1 and the line is reported as completed. Whatever message the
|
||||
\ error printed has gone wherever EMIT was sending it. POST uses this to
|
||||
\ go on to its next case, and to check the cases that must fail
|
||||
\ (docs/v4.0.0/NUCLEUS.md 6.3). (EMIT-HOOK), core.v4, is set to 0 here at
|
||||
\ the end of every line, caught or not.
|
||||
\
|
||||
\ ( s -- ) the text is done with. What it printed is sent, then a message
|
||||
\ saying how it ended -- 0 QUIT, 1 completed, 2 an error -- and the node waits
|
||||
\ for the next. (DONE) is entered with the same number and decides whether
|
||||
\ an error was one to catch; it is always jumped to, never called, by
|
||||
\ for the next. (DONE) is entered with the same number and, for an error,
|
||||
\ stops compiling first; it is always jumped to, never called, by
|
||||
\ something that has emptied the return stack (or by a fault, which empties
|
||||
\ it). (LINE-STATUS) keeps how the last text ended.
|
||||
: (FINISH) ( s -- )
|
||||
@@ -70,11 +62,8 @@ macro R-CLEAR RSTACK-DEPTH b! a !b endmacro
|
||||
jump (IDLE)
|
||||
|
||||
: (DONE)
|
||||
(EMIT-HOOK) b! 0 !b \ what is printed is printed again
|
||||
if GO -1 + if OK
|
||||
drop (RESET)
|
||||
(CATCH) b! @b if LOUD drop -1 !b 1 jump (DONE) \ caught: the text completed
|
||||
LOUD: drop 2 jump (FINISH)
|
||||
drop (RESET) 2 jump (FINISH)
|
||||
OK: drop 1 jump (FINISH)
|
||||
GO: drop 0 jump (FINISH)
|
||||
|
||||
@@ -247,13 +236,11 @@ header (SEAL)
|
||||
\ further, the message for the code is printed (-1: the word has printed
|
||||
\ its own) and the line ends with ERROR. The codes are listed in core.v4.
|
||||
header NODE-ERROR inline : NODE-ERROR' NODE-ERROR ;
|
||||
header (CATCH) inline : (CATCH)' (CATCH) ;
|
||||
header (ME) inline : (ME)' (ME) ;
|
||||
header (CONSOLE) inline : (CONSOLE)' (CONSOLE) ;
|
||||
header (LOST) inline : (LOST)' (LOST) ;
|
||||
header (WORD-DEFINED) inline : (WORD-DEFINED)' (WORD-DEFINED) ;
|
||||
header (WORD-FORGOTTEN) inline : (WORD-FORGOTTEN)' (WORD-FORGOTTEN) ;
|
||||
header (EMIT-HOOK) inline : (EMIT-HOOK)' (EMIT-HOOK) ;
|
||||
|
||||
header QUIT
|
||||
: QUIT R-CLEAR (RESET) CR 0 jump (DONE)
|
||||
|
||||
+51
-50
@@ -4,6 +4,7 @@
|
||||
* It is not part of the engine (v4/src): it needs the capsule directory,
|
||||
* which only a whole system has.
|
||||
*/
|
||||
#include "v4/post.h"
|
||||
#include "v4/blocks.h"
|
||||
#include "v4/boot.h"
|
||||
#include "v4/message.h"
|
||||
@@ -13,18 +14,18 @@
|
||||
#include "starkernel/capsule_blocks.h"
|
||||
|
||||
/* The capsules, in the order they are loaded. */
|
||||
/* POST is part of the boot: v4:post79.4th is loaded after the vocabulary it
|
||||
* tests and must end with a clean tally. -DV4_POST_AT_BOOT=0 leaves it
|
||||
* out, for work on a vocabulary that does not pass yet. */
|
||||
static const char *const boot_capsules[] = {
|
||||
"v4:forth79.4th",
|
||||
};
|
||||
|
||||
/* POST is part of the boot, and is the kernel's (v4/include/v4/post.h;
|
||||
* docs/v4.0.0/NUCLEUS.md 6.3): when the capsules are in, the kernel feeds
|
||||
* its cases to the node and judges them, and the boot passes only if none
|
||||
* failed. -DV4_POST_AT_BOOT=0 leaves it out, for work on a vocabulary
|
||||
* that does not pass yet. */
|
||||
#ifndef V4_POST_AT_BOOT
|
||||
#define V4_POST_AT_BOOT 1
|
||||
#endif
|
||||
static const char *const boot_capsules[] = {
|
||||
"v4:forth79.4th",
|
||||
#if V4_POST_AT_BOOT
|
||||
"v4:post79.4th",
|
||||
#endif
|
||||
};
|
||||
|
||||
#define LINE_MAX 1025u /* a line is at most 1024 characters, a block */
|
||||
#define STEP_LIMIT 4000000000ULL /* instruction words one line may take */
|
||||
@@ -77,37 +78,6 @@ static uint32_t word_count(const v4_node *n, const v4_image *im)
|
||||
|
||||
/* ---- handing the node a line ---------------------------------------------- */
|
||||
|
||||
/* POST's verdict. The POST capsule ends by printing one line,
|
||||
* PARITY:V4_POST tests=N pass=N fail=N
|
||||
* and the boot passes only if it has seen that line with fail=0. That no
|
||||
* line was refused is not enough: a POST that was broken half way would
|
||||
* refuse nothing. */
|
||||
static char post_line[96];
|
||||
static unsigned post_len;
|
||||
static int post_seen, post_clean;
|
||||
|
||||
static int text_at(const char *line, unsigned len, unsigned at, const char *want)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; want[i]; i++)
|
||||
if (at + i >= len || line[at + i] != want[i]) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void post_watch(char c)
|
||||
{
|
||||
static const char clean[] = " fail=0";
|
||||
if (c != '\n') {
|
||||
if (post_len < sizeof post_line) post_line[post_len++] = c;
|
||||
return;
|
||||
}
|
||||
if (text_at(post_line, post_len, 0, "PARITY:V4_POST ")) {
|
||||
post_seen = 1;
|
||||
post_clean = post_len >= sizeof clean - 1 && text_at(post_line, post_len, post_len - (unsigned)(sizeof clean - 1), clean);
|
||||
}
|
||||
post_len = 0;
|
||||
}
|
||||
|
||||
/* The boot is the node's neighbour on two of its ports. On port 0 it is
|
||||
* the kernel: the node writes the number of a request there (ENGINE.md
|
||||
* 3.3) -- for a block (blocks.h), or for one of the host's words. On port
|
||||
@@ -120,7 +90,10 @@ static void post_watch(char c)
|
||||
/* What the kernel keeps of the node's block window (blocks.h). */
|
||||
static v4_blocks boot_blocks;
|
||||
|
||||
int v4_boot_line(const v4_boot *b, const char *text, unsigned len)
|
||||
/* Hand the node a line and run it to its end. What it prints goes to the
|
||||
* console; or, if `keep` is given, into `keep`, at most `cap` characters,
|
||||
* and none of it is shown: *printed is then how many it printed in all. */
|
||||
static int run_line(const v4_boot *b, const char *text, unsigned len, char *keep, unsigned cap, unsigned *printed)
|
||||
{
|
||||
static v4_message out, in; /* one line at a time: the boot is not re-entered */
|
||||
v4_node *n = b->n;
|
||||
@@ -155,8 +128,8 @@ int v4_boot_line(const v4_boot *b, const char *text, unsigned len)
|
||||
if (v4_message_type(&in) == V4_MSG_OUTPUT) {
|
||||
for (i = 0; i < chars; i++) {
|
||||
char c = v4_message_char(&in, i);
|
||||
post_watch(c);
|
||||
b->out(&c, 1);
|
||||
if (!keep) b->out(&c, 1);
|
||||
else { if (*printed < cap) keep[*printed] = c; (*printed)++; }
|
||||
}
|
||||
} else if (v4_message_type(&in) == V4_MSG_DONE) {
|
||||
return (int)in.word[V4_MSG_HEADER];
|
||||
@@ -185,6 +158,27 @@ int v4_boot_line(const v4_boot *b, const char *text, unsigned len)
|
||||
}
|
||||
}
|
||||
|
||||
int v4_boot_line(const v4_boot *b, const char *text, unsigned len)
|
||||
{
|
||||
return run_line(b, text, len, 0, 0u, 0);
|
||||
}
|
||||
|
||||
#if V4_POST_AT_BOOT
|
||||
/* POST's host (post.h): a line is handed to the node as any line is, and
|
||||
* what the node prints is kept for the runner and not shown. */
|
||||
static int post_line(void *self, const char *text, unsigned text_len, char *out, unsigned cap, unsigned *len)
|
||||
{
|
||||
int how;
|
||||
*len = 0;
|
||||
how = run_line((const v4_boot *)self, text, text_len, out, cap, len);
|
||||
return (how == V4_TEXT_QUIT || how == V4_TEXT_COMPLETED || how == V4_TEXT_ERROR) ? how : -1;
|
||||
}
|
||||
static void post_say(void *self, const char *text, unsigned len)
|
||||
{
|
||||
((const v4_boot *)self)->out(text, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ---- one capsule --------------------------------------------------------- */
|
||||
|
||||
static void say_where(const v4_boot *b, const char *name, uint32_t block, uint32_t line)
|
||||
@@ -345,7 +339,6 @@ int v4_boot_run(const v4_boot *b)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
post_len = 0; post_seen = 0; post_clean = 0;
|
||||
/* a node is born with nothing in it, and is sent the nucleus */
|
||||
if (!v4_image_born(b->n, b->es, b->h, b->im)) {
|
||||
say(b, "V4: the nucleus is not for this build of the engine\nPARITY:FAIL\nPOST: FAILED\n");
|
||||
@@ -375,16 +368,24 @@ int v4_boot_run(const v4_boot *b)
|
||||
for (i = 0; i < sizeof boot_capsules / sizeof boot_capsules[0]; i++)
|
||||
if (!load_capsule(b, boot_capsules[i])) { say(b, "PARITY:FAIL\nPOST: FAILED\n"); return 0; }
|
||||
#if V4_POST_AT_BOOT
|
||||
if (!post_seen || !post_clean) {
|
||||
say(b, post_seen ? "V4: POST reported failures\n" : "V4: POST did not report\n");
|
||||
say(b, "PARITY:FAIL\nPOST: FAILED\n");
|
||||
return 0;
|
||||
{
|
||||
v4_post_host host;
|
||||
v4_post_tally tally;
|
||||
host.self = (void *)b; host.n = b->n; host.line = post_line; host.say = post_say;
|
||||
if (!v4_post_run(&host, v4_post_cases, v4_post_case_count, &tally)) {
|
||||
say(b, "V4: POST reported failures\nPARITY:FAIL\nPOST: FAILED\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The kernel's words and the capsules are the system: COLD comes back
|
||||
* to here, and FORGET will not go below it. */
|
||||
/* The kernel's words, the capsules and what POST's cases defined are
|
||||
* the system, as in v3: COLD comes back to here, and FORGET will not go
|
||||
* below it. */
|
||||
v4_image_seal(b->n, b->im);
|
||||
say(b, "PARITY:V4_SYSTEM word_count="); say_dec(b, word_count(b->n, b->im));
|
||||
say(b, " dict_hash="); say_hex(b, v4_boot_dict_hash(b->n, b->im));
|
||||
say(b, "\n");
|
||||
|
||||
#if V4_POST_AT_BOOT
|
||||
say(b, "PARITY:OK\nPOST: PASSED\n");
|
||||
|
||||
@@ -877,7 +877,7 @@ const v4_post_case v4_post_cases[] = {
|
||||
{ "-TRAILING.empty", l318, 1u, V4_POST_STACK, 0, 0u, "\012", 1u },
|
||||
{ "CMOVE.basic", l319, 2u, V4_POST_STACK, 0, 0u, "65 66 \012", 7u },
|
||||
{ "CMOVE.empty", l320, 1u, V4_POST_STACK, 0, 0u, "", 0u },
|
||||
{ ">IN.initial", l321, 1u, V4_POST_STACK, 0, 0u, "9 \012", 3u },
|
||||
{ ">IN.initial", l321, 1u, V4_POST_STACK, 0, 0u, "6 \012", 3u },
|
||||
{ ">IN.advances", l322, 1u, V4_POST_STACK, 0, 0u, "0 \012", 3u },
|
||||
{ "..positive", l323, 1u, V4_POST_STACK, 0, 0u, "42 \012", 4u },
|
||||
{ "..negative", l324, 1u, V4_POST_STACK, 0, 0u, "-42 \012", 5u },
|
||||
|
||||
@@ -65,8 +65,6 @@
|
||||
#define SRC (BVARS + 8)
|
||||
#define SRC_HOOK (BVARS + 9)
|
||||
#define ACL_HOOK (BUF0_W - 6) /* the xt of the access control recheck word, or 0 */
|
||||
#define EMIT_HOOK (BUF0_W - 7) /* the xt of a word EMIT gives its character to, or 0: the console */
|
||||
#define CATCH (BUF0_W - 8) /* non-zero: a line's error is recorded here, -1, and the line ends " ok" */
|
||||
#define LINE_STATUS (BUF0_W - 9) /* how the last line ended: 0 QUIT, 1 completed, 2 an error */
|
||||
#define PORT (BUF0_W - 32) /* the node's ports (node.h): V4_PORTS of them, then "any port" and "which port". Port 0 is where its requests go. */
|
||||
#define CONSOLE (BUF0_W - 16) /* the node what this one prints is sent to; 0: whoever sent the text being served */
|
||||
@@ -175,8 +173,6 @@ static int host_load(v4_text *tx, v4_node *n, const char *const *files, unsigned
|
||||
v4_text_constant(tx, "BLK", BLK);
|
||||
v4_text_constant(tx, "(SRC)", SRC);
|
||||
v4_text_constant(tx, "(SRC-HOOK)", SRC_HOOK);
|
||||
v4_text_constant(tx, "(EMIT-HOOK)", EMIT_HOOK);
|
||||
v4_text_constant(tx, "(CATCH)", CATCH);
|
||||
v4_text_constant(tx, "(LINE-STATUS)", LINE_STATUS);
|
||||
v4_text_constant(tx, "(PORT)", PORT);
|
||||
v4_text_constant(tx, "(ME)", ME);
|
||||
|
||||
@@ -1277,6 +1277,11 @@ int main(void)
|
||||
post_lost = 0;
|
||||
}
|
||||
|
||||
/* ---- nothing of POST is on the node (NUCLEUS.md 6.3) ---- */
|
||||
boot();
|
||||
CHECK(is(say("(CATCH)\n"), "UNKNOWN WORD: '(CATCH)'\n ERROR\nok> ") && is(say("(EMIT-HOOK)\n"), "UNKNOWN WORD: '(EMIT-HOOK)'\n ERROR\nok> ")
|
||||
&& is(say("T{\n"), "UNKNOWN WORD: 'T{'\n ERROR\nok> "), "the nucleus has neither of the variables the POST capsule needed, nor its words");
|
||||
|
||||
/* ---- storage that refuses a write (MESH.md 8.2) ---- */
|
||||
boot();
|
||||
CHECK(is(say(REFUSING_FIRST " BLOCK DROP UPDATE SAVE-BUFFERS 65 EMIT\n"), "Storage refused\n ERROR\nok> "), "a write storage will not take says so, and the prompt returns");
|
||||
@@ -1450,7 +1455,7 @@ int main(void)
|
||||
boot_bare();
|
||||
CHECK(load_source("tools.fth"), "tools.fth compiles, every line of it");
|
||||
CHECK(is(say(": SQ DUP * ; SEE SQ\n"), ": SQ\n dup call * \n ; \n ok\nok> "), "a definition: an in-line word, a call by name, the return");
|
||||
CHECK(is(say("SEE DUP\n"), ": DUP\n dup ; \n ok\nok> ") && is(say("SEE EMIT\n"), out) && strncmp(out, ": EMIT\n @p ", 12) == 0 && strstr(out, " b! @b \n if ") && strstr(out, " pop a! ; \n"),
|
||||
CHECK(is(say("SEE DUP\n"), ": DUP\n dup ; \n ok\nok> ") && is(say("SEE EMIT\n"), out) && strncmp(out, ": EMIT\n @p 255 and ", 20) == 0 && strstr(out, " pop a! ; \n"),
|
||||
"the capsule's own words; a literal's value follows its @p");
|
||||
CHECK(is(say("VARIABLE V 7 V ! SEE V\n"), ": V\n data: 7 \n ok\nok> ") && is(say("5 CONSTANT K SEE K\n"), ": K\n data: 5 \n ok\nok> "), "a variable and a constant show what they hold");
|
||||
CHECK(is(say(": IM 1 ; IMMEDIATE SEE IM\n"), ": IM\n @p 1 ; \nIMMEDIATE\n ok\nok> "), "an immediate word says so");
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "v4/manage.h"
|
||||
#include "v4/blocks.h"
|
||||
#include "v4/message.h"
|
||||
#include "v4/post.h"
|
||||
#include "v4/text.h"
|
||||
#include "block_subsystem.h"
|
||||
#include <stdio.h>
|
||||
@@ -154,7 +155,6 @@ static int host_open(void *self, const char *name, unsigned len)
|
||||
(void)self;
|
||||
if (len == 17 && memcmp(name, "v4:nucleus-64.f18", 17) == 0) { hera_reads.is_f18 = 1; hera_reads.cells_at = 0; return 1; }
|
||||
if (len == 14 && memcmp(name, "v4:forth79.4th", 14) == 0) return read_file(&hera_reads, "forth79.4th");
|
||||
if (len == 13 && memcmp(name, "v4:post79.4th", 13) == 0) return read_file(&hera_reads, "post79.4th");
|
||||
return 0;
|
||||
}
|
||||
static int host_cell(void *self, v4_cell *w)
|
||||
@@ -277,6 +277,30 @@ static const char *tell(v4_cell node, const char *text)
|
||||
}
|
||||
static int told(v4_cell node, const char *text) { return tell(node, text)[0] == 0 && ended == 1 && ended_how == V4_TEXT_COMPLETED; }
|
||||
|
||||
/* POST's host, for the node numbered 10 (v4/include/v4/post.h): a line is
|
||||
* told to it from the console, and what it prints is handed to the runner. */
|
||||
static int post_line(void *self, const char *text, unsigned text_len, char *out, unsigned cap, unsigned *len)
|
||||
{
|
||||
static char line[V4_MSG_MAX_CHARS + 1];
|
||||
const char *r;
|
||||
(void)self;
|
||||
*len = 0;
|
||||
if (text_len > V4_MSG_MAX_CHARS) return -1;
|
||||
memcpy(line, text, text_len); line[text_len] = 0;
|
||||
r = tell(10, line);
|
||||
if (ended != 1 || ended_from != 10) return -1;
|
||||
*len = printed_len;
|
||||
memcpy(out, r, printed_len < cap ? printed_len : cap);
|
||||
return (int)ended_how;
|
||||
}
|
||||
static char post_said[2048];
|
||||
static unsigned post_said_len;
|
||||
static void post_say(void *self, const char *text, unsigned len)
|
||||
{
|
||||
(void)self;
|
||||
if (post_said_len + len < sizeof post_said) { memcpy(post_said + post_said_len, text, len); post_said_len += len; post_said[post_said_len] = 0; }
|
||||
}
|
||||
|
||||
/* Every line of a capsule of FORTH blocks, told to a node from the console:
|
||||
* how many lines did not complete. */
|
||||
static unsigned load(v4_cell node, const char *file)
|
||||
@@ -376,7 +400,16 @@ int main(void)
|
||||
}
|
||||
CHECK(strcmp(tell(10, "NODE-ME ."), "0 ") == 0 && refused == 0, "it asks where it is, and is answered");
|
||||
CHECK(load(10, "forth79.4th") == 0, "it takes in FORTH-79");
|
||||
CHECK(load(10, "post79.4th") == 0 && post_passed[10] == 1 && post_other == 0, "and passes POST");
|
||||
{
|
||||
v4_post_host host;
|
||||
v4_post_tally tally;
|
||||
host.self = 0; host.n = node_numbered(10); host.line = post_line; host.say = post_say;
|
||||
CHECK(v4_post_run(&host, v4_post_cases, v4_post_case_count, &tally) && tally.tests == 538 && tally.pass == 538 && tally.fail == 0
|
||||
&& strstr(post_said, "PARITY:V4_POST tests=538 pass=538 fail=0\n") != NULL && strstr(post_said, "POST FAIL") == NULL,
|
||||
"and passes POST, which the kernel runs on her: %u of %u, %u failed; \"%s\"", tally.pass, tally.tests, tally.fail, post_said);
|
||||
}
|
||||
CHECK(strstr(tell(10, "T{"), "UNKNOWN WORD") != NULL, "nothing of POST's harness is on her: \"%s\"", printed);
|
||||
CHECK(strcmp(tell(10, "RS1"), "42 42 \n") == 0, "what POST's cases defined is: \"%s\"", printed);
|
||||
CHECK(load(10, "hera.4th") == 0, "and its own capsule, which makes it Hera");
|
||||
CHECK(told(10, "(SEAL)"), "that is the system it comes back to");
|
||||
|
||||
@@ -387,9 +420,10 @@ int main(void)
|
||||
CHECK(ended == 1 && ended_how == V4_TEXT_COMPLETED && ended_from == 10, "Hera births four nodes and joins them: \"%s\"", r);
|
||||
}
|
||||
CHECK(born_count == 4 && refused == 0, "four nodes were asked for: %u", born_count);
|
||||
CHECK(post_passed[10] == 1 && post_passed[11] == 0 && post_passed[12] == 0 && post_passed[13] == 0 && post_passed[14] == 0 && post_other == 0,
|
||||
"a node she births is not POSTed: POST is the kernel's, once, on Hera: %u; %u %u %u %u, %u failed",
|
||||
CHECK(post_passed[10] == 0 && post_passed[11] == 0 && post_passed[12] == 0 && post_passed[13] == 0 && post_passed[14] == 0 && post_other == 0,
|
||||
"a node she births is not POSTed, and no node prints a POST tally: POST is the kernel's, once, on Hera: %u %u %u %u %u, %u failed",
|
||||
post_passed[10], post_passed[11], post_passed[12], post_passed[13], post_passed[14], post_other);
|
||||
CHECK(strstr(tell(10, "COLD"), "Cold Start") != NULL && strcmp(tell(10, "RS1"), "42 42 \n") == 0, "COLD on Hera comes back to a system that has what POST's cases defined: \"%s\"", printed);
|
||||
CHECK(parity_count == 4 && parity_number[0] == 11 && parity_number[1] == 12 && parity_number[2] == 13 && parity_number[3] == 14, "the parity of each was recorded: %u", parity_count);
|
||||
CHECK(parity_hash[0] == parity_hash[1] && parity_hash[1] == parity_hash[2] && parity_hash[2] == parity_hash[3],
|
||||
"and their dictionary hashes are the same: %016llx %016llx %016llx %016llx",
|
||||
|
||||
+6
-2
@@ -240,10 +240,14 @@ ANSI = re.compile(r"\x1b\[[0-9;]*m")
|
||||
def run_v3(v3, cases):
|
||||
"""Runs the cases in one session. Returns a list, one entry per case:
|
||||
None if v3 did not get through it, else (error, stack, output)."""
|
||||
script = [": T| ; IMMEDIATE", ": TCLR BEGIN DEPTH WHILE DROP REPEAT ;"]
|
||||
# The lines are run as the kernel sends them to the node: without the
|
||||
# "T| " each began with when they were lines of a capsule. A case that
|
||||
# looks at where it is in its line (>IN) depends on it.
|
||||
script = [": TCLR BEGIN DEPTH WHILE DROP REPEAT ;"]
|
||||
for n, case in enumerate(cases):
|
||||
script.append('TCLR DECIMAL FORTH DEFINITIONS ." [[B%d]]"' % n)
|
||||
script.extend(case["lines"])
|
||||
assert all(line.startswith("T| ") for line in case["lines"]), case
|
||||
script.extend(line[3:] for line in case["lines"])
|
||||
script.append('." [[E%d]]" BASE @ DECIMAL .S BASE ! ." [[S%d]]"' % (n, n))
|
||||
script.append("BYE")
|
||||
done = subprocess.run([v3, "--log-none"], input=("\n".join(script) + "\n").encode("latin-1"),
|
||||
|
||||
@@ -112,7 +112,9 @@ STANDARD = {
|
||||
"TYPE.basic_string": dict(text="72 PAD C! 105 PAD 1+ C! PAD 2 TYPE CR", out="Hi\n", why=D1 + "; and " + RS),
|
||||
"TYPE.numbers": dict(text="49 PAD C! 50 PAD 1+ C! PAD 2 TYPE CR", out="12\n", why=D1 + "; and " + RS),
|
||||
|
||||
">IN.initial": dict(out="9 \n", why="FORTH-79: >IN is the offset into the input, 9 here; v3 prints an address"),
|
||||
# 6: the line is ">IN @ . CR" and >IN is read when "@" has been taken with the blank after it. It was 9
|
||||
# while the cases were a capsule, whose lines each began "T| " (until MESH.md step 6b).
|
||||
">IN.initial": dict(out="6 \n", why="FORTH-79: >IN is the offset into the input, 6 here; v3 prints an address"),
|
||||
|
||||
"WORD.empty_input": None, "WORD.space_delim": None, "WORD.newline_delim": None, "WORD.tab_delim": None,
|
||||
"WORD.comma_delim": None, "WORD.skip_leading": None, "WORD.single_char": None, "WORD.long_word": None,
|
||||
|
||||
Reference in New Issue
Block a user