about summary refs log tree commit diff stats
path: root/src/ui/window.h
Commit message (Expand)AuthorAgeFilesLines
* Removed functions from window.cJames Booth2014-12-221-3/+0
* Moved unread to window subtypesJames Booth2014-12-211-1/+4
* Added win_get_titleJames Booth2014-12-211-4/+5
* Use class instead of base pointerJames Booth2014-12-211-8/+8
* Refactoring window types, removing recipient and from references - wipJames Booth2014-12-181-4/+16
* Added rosterwin.cJames Booth2014-12-161-0/+3
* Refactor layout creationJames Booth2014-12-161-3/+3
* Added new window and layout typesJames Booth2014-12-161-39/+58
* Added window specific creation functionsJames Booth2014-12-151-1/+4
* Added win create functions for chat and private chatJames Booth2014-12-101-0/+3
* Removed unused argument from _wins_show_historyJames Booth2014-12-101-1/+1
* Renamed chat_resource -> resourceJames Booth2014-12-101-1/+1
* Moved chat resource to WIN_CHAT typeJames Booth2014-12-101-1/+1
* Moved otr properties to WIN_CHAT typeJames Booth2014-12-101-4/+4
* Added form to WIN_MUC_CONFIG typeJames Booth2014-12-101-1/+1
* Added union for window typesJames Booth2014-12-101-8/+37
* Added /resource commandJames Booth2014-12-021-0/+1
* Changed type to enum for presence colour attributesJames Booth2014-11-161-1/+0
* Replaced colours with theme_item_tJames Booth2014-11-161-3/+3
* Added seperate values for roster and occupants win sizesJames Booth2014-11-151-0/+1
* Changed subwin width to percentageJames Booth2014-11-151-1/+1
* Refactor subwin sizing and disabled wrappingJames Booth2014-11-101-1/+3
* Fixed history messages to work with wrappingJames Booth2014-11-091-3/+4
* Removed /duck commandJames Booth2014-10-181-1/+0
* Implemented /occupants showJames Booth2014-10-09
fn evaluate defs: (addr handle function), bindings: (addr table), scratch: (addr line), end: (addr word), out: (addr value-stack) {
  var line/eax: (addr line) <- copy scratch
  var word-ah/eax: (addr handle word) <- get line, data
  var curr/eax: (addr word) <- lookup *word-ah
  var curr-stream-storage: (stream byte 0x10)
  var curr-stream/edi: (addr stream byte) <- address curr-stream-storage
  clear-value-stack out
  $evaluate:loop: {
    # precondition (should never hit)
    compare curr, 0
    break-if-=
    # update curr-stream
    emit-word curr, curr-stream
#?     print-stream-to-real-screen curr-stream
#?     print-string-to-real-screen "\n"
    $evaluate:process-word: {
      # if curr-stream is an operator, perform it
      {
        var is-add?/eax: boolean <- stream-data-equal? curr-stream, "+"
        compare is-add?, 0
        break-if-=
        var _b/eax: int <- pop-int-from-value-stack out
        var b/edx: int <- copy _b
        var a/eax: int <- pop-int-from-value-stack out
        a <- add b
        push-int-to-value-stack out, a
        break $evaluate:process-word
      }
      {
        var is-sub?/eax: boolean <- stream-data-equal? curr-stream, "-"
        compare is-sub?, 0
        break-if-=
        var _b/eax: int <- pop-int-from-value-stack out
        var b/edx: int <- copy _b
        var a/eax: int <- pop-int-from-value-stack out
        a <- subtract b
        push-int-to-value-stack out, a
        break $evaluate:process-word
      }
      {
        var is-mul?/eax: boolean <- stream-data-equal? curr-stream, "*"
        compare is-mul?, 0
        break-if-=
        var _b/eax: int <- pop-int-from-value-stack out
        var b/edx: int <- copy _b
        var a/eax: int <- pop-int-from-value-stack out
        a <- multiply b
        push-int-to-value-stack out, a
        break $evaluate:process-word
      }
      # if curr-stream is a known function name, call it appropriately
      {
        var callee-h: (handle function)
        var callee-ah/eax: (addr handle function) <- address callee-h
        find-function defs, curr-stream, callee-ah
        var callee/eax: (addr function) <- lookup *callee-ah
        compare callee, 0
        break-if-=
        perform-call callee, out, defs
        break $evaluate:process-word
      }
      # if it's a name, push its value
      {
        compare bindings, 0
        break-if-=
        var tmp: (handle array byte)
        var curr-string-ah/edx: (addr handle array byte) <- address tmp
        stream-to-string curr-stream, curr-string-ah  # unfortunate leak
        var curr-string/eax: (addr array byte) <- lookup *curr-string-ah
        var val-storage: (handle value)
        var val-ah/edi: (addr handle value) <- address val-storage
        lookup-binding bindings, curr-string, val-ah
        var val/eax: (addr value) <- lookup *val-ah
        compare val, 0
        break-if-=
#?         print-string-to-real-screen "value of "
#?         print-string-to-real-screen curr-string
#?         print-string-to-real-screen " is "
#?         print-int32-hex-to-real-screen result
#?         print-string-to-real-screen "\n"
        push-value-stack out, val
        break $evaluate:process-word
      }
      # otherwise assume it's a literal int and push it
      {
        var n/eax: int <- parse-decimal-int-from-stream curr-stream
        push-int-to-value-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 find-function first: (addr handle function), name: (addr stream byte), out: (addr handle function) {
  var curr/esi: (addr handle function) <- copy first
  $find-function:loop: {
    var _f/eax: (addr function) <- lookup *curr
    var f/ecx: (addr function) <- copy _f
    compare f, 0
    break-if-=
    var curr-name-ah/eax: (addr handle array byte) <- get f, name
    var curr-name/eax: (addr array byte) <- lookup *curr-name-ah
    var done?/eax: boolean <- stream-data-equal? name, curr-name
    compare done?, 0  # false
    {
      break-if-=
      copy-handle *curr, out
      break $find-function:loop
    }
    curr <- get f, next
    loop
  }
}

fn perform-call _callee: (addr function), caller-stack: (addr value-stack), defs: (addr handle function) {
  var callee/ecx: (addr function) <- copy _callee
  # create bindings for args
  var table-storage: table
  var table/esi: (addr table) <- address table-storage
  initialize-table table, 0x10
  #
  var curr-arg-ah/eax: (addr handle word) <- get callee, args
  var curr-arg/eax: (addr word) <- lookup *curr-arg-ah
  #
  var curr-key-storage: (handle array byte)
  var curr-key/edx: (addr handle array byte) <- address curr-key-storage
  {
    compare curr-arg, 0
    break-if-=
    # create binding
    word-to-string curr-arg, curr-key
    {
#?       var tmp/eax: (addr array byte) <- lookup *curr-key
#?       print-string-to-real-screen "binding "
#?       print-string-to-real-screen tmp
#?       print-string-to-real-screen " to "
      var curr-val/eax: int <- pop-int-from-value-stack caller-stack
#?       print-int32-decimal-to-real-screen curr-val
#?       print-string-to-real-screen "\n"
      bind-int-in-table table, curr-key, curr-val
    }
    #
    var next-arg-ah/edx: (addr handle word) <- get curr-arg, next
    curr-arg <- lookup *next-arg-ah
    loop
  }
  # obtain body
  var body-ah/eax: (addr handle line) <- get callee, body
  var body/eax: (addr line) <- lookup *body-ah
  # perform call
  var stack-storage: value-stack
  var stack/edi: (addr value-stack) <- address stack-storage
  initialize-value-stack stack, 0x10
#?   print-string-to-real-screen "about to enter recursive eval\n"
  evaluate defs, table, body, 0, stack
#?   print-string-to-real-screen "exited recursive eval\n"
  # stitch result from stack into caller
  var result/eax: int <- pop-int-from-value-stack stack
  push-int-to-value-stack caller-stack, result
}

# 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
  }
}