### ----------------------------------------------------
### -- Intl::Format::Number
### -- Licenses: Artistic-2.0
### -- Authors: Matthew Stephen Stuckwisch
### -- File: lib/Intl/Format/Number.rakumod
### ----------------------------------------------------
### -- Chunk 2 of 3
ApplyInfix.new(
                :left(RakuAST::Var::Lexical.new('$power')),
                :infix(Minus),
                :right(MaxSigDigs)
            )
        ),
    :calculated);

    my $integer-digits = RakuAST::Statement::Expression.new(
        expression => RakuAST::ApplyInfix.new( :left(Result), :infix(Assign),
            right => rast-transliterate-wrap(
                RakuAST::ApplyInfix.new( :left(Result), :infix(Concat),
                    right => RakuAST::Ternary.new(
                        condition => RakuAST::ApplyInfix.new(:left(RakuAST::Var::Lexical.new('$power')), :infix(Greater), :right(Zero)),
                        then => RakuAST::ApplyPostfix.new(
                            postfix => MakeStr,
                            operand => RakuAST::ApplyPostfix.new( postfix => FloorMethod, operand => Var_N)
                        ),
                        else => RakuAST::StrLiteral.new('0'),
                    )
                ),
                \number-system
            )
        )
    );
    my $remove-integer-digits = RakuAST::Statement::Expression.new(
        expression => RakuAST::ApplyInfix.new( :left(Var_N), :infix(Assign),
            right => RakuAST::ApplyInfix.new(:left(Var_N), :infix(Minus),
                right => RakuAST::ApplyPostfix.new( :operand(Var_N), :postfix(FloorMethod))
    )   )   );
    my $completed-digits-declare = RakuAST::Statement::Expression.new(
        expression => RakuAST::VarDeclaration::Simple.new( :scope<my>, :name<$completed-digits>,
            initializer => RakuAST::Initializer::Bind.new(
                RakuAST::ApplyInfix.new( :left(RakuAST::Var::Lexical.new('$power')), :infix(RakuAST::Infix.new('max')), :right(Zero))
    )   )   );

    #| $result = $result.substr(0…) ~ GROUPER ~ $result.substr(…*) and $grouping-location -= $secondary-grouping
    #| while $grouping-location > 0;
    my @int-grouping := $needs-grouper
        ?? (RakuAST::Statement::Expression.new(
                expression => RakuAST::VarDeclaration::Simple.new( :scope<my>, :name<$grouping-location>,
                    initializer => RakuAST::Initializer::Bind.new(
                        RakuAST::ApplyInfix.new(
                            left => RakuAST::ApplyPostfix.new( :operand(Result),
                                postfix => RakuAST::Call::Method.new( name => RakuAST::Name.from-identifier('chars') )
                            ),
                            infix => Minus,
                            right => RakuAST::IntLiteral.new(format<primary-grouping-digits>)
                        )
                    )
                )
            ),
            RakuAST::Statement::Expression.new(
                expression => RakuAST::ApplyInfix.new(
                    left => RakuAST::ApplyInfix.new(
                        left => Result,
                        infix => Assign,
                        right => RakuAST::ApplyListInfix.new(
                            infix => Concat,
                            operands => (
                                RakuAST::ApplyPostfix(operand => Result,
                                    postfix => RakuAST::Call::Method.new(
                                        name => RakuAST::Name.from-identifier('substr'),
                                        args => RakuAST::ArgList.new((Zero,RakuAST::Var::Lexical.new('$grouping-location')))
                                    )
                                ),
                                RakuAST::StrLiteral.new(symbols.group),
                                RakuAST::ApplyPostfix(operand => Result,
                                    postfix => RakuAST::Call::Method.new(
                                        name => RakuAST::Name.from-identifier('substr'),
                                        args => RakuAST::ArgList.new(Zero)
                                    )
                                ),
                            ),
                        )
                    ),
                    infix => RakuAST::Infix.new('and'),
                    right => RakuAST::ApplyInfix.new(
                        left => RakuAST::ApplyInfix.new(
                            left => RakuAST::VarLexical.new('$grouping-location'),
                            infix => Assign,
                            right => RakuAST::ApplyInfix.new(
                                left => RakuAST::VarLexical.new('$grouping-location'),
                                infix => Minus,
                                right => RakuAST::IntLiteral.new(format<secondary-grouping-size>)
                            )
                        ),
                        infix => RakuAST::Infix.new('and'),
                        right => RakuAST::ApplyInfix.new(
                            left => RakuAST::VarLexical.new('$completed-digits'),
                            infix => Assign,
                            right => RakuAST::ApplyInfix.new( left =>RakuAST::VarLexical.new('$completed-digits'), :infix(Plus), :right(One))
                        )
                    )
                ),
                loop-modifier => RakuAST::StatementModifier::While.new(
                    RakuAST::ApplyInfix.new( :left(RakuAST::Var::Lexical.new: '$grouping-location'), :infix(LessThan), :right(Zero))
                )
            )
        )
        !! Empty;

        #| $n = $n * 10 ** -($power - $max-significant-digits);
        #| my $digit-difference = $max-significant-digits - $min-significant-digits;
        #| my $fractional-mod-difference = $n % 10 ** $digit-difference;
        #| my $fractional-digits-to-strip = 0;
        #| my $fractional-modder = 10;
        #| for ^$digit-difference {
        #|     last if $fractional-mod-difference % $fractional-modder > 0;
        #|     $fractional-digits-to-strip++;
        #|     $fractional-modder *= 10;
        #| }
        my @fractional-digits = RakuAST::Statement::Expression.new(
            expression => RakuAST::ApplyInfix.new( :left(Var_N), :infix(Assign),
                right => RakuAST::ApplyInfix.new( :left(Var_N), :infix(Times),
                    right => RakuAST::ApplyInfix.new( :left(Ten), :infix(Power),
                        right => RakuAST::ApplyPrefix.new( prefix => RakuAST::Prefix.new('-'),
                            operand => RakuAST::ApplyInfix.new( :infix(Minus),
                                left => RakuAST::Var::Lexical.new('$power'),
                                right => MaxSigDigs
        )   )   )   )   )   ),
        RakuAST::Statement::Expression.new(
            expression => RakuAST::VarDeclaration::Simple.new( :scope<my>, :name<$digit-difference>,
                initializer => RakuAST::Initializer::Bind.new(
                    RakuAST::ApplyInfix.new(
                        :left(MaxSigDigs),
                        :infix(Minus),
                        :right(RakuAST::IntLiteral.new(format<minimum-significant-digits>))
        )   )   )   ),
        RakuAST::Statement::Expression.new(
            expression => RakuAST::VarDeclaration::Simple.new( :scope<my>, :name<$fractional-mod-difference>,
                initializer => RakuAST::Initializer::Bind.new(
                    RakuAST::ApplyInfix.new( :left(Var_N), :infix(Mod),
                        right => RakuAST::ApplyInfix.new(
                            :left(Ten),
                            :infix(Power),
                            :right(RakuAST::Var::Lexical.new('$digit-difference'))
        )   )   )   )   ),
        RakuAST::Statement::Expression.new(
            expression => RakuAST::VarDeclaration::Simple.new( :scope<my>, :name<$fractional-digits-to-strip>,
                initializer => RakuAST::Initializer::Bind.new(Zero)
        )   ),
        RakuAST::Statement::Expression.new(
            expression => RakuAST::VarDeclaration::Simple.new( :scope<my>, :name<$fractional-modder>,
                initializer => RakuAST::Initializer::Bind.new(Ten)
        )   ),
        RakuAST::Statement::For.new(
            source => RakuAST::ApplyPrefix.new( :prefix(ZeroToN), :operand(RakuAST::Var::Lexical.new('$digit-difference'))),
            body => block-blockoid-statement-list(
                RakuAST::Statement::Expression.new(
                    expression => CallLast,
                    condition-modifier => RakuAST::StatementModifier::If.new(
                        RakuAST::ApplyInfix.new( :right(Zero), :infix(Greater),
                            left => RakuAST::Var::Lexical.new('$fractional-mod-difference'),
                            infix => Mod,
                            right => RakuAST::Var::Lexical.new('$fractional-modder')
                )   )   ),
                RakuAST::Statement::Expression.new(
                    expression => RakuAST::ApplyInfix.new(
                        left => RakuAST::Var::Lexical.new('$fractional-digits-to-strip'),
                        infix => Assign,
                        right => RakuAST::ApplyInfix.new(
                            left => RakuAST::Var::Lexical.new('$fractional-digits-to-strip'),
                            infix => Plus,
                            right => One
                )   )   ),
                RakuAST::Statement::Expression.new(
                    expression => RakuAST::ApplyInfix.new(
                        left => RakuAST::Var::Lexical.new('$fractional-modder'),
                        infix => Assign,
                        right => RakuAST::ApplyInfix.new(
                            left => RakuAST::Var::Lexical.new('$fractional-modder'),
                            infix => Times,
                            right => Ten
                )   )   ),
        )   ),
        RakuAST::Statement::Expression.new(
            expression => RakuAST::ApplyInfix.new( :left(Result), :infix(Assign),
                right => RakuAST::ApplyListInfix.new( :infix(Concat),
                    operands => (
                        Result,
                        RakuAST::StrLiteral.new(symbols.decimal),
                        rast-transliterate-wrap(
                            RakuAST::ApplyPostfix.new(
                                postfix => RakuAST::Call::Method.new(
                                    name => RakuAST::Name.from-identifier('substr'),
                                    args => RakuAST::ArgList.new(
                                        Zero,
                                        RakuAST::ApplyInfix.new(
                                            left => RakuAST::ApplyInfix.new(
                                                left => MaxSigDigs,
                                                infix => Minus,
                                                right => RakuAST::ApplyInfix.new(
                                                    left => RakuAST::Var::Lexical.new('$power'),
                                                    infix => RakuAST::Infix.new('max'),
                                                    right => RakuAST::IntLiteral.new(format<minimum-significant-digits>),
                                            )   ),
                                            infix => Minus,
                                            right => RakuAST::Var::Lexical.new('$fractional-digits-to-strip')
                                )   )   ),
                                operand => RakuAST::ApplyPostfix.new( operand => Var_N, postfix => MakeStr)
                            ),
                            number-system
        )   )   )   )   );

    # if $n { …} elsif … { pad-zero } else { decimal }
    my $fraction-if = RakuAST::Statement::If.new(
        condition => Var_N,
        then => block-blockoid-statement-list(@fractional-digits),
        elsifs => [
            RakuAST::Statement::Elsif.new(
                condition => RakuAST::ApplyInfix.new(
                    left => RakuAST::Var::Lexical.new('$completed-digits'),
                    infix => RakuAST::Infix.new('<='), # 10. is more significant than 10
                    right => RakuAST::IntLiteral.new(format<minimum-significant-digits>)
                ),
                then => block-blockoid-statement-list(
                    rastlog('C2: ', '$result'),
                    RakuAST::Statement::Expression.new(
                        expression => RakuAST::ApplyInfix.new( :left(Result), :infix(Assign),
                            right => RakuAST::ApplyListInfix.new( :infix(Concat),
                                operands => (
                                    Result,
                                    RakuAST::StrLiteral.new(symbols.decimal),
                                    RakuAST::ApplyInfix.new(
                                        left => RakuAST::StrLiteral.new(%digit-offset{number-system}.chr),
                                        infix => RakuAST::Infix.new('x'),
                                        right => RakuAST::ApplyInfix.new(
                                            left => RakuAST::IntLiteral.new(format<minimum-significant-digits>),
                                            infix => Minus,
                                            right => RakuAST::Var::Lexical.new('$completed-digits')
            )   )   )   )   )   )   )   )
        ],
        |(else => block-blockoid-statement-list(
            RakuAST::Statement::Expression.new(
                expression => RakuAST::ApplyInfix.new( :left(Result), :infix(Assign),
                    right => RakuAST::ApplyInfix.new( :left(Result), :infix(Concat), :right(RakuAST::StrLiteral.new(symbols.decimal)))
                ),
        )   ) if format<show-decimal>)
    );

    my $set-max-sig-digits := (format<maximum-significant-digits> === Inf
        ?? RakuAST::Statement::Expression.new(
        expression => RakuAST::VarDeclaration::Simple.new( :scope<my>, :name<$local-max-sig-digs>,
            initializer => RakuAST::Initializer::Bind.new(
                RakuAST::ApplyInfix.new( :left(RakuAST::IntLiteral.new(format<minimum-significant-digits>)), :infix(RakuAST::Infix.new('max')),
                        right => RakuAST::ApplyPostfix.new( postfix => CeilingMethod,
                            operand => RakuAST::ApplyPostfix.new( postfix => AbsMethod,
                                operand => RakuAST::ApplyPostfix.new( postfix => Log10Method,
                                    operand => RakuAST::Var::Dynamic.new('$*TOLERANCE')
        )   )   )   )   )   )   )
        !! Empty);

    my $exponential = format<type> eq 'scientific';
    my @modify-exponential := $exponential ?? rakuast-modify-exp()                                  !! Empty;
    my $declare-exp-power  := $exponential ?? rakuast-exp-power(format<exponential-power-multiple>) !! Empty;
    my @exponential        := $exponential ?? rast-exponential( format,symbols,number-system)       !! Empty;

    return  rast-magnitude(),           # determine $power
            $set-max-sig-digits,
           |@initial-n-adjust,          # adjust per max sig digits
            $declare-exp-power,
           |@modify-exponential,
            $integer-digits,            # format int digits
            $remove-integer-digits,     # reduce to fraction only
            $completed-digits-declare,  # declare completed digits
           |@int-grouping,              #
            $fraction-if,
           |@exponential,
            ;
}

