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 }