Task

Create a stack-based evaluator for an expression in   reverse Polish notation (RPN)   that also shows the changes in the stack as each individual token is processed as a table.



 Assume an input of a correct, space separated, string of tokens of an RPN expression
 Test with the RPN expression generated from the   Parsing/Shunting-yard algorithm   task: 

         3 4 2 * 1 5 - 2 3 ^ ^ / + 

 Print or display the output here


Notes

    ^    means exponentiation in the expression above.
    /    means division.


See also

   Parsing/Shunting-yard algorithm for a method of generating an RPN from an infix expression.
   Several solutions to 24 game/Solve make use of RPN evaluators (although tracing how they work is not a part of that task).
   Parsing/RPN to infix conversion.
   Arithmetic evaluation.


 
{calc 3 4 2 * 1 5 - 2 3 pow pow / +}
-> 
 3: 
 4: 3 
 2: 4 3 
 *: 2 4 3 
 1: 8 3 
 5: 1 8 3 
 -: 5 1 8 3 
 2: -4 8 3 
 3: 2 -4 8 3 
 pow: 3 2 -4 8 3 
 pow: 8 -4 8 3 
 /: 65536 8 3 
 +: 0.0001220703125 3 
 -> 3.0001220703125
 
where
 
{def calc
 {def calc.r
  {lambda {:x :s}
   {if {empty? :x}
    then -> {car :s}
    else {car :x}: {disp :s}{br}
         {calc.r {cdr :x}
                 {if {unop? {car :x}}
                  then {cons {{car :x} {car :s}} {cdr :s}}
                  else {if {binop? {car :x}}
                  then {cons {{car :x} {car {cdr :s}} {car :s}} {cdr {cdr :s}}}
                  else {cons {car :x} :s}} }}}}}
 {lambda {:s}
  {calc.r {list :s} nil}}}
 
using the unop? & binop? functions to test unary and binary operators
 
{def unop?
 {lambda {:op}
  {or {W.equal? :op sqrt}       // n sqrt  sqrt(n)
      {W.equal? :op exp}        // n exp   exp(n)
      {W.equal? :op log}        // n log   log(n) 
      {W.equal? :op cos}        // n cos   cos(n)
      ... and so                // ...
}}}
 
{def binop?
 {lambda {:op}
  {or {W.equal? :op +}          // m n +     m+n
      {W.equal? :op -}          // m n -     m-n
      {W.equal? :op *}          // m n *     m*n
      {W.equal? :op /}          // m n /     m/n
      {W.equal? :op %}          // m n %     m%n
      {W.equal? :op pow}        // m n pow   m^n
      ... and so on             // ...
}}}
 
and  the list, empty? and disp functions to create
a list from a string, test its emptynes and display it.
 
{def list
 {lambda {:s}
  {if {W.empty? {S.rest :s}}
   then {cons {S.first :s} nil}
   else {cons {S.first :s} {list {S.rest :s}}}}}}
 
{def empty?
 {lambda {:x}
  {W.equal? :x nil}}}
 
{def disp
 {lambda {:l}
  {if {empty? :l}
   then
   else {car :l} {disp {cdr :l}}}}}
 
Note that everything is exclusively built on 5 lambdatalk primitives: 
- "cons, car, cdr", to create lists,
- "W.equal?" which test the equality between two words, 
- and the "or" boolean function.
 