#| my $rounding-quotient   = $n / $rounding-radix;
#| my $rounding-whole      = floor $rounding-quotient;
#| my $rounding-fraction   = $rounding-quotient - $rounding-whole;
#| $n = $rounding-radix * ($rounding-whole +
#|     ($fraction == 0.5 ?? ($rounding-quotient %% 2) !! ($fraction > 1))
#| )
#| # (this is half-even rounding, per IEEE / CLDR standards)
sub rast-round($round, :$calculated = False) {
    # For future maintainers, here's a generic solution for all rounding types:
    # multi sub round(Numeric() $number, Numeric() $radix = 1, :$mode!) {
    #    my $quotient   = floor $number / $radix;
    #    my $low        = $radix * $quotient;
    #    my $variance   = $number - $low;
    #    my $high       = $low + $radix;
    #    my $half-radix = $radix / 2;
    #
    #    if $variance < $half-radix { return $low  }
    #    if $variance > $half-radix { return $high }
    #
    #    do given $mode {
    #        when 'away-from-zero' { $number      > 0 ?? $high !! $low  } # Raku default
    #        when 'toward-zero'    { $number      > 0 ?? $low  !! $high }
    #        when 'half-even'      { $quotient   %% 2 ?? $low  !! $high } # IEEE default
    #        when 'half-odd'       { $quotient   %% 2 ?? $high !! $low  }
    #        when 'half-up'        { $half-radix  > 0 ?? $high !! $low  }
    #        when 'half-down'      { $half-radix  > 0 ?? $low  !! $high }
    #    }
    # }
    return Empty if !$calculated && $round == 0;
    my      \RADIX    = $calculated ?? RakuAST::Var::Lexical.new('$rounding-radix') !! RakuAST::RatLiteral.new($round.Rat);
    constant QUOTIENT = RakuAST::Var::Lexical.new('$rounding-quotient');
    constant WHOLE    = RakuAST::Var::Lexical.new('$rounding-whole');
    constant FRACTION = RakuAST::Var::Lexical.new('$rounding-fraction');
    my @statements;
    @statements.push: RakuAST::Statement::Expression.new(
        expression => RakuAST::VarDeclaration::Simple.new(
            name => '$rounding-radix',
            scope => 'my',
            initializer => RakuAST::Initializer::Assign.new($round)
        )
    ) if $calculated;

    @statements.append:
    RakuAST::Statement::Expression.new(
        expression => RakuAST::VarDeclaration::Simple.new(
            name => '$rounding-quotient',
            scope => 'my',
            initializer => RakuAST::Initializer::Assign.new(
                RakuAST::ApplyInfix.new: :left(Var_N), :infix(Divide), :right(RADIX)
            )
        )
    ),
    RakuAST::Statement::Expression.new(
        expression => RakuAST::VarDeclaration::Simple.new(
            name => '$rounding-whole',
            scope => 'my',
            initializer => RakuAST::Initializer::Assign.new(
                RakuAST::ApplyPostfix.new(
                    postfix => RakuAST::Call::Method.new(name => RakuAST::Name.from-identifier('floor')),
                    operand => QUOTIENT
                )
            )
        )
    ),
    RakuAST::Statement::Expression.new(
        expression => RakuAST::VarDeclaration::Simple.new(
            name => '$rounding-fraction',
            scope => 'my',
            initializer => RakuAST::Initializer::Assign.new(
                RakuAST::ApplyInfix.new: :left(QUOTIENT), :infix(Minus), :right(WHOLE)
            )
        )
    ),
    RakuAST::Statement::Expression.new(
        expression => RakuAST::ApplyInfix.new(
            left  => Var_N,
            infix => Assign,
            right => RakuAST::ApplyInfix.new(
                left => RADIX,
                infix => Times,
                right => RakuAST::ApplyInfix.new(
                    left => QUOTIENT,
                    infix => Plus,
                    right => RakuAST::Ternary.new(
                        condition => RakuAST::ApplyInfix.new( :left(FRACTION), :infix(NumEqual), :right(RakuAST::RatLiteral.new: 0.5)),
                        then => RakuAST::ApplyInfix.new(:left(QUOTIENT), :infix(Divisible), :right(RakuAST::IntLiteral.new: 2  )),
                        else => RakuAST::ApplyInfix.new(:left(FRACTION), :infix(Greater), :right(RakuAST::RatLiteral.new: 0.5)),
                    )
                )
            )
        )
    );
    @statements
}

