https://github.com/akkartik/mu/blob/main/linux/apps/rpn.mu

      1 # Integer arithmetic using postfix notation
      2 #
      3 # Limitations:
      4 #   No division yet.
      5 #
      6 # To build:
      7 #   $ ./translate apps/rpn.mu
      8 #
      9 # Example session:
     10 #   $ ./a.elf
     11 #   press ctrl-c or ctrl-d to exit
     12 #   > 1
     13 #   1
     14 #   > 1 1 +
     15 #   2
     16 #   > 1 2 3 + +
     17 #   6
     18 #   > 1 2 3 * +
     19 #   7
     20 #   > 1 2 + 3 *
     21 #   9
     22 #   > 1 3 4 * +
     23 #   13
     24 #   > ^D
     25 #   $
     26 #
     27 # Error handling is non-existent. This is just a prototype.
     28
     29 fn main -> _/ebx: int {
     30   var in-storage: (stream byte 0x100)
     31   var in/esi: (addr stream byte) <- address in-storage
     32   print-string 0/screen, "press ctrl-c or ctrl-d to exit\n"
     33   # read-eval-print loop
     34   {
     35     # print prompt
     36     print-string 0/screen, "> "
     37     # read line
     38     clear-stream in
     39     read-line-from-real-keyboard in
     40     var done?/eax: boolean <- stream-empty? in
     41     compare done?, 0
     42     break-if-!=
     43     # parse and eval
     44     var out/eax: int <- simplify in
     45     # print
     46     print-int32-decimal 0/screen, out
     47     print-string 0/screen, "\n"
     48     #
     49     loop
     50   }
     51   return 0
     52 }
     53
     54 type int-stack {
     55   data: (handle array int)
     56   top: int
     57 }
     58
     59 fn simplify in: (addr stream byte) -> _/eax: int {
     60   var word-storage: slice
     61   var word/ecx: (addr slice) <- address word-storage
     62   var stack-storage: int-stack
     63   var stack/esi: (addr int-stack) <- address stack-storage
     64   initialize-int-stack stack, 0x10
     65   $simplify:word-loop: {
     66     next-word in, word
     67     var done?/eax: boolean <- slice-empty? word
     68     compare done?, 0
     69     break-if-!=
     70     # if word is an operator, perform it
     71     {
     72       var add?/eax: boolean <- slice-equal? word, "+"
     73       compare add?, 0
     74       break-if-=
     75       var _b/eax: int <- pop-int-stack stack
     76       var b/edx: int <- copy _b
     77       var a/eax: int <- pop-int-stack stack
     78       a <- add b
     79       push-int-stack stack, a
     80       loop $simplify:word-loop
     81     }
     82     {
     83       var sub?/eax: boolean <- slice-equal? word, "-"
     84       compare sub?, 0
     85       break-if-=
     86       var _b/eax: int <- pop-int-stack stack
     87       var b/edx: int <- copy _b
     88       var a/eax: int <- pop-int-stack stack
     89       a <- subtract b
     90       push-int-stack stack, a
     91       loop $simplify:word-loop
     92     }
     93     {
     94       var mul?/eax: boolean <- slice-equal? word, "*"
     95       compare mul?, 0
     96       break-if-=
     97       var _b/eax: int <- pop-int-stack stack
     98       var b/edx: int <- copy _b
     99       var a/eax: int <- pop-int-stack stack
    100       a <- multiply b
    101       push-int-stack stack, a
    102       loop $simplify:word-loop
    103     }
    104     # otherwise it's an int
    105     var n/eax: int <- parse-decimal-int-from-slice word
    106     push-int-stack stack, n
    107     loop
    108   }
    109   var result/eax: int <- pop-int-stack stack
    110   return result
    111 }
    112
    113 fn initialize-int-stack _self: (addr int-stack), n: int {
    114   var self/esi: (addr int-stack) <- copy _self
    115   var d/edi: (addr handle array int) <- get self, data
    116   populate d, n
    117   var top/eax: (addr int) <- get self, top
    118   copy-to *top, 0
    119 }
    120
    121 fn push-int-stack _self: (addr int-stack), _val: int {
    122   var self/esi: (addr int-stack) <- copy _self
    123   var top-addr/ecx: (addr int) <- get self, top
    124   var data-ah/edx: (addr handle array int) <- get self, data
    125   var data/eax: (addr array int) <- lookup *data-ah
    126   var top/edx: int <- copy *top-addr
    127   var dest-addr/edx: (addr int) <- index data, top
    128   var val/eax: int <- copy _val
    129   copy-to *dest-addr, val
    130   add-to *top-addr, 1
    131 }
    132
    133 fn pop-int-stack _self: (addr int-stack) -> _/eax: int {
    134   var self/esi: (addr int-stack) <- copy _self
    135   var top-addr/ecx: (addr int) <- get self, top
    136   {
    137     compare *top-addr, 0
    138     break-if->
    139     return 0
    140   }
    141   subtract-from *top-addr, 1
    142   var data-ah/edx: (addr handle array int) <- get self, data
    143   var data/eax: (addr array int) <- lookup *data-ah
    144   var top/edx: int <- copy *top-addr
    145   var result-addr/eax: (addr int) <- index data, top
    146   var val/eax: int <- copy *result-addr
    147   return val
    148 }