about summary refs log blame commit diff stats
path: root/factorial.mu
blob: 96a28fd3e6da197438589eaa95ecdfbfde5900a2 (plain) (tree)
1
2
3
4
5
6
7
8
9
                     
                                                               
                           
         
                     


                                                
   
                           



                                                          
  
 
                
                                    
                                 
                                                
                           
  
(function factorial [
  (default-space:space-address <- new space:literal 30:literal)
  (n:integer <- next-input)
  { begin
    ; if n=0 return 1
    (zero?:boolean <- equal n:integer 0:literal)
    (break-unless zero?:boolean)
    (reply 1:literal)
  }
  ; return n*factorial(n-1)
  (x:integer <- subtract n:integer 1:literal)
  (subresult:integer <- factorial x:integer)
  (result:integer <- multiply subresult:integer n:integer)
  (reply result:integer)
])

(function main [
  (1:integer <- factorial 5:literal)
  ($print (("result: " literal)))
  (print-integer nil:literal/terminal 1:integer)
  ($print (("\n" literal)))
])
el-stack, next-label-id) (push %edx %ebx) # ++next-label-id ff 0/subop/increment %ebx # continue e9/jump $subx-braces:next-line/disp32 $subx-braces:check-for-curly-closed: # if (line->data[line->read] != '}') goto next check 3d/compare-eax-and 0x7d/imm32/close-curly 0f 85/jump-if-= $subx-braces:word-loop/disp32 $subx-braces:emit-curly-closed: # eax = pop(label-stack) (pop %edx) # print(out, "@break" eax ":") (write-buffered *(ebp+0xc) "@break") (write-int32-hex-buffered *(ebp+0xc) %eax) (write-buffered *(ebp+0xc) ":") # continue e9/jump $subx-braces:next-line/disp32 $subx-braces:word-loop: (next-word-or-string %ecx %edi) $subx-braces:check1: # if (slice-empty?(word-slice)) break (slice-empty? %edi) 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-!= $subx-braces:next-line/disp32 $subx-braces:check-for-comment: # if (slice-starts-with?(word-slice, "#")) continue # . eax = *word-slice->start 8b/-> *edi 0/r32/eax 8a/copy-byte *eax 0/r32/AL 25/and-eax-with 0xff/imm32 # . if (eax == '#') continue 3d/compare-eax-and 0x23/imm32/hash 74/jump-if-= $subx-braces:word-loop/disp8 $subx-braces:check-for-break: # if (!slice-starts-with?(word-slice, "break/")) goto next check # . eax = slice-starts-with?(word-slice, "break/") (slice-starts-with? %edi "break/") # . if (eax == false) goto next check 3d/compare-eax-and 0/imm32/false 74/jump-if-= $subx-braces:check-for-loop/disp8 $subx-braces:emit-break: (top %edx) # print(out, "@break" eax) (write-buffered *(ebp+0xc) "@break") (write-int32-hex-buffered *(ebp+0xc) %eax) # word-slice->start += len("break") 81 0/subop/add *edi 5/imm32/strlen # emit rest of word as usual eb/jump $subx-braces:emit-word-slice/disp8 $subx-braces:check-for-loop: # if (!slice-starts-with?(word-slice, "loop/")) emit word # . eax = slice-starts-with?(word-slice, "loop/") (slice-starts-with? %edi "loop/") # . if (eax == false) goto next check 3d/compare-eax-and 0/imm32/false 74/jump-if-= $subx-braces:emit-word-slice/disp8 $subx-braces:emit-loop: (top %edx) # print(out, "@loop" eax) (write-buffered *(ebp+0xc) "@loop") (write-int32-hex-buffered *(ebp+0xc) %eax) # word-slice->start += len("loop") 81 0/subop/add *edi 4/imm32/strlen # fall through $subx-braces:emit-word-slice: # print(out, word-slice " ") (write-slice-buffered *(ebp+0xc) %edi) (write-buffered *(ebp+0xc) Space) # loop to next word e9/jump $subx-braces:word-loop/disp32 $subx-braces:next-line: # print(out, "\n") (write-buffered *(ebp+0xc) Newline) # loop to next line e9/jump $subx-braces:line-loop/disp32 $subx-braces:break: (flush *(ebp+0xc)) $subx-braces:end: # . reclaim locals 81 0/subop/add %esp 0x29c/imm32 # . restore registers 5f/pop-to-edi 5e/pop-to-esi 5b/pop-to-ebx 5a/pop-to-edx 59/pop-to-ecx 58/pop-to-eax # . epilogue 89/<- %esp 5/r32/ebp 5d/pop-to-ebp c3/return test-subx-braces-passes-most-words-through: # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # setup (clear-stream _test-input-stream) (clear-stream _test-output-stream) (clear-stream $_test-input-buffered-file->buffer) (clear-stream $_test-output-buffered-file->buffer) # test (write _test-input-stream "== abcd 0x1") (subx-braces _test-input-buffered-file _test-output-buffered-file) # check that the line just passed through (flush _test-output-buffered-file) #? # dump _test-output-stream {{{ #? (write 2 "^") #? (write-stream 2 _test-output-stream) #? (write 2 "$\n") #? # }}} (check-stream-equal _test-output-stream "== abcd 0x1 \n" "F - test-subx-braces-passes-most-words-through") # . epilogue 89/<- %esp 5/r32/ebp 5d/pop-to-ebp c3/return test-subx-braces-1: # input: # { # ab break/imm32 # cd loop/imm32 # } # # output: # @loop1: # ab @break1/imm32 # cd @loop1/imm32 # @break1: # # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # setup (clear-stream _test-input-stream) (clear-stream _test-output-stream) (clear-stream $_test-input-buffered-file->buffer) (clear-stream $_test-output-buffered-file->buffer) # test (write _test-input-stream "{\nab break/imm32\ncd loop/imm32\n}") (subx-braces _test-input-buffered-file _test-output-buffered-file) # check that the line just passed through (flush _test-output-buffered-file) #? # dump _test-output-stream {{{ #? (write 2 "^") #? (write-stream 2 _test-output-stream) #? (write 2 "$\n") #? # }}} (check-stream-equal _test-output-stream "@loop0x00000001:\nab @break0x00000001/imm32 \ncd @loop0x00000001/imm32 \n@break0x00000001:\n" "F - test-subx-braces-1") # . epilogue 89/<- %esp 5/r32/ebp 5d/pop-to-ebp c3/return test-subx-braces-2: # input: # { # { # ab break/imm32 # } # cd loop/imm32 # } # # output: # @loop1: # @loop2: # ab @break2/imm32 # @break2: # cd @loop1/imm32 # @break1: # # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # setup (clear-stream _test-input-stream) (clear-stream _test-output-stream) (clear-stream $_test-input-buffered-file->buffer) (clear-stream $_test-output-buffered-file->buffer) # test (write _test-input-stream "{\n{\nab break/imm32\n}\ncd loop/imm32\n}") (subx-braces _test-input-buffered-file _test-output-buffered-file) # check that the line just passed through (flush _test-output-buffered-file) #? # dump _test-output-stream {{{ #? (write 2 "^") #? (write-stream 2 _test-output-stream) #? (write 2 "$\n") #? # }}} (check-stream-equal _test-output-stream "@loop0x00000001:\n@loop0x00000002:\nab @break0x00000002/imm32 \n@break0x00000002:\ncd @loop0x00000001/imm32 \n@break0x00000001:\n" "F - test-subx-braces-2") # . epilogue 89/<- %esp 5/r32/ebp 5d/pop-to-ebp c3/return