The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!./pil

=pod

=head1 DESCRIPTION

This is a (somewhat broken, not completely tested) version of 
the RPM evaluator in PIL^N (the Pugs runcore mini-language). 

=head1 AUTHOR

Stevan Little <stevan@iinteractive.com>

=cut

&split := -> $str, $delim {

    &stash_acc := -> $acc, @acc {
        $acc`is_empty()`if_else( 
            -> { @acc }, 
            -> { @acc`push($acc) } 
        );    
    };

    -> $h, $t, $acc, @acc {
        &redo := &?SUB;
        $h`is_nil()`if_else(
            -> { &stash_acc`($acc, @acc) },
            -> {  
                $h`eq($delim)`if_else(
                    -> { &redo`($t`fetch(0), $t`splice(1), '', &stash_acc`($acc, @acc)) },
                    -> { &redo`($t`fetch(0), $t`splice(1), $acc`concat($h), @acc)       }
                );
            }
        );
    }`($str`fetch(0), $str`splice(1), '', []);
};

&evaluate := -> $expr {
    -> @tokens, @stack {
        @tokens`trace(); @stack`trace();        
        &redo  := &?SUB; 
        $token := @tokens`fetch(0);    
        @tokens`is_empty()`if_else(
            -> { @stack`fetch(0) },
            -> { 
                $x := @stack`fetch(@stack`length()`subtract(1))`as_int();
                $y := @stack`fetch(@stack`length()`subtract(2))`as_int();               
                @r := @stack`splice(2);                    
                $token`eq('+')`if_else(
                    -> { &redo`(@tokens`splice(1), @r`push($y`add($x)`as_int())) },
                    -> {
                        $token`eq('-')`if_else(
                            -> { &redo`(@tokens`splice(1), @r`push($y`subtract($x)`as_int())) },
                            -> {                
                                $token`eq('*')`if_else(                
                                    -> { &redo`(@tokens`splice(1), @r`push($y`multiply($x)`as_int())) },
                                    -> {                        
                                        $token`eq('/')`if_else(                
                                            -> { &redo`(@tokens`splice(1), @r`push($y`divide($x)`as_int())) },
                                            -> {
                                                $token`eq(' ')`if_else( 
                                                    -> { &redo`(@tokens`splice(1), @stack) },
                                                    -> { &redo`(@tokens`splice(1), @stack`push($token)) }
                                                );
                                            }                        
                                        );
                                    }                
                                );
                            }
                        );
                    }
                );
            }
        );
    }`(&split`($expr, ' '), []);
};

&evaluate`('3 4 * 5 / 3 *  ');