#| $n = $n * (10 ** (1-$exponential-power))
#| $power = $exponential-power - $power
sub rakuast-modify-exp is pure {
    RakuAST::Statement::Expression.new(
        expression => RakuAST::ApplyInfix.new(
            left => Var_N,
            infix => Assign,
            right => RakuAST::ApplyInfix.new(
                left => Var_N,
                infix => Times,
                right => RakuAST::ApplyInfix.new(
                    left => Ten,
                    infix => Power,
                    right => RakuAST::ApplyInfix.new(
                        left => Zero,
                        infix => Minus,
                        right => RakuAST::Var::Lexical.new('$exponential-power')
                    )
                )
            )
        )
    ),
    RakuAST::Statement::Expression.new(
        expression => RakuAST::ApplyInfix.new(
            left => RakuAST::Var::Lexical.new('$power'),
            infix => Assign,
            right => RakuAST::ApplyInfix.new(
                right => RakuAST::Var::Lexical.new('$exponential-power'),
                infix => Minus,
                left => RakuAST::Var::Lexical.new('$power')
    )   )   )
}

# TODO check with a multiplier
#| my $exponential-power = MULTIPLIER < 2 ?? $power - 1 !! MULTI * ($power div MULTI)
sub rakuast-exp-power($multiplier) is pure {
    RakuAST::Statement::Expression.new(
        expression => RakuAST::VarDeclaration::Simple.new( :scope<my>, :name<$exponential-power>,
            initializer => RakuAST::Initializer::Assign.new(
                $multiplier < 2
                    ?? RakuAST::ApplyInfix.new(
                        left => RakuAST::Var::Lexical.new('$power'),
                        infix => Minus,
                        right => One)
                    !! RakuAST::ApplyInfix.new(
                        left => RakuAST::IntLiteral.new($multiplier),
                        infix => Times,
                        right => RakuAST::ApplyInfix.new(
                            left => RakuAST::ApplyInfix.new(
                                left => RakuAST::Var::Lexical.new('$power'),
                                infix => Minus,
                                right => One),
                            infix => IntDivide,
                            right => RakuAST::IntLiteral.new($multiplier)
                        ),
                    )
            )
        )
    )
}


