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
2
3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 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
- 26 {
- 27
- 28 var x/eax: int <- draw-text-rightward 0, "> ", 0, 0x80, y, 3
- 29 set-cursor-position 0, x, y
- 30
- 31 clear-stream in
- 32 {
- 33 show-cursor 0, space
- 34 var key/eax: byte <- read-key 0
- 35 compare key, 0xa
- 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
- 47 draw-grapheme-at-cursor 0, space, 3
- 48
- 49 var out/eax: int <- simplify in
- 50
- 51 y <- increment
- 52 out, y <- draw-int32-decimal-wrapping-right-then-down 0, out, 0, y, 0x80, 0x30, 0, y, 7
- 53
- 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
- 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
-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
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 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
+ 25 {
+ 26
+ 27 var x/eax: int <- draw-text-rightward 0, "> ", 0, 0x80, y, 3
+ 28 set-cursor-position 0, x, y
+ 29
+ 30 clear-stream in
+ 31 {
+ 32 show-cursor 0, space
+ 33 var key/eax: byte <- read-key 0
+ 34 compare key, 0xa
+ 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
+ 46 draw-grapheme-at-cursor 0, space, 3
+ 47
+ 48 var out/eax: int <- simplify in
+ 49
+ 50 y <- increment
+ 51 out, y <- draw-int32-decimal-wrapping-right-then-down 0, out, 0, y, 0x80, 0x30, 0, y, 7
+ 52
+ 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
+ 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
+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 }