about summary refs log tree commit diff stats
path: root/linux/rpn.mu
diff options
context:
space:
mode:
Diffstat (limited to 'linux/rpn.mu')
-rw-r--r--linux/rpn.mu148
1 files changed, 148 insertions, 0 deletions
diff --git a/linux/rpn.mu b/linux/rpn.mu
new file mode 100644
index 00000000..762d9605
--- /dev/null
+++ b/linux/rpn.mu
@@ -0,0 +1,148 @@
+# Integer arithmetic using postfix notation
+#
+# Limitations:
+#   No division yet.
+#
+# To build:
+#   $ ./translate_mu apps/rpn.mu
+#
+# Example session:
+#   $ ./a.elf
+#   press ctrl-c or ctrl-d to exit
+#   > 1
+#   1
+#   > 1 1 +
+#   2
+#   > 1 2 3 + +
+#   6
+#   > 1 2 3 * +
+#   7
+#   > 1 2 + 3 *
+#   9
+#   > 1 3 4 * +
+#   13
+#   > ^D
+#   $
+#
+# Error handling is non-existent. This is just a prototype.
+
+fn main -> _/ebx: int {
+  var in-storage: (stream byte 0x100)
+  var in/esi: (addr stream byte) <- address in-storage
+  print-string 0/screen, "press ctrl-c or ctrl-d to exit\n"
+  # read-eval-print loop
+  {
+    # print prompt
+    print-string 0/screen, "> "
+    # read line
+    clear-stream in
+    read-line-from-real-keyboard in
+    var done?/eax: boolean <- stream-empty? in
+    compare done?, 0
+    break-if-!=
+    # parse and eval
+    var out/eax: int <- simplify in
+    # print
+    print-int32-decimal 0/screen, out
+    print-string 0/screen, "\n"
+    #
+    loop
+  }
+  return 0
+}
+
+type int-stack {
+  data: (handle array int)
+  top: int
+}
+
+fn simplify in: (addr stream byte) -> _/eax: int {
+  var word-storage: slice
+  var word/ecx: (addr slice) <- address word-storage
+  var stack-storage: int-stack
+  var stack/esi: (addr int-stack) <- address stack-storage
+  initialize-int-stack stack, 0x10
+  $simplify:word-loop: {
+    next-word in, word
+    var done?/eax: boolean <- slice-empty? word
+    compare done?, 0
+    break-if-!=
+    # if word is an operator, perform it
+    {
+      var is-add?/eax: boolean <- slice-equal? word, "+"
+      compare is-add?, 0
+      break-if-=
+      var _b/eax: int <- pop-int-stack stack
+      var b/edx: int <- copy _b
+      var a/eax: int <- pop-int-stack stack
+      a <- add b
+      push-int-stack stack, a
+      loop $simplify:word-loop
+    }
+    {
+      var is-sub?/eax: boolean <- slice-equal? word, "-"
+      compare is-sub?, 0
+      break-if-=
+      var _b/eax: int <- pop-int-stack stack
+      var b/edx: int <- copy _b
+      var a/eax: int <- pop-int-stack stack
+      a <- subtract b
+      push-int-stack stack, a
+      loop $simplify:word-loop
+    }
+    {
+      var is-mul?/eax: boolean <- slice-equal? word, "*"
+      compare is-mul?, 0
+      break-if-=
+      var _b/eax: int <- pop-int-stack stack
+      var b/edx: int <- copy _b
+      var a/eax: int <- pop-int-stack stack
+      a <- multiply b
+      push-int-stack stack, a
+      loop $simplify:word-loop
+    }
+    # otherwise it's an int
+    var n/eax: int <- parse-decimal-int-from-slice word
+    push-int-stack stack, n
+    loop
+  }
+  var result/eax: int <- pop-int-stack stack
+  return result
+}
+
+fn initialize-int-stack _self: (addr int-stack), n: int {
+  var self/esi: (addr int-stack) <- copy _self
+  var d/edi: (addr handle array int) <- get self, data
+  populate d, n
+  var top/eax: (addr int) <- get self, top
+  copy-to *top, 0
+}
+
+fn push-int-stack _self: (addr int-stack), _val: int {
+  var self/esi: (addr int-stack) <- copy _self
+  var top-addr/ecx: (addr int) <- get self, top
+  var data-ah/edx: (addr handle array int) <- get self, data
+  var data/eax: (addr array int) <- lookup *data-ah
+  var top/edx: int <- copy *top-addr
+  var dest-addr/edx: (addr int) <- index data, top
+  var val/eax: int <- copy _val
+  copy-to *dest-addr, val
+  add-to *top-addr, 1
+}
+
+fn pop-int-stack _self: (addr int-stack) -> _/eax: int {
+  var self/esi: (addr int-stack) <- copy _self
+  var top-addr/ecx: (addr int) <- get self, top
+  {
+    compare *top-addr, 0
+    break-if->
+    return 0
+  }
+  subtract-from *top-addr, 1
+  var data-ah/edx: (addr handle array int) <- get self, data
+  var data/eax: (addr array int) <- lookup *data-ah
+  var top/edx: int <- copy *top-addr
+  var result-addr/eax: (addr int) <- index data, top
+  var val/eax: int <- copy *result-addr
+  return val
+}