sub wrap-in-expressions(+@foo) is pure {
    @foo.map({RakuAST::Statement::Expression.new(expression => $^expression)}).list
}

sub rast-min-max-digits(\format,\symbols,\number-system) {
    my $reduce-for-max-integers := rast-max-int(format);
    my $set-magnitude := rast-magnitude;
    my $integer-digits := RakuAST::Statement::Expression.new(
        expression => RakuAST::ApplyInfix.new( :left(Result), :infix(Assign),
            right => RakuAST::ApplyInfix.new( :left(Result), :infix(Concat),
                right => rast-transliterate-wrap(
                    RakuAST::Ternary.new(
                        condition => RakuAST::ApplyInfix.new(:left(RakuAST::Var::Lexical.new('$power')), :infix(Greater), :right(Zero)),
                        then => RakuAST::ApplyPostfix.new(
                            postfix => MakeStr,
                            operand => RakuAST::ApplyPostfix.new( postfix => FloorMethod, operand => Var_N)
                        ),
                        else => RakuAST::StrLiteral.new('0'),
                    ),
                    number-system
    )   )   )   );

    #| $result = ('0' x ($min-digs - $power)) ~ $result if $min-digs > $power
    my $pad-leading-zeros := format<minimum-integer-digits> > 1
        ?? RakuAST::Statement::Expression.new(
            expression => RakuAST::ApplyInfix.new( :left(Result), :infix(Assign),
                right => RakuAST::ApplyInfix.new( :right(Result), :infix(Concat),
                    left => RakuAST::ApplyInfix.new(
                        left => RakuAST::StrLiteral.new(%digit-offset{number-system}.chr), # it's only 0, so we can easily hardcode the localized one
                        infix => RakuAST::Infix.new('x'),
                        right => RakuAST::ApplyInfix.new( :right(RakuAST::Var::Lexical.new('$power')), :infix(Minus),
                            left => RakuAST::IntLiteral.new(format<minimum-integer-digits>)
            )   )   )   ),
            condition-modifier => RakuAST::StatementModifier::If.new(
                RakuAST::ApplyInfix.new(
                    :left(RakuAST::IntLiteral.new(format<minimum-integer-digits>)),
                    :infix(Greater),
                    :right(RakuAST::Var::Lexical.new('$power'))
        )   )   )
        !! Empty;

    # If show decimal is a requirement, we can just add it now without an conditionals
    # Otherwise, the decimal will be added if there's a fraction (and potentially clipped!)
    my $force-decimal := (format<show-decimal>
        ?? RakuAST::Statement::Expression.new( expression =>
            RakuAST::ApplyInfix.new(:left(Result), :infix(Assign),
                right => (:left(Result), :infix(Concat), :right(RakuAST::StrLiteral.new(symbols<decimal>)))
        )   )
        !! Empty
    );
    my @fraction-statements;
    my $fraction-statements;
    if format<maximum-fractional-digits> > 0 {
        if format<maximum-fractional-digits> === Inf {
            # my $local-max-digits = MIN-DIGS max abs(magnitude($*TOLERANCE));
            @fraction-statements.push: RakuAST::Statement::Expression.new(
                expression => RakuAST::VarDeclaration::Simple.new( :scope<my>, :name<$local-max-digits>,
                    initializer => RakuAST::Initializer::Bind.new(
                        RakuAST::ApplyInfix.new(
                            left => RakuAST::IntLiteral.new(format<minimum-fractional-digits>),
                            infix => RakuAST::Infix.new('max'),
                            right => RakuAST::Call::Name.new( name => RakuAST::Name.from-identifier('abs'),
                                args => RakuAST::ArgList.new(
                                    RakuAST::ApplyInfix.new(:left(One), :infix(Minus), # because 0.1 = 0, not -1.  To be perfect, only adjust if < 1, but that (should) be the case for $*TOLERANCE
                                        right => RakuAST::Call::Name.new( name => RakuAST::Name.from-identifier('magnitude'),
                                            args => RakuAST::ArgList.new( RakuAST::Var::Dynamic.new('$*TOLERANCE') )
            )   )   )   )   )   )   )   );
        }

        @fraction-statements.push: RakuAST::Statement::Expression.new(
            expression => RakuAST::ApplyInfix.new(:left(Result), :infix(Assign),
                right => RakuAST::ApplyInfix.new( :left(Result), :infix(Concat), :right(RakuAST::StrLiteral.new(symbols<decimal>)))
            ),
        ) unless format<show-decimal>;

        # my result = $result ~ (($n - $n.floor) * 10 ** ((MAX-FRAC-DIGITS))).floor.Str
        @fraction-statements.append: RakuAST::Statement::Expression.new( expression =>
            RakuAST::ApplyInfix.new(:left(Result), :infix(Assign),
                right => RakuAST::ApplyInfix.new( :left(Result), :infix(Concat),
                        right => rast-transliterate-wrap(
                            RakuAST::ApplyPostfix.new(
                                postfix => MakeStr,
                                operand => RakuAST::ApplyPostfix.new(
                                    postfix => FloorMethod,
                                    operand => RakuAST::ApplyInfix.new(
                                        left => RakuAST::ApplyInfix.new(
                                            left => Var_N,
                                            infix => Minus,
                                            right => RakuAST::ApplyPostfix.new(
                                                postfix => FloorMethod,
                                                operand => Var_N,
                                        )   ),
                                        infix => Times,
                                        right => RakuAST::ApplyInfix.new(
                                            left => Ten,
                                            infix => Power,
                                            right => ( format<maximum-fractional-digits> === Inf
                                                ?? RakuAST::Var::Lexical.new('$local-max-digits')
                                                !! RakuAST::IntLiteral.new(format<maximum-fractional-digits>)
                            )   )   )   )   ),
                            number-system
            )   )   )   ),
        # my $fractional-clip = $result.chars; # TODO: optimize out if $min/$max guaranteed the same
        RakuAST::Statement::Expression.new(
            expression => RakuAST::VarDeclaration::Simple.new(:scope<my>, :name<$fractional-clip>,
                initializer => RakuAST::Initializer::Bind.new(
                    RakuAST::ApplyPostfix.new(
                        operand => Result,
                        postfix => RakuAST::Call::Method.new( name => RakuAST::Name.from-identifier('chars') )
        )   )   )   ),
        # for ^MAX-FRAC-DIGS {
        #   last if $result.substr($fractional-clip - 1, 1) ne ZERO;
        #   $fractional-clip -= 1;
        # }                      # TODO: optimize out if $min/$max guaranteed the same
        RakuAST::Statement::For.new(
            source => RakuAST::ApplyPrefix.new(
                :prefix(RakuAST::Prefix.new('^')),
                :operand( format<maximum-fractional-digits> === Inf
                    ?? RakuAST::Var::Lexical.new('$local-max-digits')
                    !! RakuAST::IntLiteral.new(format<maximum-fractional-digits>)
            )   ),
            body => block-blockoid-statement-list(
                RakuAST::Statement::Expression.new(
                    expression => RakuAST::Call::Name.new( name => RakuAST::Name.from-identifier('last') ),
                    condition-modifier => RakuAST::StatementModifier::If.new(
                        RakuAST::ApplyInfix.new(
                            right => RakuAST::StrLiteral.new(%digit-offset{number-system}.chr), # can cache it here
                            infix => RakuAST::Infix.new('ne'),
                            left => RakuAST::ApplyPostfix.new(
                                operand => Result,
                                postfix => RakuAST::Call::Method.new(
                                    name => RakuAST::Name.from-identifier('substr'),
                                    args => RakuAST::ArgList.new(
                                        RakuAST::ApplyInfix.new(
                                            left => RakuAST::Var::Lexical.new('$fractional-clip'),
                                            infix => Minus,
                                            right => One
                                        ),
                                        One
                )   )   )   )   )   ),
                RakuAST::Statement::Expression.new(
                    expression => RakuAST::ApplyInfix.new(
                        left => RakuAST::Var::Lexical.new('$fractional-clip'),
                        infix => Assign,
                        right => RakuAST::ApplyInfix.new(
                            left => RakuAST::Var::Lexical.new('$fractional-clip'),
                            infix => Minus,
                            right => One,
        )   )   )   )   ),
        # $result = $result.substr(0, $result.chars - $fractional-clip == $maximum-fractional-digits ?? $fractional-clip - 1 !! $fractional-clip)
        RakuAST::Statement::Expression.new( expression =>
            RakuAST::ApplyInfix.new(
                left => Result,
                infix => Assign,
                right => RakuAST::ApplyPostfix.new(
                    operand => Result,
                    postfix => RakuAST::Call::Method.new(
                        name => RakuAST::Name.from-identifier('substr'),
                        args => RakuAST::ArgList.new(
                            Zero,
                            RakuAST::Ternary.new(
                                condition => RakuAST::ApplyInfix.new(
                                    infix => NumEqual,
                                    right => (format<maximum-fractional-digits> === Inf
                                        ?? RakuAST::Var::Lexical.new('$local-max-digits')
                                        !! RakuAST::IntLiteral.new(format<maximum-fractional-digits>)
                                    ),
                                    left => RakuAST::ApplyInfix.new(
                                        left => RakuAST::ApplyPostfix.new(
                                            postfix => RakuAST::Call::Method.new(name => RakuAST::Name.from-identifier('chars')),
                                            operand => Result
                                        ),
                                        infix => Minus,
                                        right => RakuAST::Var::Lexical.new('$fractional-clip')
                                )   ),
                                then => RakuAST::ApplyInfix.new(:right(One), :infix(Minus),
                                    left => RakuAST::Var::Lexical.new('$fractional-clip')
                                ),
                                else => RakuAST::Var::Lexical.new('$fractional-clip')
                            )
        )   )   )   )   );
        $fraction-statements := RakuAST::Statement::If.new(
            condition => RakuAST::ApplyInfix.new(
                left => RakuAST::ApplyInfix.new( :left(Var_N), :right(One), :infix(RakuAST::Infix.new('%'))),
                infix => Greater,
                right => Zero),
            then => block-blockoid-statement-list(@fraction-statements)
        );
    } else {
        $fraction-statements := Empty;
    }
    my @integer-grouping := rast-integer-grouping(format,symbols);
    return  $reduce-for-max-integers,
            $set-magnitude,
            $integer-digits,
            $pad-leading-zeros,
           |@integer-grouping,
            $force-decimal,
            $fraction-statements,
    ;
}

