 DEFER: @pos-digit
 DEFER: @neg-digit
 
-: @exponent-digit-or-punc ( float-parse i number-parse n char -- float-parse number/f )
+: @exponent-digit-or-punc ( float-parse i number-parse n char -- float-parse n/f )
     {
         { CHAR: , [ [ @exponent-digit ] require-next-digit ] }
         [ @exponent-digit ]
-    } case ; inline recursive
-
-: @exponent-digit ( float-parse i number-parse n char -- float-parse number/f )
-    digit-in-radix [ [ @exponent-digit-or-punc ] add-digit ] [ @abort ] if ; inline recursive
-
-: @exponent-first-char ( float-parse i number-parse n char -- float-parse number/f )
+    } case ; inline
+
+: @exponent-digit ( float-parse i number-parse n char -- float-parse n/f )
+    { float-parse fixnum number-parse integer fixnum } declare
+    digit-in-radix [ [ @exponent-digit-or-punc ] add-digit ] [ @abort ] if ;
+
+: @exponent-first-char ( float-parse i number-parse n char -- float-parse n/f )
     {
         { CHAR: - [ [ @exponent-digit ] require-next-digit ?neg ] }
         [ @exponent-digit ]
-    } case ; inline recursive
-
-: ->exponent ( float-parse i number-parse n -- float-parse' number/f )
+    } case ; inline
+
+: ->exponent ( float-parse i number-parse n -- float-parse' n/f )
     @split-exponent [ @exponent-first-char ] require-next-digit ?store-exponent ; inline
 
 : exponent-char? ( number-parse n char -- number-parse n char ? )

        [ drop [ CHAR: p CHAR: P ] dip [ = ] curry either? ]
    } case ; inline

: or-exponent ( i number-parse n char quot -- number/f )
    ! call ; inline
    [ exponent-char? [ drop <float-parse> ->exponent ?make-float ] ] dip if ; inline
: or-mantissa->exponent ( float-parse i number-parse n char quot -- float-parse number/f )
    ! call ; inline
    [ exponent-char? [ drop ->exponent ] ] dip if ; inline

: @mantissa-digit-or-punc ( float-parse i number-parse n char -- float-parse number/f )
    {
        { CHAR: , [ [ @mantissa-digit ] require-next-digit ] }
        [ @mantissa-digit ]
    } case ; inline recursive

: @mantissa-digit ( float-parse i number-parse n char -- float-parse number/f )
    [
        digit-in-radix
        [ [ @mantissa-digit-or-punc ] add-mantissa-digit ]
        [ @abort ] if
    ] or-mantissa->exponent ; inline recursive

: ->mantissa ( i number-parse n -- number/f )
    <float-parse> [ @mantissa-digit ] next-digit ?make-float ; inline

: ->required-mantissa ( i number-parse n -- number/f )
    <float-parse> [ @mantissa-digit ] require-next-digit ?make-float ; inline

: @denom-digit-or-punc ( i number-parse n char -- number/f )
    {
        { CHAR: , [ [ @denom-digit ] require-next-digit ] }
        { CHAR: . [ ->mantissa ] }
        [ [ @denom-digit ] or-exponent ]
    } case ; inline recursive

: @denom-digit ( i number-parse n char -- number/f )
    digit-in-radix [ [ @denom-digit-or-punc ] add-digit ] [ @abort ] if ; inline recursive

: @denom-first-digit ( i number-parse n char -- number/f )
    {
        { CHAR: . [ ->mantissa ] }
        [ @denom-digit ]
    } case ; inline recursive

: ->denominator ( i number-parse n -- number/f )
    @split [ @denom-first-digit ] require-next-digit ?make-ratio ; inline

: @num-digit-or-punc ( i number-parse n char -- number/f )
    {
        { CHAR: , [ [ @num-digit ] require-next-digit ] }
        { CHAR: / [ ->denominator ] }
        [ @num-digit ]
    } case ; inline recursive

: @num-digit ( i number-parse n char -- number/f )
    digit-in-radix [ [ @num-digit-or-punc ] add-digit ] [ @abort ] if ; inline recursive

: ->numerator ( i number-parse n -- number/f )
    @split [ @num-digit ] require-next-digit ?add-ratio ; inline

: @pos-digit-or-punc ( i number-parse n char -- number/f )
    {
        { CHAR: , [ [ @pos-digit ] require-next-digit ] }
        { CHAR: + [ ->numerator ] }
        { CHAR: / [ ->denominator ] }
        { CHAR: . [ ->mantissa ] }
        [ [ @pos-digit ] or-exponent ]
    } case ; inline recursive

: @pos-digit ( i number-parse n char -- number/f )
    digit-in-radix [ [ @pos-digit-or-punc ] add-digit ] [ @abort ] if ; inline recursive

: @pos-first-digit ( i number-parse n char -- number/f )
    {
        { CHAR: . [ ->required-mantissa ] }
        [ @pos-digit ]
    } case ; inline recursive

: @neg-digit-or-punc ( i number-parse n char -- number/f )
    {
        { CHAR: , [ [ @neg-digit ] require-next-digit ] }
        { CHAR: - [ ->numerator ] }
        { CHAR: / [ ->denominator ] }
        { CHAR: . [ ->mantissa ] }
        [ [ @neg-digit ] or-exponent ]
    } case ; inline recursive

: @neg-digit ( i number-parse n char -- number/f )
    digit-in-radix [ [ @neg-digit-or-punc ] add-digit ] [ @abort ] if ; inline recursive

: @neg-first-digit ( i number-parse n char -- number/f )
    {
        { CHAR: . [ ->required-mantissa ] }
        [ @neg-digit ]
    } case ; inline recursive

: @first-char ( i number-parse n char -- number/f ) 
    {
        { CHAR: - [ [ @neg-first-digit ] require-next-digit ?neg ] }
        [ @pos-first-digit ]
    } case ; inline recursive

PRIVATE>

: base> ( str radix -- number/f )
    <number-parse> [ @first-char ] require-next-digit ;

: string>number ( str -- number/f ) 10 base> ; inline

: bin> ( str -- number/f )  2 base> ; inline
: oct> ( str -- number/f )  8 base> ; inline
: dec> ( str -- number/f ) 10 base> ; inline
: hex> ( str -- number/f ) 16 base> ; inline

: string>digits ( str -- digits )
    [ digit> ] B{ } map-as ; inline

: (digits>integer) ( valid? accum digit radix -- valid? accum )
    2dup < [ swapd * + ] [ 2drop 2drop f 0 ] if ; inline

: each-digit ( seq radix quot -- n/f )
    [ t 0 ] 3dip curry each swap [ drop f ] unless ; inline

: digits>integer ( seq radix -- n/f )
    [ (digits>integer) ] each-digit ; inline

: >digit ( n -- ch )
    dup 10 < [ CHAR: 0 + ] [ 10 - CHAR: a + ] if ; inline

: positive>base ( num radix -- str )
    dup 1 <= [ "Invalid radix" throw ] when
    [ dup 0 > ] swap [ /mod >digit ] curry "" produce-as nip
    reverse! ; inline

GENERIC# >base 1 ( n radix -- str )


: >hex ( n -- str ) 16 >base ; inline

: # ( n -- ) number>string % ; inline
