about summary refs log tree commit diff stats
path: root/prototypes/tile
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-10-01 20:40:22 -0700
committerKartik Agaram <vc@akkartik.com>2020-10-01 20:40:22 -0700
commitd75b71297426ee2d63d5630d1ef9469de48aca84 (patch)
tree0d4c517526770343822d4f409a8e9c1b7ac0e51e /prototypes/tile
parentf3ca0e3cb33d6c34dbe4c6941598d16d140be206 (diff)
downloadmu-d75b71297426ee2d63d5630d1ef9469de48aca84.tar.gz
6923
Diffstat (limited to 'prototypes/tile')
-rw-r--r--prototypes/tile/1.mu47
-rw-r--r--prototypes/tile/10.mu341
-rw-r--r--prototypes/tile/11.mu353
-rw-r--r--prototypes/tile/2.mu84
-rw-r--r--prototypes/tile/3.mu76
-rw-r--r--prototypes/tile/4.mu56
-rw-r--r--prototypes/tile/5.mu145
-rw-r--r--prototypes/tile/6.mu184
-rw-r--r--prototypes/tile/7.mu198
-rw-r--r--prototypes/tile/8.mu228
-rw-r--r--prototypes/tile/9.mu307
-rw-r--r--prototypes/tile/README.md13
12 files changed, 0 insertions, 2032 deletions
diff --git a/prototypes/tile/1.mu b/prototypes/tile/1.mu
deleted file mode 100644
index 4d0a7969..00000000
--- a/prototypes/tile/1.mu
+++ /dev/null
@@ -1,47 +0,0 @@
-# little example program: animate a line in text-mode
-#
-# To run (on Linux and x86):
-#   $ git clone https://github.com/akkartik/mu
-#   $ cd mu
-#   $ ./translate_mu prototypes/tile/1.mu
-#   $ ./a.elf
-# You should see a line drawn on a blank screen. Press a key. You should see
-# the line seem to fall down the screen. Press a second key to quit.
-# https://archive.org/details/akkartik-2min-2020-07-01
-
-fn main -> exit-status/ebx: int {
-  clear-screen 0
-  move-cursor 0, 5, 5
-  print-string 0, "_________"
-  enable-keyboard-immediate-mode
-  var dummy/eax: grapheme <- read-key-from-real-keyboard
-  var row/eax: int <- copy 5
-  {
-    compare row, 0xe  # 15
-    break-if-=
-    animate row
-    row <- increment
-    sleep 0 0x5f5e100  # 100ms
-    loop
-  }
-  var dummy/eax: grapheme <- read-key-from-real-keyboard
-  enable-keyboard-type-mode
-  clear-screen 0
-  exit-status <- copy 0
-}
-
-fn animate row: int {
-  var col/eax: int <- copy 5
-  {
-    compare col, 0xe
-    break-if-=
-    move-cursor 0, row, col
-    print-string 0, " "
-    increment row
-    move-cursor 0, row, col
-    print-string 0, "_"
-    decrement row
-    col <- increment
-    loop
-  }
-}
diff --git a/prototypes/tile/10.mu b/prototypes/tile/10.mu
deleted file mode 100644
index 6f971b1c..00000000
--- a/prototypes/tile/10.mu
+++ /dev/null
@@ -1,341 +0,0 @@
-# Moving around within a tree and creating children.
-#
-# To run (on Linux and x86):
-#   $ git clone https://github.com/akkartik/mu
-#   $ cd mu
-#   $ ./translate_mu prototypes/tile/10.mu
-#   $ ./a.elf
-#
-# Press 'c' to create new children for the root node, and keys to move:
-#   'h': parent
-#   'l': first child
-#   'j': next sibling
-#   'k': prev sibling
-
-# To run unit tests:
-#   $ ./a.elf test
-fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int {
-  var args/eax: (addr array addr array byte) <- copy args-on-stack
-  var tmp/ecx: int <- length args
-  $main-body: {
-    # if (len(args) > 1 && args[1] == "test") run-tests()
-    compare tmp, 1
-    {
-      break-if-<=
-      # if (args[1] == "test") run-tests()
-      var tmp2/ecx: (addr addr array byte) <- index args, 1
-      var tmp3/eax: boolean <- string-equal? *tmp2, "test"
-      compare tmp3, 0
-      {
-        break-if-=
-        run-tests
-        exit-status <- copy 0  # TODO: get at Num-test-failures somehow
-      }
-      break $main-body
-    }
-    # otherwise operate interactively
-    exit-status <- interactive
-  }
-}
-
-# - interactive loop
-
-type cell {
-  val: int  # single chars only for now
-  parent: (handle cell)
-  first-child: (handle cell)
-  next-sibling: (handle cell)
-  prev-sibling: (handle cell)
-}
-
-fn interactive -> exit-status/ebx: int {
-  var root-handle: (handle cell)
-  var root/esi: (addr handle cell) <- address root-handle
-  allocate root
-  var cursor-handle: (handle cell)
-  var cursor/edi: (addr handle cell) <- address cursor-handle
-  copy-handle root-handle, cursor
-  enable-keyboard-immediate-mode
-  var _root-addr/eax: (addr cell) <- lookup *root
-  var root-addr/ecx: (addr cell) <- copy _root-addr
-  var cursor-addr/eax: (addr cell) <- lookup *cursor
-  render root-addr, cursor-addr
-$main:loop: {
-    # process key
-    {
-      var c/eax: grapheme <- read-key-from-real-keyboard
-      compare c, 4  # ctrl-d
-      break-if-= $main:loop
-      process c, root, cursor
-    }
-    # render tree
-    var _root-addr/eax: (addr cell) <- lookup root-handle
-    root-addr <- copy _root-addr
-    var cursor-addr/eax: (addr cell) <- lookup *cursor
-    render root-addr, cursor-addr
-    loop
-  }
-  clear-screen 0
-  enable-keyboard-type-mode
-  exit-status <- copy 0
-}
-
-#######################################################
-# Tree mutations
-#######################################################
-
-fn process c: grapheme, root: (addr handle cell), cursor: (addr handle cell) {
-$process:body: {
-  # if c == 'h' move cursor to its parent if possible
-  {
-    compare c, 0x68  # 'h'
-    break-if-!=
-    move-to-parent cursor
-  }
-  # if c == 'l' move cursor to its first child if possible
-  {
-    compare c, 0x6c  # 'l'
-    break-if-!=
-    move-to-child cursor
-  }
-  # if c == 'j' move cursor to its next sibling if possible
-  {
-    compare c, 0x6a  # 'j'
-    break-if-!=
-    move-to-next-sibling cursor
-  }
-  # if c == 'k' move cursor to its prev sibling if possible
-  {
-    compare c, 0x6b  # 'k'
-    break-if-!=
-    move-to-prev-sibling cursor
-  }
-  # if c == 'c' create a new child at the cursor
-  {
-    compare c, 0x63  # 'c'
-    break-if-!=
-    var cursor2/eax: (addr handle cell) <- copy cursor
-    create-child *cursor2
-  }
-}
-}
-
-fn move-to-parent cursor: (addr handle cell) {
-  var cursor2/eax: (addr handle cell) <- copy cursor
-  var cursor3/eax: (addr cell) <- lookup *cursor2
-  var parent/ecx: (addr handle cell) <- get cursor3, parent
-  {
-    var tmp/eax: (addr cell) <- lookup *parent
-    compare tmp, 0
-    break-if-=
-    copy-handle *parent, cursor
-  }
-}
-
-fn move-to-child cursor: (addr handle cell) {
-  var cursor2/eax: (addr handle cell) <- copy cursor
-  var cursor3/eax: (addr cell) <- lookup *cursor2
-  var child/ecx: (addr handle cell) <- get cursor3, first-child
-  {
-    var tmp/eax: (addr cell) <- lookup *child
-    compare tmp, 0
-    break-if-=
-    copy-handle *child, cursor
-  }
-}
-
-fn move-to-next-sibling cursor: (addr handle cell) {
-  var cursor2/eax: (addr handle cell) <- copy cursor
-  var cursor3/eax: (addr cell) <- lookup *cursor2
-  var sib/ecx: (addr handle cell) <- get cursor3, next-sibling
-  {
-    var tmp/eax: (addr cell) <- lookup *sib
-    compare tmp, 0
-    break-if-=
-    copy-handle *sib, cursor
-  }
-}
-
-fn move-to-prev-sibling cursor: (addr handle cell) {
-  var cursor2/eax: (addr handle cell) <- copy cursor
-  var cursor3/eax: (addr cell) <- lookup *cursor2
-  var sib/ecx: (addr handle cell) <- get cursor3, prev-sibling
-  {
-    var tmp/eax: (addr cell) <- lookup *sib
-    compare tmp, 0
-    break-if-=
-    copy-handle *sib, cursor
-  }
-}
-
-fn create-child node: (handle cell) {
-  var n/eax: (addr cell) <- lookup node
-  var child/esi: (addr handle cell) <- get n, first-child
-  var prev/edx: (addr handle cell) <- copy 0
-  {
-    var tmp/eax: (addr cell) <- lookup *child
-    compare tmp, 0
-    break-if-=
-    prev <- copy child
-    child <- get tmp, next-sibling
-    loop
-  }
-  allocate child
-  var child2/eax: (addr cell) <- lookup *child
-  var dest/ecx: (addr handle cell) <- get child2, prev-sibling
-  # child->prev-sibling = prev
-  {
-    compare prev, 0
-    break-if-=
-    copy-handle *prev, dest
-  }
-  # child->parent = node
-  dest <- get child2, parent
-  copy-handle node, dest
-}
-
-#######################################################
-# Tree drawing
-#######################################################
-
-fn render root: (addr cell), cursor: (addr cell) {
-  clear-screen 0
-  var depth/eax: int <- tree-depth root
-  var viewport-width/ecx: int <- copy 0x65  # col2
-  viewport-width <- subtract 5  # col1
-  var column-width/eax: int <- try-divide viewport-width, depth
-  render-tree root, column-width, 5, 5, 0x20, 0x65, cursor
-}
-
-fn render-tree c: (addr cell), column-width: int, row-min: int, col-min: int, row-max: int, col-max: int, cursor: (addr cell) {
-$render-tree:body: {
-  var root-max/ecx: int <- copy col-min
-  root-max <- add column-width
-  draw-box row-min, col-min, row-max, root-max
-  var c2/edx: (addr cell) <- copy c
-  {
-    compare c2, cursor
-    break-if-!=
-    draw-hatching row-min, col-min, row-max, root-max
-  }
-  # if single child, render it (slightly shorter than the parent)
-  var nchild/eax: int <- num-children c
-  {
-    compare nchild, 1
-    break-if->
-    var child/edx: (addr handle cell) <- get c2, first-child
-    var child-addr/eax: (addr cell) <- lookup *child
-    {
-      compare child-addr, 0
-      break-if-=
-      increment row-min
-      decrement row-max
-      render-tree child-addr, column-width, row-min, root-max, row-max, col-max, cursor
-    }
-    break $render-tree:body
-  }
-  # otherwise divide vertical space up equally among children
-  var column-height/ebx: int <- copy row-max
-  column-height <- subtract row-min
-  var child-height/eax: int <- try-divide column-height, nchild
-  var child-height2/ebx: int <- copy child-height
-  var curr/edx: (addr handle cell) <- get c2, first-child
-  var curr-addr/eax: (addr cell) <- lookup *curr
-  var rmin/esi: int <- copy row-min
-  var rmax/edi: int <- copy row-min
-  rmax <- add child-height2
-  {
-    compare curr-addr, 0
-    break-if-=
-    render-tree curr-addr, column-width, rmin, root-max, rmax, col-max, cursor
-    curr <- get curr-addr, next-sibling
-    curr-addr <- lookup *curr
-    rmin <- add child-height2
-    rmax <- add child-height2
-    loop
-  }
-}
-}
-
-fn num-children node-on-stack: (addr cell) -> result/eax: int {
-  var tmp-result/edi: int <- copy 0
-  var node/eax: (addr cell) <- copy node-on-stack
-  var child/ecx: (addr handle cell) <- get node, first-child
-  var child-addr/eax: (addr cell) <- lookup *child
-  {
-    compare child-addr, 0
-    break-if-=
-    tmp-result <- increment
-    child <- get child-addr, next-sibling
-    child-addr <- lookup *child
-    loop
-  }
-  result <- copy tmp-result
-}
-
-fn tree-depth node-on-stack: (addr cell) -> result/eax: int {
-  var tmp-result/edi: int <- copy 0
-  var node/eax: (addr cell) <- copy node-on-stack
-  var child/ecx: (addr handle cell) <- get node, first-child
-  var child-addr/eax: (addr cell) <- lookup *child
-  {
-    compare child-addr, 0
-    break-if-=
-    {
-      var tmp/eax: int <- tree-depth child-addr
-      compare tmp, tmp-result
-      break-if-<=
-      tmp-result <- copy tmp
-    }
-    child <- get child-addr, next-sibling
-    child-addr <- lookup *child
-    loop
-  }
-  result <- copy tmp-result
-  result <- increment
-}
-
-fn draw-box row1: int, col1: int, row2: int, col2: int {
-  draw-horizontal-line row1, col1, col2
-  draw-vertical-line row1, row2, col1
-  draw-horizontal-line row2, col1, col2
-  draw-vertical-line row1, row2, col2
-}
-
-fn draw-hatching row1: int, col1: int, row2: int, col2: int {
-  var c/eax: int <- copy col1
-  var r1/ecx: int <- copy row1
-  r1 <- increment
-  c <- add 2
-  {
-    compare c, col2
-    break-if->=
-    draw-vertical-line r1, row2, c
-    c <- add 2
-    loop
-  }
-}
-
-fn draw-horizontal-line row: int, col1: int, col2: int {
-  var col/eax: int <- copy col1
-  move-cursor 0, row, col
-  {
-    compare col, col2
-    break-if->=
-    print-string 0, "-"
-    col <- increment
-    loop
-  }
-}
-
-fn draw-vertical-line row1: int, row2: int, col: int {
-  var row/eax: int <- copy row1
-  {
-    compare row, row2
-    break-if->=
-    move-cursor 0, row, col
-    print-string 0, "|"
-    row <- increment
-    loop
-  }
-}
diff --git a/prototypes/tile/11.mu b/prototypes/tile/11.mu
deleted file mode 100644
index 82de9fda..00000000
--- a/prototypes/tile/11.mu
+++ /dev/null
@@ -1,353 +0,0 @@
-# Moving around within a tree and creating children.
-#
-# To run (on Linux and x86):
-#   $ git clone https://github.com/akkartik/mu
-#   $ cd mu
-#   $ ./translate_mu prototypes/tile/10.mu
-#   $ ./a.elf
-#
-# Press 'c' to create new children for the root node, and keys to move:
-#   'h': parent
-#   'l': first child
-#   'j': next sibling
-#   'k': prev sibling
-
-# To run unit tests:
-#   $ ./a.elf test
-fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int {
-  var args/eax: (addr array addr array byte) <- copy args-on-stack
-  var tmp/ecx: int <- length args
-  $main-body: {
-    # if (len(args) > 1 && args[1] == "test") run-tests()
-    compare tmp, 1
-    {
-      break-if-<=
-      # if (args[1] == "test") run-tests()
-      var tmp2/ecx: (addr addr array byte) <- index args, 1
-      var tmp3/eax: boolean <- string-equal? *tmp2, "test"
-      compare tmp3, 0
-      {
-        break-if-=
-        run-tests
-        exit-status <- copy 0  # TODO: get at Num-test-failures somehow
-      }
-      break $main-body
-    }
-    # otherwise operate interactively
-    exit-status <- interactive
-  }
-}
-
-# - interactive loop
-
-type cell {
-  val: int  # single chars only for now
-  parent: (handle cell)
-  first-child: (handle cell)
-  next-sibling: (handle cell)
-  prev-sibling: (handle cell)
-}
-
-fn interactive -> exit-status/ebx: int {
-  var root-handle: (handle cell)
-  var root/esi: (addr handle cell) <- address root-handle
-  allocate root
-  var cursor-handle: (handle cell)
-  var cursor/edi: (addr handle cell) <- address cursor-handle
-  copy-handle root-handle, cursor
-  enable-keyboard-immediate-mode
-  var _root-addr/eax: (addr cell) <- lookup *root
-  var root-addr/ecx: (addr cell) <- copy _root-addr
-  var cursor-addr/eax: (addr cell) <- lookup *cursor
-  render root-addr, cursor-addr
-$main:loop: {
-    # process key
-    {
-      var c/eax: grapheme <- read-key-from-real-keyboard
-      compare c, 4  # ctrl-d
-      break-if-= $main:loop
-      process c, root, cursor
-    }
-    # render tree
-    var _root-addr/eax: (addr cell) <- lookup root-handle
-    var root-addr/ecx: (addr cell) <- copy _root-addr
-    var cursor-addr/eax: (addr cell) <- lookup *cursor
-    render root-addr, cursor-addr
-    loop
-  }
-  clear-screen 0
-  enable-keyboard-type-mode
-  exit-status <- copy 0
-}
-
-#######################################################
-# Tree mutations
-#######################################################
-
-fn process c: grapheme, root: (addr handle cell), cursor: (addr handle cell) {
-$process:body: {
-  # if c == 'h' move cursor to its parent if possible
-  {
-    compare c, 0x68  # 'h'
-    break-if-!=
-    move-to-parent cursor
-  }
-  # if c == 'l' move cursor to its first child if possible
-  {
-    compare c, 0x6c  # 'l'
-    break-if-!=
-    move-to-child cursor
-  }
-  # if c == 'j' move cursor to its next sibling if possible
-  {
-    compare c, 0x6a  # 'j'
-    break-if-!=
-    move-to-next-sibling cursor
-  }
-  # if c == 'k' move cursor to its prev sibling if possible
-  {
-    compare c, 0x6b  # 'k'
-    break-if-!=
-    move-to-prev-sibling cursor
-  }
-  # if c == 'c' create a new child at the cursor
-  {
-    compare c, 0x63  # 'c'
-    break-if-!=
-    var cursor2/eax: (addr handle cell) <- copy cursor
-    create-child *cursor2
-  }
-}
-}
-
-fn move-to-parent cursor: (addr handle cell) {
-  var cursor2/eax: (addr handle cell) <- copy cursor
-  var cursor3/eax: (addr cell) <- lookup *cursor2
-  var parent/ecx: (addr handle cell) <- get cursor3, parent
-  {
-    var tmp/eax: (addr cell) <- lookup *parent
-    compare tmp, 0
-    break-if-=
-    copy-handle *parent, cursor
-  }
-}
-
-fn move-to-child cursor: (addr handle cell) {
-  var cursor2/eax: (addr handle cell) <- copy cursor
-  var cursor3/eax: (addr cell) <- lookup *cursor2
-  var child/ecx: (addr handle cell) <- get cursor3, first-child
-  {
-    var tmp/eax: (addr cell) <- lookup *child
-    compare tmp, 0
-    break-if-=
-    copy-handle *child, cursor
-  }
-}
-
-fn move-to-next-sibling cursor: (addr handle cell) {
-  var cursor2/eax: (addr handle cell) <- copy cursor
-  var cursor3/eax: (addr cell) <- lookup *cursor2
-  var sib/ecx: (addr handle cell) <- get cursor3, next-sibling
-  {
-    var tmp/eax: (addr cell) <- lookup *sib
-    compare tmp, 0
-    break-if-=
-    copy-handle *sib, cursor
-  }
-}
-
-fn move-to-prev-sibling cursor: (addr handle cell) {
-  var cursor2/eax: (addr handle cell) <- copy cursor
-  var cursor3/eax: (addr cell) <- lookup *cursor2
-  var sib/ecx: (addr handle cell) <- get cursor3, prev-sibling
-  {
-    var tmp/eax: (addr cell) <- lookup *sib
-    compare tmp, 0
-    break-if-=
-    copy-handle *sib, cursor
-  }
-}
-
-fn create-child node: (handle cell) {
-  var n/eax: (addr cell) <- lookup node
-  var child/esi: (addr handle cell) <- get n, first-child
-  var prev/edx: (addr handle cell) <- copy 0
-  {
-    var tmp/eax: (addr cell) <- lookup *child
-    compare tmp, 0
-    break-if-=
-    prev <- copy child
-    child <- get tmp, next-sibling
-    loop
-  }
-  allocate child
-  var child2/eax: (addr cell) <- lookup *child
-  var dest/ecx: (addr handle cell) <- get child2, prev-sibling
-  # child->prev-sibling = prev
-  {
-    compare prev, 0
-    break-if-=
-    copy-handle *prev, dest
-  }
-  # child->parent = node
-  dest <- get child2, parent
-  copy-handle node, dest
-}
-
-#######################################################
-# Tree drawing
-#######################################################
-
-fn render root: (addr cell), cursor: (addr cell) {
-  clear-screen 0
-  var depth/eax: int <- tree-depth root
-  var viewport-width/ecx: int <- copy 0x65  # col2
-  viewport-width <- subtract 5  # col1
-  var column-width/eax: int <- try-divide viewport-width, depth
-  render-tree root, column-width, 5, 5, 0x20, 0x65, cursor
-}
-
-fn render-tree c: (addr cell), column-width: int, row-min: int, col-min: int, row-max: int, col-max: int, cursor: (addr cell) {
-$render-tree:body: {
-  var root-max/ecx: int <- copy col-min
-  root-max <- add column-width
-  draw-box row-min, col-min, row-max, root-max
-  move-cursor 0, row-min, col-min
-  var top-left/eax: code-point <- copy 0x250c
-  print-code-point 0, top-left
-  move-cursor 0, row-min, root-max
-  var top-right/eax: code-point <- copy 0x2510
-  print-code-point 0, top-right
-  move-cursor 0, row-max, col-min
-  var bot-left/eax: code-point <- copy 0x2514
-  print-code-point 0, bot-left
-  move-cursor 0, row-max, root-max
-  var bot-right/eax: code-point <- copy 0x2518
-  print-code-point 0, bot-right
-  var c2/edx: (addr cell) <- copy c
-  {
-    compare c2, cursor
-    break-if-!=
-    draw-hatching row-min, col-min, row-max, root-max
-  }
-  # if single child, render it (slightly shorter than the parent)
-  var nchild/eax: int <- num-children c
-  {
-    compare nchild, 1
-    break-if->
-    var child/edx: (addr handle cell) <- get c2, first-child
-    var child-addr/eax: (addr cell) <- lookup *child
-    {
-      compare child-addr, 0
-      break-if-=
-      increment row-min
-      decrement row-max
-      render-tree child-addr, column-width, row-min, root-max, row-max, col-max, cursor
-    }
-    break $render-tree:body
-  }
-  # otherwise divide vertical space up equally among children
-  var column-height/ebx: int <- copy row-max
-  column-height <- subtract row-min
-  var child-height/eax: int <- try-divide column-height, nchild
-  var child-height2/ebx: int <- copy child-height
-  var curr/edx: (addr handle cell) <- get c2, first-child
-  var curr-addr/eax: (addr cell) <- lookup *curr
-  var rmin/esi: int <- copy row-min
-  var rmax/edi: int <- copy row-min
-  rmax <- add child-height2
-  {
-    compare curr-addr, 0
-    break-if-=
-    render-tree curr-addr, column-width, rmin, root-max, rmax, col-max, cursor
-    curr <- get curr-addr, next-sibling
-    curr-addr <- lookup *curr
-    rmin <- add child-height2
-    rmax <- add child-height2
-    loop
-  }
-}
-}
-
-fn num-children node-on-stack: (addr cell) -> result/eax: int {
-  var tmp-result/edi: int <- copy 0
-  var node/eax: (addr cell) <- copy node-on-stack
-  var child/ecx: (addr handle cell) <- get node, first-child
-  var child-addr/eax: (addr cell) <- lookup *child
-  {
-    compare child-addr, 0
-    break-if-=
-    tmp-result <- increment
-    child <- get child-addr, next-sibling
-    child-addr <- lookup *child
-    loop
-  }
-  result <- copy tmp-result
-}
-
-fn tree-depth node-on-stack: (addr cell) -> result/eax: int {
-  var tmp-result/edi: int <- copy 0
-  var node/eax: (addr cell) <- copy node-on-stack
-  var child/ecx: (addr handle cell) <- get node, first-child
-  var child-addr/eax: (addr cell) <- lookup *child
-  {
-    compare child-addr, 0
-    break-if-=
-    {
-      var tmp/eax: int <- tree-depth child-addr
-      compare tmp, tmp-result
-      break-if-<=
-      tmp-result <- copy tmp
-    }
-    child <- get child-addr, next-sibling
-    child-addr <- lookup *child
-    loop
-  }
-  result <- copy tmp-result
-  result <- increment
-}
-
-fn draw-box row1: int, col1: int, row2: int, col2: int {
-  draw-horizontal-line row1, col1, col2
-  draw-vertical-line row1, row2, col1
-  draw-horizontal-line row2, col1, col2
-  draw-vertical-line row1, row2, col2
-}
-
-fn draw-hatching row1: int, col1: int, row2: int, col2: int {
-  var c/eax: int <- copy col1
-  var r1/ecx: int <- copy row1
-  r1 <- increment
-  c <- add 2
-  {
-    compare c, col2
-    break-if->=
-    draw-vertical-line r1, row2, c
-    c <- add 2
-    loop
-  }
-}
-
-fn draw-horizontal-line row: int, col1: int, col2: int {
-  var col/eax: int <- copy col1
-  move-cursor 0, row, col
-  {
-    compare col, col2
-    break-if->=
-    print-code-point 0, 0x2500
-    col <- increment
-    loop
-  }
-}
-
-fn draw-vertical-line row1: int, row2: int, col: int {
-  var row/eax: int <- copy row1
-  {
-    compare row, row2
-    break-if->=
-    move-cursor 0, row, col
-    print-code-point 0, 0x2502
-    row <- increment
-    loop
-  }
-}
diff --git a/prototypes/tile/2.mu b/prototypes/tile/2.mu
deleted file mode 100644
index 6339d61e..00000000
--- a/prototypes/tile/2.mu
+++ /dev/null
@@ -1,84 +0,0 @@
-# load test: animate a whole lot of text
-#
-# Requires a large file called "x" containing just ascii characters. One way
-# to generate it:
-#   cat /dev/urandom |base64 - |head -n 1000 > x
-# then merge pairs of lines.
-#
-# This prototype assumes it's in a window 185 characters wide.
-
-fn main -> exit-status/ebx: int {
-  var num-lines/ecx: int <- copy 0x10
-  clear-screen 0
-  # open a file
-  var f: (addr buffered-file)
-  {
-    var f-handle: (handle buffered-file)
-    var f-in/eax: (addr handle buffered-file) <- address f-handle
-    open "x", 0, f-in  # for reading
-    var f-out/eax: (addr buffered-file) <- lookup f-handle
-    copy-to f, f-out
-  }
-  # main loop
-  var row/eax: int <- copy 1
-  {
-    compare row, 0x10  # 16
-    break-if->
-    render f, row, num-lines
-    row <- increment
-#?     sleep 0 0x5f5e100  # 100ms
-    loop
-  }
-  # wait for a key
-  {
-    enable-keyboard-immediate-mode
-      var dummy/eax: grapheme <- read-key-from-real-keyboard
-    enable-keyboard-type-mode
-  }
-  # clean up
-  clear-screen 0
-  exit-status <- copy 0
-}
-
-fn render f: (addr buffered-file), start-row: int, num-rows: int {
-  var num-cols/ecx: int <- copy 0xb9  # 185
-  # if necessary, clear the row above
-$render:clear-loop: {
-    compare start-row, 1
-    break-if-<=
-    decrement start-row
-    var col/eax: int <- copy 1
-    move-cursor 0, start-row, col
-    {
-      compare col, num-cols
-      break-if->
-      print-string 0, " "
-      col <- increment
-      loop
-    }
-    increment start-row
-  }
-  # render rest of screen below
-  var row/edx: int <- copy start-row
-  var col/ebx: int <- copy 1
-  move-cursor 0, row, col
-$render:render-loop: {
-    compare row, num-rows
-    break-if->=
-    var c/eax: byte <- read-byte-buffered f
-    compare c, 0xffffffff  # EOF marker
-    break-if-=
-    compare c, 0xa  # newline
-    {
-      break-if-!=
-      row <- increment
-      col <- copy 0
-      move-cursor 0, row, col
-      loop $render:render-loop
-    }
-    var g/eax: grapheme <- copy c
-    print-grapheme 0, g
-    col <- increment
-    loop
-  }
-}
diff --git a/prototypes/tile/3.mu b/prototypes/tile/3.mu
deleted file mode 100644
index 94c9cc8c..00000000
--- a/prototypes/tile/3.mu
+++ /dev/null
@@ -1,76 +0,0 @@
-# benchmark: how fast can we print characters to screen?
-#
-# Requires a large file called "x" containing just ascii characters. One way
-# to generate it:
-#   cat /dev/urandom |base64 - |head -n 10000 > x
-# then merge pairs of lines.
-
-fn main -> exit-status/ebx: int {
-  var num-lines/ecx: int <- copy 0x64  # 100
-  clear-screen 0
-  # open a file
-  var f: (addr buffered-file)
-  {
-    var f-handle: (handle buffered-file)
-    var f-in/eax: (addr handle buffered-file) <- address f-handle
-    open "x", 0, f-in  # for reading
-    var f-out/eax: (addr buffered-file) <- lookup f-handle
-    copy-to f, f-out
-  }
-  # initial time
-  var t1_/eax: int <- time
-  var t1/edx: int <- copy t1_
-  # main loop
-  var iter/eax: int <- copy 1
-  {
-    compare iter, 0x640  # 1600
-    break-if->
-    render f, num-lines
-    iter <- increment
-    loop
-  }
-  # final time
-  var t2_/eax: int <- time
-  var t2/ebx: int <- copy t2_
-  # time taken
-  var t3/esi: int <- copy t2
-  t3 <- subtract t1
-  # clean up
-  clear-screen 0
-  # results
-  print-int32-hex 0, t1
-  print-string 0, "\n"
-  print-int32-hex 0, t2
-  print-string 0, "\n"
-  print-int32-hex 0, t3
-  print-string 0, "\n"
-  #
-  exit-status <- copy 0
-}
-
-fn render f: (addr buffered-file), num-rows: int {
-  var num-cols/ecx: int <- copy 0x64  # 100
-  # render screen
-  var row/edx: int <- copy 1
-  var col/ebx: int <- copy 1
-  move-cursor 0, row, col
-$render:render-loop: {
-    compare row, num-rows
-    break-if->=
-    var c/eax: byte <- read-byte-buffered f
-    compare c, 0xffffffff  # EOF marker
-    break-if-=
-    compare c, 0xa  # newline
-    {
-      break-if-!=
-      row <- increment
-      col <- copy 0
-      move-cursor 0, row, col
-      loop $render:render-loop
-    }
-    var g/eax: grapheme <- copy c
-    print-grapheme 0, g
-    col <- increment
-    loop
-  }
-}
diff --git a/prototypes/tile/4.mu b/prototypes/tile/4.mu
deleted file mode 100644
index 6e2a57b7..00000000
--- a/prototypes/tile/4.mu
+++ /dev/null
@@ -1,56 +0,0 @@
-# animate a large box
-#
-# To run (on Linux and x86):
-#   $ git clone https://github.com/akkartik/mu
-#   $ cd mu
-#   $ ./translate_mu prototypes/tile/4.mu
-#   $ ./a.elf
-
-fn main -> exit-status/ebx: int {
-  clear-screen 0
-  enable-keyboard-immediate-mode
-  var dummy/eax: grapheme <- read-key-from-real-keyboard
-  draw-box 5, 5, 0x23, 0x23  # 35, 35
-  sleep 0 0x5f5e100  # 100ms
-  sleep 0 0x5f5e100  # 100ms
-  draw-box 5, 5, 0x23, 0x69  # 35, 105
-  sleep 0 0x5f5e100  # 100ms
-  sleep 0 0x5f5e100  # 100ms
-  draw-box 5, 5, 0x23, 0xaf  # 35, 175
-  var dummy/eax: grapheme <- read-key-from-real-keyboard
-  enable-keyboard-type-mode
-  clear-screen 0
-  exit-status <- copy 0
-}
-
-fn draw-box row1: int, col1: int, row2: int, col2: int {
-  clear-screen 0
-  draw-horizontal-line row1, col1, col2
-  draw-vertical-line row1, row2, col1
-  draw-horizontal-line row2, col1, col2
-  draw-vertical-line row1, row2, col2
-}
-
-fn draw-horizontal-line row: int, col1: int, col2: int {
-  var col/eax: int <- copy col1
-  move-cursor 0, row, col
-  {
-    compare col, col2
-    break-if->=
-    print-string 0, "-"
-    col <- increment
-    loop
-  }
-}
-
-fn draw-vertical-line row1: int, row2: int, col: int {
-  var row/eax: int <- copy row1
-  {
-    compare row, row2
-    break-if->=
-    move-cursor 0, row, col
-    print-string 0, "|"
-    row <- increment
-    loop
-  }
-}
diff --git a/prototypes/tile/5.mu b/prototypes/tile/5.mu
deleted file mode 100644
index 58d94636..00000000
--- a/prototypes/tile/5.mu
+++ /dev/null
@@ -1,145 +0,0 @@
-# rendering a tree with a single child
-#
-# To run (on Linux and x86):
-#   $ git clone https://github.com/akkartik/mu
-#   $ cd mu
-#   $ ./translate_mu prototypes/tile/5.mu
-#   $ ./a.elf
-#
-# You should see a single rectangle representing a singleton tree node.
-# Press a key. You should see the tree grow a single child.
-# It seems useful as a visual idiom to represent nodes with a single child as
-# slightly larger than the child.
-# Once we get to multiple children we'll start tiling more regularly.
-
-type cell {
-  val: int  # single chars only for now
-  parent: (handle cell)
-  first-child: (handle cell)
-  next-sibling: (handle cell)
-  prev-sibling: (handle cell)
-}
-
-fn main -> exit-status/ebx: int {
-  var root-handle: (handle cell)
-  var root/esi: (addr handle cell) <- address root-handle
-  allocate root
-  var cursor/edi: (addr handle cell) <- copy root
-  enable-keyboard-immediate-mode
-  var root-addr/eax: (addr cell) <- lookup *root
-  render root-addr
-$main:loop: {
-    # process key
-    {
-      var c/eax: grapheme <- read-key-from-real-keyboard
-      compare c, 4  # ctrl-d
-      break-if-= $main:loop
-      process c, root, cursor
-    }
-    # render tree
-    root-addr <- lookup root-handle
-    render root-addr
-    loop
-  }
-  clear-screen 0
-  enable-keyboard-type-mode
-  exit-status <- copy 0
-}
-
-#######################################################
-# Tree mutations
-#######################################################
-
-fn process c: grapheme, root: (addr handle cell), cursor: (addr handle cell) {
-  var c1/eax: (addr handle cell) <- copy cursor
-  var c2/eax: (addr cell) <- lookup *c1
-  create-child c2
-}
-
-fn create-child node: (addr cell) {
-  var n/ecx: (addr cell) <- copy node
-  var first-child/esi: (addr handle cell) <- get n, first-child
-  allocate first-child
-}
-
-#######################################################
-# Tree drawing
-#######################################################
-
-fn render root: (addr cell) {
-  clear-screen 0
-  var depth/eax: int <- tree-depth root
-  var viewport-width/ecx: int <- copy 0x64  # col2
-  viewport-width <- subtract 5  # col1
-  var column-width/eax: int <- try-divide viewport-width, depth
-  render-tree root, column-width, 5, 5, 0x20, 0x64
-}
-
-fn render-tree c: (addr cell), column-width: int, row-min: int, col-min: int, row-max: int, col-max: int {
-  var root-max/ecx: int <- copy col-min
-  root-max <- add column-width
-  draw-box row-min, col-min, row-max, root-max
-  var c2/eax: (addr cell) <- copy c
-  var child/eax: (addr handle cell) <- get c2, first-child
-  var child-addr/eax: (addr cell) <- lookup *child
-  {
-    compare child-addr, 0
-    break-if-=
-    increment row-min
-    decrement row-max
-    render-tree child-addr, column-width, row-min, root-max, row-max, col-max
-  }
-}
-
-fn tree-depth node-on-stack: (addr cell) -> result/eax: int {
-  var tmp-result/edi: int <- copy 0
-  var node/eax: (addr cell) <- copy node-on-stack
-  var child/ecx: (addr handle cell) <- get node, first-child
-  var child-addr/eax: (addr cell) <- lookup *child
-  {
-    compare child-addr, 0
-    break-if-=
-    {
-      var tmp/eax: int <- tree-depth child-addr
-      compare tmp, tmp-result
-      break-if-<=
-      tmp-result <- copy tmp
-    }
-    child <- get child-addr, next-sibling
-    child-addr <- lookup *child
-    loop
-  }
-  result <- copy tmp-result
-  result <- increment
-}
-
-fn draw-box row1: int, col1: int, row2: int, col2: int {
-  draw-horizontal-line row1, col1, col2
-  draw-vertical-line row1, row2, col1
-  draw-horizontal-line row2, col1, col2
-  draw-vertical-line row1, row2, col2
-}
-
-fn draw-horizontal-line row: int, col1: int, col2: int {
-  var col/eax: int <- copy col1
-  move-cursor 0, row, col
-  {
-    compare col, col2
-    break-if->=
-    print-string 0, "-"
-    col <- increment
-    loop
-  }
-}
-
-fn draw-vertical-line row1: int, row2: int, col: int {
-  var row/eax: int <- copy row1
-  {
-    compare row, row2
-    break-if->=
-    move-cursor 0, row, col
-    print-string 0, "|"
-    row <- increment
-    loop
-  }
-}
diff --git a/prototypes/tile/6.mu b/prototypes/tile/6.mu
deleted file mode 100644
index be95dead..00000000
--- a/prototypes/tile/6.mu
+++ /dev/null
@@ -1,184 +0,0 @@
-# rendering trees of arbitrary depth, with each node having a single child
-#
-# To run (on Linux and x86):
-#   $ git clone https://github.com/akkartik/mu
-#   $ cd mu
-#   $ ./translate_mu prototypes/tile/6.mu
-#   $ ./a.elf
-#
-# Every time you press a key, a deeper tree is rendered. Press ctrl-c to exit.
-# It seems useful as a visual idiom to represent nodes with a single child as
-# slightly larger than the child.
-# Once we get to multiple children we'll start tiling more regularly.
-
-# We also have tests now:
-#   $ ./a.elf test
-fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int {
-  var args/eax: (addr array addr array byte) <- copy args-on-stack
-  var tmp/ecx: int <- length args
-  $main-body: {
-    # if (len(args) > 1 && args[1] == "test") run-tests()
-    compare tmp, 1
-    {
-      break-if-<=
-      # if (args[1] == "test") run-tests()
-      var tmp2/ecx: (addr addr array byte) <- index args, 1
-      var tmp3/eax: boolean <- string-equal? *tmp2, "test"
-      compare tmp3, 0
-      {
-        break-if-=
-        run-tests
-        exit-status <- copy 0  # TODO: get at Num-test-failures somehow
-      }
-      break $main-body
-    }
-    # otherwise operate interactively
-    exit-status <- interactive
-  }
-}
-
-# - interactive loop
-
-type cell {
-  val: int  # single chars only for now
-  parent: (handle cell)
-  first-child: (handle cell)
-  next-sibling: (handle cell)
-  prev-sibling: (handle cell)
-}
-
-fn interactive -> exit-status/ebx: int {
-  var root-handle: (handle cell)
-  var root/esi: (addr handle cell) <- address root-handle
-  allocate root
-  var cursor/edi: (addr handle cell) <- copy root
-  enable-keyboard-immediate-mode
-  var root-addr/eax: (addr cell) <- lookup *root
-  render root-addr
-$main:loop: {
-    # process key
-    {
-      var c/eax: grapheme <- read-key-from-real-keyboard
-      compare c, 4  # ctrl-d
-      break-if-= $main:loop
-      process c, root, cursor
-    }
-    # render tree
-    root-addr <- lookup root-handle
-    render root-addr
-    loop
-  }
-  clear-screen 0
-  enable-keyboard-type-mode
-  exit-status <- copy 0
-}
-
-#######################################################
-# Tree mutations
-#######################################################
-
-fn process c: grapheme, root: (addr handle cell), cursor: (addr handle cell) {
-  # increase depth by 1
-  var c1/ecx: (addr handle cell) <- copy cursor
-  var c2/eax: (addr cell) <- lookup *c1
-  var c3/edx: (addr cell) <- copy c2
-  {
-    print-string 0, "iter\n"
-    var tmp/ebx: (addr handle cell) <- get c3, first-child
-    var tmp2/eax: (addr cell) <- lookup *tmp
-    compare tmp2, 0
-    break-if-=
-    c1 <- copy tmp
-    c3 <- copy tmp2
-    loop
-  }
-  create-child c3
-}
-
-fn create-child node: (addr cell) {
-  var n/ecx: (addr cell) <- copy node
-  var first-child/esi: (addr handle cell) <- get n, first-child
-  allocate first-child
-}
-
-#######################################################
-# Tree drawing
-#######################################################
-
-fn render root: (addr cell) {
-  clear-screen 0
-  var depth/eax: int <- tree-depth root
-  var viewport-width/ecx: int <- copy 0x64  # col2
-  viewport-width <- subtract 5  # col1
-  var column-width/eax: int <- try-divide viewport-width, depth
-  render-tree root, column-width, 5, 5, 0x20, 0x64
-}
-
-fn render-tree c: (addr cell), column-width: int, row-min: int, col-min: int, row-max: int, col-max: int {
-  var root-max/ecx: int <- copy col-min
-  root-max <- add column-width
-  draw-box row-min, col-min, row-max, root-max
-  var c2/eax: (addr cell) <- copy c
-  var child/eax: (addr handle cell) <- get c2, first-child
-  var child-addr/eax: (addr cell) <- lookup *child
-  {
-    compare child-addr, 0
-    break-if-=
-    increment row-min
-    decrement row-max
-    render-tree child-addr, column-width, row-min, root-max, row-max, col-max
-  }
-}
-
-fn tree-depth node-on-stack: (addr cell) -> result/eax: int {
-  var tmp-result/edi: int <- copy 0
-  var node/eax: (addr cell) <- copy node-on-stack
-  var child/ecx: (addr handle cell) <- get node, first-child
-  var child-addr/eax: (addr cell) <- lookup *child
-  {
-    compare child-addr, 0
-    break-if-=
-    {
-      var tmp/eax: int <- tree-depth child-addr
-      compare tmp, tmp-result
-      break-if-<=
-      tmp-result <- copy tmp
-    }
-    child <- get child-addr, next-sibling
-    child-addr <- lookup *child
-    loop
-  }
-  result <- copy tmp-result
-  result <- increment
-}
-
-fn draw-box row1: int, col1: int, row2: int, col2: int {
-  draw-horizontal-line row1, col1, col2
-  draw-vertical-line row1, row2, col1
-  draw-horizontal-line row2, col1, col2
-  draw-vertical-line row1, row2, col2
-}
-
-fn draw-horizontal-line row: int, col1: int, col2: int {
-  var col/eax: int <- copy col1
-  move-cursor 0, row, col
-  {
-    compare col, col2
-    break-if->=
-    print-string 0, "-"
-    col <- increment
-    loop
-  }
-}
-
-fn draw-vertical-line row1: int, row2: int, col: int {
-  var row/eax: int <- copy row1
-  {
-    compare row, row2
-    break-if->=
-    move-cursor 0, row, col
-    print-string 0, "|"
-    row <- increment
-    loop
-  }
-}
diff --git a/prototypes/tile/7.mu b/prototypes/tile/7.mu
deleted file mode 100644
index e2e7aff0..00000000
--- a/prototypes/tile/7.mu
+++ /dev/null
@@ -1,198 +0,0 @@
-# rendering trees of arbitrary depth
-#
-# To run (on Linux and x86):
-#   $ git clone https://github.com/akkartik/mu
-#   $ cd mu
-#   $ ./translate_mu prototypes/tile/7.mu
-#   $ ./a.elf
-#
-# Every time you press a key, the root node gains another child. Press ctrl-c
-# to exit.
-#
-# The rendering is still simple-minded. Children and siblings render in the
-# same direction. And this interacts poorly with the depth computation, which
-# only considers children. So unlike the previous prototype which splits the
-# same screen width between more and more boxes, here the boxes grow to the
-# right.
-
-# To run unit tests:
-#   $ ./a.elf test
-fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int {
-  var args/eax: (addr array addr array byte) <- copy args-on-stack
-  var tmp/ecx: int <- length args
-  $main-body: {
-    # if (len(args) > 1 && args[1] == "test") run-tests()
-    compare tmp, 1
-    {
-      break-if-<=
-      # if (args[1] == "test") run-tests()
-      var tmp2/ecx: (addr addr array byte) <- index args, 1
-      var tmp3/eax: boolean <- string-equal? *tmp2, "test"
-      compare tmp3, 0
-      {
-        break-if-=
-        run-tests
-        exit-status <- copy 0  # TODO: get at Num-test-failures somehow
-      }
-      break $main-body
-    }
-    # otherwise operate interactively
-    exit-status <- interactive
-  }
-}
-
-# - interactive loop
-
-type cell {
-  val: int  # single chars only for now
-  parent: (handle cell)
-  first-child: (handle cell)
-  next-sibling: (handle cell)
-  prev-sibling: (handle cell)
-}
-
-fn interactive -> exit-status/ebx: int {
-  var root-handle: (handle cell)
-  var root/esi: (addr handle cell) <- address root-handle
-  allocate root
-  var cursor/edi: (addr handle cell) <- copy root
-  enable-keyboard-immediate-mode
-  var root-addr/eax: (addr cell) <- lookup *root
-  render root-addr
-$main:loop: {
-    # process key
-    {
-      var c/eax: grapheme <- read-key-from-real-keyboard
-      compare c, 4  # ctrl-d
-      break-if-= $main:loop
-      process c, root, cursor
-    }
-    # render tree
-    root-addr <- lookup root-handle
-    render root-addr
-    loop
-  }
-  clear-screen 0
-  enable-keyboard-type-mode
-  exit-status <- copy 0
-}
-
-#######################################################
-# Tree mutations
-#######################################################
-
-fn process c: grapheme, root: (addr handle cell), cursor: (addr handle cell) {
-  var c1/ecx: (addr handle cell) <- copy cursor
-  var c2/eax: (addr cell) <- lookup *c1
-  create-child c2
-}
-
-fn create-child node: (addr cell) {
-  var n/ecx: (addr cell) <- copy node
-  var child/esi: (addr handle cell) <- get n, first-child
-  {
-    var tmp/eax: (addr cell) <- lookup *child
-    compare tmp, 0
-    break-if-=
-    child <- get tmp, next-sibling
-    loop
-  }
-  allocate child
-}
-
-#######################################################
-# Tree drawing
-#######################################################
-
-fn render root: (addr cell) {
-  clear-screen 0
-  var depth/eax: int <- tree-depth root
-  var viewport-width/ecx: int <- copy 0x64  # col2
-  viewport-width <- subtract 5  # col1
-  var column-width/eax: int <- try-divide viewport-width, depth
-  render-tree root, column-width, 5, 5, 0x20, 0x64
-}
-
-fn render-tree c: (addr cell), column-width: int, row-min: int, col-min: int, row-max: int, col-max: int {
-  var root-max/ecx: int <- copy col-min
-  root-max <- add column-width
-  draw-box row-min, col-min, row-max, root-max
-  var c2/eax: (addr cell) <- copy c
-  # render child if possible
-  {
-    var child/edx: (addr handle cell) <- get c2, first-child
-    var child-addr/eax: (addr cell) <- lookup *child
-    {
-      compare child-addr, 0
-      break-if-=
-      increment row-min
-      decrement row-max
-      render-tree child-addr, column-width, row-min, root-max, row-max, col-max
-    }
-  }
-  # otherwise render sibling if possible (in the same column)
-  {
-    var sib/edx: (addr handle cell) <- get c2, next-sibling
-    var sib-addr/eax: (addr cell) <- lookup *sib
-    {
-      compare sib-addr, 0
-      break-if-=
-      increment row-min
-      decrement row-max
-      render-tree sib-addr, column-width, row-min, root-max, row-max, col-max
-    }
-  }
-}
-
-fn tree-depth node-on-stack: (addr cell) -> result/eax: int {
-  var tmp-result/edi: int <- copy 0
-  var node/eax: (addr cell) <- copy node-on-stack
-  var child/ecx: (addr handle cell) <- get node, first-child
-  var child-addr/eax: (addr cell) <- lookup *child
-  {
-    compare child-addr, 0
-    break-if-=
-    {
-      var tmp/eax: int <- tree-depth child-addr
-      compare tmp, tmp-result
-      break-if-<=
-      tmp-result <- copy tmp
-    }
-    child <- get child-addr, next-sibling
-    child-addr <- lookup *child
-    loop
-  }
-  result <- copy tmp-result
-  result <- increment
-}
-
-fn draw-box row1: int, col1: int, row2: int, col2: int {
-  draw-horizontal-line row1, col1, col2
-  draw-vertical-line row1, row2, col1
-  draw-horizontal-line row2, col1, col2
-  draw-vertical-line row1, row2, col2
-}
-
-fn draw-horizontal-line row: int, col1: int, col2: int {
-  var col/eax: int <- copy col1
-  move-cursor 0, row, col
-  {
-    compare col, col2
-    break-if->=
-    print-string 0, "-"
-    col <- increment
-    loop
-  }
-}
-
-fn draw-vertical-line row1: int, row2: int, col: int {
-  var row/eax: int <- copy row1
-  {
-    compare row, row2
-    break-if->=
-    move-cursor 0, row, col
-    print-string 0, "|"
-    row <- increment
-    loop
-  }
-}
diff --git a/prototypes/tile/8.mu b/prototypes/tile/8.mu
deleted file mode 100644
index 526df803..00000000
--- a/prototypes/tile/8.mu
+++ /dev/null
@@ -1,228 +0,0 @@
-# rendering trees of arbitrary depth
-#
-# To run (on Linux and x86):
-#   $ git clone https://github.com/akkartik/mu
-#   $ cd mu
-#   $ ./translate_mu prototypes/tile/8.mu
-#   $ ./a.elf
-#
-# Every time you press a key, the root node gains another child. Press ctrl-c
-# to exit.
-#
-# The rendering is still simple-minded. Children and siblings render in the
-# same direction. And this interacts poorly with the depth computation, which
-# only considers children. So unlike the previous prototype which splits the
-# same screen width between more and more boxes, here the boxes grow to the
-# right.
-
-# To run unit tests:
-#   $ ./a.elf test
-fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int {
-  var args/eax: (addr array addr array byte) <- copy args-on-stack
-  var tmp/ecx: int <- length args
-  $main-body: {
-    # if (len(args) > 1 && args[1] == "test") run-tests()
-    compare tmp, 1
-    {
-      break-if-<=
-      # if (args[1] == "test") run-tests()
-      var tmp2/ecx: (addr addr array byte) <- index args, 1
-      var tmp3/eax: boolean <- string-equal? *tmp2, "test"
-      compare tmp3, 0
-      {
-        break-if-=
-        run-tests
-        exit-status <- copy 0  # TODO: get at Num-test-failures somehow
-      }
-      break $main-body
-    }
-    # otherwise operate interactively
-    exit-status <- interactive
-  }
-}
-
-# - interactive loop
-
-type cell {
-  val: int  # single chars only for now
-  parent: (handle cell)
-  first-child: (handle cell)
-  next-sibling: (handle cell)
-  prev-sibling: (handle cell)
-}
-
-fn interactive -> exit-status/ebx: int {
-  var root-handle: (handle cell)
-  var root/esi: (addr handle cell) <- address root-handle
-  allocate root
-  var cursor/edi: (addr handle cell) <- copy root
-  enable-keyboard-immediate-mode
-  var root-addr/eax: (addr cell) <- lookup *root
-  render root-addr
-$main:loop: {
-    # process key
-    {
-      var c/eax: grapheme <- read-key-from-real-keyboard
-      compare c, 4  # ctrl-d
-      break-if-= $main:loop
-      process c, root, cursor
-    }
-    # render tree
-    root-addr <- lookup root-handle
-    render root-addr
-    loop
-  }
-  clear-screen 0
-  enable-keyboard-type-mode
-  exit-status <- copy 0
-}
-
-#######################################################
-# Tree mutations
-#######################################################
-
-fn process c: grapheme, root: (addr handle cell), cursor: (addr handle cell) {
-  var c1/ecx: (addr handle cell) <- copy cursor
-  var c2/eax: (addr cell) <- lookup *c1
-  create-child c2
-}
-
-fn create-child node: (addr cell) {
-  var n/ecx: (addr cell) <- copy node
-  var child/esi: (addr handle cell) <- get n, first-child
-  {
-    var tmp/eax: (addr cell) <- lookup *child
-    compare tmp, 0
-    break-if-=
-    child <- get tmp, next-sibling
-    loop
-  }
-  allocate child
-}
-
-#######################################################
-# Tree drawing
-#######################################################
-
-fn render root: (addr cell) {
-  clear-screen 0
-  var depth/eax: int <- tree-depth root
-  var viewport-width/ecx: int <- copy 0x64  # col2
-  viewport-width <- subtract 5  # col1
-  var column-width/eax: int <- try-divide viewport-width, depth
-  render-tree root, column-width, 5, 5, 0x20, 0x64
-}
-
-fn render-tree c: (addr cell), column-width: int, row-min: int, col-min: int, row-max: int, col-max: int {
-$render-tree:body: {
-  var root-max/ecx: int <- copy col-min
-  root-max <- add column-width
-  draw-box row-min, col-min, row-max, root-max
-  var c2/edx: (addr cell) <- copy c
-  # if single child, render it (slightly shorter than the parent)
-  var nchild/eax: int <- num-children c
-  {
-    compare nchild, 1
-    break-if->
-    var child/edx: (addr handle cell) <- get c2, first-child
-    var child-addr/eax: (addr cell) <- lookup *child
-    {
-      compare child-addr, 0
-      break-if-=
-      increment row-min
-      decrement row-max
-      render-tree child-addr, column-width, row-min, root-max, row-max, col-max
-    }
-    break $render-tree:body
-  }
-  # otherwise divide vertical space up equally among children
-  var column-height/ebx: int <- copy row-max
-  column-height <- subtract row-min
-  var child-height/eax: int <- try-divide column-height, nchild
-  var child-height2/ebx: int <- copy child-height
-  var curr/edx: (addr handle cell) <- get c2, first-child
-  var curr-addr/eax: (addr cell) <- lookup *curr
-  var rmin/esi: int <- copy row-min
-  var rmax/edi: int <- copy row-min
-  rmax <- add child-height2
-  {
-    compare curr-addr, 0
-    break-if-=
-    render-tree curr-addr, column-width, rmin, root-max, rmax, col-max
-    curr <- get curr-addr, next-sibling
-    curr-addr <- lookup *curr
-    rmin <- add child-height2
-    rmax <- add child-height2
-    loop
-  }
-}
-}
-
-fn num-children node-on-stack: (addr cell) -> result/eax: int {
-  var tmp-result/edi: int <- copy 0
-  var node/eax: (addr cell) <- copy node-on-stack
-  var child/ecx: (addr handle cell) <- get node, first-child
-  var child-addr/eax: (addr cell) <- lookup *child
-  {
-    compare child-addr, 0
-    break-if-=
-    tmp-result <- increment
-    child <- get child-addr, next-sibling
-    child-addr <- lookup *child
-    loop
-  }
-  result <- copy tmp-result
-}
-
-fn tree-depth node-on-stack: (addr cell) -> result/eax: int {
-  var tmp-result/edi: int <- copy 0
-  var node/eax: (addr cell) <- copy node-on-stack
-  var child/ecx: (addr handle cell) <- get node, first-child
-  var child-addr/eax: (addr cell) <- lookup *child
-  {
-    compare child-addr, 0
-    break-if-=
-    {
-      var tmp/eax: int <- tree-depth child-addr
-      compare tmp, tmp-result
-      break-if-<=
-      tmp-result <- copy tmp
-    }
-    child <- get child-addr, next-sibling
-    child-addr <- lookup *child
-    loop
-  }
-  result <- copy tmp-result
-  result <- increment
-}
-
-fn draw-box row1: int, col1: int, row2: int, col2: int {
-  draw-horizontal-line row1, col1, col2
-  draw-vertical-line row1, row2, col1
-  draw-horizontal-line row2, col1, col2
-  draw-vertical-line row1, row2, col2
-}
-
-fn draw-horizontal-line row: int, col1: int, col2: int {
-  var col/eax: int <- copy col1
-  move-cursor 0, row, col
-  {
-    compare col, col2
-    break-if->=
-    print-string 0, "-"
-    col <- increment
-    loop
-  }
-}
-
-fn draw-vertical-line row1: int, row2: int, col: int {
-  var row/eax: int <- copy row1
-  {
-    compare row, row2
-    break-if->=
-    move-cursor 0, row, col
-    print-string 0, "|"
-    row <- increment
-    loop
-  }
-}
diff --git a/prototypes/tile/9.mu b/prototypes/tile/9.mu
deleted file mode 100644
index ab143e25..00000000
--- a/prototypes/tile/9.mu
+++ /dev/null
@@ -1,307 +0,0 @@
-# moving around within a tree, though movement isn't visible yet so we can't
-# be sure it's working.
-#
-# To run (on Linux and x86):
-#   $ git clone https://github.com/akkartik/mu
-#   $ cd mu
-#   $ ./translate_mu prototypes/tile/9.mu
-#   $ ./a.elf
-#
-# Press 'c' to create new children for the root node.
-
-# To run unit tests:
-#   $ ./a.elf test
-fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int {
-  var args/eax: (addr array addr array byte) <- copy args-on-stack
-  var tmp/ecx: int <- length args
-  $main-body: {
-    # if (len(args) > 1 && args[1] == "test") run-tests()
-    compare tmp, 1
-    {
-      break-if-<=
-      # if (args[1] == "test") run-tests()
-      var tmp2/ecx: (addr addr array byte) <- index args, 1
-      var tmp3/eax: boolean <- string-equal? *tmp2, "test"
-      compare tmp3, 0
-      {
-        break-if-=
-        run-tests
-        exit-status <- copy 0  # TODO: get at Num-test-failures somehow
-      }
-      break $main-body
-    }
-    # otherwise operate interactively
-    exit-status <- interactive
-  }
-}
-
-# - interactive loop
-
-type cell {
-  val: int  # single chars only for now
-  parent: (handle cell)
-  first-child: (handle cell)
-  next-sibling: (handle cell)
-  prev-sibling: (handle cell)
-}
-
-fn interactive -> exit-status/ebx: int {
-  var root-handle: (handle cell)
-  var root/esi: (addr handle cell) <- address root-handle
-  allocate root
-  var cursor-handle: (handle cell)
-  var cursor/edi: (addr handle cell) <- address cursor-handle
-  copy-handle root-handle, cursor
-  enable-keyboard-immediate-mode
-  var _root-addr/eax: (addr cell) <- lookup *root
-  var root-addr/ecx: (addr cell) <- copy _root-addr
-  var cursor-addr/eax: (addr cell) <- lookup *cursor
-  render root-addr, cursor-addr
-$main:loop: {
-    # process key
-    {
-      var c/eax: grapheme <- read-key-from-real-keyboard
-      compare c, 4  # ctrl-d
-      break-if-= $main:loop
-      process c, root, cursor
-    }
-    # render tree
-    var _root-addr/eax: (addr cell) <- lookup root-handle
-    root-addr <- copy _root-addr
-    var cursor-addr/eax: (addr cell) <- lookup *cursor
-    render root-addr, cursor-addr
-    loop
-  }
-  clear-screen 0
-  enable-keyboard-type-mode
-  exit-status <- copy 0
-}
-
-#######################################################
-# Tree mutations
-#######################################################
-
-fn process c: grapheme, root: (addr handle cell), cursor: (addr handle cell) {
-$process:body: {
-  # if c == 'h' move cursor to its parent if possible
-  {
-    compare c, 0x68  # 'h'
-    break-if-!=
-    move-to-parent cursor
-  }
-  # if c == 'l' move cursor to its first child if possible
-  {
-    compare c, 0x6c  # 'l'
-    break-if-!=
-    move-to-child cursor
-  }
-  # if c == 'j' move cursor to its next sibling if possible
-  {
-    compare c, 0x6a  # 'j'
-    break-if-!=
-    move-to-next-sibling cursor
-  }
-  # if c == 'k' move cursor to its prev sibling if possible
-  {
-    compare c, 0x6b  # 'k'
-    break-if-!=
-    move-to-prev-sibling cursor
-  }
-  # if c == 'c' create a new child at the cursor
-  {
-    compare c, 0x63  # 'c'
-    break-if-!=
-    var cursor1/ecx: (addr handle cell) <- copy cursor
-    var cursor2/eax: (addr cell) <- lookup *cursor1
-    create-child cursor2
-  }
-}
-}
-
-fn move-to-parent cursor: (addr handle cell) {
-  var cursor2/eax: (addr handle cell) <- copy cursor
-  var cursor3/eax: (addr cell) <- lookup *cursor2
-  var parent/ecx: (addr handle cell) <- get cursor3, parent
-  {
-    var tmp/eax: (addr cell) <- lookup *parent
-    compare tmp, 0
-    break-if-=
-    copy-handle *parent, cursor
-  }
-}
-
-fn move-to-child cursor: (addr handle cell) {
-  var cursor2/eax: (addr handle cell) <- copy cursor
-  var cursor3/eax: (addr cell) <- lookup *cursor2
-  var child/ecx: (addr handle cell) <- get cursor3, first-child
-  {
-    var tmp/eax: (addr cell) <- lookup *child
-    compare tmp, 0
-    break-if-=
-    copy-handle *child, cursor
-  }
-}
-
-fn move-to-next-sibling cursor: (addr handle cell) {
-  var cursor2/eax: (addr handle cell) <- copy cursor
-  var cursor3/eax: (addr cell) <- lookup *cursor2
-  var sib/ecx: (addr handle cell) <- get cursor3, next-sibling
-  {
-    var tmp/eax: (addr cell) <- lookup *sib
-    compare tmp, 0
-    break-if-=
-    copy-handle *sib, cursor
-  }
-}
-
-fn move-to-prev-sibling cursor: (addr handle cell) {
-  var cursor2/eax: (addr handle cell) <- copy cursor
-  var cursor3/eax: (addr cell) <- lookup *cursor2
-  var sib/ecx: (addr handle cell) <- get cursor3, prev-sibling
-  {
-    var tmp/eax: (addr cell) <- lookup *sib
-    compare tmp, 0
-    break-if-=
-    copy-handle *sib, cursor
-  }
-}
-
-fn create-child node: (addr cell) {
-  var n/ecx: (addr cell) <- copy node
-  var child/esi: (addr handle cell) <- get n, first-child
-  {
-    var tmp/eax: (addr cell) <- lookup *child
-    compare tmp, 0
-    break-if-=
-    child <- get tmp, next-sibling
-    loop
-  }
-  allocate child
-}
-
-#######################################################
-# Tree drawing
-#######################################################
-
-fn render root: (addr cell), cursor: (addr cell) {
-  clear-screen 0
-  var depth/eax: int <- tree-depth root
-  var viewport-width/ecx: int <- copy 0x64  # col2
-  viewport-width <- subtract 5  # col1
-  var column-width/eax: int <- try-divide viewport-width, depth
-  render-tree root, column-width, 5, 5, 0x20, 0x64, cursor
-}
-
-fn render-tree c: (addr cell), column-width: int, row-min: int, col-min: int, row-max: int, col-max: int, cursor: (addr cell) {
-$render-tree:body: {
-  var root-max/ecx: int <- copy col-min
-  root-max <- add column-width
-  draw-box row-min, col-min, row-max, root-max
-  var c2/edx: (addr cell) <- copy c
-  # if single child, render it (slightly shorter than the parent)
-  var nchild/eax: int <- num-children c
-  {
-    compare nchild, 1
-    break-if->
-    var child/edx: (addr handle cell) <- get c2, first-child
-    var child-addr/eax: (addr cell) <- lookup *child
-    {
-      compare child-addr, 0
-      break-if-=
-      increment row-min
-      decrement row-max
-      render-tree child-addr, column-width, row-min, root-max, row-max, col-max, cursor
-    }
-    break $render-tree:body
-  }
-  # otherwise divide vertical space up equally among children
-  var column-height/ebx: int <- copy row-max
-  column-height <- subtract row-min
-  var child-height/eax: int <- try-divide column-height, nchild
-  var child-height2/ebx: int <- copy child-height
-  var curr/edx: (addr handle cell) <- get c2, first-child
-  var curr-addr/eax: (addr cell) <- lookup *curr
-  var rmin/esi: int <- copy row-min
-  var rmax/edi: int <- copy row-min
-  rmax <- add child-height2
-  {
-    compare curr-addr, 0
-    break-if-=
-    render-tree curr-addr, column-width, rmin, root-max, rmax, col-max, cursor
-    curr <- get curr-addr, next-sibling
-    curr-addr <- lookup *curr
-    rmin <- add child-height2
-    rmax <- add child-height2
-    loop
-  }
-}
-}
-
-fn num-children node-on-stack: (addr cell) -> result/eax: int {
-  var tmp-result/edi: int <- copy 0
-  var node/eax: (addr cell) <- copy node-on-stack
-  var child/ecx: (addr handle cell) <- get node, first-child
-  var child-addr/eax: (addr cell) <- lookup *child
-  {
-    compare child-addr, 0
-    break-if-=
-    tmp-result <- increment
-    child <- get child-addr, next-sibling
-    child-addr <- lookup *child
-    loop
-  }
-  result <- copy tmp-result
-}
-
-fn tree-depth node-on-stack: (addr cell) -> result/eax: int {
-  var tmp-result/edi: int <- copy 0
-  var node/eax: (addr cell) <- copy node-on-stack
-  var child/ecx: (addr handle cell) <- get node, first-child
-  var child-addr/eax: (addr cell) <- lookup *child
-  {
-    compare child-addr, 0
-    break-if-=
-    {
-      var tmp/eax: int <- tree-depth child-addr
-      compare tmp, tmp-result
-      break-if-<=
-      tmp-result <- copy tmp
-    }
-    child <- get child-addr, next-sibling
-    child-addr <- lookup *child
-    loop
-  }
-  result <- copy tmp-result
-  result <- increment
-}
-
-fn draw-box row1: int, col1: int, row2: int, col2: int {
-  draw-horizontal-line row1, col1, col2
-  draw-vertical-line row1, row2, col1
-  draw-horizontal-line row2, col1, col2
-  draw-vertical-line row1, row2, col2
-}
-
-fn draw-horizontal-line row: int, col1: int, col2: int {
-  var col/eax: int <- copy col1
-  move-cursor 0, row, col
-  {
-    compare col, col2
-    break-if->=
-    print-string 0, "-"
-    col <- increment
-    loop
-  }
-}
-
-fn draw-vertical-line row1: int, row2: int, col: int {
-  var row/eax: int <- copy row1
-  {
-    compare row, row2
-    break-if->=
-    move-cursor 0, row, col
-    print-string 0, "|"
-    row <- increment
-    loop
-  }
-}
diff --git a/prototypes/tile/README.md b/prototypes/tile/README.md
deleted file mode 100644
index 2fbe3b6c..00000000
--- a/prototypes/tile/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# Drawing tiles on screen
-
-This directory contains a series of prototypes. For more details on the
-organization of this directory and building, see [the parent directory](..).
-
-Once you've followed the instructions for building a prototype, run most of
-them like this:
-
-```
-$ ./a.elf
-```
-
-See the code of individual prototypes for further instructions.