about summary refs log blame commit diff stats
path: root/apps/tile/rpn.mu
blob: 4fec403cd7862a9d62323703ddc2c8d4f5d72b43 (plain) (tree)
1
2
3
4
5



                                                                         
                     













































                                                                     
     






                                                              



        




















                                                          


                                                                                         
                                                   

                                   































                                                              
     






                                                                   


        
fn evaluate start: (addr word), end: (addr word), out: (addr int-stack) {
  var curr/eax: (addr word) <- copy start
  var curr-text-storage: (stream byte 0x10)
  var curr-text/edi: (addr stream byte) <- address curr-text-storage
  clear-int-stack out
  $evaluate:loop: {
    # precondition (should never hit)
    compare curr, 0
    break-if-=
    # update curr-text
    emit-word curr, curr-text
    $evaluate:process-word: {
      # if curr-text is an operator, perform it
      {
        var is-add?/eax: boolean <- stream-data-equal? curr-text, "+"
        compare is-add?, 0
        break-if-=
        var _b/eax: int <- pop-int-stack out
        var b/edx: int <- copy _b
        var a/eax: int <- pop-int-stack out
        a <- add b
        push-int-stack out, a
        break $evaluate:process-word
      }
      {
        var is-sub?/eax: boolean <- stream-data-equal? curr-text, "-"
        compare is-sub?, 0
        break-if-=
        var _b/eax: int <- pop-int-stack out
        var b/edx: int <- copy _b
        var a/eax: int <- pop-int-stack out
        a <- subtract b
        push-int-stack out, a
        break $evaluate:process-word
      }
      {
        var is-mul?/eax: boolean <- stream-data-equal? curr-text, "*"
        compare is-mul?, 0
        break-if-=
        var _b/eax: int <- pop-int-stack out
        var b/edx: int <- copy _b
        var a/eax: int <- pop-int-stack out
        a <- multiply b
        push-int-stack out, a
        break $evaluate:process-word
      }
      # otherwise it's an int
      {
        var n/eax: int <- parse-decimal-int-from-stream curr-text
        push-int-stack out, n
      }
    }
    # termination check
    compare curr, end
    break-if-=
    # update
    var next-word-ah/edx: (addr handle word) <- get curr, next
    curr <- lookup *next-word-ah
    #
    loop
  }
}

fn test-evaluate {
  # input = [1, 2, +]
  var w: (handle word)
  var wah/eax: (addr handle word) <- address w
  allocate wah
  var wa/eax: (addr word) <- lookup w
  initialize-word-with wa, "1"
  append-word-with w, "2"
  var next/ecx: (addr handle word) <- get wa, next
  append-word-with *next, "+"
  # initialize output
  var stack-storage: int-stack
  var stack/edx: (addr int-stack) <- address stack-storage
  initialize-int-stack stack, 0x10
  #
  evaluate wa, 0, stack
  # check output
  var x/eax: int <- pop-int-stack stack
  check-ints-equal x, 3, "F - test-evaluate"
}

# Copy of 'simplify' that just tracks the maximum stack depth needed
# Doesn't actually need to simulate the stack, since every word has a predictable effect.
fn max-stack-depth first-word: (addr word), final-word: (addr word) -> result/edi: int {
  var curr-word/eax: (addr word) <- copy first-word
  var curr-depth/ecx: int <- copy 0
  result <- copy 0
  $max-stack-depth:loop: {
    $max-stack-depth:process-word: {
      # handle operators
      {
        var is-add?/eax: boolean <- word-equal? curr-word, "+"
        compare is-add?, 0
        break-if-=
        curr-depth <- decrement
        break $max-stack-depth:process-word
      }
      {
        var is-sub?/eax: boolean <- word-equal? curr-word, "-"
        compare is-sub?, 0
        break-if-=
        curr-depth <- decrement
        break $max-stack-depth:process-word
      }
      {
        var is-mul?/eax: boolean <- word-equal? curr-word, "*"
        compare is-mul?, 0
        break-if-=
        curr-depth <- decrement
        break $max-stack-depth:process-word
      }
      # otherwise it's an int (do we need error-checking?)
      curr-depth <- increment
      # update max depth if necessary
      {
        compare curr-depth, result
        break-if-<=
        result <- copy curr-depth
      }
    }
    # if curr-word == final-word break
    compare curr-word, final-word
    break-if-=
    # curr-word = curr-word->next
    var next-word-ah/edx: (addr handle word) <- get curr-word, next
    curr-word <- lookup *next-word-ah
    #
    loop
  }
}