// File: ArashPartow[P]exprtk/exprtk_simple_example_24.cpp
// Function: void rpn_example<double>()
void rpn_example()
{
   typedef exprtk::symbol_table<T> symbol_table_t;
   typedef exprtk::expression<T>   expression_t;
   typedef exprtk::parser<T>       parser_t;

   const std::string rpn_program =
      " var stack[1000] := [0];                                                  "
      " var top_index   := 0;                                                    "
      "                                                                          "
      " for (var i := 0; i < rpn_expression[]; i += 1)                           "
      " {                                                                        "
      "    var c := rpn_expression[i : i + 1];                                   "
      "                                                                          "
      "    if (c == ' ')                                                         "
      "    {                                                                     "
      "       continue;                                                          "
      "    }                                                                     "
      "    else if (is_digit(c))                                                 "
      "    {                                                                     "
      "       stack[top_index] := to_num(c);                                     "
      "       top_index        += 1;                                             "
      "    }                                                                     "
      "    else                                                                  "
      "    {                                                                     "
      "       var operator := c;                                                 "
      "       var operand1 := stack[top_index - 2];                              "
      "       var operand2 := stack[top_index - 1];                              "
      "       top_index    -= 2;                                                 "
      "                                                                          "
      "       switch                                                             "
      "       {                                                                  "
      "          case operator == '+' : stack[top_index] := operand1 + operand2; "
      "          case operator == '-' : stack[top_index] := operand1 - operand2; "
      "          case operator == '*' : stack[top_index] := operand1 * operand2; "
      "          case operator == '/' : stack[top_index] := operand1 / operand2; "
      "          case operator == '^' : stack[top_index] := operand1 ^ operand2; "
      "       };                                                                 "
      "                                                                          "
      "       top_index += 1;                                                    "
      "    }                                                                     "
      " };                                                                       "
      "                                                                          "
      " println(stack[0], ' = ', rpn_expression);                                "
      "                                                                          ";

   std::string rpn_expression;

   char_process<T,is_digit_func<T> > isdigit;
   char_process<T,to_num_func<T> >   tonum;
   exprtk::rtl::io::println<T>       println;

   symbol_table_t symbol_table;
   symbol_table.add_stringvar("rpn_expression", rpn_expression);
   symbol_table.add_function ("println"       , println       );
   symbol_table.add_function ("is_digit"      , isdigit       );
   symbol_table.add_function ("to_num"        , tonum         );

   expression_t expression;
   expression.register_symbol_table(symbol_table);

   parser_t parser;
   parser.compile(rpn_program, expression);

   const std::string rpn_expressions[] =
   {
      "2 3 8 / ^ 4 6 * + 3 9 / -", // 2 ^ (3 / 8) + 4 * 6 - 3 / 9
      "1 2 / 6 5 2 - / * 7 +"    , // (1 / 2) * (6 / (5 - 2)) + 7
      "1 2 * 3 / 4 * 5 / 6 *"    , // ((((1 * 2) / 3) * 4) / 5) * 6
      "8 6 4 + * 2 /"              // (8 * (6 + 4)) / 2
   };

   for (std::size_t i = 0; i < sizeof(rpn_expressions) / sizeof(std::string); ++i)
   {
      rpn_expression = rpn_expressions[i];
      expression.value();
   }
}