#| Provides code to act on $result, assuming it only has integer digits
sub rast-integer-grouping( \format,\symbols) {
    # NOOP if $primary-grouping-size ≤ 0
    # ELSE
    #   my $grouping-location = PRIMARY-GROUPING-SIZE;
    #   while $grouping-location > 0 {
    #     $result = $result.substr(0,$grouping-location) ~ GROUP-SYMBOL ~ $result.substr($grouping-location))
    format<primary-grouping-size> > 0
        ?? (RakuAST::Statement::Expression.new(
                expression => RakuAST::VarDeclaration::Simple.new( :scope<my>, :name<$grouping-location>,
                    initializer => RakuAST::Initializer::Bind.new(
                        RakuAST::ApplyInfix.new(
                            #left => RakuAST::Var::Lexical.new('$completed-digits'),
                            left => RakuAST::ApplyPostfix.new( :operand(Result),
                                postfix => RakuAST::Call::Method.new( name => RakuAST::Name.from-identifier('chars'))
                            ),
                            infix => Minus,
                            right => RakuAST::IntLiteral.new(format<primary-grouping-size>)
                        )
                    )
                )
            ),
            RakuAST::Statement::Loop::While.new(
                condition => RakuAST::ApplyInfix.new( :right(Zero), :infix(Greater),
                    left => RakuAST::Var::Lexical.new('$grouping-location')
                ),
                body => block-blockoid-statement-list(
                    RakuAST::Statement::Expression.new( expression =>
                        RakuAST::ApplyInfix.new( :left(Result), :infix(Assign),
                            right => RakuAST::ApplyListInfix.new(
                                infix => Concat,
                                operands => (
                                    RakuAST::ApplyPostfix.new(operand => Result,
                                        postfix => RakuAST::Call::Method.new(
                                            name => RakuAST::Name.from-identifier('substr'),
                                            args => RakuAST::ArgList.new(Zero,RakuAST::Var::Lexical.new('$grouping-location'))
                                        )
                                    ),
                                    RakuAST::StrLiteral.new(symbols<group>),
                                    RakuAST::ApplyPostfix.new(operand => Result,
                                        postfix => RakuAST::Call::Method.new(
                                            name => RakuAST::Name.from-identifier('substr'),
                                            args => RakuAST::ArgList.new(RakuAST::Var::Lexical.new('$grouping-location'))
                )   )   )   )   )   ),
                RakuAST::Statement::Expression.new(
                    expression => RakuAST::ApplyInfix.new(
                        left => RakuAST::Var::Lexical.new('$grouping-location'),
                        infix => Assign,
                        right => RakuAST::ApplyInfix.new(
                            left => RakuAST::Var::Lexical.new('$grouping-location'),
                            infix => Minus,
                            right => RakuAST::IntLiteral.new(format<secondary-grouping-size>)
        ))  )   )   )  