about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-11-02 19:50:34 -0800
committerKartik Agaram <vc@akkartik.com>2020-11-02 19:50:52 -0800
commita3f779158626b9ad3c81959b85cbfbbce17425fd (patch)
tree10c9da6ee8783a2ed2a3e6e928fb5d70024d1bcc
parent951c3f4c92358d3962154a4ef24a19366ea8a619 (diff)
downloadmu-a3f779158626b9ad3c81959b85cbfbbce17425fd.tar.gz
7159 - explicitly use 'return' everywhere
https://github.com/akkartik/mu/issues/45#issuecomment-719990879, task 2.
-rw-r--r--408print-float.mu4
-rw-r--r--apps/browse/main.mu52
-rw-r--r--apps/browse/paginated-screen.mu15
-rw-r--r--apps/raytracing/1.mu4
-rw-r--r--apps/raytracing/2.mu4
-rw-r--r--apps/raytracing/3.mu14
-rw-r--r--apps/raytracing/vec.mu10
-rw-r--r--apps/tile/data.mu54
-rw-r--r--apps/tile/environment.mu158
-rw-r--r--apps/tile/gap-buffer.mu111
-rw-r--r--apps/tile/grapheme-stack.mu40
-rw-r--r--apps/tile/int-stack.mu22
-rw-r--r--apps/tile/main.mu37
-rw-r--r--apps/tile/rpn.mu5
-rw-r--r--apps/tile/surface.mu105
-rw-r--r--apps/tile/table.mu4
-rw-r--r--apps/tile/value-stack.mu147
-rw-r--r--apps/tile/word.mu76
18 files changed, 407 insertions, 455 deletions
diff --git a/408print-float.mu b/408print-float.mu
index 67e46f03..d98880ac 100644
--- a/408print-float.mu
+++ b/408print-float.mu
@@ -162,10 +162,10 @@ $print-float:body: {
 }
 }
 
-#? fn main -> r/ebx: int {
+#? fn main -> _/ebx: int {
 #?   run-tests
 #? #?   test-print-float-negative-zero
 #? #?   print-int32-hex 0, 0
 #? #?   test-print-float-normal
-#?   r <- copy 0
+#?   return 0
 #? }
