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-to-screen "press ctrl-c or ctrl-d to exit\n" 39 # read-eval-print loop 40 { 41 # print prompt 42 print-string-to-screen "> " 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-hex-to-screen n 50 print-string-to-screen "\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 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<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <title>Mu - edit/009-sandbox-test.mu</title> <meta name="Generator" content="Vim/8.0"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="none"> <meta name="settings" content="number_lines,use_css,pre_wrap,no_foldcolumn,expand_tabs,line_ids,prevent_copy="> <meta name="colorscheme" content="minimal-light"> <style type="text/css"> <!-- pre { white-space: pre-wrap; font-family: monospace; color: #000000; background-color: #c6c6c6; } body { font-size:12pt; font-family: monospace; color: #000000; background-color: #c6c6c6; } a { color:inherit; } * { font-size:12pt; font-size: 1em; } .muControl { color: #804000; } .muRecipe { color: #ff8700; } .muScenario { color: #00af00; } .LineNr { } .muData { color: #ffff00; } .Delimiter { color: #c000c0; } .Constant { color: #008787; } .Special { color: #ff6060; } .Comment { color: #005faf; } .SalientComment { color: #0000af; } --> </style> <script type='text/javascript'> <!-- /* function to open any folds containing a jumped-to line before jumping to it */ function JumpToLine() { var lineNum; lineNum = window.location.hash; lineNum = lineNum.substr(1); /* strip off '#' */ if (lineNum.indexOf('L') == -1) { lineNum = 'L'+lineNum; } lineElem = document.getElementById(lineNum); /* Always jump to new location even if the line was hidden inside a fold, or * we corrected the raw number to a line ID. */ if (lineElem) { lineElem.scrollIntoView(true); } return true; } if ('onhashchange' in window) { window.onhashchange = JumpToLine; } --> </script> </head> <body onload='JumpToLine();'> <a href='https://github.com/akkartik/mu/blob/master/edit/009-sandbox-test.mu'>https://github.com/akkartik/mu/blob/master/edit/009-sandbox-test.mu</a> <pre id='vimCodeElement'> <span id="L1" class="LineNr"> 1