diff --git a/capsules/BLOCK_MAP.md b/capsules/BLOCK_MAP.md index 2ab3a33f..530c8dd7 100644 --- a/capsules/BLOCK_MAP.md +++ b/capsules/BLOCK_MAP.md @@ -1,5 +1,5 @@ # Capsule Block Manifest — Auto-generated - + @@ -30,6 +30,7 @@ | `turtle.4th` | 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108 | `0x4d470418ca543365` | n/a | | `user-font-demo.4th` | 4200, 4201, 4202 | `0xce1fd7d1b581a56d` | n/a | | `v4:forth79.4th` | 6000 | `0xa4b74bdc7deaf204` | 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 | `0x24df7b11992128ed` | 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 | @@ -368,10 +369,74 @@ | 5114 | `sdk.4th` | `0x008fdbbb62c94a3a` | ok | | 5115 | `sdk.4th` | `0x008fdbbb62c94a3a` | ok | | 6000 | `v4:forth79.4th` | `0xa4b74bdc7deaf204` | ok | +| 7000 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7001 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7002 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7003 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7004 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7005 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7006 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7007 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7008 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7009 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7010 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7011 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7012 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7013 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7014 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7015 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7016 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7017 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7018 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7019 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7020 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7021 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7022 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7023 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7024 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7025 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7026 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7027 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7028 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7029 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7030 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7031 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7032 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7033 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7034 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7035 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7036 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7037 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7038 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7039 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7040 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7041 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7042 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7043 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7044 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7045 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7046 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7047 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7048 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7049 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7050 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7051 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7052 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7053 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7054 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7055 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7056 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7057 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7058 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7059 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7060 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7061 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7062 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | +| 7063 | `v4:post79.4th` | `0x24df7b11992128ed` | ok | ## Conflicts None. --- -*37 capsule(s) scanned. Re-run `mkcapsule --manifest ` to refresh.* +*38 capsule(s) scanned. Re-run `mkcapsule --manifest ` to refresh.* diff --git a/capsules/v4/post79.4th b/capsules/v4/post79.4th new file mode 100644 index 00000000..d8d01355 --- /dev/null +++ b/capsules/v4/post79.4th @@ -0,0 +1,1787 @@ +Block 7000 +( post79.4th -- POST for the FORTH-79 Required Word Set on v4. ) +( Generated by v4/tools/mkpost.py from v3's POST cases: do not ) +( edit. docs/v4.0.0/NUCLEUS.md section 6. ) +VARIABLE T# VARIABLE TPASS VARIABLE TFAIL VARIABLE TOPEN +VARIABLE TBAD VARIABLE TWANT VARIABLE TLEN VARIABLE TSUM +VARIABLE TDEP VARIABLE TBASE +CREATE TBUF 64 ALLOT CREATE TSTK 16 ALLOT CREATE TNAME 8 ALLOT +0 T# ! 0 TPASS ! 0 TFAIL ! 0 TOPEN ! 10 TBASE ! +: TB ( -- baddr ) TBUF 4 * ; +: TN ( -- baddr ) TNAME 4 * ; +( T-EMIT is given every character a case prints: the first 255 ) +( are kept, all are counted and summed. ) +: T-EMIT ( c -- ) + DUP TSUM @ 31 * + 16777215 AND TSUM ! + TLEN @ 255 < IF TB TLEN @ + C! ELSE DROP THEN 1 TLEN +! ; +Block 7001 +: T-CLEAR ( i*x -- ) BEGIN DEPTH WHILE DROP REPEAT ; +: T. ( n -- ) 0 <# #S #> TYPE ; +( what a failing case printed, and the stack it left ) +: T-SHOW ( -- ) + ." out<" TB TLEN @ 255 MIN TYPE ." > stack<" + TDEP @ BEGIN DUP WHILE 1- DUP TSTK + @ . REPEAT DROP ." >" ; +( the verdict on the case that is open, if one is ) +: T-CLOSE ( -- ) + TOPEN @ IF + (CATCH) @ -1 = TWANT @ = 0= IF 1 TBAD ! THEN + TBAD @ IF 1 TFAIL +! + ." POST FAIL: " TN COUNT TYPE T-SHOW CR + ELSE 1 TPASS +! THEN + 0 TOPEN ! 0 (CATCH) ! TBASE @ BASE ! + THEN ; +Block 7002 +( T{ name begin a case: clean stack, errors caught ) +: T{ ( i*x -- ) T-CLOSE T-CLEAR + BL WORD COUNT 31 MIN DUP TN C! TN 1+ SWAP CMOVE + 1 T# +! 1 TOPEN ! 0 TBAD ! 0 TWANT ! 0 TLEN ! 0 TSUM ! + 0 TDEP ! 1 (CATCH) ! ; +( T| ... a line of the case, what it prints captured ) +: T| ' T-EMIT (EMIT-HOOK) ! ; IMMEDIATE +: T-END ( -- ) 0 (EMIT-HOOK) ! BASE @ TBASE ! DECIMAL ; +( -> ... the case is over: set its stack aside, top first ) +: -> ( i*x -- ) T-END 0 + BEGIN DEPTH 1 > WHILE + DUP 16 < IF SWAP OVER TSTK + ! ELSE SWAP DROP 1 TBAD ! THEN + 1+ REPEAT + 16 MIN TDEP ! ; +( ->ERR the case is over, and must have ended in an error ) +: ->ERR ( i*x -- ) T-END -1 TWANT ! T-CLEAR ; +Block 7003 +( ... }T the stack the case must have left, in order ) +: }T ( i*x -- ) + DEPTH TDEP @ = 0= IF 1 TBAD ! T-CLEAR EXIT THEN + 0 BEGIN DEPTH 1 > WHILE + SWAP OVER TSTK + @ = 0= IF 1 TBAD ! THEN 1+ REPEAT DROP ; +( len sum T= what the case must have printed ) +: T= ( len sum -- ) TSUM @ = 0= IF 1 TBAD ! THEN + TLEN @ = 0= IF 1 TBAD ! THEN ; +( the tally; a failure is an error, which ends the boot ) +: T-REPORT ( -- ) T-CLOSE 0 (CATCH) ! DECIMAL + ." PARITY:V4_POST tests=" T# @ T. ." pass=" TPASS @ T. + ." fail=" TFAIL @ T. CR + TFAIL @ IF -1 NODE-ERROR ! THEN ; +Block 7004 +T{ DUP.basic +T| 5 DUP . . CR +-> }T 5 16397428 T= +T{ DUP.zero +T| 0 DUP . . CR +-> }T 5 11775018 T= +T{ DUP.negative +T| -42 DUP . . CR +-> }T 9 15322016 T= +T{ DUP.max_int +T| 2147483647 DUP . . CR +-> }T 23 2334858 T= +T{ DUP.min_int +T| -2147483648 DUP . . CR +-> }T 25 386046 T= +Block 7005 +T{ DUP.empty_stack +T| DUP +->ERR +T{ DROP.basic +T| 5 7 DROP . CR +-> }T 3 51935 T= +T{ DROP.zero +T| 42 0 DROP . CR +-> }T 4 1598184 T= +T{ DROP.negative +T| 10 -5 DROP . CR +-> }T 4 1506889 T= +T{ DROP.double_drop +T| 1 2 3 DROP DROP . CR +-> }T 3 48091 T= +Block 7006 +T{ DROP.triple_drop +T| 1 2 3 4 DROP DROP DROP . CR +-> }T 3 48091 T= +T{ DROP.sequential +T| 5 DROP 6 DROP 7 . CR +-> }T 3 53857 T= +T{ DROP.single_item +T| 99 DROP DEPTH . CR +-> }T 3 47130 T= +T{ DROP.depth_change +T| DEPTH 1 2 DROP DEPTH SWAP - . CR +-> 0 }T 3 48091 T= +T{ DROP.preserve_depth +T| DEPTH 5 6 DROP DROP DEPTH = . CR +-> }T 3 47130 T= +Block 7007 +T{ DROP.max_int +T| 2147483647 DROP DEPTH . CR +-> }T 3 47130 T= +T{ DROP.min_int +T| -2147483648 DROP DEPTH . CR +-> }T 3 47130 T= +T{ DROP.with_dup +T| 5 DUP DROP . CR +-> }T 3 51935 T= +T{ DROP.with_swap +T| 1 2 SWAP DROP . CR +-> }T 3 49052 T= +T{ DROP.complex +T| 1 2 3 ROT DROP SWAP DROP . CR +-> }T 3 50013 T= +Block 7008 +T{ DROP.empty_stack +T| DROP +->ERR +T{ SWAP.basic +T| 5 7 SWAP . . CR +-> }T 5 16399350 T= +T{ SWAP.same_values +T| 42 42 SWAP . . CR +-> }T 7 15838026 T= +T{ SWAP.zero_nonzero +T| 0 99 SWAP . . CR +-> }T 6 12996858 T= +T{ SWAP.negative +T| -5 10 SWAP . . CR +-> }T 7 12792257 T= +Block 7009 +T{ SWAP.one_item +T| 42 SWAP +->ERR +T{ SWAP.empty_stack +T| SWAP +->ERR +T{ OVER.basic +T| 5 7 OVER . . . CR +-> }T 7 6011851 T= +T{ OVER.zeros +T| 0 0 OVER . . . CR +-> }T 7 7986234 T= +T{ OVER.mixed +T| -1 42 OVER . . . CR +-> }T 10 1455732 T= +Block 7010 +T{ OVER.one_item +T| 42 OVER +->ERR +T{ OVER.empty_stack +T| OVER +->ERR +T{ ROT.basic +T| 1 2 3 ROT . . . CR +-> }T 7 9069952 T= +T{ ROT.zeros +T| 0 0 0 ROT . . . CR +-> }T 7 7986234 T= +T{ ROT.mixed +T| -1 0 1 ROT . . . CR +-> }T 8 201263 T= +Block 7011 +T{ ROT.two_items +T| 1 2 ROT +->ERR +T{ ROT.one_item +T| 42 ROT +->ERR +T{ ROT.empty_stack +T| ROT +->ERR +T{ DEPTH.empty +T| DEPTH . CR +-> }T 3 47130 T= +T{ DEPTH.one_item +T| 42 DEPTH . CR +-> 42 }T 3 48091 T= +Block 7012 +T{ DEPTH.multiple +T| 1 2 3 DEPTH . CR +-> 1 2 3 }T 3 50013 T= +T{ PICK.pick_0 +T| 1 2 3 0 PICK . CR +-> 1 2 3 }T 3 50013 T= +T{ PICK.pick_1 +T| 1 2 3 1 PICK . CR +-> 1 2 3 }T 3 49052 T= +T{ PICK.pick_2 +T| 1 2 3 2 PICK . CR +-> 1 2 3 }T 3 48091 T= +T{ ROLL.roll_1 +T| 1 2 3 1 ROLL . . . CR +-> }T 7 9069952 T= +Block 7013 +T{ ROLL.roll_2 +T| 1 2 3 2 ROLL . . . CR +-> }T 7 7380224 T= +T{ ?DUP.nonzero +T| 42 ?DUP . . CR +-> }T 7 15838026 T= +T{ ?DUP.negative +T| -5 ?DUP . . CR +-> }T 7 12677898 T= +T{ ?DUP.zero +T| 0 ?DUP DEPTH . CR +-> 0 }T 3 48091 T= +T{ ?DUP.empty_stack +T| ?DUP +->ERR +Block 7014 +T{ >R.basic +T| 42 >R R@ . R> . CR +-> }T 7 15838026 T= +T{ >R.zero +T| 0 >R R@ . R> . CR +-> }T 5 11775018 T= +T{ >R.negative +T| -123 >R R@ . R> . CR +-> }T 11 14101290 T= +T{ >R.multiple +T| 1 2 >R >R R@ . R> . R@ . R> . CR +-> }T 9 12265744 T= +T{ >R.empty_stack +T| >R +->ERR +Block 7015 +T{ R>.basic +T| 42 >R R> . CR +-> }T 4 1598184 T= +T{ R>.lifo_order +T| 1 2 >R >R R> . R> . CR +-> }T 5 12700461 T= +T{ R>.empty_rstack +T| R> +->ERR +T{ R@.basic +T| 42 >R R@ . R> DROP CR +-> }T 4 1598184 T= +T{ R@.non_destructive +T| 99 >R R@ R@ = . R> DROP CR +-> }T 4 1388686 T= +Block 7016 +T{ R@.empty_rstack +T| R@ +->ERR +T{ !.basic +T| 42 HERE ! HERE @ . CR +-> }T 4 1598184 T= +T{ !.zero +T| 0 HERE ! HERE @ . CR +-> }T 3 47130 T= +T{ !.negative +T| -999 HERE ! HERE @ . CR +-> }T 6 529078 T= +T{ !.overwrite +T| 111 HERE ! 222 HERE ! HERE @ . CR +-> }T 5 14160220 T= +Block 7017 +T{ !.max_int +T| 2147483647 HERE ! HERE @ . CR +-> }T 12 4848918 T= +T{ !.min_int +T| -2147483648 HERE ! HERE @ . CR +-> }T 13 5383556 T= +T{ !.empty_stack +T| ! +->ERR +T{ !.one_item +T| 42 ! +->ERR +T{ @.after_store +T| 123 HERE ! HERE @ . CR +-> }T 5 13237660 T= +Block 7018 +T{ @.multiple_reads +T| 456 HERE ! HERE @ HERE @ = . CR +-> }T 4 1388686 T= +T{ @.empty_stack +T| @ +->ERR +T{ C!.basic +T| 65 HERE C! HERE C@ . CR +-> }T 4 1660649 T= +T{ C!.zero +T| 0 HERE C! HERE C@ . CR +-> }T 3 47130 T= +T{ C!.high_byte +T| 255 HERE C! HERE C@ . CR +-> }T 5 14252476 T= +Block 7019 +T{ C!.truncation +T| 256 HERE C! HERE C@ . CR +-> }T 3 47130 T= +T{ C@.after_cstore +T| 97 HERE C! HERE C@ . CR +-> }T 4 1751944 T= +T{ C@.zero_byte +T| 0 HERE C! HERE C@ . CR +-> }T 3 47130 T= +T{ ,.basic +T| 42 , HERE 8 - @ . CR +-> }T 4 1598184 T= +T{ ,.negative +T| -999 , HERE 8 - @ . CR +-> }T 6 529078 T= +Block 7020 +T{ HERE.basic +T| HERE HERE = . CR +-> }T 4 1388686 T= +T{ HERE.after_comma +T| HERE 42 , HERE SWAP - 1 CELLS = 0 SWAP / +-> 0 }T 0 0 T= +T{ ALLOT.basic +T| HERE 10 ALLOT HERE SWAP - . CR +-> }T 4 1506889 T= +T{ ALLOT.zero +T| HERE 0 ALLOT HERE SWAP - . CR +-> }T 3 47130 T= +T{ ALLOT.negative +T| HERE -4 ALLOT HERE SWAP - . CR +-> }T 4 1391569 T= +Block 7021 +T{ PAD.basic +T| PAD PAD = . CR +-> }T 4 1388686 T= +T{ PAD.different_from_here +T| PAD HERE = . CR +-> }T 3 47130 T= +T{ +!.basic +T| 10 HERE ! 5 HERE +! HERE @ . CR +->ERR +T{ +!.by_zero +T| 42 HERE ! 0 HERE +! HERE @ . CR +->ERR +T{ +!.negative +T| 10 HERE ! -3 HERE +! HERE @ . CR +->ERR +Block 7022 +T{ +!.accumulate +T| 0 HERE ! 1 HERE +! 2 HERE +! 3 HERE +! HERE @ . CR +->ERR +T{ +!.empty_stack +T| +! +->ERR +T{ FILL.basic +T| HERE 8 65 FILL HERE C@ . HERE 1+ C@ . CR +-> }T 7 14524330 T= +T{ FILL.zero_n +T| HERE 0 88 FILL +-> }T 0 0 T= +T{ FILL.zero_byte +T| HERE 4 0 FILL HERE C@ . CR +-> }T 3 47130 T= +Block 7023 +T{ FILL.empty_stack +T| FILL +->ERR +T{ MOVE.basic +T| HERE 65 OVER C! HERE 1+ 66 OVER C! HERE HERE 16 + 2 MOVE HERE +T| 16 + C@ . HERE 17 + C@ . CR +-> 302 303 }T 7 14525291 T= +T{ MOVE.zero_n +T| HERE HERE 8 + 0 MOVE +-> }T 0 0 T= +T{ MOVE.empty_stack +T| MOVE +->ERR +T{ +.basic +T| 5 7 + . CR +-> }T 4 1508811 T= +Block 7024 +T{ +.zero_add +T| 42 0 + . CR +-> }T 4 1598184 T= +T{ +.negative +T| -5 3 + . CR +-> }T 4 1389647 T= +T{ +.both_negative +T| -5 -3 + . CR +-> }T 4 1395413 T= +T{ +.overflow +T| 2147483647 1 + . CR +-> }T 12 4849879 T= +T{ +.underflow +T| -2147483648 -1 + . CR +-> }T 13 5384517 T= +Block 7025 +T{ +.empty_stack +T| + +->ERR +T{ +.one_item +T| 42 + +->ERR +T{ -.basic +T| 10 3 - . CR +-> }T 3 53857 T= +T{ -.zero_sub +T| 42 0 - . CR +-> }T 4 1598184 T= +T{ -.from_zero +T| 0 5 - . CR +-> }T 4 1392530 T= +Block 7026 +T{ -.negative +T| 5 -3 - . CR +-> }T 3 54818 T= +T{ -.same_values +T| 42 42 - . CR +-> }T 3 47130 T= +T{ -.overflow +T| -2147483648 1 - . CR +-> }T 13 5384517 T= +T{ -.underflow +T| 2147483647 -1 - . CR +-> }T 12 4849879 T= +T{ -.empty_stack +T| - +->ERR +Block 7027 +T{ -.one_item +T| 42 - +->ERR +T{ *.basic +T| 6 7 * . CR +-> }T 4 1598184 T= +T{ *.by_zero +T| 42 0 * . CR +-> }T 3 47130 T= +T{ *.by_one +T| 42 1 * . CR +-> }T 4 1598184 T= +T{ *.by_negative +T| 6 -7 * . CR +-> }T 5 9602197 T= +Block 7028 +T{ *.negative_negative +T| -6 -7 * . CR +-> }T 4 1598184 T= +T{ *.large_numbers +T| 32767 2 * . CR +-> }T 7 273505 T= +T{ *.overflow +T| 65536 65536 * . CR +-> }T 12 6984600 T= +T{ *.empty_stack +T| * +->ERR +T{ *.one_item +T| 42 * +->ERR +Block 7029 +T{ /.basic +T| 15 3 / . CR +-> }T 3 51935 T= +T{ /.by_one +T| 42 1 / . CR +-> }T 4 1598184 T= +T{ /.negative_dividend +T| -15 3 / . CR +-> }T 4 1392530 T= +T{ /.negative_divisor +T| 15 -3 / . CR +-> }T 4 1392530 T= +T{ /.both_negative +T| -15 -3 / . CR +-> }T 3 51935 T= +Block 7030 +T{ /.truncation +T| 7 3 / . CR +-> }T 3 49052 T= +T{ /.by_zero +T| 42 0 / +->ERR +T{ /.empty_stack +T| / +->ERR +T{ /.one_item +T| 42 / +->ERR +T{ MOD.basic +T| 17 5 MOD . CR +-> }T 3 49052 T= +Block 7031 +T{ MOD.exact_division +T| 15 3 MOD . CR +-> }T 3 47130 T= +T{ MOD.by_one +T| 42 1 MOD . CR +-> }T 3 47130 T= +T{ MOD.negative_dividend +T| -17 5 MOD . CR +-> }T 4 1389647 T= +T{ MOD.negative_divisor +T| 17 -5 MOD . CR +-> }T 3 49052 T= +T{ MOD.small_by_large +T| 3 7 MOD . CR +-> }T 3 50013 T= +Block 7032 +T{ MOD.by_zero +T| 42 0 MOD +->ERR +T{ MOD.empty_stack +T| MOD +->ERR +T{ MOD.one_item +T| 42 MOD +->ERR +T{ /MOD.basic +T| 17 5 /MOD . . CR +-> }T 5 14547503 T= +T{ /MOD.exact +T| 15 3 /MOD . . CR +-> }T 5 16392623 T= +Block 7033 +T{ /MOD.negative +T| -17 5 /MOD . . CR +-> }T 7 5748361 T= +T{ /MOD.by_zero +T| 42 0 /MOD +->ERR +T{ /MOD.empty_stack +T| /MOD +->ERR +T{ /MOD.one_item +T| 42 /MOD +->ERR +T{ ABS.positive +T| 42 ABS . CR +-> }T 4 1598184 T= +Block 7034 +T{ ABS.negative +T| -42 ABS . CR +-> }T 4 1598184 T= +T{ ABS.zero +T| 0 ABS . CR +-> }T 3 47130 T= +T{ ABS.min_int +T| -2147483648 ABS . CR +-> }T 12 4849879 T= +T{ ABS.empty_stack +T| ABS +->ERR +T{ NEGATE.positive +T| 42 NEGATE . CR +-> }T 5 9602197 T= +Block 7035 +T{ NEGATE.negative +T| -42 NEGATE . CR +-> }T 4 1598184 T= +T{ NEGATE.zero +T| 0 NEGATE . CR +-> }T 3 47130 T= +T{ NEGATE.min_int +T| -2147483648 NEGATE . CR +-> }T 12 4849879 T= +T{ NEGATE.empty_stack +T| NEGATE +->ERR +T{ MIN.basic +T| 5 3 MIN . CR +-> }T 3 50013 T= +Block 7036 +T{ MIN.equal +T| 42 42 MIN . CR +-> }T 4 1598184 T= +T{ MIN.negative +T| -5 -3 MIN . CR +-> }T 4 1392530 T= +T{ MIN.mixed +T| -1 1 MIN . CR +-> }T 4 1388686 T= +T{ MIN.one_item +T| 42 MIN +->ERR +T{ MIN.empty_stack +T| MIN +->ERR +Block 7037 +T{ MAX.basic +T| 5 3 MAX . CR +-> }T 3 51935 T= +T{ MAX.equal +T| 42 42 MAX . CR +-> }T 4 1598184 T= +T{ MAX.negative +T| -5 -3 MAX . CR +-> }T 4 1390608 T= +T{ MAX.mixed +T| -1 1 MAX . CR +-> }T 3 48091 T= +T{ MAX.one_item +T| 42 MAX +->ERR +Block 7038 +T{ MAX.empty_stack +T| MAX +->ERR +T{ 1+.basic +T| 5 1+ . CR +-> }T 3 52896 T= +T{ 1+.zero +T| 0 1+ . CR +-> }T 3 48091 T= +T{ 1+.negative +T| -1 1+ . CR +-> }T 3 47130 T= +T{ 1+.chain +T| 3 1+ 1+ 1+ . CR +-> }T 3 52896 T= +Block 7039 +T{ 1+.overflow +T| 2147483647 1+ . CR +-> }T 12 4849879 T= +T{ 1+.empty_stack +T| 1+ +->ERR +T{ 1-.basic +T| 5 1- . CR +-> }T 3 50974 T= +T{ 1-.to_zero +T| 1 1- . CR +-> }T 3 47130 T= +T{ 1-.to_negative +T| 0 1- . CR +-> }T 4 1388686 T= +Block 7040 +T{ 1-.chain +T| 6 1- 1- 1- . CR +-> }T 3 50013 T= +T{ 1-.underflow +T| -2147483648 1- . CR +-> }T 13 5384517 T= +T{ 1-.empty_stack +T| 1- +->ERR +T{ 2+.basic +T| 5 2+ . CR +-> }T 3 53857 T= +T{ 2+.zero +T| 0 2+ . CR +-> }T 3 49052 T= +Block 7041 +T{ 2+.negative +T| -3 2+ . CR +-> }T 4 1388686 T= +T{ 2+.empty_stack +T| 2+ +->ERR +T{ 2-.basic +T| 7 2- . CR +-> }T 3 51935 T= +T{ 2-.zero +T| 2 2- . CR +-> }T 3 47130 T= +T{ 2-.negative +T| 0 2- . CR +-> }T 4 1389647 T= +Block 7042 +T{ 2-.empty_stack +T| 2- +->ERR +T{ AND.both_true +T| -1 -1 AND . CR +-> }T 4 1388686 T= +T{ AND.first_false +T| 0 -1 AND . CR +-> }T 3 47130 T= +T{ AND.second_false +T| -1 0 AND . CR +-> }T 3 47130 T= +T{ AND.both_false +T| 0 0 AND . CR +-> }T 3 47130 T= +Block 7043 +T{ AND.bitwise +T| 85 51 AND . CR +-> }T 4 1513616 T= +T{ AND.empty_stack +T| AND +->ERR +T{ AND.one_item +T| 42 AND +->ERR +T{ OR.both_true +T| -1 -1 OR . CR +-> }T 4 1388686 T= +T{ OR.first_false +T| 0 -1 OR . CR +-> }T 4 1388686 T= +Block 7044 +T{ OR.second_false +T| -1 0 OR . CR +-> }T 4 1388686 T= +T{ OR.both_false +T| 0 0 OR . CR +-> }T 3 47130 T= +T{ OR.bitwise +T| 85 51 OR . CR +-> }T 5 13213635 T= +T{ OR.empty_stack +T| OR +->ERR +T{ OR.one_item +T| 42 OR +->ERR +Block 7045 +T{ XOR.both_true +T| -1 -1 XOR . CR +-> }T 3 47130 T= +T{ XOR.first_false +T| 0 -1 XOR . CR +-> }T 4 1388686 T= +T{ XOR.second_false +T| -1 0 XOR . CR +-> }T 4 1388686 T= +T{ XOR.both_false +T| 0 0 XOR . CR +-> }T 3 47130 T= +T{ XOR.bitwise +T| 85 51 XOR . CR +-> }T 5 13177117 T= +Block 7046 +T{ XOR.empty_stack +T| XOR +->ERR +T{ XOR.one_item +T| 42 XOR +->ERR +T{ NOT.true +T| -1 NOT . CR +-> }T 3 47130 T= +T{ NOT.false +T| 0 NOT . CR +-> }T 4 1388686 T= +T{ NOT.positive +T| 42 NOT . CR +-> }T 3 47130 T= +Block 7047 +T{ NOT.negative +T| -42 NOT . CR +-> }T 3 47130 T= +T{ NOT.empty_stack +T| NOT +->ERR +T{ =.equal +T| 42 42 = . CR +-> }T 4 1388686 T= +T{ =.not_equal +T| 42 43 = . CR +-> }T 3 47130 T= +T{ =.zero_equal +T| 0 0 = . CR +-> }T 4 1388686 T= +Block 7048 +T{ =.negative_equal +T| -42 -42 = . CR +-> }T 4 1388686 T= +T{ =.negative_positive +T| -42 42 = . CR +-> }T 3 47130 T= +T{ =.empty_stack +T| = +->ERR +T{ =.one_item +T| 42 = +->ERR +T{ <.less_than +T| 5 7 < . CR +-> }T 4 1388686 T= +Block 7049 +T{ <.greater_than +T| 7 5 < . CR +-> }T 3 47130 T= +T{ <.equal +T| 5 5 < . CR +-> }T 3 47130 T= +T{ <.negative_positive +T| -5 5 < . CR +-> }T 4 1388686 T= +T{ <.negative_negative +T| -7 -5 < . CR +-> }T 4 1388686 T= +T{ <.empty_stack +T| < +->ERR +Block 7050 +T{ <.one_item +T| 42 < +->ERR +T{ >.greater_than +T| 7 5 > . CR +-> }T 4 1388686 T= +T{ >.less_than +T| 5 7 > . CR +-> }T 3 47130 T= +T{ >.equal +T| 5 5 > . CR +-> }T 3 47130 T= +T{ >.positive_negative +T| 5 -5 > . CR +-> }T 4 1388686 T= +Block 7051 +T{ >.negative_negative +T| -5 -7 > . CR +-> }T 4 1388686 T= +T{ >.empty_stack +T| > +->ERR +T{ >.one_item +T| 42 > +->ERR +T{ 0=.zero +T| 0 0= . CR +-> }T 4 1388686 T= +T{ 0=.positive +T| 42 0= . CR +-> }T 3 47130 T= +Block 7052 +T{ 0=.negative +T| -42 0= . CR +-> }T 3 47130 T= +T{ 0=.empty_stack +T| 0= +->ERR +T{ 0<.negative +T| -42 0< . CR +-> }T 4 1388686 T= +T{ 0<.zero +T| 0 0< . CR +-> }T 3 47130 T= +T{ 0<.positive +T| 42 0< . CR +-> }T 3 47130 T= +Block 7053 +T{ 0<.empty_stack +T| 0< +->ERR +T{ 0>.positive +T| 42 0> . CR +-> }T 4 1388686 T= +T{ 0>.zero +T| 0 0> . CR +-> }T 3 47130 T= +T{ 0>.negative +T| -42 0> . CR +-> }T 3 47130 T= +T{ 0>.empty_stack +T| 0> +->ERR +Block 7054 +T{ U<.less +T| 3 5 U< . CR +-> }T 4 1388686 T= +T{ U<.equal +T| 5 5 U< . CR +-> }T 3 47130 T= +T{ U<.greater +T| 7 5 U< . CR +-> }T 3 47130 T= +T{ U<.zero_one +T| 0 1 U< . CR +-> }T 4 1388686 T= +T{ U<.empty_stack +T| U< +->ERR +Block 7055 +T{ */.basic +T| 6 7 4 */ . CR +-> }T 4 1506889 T= +T{ */.exact_division +T| 12 5 3 */ . CR +-> }T 4 1536680 T= +T{ */.zero_multiply +T| 0 999 123 */ . CR +-> }T 3 47130 T= +T{ */.by_one +T| 42 5 1 */ . CR +-> }T 5 14128507 T= +T{ */.truncation +T| 7 3 2 */ . CR +-> }T 4 1506889 T= +Block 7056 +T{ */.negative_multiply +T| -6 7 4 */ . CR +-> }T 5 9510902 T= +T{ */.negative_divisor +T| 6 7 -4 */ . CR +-> }T 5 9510902 T= +T{ */.div_by_zero +T| 6 7 0 */ +->ERR +T{ */.empty_stack +T| */ +->ERR +T{ */.two_items +T| 1 2 */ +->ERR +Block 7057 +T{ */MOD.basic +T| 17 3 5 */MOD . . CR +-> }T 6 5318234 T= +T{ */MOD.exact_division +T| 15 4 3 */MOD . . CR +-> }T 6 391992 T= +T{ */MOD.zero_multiply +T| 0 999 123 */MOD . . CR +-> }T 5 11775018 T= +T{ */MOD.by_one +T| 42 5 1 */MOD . . CR +-> }T 7 4765003 T= +T{ */MOD.remainder +T| 7 8 5 */MOD . . CR +-> }T 6 6241755 T= +Block 7058 +T{ */MOD.negative +T| -7 3 4 */MOD . . CR +-> }T 7 12674054 T= +T{ */MOD.div_by_zero +T| 6 7 0 */MOD +->ERR +T{ */MOD.empty_stack +T| */MOD +->ERR +T{ D+.basic +T| 100 200 300 400 D+ . . CR +-> }T 9 6378548 T= +T{ D+.zero_add +T| 42 99 0 0 D+ . . CR +-> }T 7 6471656 T= +Block 7059 +T{ D+.negative +T| -100 -200 50 75 D+ . . CR +-> }T 10 13971193 T= +T{ D+.carry +T| 2147483647 0 1 0 D+ . . CR +-> }T 14 4234951 T= +T{ D+.both_negative +T| -100 -200 -300 -400 D+ . . CR +-> }T 11 5003369 T= +T{ D+.three_items +T| 1 2 3 D+ +->ERR +T{ D+.empty_stack +T| D+ +->ERR +Block 7060 +T{ DNEGATE.positive +T| 100 200 DNEGATE . . CR +-> }T 11 13922440 T= +T{ DNEGATE.negative +T| -100 -200 DNEGATE . . CR +-> }T 9 14912460 T= +T{ DNEGATE.zero +T| 0 0 DNEGATE . . CR +-> }T 5 11775018 T= +T{ DNEGATE.max_positive +T| 2147483647 0 DNEGATE . . CR +-> }T 16 11447367 T= +T{ DNEGATE.one_item +T| 42 DNEGATE +->ERR +Block 7061 +T{ DNEGATE.empty_stack +T| DNEGATE +->ERR +T{ D<.less_than +T| 100 200 300 400 D< . CR +-> }T 4 1388686 T= +T{ D<.greater_than +T| 300 400 100 200 D< . CR +-> }T 3 47130 T= +T{ D<.equal +T| 100 200 100 200 D< . CR +-> }T 3 47130 T= +T{ D<.negative_positive +T| -100 -1 100 0 D< . CR +-> }T 4 1388686 T= +Block 7062 +T{ D<.negative_negative +T| -300 -1 -100 -1 D< . CR +-> }T 4 1388686 T= +T{ D<.high_word_diff +T| 100 200 100 300 D< . CR +-> }T 4 1388686 T= +T{ D<.three_items +T| 1 2 3 D< +->ERR +T{ D<.empty_stack +T| D< +->ERR +T{ BASE.decimal +T| DECIMAL 42 . CR +-> }T 4 1598184 T= +Block 7063 +T{ BASE.hex +T| HEX FF . CR +-> }T 4 2153642 T= +T{ BASE.octal +T| OCTAL 52 . CR +-> }T 4 1627975 T= +T{ BASE.base_store +T| 16 BASE ! 255 . CR +-> }T 5 16131231 T= +T{ BASE.base_fetch +T| BASE @ . CR +-> }T 4 1510733 T= +T{ DECIMAL.from_hex +T| HEX FF DECIMAL . CR +-> }T 5 14252476 T= +Block 7064 +T{ DECIMAL.from_octal +T| OCTAL 52 DECIMAL . CR +-> }T 4 1598184 T= +T{ DECIMAL.state_persist +T| DECIMAL 42 . CR 42 . CR HEX 42 . CR +-> }T 12 9440440 T= +T{ <#.basic +T| DECIMAL 42 S>D <# #S #> TYPE CR +-> }T 22 14470350 T= +T{ <#.empty +T| 0 <# #> TYPE CR +-> 0 }T 1 10 T= +T{ <#.negative +T| -42 <# #S #> TYPE CR +-> }T 3 51532 T= +Block 7065 +T{ #.single_digit +T| 15 <# # #> TYPE CR +-> }T 2 1653 T= +T{ #.multiple +T| 15 <# # # #> TYPE CR +-> }T 3 48742 T= +T{ #.zero_pad +T| 5 <# # 0 # #> TYPE CR +-> 0 }T 3 47781 T= +T{ #S.basic +T| 42 <# #S #> TYPE CR +-> }T 3 51532 T= +T{ #S.zero +T| 0 <# #S #> TYPE CR +-> }T 2 1498 T= +Block 7066 +T{ #S.large +T| 1234567890 <# #S #> TYPE CR +-> }T 11 7265487 T= +T{ SIGN.negative +T| -42 ABS <# #S SIGN #> TYPE CR +-> 0 }T 3 51532 T= +T{ SIGN.positive +T| 42 <# #S SIGN #> TYPE CR +-> 0 }T 3 51532 T= +T{ SIGN.zero +T| 0 <# #S SIGN #> TYPE CR +-> 0 }T 2 1498 T= +T{ #>.normal +T| 42 <# #S #> TYPE CR +-> }T 3 51532 T= +Block 7067 +T{ #>.empty +T| 0 <# #> TYPE CR +-> 0 }T 1 10 T= +T{ #>.stack_effect +T| 42 <# #S #> SWAP . . CR +-> }T 6 4087998 T= +T{ HOLD.basic +T| 42 <# 46 HOLD #S #> TYPE CR +-> }T 4 1598618 T= +T{ HOLD.overflow +T| <# 257 HOLD #> +->ERR +T{ COUNT.basic +T| HERE S" Test" DROP COUNT . . CR +-> 302 }T 8 8794556 T= +Block 7068 +T{ COUNT.empty +T| HERE 0 OVER C! COUNT . . CR +-> }T 7 11241141 T= +T{ COUNT.max_length +T| HERE 255 OVER C! COUNT . . CR +-> }T 9 2533207 T= +T{ COUNT.string_bounds +T| HERE COUNT SWAP 1- = . CR +-> }T 3 47130 T= +T{ COUNT.empty_stack +T| COUNT +->ERR +T{ -TRAILING.basic +T| HERE S" Test " -TRAILING TYPE CR +-> 307 }T 6 6975864 T= +Block 7069 +T{ -TRAILING.all_spaces +T| HERE S" " -TRAILING TYPE CR +-> 315 }T 1 10 T= +T{ -TRAILING.no_spaces +T| HERE S" Test" -TRAILING TYPE CR +-> 320 }T 5 13589912 T= +T{ -TRAILING.empty +T| HERE 0 -TRAILING TYPE CR +-> }T 1 10 T= +T{ CMOVE.basic +T| HERE S" Test" DUP >R HERE 10 + SWAP CMOVE CR +-> 325 }T 1 10 T= +T{ CMOVE.empty +T| HERE HERE 10 + 0 CMOVE +-> }T 0 0 T= +Block 7070 +T{ CMOVE.overlap +T| HERE DUP 1+ 5 CMOVE +-> }T 0 0 T= +T{ CMOVE.bounds +T| HERE PAD 1000 CMOVE +->ERR +T{ >IN.initial +T| >IN @ . CR +-> }T 11 6895390 T= +T{ >IN.advances +T| : TWIN >IN @ >IN @ - . CR ; TWIN +-> }T 3 47130 T= +T{ ..positive +T| 42 . CR +-> }T 4 1598184 T= +Block 7071 +T{ ..negative +T| -42 . CR +-> }T 5 9602197 T= +T{ ..zero +T| 0 . CR +-> }T 3 47130 T= +T{ ..max_int +T| 2147483647 . CR +-> }T 12 4848918 T= +T{ ..min_int +T| -2147483648 . CR +-> }T 13 5383556 T= +T{ ..multiple +T| 1 2 3 . . . CR +-> }T 7 4767936 T= +Block 7072 +T{ ..empty_stack +T| . +->ERR +T{ CR.basic +T| 42 . CR 43 . CR +-> }T 8 16061841 T= +T{ CR.multiple +T| CR CR CR +-> }T 3 9930 T= +T{ CR.no_stack_effect +T| DEPTH CR DEPTH = . CR +-> }T 4 345040 T= +T{ CR.after_output +T| 1 2 3 . . . CR +-> }T 7 4767936 T= +Block 7073 +T{ SPACE.basic +T| 42 . SPACE 43 . CR +-> }T 8 2824871 T= +T{ SPACE.multiple +T| SPACE SPACE SPACE +-> }T 3 31776 T= +T{ SPACE.no_stack_effect +T| DEPTH SPACE DEPTH = . CR +-> }T 4 1000442 T= +T{ SPACE.with_text +T| 65 EMIT SPACE 66 EMIT CR +-> }T 4 1969223 T= +T{ SPACES.zero +T| 0 SPACES +-> }T 0 0 T= +Block 7074 +T{ SPACES.one +T| 1 SPACES +-> }T 1 32 T= +T{ SPACES.multiple +T| 5 SPACES +-> }T 5 13760544 T= +T{ SPACES.large +T| 20 SPACES +-> }T 20 10692608 T= +T{ SPACES.negative +T| -5 SPACES +-> }T 0 0 T= +T{ SPACES.with_output +T| 42 . 3 SPACES 43 . CR +-> }T 10 11278119 T= +Block 7075 +T{ SPACES.empty_stack +T| SPACES +->ERR +T{ EMIT.letter_A +T| 65 EMIT CR +-> }T 2 2025 T= +T{ EMIT.letter_Z +T| 90 EMIT CR +-> }T 2 2800 T= +T{ EMIT.digit +T| 48 EMIT CR +-> }T 2 1498 T= +T{ EMIT.space_char +T| 32 EMIT CR +-> }T 2 1002 T= +Block 7076 +T{ EMIT.newline +T| 10 EMIT +-> }T 1 10 T= +T{ EMIT.high_ascii +T| 127 EMIT CR +-> }T 2 3947 T= +T{ EMIT.truncation +T| 321 EMIT CR +-> }T 2 2025 T= +T{ EMIT.negative +T| -1 EMIT CR +-> }T 2 1963 T= +T{ EMIT.sequence +T| 72 EMIT 73 EMIT 10 EMIT +-> }T 3 71465 T= +Block 7077 +T{ EMIT.empty_stack +T| EMIT +->ERR +T{ TYPE.basic_string +T| HERE S" Hello" DUP >R HERE SWAP CMOVE HERE R> TYPE CR +-> 400 }T 6 10415512 T= +T{ TYPE.empty_string +T| HERE 0 TYPE CR +-> }T 1 10 T= +T{ TYPE.single_char +T| HERE 65 OVER C! 1 TYPE CR +-> }T 2 2025 T= +T{ TYPE.numbers +T| HERE S" 12345" DUP >R HERE SWAP CMOVE HERE R> TYPE CR +-> 406 }T 6 7734839 T= +Block 7078 +T{ TYPE.zero_length +T| PAD 0 TYPE +-> }T 0 0 T= +T{ TYPE.one_item +T| PAD TYPE +->ERR +T{ TYPE.empty_stack +T| TYPE +->ERR +T{ COUNT.basic~2 +T| HERE S" Test" DROP C@ HERE 1+ SWAP COUNT . . CR +-> 412 418 }T 6 12963223 T= +T{ COUNT.empty~2 +T| HERE 0 OVER C! COUNT . . CR +-> }T 7 12194453 T= +Block 7079 +T{ COUNT.max_length~2 +T| HERE 255 OVER C! COUNT . . CR +-> }T 9 3486519 T= +T{ COUNT.zero_addr_plus_one +T| HERE COUNT SWAP 1- = . CR +-> }T 3 47130 T= +T{ COUNT.empty_stack~2 +T| COUNT +->ERR +T{ WORD.empty_input +T| BL WORD COUNT . CR +-> 113 }T 3 47130 T= +T{ WORD.space_delim +T| 32 WORD DROP +-> }T 0 0 T= +Block 7080 +T{ WORD.newline_delim +T| 10 WORD DROP +-> }T 0 0 T= +T{ WORD.tab_delim +T| 9 WORD DROP +-> }T 0 0 T= +T{ WORD.comma_delim +T| 44 WORD DROP +-> }T 0 0 T= +T{ WORD.skip_leading +T| BL WORD DROP +-> }T 0 0 T= +T{ WORD.single_char +T| BL WORD COUNT . CR +-> 113 }T 3 47130 T= +Block 7081 +T{ WORD.long_word +T| BL WORD COUNT 0 > . CR +-> 113 }T 3 47130 T= +T{ WORD.zero_delim +T| 0 WORD DROP +-> }T 0 0 T= +T{ WORD.high_ascii +T| 127 WORD DROP +-> }T 0 0 T= +T{ WORD.count_format +T| BL WORD C@ . CR +-> }T 3 47130 T= +T{ WORD.count_value +T| BL WORD COUNT SWAP DROP . CR +-> }T 3 47130 T= +Block 7082 +T{ WORD.empty_stack +T| WORD +->ERR +T{ WORD.multi_delim +T| BL WORD DROP BL WORD DROP +-> }T 0 0 T= +T{ BLOCK.basic +T| 1 BLOCK DUP . CR +-> 5238784 }T 9 11810843 T= +T{ BLOCK.zero_block +T| 0 BLOCK +->ERR +T{ BLOCK.large_block +T| 65536 BLOCK +->ERR +Block 7083 +T{ BLOCK.negative +T| -1 BLOCK +->ERR +T{ BLOCK.empty_stack +T| BLOCK +->ERR +T{ BUFFER.basic +T| 1 BUFFER DUP . CR +-> 5238784 }T 9 11810843 T= +T{ BUFFER.zero_block +T| 0 BUFFER +->ERR +T{ BUFFER.flush_dirty +T| 2 BLOCK 1+ 2 BUFFER +-> 5239809 5239808 }T 0 0 T= +Block 7084 +T{ BUFFER.empty_stack +T| BUFFER +->ERR +T{ UPDATE.basic +T| 1 BLOCK UPDATE +-> 5238784 }T 0 0 T= +T{ UPDATE.multiple +T| 1 BLOCK UPDATE UPDATE +-> 5238784 }T 0 0 T= +T{ UPDATE.no_block +T| 0 SCR ! UPDATE +->ERR +T{ SAVE-BUFFERS.basic +T| SAVE-BUFFERS +-> }T 0 0 T= +Block 7085 +T{ SAVE-BUFFERS.dirty_blocks +T| 1 BLOCK UPDATE SAVE-BUFFERS +-> 5238784 }T 0 0 T= +T{ SAVE-BUFFERS.no_dirty +T| SAVE-BUFFERS +-> }T 0 0 T= +T{ EMPTY-BUFFERS.basic +T| EMPTY-BUFFERS +-> }T 0 0 T= +T{ EMPTY-BUFFERS.after_use +T| 1 BLOCK EMPTY-BUFFERS +-> 5238784 }T 0 0 T= +T{ EMPTY-BUFFERS.dirty_blocks +T| 1 BLOCK UPDATE EMPTY-BUFFERS +-> 5238784 }T 0 0 T= +Block 7086 +T{ LOAD.basic +T| 1 LOAD +-> }T 0 0 T= +T{ LOAD.zero_block +T| 0 LOAD +->ERR +T{ LOAD.nonexistent +T| 9999 LOAD +->ERR +T{ LOAD.empty_stack +T| LOAD +->ERR +T{ LIST.basic +T| 1 LIST +-> }T 1114 997788 T= +Block 7087 +T{ LIST.zero_block +T| 0 LIST +->ERR +T{ LIST.nonexistent +T| 9999 LIST +->ERR +T{ LIST.empty_stack +T| LIST +->ERR +T{ SCR.basic +T| SCR @ . CR +-> }T 3 48091 T= +T{ SCR.after_list +T| 1 LIST SCR @ . CR +-> }T 1117 12700863 T= +Block 7088 +T{ SCR.after_load +T| 1 LOAD SCR @ . CR +-> }T 0 0 T= +T{ HERE.basic~2 +T| HERE HERE = . CR +-> }T 4 1388686 T= +T{ HERE.after_comma~2 +T| HERE 42 , HERE SWAP - 1 CELLS = 0 SWAP / +->ERR +T{ HERE.after_c_comma +T| HERE 65 C, HERE SWAP - . CR +-> }T 3 48091 T= +T{ HERE.after_allot +T| HERE 10 ALLOT HERE SWAP - . CR +-> }T 4 1506889 T= +Block 7089 +T{ HERE.stability +T| HERE DUP HERE = . CR +-> 443 }T 4 1388686 T= +T{ ALLOT.basic~2 +T| HERE 10 ALLOT HERE SWAP - . CR +-> }T 4 1506889 T= +T{ ALLOT.zero~2 +T| HERE 0 ALLOT HERE SWAP - . CR +-> }T 3 47130 T= +T{ ALLOT.negative~2 +T| HERE -4 ALLOT HERE SWAP - . CR +-> }T 4 1391569 T= +T{ ALLOT.large +T| HERE 100 ALLOT HERE SWAP - . CR +-> }T 5 13175195 T= +Block 7090 +T{ ALLOT.after_use +T| ALIGN HERE 10 ALLOT 42 OVER ! @ . CR +-> }T 4 1598184 T= +T{ ALLOT.empty_stack +T| ALLOT +->ERR +T{ ,.basic~2 +T| 42 , HERE 1 CELLS - @ . CR +-> }T 4 1598184 T= +T{ ,.negative~2 +T| -999 , HERE 1 CELLS - @ . CR +-> }T 6 529078 T= +T{ ,.zero +T| 0 , HERE 1 CELLS - @ . CR +-> }T 3 47130 T= +Block 7091 +T{ ,.max_int +T| 2147483647 , HERE 1 CELLS - @ . CR +-> }T 12 4848918 T= +T{ ,.min_int +T| -2147483648 , HERE 1 CELLS - @ . CR +-> }T 13 5383556 T= +T{ ,.multiple +T| 10 , 20 , HERE 1 CELLS - @ . HERE 1 CELLS - @ . CR +-> }T 7 12227402 T= +T{ ,.empty_stack +T| , +->ERR +T{ PAD.basic~2 +T| PAD PAD = . CR +-> }T 4 1388686 T= +Block 7092 +T{ PAD.different_from_here~2 +T| PAD HERE = . CR +-> }T 3 47130 T= +T{ PAD.stability +T| PAD DUP PAD = . CR +-> 5242368 }T 4 1388686 T= +T{ PAD.usable +T| PAD 42 OVER ! @ . CR +-> }T 4 1598184 T= +T{ CREATE.basic +T| CREATE test1 42 , test1 @ . CR +-> }T 4 1598184 T= +T{ CREATE.empty_name +T| CREATE +->ERR +Block 7093 +T{ CREATE.redefine_shadows +T| CREATE T 1 , CREATE T 2 , T @ . CR +-> }T 3 49052 T= +T{ CREATE.duplicate +T| CREATE test2 CREATE test2 +-> }T 0 0 T= +T{ CREATE.long_name +T| CREATE abcdefghijklmnopqrstuvwxyz +-> }T 0 0 T= +T{ FORGET.basic +T| CREATE temp1 FORGET temp1 +-> }T 0 0 T= +T{ IMMEDIATE.basic +T| : test3 42 ; IMMEDIATE test3 . CR +-> }T 4 1598184 T= +Block 7094 +T{ IMMEDIATE.already_immediate +T| : test4 43 ; IMMEDIATE IMMEDIATE +-> }T 0 0 T= +T{ FIND.existing +T| FIND DUP . CR +-> }T 11 15395591 T= +T{ FIND.user_word +T| : test5 44 ; FIND test5 . CR +-> }T 11 8385165 T= +T{ FIND.nonexistent +T| FIND nonexistent . CR +-> }T 3 47130 T= +T{ FIND.empty +T| FIND +->ERR +Block 7095 +T{ DEFINITIONS.basic +T| FORTH DEFINITIONS +-> }T 0 0 T= +T{ DEFINITIONS.multiple +T| FORTH DEFINITIONS DEFINITIONS +-> }T 0 0 T= +T{ VOCABULARY.basic +T| VOCABULARY TEST-VOC1 TEST-VOC1 DEFINITIONS +-> }T 0 0 T= +T{ VOCABULARY.create_and_switch +T| VOCABULARY MYVOC MYVOC DEFINITIONS CONTEXT @ . CR +-> }T 11 11526440 T= +T{ VOCABULARY.word_isolation +T| VOCABULARY ISOLATED ISOLATED DEFINITIONS : ISOWORD 99 ; FORTH +T| DEFINITIONS +-> }T 0 0 T= +Block 7096 +T{ VOCABULARY.cross_vocab_access +T| VOCABULARY V1 V1 DEFINITIONS : V1WORD 11 ; FORTH V1WORD . CR +-> }T 4 1507850 T= +T{ VOCABULARY.multiple_vocabs +T| VOCABULARY VA VOCABULARY VB VOCABULARY VC VA DEFINITIONS +-> }T 0 0 T= +T{ VOCABULARY.duplicate +T| VOCABULARY TESTVOC VOCABULARY TESTVOC +->ERR +T{ VOCABULARY.empty_name +T| VOCABULARY +->ERR +T{ FORTH.basic +T| FORTH DEFINITIONS +-> }T 0 0 T= +Block 7097 +T{ FORTH.persistence +T| FORTH : TEST1 42 ; TEST1 . CR +-> }T 4 1598184 T= +T{ FORTH.from_other +T| VOCABULARY OTHER-VOC OTHER-VOC FORTH +-> }T 0 0 T= +T{ DEFINITIONS.basic~2 +T| FORTH DEFINITIONS +-> }T 0 0 T= +T{ DEFINITIONS.new_vocab +T| VOCABULARY TEST-VOC6 TEST-VOC6 DEFINITIONS +-> }T 0 0 T= +T{ DEFINITIONS.word_creation +T| VOCABULARY TEST-VOC7 TEST-VOC7 DEFINITIONS : TEST2 43 ; +-> }T 0 0 T= +Block 7098 +T{ CONTEXT.basic +T| CONTEXT @ . CR +-> }T 11 8729384 T= +T{ CONTEXT.initial +T| FORTH CONTEXT @ . CR +-> }T 11 2699444 T= +T{ CURRENT.basic +T| CURRENT @ . CR +-> }T 11 8729384 T= +T{ CURRENT.after_def +T| VOCABULARY TEST-VOC8 TEST-VOC8 DEFINITIONS CURRENT @ . CR +-> }T 11 14389674 T= +T{ ABORT.basic +T| ABORT +-> }T 0 0 T= +Block 7099 +T{ ABORT.with_data +T| 1 2 3 ABORT DEPTH . CR +-> }T 0 0 T= +T{ ABORT.in_definition_runtime +T| : BAD-WORD ABORT ; 123 BAD-WORD DEPTH . CR +-> }T 0 0 T= +T{ :.basic +T| : TEST1 42 ; TEST1 . CR +-> }T 4 1598184 T= +T{ :.empty_name +T| : +->ERR +T{ ;.alone +T| ; +->ERR +Block 7100 +T{ ;.immediate +T| : TEST4 42 ; IMMEDIATE TEST4 . CR +-> }T 4 1598184 T= +T{ CONSTANT.basic +T| 42 CONSTANT MEANING MEANING . CR +-> }T 4 1598184 T= +T{ CONSTANT.zero +T| 0 CONSTANT ZERO ZERO . CR +-> }T 3 47130 T= +T{ CONSTANT.negative +T| -1 CONSTANT MINUS MINUS . CR +-> }T 4 1388686 T= +T{ CONSTANT.empty_stack +T| CONSTANT +->ERR +Block 7101 +T{ VARIABLE.basic +T| VARIABLE VAR1 42 VAR1 ! VAR1 @ . CR +-> }T 4 1598184 T= +T{ VARIABLE.multiple +T| VARIABLE VAR2 VARIABLE VAR3 +-> }T 0 0 T= +T{ VARIABLE.store_fetch +T| VARIABLE VAR4 -99 VAR4 ! VAR4 @ . CR +-> }T 5 9757879 T= +T{ CREATE.basic~2 +T| CREATE OBJ1 +-> }T 0 0 T= +T{ CREATE.with_data +T| CREATE OBJ2 42 , OBJ2 @ . CR +-> }T 4 1598184 T= +Block 7102 +T{ CREATE.empty_name~2 +T| CREATE +->ERR +T{ DOES>.basic +T| : CONST CREATE , DOES> @ ; 42 CONST MEANING MEANING . CR +-> }T 4 1598184 T= +T{ DOES>.multiple +T| : ARRAY CREATE DOES> SWAP CELLS + ; CREATE ARR 10 CELLS ALLOT +-> }T 0 0 T= +T{ DOES>.outside +T| DOES> +->ERR +T{ [.basic +T| : TEST5 [ 42 ] LITERAL ; TEST5 . CR +-> }T 4 1598184 T= +Block 7103 +T{ [.outside +T| [ +-> }T 0 0 T= +T{ ].nested +T| : TEST6 [ ] 42 ; TEST6 . CR +-> }T 4 1598184 T= +T{ IF.true +T| : TEST1 IF 42 ELSE 24 THEN ; -1 TEST1 . CR +-> -1 }T 4 1598184 T= +T{ IF.false +T| : TEST2 IF 42 ELSE 24 THEN ; 0 TEST2 . CR +-> 0 }T 4 1599145 T= +T{ IF.nested +T| : TEST3 IF IF 1 ELSE 2 THEN ELSE 3 THEN ; -1 -1 TEST3 . CR +-> }T 3 48091 T= +Block 7104 +T{ IF.no_else +T| : TEST4 IF 42 THEN ; -1 TEST4 . CR +-> }T 4 1598184 T= +T{ IF.empty_stack +T| IF +->ERR +T{ ELSE.alone +T| ELSE +->ERR +T{ THEN.alone +T| THEN +->ERR +T{ BEGIN.until +T| : TEST5 0 BEGIN 1+ DUP 5 = UNTIL ; TEST5 . CR +-> }T 3 51935 T= +Block 7105 +T{ BEGIN.while +T| : TEST6 0 BEGIN DUP 5 < WHILE 1+ REPEAT ; TEST6 . CR +-> }T 3 51935 T= +T{ BEGIN.alone +T| BEGIN +->ERR +T{ UNTIL.basic +T| : TEST8 BEGIN DUP 1- DUP 0= UNTIL ; 5 TEST8 . CR +-> 5 4 3 2 1 }T 3 47130 T= +T{ UNTIL.immediate +T| : TEST9 BEGIN 1 UNTIL ; IMMEDIATE +-> }T 0 0 T= +T{ UNTIL.no_begin +T| UNTIL +->ERR +Block 7106 +T{ WHILE.basic +T| : TEST10 BEGIN DUP 5 < WHILE 1+ REPEAT ; 0 TEST10 . CR +-> }T 3 51935 T= +T{ WHILE.zero_times +T| : TEST11 BEGIN DUP 0< WHILE 1+ REPEAT ; 0 TEST11 . CR +-> }T 3 47130 T= +T{ WHILE.no_begin +T| WHILE +->ERR +T{ REPEAT.basic +T| : TEST12 BEGIN DUP 5 < WHILE 1+ REPEAT ; 0 TEST12 . CR +-> }T 3 51935 T= +T{ REPEAT.no_while +T| REPEAT +->ERR +Block 7107 +T{ DO.basic +T| : TEST13 5 0 DO I . LOOP ; TEST13 CR +-> }T 11 12528484 T= +T{ DO.negative +T| : TEST14 -1 -5 DO I . LOOP ; TEST14 CR +-> }T 13 11696776 T= +T{ DO.empty +T| : TEST15 0 0 DO LOOP ; +-> }T 0 0 T= +T{ DO.nested +T| : TEST16 3 0 DO 3 0 DO J I + . LOOP LOOP ; TEST16 CR +-> }T 19 14426156 T= +T{ LOOP.basic +T| : TEST20 5 0 DO I . LOOP ; TEST20 CR +-> }T 11 12528484 T= +Block 7108 +T{ LOOP.no_do +T| LOOP +->ERR +T{ +LOOP.basic +T| : TEST21 10 0 DO I . 2 +LOOP ; TEST21 CR +-> }T 11 16410222 T= +T{ +LOOP.negative +T| : TEST22 0 10 DO I . -1 +LOOP ; TEST22 CR +-> }T 24 15411990 T= +T{ +LOOP.variable +T| : TEST23 10 0 DO I . DUP +LOOP ; 3 TEST23 CR +-> 3 }T 9 8104156 T= +T{ I.basic +T| : TI 4 0 DO I . LOOP CR ; TI +-> }T 9 7781840 T= +Block 7109 +T{ I.single +T| : TI1 1 0 DO I . LOOP CR ; TI1 +-> }T 3 47130 T= +T{ I.offset +T| : TI2 5 3 DO I . LOOP CR ; TI2 +-> }T 5 14549425 T= +T{ I.in_expr +T| : TI3 3 0 DO I 2 * . LOOP CR ; TI3 +-> }T 7 9837120 T= +T{ J.basic +T| : TJ 2 0 DO 3 0 DO J . LOOP LOOP CR ; TJ +-> }T 13 4074221 T= +T{ J.paired +T| : TJ2 2 0 DO 2 0 DO J I + . LOOP LOOP CR ; TJ2 +-> }T 9 6857358 T= +Block 7110 +T{ EXIT.early_return +T| : TEX 5 EXIT 99 ; TEX . CR +-> }T 3 51935 T= +T{ EXIT.cond_exit_pos +T| : TEX2 DUP 0> IF EXIT THEN NEGATE ; 3 TEX2 . CR +-> }T 3 50013 T= +T{ EXIT.cond_exit_neg +T| : TEX2 DUP 0> IF EXIT THEN NEGATE ; -4 TEX2 . CR +-> }T 3 50974 T= +T{ EXIT.no_skipped +T| : TEX3 1 2 EXIT 3 ; TEX3 . . CR +-> }T 5 13623021 T= +T{ LEAVE.basic +T| : TLV 0 5 0 DO I 3 = IF LEAVE THEN 1+ LOOP ; TLV . CR +-> }T 3 50013 T= +Block 7111 +T{ LEAVE.at_start +T| : TLV2 0 5 0 DO LEAVE 1+ LOOP ; TLV2 . CR +-> }T 3 47130 T= +T{ LEAVE.qdloop +T| : TLV3 0 5 0 ?DO I 2 = IF LEAVE THEN 1+ LOOP ; TLV3 . CR +-> }T 3 49052 T= +Block 7112 +T-REPORT +FORGET T# DECIMAL diff --git a/logs/20261005-160144/amd64/qemu-amd64-20261005-160144.log b/logs/20261005-160144/amd64/qemu-amd64-20261005-160144.log new file mode 100644 index 00000000..a2c80e67 --- /dev/null +++ b/logs/20261005-160144/amd64/qemu-amd64-20261005-160144.log @@ -0,0 +1,108 @@ +[=3hBdsDxe: 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) +[=3hStarKernel 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 5 2026 16:01:18 + +UEFI BootServices: EXITED + +=== StarKernel Boot Information === +Memory map entries: 131 +Total memory: 1023 MB +Usable memory: 968 MB +=================================== + +PMM initialized. +PMM statistics: + Total pages: 249248 + Free pages : 247725 + Used pages : 1523 + Total MB : 973 + Free MB : 967 + 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=2102894063 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=1010732930, tick_hz=100, initial_count=10107329 +APIC Timer: configured (masked, ready to start) +Heartbeat: init done +Kernel initialization complete. +Boot successful! + +StarForth v4: one host node, the F18-derived engine +PARITY:V4_NUCLEUS words=295 image_hash=0x3ed5d5fc83f0b026 +V4: capsule v4:forth79.4th signature: missing (unsigned) +PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0xa4b74bdc7deaf204 capsule_hash=0xa4b74bdc7deaf204 dict_hash=0x118de9d37e682ea4 +PARITY:OK +ok> \ No newline at end of file diff --git a/logs/20261005-160234/aarch64/qemu-aarch64-20261005-160234.log b/logs/20261005-160234/aarch64/qemu-aarch64-20261005-160234.log new file mode 100644 index 00000000..dcc257d0 --- /dev/null +++ b/logs/20261005-160234/aarch64/qemu-aarch64-20261005-160234.log @@ -0,0 +1,82 @@ +UEFI firmware (version 2025.11-3ubuntu7.3 built at 15:40:26 on Sep 23 2026) +[=3hBdsDxe: 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) +[=3hStarKernel 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 5 2026 16:02:10 + +UEFI BootServices: EXITED + +=== StarKernel Boot Information === +Memory map entries: 108 +Total memory: 4093 MB +Usable memory: 4056 MB +=================================== + +PMM initialized. +PMM statistics: + Total pages: 1039860 + Free pages : 1038449 + Used pages : 1411 + Total MB : 4061 + Free MB : 4056 + 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 +PARITY:V4_NUCLEUS words=295 image_hash=0x3ed5d5fc83f0b026 +V4: capsule v4:forth79.4th signature: missing (unsigned) +PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0xa4b74bdc7deaf204 capsule_hash=0xa4b74bdc7deaf204 dict_hash=0x118de9d37e682ea4 +PARITY:OK +ok> \ No newline at end of file diff --git a/logs/20261005-160400/riscv64/qemu-riscv64-20261005-160400.log b/logs/20261005-160400/riscv64/qemu-riscv64-20261005-160400.log new file mode 100644 index 00000000..7bdc2c2c --- /dev/null +++ b/logs/20261005-160400/riscv64/qemu-riscv64-20261005-160400.log @@ -0,0 +1,152 @@ + +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 +[=3hRISC-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 +[=3hStarKernel 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 = 0x00000000bde99936 +riscv64: satp cleared -- Bare mode, explicit (item 4.3.5a) + + + _____ _ _ __ _ + / ____| | | |/ / | | + | (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| | + \___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ | + ____) | || (_| | | | . \ __/ | | | | | __/ | + |_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_| + +LithosAnanke v2.1.0 +Architecture: riscv64 +Build: Oct 5 2026 16:03:23 + +UEFI BootServices: EXITED + +=== StarKernel Boot Information === +Memory map entries: 100 +Total memory: 1020 MB +Usable memory: 977 MB +=================================== + +PMM initialized. +PMM statistics: + Total pages: 250775 + Free pages : 250123 + Used pages : 652 + Total MB : 979 + Free MB : 977 + 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 +PARITY:V4_NUCLEUS words=295 image_hash=0x3ed5d5fc83f0b026 +V4: capsule v4:forth79.4th signature: missing (unsigned) +PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0xa4b74bdc7deaf204 capsule_hash=0xa4b74bdc7deaf204 dict_hash=0x118de9d37e682ea4 +PARITY:OK +ok> \ No newline at end of file diff --git a/v4/Makefile b/v4/Makefile index c5b983fa..52e571aa 100644 --- a/v4/Makefile +++ b/v4/Makefile @@ -129,6 +129,20 @@ $(BINDIR)/boot-$(1).txt: $(BINDIR)/starforth4-$(1) endef $(foreach i,$(HOSTED_ISAS),$(eval $(call HOSTED_RULE,$(i)))) +# `make post` builds the amd64 system with POST in its boot +# (V4_POST_AT_BOOT=1, system/boot.c) and boots it: the POST capsule, +# ../capsules/v4/post79.4th, is loaded after forth79.4th and must end with a +# clean tally. `make post79` writes that capsule again from v3's cases +# (tools/mkpost.py); it needs the hosted v3 binary. +.PHONY: post post79 +$(BINDIR)/starforth4-post: $(HERE)/tools/hosted.c $(BINDIR)/v4_image_64.c $(CAPSULE_DIR_C) $(ENGINE_SRCS) $(SYSTEM_SRCS) $(wildcard $(HERE)/include/v4/*.h) $(HERE)/Makefile + $(CC_amd64) $(CFLAGS) -D_POSIX_C_SOURCE=200809L -I$(HERE)/include -DV4_CELL_BITS=64 $(HOST_DEFS) -c $(HERE)/tools/hosted.c -o $(BINDIR)/hosted-post.o + $(CC_amd64) $(SYSTEM_CFLAGS) -DV4_POST_AT_BOOT=1 -static $(BINDIR)/hosted-post.o $(BINDIR)/v4_image_64.c $(CAPSULE_DIR_C) $(ENGINE_SRCS) $(SYSTEM_SRCS) -o $@ +post: $(BINDIR)/starforth4-post + @$(BINDIR)/starforth4-post < /dev/null +post79: + python3 $(HERE)/tools/mkpost.py + # `make hosted` builds the three. `make hosted-check` boots each with no # input and requires that all three print the same lines, ending in # PARITY:OK and the prompt: the same hashes on every ISA. diff --git a/v4/README.md b/v4/README.md index b2f6e6f6..35e615f5 100644 --- a/v4/README.md +++ b/v4/README.md @@ -55,21 +55,58 @@ and fails unless their output is identical and ends in `PARITY:OK`. A capsule line the node does not answer ` ok` to ends the boot, naming the capsule, block and line, with `PARITY:FAIL` and `POST: FAILED`. -State, 2026-10-05: capsule loading works on all six builds. The three hosted -binaries and the three bare-metal kernels (`clean qemu` with `STARFORTH_V4=1`) -print the same four lines and reach `ok>`: +State, 2026-10-05, after the POST work began: all six builds load +`v4:forth79.4th` and reach `ok>` with the same lines: ``` -PARITY:V4_NUCLEUS words=292 image_hash=0x60b74e4f87adb0ac -PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0xa4b74bdc7deaf204 capsule_hash=0xa4b74bdc7deaf204 dict_hash=0x0baed67626b4fac4 +PARITY:V4_NUCLEUS words=295 image_hash=0x3ed5d5fc83f0b026 +PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0xa4b74bdc7deaf204 capsule_hash=0xa4b74bdc7deaf204 dict_hash=0x118de9d37e682ea4 PARITY:OK ok> ``` -Bare-metal logs: `logs/20261005-152955/amd64/`, `logs/20261005-154021/aarch64/`, -`logs/20261005-154150/riscv64/`. Each run was ended once the prompt was in the +Bare-metal logs: `logs/20261005-160144/amd64/`, `logs/20261005-160234/aarch64/`, +`logs/20261005-160400/riscv64/`. Each run was ended once the prompt was in the log; nothing was typed at a bare-metal prompt, so keyboard input there is not yet verified. The capsules were unsigned (no signing key on this machine). -`forth79.4th` holds no definitions yet: all 292 words are still in the -nucleus. There is no POST yet. +`forth79.4th` holds no definitions yet: every word is still in the nucleus. + +## POST + +`capsules/v4/post79.4th` is v3's POST cases for the FORTH-79 Required Word +Set, written by `v4/tools/mkpost.py` (`make -C v4 post79`): 537 cases in +blocks 7000–7112, covering 111 of the 130 required words. Each case carries +what the hosted v3 binary did with the same line — error or not, the stack, +the length and checksum of what was printed — and v4 must do the same. + +**POST does not pass yet, so it is not in the boot.** `make -C v4 post` builds +the amd64 system with it (`-DV4_POST_AT_BOOT=1`) and boots it: + +``` +PARITY:V4_POST tests=537 pass=439 fail=98 +PARITY:FAIL +POST: FAILED +``` + +The 98 are not yet sorted into v4 defects and differences that need a +ruling. A first reading finds four kinds: + +| Kind | About | Examples | +|---|---|---| +| The case prints or leaves a memory address, which differs between the two machines | 40 | `HERE`, `PAD`, `1 BLOCK`, `BL WORD`, `CONTEXT @ .`, `FIND` | +| v3 departs from FORTH-79 and v4 follows the standard | 35 | `PICK` and `ROLL` count from 1; `<# # #S #>` take a double number; `LEAVE` ends the loop at the next `LOOP`; `>R` `R>` only inside a definition | +| The case assumes v3's byte address units, where a v4 address unit is a cell (D-1) | 8 | `42 , HERE 8 - @`, `PAD 42 OVER !` | +| Not yet understood | 15 | vocabulary cases, `LIST`'s layout, `16 BASE ! 255 .`, `321 EMIT`, cases v3 ends in an error and v4 does not | + +Required words with no v3 case, and so no POST case: `U*` `U/MOD` `?` +`EXECUTE` `KEY` `EXPECT` `QUERY` `U.` `CONVERT` `'` `."` `LITERAL` `STATE` +`COMPILE` `[COMPILE]` `(` `QUIT` `BLK` `79-STANDARD`. `U*` and `U/MOD` are +in neither v3 nor v4. + +Twelve v3 cases are left out: three read the keyboard, two forget a word of +the system, two store to the search order, and five leave v3 unable to +continue in one session (`mkpost.py` prints the list). + +The boot passes POST only on seeing the tally line with `fail=0` +(`v4/system/boot.c`); that no line was refused is not enough. diff --git a/v4/capsule/quit.v4 b/v4/capsule/quit.v4 index 44926d11..3b7d713c 100644 --- a/v4/capsule/quit.v4 +++ b/v4/capsule/quit.v4 @@ -68,6 +68,11 @@ macro R-CLEAR RSTACK-DEPTH b! a !b endmacro \ FORTH-79: clear the return stack, set execution mode, return control to \ the terminal; no message is given. The data stack is left as it is. +\ NODE-ERROR, by name: how a definition written in FORTH raises an error. +\ A store of a code that is not zero is the trap of D-18 -- the word goes no +\ 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 (EMIT-HOOK) inline : (EMIT-HOOK)' (EMIT-HOOK) ; diff --git a/v4/include/v4/boot.h b/v4/include/v4/boot.h index b925c5b0..80361ca0 100644 --- a/v4/include/v4/boot.h +++ b/v4/include/v4/boot.h @@ -6,8 +6,11 @@ * the text goes. So the two start the same way and print the same lines: * * PARITY:V4_NUCLEUS words=N image_hash=0x... - * PARITY:V4_CAPSULE name=... capsule_id=0x... capsule_hash=0x... dict_hash=0x... + * PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x... capsule_hash=0x... dict_hash=0x... + * PARITY:V4_POST tests=N pass=N fail=N (printed by the POST capsule) + * PARITY:V4_CAPSULE name=v4:post79.4th capsule_id=0x... capsule_hash=0x... dict_hash=0x... * PARITY:OK + * POST: PASSED * ok> * * or, if anything is wrong, what was wrong and then diff --git a/v4/system/boot.c b/v4/system/boot.c index e3e0ddf1..840a9fff 100644 --- a/v4/system/boot.c +++ b/v4/system/boot.c @@ -11,7 +11,18 @@ #include "starkernel/capsule_blocks.h" /* The capsules, in the order they are loaded. */ -static const char *const boot_capsules[] = { "v4:forth79.4th" }; +/* POST is not yet part of the boot: v4:post79.4th does not pass yet + * (v4/README.md). Build with -DV4_POST_AT_BOOT=1 to load it and to require + * its clean tally; `make -C v4 post` does. */ +#ifndef V4_POST_AT_BOOT +#define V4_POST_AT_BOOT 0 +#endif +static const char *const boot_capsules[] = { + "v4:forth79.4th", +#if V4_POST_AT_BOOT + "v4:post79.4th", +#endif +}; #define LINE_MAX 80u /* QUERY takes 80 characters, the new-line among them */ #define STEP_LIMIT 4000000000ULL /* instruction words one line may take */ @@ -105,6 +116,37 @@ typedef struct { unsigned len; } tail; +/* 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; +} + static void tail_put(const v4_boot *b, tail *t, int show, char c) { unsigned i; @@ -130,7 +172,10 @@ static int run_to_prompt(const v4_boot *b, int show) for (;;) { (void)v4_exec_step_word(n, b->es, b->h); if (n->console_len) { - for (i = 0; i < n->console_len; i++) tail_put(b, &t, show, (char)n->console[i]); + for (i = 0; i < n->console_len; i++) { + post_watch((char)n->console[i]); + tail_put(b, &t, show, (char)n->console[i]); + } n->console_len = 0; } if (n->stopped) { say(b, "\nV4: the node stopped on a fault\n"); return 0; } @@ -233,6 +278,7 @@ int v4_boot_run(const v4_boot *b, unsigned char *disk, unsigned blocks) { unsigned i; + post_len = 0; post_seen = 0; post_clean = 0; if (!v4_image_boot(b->n, b->es, b->h, b->im, disk, blocks)) { say(b, "V4: the nucleus image is not for this build of the engine\nPARITY:FAIL\nPOST: FAILED\n"); return 0; @@ -247,7 +293,18 @@ int v4_boot_run(const v4_boot *b, unsigned char *disk, unsigned blocks) 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; + } +#endif +#if V4_POST_AT_BOOT + say(b, "PARITY:OK\nPOST: PASSED\nok> "); +#else say(b, "PARITY:OK\nok> "); +#endif return 1; } diff --git a/v4/tools/mkpost.py b/v4/tools/mkpost.py new file mode 100755 index 00000000..578ede60 --- /dev/null +++ b/v4/tools/mkpost.py @@ -0,0 +1,455 @@ +#!/usr/bin/env python3 +"""mkpost.py -- write capsules/v4/post79.4th from v3's POST cases. + + v4/tools/mkpost.py [--v3 PATH] [--report FILE] + +A development tool, run when the cases change; its output is committed and +reviewed like any source. docs/v4.0.0/NUCLEUS.md section 6. + +What it does: + + 1. Reads v3's case tables, v3/src/test_runner/modules/*.c, in the order + v3's own POST runs them. A case is a word, a name, a line of FORTH and + whether an error is expected. + 2. Keeps the cases for words of the FORTH-79 Required Word Set. + 3. Runs every kept case, in order, in one session of the hosted v3 binary, + and records what v3 did: an error or not, the data stack, and what was + printed. v3 is the reference. + 4. Writes the harness and one case after another as a .4th capsule: + + T{ DUP.basic name the case, start clean + T| 5 DUP . . a line of the case, its output captured + -> 5 5 }T 0 0 T= v3's stack; v3's output: length, checksum + + or, for a case v3 ended with an error, ->ERR in place of the last + line. + +A case is left out, and listed in the report, when: its word reads the +keyboard; it forgets a word of the system or damages it on purpose; v3 could +not finish it in one +session; or one of its lines cannot be cut to fit a 64-character block +line. +""" +import argparse +import os +import re +import subprocess +import sys + +ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) +MODULE_DIR = os.path.join(ROOT, "v3", "src", "test_runner", "modules") +OUTPUT = os.path.join(ROOT, "capsules", "v4", "post79.4th") +FIRST_BLOCK = 7000 +LINE_MAX = 64 + +# v3's POST order (v3/src/test_runner/test_runner.c, test_modules[]), the +# modules that test FORTH-79 words. +MODULES = [ + "stack_words_test.c", "return_stack_words_test.c", "memory_words_test.c", + "arithmetic_words_test.c", "logical_words_test.c", + "mixed_arithmetic_words_test.c", "double_words_test.c", + "format_words_test.c", "string_words_test.c", "io_words_test.c", + "block_words_test.c", "dictionary_words_test.c", + "dictionary_manipulation_words_test.c", "vocabulary_words_test.c", + "system_words_test.c", "defining_words_tests.c", "control_words_test.c", +] + +# The FORTH-79 Standard's Required Word Set, by the standard's own groups. +# Written from the standard's word list; check it against the document +# before relying on it for a claim of compliance. +REQUIRED = """ +DUP DROP SWAP OVER ROT PICK ROLL ?DUP DEPTH >R R> R@ +< = > 0< 0= 0> D< U< NOT ++ - * / MOD /MOD */ */MOD 1+ 1- 2+ 2- MAX MIN ABS NEGATE D+ DNEGATE +U* U/MOD AND OR XOR +@ ! C@ C! ? +! MOVE CMOVE FILL +DO LOOP +LOOP I J LEAVE IF ELSE THEN BEGIN UNTIL WHILE REPEAT EXIT EXECUTE +CR EMIT SPACE SPACES TYPE COUNT -TRAILING KEY EXPECT QUERY WORD +BASE DECIMAL . U. CONVERT <# # #S HOLD SIGN #> +LIST LOAD SCR BLOCK UPDATE BUFFER SAVE-BUFFERS EMPTY-BUFFERS +: ; VARIABLE CONSTANT VOCABULARY CREATE DOES> +CONTEXT CURRENT FORTH DEFINITIONS ' FIND FORGET +, ALLOT ." IMMEDIATE LITERAL STATE [ ] COMPILE [COMPILE] +( >IN ABORT QUIT HERE PAD BLK 79-STANDARD +""".split() + +# Words whose cases wait for the keyboard, which a boot cannot type at. +KEYBOARD = {"KEY", "EXPECT", "QUERY"} + +# ---- the harness: blocks FIRST_BLOCK up, FORTH-79 and the two nucleus hooks ---- +HARNESS = r""" +( post79.4th -- POST for the FORTH-79 Required Word Set on v4. ) +( Generated by v4/tools/mkpost.py from v3's POST cases: do not ) +( edit. docs/v4.0.0/NUCLEUS.md section 6. ) +VARIABLE T# VARIABLE TPASS VARIABLE TFAIL VARIABLE TOPEN +VARIABLE TBAD VARIABLE TWANT VARIABLE TLEN VARIABLE TSUM +VARIABLE TDEP VARIABLE TBASE +CREATE TBUF 64 ALLOT CREATE TSTK 16 ALLOT CREATE TNAME 8 ALLOT +0 T# ! 0 TPASS ! 0 TFAIL ! 0 TOPEN ! 10 TBASE ! +: TB ( -- baddr ) TBUF 4 * ; +: TN ( -- baddr ) TNAME 4 * ; +( T-EMIT is given every character a case prints: the first 255 ) +( are kept, all are counted and summed. ) +: T-EMIT ( c -- ) + DUP TSUM @ 31 * + 16777215 AND TSUM ! + TLEN @ 255 < IF TB TLEN @ + C! ELSE DROP THEN 1 TLEN +! ; +===== +: T-CLEAR ( i*x -- ) BEGIN DEPTH WHILE DROP REPEAT ; +: T. ( n -- ) 0 <# #S #> TYPE ; +( what a failing case printed, and the stack it left ) +: T-SHOW ( -- ) + ." out<" TB TLEN @ 255 MIN TYPE ." > stack<" + TDEP @ BEGIN DUP WHILE 1- DUP TSTK + @ . REPEAT DROP ." >" ; +( the verdict on the case that is open, if one is ) +: T-CLOSE ( -- ) + TOPEN @ IF + (CATCH) @ -1 = TWANT @ = 0= IF 1 TBAD ! THEN + TBAD @ IF 1 TFAIL +! + ." POST FAIL: " TN COUNT TYPE T-SHOW CR + ELSE 1 TPASS +! THEN + 0 TOPEN ! 0 (CATCH) ! TBASE @ BASE ! + THEN ; +===== +( T{ name begin a case: clean stack, errors caught ) +: T{ ( i*x -- ) T-CLOSE T-CLEAR + BL WORD COUNT 31 MIN DUP TN C! TN 1+ SWAP CMOVE + 1 T# +! 1 TOPEN ! 0 TBAD ! 0 TWANT ! 0 TLEN ! 0 TSUM ! + 0 TDEP ! 1 (CATCH) ! ; +( T| ... a line of the case, what it prints captured ) +: T| ' T-EMIT (EMIT-HOOK) ! ; IMMEDIATE +: T-END ( -- ) 0 (EMIT-HOOK) ! BASE @ TBASE ! DECIMAL ; +( -> ... the case is over: set its stack aside, top first ) +: -> ( i*x -- ) T-END 0 + BEGIN DEPTH 1 > WHILE + DUP 16 < IF SWAP OVER TSTK + ! ELSE SWAP DROP 1 TBAD ! THEN + 1+ REPEAT + 16 MIN TDEP ! ; +( ->ERR the case is over, and must have ended in an error ) +: ->ERR ( i*x -- ) T-END -1 TWANT ! T-CLEAR ; +===== +( ... }T the stack the case must have left, in order ) +: }T ( i*x -- ) + DEPTH TDEP @ = 0= IF 1 TBAD ! T-CLEAR EXIT THEN + 0 BEGIN DEPTH 1 > WHILE + SWAP OVER TSTK + @ = 0= IF 1 TBAD ! THEN 1+ REPEAT DROP ; +( len sum T= what the case must have printed ) +: T= ( len sum -- ) TSUM @ = 0= IF 1 TBAD ! THEN + TLEN @ = 0= IF 1 TBAD ! THEN ; +( the tally; a failure is an error, which ends the boot ) +: T-REPORT ( -- ) T-CLOSE 0 (CATCH) ! DECIMAL + ." PARITY:V4_POST tests=" T# @ T. ." pass=" TPASS @ T. + ." fail=" TFAIL @ T. CR + TFAIL @ IF -1 NODE-ERROR ! THEN ; +""" + + +# ---- reading v3's case tables ---------------------------------------------- + +TOKEN = re.compile(r''' + \s+ | /\*.*?\*/ | //[^\n]* | + (?P"(?:\\.|[^"\\])*") | + (?P[{}(),;=\[\]&*]) | + (?P[A-Za-z0-9_.+\-]+) +''', re.S | re.X) + +ESCAPES = {"n": "\n", "t": "\t", "\\": "\\", '"': '"', "r": "\r", "0": "\0"} + + +def unescape(lit): + out, i, body = [], 0, lit[1:-1] + while i < len(body): + if body[i] == "\\" and i + 1 < len(body): + out.append(ESCAPES.get(body[i + 1], body[i + 1])) + i += 2 + else: + out.append(body[i]) + i += 1 + return "".join(out) + + +def tokens(text): + pos, out = 0, [] + while pos < len(text): + m = TOKEN.match(text, pos) + if not m: + pos += 1 + continue + pos = m.end() + if m.group("str"): + value = unescape(m.group("str")) + if out and out[-1][0] == "str": # adjacent literals join + out[-1] = ("str", out[-1][1] + value) + else: + out.append(("str", value)) + elif m.group("punct"): + out.append(("punct", m.group("punct"))) + elif m.group("word"): + out.append(("word", m.group("word"))) + return out + + +def parse_braces(toks, i): + """toks[i] is '{'; returns (nested list, index after the matching '}').""" + items = [] + i += 1 + while toks[i] != ("punct", "}"): + if toks[i] == ("punct", "{"): + sub, i = parse_braces(toks, i) + items.append(sub) + elif toks[i] == ("punct", ","): + i += 1 + else: + items.append(toks[i][1] if toks[i][0] != "str" else ("s", toks[i][1])) + i += 1 + return items, i + 1 + + +def read_module(path): + """Yields (word, case name, input, should_error) for every implemented case.""" + toks = tokens(open(path, encoding="utf-8", errors="replace").read()) + for i, t in enumerate(toks): + if t != ("word", "WordTestSuite"): + continue + j = i + while j < len(toks) and toks[j] != ("punct", "=") and toks[j] != ("punct", ";") and toks[j] != ("punct", "("): + j += 1 + if j >= len(toks) or toks[j] != ("punct", "="): + continue + suites, _ = parse_braces(toks, j + 1) + for suite in suites: + if not isinstance(suite, list) or not suite or not isinstance(suite[0], tuple): + continue + word = suite[0][1] + for case in suite[1]: + if not isinstance(case, list) or len(case) < 6 or not isinstance(case[0], tuple): + continue + name, text = case[0][1], case[1][1] + should_error, implemented = case[4] != "0", case[5] != "0" + if implemented: + yield word, name, text, should_error + + +# ---- cutting a case's line to block lines ------------------------------------ + +STRING_OPENERS = {'."', 'S"', 'ABORT"', '.('} + + +def atoms(text): + """The line as pieces that must each stay on one line: a word, or a word + that takes text together with its text. None if the line has a new-line + inside such a text.""" + out, i, n = [], 0, len(text) + while i < n: + if text[i].isspace(): + i += 1 + continue + j = i + while j < n and not text[j].isspace(): + j += 1 + word = text[i:j] + upper = word.upper() + if upper in STRING_OPENERS or upper == "(": + close = ")" if upper in ("(", ".(") else '"' + k = text.find(close, j + 1 if j < n else j) + if k < 0: + k = n - 1 + piece = text[i:k + 1] + if "\n" in piece: + return None + out.append(piece) + i = k + 1 + elif word == "\\": + break # the rest of the line is a comment + else: + out.append(word) + i = j + return out + + +def pack(prefix, pieces, width=LINE_MAX): + """Pieces into lines no longer than `width`, each begun with `prefix` + (which may be empty). None if a piece cannot fit on a line.""" + head = [prefix] if prefix else [] + lines, current = [], [] + for piece in pieces: + if len(" ".join(head + [piece])) > width: + return None + if current and len(" ".join(head + current + [piece])) > width: + lines.append(current) + current = [] + current.append(piece) + if current: + lines.append(current) + return [" ".join(head + line) for line in lines] + + +# A store to the search order, which v3's C test runner survives and a +# running FORTH system does not. +DAMAGES = re.compile(r"\b(CONTEXT|CURRENT)\s+!") + + +def forgets_system_word(text): + """True if the line FORGETs a word it did not itself define. In a plain + v3 session that takes the rest of the system with it, and v4 refuses.""" + words = text.split() + for i, word in enumerate(words[:-1]): + if word.upper() == "FORGET": + target = words[i + 1] + made = any(words[k] == target and k > 0 and words[k - 1].upper() in + (":", "CREATE", "VARIABLE", "CONSTANT", "VOCABULARY") for k in range(i)) + if not made: + return True + return False + + +# ---- what v3 does -------------------------------------------------------------- + +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 ;"] + for n, case in enumerate(cases): + script.append('TCLR ." [[B%d]]"' % n) + script.extend(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", capture_output=True, + text=True, errors="replace", timeout=600) + text = ANSI.sub("", done.stdout) + results = [] + for n, case in enumerate(cases): + begin, mid, end = "[[B%d]] ok\nok> " % n, "ok> [[E%d]]" % n, "[[S%d]]" % n + b = text.find(begin) + e = text.find(mid, b) if b >= 0 else -1 + s = text.find(end, e) if e >= 0 else -1 + if b < 0 or e < 0 or s < 0: + results.append(None) + continue + body = text[b + len(begin):e] + # one "ok> " and one " ok" or " ERROR" for every line of the case + chunks = body.split("ok> ") + output, error, ok = "", False, True + for chunk in chunks: + if chunk.endswith(" ERROR\n"): + output += chunk[:-len(" ERROR\n")] + error = True + elif chunk.endswith(" ok\n"): + output += chunk[:-len(" ok\n")] + else: + ok = False + m = re.match(r"<(\d+)>((?: -?\d+)*) \n", text[e + len(mid):s]) + if not ok or not m: + results.append(None) + continue + stack = [int(v) for v in m.group(2).split()] + results.append((error, stack[:-1], output)) # the last value is BASE + return results + + +def checksum(output): + total = 0 + for ch in output.encode("latin-1", errors="replace"): + total = (total * 31 + ch) & 0xFFFFFF + return total + + +# ---- writing the capsule ------------------------------------------------------- + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--v3", default=os.path.join(ROOT, "lfs", "amd64", "starforth")) + ap.add_argument("--report", default=None) + args = ap.parse_args() + + required, left_out, cases, seen = set(REQUIRED), [], [], {} + for module in MODULES: + for word, name, text, should_error in read_module(os.path.join(MODULE_DIR, module)): + if word not in required: + continue + label = ("%s.%s" % (word, name))[:31] + seen[label] = seen.get(label, 0) + 1 + if seen[label] > 1: + label = (label[:28] + "~%d" % seen[label])[:31] + if word in KEYBOARD: + left_out.append((label, "reads the keyboard")) + continue + if forgets_system_word(text): + left_out.append((label, "forgets a word of the system")) + continue + if DAMAGES.search(text.upper()): + left_out.append((label, "damages the system on purpose")) + continue + pieces = atoms(text) + lines = pack("T|", pieces) if pieces is not None else None + if not lines: + left_out.append((label, "a line cannot be cut to fit a block line")) + continue + cases.append({"label": label, "word": word, "text": text, "lines": lines, "should_error": should_error}) + + # v3 is run until every case left is one it gets through + while True: + results = run_v3(args.v3, cases) + bad = [i for i, r in enumerate(results) if r is None] + if not bad: + break + first = bad[0] + left_out.append((cases[first]["label"], "v3 did not get through it in one session")) + del cases[first] + + blocks, current = [], [] + + def flush(): + if current: + blocks.append(list(current)) + del current[:] + + for part in HARNESS.strip("\n").split("=====\n"): + current.extend(part.strip("\n").split("\n")) + flush() + + disagreements = [] + for case, (error, stack, output) in zip(cases, results): + if error != case["should_error"]: + disagreements.append((case["label"], "v3's table says %s, v3 %s" + % ("error" if case["should_error"] else "no error", + "raised one" if error else "raised none"))) + lines = ["T{ " + case["label"]] + case["lines"] + if error: + lines.append("->ERR") + else: + tail = ["->"] + [str(v) for v in stack] + ["}T", str(len(output)), str(checksum(output)), "T="] + lines.extend(pack("", tail)) + if len(current) + len(lines) > 16: + flush() + current.extend(lines) + flush() + blocks.append(["T-REPORT", "FORGET T# DECIMAL"]) + + with open(OUTPUT, "w", encoding="ascii") as out: + for k, block in enumerate(blocks): + assert len(block) <= 16, block + out.write("Block %d\n" % (FIRST_BLOCK + k)) + for line in block: + assert len(line) <= LINE_MAX, line + out.write(line + "\n") + + tested = sorted({c["word"] for c in cases}) + untested = [w for w in REQUIRED if w not in set(tested)] + report = ["POST cases: %d, in %d blocks (%d to %d)" % (len(cases), len(blocks), FIRST_BLOCK, FIRST_BLOCK + len(blocks) - 1), + "Required words with at least one case: %d of %d" % (len(tested), len(REQUIRED)), + "Required words with no case: " + " ".join(untested), "", + "Left out (%d):" % len(left_out)] + report += [" %-32s %s" % item for item in left_out] + report += ["", "v3 did not do what its own table expects (%d):" % len(disagreements)] + report += [" %-32s %s" % item for item in disagreements] + text = "\n".join(report) + "\n" + if args.report: + open(args.report, "w").write(text) + sys.stdout.write(text) + + +if __name__ == "__main__": + main()