diff --git a/apps/browse/main.mu b/apps/browse/main.mu
index 3a397ee0..d2510071 100644
--- a/apps/browse/main.mu
+++ b/apps/browse/main.mu
@@ -1,33 +1,29 @@
-fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int {
+fn main args-on-stack: (addr array addr array byte) -> _/ebx: int {
   var args/eax: (addr array addr array byte) <- copy args-on-stack
   var len/ecx: int <- length args
-  $main-body: {
-    # if (len(args) <= 1) print usage and exit
-    compare len, 1
-    {
-      break-if->
-      print-string-to-real-screen "usage: browse [filename]\n"
-      print-string-to-real-screen "    or browse test\n"
-      exit-status <- copy 1
-      break $main-body
-    }
-    # if (args[1] == "test") run-tests()
-    var tmp/ecx: (addr addr array byte) <- index args, 1
-    var tmp2/eax: boolean <- string-equal? *tmp, "test"
-    compare tmp2, 0
-    {
-      break-if-=
-      run-tests
-      exit-status <- copy 0  # TODO: get at Num-test-failures somehow
-      break $main-body
-    }
-    # otherwise interactive mode
-    exit-status <- interactive args-on-stack
+  # if (len(args) <= 1) print usage and exit
+  compare len, 1
+  {
+    break-if->
+    print-string-to-real-screen "usage: browse [filename]\n"
+    print-string-to-real-screen "    or browse test\n"
+    return 1
   }
+  # if (args[1] == "test") run-tests()
+  var tmp/ecx: (addr addr array byte) <- index args, 1
+  var tmp2/eax: boolean <- string-equal? *tmp, "test"
+  compare tmp2, 0
+  {
+    break-if-=
+    run-tests
+    return 0  # TODO: get at Num-test-failures somehow
+  }
+  # otherwise interactive mode
+  var result/ebx: int <- interactive args-on-stack
+  return result
 }
 
-fn interactive _args: (addr array addr array byte) -> exit-status/ebx: int {
-$interactive:body: {
+fn interactive _args: (addr array addr array byte) -> _/ebx: int {
   # initialize fs from args[1]
   var args/eax: (addr array addr array byte) <- copy _args
   var arg/eax: (addr addr array byte) <- index args, 1
@@ -42,8 +38,7 @@ $interactive:body: {
     compare fs, 0
     break-if-!=
     print-string-to-real-screen "file not found\n"
-    exit-status <- copy 1
-    break $interactive:body
+    return 1
   }
   #
   enable-screen-grid-mode
@@ -62,8 +57,7 @@ $interactive:body: {
   }
   enable-keyboard-type-mode
   enable-screen-type-mode
-  exit-status <- copy 0
-}
+  return 0
 }
 
 fn render screen: (addr paginated-screen), fs: (addr buffered-file) {
diff --git a/apps/browse/paginated-screen.mu b/apps/browse/paginated-screen.mu
index 9d02dcce..783a1cac 100644
--- a/apps/browse/paginated-screen.mu
+++ b/apps/browse/paginated-screen.mu
@@ -122,8 +122,7 @@ fn start-drawing _self: (addr paginated-screen) {
   reposition-cursor self
 }
 
-fn done-drawing? _self: (addr paginated-screen) -> result/eax: boolean {
-$done-drawing?:body: {
+fn done-drawing? _self: (addr paginated-screen) -> _/eax: boolean {
   # if (self->leftcol == left-margin + 1) return false
   var self/esi: (addr paginated-screen) <- copy _self
   var tmp/eax: (addr int) <- get self, left-margin
@@ -133,8 +132,7 @@ $done-drawing?:body: {
   $done-drawing:first-page?: {
     compare first-col, *tmp
     break-if-!=
-    result <- copy 0
-    break $done-drawing?:body
+    return 0  # false
   }
   # return self->rightcol > self->ncols + 1
   tmp <- get self, ncols
@@ -149,14 +147,9 @@ $done-drawing?:body: {
   compare *tmp, max
   {
     break-if->
-    result <- copy 0  # false
-    break $done-drawing?:body
+    return 0  # false
   }
-  {
-    break-if-<=
-    result <- copy 1  # true
-  }
-}
+  return 1  # true
 }
 
 fn add-grapheme _self: (addr paginated-screen), c: grapheme {
diff --git a/apps/raytracing/1.mu b/apps/raytracing/1.mu
index 539332ea..fbc76f1d 100644
--- a/apps/raytracing/1.mu
+++ b/apps/raytracing/1.mu
@@ -7,7 +7,7 @@
 #   $ ./translate_mu apps/raytracing/1.mu
 #   $ ./a.elf > 1.ppm
 
-fn main -> exit-status/ebx: int {
+fn main -> _/ebx: int {
   print-string 0, "P3\n256 256\n255\n"
   var j/ecx: int <- copy 0xff
   {
@@ -27,5 +27,5 @@ fn main -> exit-status/ebx: int {
     j <- decrement
     loop
   }
-  exit-status <- copy 1
+  return 0
 }
diff --git a/apps/raytracing/2.mu b/apps/raytracing/2.mu
index 69bc9a40..e23ce3b4 100644
--- a/apps/raytracing/2.mu
+++ b/apps/raytracing/2.mu
@@ -6,7 +6,7 @@
 #   $ ./translate_mu apps/raytracing/2.mu
 #   $ ./a.elf > 2.ppm
 
-fn main -> exit-status/ebx: int {
+fn main -> _/ebx: int {
   print-string 0, "P3\n256 256\n255\n"
   var _four/edx: int <- copy 4
   var four/xmm1: float <- convert _four
@@ -47,7 +47,7 @@ fn main -> exit-status/ebx: int {
     j <- decrement
     loop
   }
-  exit-status <- copy 1
+  return 0
 }
 
 type rgb {
diff --git a/apps/raytracing/3.mu b/apps/raytracing/3.mu
index acc2df33..5b87f344 100644
--- a/apps/raytracing/3.mu
+++ b/apps/raytracing/3.mu
@@ -59,7 +59,7 @@ fn ray-color _in: (addr ray), _out: (addr rgb) {
 #?   print-string 0, "\n"
 }
 
-fn main -> exit-status/ebx: int {
+fn main -> _/ebx: int {
 
   # image
   #   width = 400
@@ -221,7 +221,7 @@ fn main -> exit-status/ebx: int {
     j <- decrement
     loop
   }
-  exit-status <- copy 1
+  return 0
 }
 
 type ray {
@@ -457,18 +457,19 @@ fn vec3-unit in: (addr vec3), out: (addr vec3) {
   vec3-scale-down out, len
 }
 
-fn vec3-length v: (addr vec3) -> result/xmm0: float {
-  result <- vec3-length-squared v
+fn vec3-length v: (addr vec3) -> _/xmm0: float {
+  var result/xmm0: float <- vec3-length-squared v
   result <- square-root result
+  return result
 }
 
-fn vec3-length-squared _v: (addr vec3) -> result/xmm0: float {
+fn vec3-length-squared _v: (addr vec3) -> _/xmm0: float {
   var v/esi: (addr vec3) <- copy _v
   # result = v.x * v.x
   var src/eax: (addr float) <- get v, x
   var tmp/xmm1: float <- copy *src
   tmp <- multiply tmp
-  result <- copy tmp
+  var result/xmm0: float <- copy tmp
   # result += v.y * v.y
   src <- get v, y
   tmp <- copy *src
@@ -479,4 +480,5 @@ fn vec3-length-squared _v: (addr vec3) -> result/xmm0: float {
   tmp <- copy *src
   tmp <- multiply tmp
   result <- add tmp
+  return result
 }
diff --git a/apps/raytracing/vec.mu b/apps/raytracing/vec.mu
index ce745a15..c93bab91 100644
--- a/apps/raytracing/vec.mu
+++ b/apps/raytracing/vec.mu
@@ -102,18 +102,19 @@ fn vec3-unit in: (addr vec3), out: (addr vec3) {
   vec3-scale-down out, len
 }
 
-fn vec3-length v: (addr vec3) -> result/xmm0: float {
-  result <- vec3-length-squared v
+fn vec3-length v: (addr vec3) -> _/xmm0: float {
+  var result/xmm0: float <- vec3-length-squared v
   result <- square-root result
+  return result
 }
 
-fn vec3-length-squared _v: (addr vec3) -> result/xmm0: float {
+fn vec3-length-squared _v: (addr vec3) -> _/xmm0: float {
   var v/esi: (addr vec3) <- copy _v
   # result = v.x * v.x
   var src/eax: (addr float) <- get v, x
   var tmp/xmm1: float <- copy *src
   tmp <- multiply tmp
-  result <- copy tmp
+  var result/xmm0: float <- copy tmp
   # result += v.y * v.y
   src <- get v, y
   tmp <- copy *src
@@ -124,6 +125,7 @@ fn vec3-length-squared _v: (addr vec3) -> result/xmm0: float {
   tmp <- copy *src
   tmp <- multiply tmp
   result <- add tmp
+  return result
 }
 
 fn vec3-dot _v1: (addr vec3), _v2: (addr vec3) -> result/xmm0: float {
diff --git a/apps/tile/data.mu b/apps/tile/data.mu
index b1ed4083..e7f9a141 100644
--- a/apps/tile/data.mu
+++ b/apps/tile/data.mu
@@ -377,27 +377,28 @@ fn function-body functions: (addr handle function), _word: (addr handle word), o
   }
 }
 
-fn body-length functions: (addr handle function), function-name: (addr handle word) -> result/eax: int {
+fn body-length functions: (addr handle function), function-name: (addr handle word) -> _/eax: int {
   var body-storage: (handle line)
   var body-ah/edi: (addr handle line) <- address body-storage
   function-body functions, function-name, body-ah
   var body/eax: (addr line) <- lookup *body-ah
-  result <- line-length body
+  var result/eax: int <- line-length body
+  return result
 }
 
-fn line-length _in: (addr line) -> result/eax: int {
+fn line-length _in: (addr line) -> _/eax: int {
   var in/esi: (addr line) <- copy _in
   var curr-ah/ecx: (addr handle word) <- get in, data
-  var out/edi: int <- copy 0
+  var result/edi: int <- copy 0
   {
     var curr/eax: (addr word) <- lookup *curr-ah
     compare curr, 0
     break-if-=
     curr-ah <- get curr, next
-    out <- increment
+    result <- increment
     loop
   }
-  result <- copy out
+  return result
 }
 
 fn populate-text-with _out: (addr handle array byte), _in: (addr array byte) {
@@ -440,9 +441,8 @@ fn initialize-path-from-line _line: (addr line), _out: (addr handle call-path-el
   copy-object src, dest
 }
 
-fn find-in-call-paths call-paths: (addr handle call-path), needle: (addr handle call-path-element) -> result/eax: boolean {
+fn find-in-call-paths call-paths: (addr handle call-path), needle: (addr handle call-path-element) -> _/eax: boolean {
   var curr-ah/esi: (addr handle call-path) <- copy call-paths
-  var out/edi: boolean <- copy 0  # false
   $find-in-call-path:loop: {
     var curr/eax: (addr call-path) <- lookup *curr-ah
     compare curr, 0
@@ -453,18 +453,16 @@ fn find-in-call-paths call-paths: (addr handle call-path), needle: (addr handle
       compare match?, 0  # false
       {
         break-if-=
-        out <- copy 1  # true
-        break $find-in-call-path:loop
+        return 1  # true
       }
     }
     curr-ah <- get curr, next
     loop
   }
-  result <- copy out
+  return 0  # false
 }
 
-fn call-path-element-match? _x: (addr handle call-path-element), _y: (addr handle call-path-element) -> result/eax: boolean {
-$call-path-element-match?:body: {
+fn call-path-element-match? _x: (addr handle call-path-element), _y: (addr handle call-path-element) -> _/eax: boolean {
   var x-ah/eax: (addr handle call-path-element) <- copy _x
   var x-a/eax: (addr call-path-element) <- lookup *x-ah
   var x/esi: (addr call-path-element) <- copy x-a
@@ -474,20 +472,17 @@ $call-path-element-match?:body: {
   compare x, y
   {
     break-if-!=
-    result <- copy 1  # true
-    break $call-path-element-match?:body
+    return 1  # true
   }
   compare x, 0
   {
     break-if-!=
-    result <- copy 0  # false
-    break $call-path-element-match?:body
+    return 0  # false
   }
   compare y, 0
   {
     break-if-!=
-    result <- copy 0  # false
-    break $call-path-element-match?:body
+    return 0  # false
   }
   # compare word addresses, not contents
   var x-data-ah/ecx: (addr handle word) <- get x, word
@@ -504,13 +499,12 @@ $call-path-element-match?:body: {
   compare x-data, y-data
   {
     break-if-=
-    result <- copy 0  # false
-    break $call-path-element-match?:body
+    return 0  # false
   }
   var x-next/ecx: (addr handle call-path-element) <- get x, next
   var y-next/eax: (addr handle call-path-element) <- get y, next
-  result <- call-path-element-match? x-next, y-next
-}
+  var result/eax: boolean <- call-path-element-match? x-next, y-next
+  return result
 }
 
 # order is irrelevant
@@ -551,7 +545,6 @@ fn deep-copy-call-path-element _src: (addr handle call-path-element), _dest: (ad
 }
 
 fn delete-in-call-path list: (addr handle call-path), needle: (addr handle call-path-element) {
-$delete-in-call-path:body: {
   var curr-ah/esi: (addr handle call-path) <- copy list
   $delete-in-call-path:loop: {
     var _curr/eax: (addr call-path) <- lookup *curr-ah
@@ -573,7 +566,6 @@ $delete-in-call-path:body: {
     loop
   }
 }
-}
 
 fn increment-final-element list: (addr handle call-path-element) {
   var final-ah/eax: (addr handle call-path-element) <- copy list
@@ -658,7 +650,6 @@ fn drop-nested-calls _list: (addr handle call-path-element) {
 }
 
 fn dump-call-path-element screen: (addr screen), _x-ah: (addr handle call-path-element) {
-$dump-call-path-element:body: {
   var x-ah/ecx: (addr handle call-path-element) <- copy _x-ah
   var _x/eax: (addr call-path-element) <- lookup *x-ah
   var x/esi: (addr call-path-element) <- copy _x
@@ -672,17 +663,12 @@ $dump-call-path-element:body: {
     break-if-=
     print-string screen, " "
     dump-call-path-element screen, next-ah
-    break $dump-call-path-element:body
+    return
   }
-  {
-    break-if-!=
-    print-string screen, "\n"
-  }
-}
+  print-string screen, "\n"
 }
 
 fn dump-call-paths screen: (addr screen), _x-ah: (addr handle call-path) {
-$dump-call-paths:body: {
   var x-ah/ecx: (addr handle call-path) <- copy _x-ah
   var x/eax: (addr call-path) <- lookup *x-ah
   compare x, 0
@@ -695,7 +681,5 @@ $dump-call-paths:body: {
   {
     break-if-=
     dump-call-paths screen, next-ah
-    break $dump-call-paths:body
   }
 }
-}
diff --git a/apps/tile/environment.mu b/apps/tile/environment.mu
index e3a069f0..3105ed89 100644
--- a/apps/tile/environment.mu
+++ b/apps/tile/environment.mu
@@ -760,61 +760,65 @@ fn copy-unbound-words-to-args _functions: (addr handle function) {
   }
 }
 
-fn bound-function? w: (addr word), functions-ah: (addr handle function) -> result/ebx: boolean {
-  result <- copy 1  # true
-  # if w == "+" return true
-  var subresult/eax: boolean <- word-equal? w, "+"
-  compare subresult, 0  # false
-  break-if-!=
-  # if w == "-" return true
-  subresult <- word-equal? w, "-"
-  compare subresult, 0  # false
-  break-if-!=
-  # if w == "*" return true
-  subresult <- word-equal? w, "*"
-  compare subresult, 0  # false
-  break-if-!=
-  # if w == "len" return true
-  subresult <- word-equal? w, "len"
-  compare subresult, 0  # false
-  break-if-!=
-  # if w == "open" return true
-  subresult <- word-equal? w, "open"
-  compare subresult, 0  # false
-  break-if-!=
-  # if w == "read" return true
-  subresult <- word-equal? w, "read"
-  compare subresult, 0  # false
-  break-if-!=
-  # if w == "slurp" return true
-  subresult <- word-equal? w, "slurp"
-  compare subresult, 0  # false
-  break-if-!=
-  # if w == "lines" return true
-  subresult <- word-equal? w, "lines"
-  compare subresult, 0  # false
-  break-if-!=
-  # if w == "dup" return true
-  subresult <- word-equal? w, "dup"
-  compare subresult, 0  # false
-  break-if-!=
-  # if w == "swap" return true
-  subresult <- word-equal? w, "swap"
-  compare subresult, 0  # false
-  break-if-!=
-  # return w in functions
-  var out-h: (handle function)
-  var out/eax: (addr handle function) <- address out-h
-  callee functions-ah, w, out
-  var found?/eax: (addr function) <- lookup *out
-  result <- copy found?
+fn bound-function? w: (addr word), functions-ah: (addr handle function) -> _/ebx: boolean {
+  var result/ebx: boolean <- copy 1  # true
+  {
+    # if w == "+" return true
+    var subresult/eax: boolean <- word-equal? w, "+"
+    compare subresult, 0  # false
+    break-if-!=
+    # if w == "-" return true
+    subresult <- word-equal? w, "-"
+    compare subresult, 0  # false
+    break-if-!=
+    # if w == "*" return true
+    subresult <- word-equal? w, "*"
+    compare subresult, 0  # false
+    break-if-!=
+    # if w == "len" return true
+    subresult <- word-equal? w, "len"
+    compare subresult, 0  # false
+    break-if-!=
+    # if w == "open" return true
+    subresult <- word-equal? w, "open"
+    compare subresult, 0  # false
+    break-if-!=
+    # if w == "read" return true
+    subresult <- word-equal? w, "read"
+    compare subresult, 0  # false
+    break-if-!=
+    # if w == "slurp" return true
+    subresult <- word-equal? w, "slurp"
+    compare subresult, 0  # false
+    break-if-!=
+    # if w == "lines" return true
+    subresult <- word-equal? w, "lines"
+    compare subresult, 0  # false
+    break-if-!=
+    # if w == "dup" return true
+    subresult <- word-equal? w, "dup"
+    compare subresult, 0  # false
+    break-if-!=
+    # if w == "swap" return true
+    subresult <- word-equal? w, "swap"
+    compare subresult, 0  # false
+    break-if-!=
+    # return w in functions
+    var out-h: (handle function)
+    var out/eax: (addr handle function) <- address out-h
+    callee functions-ah, w, out
+    var found?/eax: (addr function) <- lookup *out
+    result <- copy found?
+  }
+  return result
 }
 
-fn arg-exists? _f-ah: (addr handle function), arg: (addr word) -> result/ebx: boolean {
+fn arg-exists? _f-ah: (addr handle function), arg: (addr word) -> _/ebx: boolean {
   var f-ah/eax: (addr handle function) <- copy *_f-ah
   var f/eax: (addr function) <- lookup *f-ah
   var args-ah/eax: (addr handle word) <- get f, args
-  result <- word-exists? args-ah, arg
+  var result/ebx: boolean <- word-exists? args-ah, arg
+  return result
 }
 
 # construct a call to `f` with copies of exactly its args
@@ -1177,32 +1181,33 @@ fn render-line-without-stack screen: (addr screen), _line: (addr line), curr-row
   }
 }
 
-fn call-depth-at-cursor _sandbox: (addr sandbox) -> result/eax: int {
+fn call-depth-at-cursor _sandbox: (addr sandbox) -> _/eax: int {
   var sandbox/esi: (addr sandbox) <- copy _sandbox
   var cursor-call-path/edi: (addr handle call-path-element) <- get sandbox, cursor-call-path
-  result <- call-path-element-length cursor-call-path
-  result <- add 2  # input-row-1
+  var result/eax: int <- call-path-element-length cursor-call-path
+  result <- add 2  # input-row - 1
+  return result
 }
 
-fn call-path-element-length _x: (addr handle call-path-element) -> result/eax: int {
+fn call-path-element-length _x: (addr handle call-path-element) -> _/eax: int {
   var curr-ah/ecx: (addr handle call-path-element) <- copy _x
-  var out/edi: int <- copy 0
+  var result/edi: int <- copy 0
   {
     var curr/eax: (addr call-path-element) <- lookup *curr-ah
     compare curr, 0
     break-if-=
     curr-ah <- get curr, next
-    out <- increment
+    result <- increment
     loop
   }
-  result <- copy out
+  return result
 }
 
 # Render the line of words in line, along with the state of the stack under each word.
 # Also render any expanded function calls using recursive calls.
 #
 # Along the way, compute the column the cursor should be positioned at (cursor-col-addr).
-fn render-line screen: (addr screen), functions: (addr handle function), bindings: (addr table), first-line: (addr line), _line: (addr line), expanded-words: (addr handle call-path), top-row: int, left-col: int, curr-path: (addr handle call-path-element), cursor-word: (addr word), cursor-call-path: (addr handle call-path-element), cursor-row-addr: (addr int), cursor-col-addr: (addr int) -> right-col/ecx: int {
+fn render-line screen: (addr screen), functions: (addr handle function), bindings: (addr table), first-line: (addr line), _line: (addr line), expanded-words: (addr handle call-path), top-row: int, left-col: int, curr-path: (addr handle call-path-element), cursor-word: (addr word), cursor-call-path: (addr handle call-path-element), cursor-row-addr: (addr int), cursor-col-addr: (addr int) -> _/ecx: int {
 #?   print-string 0, "--\n"
   # curr-word
   var line/esi: (addr line) <- copy _line
@@ -1331,7 +1336,7 @@ fn render-line screen: (addr screen), functions: (addr handle function), binding
     increment-final-element curr-path
     loop
   }
-  right-col <- copy curr-col
+  return curr-col
 }
 
 fn callee functions: (addr handle function), word: (addr word), out: (addr handle function) {
@@ -1346,7 +1351,7 @@ fn callee functions: (addr handle function), word: (addr word), out: (addr handl
 #   - starting somewhere below at left-col: the stack result from interpreting first-world to final-word (inclusive)
 #
 # Return the farthest column written.
-fn render-column screen: (addr screen), functions: (addr handle function), bindings: (addr table), first-line: (addr line), line: (addr line), final-word: (addr word), top-row: int, left-col: int -> right-col/ecx: int {
+fn render-column screen: (addr screen), functions: (addr handle function), bindings: (addr table), first-line: (addr line), line: (addr line), final-word: (addr word), top-row: int, left-col: int -> _/ecx: int {
 #?   print-string 0, "render-column\n"
   var max-width/esi: int <- copy 0
   {
@@ -1396,13 +1401,14 @@ fn render-column screen: (addr screen), functions: (addr handle function), bindi
   }
 
   # post-process right-col
-  right-col <- copy left-col
+  var right-col/ecx: int <- copy left-col
   right-col <- add max-width
   right-col <- add 1  # margin-right
 #?   print-int32-decimal 0, left-col
 #?   print-string 0, " => "
 #?   print-int32-decimal 0, right-col
 #?   print-string 0, "\n"
+  return right-col
 }
 
 fn render-value screen: (addr screen), _val: (addr value), max-width: int {
@@ -1522,8 +1528,9 @@ fn render-array screen: (addr screen), _a: (addr array value) {
   print-grapheme screen, 0x5d  # ']'
 }
 
-fn hash-color val: int -> result/eax: int {
-  result <- try-modulo val, 7  # assumes that 7 is always the background color
+fn hash-color val: int -> _/eax: int {
+  var result/eax: int <- try-modulo val, 7  # assumes that 7 is always the background color
+  return result
 }
 
 fn clear-canvas _env: (addr environment) {
@@ -1604,7 +1611,7 @@ fn clear-canvas _env: (addr environment) {
 }
 
 # only single-line functions supported for now
-fn render-function screen: (addr screen), row: int, col: int, _f: (addr function) -> out-row/ebx: int {
+fn render-function screen: (addr screen), row: int, col: int, _f: (addr function) -> _/ebx: int {
   var f/esi: (addr function) <- copy _f
   var args/ecx: (addr handle word) <- get f, args
   move-cursor screen, row, col
@@ -1622,48 +1629,41 @@ fn render-function screen: (addr screen), row: int, col: int, _f: (addr function
   var body/eax: (addr line) <- lookup *body-ah
   var body-words-ah/eax: (addr handle word) <- get body, data
   print-words screen, body-words-ah
-  out-row <- copy row
+  return row
 }
 
-fn real-grapheme? g: grapheme -> result/eax: boolean {
-$real-grapheme?:body: {
+fn real-grapheme? g: grapheme -> _/eax: boolean {
   # if g == newline return true
   compare g, 0xa
   {
     break-if-!=
-    result <- copy 1  # true
-    break $real-grapheme?:body
+    return 1  # true
   }
   # if g == tab return true
   compare g, 9
   {
     break-if-!=
-    result <- copy 1  # true
-    break $real-grapheme?:body
+    return 1  # true
   }
   # if g < 32 return false
   compare g, 0x20
   {
     break-if->=
-    result <- copy 0  # false
-    break $real-grapheme?:body
+    return 0  # false
   }
   # if g <= 255 return true
   compare g, 0xff
   {
     break-if->
-    result <- copy 1  # true
-    break $real-grapheme?:body
+    return 1  # true
   }
   # if (g&0xff == Esc) it's an escape sequence
   and-with g, 0xff
   compare g, 0x1b  # Esc
   {
     break-if-!=
-    result <- copy 0  # false
-    break $real-grapheme?:body
+    return 0  # false
   }
   # otherwise return true
-  result <- copy 1  # true
-}
+  return 1  # true
 }
diff --git a/apps/tile/gap-buffer.mu b/apps/tile/gap-buffer.mu
index 07ce68a3..4d71789d 100644
--- a/apps/tile/gap-buffer.mu
+++ b/apps/tile/gap-buffer.mu
@@ -88,15 +88,16 @@ fn render-gap-buffer screen: (addr screen), _gap: (addr gap-buffer) {
   render-stack-from-top right, screen
 }
 
-fn gap-buffer-length _gap: (addr gap-buffer) -> result/eax: int {
+fn gap-buffer-length _gap: (addr gap-buffer) -> _/eax: int {
   var gap/esi: (addr gap-buffer) <- copy _gap
   var left/eax: (addr grapheme-stack) <- get gap, left
   var tmp/eax: (addr int) <- get left, top
   var left-length/ecx: int <- copy *tmp
   var right/esi: (addr grapheme-stack) <- get gap, right
   tmp <- get right, top
-  result <- copy *tmp
+  var result/eax: int <- copy *tmp
   result <- add left-length
+  return result
 }
 
 fn add-grapheme-at-gap _self: (addr gap-buffer), g: grapheme {
@@ -121,63 +122,59 @@ fn gap-to-end self: (addr gap-buffer) {
   }
 }
 
-fn gap-at-start? _self: (addr gap-buffer) -> result/eax: boolean {
+fn gap-at-start? _self: (addr gap-buffer) -> _/eax: boolean {
   var self/esi: (addr gap-buffer) <- copy _self
   var left/eax: (addr grapheme-stack) <- get self, left
-  result <- grapheme-stack-empty? left
+  var result/eax: boolean <- grapheme-stack-empty? left
+  return result
 }
 
-fn gap-at-end? _self: (addr gap-buffer) -> result/eax: boolean {
+fn gap-at-end? _self: (addr gap-buffer) -> _/eax: boolean {
   var self/esi: (addr gap-buffer) <- copy _self
   var right/eax: (addr grapheme-stack) <- get self, right
-  result <- grapheme-stack-empty? right
+  var result/eax: boolean <- grapheme-stack-empty? right
+  return result
 }
 
-fn gap-right _self: (addr gap-buffer) -> result/eax: grapheme {
-$gap-right:body: {
+fn gap-right _self: (addr gap-buffer) -> _/eax: grapheme {
   var self/esi: (addr gap-buffer) <- copy _self
-  var g/edx: grapheme <- copy 0
-  {
-    var right/ecx: (addr grapheme-stack) <- get self, right
-    result <- pop-grapheme-stack right
-    compare result, -1
-    break-if-= $gap-right:body
-    g <- copy result
-  }
+  var g/eax: grapheme <- copy 0
+  var right/ecx: (addr grapheme-stack) <- get self, right
+  g <- pop-grapheme-stack right
+  compare g, -1
   {
+    break-if-=
     var left/ecx: (addr grapheme-stack) <- get self, left
     push-grapheme-stack left, g
   }
-}
+  return g
 }
 
-fn gap-left _self: (addr gap-buffer) -> result/eax: grapheme {
-$gap-left:body: {
+fn gap-left _self: (addr gap-buffer) -> _/eax: grapheme {
   var self/esi: (addr gap-buffer) <- copy _self
-  var g/edx: grapheme <- copy 0
+  var g/eax: grapheme <- copy 0
   {
     var left/ecx: (addr grapheme-stack) <- get self, left
-    result <- pop-grapheme-stack left
-    compare result, -1
-    break-if-= $gap-left:body
-    g <- copy result
+    g <- pop-grapheme-stack left
   }
+  compare g, -1
   {
+    break-if-=
     var right/ecx: (addr grapheme-stack) <- get self, right
     push-grapheme-stack right, g
   }
-}
+  return g
 }
 
-fn gap-index _self: (addr gap-buffer) -> result/eax: int {
+fn gap-index _self: (addr gap-buffer) -> _/eax: int {
   var self/eax: (addr gap-buffer) <- copy _self
   var left/eax: (addr grapheme-stack) <- get self, left
   var top-addr/eax: (addr int) <- get left, top
-  result <- copy *top-addr
+  var result/eax: int <- copy *top-addr
+  return result
 }
 
-fn first-grapheme-in-gap-buffer _self: (addr gap-buffer) -> result/eax: grapheme {
-$first-grapheme-in-gap-buffer:body: {
+fn first-grapheme-in-gap-buffer _self: (addr gap-buffer) -> _/eax: grapheme {
   var self/esi: (addr gap-buffer) <- copy _self
   # try to read from left
   var left/eax: (addr grapheme-stack) <- get self, left
@@ -188,8 +185,7 @@ $first-grapheme-in-gap-buffer:body: {
     var data-ah/eax: (addr handle array grapheme) <- get left, data
     var data/eax: (addr array grapheme) <- lookup *data-ah
     var result-addr/eax: (addr grapheme) <- index data, 0
-    result <- copy *result-addr
-    break $first-grapheme-in-gap-buffer:body
+    return *result-addr
   }
   # try to read from right
   var right/eax: (addr grapheme-stack) <- get self, right
@@ -202,16 +198,13 @@ $first-grapheme-in-gap-buffer:body: {
     var top/ecx: int <- copy *top-addr
     top <- decrement
     var result-addr/eax: (addr grapheme) <- index data, top
-    result <- copy *result-addr
-    break $first-grapheme-in-gap-buffer:body
+    return *result-addr
   }
   # give up
-  result <- copy -1
-}
+  return -1
 }
 
-fn grapheme-before-cursor-in-gap-buffer _self: (addr gap-buffer) -> result/eax: grapheme {
-$grapheme-before-cursor-in-gap-buffer:body: {
+fn grapheme-before-cursor-in-gap-buffer _self: (addr gap-buffer) -> _/eax: grapheme {
   var self/esi: (addr gap-buffer) <- copy _self
   # try to read from left
   var left/ecx: (addr grapheme-stack) <- get self, left
@@ -219,13 +212,12 @@ $grapheme-before-cursor-in-gap-buffer:body: {
   compare *top-addr, 0
   {
     break-if-<=
-    result <- pop-grapheme-stack left
+    var result/eax: grapheme <- pop-grapheme-stack left
     push-grapheme-stack left, result
-    break $grapheme-before-cursor-in-gap-buffer:body
+    return result
   }
   # give up
-  result <- copy -1
-}
+  return -1
 }
 
 fn delete-before-gap _self: (addr gap-buffer) {
@@ -234,14 +226,14 @@ fn delete-before-gap _self: (addr gap-buffer) {
   var dummy/eax: grapheme <- pop-grapheme-stack left
 }
 
-fn pop-after-gap _self: (addr gap-buffer) -> result/eax: grapheme {
+fn pop-after-gap _self: (addr gap-buffer) -> _/eax: grapheme {
   var self/eax: (addr gap-buffer) <- copy _self
   var right/eax: (addr grapheme-stack) <- get self, right
-  result <- pop-grapheme-stack right
+  var result/eax: grapheme <- pop-grapheme-stack right
+  return result
 }
 
-fn gap-buffer-equal? _self: (addr gap-buffer), s: (addr array byte) -> result/eax: boolean {
-$gap-buffer-equal?:body: {
+fn gap-buffer-equal? _self: (addr gap-buffer), s: (addr array byte) -> _/eax: boolean {
   var self/esi: (addr gap-buffer) <- copy _self
   # complication: graphemes may be multiple bytes
   # so don't rely on length
@@ -251,17 +243,23 @@ $gap-buffer-equal?:body: {
   write expected-stream, s
   # compare left
   var left/edx: (addr grapheme-stack) <- get self, left
-  result <- prefix-match? left, expected-stream
+  var result/eax: boolean <- prefix-match? left, expected-stream
   compare result, 0  # false
-  break-if-= $gap-buffer-equal?:body
+  {
+    break-if-!=
+    return result
+  }
   # compare right
   var right/edx: (addr grapheme-stack) <- get self, right
   result <- suffix-match? right, expected-stream
   compare result, 0  # false
-  break-if-= $gap-buffer-equal?:body
+  {
+    break-if-!=
+    return result
+  }
   # ensure there's nothing left over
   result <- stream-empty? expected-stream
-}
+  return result
 }
 
 fn test-gap-buffer-equal-from-end? {
@@ -331,12 +329,15 @@ fn copy-gap-buffer _src-ah: (addr handle gap-buffer), _dest-ah: (addr handle gap
   copy-grapheme-stack src, dest
 }
 
-fn gap-buffer-is-decimal-integer? _self: (addr gap-buffer) -> result/eax: boolean {
+fn gap-buffer-is-decimal-integer? _self: (addr gap-buffer) -> _/eax: boolean {
   var self/esi: (addr gap-buffer) <- copy _self
   var curr/ecx: (addr grapheme-stack) <- get self, left
-  result <- grapheme-stack-is-decimal-integer? curr
-  compare result, 0  # false
-  break-if-=
-  curr <- get self, right
-  result <- grapheme-stack-is-decimal-integer? curr
+  var result/eax: boolean <- grapheme-stack-is-decimal-integer? curr
+  {
+    compare result, 0  # false
+    break-if-=
+    curr <- get self, right
+    result <- grapheme-stack-is-decimal-integer? curr
+  }
+  return result
 }
diff --git a/apps/tile/grapheme-stack.mu b/apps/tile/grapheme-stack.mu
index 620e2eda..8b123331 100644
--- a/apps/tile/grapheme-stack.mu
+++ b/apps/tile/grapheme-stack.mu
@@ -17,18 +17,15 @@ fn clear-grapheme-stack _self: (addr grapheme-stack) {
   copy-to *top, 0
 }
 
-fn grapheme-stack-empty? _self: (addr grapheme-stack) -> result/eax: boolean {
-$grapheme-stack-empty?:body: {
+fn grapheme-stack-empty? _self: (addr grapheme-stack) -> _/eax: boolean {
   var self/esi: (addr grapheme-stack) <- copy _self
   var top/eax: (addr int) <- get self, top
   compare *top, 0
   {
     break-if-!=
-    result <- copy 1  # true
-    break $grapheme-stack-empty?:body
+    return 1  # true
   }
-  result <- copy 0  # false
-}
+  return 0  # false
 }
 
 fn push-grapheme-stack _self: (addr grapheme-stack), _val: grapheme {
@@ -43,23 +40,20 @@ fn push-grapheme-stack _self: (addr grapheme-stack), _val: grapheme {
   add-to *top-addr, 1
 }
 
-fn pop-grapheme-stack _self: (addr grapheme-stack) -> val/eax: grapheme {
-$pop-grapheme-stack:body: {
+fn pop-grapheme-stack _self: (addr grapheme-stack) -> _/eax: grapheme {
   var self/esi: (addr grapheme-stack) <- copy _self
   var top-addr/ecx: (addr int) <- get self, top
   {
     compare *top-addr, 0
     break-if->
-    val <- copy -1
-    break $pop-grapheme-stack:body
+    return -1
   }
   subtract-from *top-addr, 1
   var data-ah/edx: (addr handle array grapheme) <- get self, data
   var data/eax: (addr array grapheme) <- lookup *data-ah
   var top/edx: int <- copy *top-addr
   var result-addr/eax: (addr grapheme) <- index data, top
-  val <- copy *result-addr
-}
+  return *result-addr
 }
 
 fn copy-grapheme-stack _src: (addr grapheme-stack), dest: (addr grapheme-stack) {
@@ -120,8 +114,7 @@ fn render-stack-from-top _self: (addr grapheme-stack), screen: (addr screen) {
 
 # compare from bottom
 # beware: modifies 'stream', which must be disposed of after a false result
-fn prefix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> result/eax: boolean {
-$prefix-match?:body: {
+fn prefix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> _/eax: boolean {
   var self/esi: (addr grapheme-stack) <- copy _self
   var data-ah/edi: (addr handle array grapheme) <- get self, data
   var _data/eax: (addr array grapheme) <- lookup *data-ah
@@ -138,21 +131,18 @@ $prefix-match?:body: {
       {
         compare expected, *curr-a
         break-if-=
-        result <- copy 0  # false
-        break $prefix-match?:body
+        return 0  # false
       }
     }
     i <- increment
     loop
   }
-  result <- copy 1   # true
-}
+  return 1   # true
 }
 
 # compare from bottom
 # beware: modifies 'stream', which must be disposed of after a false result
-fn suffix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> result/eax: boolean {
-$suffix-match?:body: {
+fn suffix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> _/eax: boolean {
   var self/esi: (addr grapheme-stack) <- copy _self
   var data-ah/edi: (addr handle array grapheme) <- get self, data
   var _data/eax: (addr array grapheme) <- lookup *data-ah
@@ -170,24 +160,23 @@ $suffix-match?:body: {
       {
         compare expected, *curr-a
         break-if-=
-        result <- copy 0  # false
-        break $suffix-match?:body
+        return 0  # false
       }
     }
     i <- decrement
     loop
   }
-  result <- copy 1   # true
-}
+  return 1   # true
 }
 
-fn grapheme-stack-is-decimal-integer? _self: (addr grapheme-stack) -> result/eax: boolean {
+fn grapheme-stack-is-decimal-integer? _self: (addr grapheme-stack) -> _/eax: boolean {
   var self/esi: (addr grapheme-stack) <- copy _self
   var data-ah/eax: (addr handle array grapheme) <- get self, data
   var _data/eax: (addr array grapheme) <- lookup *data-ah
   var data/edx: (addr array grapheme) <- copy _data
   var top-addr/ecx: (addr int) <- get self, top
   var i/ebx: int <- copy 0
+  var result/eax: boolean <- copy 1  # true
   $grapheme-stack-is-integer?:loop: {
     compare i, *top-addr
     break-if->=
@@ -198,4 +187,5 @@ fn grapheme-stack-is-decimal-integer? _self: (addr grapheme-stack) -> result/eax
     i <- increment
     loop
   }
+  return result
 }
diff --git a/apps/tile/int-stack.mu b/apps/tile/int-stack.mu
index 3bb9336f..726684bd 100644
--- a/apps/tile/int-stack.mu
+++ b/apps/tile/int-stack.mu
@@ -29,41 +29,35 @@ fn push-int-stack _self: (addr int-stack), _val: int {
   add-to *top-addr, 1
 }
 
-fn pop-int-stack _self: (addr int-stack) -> val/eax: int {
-$pop-int-stack:body: {
+fn pop-int-stack _self: (addr int-stack) -> _/eax: int {
   var self/esi: (addr int-stack) <- copy _self
   var top-addr/ecx: (addr int) <- get self, top
   {
     compare *top-addr, 0
     break-if->
-    val <- copy 0
-    break $pop-int-stack:body
+    return 0
   }
   subtract-from *top-addr, 1
   var data-ah/edx: (addr handle array int) <- get self, data
   var data/eax: (addr array int) <- lookup *data-ah
   var top/edx: int <- copy *top-addr
   var result-addr/eax: (addr int) <- index data, top
-  val <- copy *result-addr
-}
+  return *result-addr
 }
 
-fn int-stack-empty? _self: (addr int-stack) -> result/eax: boolean {
-$int-stack-empty?:body: {
+fn int-stack-empty? _self: (addr int-stack) -> _/eax: boolean {
   var self/esi: (addr int-stack) <- copy _self
   var top-addr/eax: (addr int) <- get self, top
   compare *top-addr, 0
   {
     break-if-!=
-    result <- copy 1  # true
-    break $int-stack-empty?:body
+    return 1  # true
   }
-  result <- copy 0  # false
-}
+  return 0  # false
 }
 
-fn int-stack-length _self: (addr int-stack) -> result/eax: int {
+fn int-stack-length _self: (addr int-stack) -> _/eax: int {
   var self/esi: (addr int-stack) <- copy _self
   var top-addr/eax: (addr int) <- get self, top
-  result <- copy *top-addr
+  return *top-addr
 }
diff --git a/apps/tile/main.mu b/apps/tile/main.mu
index 2e51eba1..c4010c4b 100644
--- a/apps/tile/main.mu
+++ b/apps/tile/main.mu
@@ -1,4 +1,4 @@
-fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int {
+fn main args-on-stack: (addr array addr array byte) -> _/ebx: int {
   var args/eax: (addr array addr array byte) <- copy args-on-stack
   var len/ecx: int <- length args
   $main-body: {
@@ -12,8 +12,7 @@ fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int {
       {
         break-if-=
         run-tests
-        exit-status <- copy 0  # TODO: get at Num-test-failures somehow
-        break $main-body
+        return 0  # TODO: get at Num-test-failures somehow
       }
       # if single arg is 'screen', run in full-screen mode
       tmp2 <- string-equal? *tmp, "screen"
@@ -21,8 +20,7 @@ fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int {
       {
         break-if-=
         interactive
-        exit-status <- copy 0
-        break $main-body
+        return 0
       }
       # if single arg is 'type', run in typewriter mode
       tmp2 <- string-equal? *tmp, "type"
@@ -30,8 +28,7 @@ fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int {
       {
         break-if-=
         repl
-        exit-status <- copy 0
-        break $main-body
+        return 0
       }
       # if single arg is 'test' ...
       tmp2 <- string-equal? *tmp, "test2"
@@ -39,8 +36,7 @@ fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int {
       {
         break-if-=
         test
-        exit-status <- copy 0
-        break $main-body
+        return 0
       }
     }
     # otherwise error message
@@ -48,7 +44,7 @@ fn main args-on-stack: (addr array addr array byte) -> exit-status/ebx: int {
     print-string-to-real-screen "  to run tests: tile test\n"
     print-string-to-real-screen "  full-screen mode: tile screen\n"
     print-string-to-real-screen "  regular REPL: tile type\n"
-    exit-status <- copy 1
+    return 1
   }
 }
 
@@ -72,16 +68,17 @@ fn interactive {
 }
 
 fn test {
-  var env-storage: environment
-  var env/esi: (addr environment) <- address env-storage
-  initialize-environment-with-fake-screen env, 5, 0xa
-  var g/eax: grapheme <- copy 0x22  # '"'
-  process env, g
-  g <- copy 0x61  # 'a'
-  process env, g
-  g <- copy 0x22  # '"'
-  process env, g
-  render env
+  test-surface-pin-at-origin
+#?   var env-storage: environment
+#?   var env/esi: (addr environment) <- address env-storage
+#?   initialize-environment-with-fake-screen env, 5, 0xa
+#?   var g/eax: grapheme <- copy 0x22  # '"'
+#?   process env, g
+#?   g <- copy 0x61  # 'a'
+#?   process env, g
+#?   g <- copy 0x22  # '"'
+#?   process env, g
+#?   render env
 }
 
 fn repl {
diff --git a/apps/tile/rpn.mu b/apps/tile/rpn.mu
index e2c7aeef..0a8f9fc5 100644
--- a/apps/tile/rpn.mu
+++ b/apps/tile/rpn.mu
@@ -560,10 +560,10 @@ fn bind-args _callee: (addr function), _caller-stack: (addr value-stack), table:
 
 # 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 {
+fn max-stack-depth first-word: (addr word), final-word: (addr word) -> _/edi: int {
   var curr-word/eax: (addr word) <- copy first-word
   var curr-depth/ecx: int <- copy 0
-  result <- copy 0
+  var result/edi: int <- copy 0
   $max-stack-depth:loop: {
     $max-stack-depth:process-word: {
       # handle operators
@@ -606,4 +606,5 @@ fn max-stack-depth first-word: (addr word), final-word: (addr word) -> result/ed
     #
     loop
   }
+  return result
 }
diff --git a/apps/tile/surface.mu b/apps/tile/surface.mu
index e4cfffaf..9f520a3c 100644
--- a/apps/tile/surface.mu
+++ b/apps/tile/surface.mu
@@ -166,107 +166,102 @@ fn print-screen-cell screen: (addr screen), _cell: (addr screen-cell) {
 #?   print-string-to-real-screen "\n"
 }
 
-fn surface-screen-cell-index _self: (addr surface), row: int, col: int -> result/eax: int {
+fn surface-screen-cell-index _self: (addr surface), row: int, col: int -> _/eax: int {
   var self/esi: (addr surface) <- copy _self
 #?   print-int32-hex-to-real-screen row
 #?   print-string-to-real-screen ", "
 #?   print-int32-hex-to-real-screen col
 #?   print-string-to-real-screen "\n"
-  result <- copy -1
-  compare row, 1
-  break-if-<
-  compare col, 1
-  break-if-<
-  var nrows-addr/ecx: (addr int) <- get self, nrows
-  var nrows/ecx: int <- copy *nrows-addr
-  compare row, nrows
-  break-if->
-  var ncols-addr/ecx: (addr int) <- get self, ncols
-  var ncols/ecx: int <- copy *ncols-addr
-  compare col, ncols
-  break-if->
-#?   print-string-to-real-screen "!\n"
-  result <- copy row
-  result <- subtract 1
-  result <- multiply ncols
-  result <- add col
-  result <- subtract 1
+  var result/eax: int <- copy -1
+  {
+    compare row, 1
+    break-if-<
+    compare col, 1
+    break-if-<
+    var nrows-addr/ecx: (addr int) <- get self, nrows
+    var nrows/ecx: int <- copy *nrows-addr
+    compare row, nrows
+    break-if->
+    var ncols-addr/ecx: (addr int) <- get self, ncols
+    var ncols/ecx: int <- copy *ncols-addr
+    compare col, ncols
+    break-if->
+  #?   print-string-to-real-screen "!\n"
+    result <- copy row
+    result <- subtract 1
+    result <- multiply ncols
+    result <- add col
+    result <- subtract 1
+  }
+  return result
 }
 
-fn screen-row-to-surface _self: (addr surface), screen-row: int -> result/ecx: int {
+fn screen-row-to-surface _self: (addr surface), screen-row: int -> _/ecx: int {
   var self/esi: (addr surface) <- copy _self
-  result <- copy screen-row
+  var result/ecx: int <- copy screen-row
   var tmp/eax: (addr int) <- get self, pin-row
   result <- add *tmp
   tmp <- get self, pin-screen-row
   result <- subtract *tmp
+  return result
 }
 
-fn max a: int, b: int -> result/eax: int {
-$max:body: {
-  var a2/eax: int <- copy a
-  compare a2, b
+fn max _a: int, b: int -> _/eax: int {
+  var a/eax: int <- copy _a
+  compare a, b
   {
     break-if->
-    result <- copy b
-    break $max:body
-  }
-  {
-    break-if-<=
-    result <- copy a2
+    return b
   }
-}
+  return a
 }
 
-fn min a: int, b: int -> result/eax: int {
-$min:body: {
-  var a2/eax: int <- copy a
-  compare a2, b
+fn min _a: int, b: int -> _/eax: int {
+  var a/eax: int <- copy _a
+  compare a, b
   {
     break-if->
-    result <- copy a2
-    break $min:body
+    return a
   }
-  {
-    break-if-<=
-    result <- copy b
-  }
-}
+  return b
 }
 
-fn screen-col-to-surface _self: (addr surface), screen-col: int -> result/edx: int {
+fn screen-col-to-surface _self: (addr surface), screen-col: int -> _/edx: int {
   var self/esi: (addr surface) <- copy _self
-  result <- copy screen-col
+  var result/edx: int <- copy screen-col
   var tmp/eax: (addr int) <- get self, pin-col
   result <- add *tmp
   tmp <- get self, pin-screen-col
   result <- subtract *tmp
+  return result
 }
 
-fn surface-row-to-screen _self: (addr surface), row: int -> result/ecx: int {
+fn surface-row-to-screen _self: (addr surface), row: int -> _/ecx: int {
   var self/esi: (addr surface) <- copy _self
-  result <- copy row
+  var result/ecx: int <- copy row
   var tmp/eax: (addr int) <- get self, pin-screen-row
   result <- add *tmp
   tmp <- get self, pin-row
   result <- subtract *tmp
+  return result
 }
 
-fn surface-col-to-screen _self: (addr surface), col: int -> result/edx: int {
+fn surface-col-to-screen _self: (addr surface), col: int -> _/edx: int {
   var self/esi: (addr surface) <- copy _self
-  result <- copy col
+  var result/edx: int <- copy col
   var tmp/eax: (addr int) <- get self, pin-screen-col
   result <- add *tmp
   tmp <- get self, pin-col
   result <- subtract *tmp
+  return result
 }
 
 # assumes last line doesn't end in '\n'
-fn num-lines in: (addr array byte) -> result/ecx: int {
+fn num-lines in: (addr array byte) -> _/ecx: int {
   var s: (stream byte 0x100)
   var s-addr/esi: (addr stream byte) <- address s
   write s-addr, in
-  result <- copy 1
+  var result/ecx: int <- copy 1
   {
     var done?/eax: boolean <- stream-empty? s-addr
     compare done?, 0  # false
@@ -277,13 +272,14 @@ fn num-lines in: (addr array byte) -> result/ecx: int {
     result <- increment
     loop
   }
+  return result
 }
 
-fn first-line-length in: (addr array byte) -> result/edx: int {
+fn first-line-length in: (addr array byte) -> _/edx: int {
   var s: (stream byte 0x100)
   var s-addr/esi: (addr stream byte) <- address s
   write s-addr, in
-  result <- copy 0
+  var result/edx: int <- copy 0
   {
     var done?/eax: boolean <- stream-empty? s-addr
     compare done?, 0  # false
@@ -294,6 +290,7 @@ fn first-line-length in: (addr array byte) -> result/edx: int {
     result <- increment
     loop
   }
+  return result
 }
 
 fn fill-in _out: (addr array screen-cell), in: (addr array byte) {
diff --git a/apps/tile/table.mu b/apps/tile/table.mu
index 267bed99..a4a2bae6 100644
--- a/apps/tile/table.mu
+++ b/apps/tile/table.mu
@@ -15,10 +15,11 @@ fn bind-in-table _self: (addr table), key: (addr handle array byte), val: (addr
 }
 
 # manual test: full array of binds
-fn next-empty-slot _data: (addr array bind), key: (addr handle array byte) -> result/eax: (offset bind) {
+fn next-empty-slot _data: (addr array bind), key: (addr handle array byte) -> _/eax: (offset bind) {
   var data/esi: (addr array bind) <- copy _data
   var len/ecx: int <- length data
   var i/edx: int <- copy 0
+  var result/eax: (offset bind) <- copy 0
   $next-empty-slot:loop: {
     result <- compute-offset data, i
     compare i, len
@@ -34,6 +35,7 @@ fn next-empty-slot _data: (addr array bind), key: (addr handle array byte) -> re
     i <- increment
     loop
   }
+  return result
 }
 
 fn make-int-binding _self: (addr bind), key: (addr handle array byte), _val: int {
diff --git a/apps/tile/value-stack.mu b/apps/tile/value-stack.mu
index 8da8c920..9515b7fa 100644
--- a/apps/tile/value-stack.mu
+++ b/apps/tile/value-stack.mu
@@ -83,15 +83,13 @@ fn push-value-stack _self: (addr value-stack), val: (addr value) {
   increment *top-addr
 }
 
-fn pop-int-from-value-stack _self: (addr value-stack) -> val/eax: int {
-$pop-int-from-value-stack:body: {
+fn pop-int-from-value-stack _self: (addr value-stack) -> _/eax: int {
   var self/esi: (addr value-stack) <- copy _self
   var top-addr/ecx: (addr int) <- get self, top
   {
     compare *top-addr, 0
     break-if->
-    val <- copy -1
-    break $pop-int-from-value-stack:body
+    return -1
   }
   decrement *top-addr
   var data-ah/edx: (addr handle array value) <- get self, data
@@ -100,145 +98,134 @@ $pop-int-from-value-stack:body: {
   var dest-offset/edx: (offset value) <- compute-offset data, top
   var result-addr/eax: (addr value) <- index data, dest-offset
   var result-addr2/eax: (addr int) <- get result-addr, int-data
-  val <- copy *result-addr2
-}
+  return *result-addr2
 }
 
-fn value-stack-empty? _self: (addr value-stack) -> result/eax: boolean {
-$value-stack-empty?:body: {
+fn value-stack-empty? _self: (addr value-stack) -> _/eax: boolean {
   var self/esi: (addr value-stack) <- copy _self
   var top/eax: (addr int) <- get self, top
   compare *top, 0
   {
     break-if-!=
-    result <- copy 1  # true
-    break $value-stack-empty?:body
+    return 1  # true
   }
-  result <- copy 0  # false
-}
+  return 0  # false
 }
 
-fn value-stack-length _self: (addr value-stack) -> result/eax: int {
+fn value-stack-length _self: (addr value-stack) -> _/eax: int {
   var self/esi: (addr value-stack) <- copy _self
   var top-addr/eax: (addr int) <- get self, top
-  result <- copy *top-addr
+  return *top-addr
 }
 
-fn value-stack-max-width _self: (addr value-stack) -> result/eax: int {
+fn value-stack-max-width _self: (addr value-stack) -> _/eax: int {
   var self/esi: (addr value-stack) <- copy _self
   var data-ah/edi: (addr handle array value) <- get self, data
   var _data/eax: (addr array value) <- lookup *data-ah
   var data/edi: (addr array value) <- copy _data
   var top-addr/ecx: (addr int) <- get self, top
   var i/ebx: int <- copy 0
-  var out: int
+  var result: int
   {
     compare i, *top-addr
     break-if->=
     var o/edx: (offset value) <- compute-offset data, i
     var v/edx: (addr value) <- index data, o
     var w/eax: int <- value-width v, 1  # top-level=true
-    # if (w > out) w = out
+    # if (w > result) w = result
     {
-      compare w, out
+      compare w, result
       break-if-<=
-      copy-to out, w
+      copy-to result, w
     }
     i <- increment
     loop
   }
-  result <- copy out
+  return result
 }
 
-fn value-width _v: (addr value), top-level: boolean -> result/eax: int {
-  var out/edi: int <- copy 0
-  $value-width:core: {
-    var v/esi: (addr value) <- copy _v
-    var type/eax: (addr int) <- get v, type
-    {
-      compare *type, 0  # int
-      break-if-!=
-      var v-int/edx: (addr int) <- get v, int-data
-      var _out/eax: int <- decimal-size *v-int
-      out <- copy _out
-      break $value-width:core
-    }
-    {
-      compare *type, 1  # string
-      break-if-!=
-      var s-ah/eax: (addr handle array byte) <- get v, text-data
-      var s/eax: (addr array byte) <- lookup *s-ah
-      compare s, 0
-      break-if-=
-      var _out/eax: int <- length s
-      out <- copy _out
-      compare out, 0xd  # max string size
-      {
-        break-if-<=
-        out <- copy 0xd
-      }
-      # if it's a nested string, include space for quotes
-      # we don't do this for the top-level, where the quotes will overflow
-      # into surrounding padding.
-      compare top-level, 0  # false
-      {
-        break-if-!=
-        out <- add 2
-      }
-      break $value-width:core
-    }
+fn value-width _v: (addr value), top-level: boolean -> _/eax: int {
+  var v/esi: (addr value) <- copy _v
+  var type/eax: (addr int) <- get v, type
+  {
+    compare *type, 0  # int
+    break-if-!=
+    var v-int/edx: (addr int) <- get v, int-data
+    var result/eax: int <- decimal-size *v-int
+    return result
+  }
+  {
+    compare *type, 1  # string
+    break-if-!=
+    var s-ah/eax: (addr handle array byte) <- get v, text-data
+    var s/eax: (addr array byte) <- lookup *s-ah
+    compare s, 0
+    break-if-=
+    var result/eax: int <- length s
+    compare result, 0xd  # max string size
     {
-      compare *type, 2  # array
-      break-if-!=
-      var a-ah/eax: (addr handle array value) <- get v, array-data
-      var a/eax: (addr array value) <- lookup *a-ah
-      compare a, 0
-      break-if-=
-      var _out/eax: int <- array-width a
-      out <- copy _out
-      break $value-width:core
+      break-if-<=
+      result <- copy 0xd
     }
+    # if it's a nested string, include space for quotes
+    # we don't do this for the top-level, where the quotes will overflow
+    # into surrounding padding.
+    compare top-level, 0  # false
     {
-      compare *type, 3  # file handle
       break-if-!=
-      var f-ah/eax: (addr handle buffered-file) <- get v, file-data
-      var f/eax: (addr buffered-file) <- lookup *f-ah
-      compare f, 0
-      break-if-=
-      # TODO
-      out <- copy 4
-      break $value-width:core
+      result <- add 2
     }
+    return result
+  }
+  {
+    compare *type, 2  # array
+    break-if-!=
+    var a-ah/eax: (addr handle array value) <- get v, array-data
+    var a/eax: (addr array value) <- lookup *a-ah
+    compare a, 0
+    break-if-=
+    var result/eax: int <- array-width a
+    return result
+  }
+  {
+    compare *type, 3  # file handle
+    break-if-!=
+    var f-ah/eax: (addr handle buffered-file) <- get v, file-data
+    var f/eax: (addr buffered-file) <- lookup *f-ah
+    compare f, 0
+    break-if-=
+    # TODO: visualizing file handles
+    return 4
   }
-  result <- copy out
+  return 0
 }
 
 # keep sync'd with render-array
-fn array-width _a: (addr array value) -> result/eax: int {
+fn array-width _a: (addr array value) -> _/eax: int {
   var a/esi: (addr array value) <- copy _a
   var max/ecx: int <- length a
   var i/eax: int <- copy 0
-  var out/edi: int <- copy 0
+  var result/edi: int <- copy 0
   {
     compare i, max
     break-if->=
     {
       compare i, 0
       break-if-=
-      out <- increment  # for space
+      result <- increment  # for space
     }
     var off/ecx: (offset value) <- compute-offset a, i
     var x/ecx: (addr value) <- index a, off
     {
       var w/eax: int <- value-width x, 0
-      out <- add w
+      result <- add w
     }
     i <- increment
     loop
   }
-  result <- copy out
   # we won't add 2 for surrounding brackets since we don't surround arrays in
   # spaces like other value types
+  return result
 }
 
 fn save-lines in-h: (handle array (handle array byte)), _out-ah: (addr handle array value) {
diff --git a/apps/tile/word.mu b/apps/tile/word.mu
index 9e8fb45e..c51c4bf4 100644
--- a/apps/tile/word.mu
+++ b/apps/tile/word.mu
@@ -96,18 +96,20 @@ fn copy-word-contents-before-cursor _src-ah: (addr handle word), _dest-ah: (addr
   }
 }
 
-fn word-equal? _self: (addr word), s: (addr array byte) -> result/eax: boolean {
+fn word-equal? _self: (addr word), s: (addr array byte) -> _/eax: boolean {
   var self/esi: (addr word) <- copy _self
   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
   var data/eax: (addr gap-buffer) <- lookup *data-ah
-  result <- gap-buffer-equal? data, s
+  var result/eax: boolean <- gap-buffer-equal? data, s
+  return result
 }
 
-fn word-length _self: (addr word) -> result/eax: int {
+fn word-length _self: (addr word) -> _/eax: int {
   var self/esi: (addr word) <- copy _self
   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
   var data/eax: (addr gap-buffer) <- lookup *data-ah
-  result <- gap-buffer-length data
+  var result/eax: int <- gap-buffer-length data
+  return result
 }
 
 fn first-word _in: (addr handle word), out: (addr handle word) {
@@ -143,18 +145,20 @@ fn final-word _in: (addr handle word), out: (addr handle word) {
   copy-object curr-ah, out
 }
 
-fn first-grapheme _self: (addr word) -> result/eax: grapheme {
+fn first-grapheme _self: (addr word) -> _/eax: grapheme {
   var self/esi: (addr word) <- copy _self
   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
   var data/eax: (addr gap-buffer) <- lookup *data-ah
-  result <- first-grapheme-in-gap-buffer data
+  var result/eax: grapheme <- first-grapheme-in-gap-buffer data
+  return result
 }
 
-fn grapheme-before-cursor _self: (addr word) -> result/eax: grapheme {
+fn grapheme-before-cursor _self: (addr word) -> _/eax: grapheme {
   var self/esi: (addr word) <- copy _self
   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
   var data/eax: (addr gap-buffer) <- lookup *data-ah
-  result <- grapheme-before-cursor-in-gap-buffer data
+  var result/eax: grapheme <- grapheme-before-cursor-in-gap-buffer data
+  return result
 }
 
 fn add-grapheme-to-word _self: (addr word), c: grapheme {
@@ -164,18 +168,20 @@ fn add-grapheme-to-word _self: (addr word), c: grapheme {
   add-grapheme-at-gap data, c
 }
 
-fn cursor-at-start? _self: (addr word) -> result/eax: boolean {
+fn cursor-at-start? _self: (addr word) -> _/eax: boolean {
   var self/esi: (addr word) <- copy _self
   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
   var data/eax: (addr gap-buffer) <- lookup *data-ah
-  result <- gap-at-start? data
+  var result/eax: boolean <- gap-at-start? data
+  return result
 }
 
 fn cursor-at-end? _self: (addr word) -> result/eax: boolean {
   var self/esi: (addr word) <- copy _self
   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
   var data/eax: (addr gap-buffer) <- lookup *data-ah
-  result <- gap-at-end? data
+  var result/eax: boolean <- gap-at-end? data
+  return result
 }
 
 fn cursor-left _self: (addr word) {
@@ -206,11 +212,12 @@ fn cursor-to-end _self: (addr word) {
   gap-to-end data
 }
 
-fn cursor-index _self: (addr word) -> result/eax: int {
+fn cursor-index _self: (addr word) -> _/eax: int {
   var self/esi: (addr word) <- copy _self
   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
   var data/eax: (addr gap-buffer) <- lookup *data-ah
-  result <- gap-index data
+  var result/eax: int <- gap-index data
+  return result
 }
 
 fn delete-before-cursor _self: (addr word) {
@@ -220,30 +227,29 @@ fn delete-before-cursor _self: (addr word) {
   delete-before-gap data
 }
 
-fn pop-after-cursor _self: (addr word) -> result/eax: grapheme {
+fn pop-after-cursor _self: (addr word) -> _/eax: grapheme {
   var self/esi: (addr word) <- copy _self
   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
   var data/eax: (addr gap-buffer) <- lookup *data-ah
-  result <- pop-after-gap data
+  var result/eax: grapheme <- pop-after-gap data
+  return result
 }
 
 fn delete-next _self: (addr word) {
-$delete-next:body: {
   var self/esi: (addr word) <- copy _self
   var next-ah/edi: (addr handle word) <- get self, next
   var next/eax: (addr word) <- lookup *next-ah
   compare next, 0
-  break-if-= $delete-next:body
+  break-if-=
   var next-next-ah/ecx: (addr handle word) <- get next, next
   var self-ah/esi: (addr handle word) <- get next, prev
   copy-object next-next-ah, next-ah
   var new-next/eax: (addr word) <- lookup *next-next-ah
   compare new-next, 0
-  break-if-= $delete-next:body
+  break-if-=
   var dest/eax: (addr handle word) <- get new-next, prev
   copy-object self-ah, dest
 }
-}
 
 fn print-word screen: (addr screen), _self: (addr word) {
   var self/esi: (addr word) <- copy _self
@@ -312,7 +318,6 @@ fn copy-words-in-reverse _src-ah: (addr handle word), _dest-ah: (addr handle wor
 }
 
 fn copy-word-at-end src: (addr word), _dest-ah: (addr handle word) {
-$copy-word-at-end:body: {
   var dest-ah/edi: (addr handle word) <- copy _dest-ah
   # if dest is null, copy and return
   var dest-a/eax: (addr word) <- lookup *dest-ah
@@ -320,7 +325,7 @@ $copy-word-at-end:body: {
   {
     break-if-!=
     copy-word src, dest-ah
-    break $copy-word-at-end:body
+    return
   }
   # copy current word
   var new: (handle word)
@@ -339,10 +344,8 @@ $copy-word-at-end:body: {
   }
   chain-words curr-ah, new-ah
 }
-}
 
 fn append-word-at-end-with _dest-ah: (addr handle word), s: (addr array byte) {
-$append-word-at-end-with:body: {
   var dest-ah/edi: (addr handle word) <- copy _dest-ah
   # if dest is null, copy and return
   var dest-a/eax: (addr word) <- lookup *dest-ah
@@ -350,7 +353,7 @@ $append-word-at-end-with:body: {
   {
     break-if-!=
     allocate-word-with dest-ah, s
-    break $append-word-at-end-with:body
+    return
   }
   # otherwise append at end
   var curr-ah/edi: (addr handle word) <- copy dest-ah
@@ -365,7 +368,6 @@ $append-word-at-end-with:body: {
   }
   append-word-with *curr-ah, s
 }
-}
 
 fn copy-word _src-a: (addr word), _dest-ah: (addr handle word) {
   var dest-ah/eax: (addr handle word) <- copy _dest-ah
@@ -511,37 +513,43 @@ fn word-to-string _self: (addr word), out: (addr handle array byte) {
   gap-buffer-to-string data, out
 }
 
-fn word-is-decimal-integer? _self: (addr word) -> result/eax: boolean {
+fn word-is-decimal-integer? _self: (addr word) -> _/eax: boolean {
   var self/eax: (addr word) <- copy _self
   var data-ah/eax: (addr handle gap-buffer) <- get self, scalar-data
   var data/eax: (addr gap-buffer) <- lookup *data-ah
-  result <- gap-buffer-is-decimal-integer? data
+  var result/eax: boolean <- gap-buffer-is-decimal-integer? data
+  return result
 }
 
 # ABSOLUTELY GHASTLY
-fn word-exists? _haystack-ah: (addr handle word), _needle: (addr word) -> result/ebx: boolean {
+fn word-exists? _haystack-ah: (addr handle word), _needle: (addr word) -> _/ebx: boolean {
   var needle-name-storage: (handle addr byte)
   var needle-name-ah/eax: (addr handle array byte) <- address needle-name-storage
   word-to-string _needle, needle-name-ah  # profligate leak
   var _needle-name/eax: (addr array byte) <- lookup *needle-name-ah
   var needle-name/edi: (addr array byte) <- copy _needle-name
   # base case
-  result <- copy 0   # false
   var haystack-ah/esi: (addr handle word) <- copy _haystack-ah
   var curr/eax: (addr word) <- lookup *haystack-ah
   compare curr, 0
-  break-if-=
+  {
+    break-if-!=
+    return 0  # false
+  }
   # check curr
   var curr-name-storage: (handle addr byte)
   var curr-name-ah/ecx: (addr handle array byte) <- address curr-name-storage
   word-to-string curr, curr-name-ah  # profligate leak
   var curr-name/eax: (addr array byte) <- lookup *curr-name-ah
   var found?/eax: boolean <- string-equal? needle-name, curr-name
-  result <- copy found?
-  compare result, 0
-  break-if-!=
+  compare found?, 0
+  {
+    break-if-=
+    return 1  # true
+  }
   # recurse
   var curr/eax: (addr word) <- lookup *haystack-ah
   var next-haystack-ah/eax: (addr handle word) <- get curr, next
-  result <- word-exists? next-haystack-ah, _needle
+  var result/ebx: boolean <- word-exists? next-haystack-ah, _needle
+  return result
 }