From 8f9b21f0859a721150e673f6c5be78e3869359e6 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Tue, 16 Jun 2020 00:09:16 -0700 Subject: 6547 --- html/apps/arith.mu.html | 318 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 html/apps/arith.mu.html (limited to 'html/apps/arith.mu.html') diff --git a/html/apps/arith.mu.html b/html/apps/arith.mu.html new file mode 100644 index 00000000..64db9a11 --- /dev/null +++ b/html/apps/arith.mu.html @@ -0,0 +1,318 @@ + + + + +Mu - apps/arith.mu + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/apps/arith.mu +
+  1 # Integer arithmetic using conventional precedence.
+  2 #
+  3 # Follows part 2 of Jack Crenshaw's "Let's build a compiler!"
+  4 #   https://compilers.iecc.com/crenshaw
+  5 #
+  6 # Limitations:
+  7 #   Reads numbers in decimal, but prints numbers in hex :(
+  8 #   No division yet.
+  9 #
+ 10 # To build:
+ 11 #   $ ./translate_mu apps/arith.mu
+ 12 #
+ 13 # Example session:
+ 14 #   $ ./a.elf
+ 15 #   press ctrl-c or ctrl-d to exit
+ 16 #   > 1
+ 17 #   0x00000001
+ 18 #   > 1+1
+ 19 #   0x00000002
+ 20 #   > 1 + 1
+ 21 #   0x00000002
+ 22 #   > 1+2 +3
+ 23 #   0x00000006
+ 24 #   > 1+2 *3
+ 25 #   0x00000007
+ 26 #   > (1+2) *3
+ 27 #   0x00000009
+ 28 #   > 1 + 3*4
+ 29 #   0x0000000d
+ 30 #   > ^D
+ 31 #   $
+ 32 #
+ 33 # Error handling is non-existent. This is just a prototype.
+ 34 
+ 35 fn main -> exit-status/ebx: int {
+ 36   var look/esi: byte <- copy 0  # lookahead
+ 37   var n/eax: int <- copy 0  # result of each expression
+ 38   print-string "press ctrl-c or ctrl-d to exit\n"
+ 39   # read-eval-print loop
+ 40   {
+ 41     # print prompt
+ 42     print-string "> "
+ 43     # read and eval
+ 44     n, look <- simplify  # we explicitly thread 'look' everywhere
+ 45     # if (look == 0) break
+ 46     compare look, 0
+ 47     break-if-=
+ 48     # print
+ 49     print-int32-to-screen n
+ 50     print-string "\n"
+ 51     #
+ 52     loop
+ 53   }
+ 54   exit-status <- copy 0
+ 55 }
+ 56 
+ 57 fn simplify -> result/eax: int, look/esi: byte {
+ 58   # prime the pump
+ 59   look <- get-char  # prime the pump
+ 60   # do it
+ 61   result, look <- expression look
+ 62 }
+ 63 
+ 64 fn expression _look: byte -> result/eax: int, look/esi: byte {
+ 65   look <- copy _look  # should be a no-op
+ 66   # read arg
+ 67   result, look <- term look
+ 68   $expression:loop: {
+ 69     # while next non-space char in ['+', '-']
+ 70     look <- skip-spaces look
+ 71     {
+ 72       var continue?/eax: boolean <- is-add-or-sub? look
+ 73       compare continue?, 0  # false
+ 74       break-if-= $expression:loop
+ 75     }
+ 76     # read operator
+ 77     var op/ecx: byte <- copy 0
+ 78     op, look <- operator look
+ 79     # read next arg
+ 80     var second/edx: int <- copy 0
+ 81     look <- skip-spaces look
+ 82     {
+ 83       var tmp/eax: int <- copy 0
+ 84       tmp, look <- term look
+ 85       second <- copy tmp
+ 86     }
+ 87     # reduce
+ 88     $expression:perform-op: {
+ 89       {
+ 90         compare op, 0x2b  # '+'
+ 91         break-if-!=
+ 92         result <- add second
+ 93         break $expression:perform-op
+ 94       }
+ 95       {
+ 96         compare op, 0x2d  # '-'
+ 97         break-if-!=
+ 98         result <- subtract second
+ 99         break $expression:perform-op
+100       }
+101     }
+102     loop
+103   }
+104   look <- skip-spaces look
+105 }
+106 
+107 fn term _look: byte -> result/eax: int, look/esi: byte {
+108   look <- copy _look  # should be a no-op
+109   # read arg
+110   look <- skip-spaces look
+111   result, look <- factor look
+112   $term:loop: {
+113     # while next non-space char in ['*', '/']
+114     look <- skip-spaces look
+115     {
+116       var continue?/eax: boolean <- is-mul-or-div? look
+117       compare continue?, 0  # false
+118       break-if-= $term:loop
+119     }
+120     # read operator
+121     var op/ecx: byte <- copy 0
+122     op, look <- operator look
+123     # read next arg
+124     var second/edx: int <- copy 0
+125     look <- skip-spaces look
+126     {
+127       var tmp/eax: int <- copy 0
+128       tmp, look <- factor look
+129       second <- copy tmp
+130     }
+131     # reduce
+132     $term:perform-op: {
+133       {
+134         compare op, 0x2a  # '*'
+135         break-if-!=
+136         result <- multiply second
+137         break $term:perform-op
+138       }
+139 #?       {
+140 #?         compare op, 0x2f  # '/'
+141 #?         break-if-!=
+142 #?         result <- divide second  # not in Mu yet
+143 #?         break $term:perform-op
+144 #?       }
+145     }
+146     loop
+147   }
+148 }
+149 
+150 fn factor _look: byte -> result/eax: int, look/esi: byte {
+151 $factor:body: {
+152   look <- copy _look  # should be a no-op
+153   look <- skip-spaces look
+154   # if next char is not '(', parse a number
+155   compare look, 0x28  # '('
+156   {
+157     break-if-=
+158     result, look <- num look
+159     break $factor:body
+160   }
+161   # otherwise recurse
+162   look <- get-char look  # '('
+163   result, look <- expression look
+164   look <- skip-spaces look
+165   look <- get-char look  # ')'
+166 }  # $factor:body
+167 }
+168 
+169 fn is-mul-or-div? c: byte -> result/eax: bool {
+170 $is-mul-or-div?:body: {
+171   compare c, 0x2a  # '*'
+172   {
+173     break-if-!=
+174     result <- copy 1  # true
+175     break $is-mul-or-div?:body
+176   }
+177   compare c, 0x2f  # '/'
+178   {
+179     break-if-!=
+180     result <- copy 1  # true
+181     break $is-mul-or-div?:body
+182   }
+183   result <- copy 0  # false
+184 }  # $is-mul-or-div?:body
+185 }
+186 
+187 fn is-add-or-sub? c: byte -> result/eax: bool {
+188 $is-add-or-sub?:body: {
+189   compare c, 0x2b  # '+'
+190   {
+191     break-if-!=
+192     result <- copy 1  # true
+193     break $is-add-or-sub?:body
+194   }
+195   compare c, 0x2d  # '-'
+196   {
+197     break-if-!=
+198     result <- copy 1  # true
+199     break $is-add-or-sub?:body
+200   }
+201   result <- copy 0  # false
+202 }  # $is-add-or-sub?:body
+203 }
+204 
+205 fn operator _look: byte -> op/ecx: byte, look/esi: byte {
+206   op <- copy _look
+207   look <- get-char
+208 }
+209 
+210 fn num _look: byte -> result/eax: int, look/esi: byte {
+211   look <- copy _look  # should be a no-op
+212   var out/edi: int <- copy 0
+213   {
+214     var first-digit/eax: int <- to-decimal-digit look
+215     out <- copy first-digit
+216   }
+217   {
+218     look <- get-char
+219     # done?
+220     var digit?/eax: bool <- is-decimal-digit? look
+221     compare digit?, 0  # false
+222     break-if-=
+223     # out *= 10
+224     {
+225       var ten/eax: int <- copy 0xa
+226       out <- multiply ten
+227     }
+228     # out += digit(look)
+229     var digit/eax: int <- to-decimal-digit look
+230     out <- add digit
+231     loop
+232   }
+233   result <- copy out
+234 }
+235 
+236 fn skip-spaces _look: byte -> look/esi: byte {
+237   look <- copy _look  # should be a no-op
+238   {
+239     compare look, 0x20
+240     break-if-!=
+241     look <- get-char
+242     loop
+243   }
+244 }
+245 
+246 fn get-char -> look/esi: byte {
+247   var tmp/eax: byte <- read-key
+248   look <- copy tmp
+249   compare look, 0
+250   {
+251     break-if-!=
+252     print-string "^D\n"
+253     syscall_exit
+254   }
+255 }
+
+ + + -- cgit 1.4.1-2-gfad0