// Assembly:
subq $0xe08, %rsp            # imm = 0xE08
leaq 0xde7(%rsp), %rdi
movq %rdi, 0xb0(%rsp)
callq 0x111650
movq 0xb0(%rsp), %rdx
leaq 0x332cf4(%rip), %rsi    # 0x44b53f
leaq 0xde8(%rsp), %rdi
callq 0x118760
jmp 0x11885a
leaq 0xde7(%rsp), %rdi
callq 0x111780
leaq 0xdb0(%rsp), %rdi
callq 0x111270
leaq 0xd68(%rsp), %rdi
callq 0x119440
jmp 0x118883
leaq 0xd20(%rsp), %rdi
callq 0x119500
jmp 0x118892
leaq 0xc97(%rsp), %rdi
movq %rdi, 0xa8(%rsp)
callq 0x111650
movq 0xa8(%rsp), %rdx
leaq 0x333786(%rip), %rsi    # 0x44c03c
leaq 0xc98(%rsp), %rdi
callq 0x118760
jmp 0x1188c5
leaq 0xcb8(%rsp), %rdi
leaq 0xc98(%rsp), %rsi
callq 0x1195c0
jmp 0x1188dc
leaq 0xc98(%rsp), %rdi
callq 0x111798
leaq 0xc97(%rsp), %rdi
callq 0x111780
leaq 0xc88(%rsp), %rdi
movl $0x1, %esi
callq 0x1196d0
jmp 0x11890a
leaq 0xc67(%rsp), %rdi
movq %rdi, 0xa0(%rsp)
callq 0x111650
movq 0xa0(%rsp), %rdx
leaq 0x333715(%rip), %rsi    # 0x44c043
leaq 0xc68(%rsp), %rdi
callq 0x118760
jmp 0x11893d
leaq 0xc88(%rsp), %rdi
leaq 0xc68(%rsp), %rsi
leaq 0xdb0(%rsp), %rdx
xorl %ecx, %ecx
callq 0x119710
jmp 0x11895e
leaq 0xc68(%rsp), %rdi
callq 0x111798
leaq 0xc67(%rsp), %rdi
callq 0x111780
leaq 0xc3f(%rsp), %rdi
movq %rdi, 0x98(%rsp)
callq 0x111650
movq 0x98(%rsp), %rdx
leaq 0x3336b6(%rip), %rsi    # 0x44c052
leaq 0xc40(%rsp), %rdi
callq 0x118760
jmp 0x1189ab
leaq 0xc88(%rsp), %rdi
leaq 0xc40(%rsp), %rsi
leaq 0xcb8(%rsp), %rdx
callq 0x1197d0
jmp 0x1189ca
leaq 0xc40(%rsp), %rdi
callq 0x111798
leaq 0xc3f(%rsp), %rdi
callq 0x111780
leaq 0xc17(%rsp), %rdi
movq %rdi, 0x90(%rsp)
callq 0x111650
movq 0x90(%rsp), %rdx
leaq 0x333652(%rip), %rsi    # 0x44c05a
leaq 0xc18(%rsp), %rdi
callq 0x118760
jmp 0x118a17
leaq 0xc88(%rsp), %rdi
leaq 0xc18(%rsp), %rsi
leaq 0xd68(%rsp), %rdx
callq 0x1197d0
jmp 0x118a36
leaq 0xc18(%rsp), %rdi
callq 0x111798
leaq 0xc17(%rsp), %rdi
callq 0x111780
leaq 0xbef(%rsp), %rdi
movq %rdi, 0x88(%rsp)
callq 0x111650
movq 0x88(%rsp), %rdx
leaq 0x3335ef(%rip), %rsi    # 0x44c063
leaq 0xbf0(%rsp), %rdi
callq 0x118760
jmp 0x118a83
leaq 0xc88(%rsp), %rdi
leaq 0xbf0(%rsp), %rsi
leaq 0xd20(%rsp), %rdx
callq 0x1197d0
jmp 0x118aa2
leaq 0xbf0(%rsp), %rdi
callq 0x111798
leaq 0xbef(%rsp), %rdi
callq 0x111780
leaq 0xbc8(%rsp), %rdi
callq 0x1199d0
jmp 0x118acb
leaq 0xbc8(%rsp), %rdi
leaq 0xc88(%rsp), %rsi
callq 0x119a80
jmp 0x118ae2
leaq 0x150(%rsp), %rdi
movl $0x7f, %esi
callq 0x119b30
jmp 0x118af6
leaq 0x2a0(%rsp), %rdi
leaq 0x150(%rsp), %rsi
callq 0x119c60
jmp 0x118b0d
leaq 0x150(%rsp), %rdi
callq 0x11a490
leaq 0x2a0(%rsp), %rdi
leaq 0xde8(%rsp), %rsi
leaq 0xbc8(%rsp), %rdx
callq 0x11a500
jmp 0x118b39
movb $0x1, 0xc3(%rsp)
leaq 0xd0(%rsp), %rax
movq %rax, 0x78(%rsp)
movq %rax, 0xc8(%rsp)
leaq 0xc7(%rsp), %rdi
movq %rdi, 0x80(%rsp)
callq 0x111650
movq 0x78(%rsp), %rdi
movq 0x80(%rsp), %rdx
leaq 0x3334eb(%rip), %rsi    # 0x44c06a
callq 0x118760
jmp 0x118b86
leaq 0xf0(%rsp), %rax
movq %rax, 0x68(%rsp)
movq %rax, 0xc8(%rsp)
leaq 0xc6(%rsp), %rdi
movq %rdi, 0x70(%rsp)
callq 0x111650
movq 0x68(%rsp), %rdi
movq 0x70(%rsp), %rdx
leaq 0x3334c6(%rip), %rsi    # 0x44c084
callq 0x118760
jmp 0x118bc5
leaq 0x110(%rsp), %rax
movq %rax, 0x58(%rsp)
movq %rax, 0xc8(%rsp)
leaq 0xc5(%rsp), %rdi
movq %rdi, 0x60(%rsp)
callq 0x111650
movq 0x58(%rsp), %rdi
movq 0x60(%rsp), %rdx
leaq 0x33349d(%rip), %rsi    # 0x44c09a
callq 0x118760
jmp 0x118c04
leaq 0x130(%rsp), %rax
movq %rax, 0x48(%rsp)
movq %rax, 0xc8(%rsp)
leaq 0xc4(%rsp), %rdi
movq %rdi, 0x50(%rsp)
callq 0x111650
movq 0x48(%rsp), %rdi
movq 0x50(%rsp), %rdx
leaq 0x333474(%rip), %rsi    # 0x44c0b0
callq 0x118760
jmp 0x118c43
movb $0x0, 0xc3(%rsp)
leaq 0xc4(%rsp), %rdi
callq 0x111780
leaq 0xc5(%rsp), %rdi
callq 0x111780
leaq 0xc6(%rsp), %rdi
callq 0x111780
leaq 0xc7(%rsp), %rdi
callq 0x111780
movq $0x0, 0xb8(%rsp)
cmpq $0x4, 0xb8(%rsp)
jae 0x119045
movq 0xb8(%rsp), %rax
shlq $0x5, %rax
leaq 0xd0(%rsp,%rax), %rsi
leaq 0xdb0(%rsp), %rdi
callq 0x111720
jmp 0x118cbd
leaq 0xbc8(%rsp), %rdi
callq 0x11ad90
jmp 0x118ccc
jmp 0x118cce
movq 0xb8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xb8(%rsp)
jmp 0x118c8b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
leaq 0xde7(%rsp), %rdi
callq 0x111780
jmp 0x119185
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
jmp 0x11916b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
jmp 0x11915e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
jmp 0x118d73
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
leaq 0xc98(%rsp), %rdi
callq 0x111798
leaq 0xc97(%rsp), %rdi
callq 0x111780
jmp 0x119151
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
jmp 0x119144
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
jmp 0x118dd5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
leaq 0xc68(%rsp), %rdi
callq 0x111798
leaq 0xc67(%rsp), %rdi
callq 0x111780
jmp 0x119137
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
jmp 0x118e1e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
leaq 0xc40(%rsp), %rdi
callq 0x111798
leaq 0xc3f(%rsp), %rdi
callq 0x111780
jmp 0x119137
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
jmp 0x118e67
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
leaq 0xc18(%rsp), %rdi
callq 0x111798
leaq 0xc17(%rsp), %rdi
callq 0x111780
jmp 0x119137
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
jmp 0x118eb0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
leaq 0xbf0(%rsp), %rdi
callq 0x111798
leaq 0xbef(%rsp), %rdi
callq 0x111780
jmp 0x119137
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
jmp 0x119137
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
jmp 0x11912a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
leaq 0x150(%rsp), %rdi
callq 0x11a490
jmp 0x11912a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
jmp 0x11911d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
jmp 0x118fb0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
jmp 0x118fa3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
jmp 0x118f96
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
leaq 0xc4(%rsp), %rdi
callq 0x111780
leaq 0xc5(%rsp), %rdi
callq 0x111780
leaq 0xc6(%rsp), %rdi
callq 0x111780
leaq 0xc7(%rsp), %rdi
callq 0x111780
testb $0x1, 0xc3(%rsp)
jne 0x118fc9
jmp 0x11900f
movq 0xc8(%rsp), %rax
leaq 0xd0(%rsp), %rcx
cmpq %rax, %rcx
movq %rax, 0x40(%rsp)
je 0x11900d
movq 0x40(%rsp), %rdi
addq $-0x20, %rdi
movq %rdi, 0x38(%rsp)
callq 0x111798
movq 0x38(%rsp), %rax
leaq 0xd0(%rsp), %rcx
cmpq %rcx, %rax
movq %rax, 0x40(%rsp)
jne 0x118fe3
jmp 0x11900f
jmp 0x11911d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xdd8(%rsp)
movl %eax, 0xdd4(%rsp)
leaq 0xd0(%rsp), %rax
movq %rax, 0x28(%rsp)
addq $0x80, %rax
movq %rax, 0x30(%rsp)
jmp 0x1190f4
leaq 0xd0(%rsp), %rax
movq %rax, 0x18(%rsp)
addq $0x80, %rax
movq %rax, 0x20(%rsp)
movq 0x20(%rsp), %rdi
addq $-0x20, %rdi
movq %rdi, 0x10(%rsp)
callq 0x111798
movq 0x18(%rsp), %rcx
movq 0x10(%rsp), %rax
cmpq %rcx, %rax
movq %rax, 0x20(%rsp)
jne 0x11905d
leaq 0x2a0(%rsp), %rdi
callq 0x11adb0
leaq 0xbc8(%rsp), %rdi
callq 0x11afb0
leaq 0xc88(%rsp), %rdi
callq 0x11aff0
leaq 0xcb8(%rsp), %rdi
callq 0x11b070
leaq 0xd20(%rsp), %rdi
callq 0x11b0a0
leaq 0xd68(%rsp), %rdi
callq 0x11b0b0
leaq 0xdb0(%rsp), %rdi
callq 0x111798
leaq 0xde8(%rsp), %rdi
callq 0x111798
addq $0xe08, %rsp            # imm = 0xE08
retq
movq 0x30(%rsp), %rdi
addq $-0x20, %rdi
movq %rdi, 0x8(%rsp)
callq 0x111798
movq 0x28(%rsp), %rcx
movq 0x8(%rsp), %rax
cmpq %rcx, %rax
movq %rax, 0x30(%rsp)
jne 0x1190f4
jmp 0x11911d
leaq 0x2a0(%rsp), %rdi
callq 0x11adb0
leaq 0xbc8(%rsp), %rdi
callq 0x11afb0
leaq 0xc88(%rsp), %rdi
callq 0x11aff0
leaq 0xcb8(%rsp), %rdi
callq 0x11b070
leaq 0xd20(%rsp), %rdi
callq 0x11b0a0
leaq 0xd68(%rsp), %rdi
callq 0x11b0b0
leaq 0xdb0(%rsp), %rdi
callq 0x111798
leaq 0xde8(%rsp), %rdi
callq 0x111798
movq 0xdd8(%rsp), %rdi
callq 0x111450
nopw %cs:(%rax,%rax)
nopl (%rax)