diff options
Diffstat (limited to 'linux/rpn.mu')
-rw-r--r-- | linux/rpn.mu | 148 |
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 +} |