diff --git a/baremetal/rpn.mu b/baremetal/rpn.mu index 0944b42b..aea6b0fa 100644 --- a/baremetal/rpn.mu +++ b/baremetal/rpn.mu @@ -1,7 +1,8 @@ # Integer arithmetic using postfix notation # # Limitations: -# No division yet. +# '+' and '*' temporarily not available until the keyboard driver supports the shift key +# Division not implemented yet. # # To build: # $ ./translate_mu_baremetal baremetal/rpn.mu @@ -13,8 +14,6 @@ # > 5 3 - # 2 # -# '+' and '*' not supported yet because they require the shift key. -# # Error handling is non-existent. This is just a prototype. fn main -> _/ebx: int { diff --git a/html/baremetal/rpn.mu.html b/html/baremetal/rpn.mu.html index eb25a5ae..b613716b 100644 --- a/html/baremetal/rpn.mu.html +++ b/html/baremetal/rpn.mu.html @@ -59,158 +59,157 @@ if ('onhashchange' in window) { 1 # Integer arithmetic using postfix notation 2 # 3 # Limitations: - 4 # No division yet. - 5 # - 6 # To build: - 7 # $ ./translate_mu_baremetal baremetal/rpn.mu - 8 # - 9 # Example session: - 10 # $ qemu-system-i386 disk.img - 11 # > 4 - 12 # 4 - 13 # > 5 3 - - 14 # 2 - 15 # - 16 # '+' and '*' not supported yet because they require the shift key. - 17 # - 18 # Error handling is non-existent. This is just a prototype. - 19 - 20 fn main -> _/ebx: int { - 21 var in-storage: (stream byte 0x80) - 22 var in/esi: (addr stream byte) <- address in-storage - 23 var y/ecx: int <- copy 0 - 24 var space/edx: grapheme <- copy 0x20 - 25 # read-eval-print loop - 26 { - 27 # print prompt - 28 var x/eax: int <- draw-text-rightward 0, "> ", 0, 0x80, y, 3 - 29 set-cursor-position 0, x, y - 30 # read line from keyboard - 31 clear-stream in - 32 { - 33 show-cursor 0, space - 34 var key/eax: byte <- read-key 0 - 35 compare key, 0xa # newline - 36 break-if-= - 37 compare key, 0 - 38 loop-if-= - 39 var key2/eax: int <- copy key - 40 append-byte in, key2 - 41 var g/eax: grapheme <- copy key2 - 42 draw-grapheme-at-cursor 0, g, 0xf - 43 cursor-right 0 - 44 loop - 45 } - 46 # clear cursor - 47 draw-grapheme-at-cursor 0, space, 3 # 3=foreground color, which is never used - 48 # parse and eval - 49 var out/eax: int <- simplify in - 50 # print - 51 y <- increment - 52 out, y <- draw-int32-decimal-wrapping-right-then-down 0, out, 0, y, 0x80, 0x30, 0, y, 7 - 53 # newline - 54 y <- increment - 55 # - 56 loop - 57 } - 58 return 0 - 59 } - 60 - 61 type int-stack { - 62 data: (handle array int) - 63 top: int - 64 } - 65 - 66 fn simplify in: (addr stream byte) -> _/eax: int { - 67 var word-storage: slice - 68 var word/ecx: (addr slice) <- address word-storage - 69 var stack-storage: int-stack - 70 var stack/esi: (addr int-stack) <- address stack-storage - 71 initialize-int-stack stack, 0x10 - 72 $simplify:word-loop: { - 73 next-word in, word - 74 var done?/eax: boolean <- slice-empty? word - 75 compare done?, 0 - 76 break-if-!= - 77 # if word is an operator, perform it - 78 { - 79 var is-add?/eax: boolean <- slice-equal? word, "+" - 80 compare is-add?, 0 - 81 break-if-= - 82 var _b/eax: int <- pop-int-stack stack - 83 var b/edx: int <- copy _b - 84 var a/eax: int <- pop-int-stack stack - 85 a <- add b - 86 push-int-stack stack, a - 87 loop $simplify:word-loop - 88 } - 89 { - 90 var is-sub?/eax: boolean <- slice-equal? word, "-" - 91 compare is-sub?, 0 - 92 break-if-= - 93 var _b/eax: int <- pop-int-stack stack - 94 var b/edx: int <- copy _b - 95 var a/eax: int <- pop-int-stack stack - 96 a <- subtract b - 97 push-int-stack stack, a - 98 loop $simplify:word-loop - 99 } -100 { -101 var is-mul?/eax: boolean <- slice-equal? word, "*" -102 compare is-mul?, 0 -103 break-if-= -104 var _b/eax: int <- pop-int-stack stack -105 var b/edx: int <- copy _b -106 var a/eax: int <- pop-int-stack stack -107 a <- multiply b -108 push-int-stack stack, a -109 loop $simplify:word-loop -110 } -111 # otherwise it's an int -112 var n/eax: int <- parse-decimal-int-from-slice word -113 push-int-stack stack, n -114 loop -115 } -116 var result/eax: int <- pop-int-stack stack -117 return result -118 } -119 -120 fn initialize-int-stack _self: (addr int-stack), n: int { -121 var self/esi: (addr int-stack) <- copy _self -122 var d/edi: (addr handle array int) <- get self, data -123 populate d, n -124 var top/eax: (addr int) <- get self, top -125 copy-to *top, 0 -126 } -127 -128 fn push-int-stack _self: (addr int-stack), _val: int { -129 var self/esi: (addr int-stack) <- copy _self -130 var top-addr/ecx: (addr int) <- get self, top -131 var data-ah/edx: (addr handle array int) <- get self, data -132 var data/eax: (addr array int) <- lookup *data-ah -133 var top/edx: int <- copy *top-addr -134 var dest-addr/edx: (addr int) <- index data, top -135 var val/eax: int <- copy _val -136 copy-to *dest-addr, val -137 add-to *top-addr, 1 -138 } -139 -140 fn pop-int-stack _self: (addr int-stack) -> _/eax: int { -141 var self/esi: (addr int-stack) <- copy _self -142 var top-addr/ecx: (addr int) <- get self, top -143 { -144 compare *top-addr, 0 -145 break-if-> -146 return 0 -147 } -148 subtract-from *top-addr, 1 -149 var data-ah/edx: (addr handle array int) <- get self, data -150 var data/eax: (addr array int) <- lookup *data-ah -151 var top/edx: int <- copy *top-addr -152 var result-addr/eax: (addr int) <- index data, top -153 var val/eax: int <- copy *result-addr -154 return val -155 } + 4 # '+' and '*' temporarily not available until the keyboard driver supports the shift key + 5 # Division not implemented yet. + 6 # + 7 # To build: + 8 # $ ./translate_mu_baremetal baremetal/rpn.mu + 9 # + 10 # Example session: + 11 # $ qemu-system-i386 disk.img + 12 # > 4 + 13 # 4 + 14 # > 5 3 - + 15 # 2 + 16 # + 17 # Error handling is non-existent. This is just a prototype. + 18 + 19 fn main -> _/ebx: int { + 20 var in-storage: (stream byte 0x80) + 21 var in/esi: (addr stream byte) <- address in-storage + 22 var y/ecx: int <- copy 0 + 23 var space/edx: grapheme <- copy 0x20 + 24 # read-eval-print loop + 25 { + 26 # print prompt + 27 var x/eax: int <- draw-text-rightward 0, "> ", 0, 0x80, y, 3 + 28 set-cursor-position 0, x, y + 29 # read line from keyboard + 30 clear-stream in + 31 { + 32 show-cursor 0, space + 33 var key/eax: byte <- read-key 0 + 34 compare key, 0xa # newline + 35 break-if-= + 36 compare key, 0 + 37 loop-if-= + 38 var key2/eax: int <- copy key + 39 append-byte in, key2 + 40 var g/eax: grapheme <- copy key2 + 41 draw-grapheme-at-cursor 0, g, 0xf + 42 cursor-right 0 + 43 loop + 44 } + 45 # clear cursor + 46 draw-grapheme-at-cursor 0, space, 3 # 3=foreground color, which is never used + 47 # parse and eval + 48 var out/eax: int <- simplify in + 49 # print + 50 y <- increment + 51 out, y <- draw-int32-decimal-wrapping-right-then-down 0, out, 0, y, 0x80, 0x30, 0, y, 7 + 52 # newline + 53 y <- increment + 54 # + 55 loop + 56 } + 57 return 0 + 58 } + 59 + 60 type int-stack { + 61 data: (handle array int) + 62 top: int + 63 } + 64 + 65 fn simplify in: (addr stream byte) -> _/eax: int { + 66 var word-storage: slice + 67 var word/ecx: (addr slice) <- address word-storage + 68 var stack-storage: int-stack + 69 var stack/esi: (addr int-stack) <- address stack-storage + 70 initialize-int-stack stack, 0x10 + 71 $simplify:word-loop: { + 72 next-word in, word + 73 var done?/eax: boolean <- slice-empty? word + 74 compare done?, 0 + 75 break-if-!= + 76 # if word is an operator, perform it + 77 { + 78 var is-add?/eax: boolean <- slice-equal? word, "+" + 79 compare is-add?, 0 + 80 break-if-= + 81 var _b/eax: int <- pop-int-stack stack + 82 var b/edx: int <- copy _b + 83 var a/eax: int <- pop-int-stack stack + 84 a <- add b + 85 push-int-stack stack, a + 86 loop $simplify:word-loop + 87 } + 88 { + 89 var is-sub?/eax: boolean <- slice-equal? word, "-" + 90 compare is-sub?, 0 + 91 break-if-= + 92 var _b/eax: int <- pop-int-stack stack + 93 var b/edx: int <- copy _b + 94 var a/eax: int <- pop-int-stack stack + 95 a <- subtract b + 96 push-int-stack stack, a + 97 loop $simplify:word-loop + 98 } + 99 { +100 var is-mul?/eax: boolean <- slice-equal? word, "*" +101 compare is-mul?, 0 +102 break-if-= +103 var _b/eax: int <- pop-int-stack stack +104 var b/edx: int <- copy _b +105 var a/eax: int <- pop-int-stack stack +106 a <- multiply b +107 push-int-stack stack, a +108 loop $simplify:word-loop +109 } +110 # otherwise it's an int +111 var n/eax: int <- parse-decimal-int-from-slice word +112 push-int-stack stack, n +113 loop +114 } +115 var result/eax: int <- pop-int-stack stack +116 return result +117 } +118 +119 fn initialize-int-stack _self: (addr int-stack), n: int { +120 var self/esi: (addr int-stack) <- copy _self +121 var d/edi: (addr handle array int) <- get self, data +122 populate d, n +123 var top/eax: (addr int) <- get self, top +124 copy-to *top, 0 +125 } +126 +127 fn push-int-stack _self: (addr int-stack), _val: int { +128 var self/esi: (addr int-stack) <- copy _self +129 var top-addr/ecx: (addr int) <- get self, top +130 var data-ah/edx: (addr handle array int) <- get self, data +131 var data/eax: (addr array int) <- lookup *data-ah +132 var top/edx: int <- copy *top-addr +133 var dest-addr/edx: (addr int) <- index data, top +134 var val/eax: int <- copy _val +135 copy-to *dest-addr, val +136 add-to *top-addr, 1 +137 } +138 +139 fn pop-int-stack _self: (addr int-stack) -> _/eax: int { +140 var self/esi: (addr int-stack) <- copy _self +141 var top-addr/ecx: (addr int) <- get self, top +142 { +143 compare *top-addr, 0 +144 break-if-> +145 return 0 +146 } +147 subtract-from *top-addr, 1 +148 var data-ah/edx: (addr handle array int) <- get self, data +149 var data/eax: (addr array int) <- lookup *data-ah +150 var top/edx: int <- copy *top-addr +151 var result-addr/eax: (addr int) <- index data, top +152 var val/eax: int <- copy *result-addr +153 return val +154 }