<#, #>, #, #S, SIGN, HOLD

This commit is contained in:
Remko Tronçon 2022-05-01 11:57:42 +02:00
parent ba5bff8a99
commit ed469cbef4
3 changed files with 155 additions and 68 deletions

View file

@ -818,57 +818,57 @@ TESTING <# # #S #> HOLD SIGN BASE >NUMBER HEX DECIMAL
R> DROP 2DROP <FALSE> \ LENGTHS MISMATCH
THEN ;
\ TODO : GP1 <# 41 HOLD 42 HOLD 0 0 #> S" BA" S= ;
\ TODO T{ GP1 -> <TRUE> }T
\ TODO
\ TODO : GP2 <# -1 SIGN 0 SIGN -1 SIGN 0 0 #> S" --" S= ;
\ TODO T{ GP2 -> <TRUE> }T
\ TODO
\ TODO : GP3 <# 1 0 # # #> S" 01" S= ;
\ TODO T{ GP3 -> <TRUE> }T
\ TODO
\ TODO : GP4 <# 1 0 #S #> S" 1" S= ;
\ TODO T{ GP4 -> <TRUE> }T
: GP1 <# 41 HOLD 42 HOLD 0 0 #> S" BA" S= ;
T{ GP1 -> <TRUE> }T
: GP2 <# -1 SIGN 0 SIGN -1 SIGN 0 0 #> S" --" S= ;
T{ GP2 -> <TRUE> }T
: GP3 <# 1 0 # # #> S" 01" S= ;
T{ GP3 -> <TRUE> }T
: GP4 <# 1 0 #S #> S" 1" S= ;
T{ GP4 -> <TRUE> }T
24 CONSTANT MAX-BASE \ BASE 2 .. 36
: COUNT-BITS
0 0 INVERT BEGIN DUP WHILE >R 1+ R> 2* REPEAT DROP ;
COUNT-BITS 2* CONSTANT #BITS-UD \ NUMBER OF BITS IN UD
\ TODO : GP5
\ TODO BASE @ <TRUE>
\ TODO MAX-BASE 1+ 2 DO \ FOR EACH POSSIBLE BASE
\ TODO I BASE ! \ TBD: ASSUMES BASE WORKS
\ TODO I 0 <# #S #> S" 10" S= AND
\ TODO LOOP
\ TODO SWAP BASE ! ;
\ TODO T{ GP5 -> <TRUE> }T
\ TODO
\ TODO : GP6
\ TODO BASE @ >R 2 BASE !
\ TODO MAX-UINT MAX-UINT <# #S #> \ MAXIMUM UD TO BINARY
\ TODO R> BASE ! \ S: C-ADDR U
\ TODO DUP #BITS-UD = SWAP
\ TODO 0 DO \ S: C-ADDR FLAG
\ TODO OVER C@ [CHAR] 1 = AND \ ALL ONES
\ TODO >R CHAR+ R>
\ TODO LOOP SWAP DROP ;
\ TODO T{ GP6 -> <TRUE> }T
\ TODO
\ TODO : GP7
\ TODO BASE @ >R MAX-BASE BASE !
\ TODO <TRUE>
\ TODO A 0 DO
\ TODO I 0 <# #S #>
\ TODO 1 = SWAP C@ I 30 + = AND AND
\ TODO LOOP
\ TODO MAX-BASE A DO
\ TODO I 0 <# #S #>
\ TODO 1 = SWAP C@ 41 I A - + = AND AND
\ TODO LOOP
\ TODO R> BASE ! ;
\ TODO
\ TODO T{ GP7 -> <TRUE> }T
: GP5
BASE @ <TRUE>
MAX-BASE 1+ 2 DO \ FOR EACH POSSIBLE BASE
I BASE ! \ TBD: ASSUMES BASE WORKS
I 0 <# #S #> S" 10" S= AND
LOOP
SWAP BASE ! ;
T{ GP5 -> <TRUE> }T
: GP6
BASE @ >R 2 BASE !
MAX-UINT MAX-UINT <# #S #> \ MAXIMUM UD TO BINARY
R> BASE ! \ S: C-ADDR U
DUP #BITS-UD = SWAP
0 DO \ S: C-ADDR FLAG
OVER C@ [CHAR] 1 = AND \ ALL ONES
>R CHAR+ R>
LOOP SWAP DROP ;
T{ GP6 -> <TRUE> }T
: GP7
BASE @ >R MAX-BASE BASE !
<TRUE>
A 0 DO
I 0 <# #S #>
1 = SWAP C@ I 30 + = AND AND
LOOP
MAX-BASE A DO
I 0 <# #S #>
1 = SWAP C@ 41 I A - + = AND AND
LOOP
R> BASE ! ;
T{ GP7 -> <TRUE> }T
\ >NUMBER TESTS
CREATE GN-BUF 0 C,
@ -893,17 +893,17 @@ T{ 0 0 GN' G' 10 >NUMBER-BASED -> 0 0 GN-STRING }T
T{ 0 0 GN' G' MAX-BASE >NUMBER-BASED -> 10 0 GN-CONSUMED }T
T{ 0 0 GN' Z' MAX-BASE >NUMBER-BASED -> 23 0 GN-CONSUMED }T
\ TODO : GN1 \ ( UD BASE -- UD' LEN ) UD SHOULD EQUAL UD' AND LEN SHOULD BE ZERO.
\ TODO BASE @ >R BASE !
\ TODO <# #S #>
\ TODO 0 0 2SWAP >NUMBER SWAP DROP \ RETURN LENGTH ONLY
\ TODO R> BASE ! ;
\ TODO T{ 0 0 2 GN1 -> 0 0 0 }T
\ TODO T{ MAX-UINT 0 2 GN1 -> MAX-UINT 0 0 }T
\ TODO T{ MAX-UINT DUP 2 GN1 -> MAX-UINT DUP 0 }T
\ TODO T{ 0 0 MAX-BASE GN1 -> 0 0 0 }T
\ TODO T{ MAX-UINT 0 MAX-BASE GN1 -> MAX-UINT 0 0 }T
\ TODO T{ MAX-UINT DUP MAX-BASE GN1 -> MAX-UINT DUP 0 }T
: GN1 \ ( UD BASE -- UD' LEN ) UD SHOULD EQUAL UD' AND LEN SHOULD BE ZERO.
BASE @ >R BASE !
<# #S #>
0 0 2SWAP >NUMBER SWAP DROP \ RETURN LENGTH ONLY
R> BASE ! ;
T{ 0 0 2 GN1 -> 0 0 0 }T
T{ MAX-UINT 0 2 GN1 -> MAX-UINT 0 0 }T
T{ MAX-UINT DUP 2 GN1 -> MAX-UINT DUP 0 }T
T{ 0 0 MAX-BASE GN1 -> 0 0 0 }T
T{ MAX-UINT 0 MAX-BASE GN1 -> MAX-UINT 0 0 }T
T{ MAX-UINT DUP MAX-BASE GN1 -> MAX-UINT DUP 0 }T
: GN2 \ ( -- 16 10 )
BASE @ >R HEX BASE @ DECIMAL BASE @ R> BASE ! ;

View file

@ -85,6 +85,7 @@
;; RETURN_STACK_BASE := 0x2000
;; STACK_BASE := 0x10000
;; STRINGS_BASE := 0x20000
;; PICTURED_OUTPUT_BASE := 0x21000 (filled backward)
;; DICTIONARY_BASE := 0x21000
(memory (export "memory") 1600 (; = MEMORY_SIZE_PAGES ;))
@ -214,16 +215,49 @@
(data (i32.const 0x21000 (; = DICTIONARY_BASE ;)) "\00\00\00\00\01!\00\00\10\00\00\00")
(elem (i32.const 0x10) $!)
(func $# (param $tos i32) (result i32)
(call $fail (local.get $tos) (i32.const 0x20084))) ;; not implemented
(func $# (param $tos i32) (result i32)
(local $v i64)
(local $base i64)
(local $bbtos i32)
(local $m i64)
(local $npo i32)
(local.set $base (i64.extend_i32_u (i32.load (i32.const 0x100 (; = BASE_BASE ;)))))
(local.set $v (i64.load (local.tee $bbtos (i32.sub (local.get $tos) (i32.const 8)))))
(local.set $m (i64.rem_u (local.get $v) (local.get $base)))
(local.set $v (i64.div_u (local.get $v) (local.get $base)))
(i32.store8 (local.tee $npo (i32.sub (global.get $po) (i32.const 1)))
(call $numberToChar (i32.wrap_i64 (local.get $m))))
(i64.store (local.get $bbtos) (local.get $v))
(global.set $po (local.get $npo))
(local.get $tos))
(data (i32.const 135180) "\00\10\02\00\01#\00\00\11\00\00\00")
(elem (i32.const 0x11) $#)
(func $#> (param $tos i32) (result i32) (call $fail (local.get $tos) (i32.const 0x20084))) ;; not implemented
(func $#> (param $tos i32) (result i32)
(i32.store (i32.sub (local.get $tos) (i32.const 8)) (global.get $po))
(i32.store (i32.sub (local.get $tos) (i32.const 4)) (i32.sub (i32.const 0x21000 (; = PICTURED_OUTPUT_BASE ;)) (global.get $po)))
(local.get $tos))
(data (i32.const 135192) "\0c\10\02\00\02#>\00\12\00\00\00")
(elem (i32.const 0x12) $#>)
(func $#S (param $tos i32) (result i32) (call $fail (local.get $tos) (i32.const 0x20084))) ;; not implemented
(func $#S (param $tos i32) (result i32)
(local $v i64)
(local $base i64)
(local $bbtos i32)
(local $m i64)
(local $po i32)
(local.set $base (i64.extend_i32_u (i32.load (i32.const 0x100 (; = BASE_BASE ;)))))
(local.set $v (i64.load (local.tee $bbtos (i32.sub (local.get $tos) (i32.const 8)))))
(local.set $po (global.get $po))
(loop $loop
(local.set $m (i64.rem_u (local.get $v) (local.get $base)))
(local.set $v (i64.div_u (local.get $v) (local.get $base)))
(i32.store8 (local.tee $po (i32.sub (local.get $po) (i32.const 1)))
(call $numberToChar (i32.wrap_i64 (local.get $m))))
(br_if $loop (i64.ne (local.get $v) (i64.const 0))))
(i64.store (local.get $bbtos) (local.get $v))
(global.set $po (local.get $po))
(local.get $tos))
(data (i32.const 135204) "\18\10\02\00\02#S\00\13\00\00\00")
(elem (i32.const 0x13) $#S)
@ -549,7 +583,8 @@
(elem (i32.const 0x2f) $<)
(func $<# (param $tos i32) (result i32)
(call $fail (local.get $tos) (i32.const 0x20084))) ;; not implemented
(global.set $po (i32.const 0x21000 (; = PICTURED_OUTPUT_BASE ;)))
(local.get $tos))
(data (i32.const 135580) "\90\11\02\00\02<#\000\00\00\00")
(elem (i32.const 0x30) $<#)
@ -942,6 +977,7 @@
(data (i32.const 136164) "\d4\13\02\00" "\2b" (; HIDDEN ;) "UNUSED1____" "X\00\00\00")
(elem (i32.const 0x58) $UNUSED1)
;; 6.1.1345
(func $ENVIRONMENT? (param $tos i32) (result i32)
(local $addr i32)
(local $len i32)
@ -1111,7 +1147,13 @@
(elem (i32.const 0x5f) $HERE)
(func $HOLD (param $tos i32) (result i32)
(call $fail (local.get $tos) (i32.const 0x20084))) ;; not implemented
(local $btos i32)
(local $npo i32)
(i32.store8
(local.tee $npo (i32.sub (global.get $po) (i32.const 1)))
(i32.load (local.tee $btos (i32.sub (local.get $tos) (i32.const 4)))))
(global.set $po (local.get $npo))
(local.get $btos))
(data (i32.const 136300) "\5c\14\02\00\04HOLD\00\00\00`\00\00\00")
(elem (i32.const 0x60) $HOLD)
@ -1406,7 +1448,13 @@
;; 6.1.2210
(func $SIGN (param $tos i32) (result i32)
(call $fail (local.get $tos) (i32.const 0x20084))) ;; not implemented
(local $btos i32)
(local $npo i32)
(if (i32.lt_s (i32.load (local.tee $btos (i32.sub (local.get $tos) (i32.const 4)))) (i32.const 0))
(then
(i32.store8 (local.tee $npo (i32.sub (global.get $po) (i32.const 1))) (i32.const 0x2D (; '-' ;)))
(global.set $po (local.get $npo))))
(local.get $btos))
(data (i32.const 136716) "\00\16\02\00\04SIGN\00\00\00}\00\00\00")
(elem (i32.const 0x7d) $SIGN)
@ -1835,11 +1883,7 @@
(if (i32.eqz (local.get $v))
(then)
(else (call $U._ (local.get $v) (local.get $base))))
(if (i32.ge_u (local.get $m) (i32.const 10))
(then
(call $shell_emit (i32.add (local.get $m) (i32.const 0x37))))
(else
(call $shell_emit (i32.add (local.get $m) (i32.const 0x30))))))
(call $shell_emit (call $numberToChar (local.get $m))))
;; 15.6.1.0220
(func $.S (param $tos i32) (result i32)
@ -2058,6 +2102,8 @@
(global $here (mut i32) (i32.const 0x218c4))
(global $nextTableIndex (mut i32) (i32.const 0xaa (; = NEXT_TABLE_INDEX ;)))
;; Pictured output pointer
(global $po (mut i32) (i32.const -1))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Compiler functions
@ -2688,6 +2734,12 @@
(return (local.get $n))))
(unreachable))
(func $numberToChar (param $v i32) (result i32)
(if (result i32) (i32.ge_u (local.get $v) (i32.const 10))
(then
(i32.add (local.get $v) (i32.const 0x37)))
(else
(i32.add (local.get $v) (i32.const 0x30)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; API Functions

View file

@ -1522,6 +1522,41 @@ function loadTests() {
});
});
describe("HOLD", () => {
it("should work", () => {
run("<# 65 HOLD 66 HOLD 0 0 #> TYPE");
expect(output.trim()).to.eql("BA");
expect(stackValues()).to.eql([]);
});
});
describe("SIGN", () => {
it("should support positive", () => {
run("<# 65 HOLD 123 SIGN 66 HOLD 0 0 #> TYPE");
expect(output.trim()).to.eql("BA");
expect(stackValues()).to.eql([]);
});
it("should support negative", () => {
run("<# 65 HOLD -123 SIGN 66 HOLD 0 0 #> TYPE");
expect(output.trim()).to.eql("B-A");
expect(stackValues()).to.eql([]);
});
});
describe("#", () => {
it("should work", () => {
run("<# 123 0 # #> TYPE");
expect(output.trim()).to.eql("3");
expect(stackValues()).to.eql([]);
});
});
it("should work", () => {
run("<# 12345 0 # # 46 HOLD #S #> TYPE");
expect(output.trim()).to.eql("123.45");
});
describe("system", () => {
it("should run sieve", () => {
run(sieve);