Fleet Forth conforms to the Forth-83 Standard, which seems more appropriate considering when the C64 came out, and I like the Forth-83 Standard better. Since Fleet Forth conforms to the Forth-83 Standard, I didn't include the form 'c'. I didn't want to add that much extra code. I use ASCII , the immediate state smart word replaced by CHAR and [CHAR] in the new standard.
Since Fleet Forth conforms to the Forth-83 Standard, there are some differences in how numeric strings are handled. The leading count is ignored and the numeric string must have a trailing space.
Yes, I put the value of BASE on the return stack, or rather, I used a word that did. Fleet Forth has the word RB (restore base). When RB is used in a word, whatever the base was prior to executing RB is restored when that word exits, unless it aborts. -NUMBER never aborts. It passes a flag, FALSE for successful conversion, TRUE if it failed.
RB uses the word CO (coroutine).
Code: Select all
// COROUTINES
: CO 2R> SWAP 2>R ;
// RESTORE BASE AT END OF WORD
// CALLING RB
: RB ( -- )
BASE @ R> 2>R CO
R> BASE ! ;
Here is the original version of -NUMBER
Code: Select all
: -NUMBER ( ADR -- D FLAG )
DPL ON 0 0 ROT
DUP 1+ C@ ASCII - =
DUP>R - DUP>R
BEGIN
CONVERT DUP C@ VALID?
WHILE
DUP 1+ C@ VALID? 0=
WHILE
DPL OFF
REPEAT
THEN
DUP C@ BL <> SWAP
2- DPL @ 0< - R> = OR
R> 0EXIT >R DNEGATE R> ;
Here is the modified version of -NUMBER
Code: Select all
HEX
NH
CREATE BASE.TABLE
0A C, 10 C, 2 C,
: -NUMBER ( ADR -- D FLAG )
RB
DUP 1+ C@ ASCII # - DUP 3 U<
IF
BASE.TABLE + C@ BASE !
1+ DUP
THEN
DROP
DPL ON 0 0 ROT
DUP 1+ C@ ASCII - =
DUP>R - DUP>R
BEGIN
CONVERT DUP C@ VALID?
WHILE
DUP 1+ C@ VALID? 0=
WHILE
DPL OFF
REPEAT
THEN
DUP C@ BL <> SWAP
2- DPL @ 0< - R> = OR
R> 0EXIT >R DNEGATE R> ;
NH is a metacompiler word that causes the following word to be compiled without a header.
VALID? is a word that takes a character and returns a true flag if it is valid punctuation for a number. It is a deferred word and the default is to only accept a period as valid.
For completeness, here is the source for CONVERT
Code: Select all
: CONVERT ( D1 ADR1 -- D2 ADR2 )
1+
BEGIN
COUNT BASE @ DIGIT
WHILE
2SWAP BASE @ *
SWAP BASE @ UM* D+
ROT
DPL @ 0< 1+ DPL +!
REPEAT
1- ;
DIGIT takes the character to be converted and the number base to use. It returns the digit as a single cell number and a true flag or just a false flag if the character is not a digit in the specified base.
( CHR #BASE -- N TF )
( CHR #BASE -- FF )