https://github.com/akkartik/mu/blob/master/apps/rpn.mu
  1 # Integer arithmetic using postfix notation
  2 #
  3 # Limitations:
  4 #   No division yet.
  5 #
  6 # To build:
  7 #   $ ./translate_mu 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 -> exit-status/ebx: int {
 30   var in-storage: (stream byte 0x100)
 31   var in/esi: (addr stream byte) <- address in-storage
 32   print-string 0, "press ctrl-c or ctrl-d to exit\n"
 33   # read-eval-print loop
 34   {
 35     # print prompt
 36     print-string 0, "> "
 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, out
 47     print-string 0, "\n"
 48     #
 49     loop
 50   }
 51   exit-status <- copy 0
 52 }
 53 
 54 type int-stack {
 55   data: (handle array int)
 56   top: int
 57 }
 58 
 59 fn simplify in: (addr stream byte) -> result/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 is-add?/eax: boolean <- slice-equal? word, "+"
 73       compare is-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 is-sub?/eax: boolean <- slice-equal? word, "-"
 84       compare is-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 is-mul?/eax: boolean <- slice-equal? word, "*"
 95       compare is-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   result <- pop-int-stack stack
110 }
111 
112 fn initialize-int-stack _self: (addr int-stack), n: int {
113   var self/esi: (addr int-stack) <- copy _self
114   var d/edi: (addr handle array int) <- get self, data
115   populate d, n
116   var top/eax: (addr int) <- get self, top
117   copy-to *top, 0
118 }
119 
120 fn push-int-stack _self: (addr int-stack), _val: int {
121   var self/esi: (addr int-stack) <- copy _self
122   var top-addr/ecx: (addr int) <- get self, top
123   var data-ah/edx: (addr handle array int) <- get self, data
124   var data/eax: (addr array int) <- lookup *data-ah
125   var top/edx: int <- copy *top-addr
126   var dest-addr/edx: (addr int) <- index data, top
127   var val/eax: int <- copy _val
128   copy-to *dest-addr, val
129   add-to *top-addr, 1
130 }
131 
132 fn pop-int-stack _self: (addr int-stack) -> val/eax: int {
133 $pop-int-stack:body: {
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     val <- copy 0
140     break $pop-int-stack:body
141   }
142   subtract-from *top-addr, 1
143   var data-ah/edx: (addr handle array int) <- get self, data
144   var data/eax: (addr array int) <- lookup *data-ah
145   var top/edx: int <- copy *top-addr
146   var result-addr/eax: (addr int) <- index data, top
147   val <- copy *result-addr
148 }
149 }