about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--callcc.mu6
-rw-r--r--channel.mu20
-rw-r--r--chessboard.mu312
-rw-r--r--console.mu2
-rw-r--r--counters.mu12
-rw-r--r--edit.mu1580
-rw-r--r--factorial.mu14
-rw-r--r--tangle.mu12
8 files changed, 978 insertions, 980 deletions
diff --git a/callcc.mu b/callcc.mu
index 5e8661bb..1bf32973 100644
--- a/callcc.mu
+++ b/callcc.mu
@@ -2,16 +2,16 @@
 
 recipe main [
   c:continuation <- f
-  continue-from c:continuation            # <-- ..when you hit this
+  continue-from c                         # <-- ..when you hit this
 ]
 
 recipe f [
   c:continuation <- g
-  reply c:continuation
+  reply c
 ]
 
 recipe g [
   c:continuation <- current-continuation  # <-- loop back to here
   $print 1
-  reply c:continuation  # threaded through unmodified after first iteration
+  reply c  # threaded through unmodified after first iteration
 ]
diff --git a/channel.mu b/channel.mu
index eb5b9641..ffa6d9f6 100644
--- a/channel.mu
+++ b/channel.mu
@@ -7,13 +7,13 @@ recipe producer [
   # n = 0
   n:number <- copy 0
   {
-    done?:boolean <- lesser-than n:number, 5
-    break-unless done?:boolean
+    done?:boolean <- lesser-than n, 5
+    break-unless done?
     # other threads might get between these prints
-    $print [produce: ], n:number, [ 
+    $print [produce: ], n, [ 
 ]
-    chan:address:channel <- write chan:address:channel, n:number
-    n:number <- add n:number, 1
+    chan:address:channel <- write chan, n
+    n <- add n, 1
     loop
   }
 ]
@@ -24,7 +24,7 @@ recipe consumer [
   chan:address:channel <- next-ingredient
   {
     # read an integer from the channel
-    n:number, chan:address:channel <- read chan:address:channel
+    n:number, chan:address:channel <- read chan
     # other threads might get between these prints
     $print [consume: ], n:number, [ 
 ]
@@ -36,8 +36,8 @@ recipe main [
   local-scope
   chan:address:channel <- new-channel 3
   # create two background 'routines' that communicate by a channel
-  routine1:number <- start-running producer:recipe, chan:address:channel
-  routine2:number <- start-running consumer:recipe, chan:address:channel
-  wait-for-routine routine1:number
-  wait-for-routine routine2:number
+  routine1:number <- start-running producer:recipe, chan
+  routine2:number <- start-running consumer:recipe, chan
+  wait-for-routine routine1
+  wait-for-routine routine2
 ]
diff --git a/chessboard.mu b/chessboard.mu
index 12c13417..d70c0544 100644
--- a/chessboard.mu
+++ b/chessboard.mu
@@ -38,7 +38,7 @@ scenario print-board-and-read-move [
 #?     $browse-trace #? 1
 #?     $close-trace #? 1
     # icon for the cursor
-    screen:address <- print-character screen:address, 9251/␣
+    screen <- print-character screen, 9251/␣
   ]
   screen-should-contain [
   #            1         2         3         4         5         6         7         8         9         10        11
@@ -74,39 +74,39 @@ recipe chessboard [
   local-scope
   screen:address <- next-ingredient
   console:address <- next-ingredient
-#?   $print [screen: ], screen:address, [, console: ], console:address, 10/newline
+#?   $print [screen: ], screen, [, console: ], console, 10/newline
   board:address:array:address:array:character <- initial-position
   # hook up stdin
   stdin:address:channel <- new-channel 10/capacity
-  start-running send-keys-to-channel:recipe, console:address, stdin:address:channel, screen:address
+  start-running send-keys-to-channel:recipe, console, stdin, screen
   # buffer lines in stdin
   buffered-stdin:address:channel <- new-channel 10/capacity
-  start-running buffer-lines:recipe, stdin:address:channel, buffered-stdin:address:channel
+  start-running buffer-lines:recipe, stdin, buffered-stdin
   {
     msg:address:array:character <- new [Stupid text-mode chessboard. White pieces in uppercase; black pieces in lowercase. No checking for legal moves.
 ]
-    print-string screen:address, msg:address:array:character
-    cursor-to-next-line screen:address
-    print-board screen:address, board:address:array:address:array:character
-    cursor-to-next-line screen:address
-    msg:address:array:character <- new [Type in your move as <from square>-<to square>. For example: 'a2-a4'. Then press <enter>.
+    print-string screen, msg
+    cursor-to-next-line screen
+    print-board screen, board
+    cursor-to-next-line screen
+    msg <- new [Type in your move as <from square>-<to square>. For example: 'a2-a4'. Then press <enter>.
 ]
-    print-string screen:address, msg:address:array:character
-    cursor-to-next-line screen:address
-    msg:address:array:character <- new [Hit 'q' to exit.
+    print-string screen, msg
+    cursor-to-next-line screen
+    msg <- new [Hit 'q' to exit.
 ]
-    print-string screen:address, msg:address:array:character
+    print-string screen, msg
     {
-      cursor-to-next-line screen:address
-      msg:address:array:character <- new [move: ]
-      print-string screen:address, msg:address:array:character
-      m:address:move, quit:boolean, error:boolean <- read-move buffered-stdin:address:channel, screen:address
-      break-if quit:boolean, +quit:offset
-      buffered-stdin:address:channel <- clear-channel buffered-stdin:address:channel  # cleanup after error. todo: test this?
-      loop-if error:boolean
+      cursor-to-next-line screen
+      msg <- new [move: ]
+      print-string screen, msg
+      m:address:move, quit:boolean, error:boolean <- read-move buffered-stdin, screen
+      break-if quit, +quit:label
+      buffered-stdin <- clear-channel buffered-stdin  # cleanup after error. todo: test this?
+      loop-if error
     }
-    board:address:array:address:array:character <- make-move board:address:array:address:array:character, m:address:move
-    clear-screen screen:address
+    board <- make-move board, m
+    clear-screen screen
     loop
   }
   +quit
@@ -118,40 +118,40 @@ recipe new-board [
   local-scope
   initial-position:address:array:number <- next-ingredient
   # assert(length(initial-position) == 64)
-  len:number <- length initial-position:address:array:number/lookup
-  correct-length?:boolean <- equal len:number, 64
-  assert correct-length?:boolean, [chessboard had incorrect size]
+  len:number <- length *initial-position
+  correct-length?:boolean <- equal len, 64
+  assert correct-length?, [chessboard had incorrect size]
   # board is an array of pointers to files; file is an array of characters
   board:address:array:address:array:character <- new location:type, 8
   col:number <- copy 0
   {
-    done?:boolean <- equal col:number, 8
-    break-if done?:boolean
-    file:address:address:array:character <- index-address board:address:array:address:array:character/lookup, col:number
-    file:address:address:array:character/lookup <- new-file initial-position:address:array:number, col:number
-    col:number <- add col:number, 1
+    done?:boolean <- equal col, 8
+    break-if done?
+    file:address:address:array:character <- index-address *board, col
+    *file <- new-file initial-position, col
+    col <- add col, 1
     loop
   }
-  reply board:address:array:address:array:character
+  reply board
 ]
 
 recipe new-file [
   local-scope
   position:address:array:number <- next-ingredient
   index:number <- next-ingredient
-  index:number <- multiply index:number, 8
+  index <- multiply index, 8
   result:address:array:character <- new character:type, 8
   row:number <- copy 0
   {
-    done?:boolean <- equal row:number, 8
-    break-if done?:boolean
-    dest:address:character <- index-address result:address:array:character/lookup, row:number
-    dest:address:character/lookup <- index position:address:array:number/lookup, index:number
-    row:number <- add row:number, 1
-    index:number <- add index:number, 1
+    done?:boolean <- equal row, 8
+    break-if done?
+    dest:address:character <- index-address *result, row
+    *dest <- index *position, index
+    row <- add row, 1
+    index <- add index, 1
     loop
   }
-  reply result:address:array:character
+  reply result
 ]
 
 recipe print-board [
@@ -160,42 +160,42 @@ recipe print-board [
   board:address:array:address:array:character <- next-ingredient
   row:number <- copy 7  # start printing from the top of the board
   # print each row
-#?   $print [printing board to screen ], screen:address, 10/newline
+#?   $print [printing board to screen ], screen, 10/newline
   {
-    done?:boolean <- lesser-than row:number, 0
-    break-if done?:boolean
-#?     $print [printing rank ], row:number, 10/newline
+    done?:boolean <- lesser-than row, 0
+    break-if done?
+#?     $print [printing rank ], row, 10/newline
     # print rank number as a legend
-    rank:number <- add row:number, 1
-    print-integer screen:address, rank:number
+    rank:number <- add row, 1
+    print-integer screen, rank
     s:address:array:character <- new [ | ]
-    print-string screen:address, s:address:array:character
+    print-string screen, s
     # print each square in the row
     col:number <- copy 0
     {
       done?:boolean <- equal col:number, 8
       break-if done?:boolean
-      f:address:array:character <- index board:address:array:address:array:character/lookup, col:number
-      c:character <- index f:address:array:character/lookup, row:number
-      print-character screen:address, c:character
-      print-character screen:address, 32/space
-      col:number <- add col:number, 1
+      f:address:array:character <- index *board, col
+      c:character <- index *f, row
+      print-character screen, c
+      print-character screen, 32/space
+      col <- add col, 1
       loop
     }
-    row:number <- subtract row:number, 1
-    cursor-to-next-line screen:address
+    row <- subtract row, 1
+    cursor-to-next-line screen
     loop
   }
   # print file letters as legend
 #?   $print [printing legend
 #? ] #? 1
-  s:address:array:character <- new [  +----------------]
-  print-string screen:address, s:address:array:character
-  screen:address <- cursor-to-next-line screen:address
-#?   screen:address <- print-character screen:address, 97 #? 1
-  s:address:array:character <- new [    a b c d e f g h]
-  screen:address <- print-string screen:address, s:address:array:character
-  screen:address <- cursor-to-next-line screen:address
+  s <- new [  +----------------]
+  print-string screen, s
+  screen <- cursor-to-next-line screen
+#?   screen <- print-character screen, 97 #? 1
+  s <- new [    a b c d e f g h]
+  screen <- print-string screen, s
+  screen <- cursor-to-next-line screen
 #?   $print [done printing board
 #? ] #? 1
 ]
@@ -221,8 +221,8 @@ recipe initial-position [
 #?       66/B, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 98/b,
 #?       78/N, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 110/n,
 #?       82/R, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 114/r
-  board:address:array:address:array:character <- new-board initial-position:address:array:number
-  reply board:address:array:address:array:character
+  board:address:array:address:array:character <- new-board initial-position
+  reply board
 ]
 
 scenario printing-the-board [
@@ -266,32 +266,32 @@ recipe read-move [
   stdin:address:channel <- next-ingredient
   screen:address <- next-ingredient
 #?   $print screen:address #? 1
-  from-file:number, quit?:boolean, error?:boolean <- read-file stdin:address:channel, screen:address
-  reply-if quit?:boolean, 0/dummy, quit?:boolean, error?:boolean
-  reply-if error?:boolean, 0/dummy, quit?:boolean, error?:boolean
+  from-file:number, quit?:boolean, error?:boolean <- read-file stdin, screen
+  reply-if quit?, 0/dummy, quit?, error?
+  reply-if error?, 0/dummy, quit?, error?
 #?   close-console #? 1
   # construct the move object
   result:address:move <- new move:type
-  x:address:number <- get-address result:address:move/lookup, from-file:offset
-  x:address:number/lookup <- copy from-file:number
-  x:address:number <- get-address result:address:move/lookup, from-rank:offset
-  x:address:number/lookup, quit?:boolean, error?:boolean <- read-rank stdin:address:channel, screen:address
-  reply-if quit?:boolean, 0/dummy, quit?:boolean, error?:boolean
-  reply-if error?:boolean, 0/dummy, quit?:boolean, error?:boolean
-  error?:boolean <- expect-from-channel stdin:address:channel, 45/dash, screen:address
-  reply-if error?:boolean, 0/dummy, 0/quit, error?:boolean
-  x:address:number <- get-address result:address:move/lookup, to-file:offset
-  x:address:number/lookup, quit?:boolean, error?:boolean <- read-file stdin:address:channel, screen:address
-  reply-if quit?:boolean, 0/dummy, quit?:boolean, error?:boolean
-  reply-if error?:boolean, 0/dummy, quit?:boolean, error?:boolean
-  x:address:number <- get-address result:address:move/lookup, to-rank:offset
-  x:address:number/lookup, quit?:boolean, error?:boolean <- read-rank stdin:address:channel, screen:address
+  x:address:number <- get-address *result, from-file:offset
+  *x <- copy from-file
+  x <- get-address *result, from-rank:offset
+  *x, quit?, error? <- read-rank stdin, screen
+  reply-if quit?, 0/dummy, quit?, error?
+  reply-if error?, 0/dummy, quit?, error?
+  error? <- expect-from-channel stdin, 45/dash, screen
+  reply-if error?, 0/dummy, 0/quit, error?
+  x <- get-address *result, to-file:offset
+  *x, quit?, error? <- read-file stdin, screen
   reply-if quit?:boolean, 0/dummy, quit?:boolean, error?:boolean
   reply-if error?:boolean, 0/dummy, quit?:boolean, error?:boolean
+  x:address:number <- get-address *result, to-rank:offset
+  *x, quit?, error? <- read-rank stdin, screen
+  reply-if quit?, 0/dummy, quit?, error?
+  reply-if error?, 0/dummy, quit?, error?
 #?   $exit #? 1
-  error?:boolean <- expect-from-channel stdin:address:channel, 10/newline, screen:address
-  reply-if error?:boolean, 0/dummy, 0/quit, error?:boolean
-  reply result:address:move, quit?:boolean, error?:boolean
+  error? <- expect-from-channel stdin, 10/newline, screen
+  reply-if error?, 0/dummy, 0/quit, error?
+  reply result, quit?, error?
 ]
 
 # file:number, quit:boolean, error:boolean <- read-file stdin:address:channel, screen:address
@@ -300,50 +300,50 @@ recipe read-file [
   local-scope
   stdin:address:channel <- next-ingredient
   screen:address <- next-ingredient
-  c:character, stdin:address:channel <- read stdin:address:channel
+  c:character, stdin <- read stdin
   {
-    q-pressed?:boolean <- equal c:character, 81/Q
-    break-unless q-pressed?:boolean
+    q-pressed?:boolean <- equal c, 81/Q
+    break-unless q-pressed?
     reply 0/dummy, 1/quit, 0/error
   }
   {
-    q-pressed?:boolean <- equal c:character, 113/q
-    break-unless q-pressed?:boolean
+    q-pressed? <- equal c, 113/q
+    break-unless q-pressed?
     reply 0/dummy, 1/quit, 0/error
   }
   {
-    empty-fake-keyboard?:boolean <- equal c:character, 0/eof
-    break-unless empty-fake-keyboard?:boolean
+    empty-fake-keyboard?:boolean <- equal c, 0/eof
+    break-unless empty-fake-keyboard?
     reply 0/dummy, 1/quit, 0/error
   }
   {
-    newline?:boolean <- equal c:character, 10/newline
-    break-unless newline?:boolean
+    newline?:boolean <- equal c, 10/newline
+    break-unless newline?
     error-message:address:array:character <- new [that's not enough]
-    print-string screen:address, error-message:address:array:character
+    print-string screen, error-message
     reply 0/dummy, 0/quit, 1/error
   }
-  file:number <- subtract c:character, 97/a
-#?   $print file:number, 10/newline
+  file:number <- subtract c, 97/a
+#?   $print file, 10/newline
   # 'a' <= file <= 'h'
   {
-    above-min:boolean <- greater-or-equal file:number, 0
-    break-if above-min:boolean
+    above-min:boolean <- greater-or-equal file, 0
+    break-if above-min
     error-message:address:array:character <- new [file too low: ]
-    print-string screen:address, error-message:address:array:character
-    print-character screen:address, c:character
-    cursor-to-next-line screen:address
+    print-string screen, error-message
+    print-character screen, c
+    cursor-to-next-line screen
     reply 0/dummy, 0/quit, 1/error
   }
   {
-    below-max:boolean <- lesser-than file:number, 8
-    break-if below-max:boolean
-    error-message:address:array:character <- new [file too high: ]
-    print-string screen:address, error-message:address:array:character
-    print-character screen:address, c:character
+    below-max:boolean <- lesser-than file, 8
+    break-if below-max
+    error-message <- new [file too high: ]
+    print-string screen, error-message
+    print-character screen, c
     reply 0/dummy, 0/quit, 1/error
   }
-  reply file:number, 0/quit, 0/error
+  reply file, 0/quit, 0/error
 ]
 
 # rank:number <- read-rank stdin:address:channel, screen:address
@@ -352,44 +352,44 @@ recipe read-rank [
   local-scope
   stdin:address:channel <- next-ingredient
   screen:address <- next-ingredient
-  c:character, stdin:address:channel <- read stdin:address:channel
+  c:character, stdin <- read stdin
   {
-    q-pressed?:boolean <- equal c:character, 8/Q
-    break-unless q-pressed?:boolean
+    q-pressed?:boolean <- equal c, 8/Q
+    break-unless q-pressed?
     reply 0/dummy, 1/quit, 0/error
   }
   {
-    q-pressed?:boolean <- equal c:character, 113/q
-    break-unless q-pressed?:boolean
+    q-pressed? <- equal c, 113/q
+    break-unless q-pressed?
     reply 0/dummy, 1/quit, 0/error
   }
   {
-    newline?:boolean <- equal c:character, 10  # newline
-    break-unless newline?:boolean
+    newline?:boolean <- equal c, 10  # newline
+    break-unless newline?
     error-message:address:array:character <- new [that's not enough]
-    print-string screen:address, error-message:address:array:character
+    print-string screen, error-message
     reply 0/dummy, 0/quit, 1/error
   }
-  rank:number <- subtract c:character, 49/'1'
-#?   $print rank:number, 10/newline
+  rank:number <- subtract c, 49/'1'
+#?   $print rank, 10/newline
   # assert'1' <= rank <= '8'
   {
-    above-min:boolean <- greater-or-equal rank:number, 0
-    break-if above-min:boolean
-    error-message:address:array:character <- new [rank too low: ]
-    print-string screen:address, error-message:address:array:character
-    print-character screen:address, c:character
+    above-min:boolean <- greater-or-equal rank, 0
+    break-if above-min
+    error-message <- new [rank too low: ]
+    print-string screen, error-message
+    print-character screen, c
     reply 0/dummy, 0/quit, 1/error
   }
   {
-    below-max:boolean <- lesser-or-equal rank:number, 7
-    break-if below-max:boolean
-    error-message:address:array:character <- new [rank too high: ]
-    print-string screen:address, error-message:address:array:character
-    print-character screen:address, c:character
+    below-max:boolean <- lesser-or-equal rank, 7
+    break-if below-max
+    error-message <- new [rank too high: ]
+    print-string screen, error-message
+    print-character screen, c
     reply 0/dummy, 0/quit, 1/error
   }
-  reply rank:number, 0/quit, 0/error
+  reply rank, 0/quit, 0/error
 ]
 
 # read a character from the given channel and check that it's what we expect
@@ -399,15 +399,15 @@ recipe expect-from-channel [
   stdin:address:channel <- next-ingredient
   expected:character <- next-ingredient
   screen:address <- next-ingredient
-  c:character, stdin:address:channel <- read stdin:address:channel
-  match?:boolean <- equal c:character, expected:character
+  c:character, stdin <- read stdin
   {
-    break-if match?:boolean
+    match?:boolean <- equal c, expected
+    break-if match?
     s:address:array:character <- new [expected character not found]
-    print-string screen:address, s:address:array:character
+    print-string screen, s
   }
-  result:boolean <- not match?:boolean
-  reply result:boolean
+  result:boolean <- not match?
+  reply result
 ]
 
 scenario read-move-blocking [
@@ -590,22 +590,22 @@ recipe make-move [
   local-scope
   b:address:array:address:array:character <- next-ingredient
   m:address:move <- next-ingredient
-  from-file:number <- get m:address:move/lookup, from-file:offset
-#?   $print from-file:number, 10/newline
-  from-rank:number <- get m:address:move/lookup, from-rank:offset
-#?   $print from-rank:number, 10/newline
-  to-file:number <- get m:address:move/lookup, to-file:offset
-#?   $print to-file:number, 10/newline
-  to-rank:number <- get m:address:move/lookup, to-rank:offset
-#?   $print to-rank:number, 10/newline
-  f:address:array:character <- index b:address:array:address:array:character/lookup, from-file:number
-  src:address:character/square <- index-address f:address:array:character/lookup, from-rank:number
-  f:address:array:character <- index b:address:array:address:array:character/lookup, to-file:number
-  dest:address:character/square <- index-address f:address:array:character/lookup, to-rank:number
-#?   $print src:address:character/lookup, 10/newline
-  dest:address:character/lookup/square <- copy src:address:character/lookup/square
-  src:address:character/lookup/square <- copy 32/space
-  reply b:address:array:address:array:character/same-as-ingredient:0
+  from-file:number <- get *m, from-file:offset
+#?   $print from-file, 10/newline
+  from-rank:number <- get *m, from-rank:offset
+#?   $print from-rank, 10/newline
+  to-file:number <- get *m, to-file:offset
+#?   $print to-file, 10/newline
+  to-rank:number <- get *m, to-rank:offset
+#?   $print to-rank, 10/newline
+  f:address:array:character <- index *b, from-file
+  src:address:character/square <- index-address *f, from-rank
+  f <- index *b, to-file
+  dest:address:character/square <- index-address *f, to-rank
+#?   $print *src, 10/newline
+  *dest <- copy *src
+  *src <- copy 32/space
+  reply b/same-as-ingredient:0
 ]
 
 scenario making-a-move [
@@ -613,14 +613,14 @@ scenario making-a-move [
   run [
     2:address:array:address:array:character/board <- initial-position
     3:address:move <- new move:type
-    4:address:number <- get-address 3:address:move/lookup, from-file:offset
-    4:address:number/lookup <- copy 6/g
-    5:address:number <- get-address 3:address:move/lookup, from-rank:offset
-    5:address:number/lookup <- copy 1/'2'
-    6:address:number <- get-address 3:address:move/lookup, to-file:offset
-    6:address:number/lookup <- copy 6/g
-    7:address:number <- get-address 3:address:move/lookup, to-rank:offset
-    7:address:number/lookup <- copy 3/'4'
+    4:address:number <- get-address *3:address:move, from-file:offset
+    *4:address:number <- copy 6/g
+    5:address:number <- get-address *3:address:move, from-rank:offset
+    *5:address:number <- copy 1/'2'
+    6:address:number <- get-address *3:address:move, to-file:offset
+    *6:address:number <- copy 6/g
+    7:address:number <- get-address *3:address:move, to-rank:offset
+    *7:address:number <- copy 3/'4'
     2:address:array:address:array:character/board <- make-move 2:address:array:address:array:character/board, 3:address:move
     screen:address <- print-board screen:address, 2:address:array:address:array:character/board
   ]
diff --git a/console.mu b/console.mu
index 0dd59212..a1bda1bc 100644
--- a/console.mu
+++ b/console.mu
@@ -6,7 +6,7 @@ recipe main [
   open-console
   {
     _, found?:boolean <- check-for-interaction
-    break-if found?:boolean
+    break-if found?
     print-character-to-display 97, 7/white
     loop
   }
diff --git a/counters.mu b/counters.mu
index 6428ff9b..be1f098a 100644
--- a/counters.mu
+++ b/counters.mu
@@ -4,14 +4,14 @@
 recipe new-counter [
   default-space:address:array:location <- new location:type, 30
   n:number <- next-ingredient
-  reply default-space:address:array:location
+  reply default-space
 ]
 
 recipe increment-counter [
   local-scope
   0:address:array:location/names:new-counter <- next-ingredient  # setup outer space; it *must* come from 'new-counter'
   x:number <- next-ingredient
-  n:number/space:1 <- add n:number/space:1, x:number
+  n:number/space:1 <- add n:number/space:1, x
   reply n:number/space:1
 ]
 
@@ -22,13 +22,13 @@ recipe main [
   # counter B
   b:address:array:location <- new-counter 23
   # increment both by 2 but in different ways
-  increment-counter a:address:array:location, 1
-  b-value:number <- increment-counter b:address:array:location, 2
-  a-value:number <- increment-counter a:address:array:location, 1
+  increment-counter a, 1
+  b-value:number <- increment-counter b, 2
+  a-value:number <- increment-counter a, 1
   # check results
   $print [Contents of counters
 ]
   # trailing space in next line is to help with syntax highlighting
-  $print [a: ], a-value:number, [ b: ], b-value:number, [ 
+  $print [a: ], a-value, [ b: ], b-value, [ 
 ]
 ]
diff --git a/edit.mu b/edit.mu
index a1e6408a..ae92a8d6 100644
--- a/edit.mu
+++ b/edit.mu
@@ -5,11 +5,11 @@ recipe main [
   open-console
   initial-recipe:address:array:character <- restore [recipes.mu]
   initial-sandbox:address:array:character <- new []
-  env:address:programming-environment-data <- new-programming-environment 0/screen, initial-recipe:address:array:character, initial-sandbox:address:array:character
-  env:address:programming-environment-data <- restore-sandboxes env:address:programming-environment-data
-  render-all 0/screen, env:address:programming-environment-data
+  env:address:programming-environment-data <- new-programming-environment 0/screen, initial-recipe, initial-sandbox
+  env <- restore-sandboxes env
+  render-all 0/screen, env
   show-screen 0/screen
-  event-loop 0/screen, 0/console, env:address:programming-environment-data
+  event-loop 0/screen, 0/console, env
   # never gets here
 ]
 
@@ -26,30 +26,30 @@ recipe new-programming-environment [
   screen:address <- next-ingredient
   initial-recipe-contents:address:array:character <- next-ingredient
   initial-sandbox-contents:address:array:character <- next-ingredient
-  width:number <- screen-width screen:address
-  height:number <- screen-height screen:address
+  width:number <- screen-width screen
+  height:number <- screen-height screen
   # top menu
   result:address:programming-environment-data <- new programming-environment-data:type
-  draw-horizontal screen:address, 0, 0/left, width:number, 32/space, 0/black, 238/grey
-  button-start:number <- subtract width:number, 20
-  button-on-screen?:boolean <- greater-or-equal button-start:number, 0
-  assert button-on-screen?:boolean, [screen too narrow for menu]
-  move-cursor screen:address, 0/row, button-start:number/column
+  draw-horizontal screen, 0, 0/left, width, 32/space, 0/black, 238/grey
+  button-start:number <- subtract width, 20
+  button-on-screen?:boolean <- greater-or-equal button-start, 0
+  assert button-on-screen?, [screen too narrow for menu]
+  move-cursor screen, 0/row, button-start
   run-button:address:array:character <- new [ run (F4) ]
-  print-string screen:address, run-button:address:array:character, 255/white, 161/reddish
+  print-string screen, run-button, 255/white, 161/reddish
   # dotted line down the middle
-  divider:number, _ <- divide-with-remainder width:number, 2
-  draw-vertical screen:address, divider:number, 1/top, height:number, 9482/vertical-dotted
+  divider:number, _ <- divide-with-remainder width, 2
+  draw-vertical screen, divider, 1/top, height, 9482/vertical-dotted
   # recipe editor on the left
-  recipes:address:address:editor-data <- get-address result:address:programming-environment-data/lookup, recipes:offset
-  recipes:address:address:editor-data/lookup <- new-editor initial-recipe-contents:address:array:character, screen:address, 0/left, divider:number/right
+  recipes:address:address:editor-data <- get-address *result, recipes:offset
+  *recipes <- new-editor initial-recipe-contents, screen, 0/left, divider/right
   # sandbox editor on the right
-  new-left:number <- add divider:number, 1
-  new-right:number <- add new-left:number, 5
-  current-sandbox:address:address:editor-data <- get-address result:address:programming-environment-data/lookup, current-sandbox:offset
-  current-sandbox:address:address:editor-data/lookup <- new-editor initial-sandbox-contents:address:array:character, screen:address, new-left:number, width:number
-  screen:address <- render-all screen:address, result:address:programming-environment-data
-  reply result:address:programming-environment-data
+  new-left:number <- add divider, 1
+  new-right:number <- add new-left, 5
+  current-sandbox:address:address:editor-data <- get-address *result, current-sandbox:offset
+  *current-sandbox <- new-editor initial-sandbox-contents, screen, new-left, width/right
+  screen <- render-all screen, result
+  reply result
 ]
 
 scenario editor-initially-prints-string-to-screen [
@@ -94,52 +94,52 @@ recipe new-editor [
   # no clipping of bounds
   left:number <- next-ingredient
   right:number <- next-ingredient
-  right:number <- subtract right:number, 1
+  right <- subtract right, 1
   result:address:editor-data <- new editor-data:type
   # initialize screen-related fields
-  x:address:number <- get-address result:address:editor-data/lookup, left:offset
-  x:address:number/lookup <- copy left:number
-  x:address:number <- get-address result:address:editor-data/lookup, right:offset
-  x:address:number/lookup <- copy right:number
+  x:address:number <- get-address *result, left:offset
+  *x <- copy left
+  x <- get-address *result, right:offset
+  *x <- copy right
   # initialize cursor
-  x:address:number <- get-address result:address:editor-data/lookup, cursor-row:offset
-  x:address:number/lookup <- copy 1/top
-  x:address:number <- get-address result:address:editor-data/lookup, cursor-column:offset
-  x:address:number/lookup <- copy left:number
-  init:address:address:duplex-list <- get-address result:address:editor-data/lookup, data:offset
-  init:address:address:duplex-list/lookup <- push-duplex 167/§, 0/tail
-  y:address:address:duplex-list <- get-address result:address:editor-data/lookup, before-cursor:offset
-  y:address:address:duplex-list/lookup <- copy init:address:address:duplex-list/lookup
+  x <- get-address *result, cursor-row:offset
+  *x <- copy 1/top
+  x <- get-address *result, cursor-column:offset
+  *x <- copy left
+  init:address:address:duplex-list <- get-address *result, data:offset
+  *init <- push-duplex 167/§, 0/tail
+  y:address:address:duplex-list <- get-address *result, before-cursor:offset
+  *y <- copy *init
   # early exit if s is empty
-  reply-unless s:address:array:character, result:address:editor-data
-  len:number <- length s:address:array:character/lookup
-  reply-unless len:number, result:address:editor-data
+  reply-unless s, result
+  len:number <- length *s
+  reply-unless len, result
   idx:number <- copy 0
   # now we can start appending the rest, character by character
-  curr:address:duplex-list <- copy init:address:address:duplex-list/lookup
+  curr:address:duplex-list <- copy *init
   {
-    done?:boolean <- greater-or-equal idx:number, len:number
-    break-if done?:boolean
-    c:character <- index s:address:array:character/lookup, idx:number
-    insert-duplex c:character, curr:address:duplex-list
+    done?:boolean <- greater-or-equal idx, len
+    break-if done?
+    c:character <- index *s, idx
+    insert-duplex c, curr
     # next iter
-    curr:address:duplex-list <- next-duplex curr:address:duplex-list
-    idx:number <- add idx:number, 1
+    curr <- next-duplex curr
+    idx <- add idx, 1
     loop
   }
   # initialize cursor to top of screen
-  y:address:address:duplex-list <- get-address result:address:editor-data/lookup, before-cursor:offset
-  y:address:address:duplex-list/lookup <- copy init:address:address:duplex-list/lookup
+  y <- get-address *result, before-cursor:offset
+  *y <- copy *init
   # initial render to screen, just for some old tests
-  _, screen:address <- render screen:address, result:address:editor-data
-  reply result:address:editor-data
+  _, screen <- render screen, result
+  reply result
 ]
 
 scenario editor-initializes-without-data [
   assume-screen 5/width, 3/height
   run [
     1:address:editor-data <- new-editor 0/data, screen:address, 2/left, 5/right
-    2:editor-data <- copy 1:address:editor-data/lookup
+    2:editor-data <- copy *1:address:editor-data
   ]
   memory-should-contain [
     # 2 (data) <- just the § sentinel
@@ -161,108 +161,108 @@ recipe render [
   local-scope
   screen:address <- next-ingredient
   editor:address:editor-data <- next-ingredient
-  reply-unless editor:address:editor-data, 1/top, screen:address/same-as-ingredient:0
-  left:number <- get editor:address:editor-data/lookup, left:offset
-  screen-height:number <- screen-height screen:address
-  right:number <- get editor:address:editor-data/lookup, right:offset
-  hide-screen screen:address
+  reply-unless editor, 1/top, screen/same-as-ingredient:0
+  left:number <- get *editor, left:offset
+  screen-height:number <- screen-height screen
+  right:number <- get *editor, right:offset
+  hide-screen screen
   # highlight mu code with color
   color:number <- copy 7/white
   highlighting-state:number <- copy 0/normal
   # traversing editor
-  curr:address:duplex-list <- get editor:address:editor-data/lookup, data:offset
-  prev:address:duplex-list <- copy curr:address:duplex-list
-  curr:address:duplex-list <- next-duplex curr:address:duplex-list
+  curr:address:duplex-list <- get *editor, data:offset
+  prev:address:duplex-list <- copy curr
+  curr <- next-duplex curr
   # traversing screen
   row:number <- copy 1/top
-  column:number <- copy left:number
-  cursor-row:address:number <- get-address editor:address:editor-data/lookup, cursor-row:offset
-  cursor-column:address:number <- get-address editor:address:editor-data/lookup, cursor-column:offset
-  before-cursor:address:address:duplex-list <- get-address editor:address:editor-data/lookup, before-cursor:offset
-  move-cursor screen:address, row:number, column:number
+  column:number <- copy left
+  cursor-row:address:number <- get-address *editor, cursor-row:offset
+  cursor-column:address:number <- get-address *editor, cursor-column:offset
+  before-cursor:address:address:duplex-list <- get-address *editor, before-cursor:offset
+  move-cursor screen, row, column
   {
     +next-character
-    break-unless curr:address:duplex-list
-    off-screen?:boolean <- greater-or-equal row:number, screen-height:number
-    break-if off-screen?:boolean
+    break-unless curr
+    off-screen?:boolean <- greater-or-equal row, screen-height
+    break-if off-screen?
     # update editor-data.before-cursor
     # Doing so at the start of each iteration ensures it stays one step behind
     # the current character.
     {
-      at-cursor-row?:boolean <- equal row:number, cursor-row:address:number/lookup
-      break-unless at-cursor-row?:boolean
-      at-cursor?:boolean <- equal column:number, cursor-column:address:number/lookup
-      break-unless at-cursor?:boolean
-      before-cursor:address:address:duplex-list/lookup <- prev-duplex curr:address:duplex-list
+      at-cursor-row?:boolean <- equal row, *cursor-row
+      break-unless at-cursor-row?
+      at-cursor?:boolean <- equal column, *cursor-column
+      break-unless at-cursor?
+      *before-cursor <- prev-duplex curr
     }
-    c:character <- get curr:address:duplex-list/lookup, value:offset
-    color:number, highlighting-state:number <- get-color color:number, highlighting-state:number, c:character
+    c:character <- get *curr, value:offset
+    color, highlighting-state <- get-color color, highlighting-state, c
     {
       # newline? move to left rather than 0
-      newline?:boolean <- equal c:character, 10/newline
-      break-unless newline?:boolean
+      newline?:boolean <- equal c, 10/newline
+      break-unless newline?
       # adjust cursor if necessary
       {
-        at-cursor-row?:boolean <- equal row:number, cursor-row:address:number/lookup
-        break-unless at-cursor-row?:boolean
-        left-of-cursor?:boolean <- lesser-than column:number, cursor-column:address:number/lookup
-        break-unless left-of-cursor?:boolean
-        cursor-column:address:number/lookup <- copy column:number
-        before-cursor:address:address:duplex-list/lookup <- prev-duplex curr:address:duplex-list
+        at-cursor-row? <- equal row, *cursor-row
+        break-unless at-cursor-row?
+        left-of-cursor?:boolean <- lesser-than column, *cursor-column
+        break-unless left-of-cursor?
+        *cursor-column <- copy column
+        *before-cursor <- prev-duplex curr
       }
       # clear rest of line in this window
-      clear-line-delimited screen:address, column:number, right:number
+      clear-line-delimited screen, column, right
       # skip to next line
-      row:number <- add row:number, 1
-      column:number <- copy left:number
-      move-cursor screen:address, row:number, column:number
-      curr:address:duplex-list <- next-duplex curr:address:duplex-list
-      prev:address:duplex-list <- next-duplex prev:address:duplex-list
+      row <- add row, 1
+      column <- copy left
+      move-cursor screen, row, column
+      curr <- next-duplex curr
+      prev <- next-duplex prev
       loop +next-character:label
     }
     {
       # at right? wrap. even if there's only one more letter left; we need
       # room for clicking on the cursor after it.
-      at-right?:boolean <- equal column:number, right:number
-      break-unless at-right?:boolean
+      at-right?:boolean <- equal column, right
+      break-unless at-right?
       # print wrap icon
-      print-character screen:address, 8617/loop-back-to-left, 245/grey
-      column:number <- copy left:number
-      row:number <- add row:number, 1
-      move-cursor screen:address, row:number, column:number
+      print-character screen, 8617/loop-back-to-left, 245/grey
+      column <- copy left
+      row <- add row, 1
+      move-cursor screen, row, column
       # don't increment curr
       loop +next-character:label
     }
-    print-character screen:address, c:character, color:number
-    curr:address:duplex-list <- next-duplex curr:address:duplex-list
-    prev:address:duplex-list <- next-duplex prev:address:duplex-list
-    column:number <- add column:number, 1
+    print-character screen, c, color
+    curr <- next-duplex curr
+    prev <- next-duplex prev
+    column <- add column, 1
     loop
   }
   # is cursor to the right of the last line? move to end
   {
-    at-cursor-row?:boolean <- equal row:number, cursor-row:address:number/lookup
-    cursor-outside-line?:boolean <- lesser-or-equal column:number, cursor-column:address:number/lookup
-    before-cursor-on-same-line?:boolean <- and at-cursor-row?:boolean, cursor-outside-line?:boolean
-    above-cursor-row?:boolean <- lesser-than row:number, cursor-row:address:number/lookup
-    before-cursor?:boolean <- or before-cursor-on-same-line?:boolean, above-cursor-row?:boolean
-    break-unless before-cursor?:boolean
-    cursor-row:address:number/lookup <- copy row:number
-    cursor-column:address:number/lookup <- copy column:number
+    at-cursor-row? <- equal row, *cursor-row
+    cursor-outside-line?:boolean <- lesser-or-equal column, *cursor-column
+    before-cursor-on-same-line?:boolean <- and at-cursor-row?, cursor-outside-line?
+    above-cursor-row?:boolean <- lesser-than row, *cursor-row
+    before-cursor?:boolean <- or before-cursor-on-same-line?, above-cursor-row?
+    break-unless before-cursor?
+    *cursor-row <- copy row
+    *cursor-column <- copy column
     # line not wrapped but cursor outside bounds? wrap cursor
     {
-      too-far-right?:boolean <- greater-than cursor-column:address:number/lookup, right:number
-      break-unless too-far-right?:boolean
-      cursor-column:address:number/lookup <- copy left:number
-      cursor-row:address:number/lookup <- add cursor-row:address:number/lookup, 1
-      above-screen-bottom?:boolean <- lesser-than cursor-row:address:number/lookup, screen-height:number
-      assert above-screen-bottom?:boolean, [unimplemented: wrapping cursor past bottom of screen]
+      too-far-right?:boolean <- greater-than *cursor-column, right
+      break-unless too-far-right?
+      *cursor-column <- copy left
+      *cursor-row <- add *cursor-row, 1
+      above-screen-bottom?:boolean <- lesser-than *cursor-row, screen-height
+      assert above-screen-bottom?, [unimplemented: wrapping cursor past bottom of screen]
     }
-    before-cursor:address:address:duplex-list/lookup <- copy prev:address:duplex-list
+    *before-cursor <- copy prev
   }
   # clear rest of current line
-  clear-line-delimited screen:address, column:number, right:number
-  reply row:number, screen:address/same-as-ingredient:0
+  clear-line-delimited screen, column, right
+  reply row, screen/same-as-ingredient:0
 ]
 
 # row:number, screen:address <- render-string screen:address, s:address:array:character, left:number, right:number, color:number, row:number
@@ -277,62 +277,62 @@ recipe render-string [
   right:number <- next-ingredient
   color:number <- next-ingredient
   row:number <- next-ingredient
-  row:number <- add row:number, 1
-  reply-unless s:address:array:character, row:number/same-as-ingredient:5, screen:address/same-as-ingredient:0
-  column:number <- copy left:number
-  move-cursor screen:address, row:number, column:number
-  screen-height:number <- screen-height screen:address
+  row <- add row, 1
+  reply-unless s, row/same-as-ingredient:5, screen/same-as-ingredient:0
+  column:number <- copy left
+  move-cursor screen, row, column
+  screen-height:number <- screen-height screen
   i:number <- copy 0
-  len:number <- length s:address:array:character/lookup
+  len:number <- length *s
   {
     +next-character
-    done?:boolean <- greater-or-equal i:number, len:number
-    break-if done?:boolean
-    done?:boolean <- greater-or-equal row:number, screen-height:number
-    break-if done?:boolean
-    c:character <- index s:address:array:character/lookup, i:number
+    done?:boolean <- greater-or-equal i, len
+    break-if done?
+    done? <- greater-or-equal row, screen-height
+    break-if done?
+    c:character <- index *s, i
     {
       # at right? wrap.
-      at-right?:boolean <- equal column:number, right:number
-      break-unless at-right?:boolean
+      at-right?:boolean <- equal column, right
+      break-unless at-right?
       # print wrap icon
-      print-character screen:address, 8617/loop-back-to-left, 245/grey
-      column:number <- copy left:number
-      row:number <- add row:number, 1
-      move-cursor screen:address, row:number, column:number
+      print-character screen, 8617/loop-back-to-left, 245/grey
+      column <- copy left
+      row <- add row, 1
+      move-cursor screen, row, column
       loop +next-character:label  # retry i
     }
-    i:number <- add i:number, 1
+    i <- add i, 1
     {
       # newline? move to left rather than 0
-      newline?:boolean <- equal c:character, 10/newline
-      break-unless newline?:boolean
+      newline?:boolean <- equal c, 10/newline
+      break-unless newline?
       # clear rest of line in this window
       {
-        done?:boolean <- greater-than column:number, right:number
-        break-if done?:boolean
-        print-character screen:address, 32/space
-        column:number <- add column:number, 1
+        done? <- greater-than column, right
+        break-if done?
+        print-character screen, 32/space
+        column <- add column, 1
         loop
       }
-      row:number <- add row:number, 1
-      column:number <- copy left:number
-      move-cursor screen:address, row:number, column:number
+      row <- add row, 1
+      column <- copy left
+      move-cursor screen, row, column
       loop +next-character:label
     }
-    print-character screen:address, c:character, color:number
-    column:number <- add column:number, 1
+    print-character screen, c, color
+    column <- add column, 1
     loop
   }
   {
     # clear rest of current line
-    line-done?:boolean <- greater-than column:number, right:number
-    break-if line-done?:boolean
-    print-character screen:address, 32/space
-    column:number <- add column:number, 1
+    line-done?:boolean <- greater-than column, right
+    break-if line-done?
+    print-character screen, 32/space
+    column <- add column, 1
     loop
   }
-  reply row:number/same-as-ingredient:5, screen:address/same-as-ingredient:0
+  reply row/same-as-ingredient:5, screen/same-as-ingredient:0
 ]
 
 # row:number, screen:address <- render-screen screen:address, sandbox-screen:address, left:number, right:number, row:number
@@ -345,63 +345,63 @@ recipe render-screen [
   left:number <- next-ingredient
   right:number <- next-ingredient
   row:number <- next-ingredient
-  row:number <- add row:number, 1
-  reply-unless s:address:screen, row:number/same-as-ingredient:4, screen:address/same-as-ingredient:0
+  row <- add row, 1
+  reply-unless s, row/same-as-ingredient:4, screen/same-as-ingredient:0
   # print 'screen:'
   header:address:array:character <- new [screen:]
-  row:number <- subtract row:number, 1  # compensate for render-string below
-  row:number <- render-string screen:address, header:address:array:character, left:number, right:number, 245/grey, row:number
+  row <- subtract row, 1  # compensate for render-string below
+  row <- render-string screen, header, left, right, 245/grey, row
   # newline
-  row:number <- add row:number, 1
-  move-cursor screen:address, row:number, left:number
+  row <- add row, 1
+  move-cursor screen, row, left
   # start printing s
-  column:number <- copy left:number
-  s-width:number <- screen-width s:address:screen
-  s-height:number <- screen-height s:address:screen
-  buf:address:array:screen-cell <- get s:address:screen/lookup, data:offset
-  stop-printing:number <- add left:number, s-width:number, 3
-  max-column:number <- min stop-printing:number, right:number
+  column:number <- copy left
+  s-width:number <- screen-width s
+  s-height:number <- screen-height s
+  buf:address:array:screen-cell <- get *s, data:offset
+  stop-printing:number <- add left, s-width, 3
+  max-column:number <- min stop-printing, right
   i:number <- copy 0
-  len:number <- length buf:address:array:screen-cell/lookup
-  screen-height:number <- screen-height screen:address
+  len:number <- length *buf
+  screen-height:number <- screen-height screen
   {
-    done?:boolean <- greater-or-equal i:number, len:number
-    break-if done?:boolean
-    done?:boolean <- greater-or-equal row:number, screen-height:number
-    break-if done?:boolean
-    column:number <- copy left:number
-    move-cursor screen:address, row:number, column:number
+    done?:boolean <- greater-or-equal i, len
+    break-if done?
+    done? <- greater-or-equal row, screen-height
+    break-if done?
+    column <- copy left
+    move-cursor screen, row, column
     # initial leader for each row: two spaces and a '.'
-    print-character screen:address, 32/space, 245/grey
-    print-character screen:address, 32/space, 245/grey
-    print-character screen:address, 46/full-stop, 245/grey
-    column:number <- add left:number, 3
+    print-character screen, 32/space, 245/grey
+    print-character screen, 32/space, 245/grey
+    print-character screen, 46/full-stop, 245/grey
+    column <- add left, 3
     {
       # print row
-      row-done?:boolean <- greater-or-equal column:number, max-column:number
-      break-if row-done?:boolean
-      curr:screen-cell <- index buf:address:array:screen-cell/lookup, i:number
-      c:character <- get curr:screen-cell, contents:offset
-      print-character screen:address, c:character, 245/grey
-      column:number <- add column:number, 1
-      i:number <- add i:number, 1
+      row-done?:boolean <- greater-or-equal column, max-column
+      break-if row-done?
+      curr:screen-cell <- index *buf, i
+      c:character <- get curr, contents:offset
+      print-character screen, c, 245/grey
+      column <- add column, 1
+      i <- add i, 1
       loop
     }
     # print final '.'
-    print-character screen:address, 46/full-stop, 245/grey
-    column:number <- add column:number, 1
+    print-character screen, 46/full-stop, 245/grey
+    column <- add column, 1
     {
       # clear rest of current line
-      line-done?:boolean <- greater-than column:number, right:number
-      break-if line-done?:boolean
-      print-character screen:address, 32/space
-      column:number <- add column:number, 1
+      line-done?:boolean <- greater-than column, right
+      break-if line-done?
+      print-character screen, 32/space
+      column <- add column, 1
       loop
     }
-    row:number <- add row:number, 1
+    row <- add row, 1
     loop
   }
-  reply row:number/same-as-ingredient:4, screen:address/same-as-ingredient:0
+  reply row/same-as-ingredient:4, screen/same-as-ingredient:0
 ]
 
 recipe clear-line-delimited [
@@ -409,12 +409,12 @@ recipe clear-line-delimited [
   screen:address <- next-ingredient
   left:number <- next-ingredient
   right:number <- next-ingredient
-  column:number <- copy left:number
+  column:number <- copy left
   {
-    done?:boolean <- greater-than column:number, right:number
-    break-if done?:boolean
-    print-character screen:address, 32/space
-    column:number <- add column:number, 1
+    done?:boolean <- greater-than column, right
+    break-if done?
+    print-character screen, 32/space
+    column <- add column, 1
     loop
   }
 ]
@@ -509,8 +509,8 @@ scenario editor-initializes-empty-text [
   run [
     1:address:array:character <- new []
     2:address:editor-data <- new-editor 1:address:array:character, screen:address, 0/left, 5/right
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   screen-should-contain [
     .     .
@@ -562,47 +562,47 @@ recipe get-color [
   color:number <- next-ingredient
   highlighting-state:number <- next-ingredient
   c:character <- next-ingredient
-  color-is-white?:boolean <- equal color:number, 7/white
-#?   $print [character: ], c:character, 10/newline #? 1
+  color-is-white?:boolean <- equal color, 7/white
+#?   $print [character: ], c, 10/newline #? 1
   # if color is white and next character is '#', switch color to blue
   {
-    break-unless color-is-white?:boolean
-    starting-comment?:boolean <- equal c:character, 35/#
-    break-unless starting-comment?:boolean
+    break-unless color-is-white?
+    starting-comment?:boolean <- equal c, 35/#
+    break-unless starting-comment?
 #?     $print [switch color back to blue], 10/newline #? 1
-    color:number <- copy 12/lightblue
+    color <- copy 12/lightblue
     jump +exit:label
   }
   # if color is blue and next character is newline, switch color to white
   {
-    color-is-blue?:boolean <- equal color:number, 12/lightblue
-    break-unless color-is-blue?:boolean
-    ending-comment?:boolean <- equal c:character, 10/newline
-    break-unless ending-comment?:boolean
+    color-is-blue?:boolean <- equal color, 12/lightblue
+    break-unless color-is-blue?
+    ending-comment?:boolean <- equal c, 10/newline
+    break-unless ending-comment?
 #?     $print [switch color back to white], 10/newline #? 1
-    color:number <- copy 7/white
+    color <- copy 7/white
     jump +exit:label
   }
   # if color is white (no comments) and next character is '<', switch color to red
   {
-    break-unless color-is-white?:boolean
-    starting-assignment?:boolean <- equal c:character, 60/<
-    break-unless starting-assignment?:boolean
-    color:number <- copy 1/red
+    break-unless color-is-white?
+    starting-assignment?:boolean <- equal c, 60/<
+    break-unless starting-assignment?
+    color <- copy 1/red
     jump +exit:label
   }
   # if color is red and next character is space, switch color to white
   {
-    color-is-red?:boolean <- equal color:number, 1/red
-    break-unless color-is-red?:boolean
-    ending-assignment?:boolean <- equal c:character, 32/space
-    break-unless ending-assignment?:boolean
-    color:number <- copy 7/white
+    color-is-red?:boolean <- equal color, 1/red
+    break-unless color-is-red?
+    ending-assignment?:boolean <- equal c, 32/space
+    break-unless ending-assignment?
+    color <- copy 7/white
     jump +exit:label
   }
   # otherwise no change
   +exit
-  reply color:number, highlighting-state:number
+  reply color, highlighting-state
 ]
 
 scenario render-colors-assignment [
@@ -636,78 +636,78 @@ recipe event-loop [
   screen:address <- next-ingredient
   console:address <- next-ingredient
   env:address:programming-environment-data <- next-ingredient
-  recipes:address:editor-data <- get env:address:programming-environment-data/lookup, recipes:offset
-  current-sandbox:address:editor-data <- get env:address:programming-environment-data/lookup, current-sandbox:offset
-  sandbox-in-focus?:address:boolean <- get-address env:address:programming-environment-data/lookup, sandbox-in-focus?:offset
+  recipes:address:editor-data <- get *env, recipes:offset
+  current-sandbox:address:editor-data <- get *env, current-sandbox:offset
+  sandbox-in-focus?:address:boolean <- get-address *env, sandbox-in-focus?:offset
   {
     # looping over each (keyboard or touch) event as it occurs
     +next-event
-    e:event, console:address, found?:boolean, quit?:boolean <- read-event console:address
-    loop-unless found?:boolean
-    break-if quit?:boolean  # only in tests
+    e:event, console, found?:boolean, quit?:boolean <- read-event console
+    loop-unless found?
+    break-if quit?  # only in tests
     trace [app], [next-event]
     # check for global events that will trigger regardless of which editor has focus
     {
       k:address:number <- maybe-convert e:event, keycode:variant
-      break-unless k:address:number
+      break-unless k
       # F4? load all code and run all sandboxes.
       {
-        do-run?:boolean <- equal k:address:number/lookup, 65532/F4
-        break-unless do-run?:boolean
-        run-sandboxes env:address:programming-environment-data
+        do-run?:boolean <- equal *k, 65532/F4
+        break-unless do-run?
+        run-sandboxes env
         # F4 might update warnings and results on both sides
-        screen:address <- render-all screen:address, env:address:programming-environment-data
-        update-cursor screen:address, recipes:address:editor-data, current-sandbox:address:editor-data, sandbox-in-focus?:address:boolean/lookup
-        show-screen screen:address
+        screen <- render-all screen, env
+        update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
+        show-screen screen
         loop +next-event:label
       }
     }
     {
       c:address:character <- maybe-convert e:event, text:variant
-      break-unless c:address:character
+      break-unless c
       # ctrl-n? - switch focus
       {
-        ctrl-n?:boolean <- equal c:address:character/lookup, 14/ctrl-n
-        break-unless ctrl-n?:boolean
-        sandbox-in-focus?:address:boolean/lookup <- not sandbox-in-focus?:address:boolean/lookup
-        update-cursor screen:address, recipes:address:editor-data, current-sandbox:address:editor-data, sandbox-in-focus?:address:boolean/lookup
-        show-screen screen:address
+        ctrl-n?:boolean <- equal *c, 14/ctrl-n
+        break-unless ctrl-n?
+        *sandbox-in-focus? <- not *sandbox-in-focus?
+        update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
+        show-screen screen
         loop +next-event:label
       }
     }
     # 'touch' event
     {
       t:address:touch-event <- maybe-convert e:event, touch:variant
-      break-unless t:address:touch-event
+      break-unless t
       # ignore all but 'left-click' events for now
       # todo: test this
-      touch-type:number <- get t:address:touch-event/lookup, type:offset
-      is-left-click?:boolean <- equal touch-type:number, 65513/mouse-left
-      loop-unless is-left-click?:boolean, +next-event:label
+      touch-type:number <- get *t, type:offset
+      is-left-click?:boolean <- equal touch-type, 65513/mouse-left
+      loop-unless is-left-click?, +next-event:label
       # on a sandbox delete icon? process delete
       {
-        was-delete?:boolean <- delete-sandbox t:address:touch-event/lookup, env:address:programming-environment-data
-        break-unless was-delete?:boolean
+        was-delete?:boolean <- delete-sandbox *t, env
+        break-unless was-delete?
 #?         trace [app], [delete clicked] #? 1
-        screen:address <- render-sandbox-side screen:address, env:address:programming-environment-data, 1/clear
-        update-cursor screen:address, recipes:address:editor-data, current-sandbox:address:editor-data, sandbox-in-focus?:address:boolean/lookup
-        show-screen screen:address
+        screen <- render-sandbox-side screen, env, 1/clear
+        update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
+        show-screen screen
         loop +next-event:label
       }
       # if not, send to both editors
-      _ <- move-cursor-in-editor screen:address, recipes:address:editor-data, t:address:touch-event/lookup
-      sandbox-in-focus?:address:boolean/lookup <- move-cursor-in-editor screen:address, current-sandbox:address:editor-data, t:address:touch-event/lookup
+      _ <- move-cursor-in-editor screen, recipes, *t
+      *sandbox-in-focus? <- move-cursor-in-editor screen, current-sandbox, *t
       jump +continue:label
     }
     # if it's not global, send to appropriate editor
     {
       {
-        break-if sandbox-in-focus?:address:boolean/lookup
-        handle-event screen:address, console:address, recipes:address:editor-data, e:event
+        break-if *sandbox-in-focus?
+        handle-event screen, console, recipes, e:event
       }
       {
-        break-unless sandbox-in-focus?:address:boolean/lookup
-        handle-event screen:address, console:address, current-sandbox:address:editor-data, e:event
+        break-unless *sandbox-in-focus?
+        handle-event screen, console, current-sandbox, e:event
       }
     }
     +continue
@@ -716,9 +716,9 @@ recipe event-loop [
     # they won't usually come fast enough to trigger this.
     # todo: test this
     {
-      more-events?:boolean <- has-more-events? console:address
-      break-if more-events?:boolean
-      render-minimal screen:address, env:address:programming-environment-data
+      more-events?:boolean <- has-more-events? console
+      break-if more-events?
+      render-minimal screen, env
     }
     loop
   }
@@ -733,27 +733,27 @@ recipe editor-event-loop [
   {
     # looping over each (keyboard or touch) event as it occurs
     +next-event
-    e:event, console:address, found?:boolean, quit?:boolean <- read-event console:address
-    loop-unless found?:boolean
-    break-if quit?:boolean  # only in tests
+    e:event, console:address, found?:boolean, quit?:boolean <- read-event console
+    loop-unless found?
+    break-if quit?  # only in tests
     trace [app], [next-event]
     # 'touch' event - send to both editors
     {
       t:address:touch-event <- maybe-convert e:event, touch:variant
-      break-unless t:address:touch-event
-      move-cursor-in-editor screen:address, editor:address:editor-data, t:address:touch-event/lookup
+      break-unless t
+      move-cursor-in-editor screen, editor, *t
       jump +continue:label
     }
     # other events - send to appropriate editor
-    handle-event screen:address, console:address, editor:address:editor-data, e:event
+    handle-event screen, console, editor, e:event
     +continue
-    row:number, screen:address <- render screen:address, editor:address:editor-data
+    row:number, screen <- render screen, editor
     # clear next line, in case we just processed a backspace
-    left:number <- get editor:address:editor-data/lookup, left:offset
-    right:number <- get editor:address:editor-data/lookup, right:offset
-    row:number <- add row:number, 1
-    move-cursor screen:address, row:number, left:number
-    clear-line-delimited screen:address, left:number, right:number
+    left:number <- get *editor, left:offset
+    right:number <- get *editor, right:offset
+    row <- add row, 1
+    move-cursor screen, row, left
+    clear-line-delimited screen, left, right
     loop
   }
 ]
@@ -764,185 +764,185 @@ recipe handle-event [
   console:address <- next-ingredient
   editor:address:editor-data <- next-ingredient
   e:event <- next-ingredient
-  reply-unless editor:address:editor-data
+  reply-unless editor
   # character
   {
     c:address:character <- maybe-convert e:event, text:variant
-    break-unless c:address:character
+    break-unless c
     ## check for special characters
     # backspace - delete character before cursor
     {
-      backspace?:boolean <- equal c:address:character/lookup, 8/backspace
-      break-unless backspace?:boolean
-      delete-before-cursor editor:address:editor-data
+      backspace?:boolean <- equal *c, 8/backspace
+      break-unless backspace?
+      delete-before-cursor editor
       reply
     }
     # ctrl-a - move cursor to start of line
     {
-      ctrl-a?:boolean <- equal c:address:character/lookup, 1/ctrl-a
-      break-unless ctrl-a?:boolean
-      move-to-start-of-line editor:address:editor-data
+      ctrl-a?:boolean <- equal *c, 1/ctrl-a
+      break-unless ctrl-a?
+      move-to-start-of-line editor
       reply
     }
     # ctrl-e - move cursor to end of line
     {
-      ctrl-e?:boolean <- equal c:address:character/lookup, 5/ctrl-e
-      break-unless ctrl-e?:boolean
-      move-to-end-of-line editor:address:editor-data
+      ctrl-e?:boolean <- equal *c, 5/ctrl-e
+      break-unless ctrl-e?
+      move-to-end-of-line editor
       reply
     }
     # ctrl-u - delete until start of line (excluding cursor)
     {
-      ctrl-u?:boolean <- equal c:address:character/lookup, 21/ctrl-u
-      break-unless ctrl-u?:boolean
-      delete-to-start-of-line editor:address:editor-data
+      ctrl-u?:boolean <- equal *c, 21/ctrl-u
+      break-unless ctrl-u?
+      delete-to-start-of-line editor
       reply
     }
     # ctrl-k - delete until end of line (including cursor)
     {
-      ctrl-k?:boolean <- equal c:address:character/lookup, 11/ctrl-k
-      break-unless ctrl-k?:boolean
-      delete-to-end-of-line editor:address:editor-data
+      ctrl-k?:boolean <- equal *c, 11/ctrl-k
+      break-unless ctrl-k?
+      delete-to-end-of-line editor
       reply
     }
     # tab - insert two spaces
     {
-      tab?:boolean <- equal c:address:character/lookup, 9/tab
+      tab?:boolean <- equal *c, 9/tab
       break-unless tab?:boolean
-      insert-at-cursor editor:address:editor-data, 32/space, screen:address
-      insert-at-cursor editor:address:editor-data, 32/space, screen:address
+      insert-at-cursor editor, 32/space, screen
+      insert-at-cursor editor, 32/space, screen
       reply
     }
     # otherwise type it in
-    insert-at-cursor editor:address:editor-data, c:address:character/lookup, screen:address
+    insert-at-cursor editor, *c, screen
     reply
   }
   # otherwise it's a special key
   k:address:number <- maybe-convert e:event, keycode:variant
-  assert k:address:number, [event was of unknown type; neither keyboard nor mouse]
-  d:address:duplex-list <- get editor:address:editor-data/lookup, data:offset
-  before-cursor:address:address:duplex-list <- get-address editor:address:editor-data/lookup, before-cursor:offset
-  cursor-row:address:number <- get-address editor:address:editor-data/lookup, cursor-row:offset
-  cursor-column:address:number <- get-address editor:address:editor-data/lookup, cursor-column:offset
-  screen-height:number <- screen-height screen:address
-  left:number <- get editor:address:editor-data/lookup, left:offset
-  right:number <- get editor:address:editor-data/lookup, right:offset
+  assert k, [event was of unknown type; neither keyboard nor mouse]
+  d:address:duplex-list <- get *editor, data:offset
+  before-cursor:address:address:duplex-list <- get-address *editor, before-cursor:offset
+  cursor-row:address:number <- get-address *editor, cursor-row:offset
+  cursor-column:address:number <- get-address *editor, cursor-column:offset
+  screen-height:number <- screen-height screen
+  left:number <- get *editor, left:offset
+  right:number <- get *editor, right:offset
   # arrows; update cursor-row and cursor-column, leave before-cursor to 'render'.
   # right arrow
   {
-    move-to-next-character?:boolean <- equal k:address:number/lookup, 65514/right-arrow
-    break-unless move-to-next-character?:boolean
+    move-to-next-character?:boolean <- equal *k, 65514/right-arrow
+    break-unless move-to-next-character?
     # if not at end of text
-    old-cursor:address:duplex-list <- next-duplex before-cursor:address:address:duplex-list/lookup
-    break-unless old-cursor:address:duplex-list
+    old-cursor:address:duplex-list <- next-duplex *before-cursor
+    break-unless old-cursor
     # scan to next character
-    before-cursor:address:address:duplex-list/lookup <- copy old-cursor:address:duplex-list
+    *before-cursor <- copy old-cursor
     # if crossed a newline, move cursor to start of next row
     {
-      old-cursor-character:character <- get before-cursor:address:address:duplex-list/lookup/lookup, value:offset
-      was-at-newline?:boolean <- equal old-cursor-character:character, 10/newline
-      break-unless was-at-newline?:boolean
-      cursor-row:address:number/lookup <- add cursor-row:address:number/lookup, 1
-      cursor-column:address:number/lookup <- copy left:number
+      old-cursor-character:character <- get **before-cursor, value:offset
+      was-at-newline?:boolean <- equal old-cursor-character, 10/newline
+      break-unless was-at-newline?
+      *cursor-row <- add *cursor-row, 1
+      *cursor-column <- copy left
       # todo: what happens when cursor is too far down?
-      screen-height:number <- screen-height screen:address
-      above-screen-bottom?:boolean <- lesser-than cursor-row:address:number/lookup, screen-height:number
-      assert above-screen-bottom?:boolean, [unimplemented: moving past bottom of screen]
+      screen-height <- screen-height screen
+      above-screen-bottom?:boolean <- lesser-than *cursor-row, screen-height
+      assert above-screen-bottom?, [unimplemented: moving past bottom of screen]
       reply
     }
     # if the line wraps, move cursor to start of next row
     {
       # if we're at the column just before the wrap indicator
-      wrap-column:number <- subtract right:number, 1
-      at-wrap?:boolean <- equal cursor-column:address:number/lookup, wrap-column:number
-      break-unless at-wrap?:boolean
+      wrap-column:number <- subtract right, 1
+      at-wrap?:boolean <- equal *cursor-column, wrap-column
+      break-unless at-wrap?
       # and if next character isn't newline
-      new-cursor:address:duplex-list <- next-duplex old-cursor:address:duplex-list
-      break-unless new-cursor:address:duplex-list
-      next-character:character <- get new-cursor:address:duplex-list/lookup, value:offset
-      newline?:boolean <- equal next-character:character, 10/newline
-      break-if newline?:boolean
-      cursor-row:address:number/lookup <- add cursor-row:address:number/lookup, 1
-      cursor-column:address:number/lookup <- copy left:number
+      new-cursor:address:duplex-list <- next-duplex old-cursor
+      break-unless new-cursor
+      next-character:character <- get *new-cursor, value:offset
+      newline?:boolean <- equal next-character, 10/newline
+      break-if newline?
+      *cursor-row <- add *cursor-row, 1
+      *cursor-column <- copy left
       # todo: what happens when cursor is too far down?
-      above-screen-bottom?:boolean <- lesser-than cursor-row:address:number/lookup, screen-height:number
-      assert above-screen-bottom?:boolean, [unimplemented: moving past bottom of screen]
+      above-screen-bottom?:boolean <- lesser-than *cursor-row, screen-height
+      assert above-screen-bottom?, [unimplemented: moving past bottom of screen]
       reply
     }
     # otherwise move cursor one character right
-    cursor-column:address:number/lookup <- add cursor-column:address:number/lookup, 1
+    *cursor-column <- add *cursor-column, 1
   }
   # left arrow
   {
-    move-to-previous-character?:boolean <- equal k:address:number/lookup, 65515/left-arrow
-    break-unless move-to-previous-character?:boolean
+    move-to-previous-character?:boolean <- equal *k, 65515/left-arrow
+    break-unless move-to-previous-character?
 #?     trace [app], [left arrow] #? 1
     # if not at start of text (before-cursor at § sentinel)
-    prev:address:duplex-list <- prev-duplex before-cursor:address:address:duplex-list/lookup
-    break-unless prev:address:duplex-list
+    prev:address:duplex-list <- prev-duplex *before-cursor
+    break-unless prev
     # if cursor not at left margin, move one character left
     {
-      at-left-margin?:boolean <- equal cursor-column:address:number/lookup, 0
-      break-if at-left-margin?:boolean
+      at-left-margin?:boolean <- equal *cursor-column, 0
+      break-if at-left-margin?
 #?       trace [app], [decrementing] #? 1
-      cursor-column:address:number/lookup <- subtract cursor-column:address:number/lookup, 1
+      *cursor-column <- subtract *cursor-column, 1
       reply
     }
     # if at left margin, there's guaranteed to be a previous line, since we're
     # not at start of text
     {
       # if before-cursor is at newline, figure out how long the previous line is
-      prevc:character <- get before-cursor:address:address:duplex-list/lookup/lookup, value:offset
-      previous-character-is-newline?:boolean <- equal prevc:character, 10/newline
-      break-unless previous-character-is-newline?:boolean
+      prevc:character <- get **before-cursor, value:offset
+      previous-character-is-newline?:boolean <- equal prevc, 10/newline
+      break-unless previous-character-is-newline?
 #?       trace [app], [previous line] #? 1
       # compute length of previous line
-      end-of-line:number <- previous-line-length before-cursor:address:address:duplex-list/lookup, d:address:duplex-list
-      cursor-row:address:number/lookup <- subtract cursor-row:address:number/lookup, 1
-      cursor-column:address:number/lookup <- copy end-of-line:number
+      end-of-line:number <- previous-line-length *before-cursor, d
+      *cursor-row <- subtract *cursor-row, 1
+      *cursor-column <- copy end-of-line
       reply
     }
     # if before-cursor is not at newline, we're just at a wrapped line
-    assert cursor-row:address:number/lookup, [unimplemented: moving cursor above top of screen]
-    cursor-row:address:number/lookup <- subtract cursor-row:address:number/lookup, 1
-    cursor-column:address:number/lookup <- subtract right:number, 1  # leave room for wrap icon
+    assert *cursor-row, [unimplemented: moving cursor above top of screen]
+    *cursor-row <- subtract *cursor-row, 1
+    *cursor-column <- subtract right, 1  # leave room for wrap icon
   }
   # down arrow
   {
-    move-to-next-line?:boolean <- equal k:address:number/lookup, 65516/down-arrow
-    break-unless move-to-next-line?:boolean
+    move-to-next-line?:boolean <- equal *k, 65516/down-arrow
+    break-unless move-to-next-line?
     # todo: support scrolling
-    already-at-bottom?:boolean <- greater-or-equal cursor-row:address:number/lookup, screen-height:number
-    break-if already-at-bottom?:boolean
+    already-at-bottom?:boolean <- greater-or-equal *cursor-row, screen-height
+    break-if already-at-bottom?
 #?     $print [moving down
 #? ] #? 1
-    cursor-row:address:number/lookup <- add cursor-row:address:number/lookup, 1
+    *cursor-row <- add *cursor-row, 1
     # that's it; render will adjust cursor-column as necessary
   }
   # up arrow
   {
-    move-to-previous-line?:boolean <- equal k:address:number/lookup, 65517/up-arrow
-    break-unless move-to-previous-line?:boolean
+    move-to-previous-line?:boolean <- equal *k, 65517/up-arrow
+    break-unless move-to-previous-line?
     # todo: support scrolling
-    already-at-top?:boolean <- lesser-or-equal cursor-row:address:number/lookup, 1/top
-    break-if already-at-top?:boolean
+    already-at-top?:boolean <- lesser-or-equal *cursor-row, 1/top
+    break-if already-at-top?
 #?     $print [moving up
 #? ] #? 1
-    cursor-row:address:number/lookup <- subtract cursor-row:address:number/lookup, 1
+    *cursor-row <- subtract *cursor-row, 1
     # that's it; render will adjust cursor-column as necessary
   }
   # home
   {
-    home?:boolean <- equal k:address:number/lookup, 65521/home
-    break-unless home?:boolean
-    move-to-start-of-line editor:address:editor-data
+    home?:boolean <- equal *k, 65521/home
+    break-unless home?
+    move-to-start-of-line editor
     reply
   }
   # end
   {
-    end?:boolean <- equal k:address:number/lookup, 65520/end
-    break-unless end?:boolean
-    move-to-end-of-line editor:address:editor-data
+    end?:boolean <- equal *k, 65520/end
+    break-unless end?
+    move-to-end-of-line editor
     reply
   }
 ]
@@ -954,19 +954,19 @@ recipe move-cursor-in-editor [
   screen:address <- next-ingredient
   editor:address:editor-data <- next-ingredient
   t:touch-event <- next-ingredient
-  reply-unless editor:address:editor-data, 0/false
-  click-column:number <- get t:touch-event, column:offset
-  left:number <- get editor:address:editor-data/lookup, left:offset
-  too-far-left?:boolean <- lesser-than click-column:number, left:number
-  reply-if too-far-left?:boolean, 0/false
-  right:number <- get editor:address:editor-data/lookup, right:offset
-  too-far-right?:boolean <- greater-than click-column:number, right:number
-  reply-if too-far-right?:boolean, 0/false
+  reply-unless editor, 0/false
+  click-column:number <- get t, column:offset
+  left:number <- get *editor, left:offset
+  too-far-left?:boolean <- lesser-than click-column, left
+  reply-if too-far-left?, 0/false
+  right:number <- get *editor, right:offset
+  too-far-right?:boolean <- greater-than click-column, right
+  reply-if too-far-right?, 0/false
   # update cursor
-  cursor-row:address:number <- get-address editor:address:editor-data/lookup, cursor-row:offset
-  cursor-row:address:number/lookup <- get t:touch-event, row:offset
-  cursor-column:address:number <- get-address editor:address:editor-data/lookup, cursor-column:offset
-  cursor-column:address:number/lookup <- get t:touch-event, column:offset
+  cursor-row:address:number <- get-address *editor, cursor-row:offset
+  *cursor-row <- get t, row:offset
+  cursor-column:address:number <- get-address *editor, cursor-column:offset
+  *cursor-column <- get t, column:offset
   # gain focus
   reply 1/true
 ]
@@ -976,33 +976,33 @@ recipe insert-at-cursor [
   editor:address:editor-data <- next-ingredient
   c:character <- next-ingredient
   screen:address <- next-ingredient
-#?   $print [insert ], c:character, 10/newline #? 1
-  before-cursor:address:address:duplex-list <- get-address editor:address:editor-data/lookup, before-cursor:offset
-  insert-duplex c:character, before-cursor:address:address:duplex-list/lookup
-  before-cursor:address:address:duplex-list/lookup <- next-duplex before-cursor:address:address:duplex-list/lookup
-  cursor-row:address:number <- get-address editor:address:editor-data/lookup, cursor-row:offset
-  cursor-column:address:number <- get-address editor:address:editor-data/lookup, cursor-column:offset
-  left:number <- get editor:address:editor-data/lookup, left:offset
-  right:number <- get editor:address:editor-data/lookup, right:offset
+#?   $print [insert ], c, 10/newline #? 1
+  before-cursor:address:address:duplex-list <- get-address *editor, before-cursor:offset
+  insert-duplex c, *before-cursor
+  *before-cursor <- next-duplex *before-cursor
+  cursor-row:address:number <- get-address *editor, cursor-row:offset
+  cursor-column:address:number <- get-address *editor, cursor-column:offset
+  left:number <- get *editor, left:offset
+  right:number <- get *editor, right:offset
   # update cursor: if newline, move cursor to start of next line
   # todo: bottom of screen
   {
-    newline?:boolean <- equal c:character, 10/newline
-    break-unless newline?:boolean
-    cursor-row:address:number/lookup <- add cursor-row:address:number/lookup, 1
-    cursor-column:address:number/lookup <- copy left:number
+    newline?:boolean <- equal c, 10/newline
+    break-unless newline?
+    *cursor-row <- add *cursor-row, 1
+    *cursor-column <- copy left
     # indent if necessary
 #?     $print [computing indent], 10/newline #? 1
-    d:address:duplex-list <- get editor:address:editor-data/lookup, data:offset
-    end-of-previous-line:address:duplex-list <- prev-duplex before-cursor:address:address:duplex-list/lookup
-    indent:number <- line-indent end-of-previous-line:address:duplex-list, d:address:duplex-list
-#?     $print indent:number, 10/newline #? 1
+    d:address:duplex-list <- get *editor, data:offset
+    end-of-previous-line:address:duplex-list <- prev-duplex *before-cursor
+    indent:number <- line-indent end-of-previous-line, d
+#?     $print indent, 10/newline #? 1
     i:number <- copy 0
     {
-      indent-done?:boolean <- greater-or-equal i:number, indent:number
-      break-if indent-done?:boolean
-      insert-at-cursor editor:address:editor-data, 32/space, screen:address
-      i:number <- add i:number, 1
+      indent-done?:boolean <- greater-or-equal i, indent
+      break-if indent-done?
+      insert-at-cursor editor, 32/space, screen
+      i <- add i, 1
       loop
     }
     reply
@@ -1010,42 +1010,42 @@ recipe insert-at-cursor [
   # if the line wraps at the cursor, move cursor to start of next row
   {
     # if we're at the column just before the wrap indicator
-    wrap-column:number <- subtract right:number, 1
-#?     $print [wrap? ], cursor-column:address:number/lookup, [ vs ], wrap-column:number, 10/newline
-    at-wrap?:boolean <- greater-or-equal cursor-column:address:number/lookup, wrap-column:number
-    break-unless at-wrap?:boolean
+    wrap-column:number <- subtract right, 1
+#?     $print [wrap? ], *cursor-column, [ vs ], wrap-column, 10/newline
+    at-wrap?:boolean <- greater-or-equal *cursor-column, wrap-column
+    break-unless at-wrap?
 #?     $print [wrap!
 #? ] #? 1
-    cursor-column:address:number/lookup <- subtract cursor-column:address:number/lookup, wrap-column:number
-    cursor-row:address:number/lookup <- add cursor-row:address:number/lookup, 1
+    *cursor-column <- subtract *cursor-column, wrap-column
+    *cursor-row <- add *cursor-row, 1
     # todo: what happens when cursor is too far down?
-    screen-height:number <- screen-height screen:address
-    above-screen-bottom?:boolean <- lesser-than cursor-row:address:number/lookup, screen-height:number
-    assert above-screen-bottom?:boolean, [unimplemented: typing past bottom of screen]
+    screen-height:number <- screen-height screen
+    above-screen-bottom?:boolean <- lesser-than *cursor-row, screen-height
+    assert above-screen-bottom?, [unimplemented: typing past bottom of screen]
 #?     $print [return
 #? ] #? 1
     reply
   }
   # otherwise move cursor right
-  cursor-column:address:number/lookup <- add cursor-column:address:number/lookup, 1
+  *cursor-column <- add *cursor-column, 1
 ]
 
 recipe delete-before-cursor [
   local-scope
   editor:address:editor-data <- next-ingredient
-  before-cursor:address:address:duplex-list <- get-address editor:address:editor-data/lookup, before-cursor:offset
-  d:address:duplex-list <- get editor:address:editor-data/lookup, data:offset
+  before-cursor:address:address:duplex-list <- get-address *editor:address:editor-data, before-cursor:offset
+  d:address:duplex-list <- get *editor:address:editor-data, data:offset
   # unless already at start
-  at-start?:boolean <- equal before-cursor:address:address:duplex-list/lookup, d:address:duplex-list
+  at-start?:boolean <- equal *before-cursor:address:address:duplex-list, d:address:duplex-list
   reply-if at-start?:boolean
   # delete character
-  prev:address:duplex-list <- prev-duplex before-cursor:address:address:duplex-list/lookup
-  remove-duplex before-cursor:address:address:duplex-list/lookup
+  prev:address:duplex-list <- prev-duplex *before-cursor:address:address:duplex-list
+  remove-duplex *before-cursor:address:address:duplex-list
   # update cursor
-  before-cursor:address:address:duplex-list/lookup <- copy prev:address:duplex-list
-  cursor-column:address:number <- get-address editor:address:editor-data/lookup, cursor-column:offset
-  cursor-column:address:number/lookup <- subtract cursor-column:address:number/lookup, 1
-#?   $print [delete-before-cursor: ], cursor-column:address:number/lookup, 10/newline
+  *before-cursor:address:address:duplex-list <- copy prev:address:duplex-list
+  cursor-column:address:number <- get-address *editor:address:editor-data, cursor-column:offset
+  *cursor-column:address:number <- subtract *cursor-column:address:number, 1
+#?   $print [delete-before-cursor: ], *cursor-column:address:number, 10/newline
 ]
 
 # takes a pointer 'curr' into the doubly-linked list and its sentinel, counts
@@ -1055,21 +1055,21 @@ recipe previous-line-length [
   curr:address:duplex-list <- next-ingredient
   start:address:duplex-list <- next-ingredient
   result:number <- copy 0
-  reply-unless curr:address:duplex-list, result:number
-  at-start?:boolean <- equal curr:address:duplex-list, start:address:duplex-list
-  reply-if at-start?:boolean, result:number
+  reply-unless curr, result
+  at-start?:boolean <- equal curr, start
+  reply-if at-start?, result
   {
-    curr:address:duplex-list <- prev-duplex curr:address:duplex-list
-    break-unless curr:address:duplex-list
-    at-start?:boolean <- equal curr:address:duplex-list, start:address:duplex-list
-    break-if at-start?:boolean
-    c:character <- get curr:address:duplex-list/lookup, value:offset
-    at-newline?:boolean <- equal c:character 10/newline
-    break-if at-newline?:boolean
-    result:number <- add result:number, 1
+    curr <- prev-duplex curr
+    break-unless curr
+    at-start?:boolean <- equal curr, start
+    break-if at-start?
+    c:character <- get *curr, value:offset
+    at-newline?:boolean <- equal c, 10/newline
+    break-if at-newline?
+    result <- add result, 1
     loop
   }
-  reply result:number
+  reply result
 ]
 
 # takes a pointer 'curr' into the doubly-linked list and its sentinel, counts
@@ -1079,57 +1079,57 @@ recipe line-indent [
   curr:address:duplex-list <- next-ingredient
   start:address:duplex-list <- next-ingredient
   result:number <- copy 0
-  reply-unless curr:address:duplex-list, result:number
+  reply-unless curr, result
 #?   $print [a0], 10/newline #? 1
-  at-start?:boolean <- equal curr:address:duplex-list, start:address:duplex-list
-  reply-if at-start?:boolean, result:number
+  at-start?:boolean <- equal curr, start
+  reply-if at-start?, result
 #?   $print [a1], 10/newline #? 1
   {
-    curr:address:duplex-list <- prev-duplex curr:address:duplex-list
-    break-unless curr:address:duplex-list
+    curr <- prev-duplex curr
+    break-unless curr
 #?   $print [a2], 10/newline #? 1
-    at-start?:boolean <- equal curr:address:duplex-list, start:address:duplex-list
-    break-if at-start?:boolean
+    at-start?:boolean <- equal curr, start
+    break-if at-start?
 #?   $print [a3], 10/newline #? 1
-    c:character <- get curr:address:duplex-list/lookup, value:offset
-    at-newline?:boolean <- equal c:character, 10/newline
-    break-if at-newline?:boolean
+    c:character <- get *curr, value:offset
+    at-newline?:boolean <- equal c, 10/newline
+    break-if at-newline?
 #?   $print [a4], 10/newline #? 1
     # if c is a space, increment result
-    is-space?:boolean <- equal c:character, 32/space
+    is-space?:boolean <- equal c, 32/space
     {
-      break-unless is-space?:boolean
-      result:number <- add result:number, 1
+      break-unless is-space?
+      result <- add result, 1
     }
     # if c is not a space, reset result
     {
-      break-if is-space?:boolean
-      result:number <- copy 0
+      break-if is-space?
+      result <- copy 0
     }
     loop
   }
-  reply result:number
+  reply result
 ]
 
 recipe move-to-start-of-line [
   local-scope
   editor:address:editor-data <- next-ingredient
   # update cursor column
-  left:number <- get editor:address:editor-data/lookup, left:offset
-  cursor-column:address:number <- get-address editor:address:editor-data/lookup, cursor-column:offset
-  cursor-column:address:number/lookup <- copy left:number
+  left:number <- get *editor, left:offset
+  cursor-column:address:number <- get-address *editor, cursor-column:offset
+  *cursor-column <- copy left
   # update before-cursor
-  before-cursor:address:address:duplex-list <- get-address editor:address:editor-data/lookup, before-cursor:offset
-  init:address:duplex-list <- get editor:address:editor-data/lookup, data:offset
+  before-cursor:address:address:duplex-list <- get-address *editor, before-cursor:offset
+  init:address:duplex-list <- get *editor, data:offset
   # while not at start of line, move 
   {
-    at-start-of-text?:boolean <- equal before-cursor:address:address:duplex-list/lookup, init:address:duplex-list
-    break-if at-start-of-text?:boolean
-    prev:character <- get before-cursor:address:address:duplex-list/lookup/lookup, value:offset
-    at-start-of-line?:boolean <- equal prev:character, 10/newline
-    break-if at-start-of-line?:boolean
-    before-cursor:address:address:duplex-list/lookup <- prev-duplex before-cursor:address:address:duplex-list/lookup
-    assert before-cursor:address:address:duplex-list/lookup, [move-to-start-of-line tried to move before start of text]
+    at-start-of-text?:boolean <- equal *before-cursor, init
+    break-if at-start-of-text?
+    prev:character <- get **before-cursor, value:offset
+    at-start-of-line?:boolean <- equal prev, 10/newline
+    break-if at-start-of-line?
+    *before-cursor <- prev-duplex *before-cursor
+    assert *before-cursor, [move-to-start-of-line tried to move before start of text]
     loop
   }
 ]
@@ -1137,75 +1137,75 @@ recipe move-to-start-of-line [
 recipe move-to-end-of-line [
   local-scope
   editor:address:editor-data <- next-ingredient
-  before-cursor:address:address:duplex-list <- get-address editor:address:editor-data/lookup, before-cursor:offset
-  cursor-column:address:number <- get-address editor:address:editor-data/lookup, cursor-column:offset
+  before-cursor:address:address:duplex-list <- get-address *editor, before-cursor:offset
+  cursor-column:address:number <- get-address *editor, cursor-column:offset
   # while not at start of line, move 
   {
-    next:address:duplex-list <- next-duplex before-cursor:address:address:duplex-list/lookup
-    break-unless next:address:duplex-list  # end of text
-    nextc:character <- get next:address:duplex-list/lookup, value:offset
-    at-end-of-line?:boolean <- equal nextc:character, 10/newline
-    break-if at-end-of-line?:boolean
-    before-cursor:address:address:duplex-list/lookup <- copy next:address:duplex-list
-    cursor-column:address:number/lookup <- add cursor-column:address:number/lookup, 1
+    next:address:duplex-list <- next-duplex *before-cursor
+    break-unless next  # end of text
+    nextc:character <- get *next, value:offset
+    at-end-of-line?:boolean <- equal nextc, 10/newline
+    break-if at-end-of-line?
+    *before-cursor <- copy next
+    *cursor-column <- add *cursor-column, 1
     loop
   }
-  # move one past end of line
-  cursor-column:address:number/lookup <- add cursor-column:address:number/lookup, 1
+  # move one past final character
+  *cursor-column <- add *cursor-column, 1
 ]
 
 recipe delete-to-start-of-line [
   local-scope
   editor:address:editor-data <- next-ingredient
   # compute range to delete
-  init:address:duplex-list <- get editor:address:editor-data/lookup, data:offset
-  before-cursor:address:address:duplex-list <- get-address editor:address:editor-data/lookup, before-cursor:offset
-  start:address:duplex-list <- copy before-cursor:address:address:duplex-list/lookup
-  end:address:duplex-list <- next-duplex before-cursor:address:address:duplex-list/lookup
+  init:address:duplex-list <- get *editor, data:offset
+  before-cursor:address:address:duplex-list <- get-address *editor, before-cursor:offset
+  start:address:duplex-list <- copy *before-cursor
+  end:address:duplex-list <- next-duplex *before-cursor
   {
-    at-start-of-text?:boolean <- equal start:address:duplex-list, init:address:duplex-list
-    break-if at-start-of-text?:boolean
-    curr:character <- get start:address:duplex-list/lookup, value:offset
-    at-start-of-line?:boolean <- equal curr:character, 10/newline
-    break-if at-start-of-line?:boolean
-    start:address:duplex-list <- prev-duplex start:address:duplex-list
-    assert start:address:duplex-list, [delete-to-start-of-line tried to move before start of text]
+    at-start-of-text?:boolean <- equal start, init
+    break-if at-start-of-text?
+    curr:character <- get *start, value:offset
+    at-start-of-line?:boolean <- equal curr, 10/newline
+    break-if at-start-of-line?
+    start <- prev-duplex start
+    assert start, [delete-to-start-of-line tried to move before start of text]
     loop
   }
   # snip it out
-  start-next:address:address:duplex-list <- get-address start:address:duplex-list/lookup, next:offset
-  start-next:address:address:duplex-list/lookup <- copy end:address:duplex-list
-  end-prev:address:address:duplex-list <- get-address end:address:duplex-list/lookup, prev:offset
-  end-prev:address:address:duplex-list/lookup <- copy start:address:duplex-list
+  start-next:address:address:duplex-list <- get-address *start, next:offset
+  *start-next <- copy end
+  end-prev:address:address:duplex-list <- get-address *end, prev:offset
+  *end-prev <- copy start
   # adjust cursor
-  before-cursor:address:address:duplex-list/lookup <- prev-duplex end:address:duplex-list
-  left:number <- get editor:address:editor-data/lookup, left:offset
-  cursor-column:address:number <- get-address editor:address:editor-data/lookup, cursor-column:offset
-  cursor-column:address:number/lookup <- copy left:number
+  *before-cursor <- prev-duplex end
+  left:number <- get *editor, left:offset
+  cursor-column:address:number <- get-address *editor, cursor-column:offset
+  *cursor-column <- copy left
 ]
 
 recipe delete-to-end-of-line [
   local-scope
   editor:address:editor-data <- next-ingredient
   # compute range to delete
-  start:address:duplex-list <- get editor:address:editor-data/lookup, before-cursor:offset
-  end:address:duplex-list <- next-duplex start:address:duplex-list
+  start:address:duplex-list <- get *editor, before-cursor:offset
+  end:address:duplex-list <- next-duplex start
   {
-    at-end-of-text?:boolean <- equal end:address:duplex-list, 0/null
-    break-if at-end-of-text?:boolean
-    curr:character <- get end:address:duplex-list/lookup, value:offset
-    at-end-of-line?:boolean <- equal curr:character, 10/newline
-    break-if at-end-of-line?:boolean
-    end:address:duplex-list <- next-duplex end:address:duplex-list
+    at-end-of-text?:boolean <- equal end, 0/null
+    break-if at-end-of-text?
+    curr:character <- get *end, value:offset
+    at-end-of-line?:boolean <- equal curr, 10/newline
+    break-if at-end-of-line?
+    end <- next-duplex end
     loop
   }
   # snip it out
-  start-next:address:address:duplex-list <- get-address start:address:duplex-list/lookup, next:offset
-  start-next:address:address:duplex-list/lookup <- copy end:address:duplex-list
+  start-next:address:address:duplex-list <- get-address *start, next:offset
+  *start-next <- copy end
   {
-    break-unless end:address:duplex-list
-    end-prev:address:address:duplex-list <- get-address end:address:duplex-list/lookup, prev:offset
-    end-prev:address:address:duplex-list/lookup <- copy start:address:duplex-list
+    break-unless end
+    end-prev:address:address:duplex-list <- get-address *end, prev:offset
+    *end-prev <- copy start
   }
 ]
 
@@ -1213,38 +1213,38 @@ recipe render-all [
   local-scope
   screen:address <- next-ingredient
   env:address:programming-environment-data <- next-ingredient
-  screen:address <- render-recipes screen:address, env:address:programming-environment-data, 1/clear-below
-  screen:address <- render-sandbox-side screen:address, env:address:programming-environment-data, 1/clear-below
-  recipes:address:editor-data <- get env:address:programming-environment-data/lookup, recipes:offset
-  current-sandbox:address:editor-data <- get env:address:programming-environment-data/lookup, current-sandbox:offset
-  sandbox-in-focus?:boolean <- get env:address:programming-environment-data/lookup, sandbox-in-focus?:offset
-  update-cursor screen:address, recipes:address:editor-data, current-sandbox:address:editor-data, sandbox-in-focus?:boolean
-  show-screen screen:address
-  reply screen:address/same-as-ingredient:0
+  screen <- render-recipes screen, env, 1/clear-below
+  screen <- render-sandbox-side screen, env, 1/clear-below
+  recipes:address:editor-data <- get *env, recipes:offset
+  current-sandbox:address:editor-data <- get *env, current-sandbox:offset
+  sandbox-in-focus?:boolean <- get *env, sandbox-in-focus?:offset
+  update-cursor screen, recipes, current-sandbox, sandbox-in-focus?
+  show-screen screen
+  reply screen/same-as-ingredient:0
 ]
 
 recipe render-minimal [
   local-scope
   screen:address <- next-ingredient
   env:address:programming-environment-data <- next-ingredient
-  recipes:address:editor-data <- get env:address:programming-environment-data/lookup, recipes:offset
-  current-sandbox:address:editor-data <- get env:address:programming-environment-data/lookup, current-sandbox:offset
-  sandbox-in-focus?:boolean <- get env:address:programming-environment-data/lookup, sandbox-in-focus?:offset
+  recipes:address:editor-data <- get *env, recipes:offset
+  current-sandbox:address:editor-data <- get *env, current-sandbox:offset
+  sandbox-in-focus?:boolean <- get *env, sandbox-in-focus?:offset
   {
-    break-if sandbox-in-focus?:boolean
-    screen:address <- render-recipes screen:address, env:address:programming-environment-data
-    cursor-row:number <- get recipes:address:editor-data/lookup, cursor-row:offset
-    cursor-column:number <- get recipes:address:editor-data/lookup, cursor-column:offset
+    break-if sandbox-in-focus?
+    screen <- render-recipes screen, env
+    cursor-row:number <- get *recipes, cursor-row:offset
+    cursor-column:number <- get *recipes, cursor-column:offset
   }
   {
-    break-unless sandbox-in-focus?:boolean
-    screen:address <- render-sandbox-side screen:address, env:address:programming-environment-data
-    cursor-row:number <- get current-sandbox:address:editor-data/lookup, cursor-row:offset
-    cursor-column:number <- get current-sandbox:address:editor-data/lookup, cursor-column:offset
+    break-unless sandbox-in-focus?
+    screen <- render-sandbox-side screen, env
+    cursor-row:number <- get *current-sandbox, cursor-row:offset
+    cursor-column:number <- get *current-sandbox, cursor-column:offset
   }
-  move-cursor screen:address, cursor-row:number, cursor-column:number
-  show-screen screen:address
-  reply screen:address/same-as-ingredient:0
+  move-cursor screen, cursor-row, cursor-column
+  show-screen screen
+  reply screen/same-as-ingredient:0
 ]
 
 recipe render-recipes [
@@ -1252,40 +1252,40 @@ recipe render-recipes [
   screen:address <- next-ingredient
   env:address:programming-environment-data <- next-ingredient
   clear:boolean <- next-ingredient
-  recipes:address:editor-data <- get env:address:programming-environment-data/lookup, recipes:offset
+  recipes:address:editor-data <- get *env, recipes:offset
   # render recipes
-  left:number <- get recipes:address:editor-data/lookup, left:offset
-  right:number <- get recipes:address:editor-data/lookup, right:offset
-  row:number, screen:address <- render screen:address, recipes:address:editor-data
-  recipe-warnings:address:array:character <- get env:address:programming-environment-data/lookup, recipe-warnings:offset
+  left:number <- get *recipes, left:offset
+  right:number <- get *recipes, right:offset
+  row:number, screen <- render screen, recipes
+  recipe-warnings:address:array:character <- get *env, recipe-warnings:offset
   {
     # print any warnings
-    break-unless recipe-warnings:address:array:character
-    row:number, screen:address <- render-string screen:address, recipe-warnings:address:array:character, left:number, right:number, 1/red, row:number
+    break-unless recipe-warnings
+    row, screen <- render-string screen, recipe-warnings, left, right, 1/red, row
   }
   {
     # no warnings? move to next line
-    break-if recipe-warnings:address:array:character
-    row:number <- add row:number, 1
+    break-if recipe-warnings
+    row <- add row, 1
   }
   # draw dotted line after recipes
-  draw-horizontal screen:address, row:number, left:number, right:number, 9480/horizontal-dotted
+  draw-horizontal screen, row, left, right, 9480/horizontal-dotted
   # clear next line, in case we just processed a backspace
-  row:number <- add row:number, 1
-  move-cursor screen:address, row:number, left:number
-  clear-line-delimited screen:address, left:number, right:number
+  row <- add row, 1
+  move-cursor screen, row, left
+  clear-line-delimited screen, left, right
   # clear rest of screen in this column, if requested
-  reply-unless clear:boolean, screen:address/same-as-ingredient:0
-  screen-height:number <- screen-height screen:address
+  reply-unless clear, screen/same-as-ingredient:0
+  screen-height:number <- screen-height screen
   {
-    at-bottom-of-screen?:boolean <- greater-or-equal row:number, screen-height:number
-    break-if at-bottom-of-screen?:boolean
-    move-cursor screen:address, row:number, left:number
-    clear-line-delimited screen:address, left:number, right:number
-    row:number <- add row:number, 1
+    at-bottom-of-screen?:boolean <- greater-or-equal row, screen-height
+    break-if at-bottom-of-screen?
+    move-cursor screen, row, left
+    clear-line-delimited screen, left, right
+    row <- add row, 1
     loop
   }
-  reply screen:address/same-as-ingredient:0
+  reply screen/same-as-ingredient:0
 ]
 
 recipe update-cursor [
@@ -1295,20 +1295,20 @@ recipe update-cursor [
   current-sandbox:address:editor-data <- next-ingredient
   sandbox-in-focus?:boolean <- next-ingredient
   {
-    break-if sandbox-in-focus?:boolean
+    break-if sandbox-in-focus?
 #?     $print [recipes in focus
 #? ] #? 1
-    cursor-row:number <- get recipes:address:editor-data/lookup, cursor-row:offset
-    cursor-column:number <- get recipes:address:editor-data/lookup, cursor-column:offset
+    cursor-row:number <- get *recipes, cursor-row:offset
+    cursor-column:number <- get *recipes, cursor-column:offset
   }
   {
-    break-unless sandbox-in-focus?:boolean
+    break-unless sandbox-in-focus?
 #?     $print [sandboxes in focus
 #? ] #? 1
-    cursor-row:number <- get current-sandbox:address:editor-data/lookup, cursor-row:offset
-    cursor-column:number <- get current-sandbox:address:editor-data/lookup, cursor-column:offset
+    cursor-row:number <- get *current-sandbox, cursor-row:offset
+    cursor-column:number <- get *current-sandbox, cursor-column:offset
   }
-  move-cursor screen:address, cursor-row:number, cursor-column:number
+  move-cursor screen, cursor-row, cursor-column
 ]
 
 scenario editor-handles-empty-event-queue [
@@ -1335,8 +1335,8 @@ scenario editor-handles-mouse-clicks [
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   screen-should-contain [
     .          .
@@ -1358,8 +1358,8 @@ scenario editor-handles-mouse-clicks-outside-text [
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   memory-should-contain [
     3 <- 1  # cursor row
@@ -1377,8 +1377,8 @@ def]
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   memory-should-contain [
     3 <- 1  # cursor row
@@ -1396,8 +1396,8 @@ def]
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   memory-should-contain [
     3 <- 2  # cursor row
@@ -1416,8 +1416,8 @@ scenario editor-handles-mouse-clicks-outside-column [
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   screen-should-contain [
     .          .
@@ -1603,8 +1603,8 @@ scenario editor-wraps-cursor-after-inserting-characters [
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   screen-should-contain [
     .          .
@@ -1628,8 +1628,8 @@ scenario editor-wraps-cursor-after-inserting-characters-2 [
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   screen-should-contain [
     .          .
@@ -1724,8 +1724,8 @@ ef]
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   # cursor should be below start of previous line
   memory-should-contain [
@@ -1746,8 +1746,8 @@ scenario editor-handles-backspace-key [
   replace-in-console 171/«, 3:event/backspace
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    4:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    5:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    4:number <- get *2:address:editor-data, cursor-row:offset
+    5:number <- get *2:address:editor-data, cursor-column:offset
   ]
   screen-should-contain [
     .          .
@@ -1877,8 +1877,8 @@ scenario editor-moves-cursor-to-next-wrapped-line-with-right-arrow [
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   screen-should-contain [
     .          .
@@ -1904,8 +1904,8 @@ scenario editor-moves-cursor-to-next-wrapped-line-with-right-arrow-2 [
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   memory-should-contain [
     3 <- 2
@@ -1917,8 +1917,8 @@ scenario editor-moves-cursor-to-next-wrapped-line-with-right-arrow-2 [
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   memory-should-contain [
     3 <- 2
@@ -1936,8 +1936,8 @@ scenario editor-moves-cursor-to-next-wrapped-line-with-right-arrow-3 [
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   screen-should-contain [
     .          .
@@ -2004,8 +2004,8 @@ d]
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   memory-should-contain [
     3 <- 1
@@ -2106,8 +2106,8 @@ scenario editor-moves-across-screen-lines-across-wrap-with-left-arrow [
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   memory-should-contain [
     3 <- 1  # previous row
@@ -2126,8 +2126,8 @@ def]
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   memory-should-contain [
     3 <- 1
@@ -2146,8 +2146,8 @@ def]
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   # ..and ends at (2, 0)
   memory-should-contain [
@@ -2167,8 +2167,8 @@ def]
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   memory-should-contain [
     3 <- 1
@@ -2187,8 +2187,8 @@ de]
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   memory-should-contain [
     3 <- 2
@@ -2210,8 +2210,8 @@ scenario editor-moves-to-start-of-line-with-ctrl-a [
   replace-in-console 97/a, 3:event/ctrl-a
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    4:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    5:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    4:number <- get *2:address:editor-data, cursor-row:offset
+    5:number <- get *2:address:editor-data, cursor-column:offset
   ]
   # cursor moves to start of line
   memory-should-contain [
@@ -2234,8 +2234,8 @@ scenario editor-moves-to-start-of-line-with-ctrl-a-2 [
   replace-in-console 97/a, 3:event/ctrl-a
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    4:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    5:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    4:number <- get *2:address:editor-data, cursor-row:offset
+    5:number <- get *2:address:editor-data, cursor-column:offset
   ]
   # cursor moves to start of line
   memory-should-contain [
@@ -2256,8 +2256,8 @@ scenario editor-moves-to-start-of-line-with-home [
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   # cursor moves to start of line
   memory-should-contain [
@@ -2278,8 +2278,8 @@ scenario editor-moves-to-start-of-line-with-home-2 [
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   # cursor moves to start of line
   memory-should-contain [
@@ -2302,8 +2302,8 @@ scenario editor-moves-to-start-of-line-with-ctrl-e [
   replace-in-console 101/e, 3:event/ctrl-e
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    4:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    5:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    4:number <- get *2:address:editor-data, cursor-row:offset
+    5:number <- get *2:address:editor-data, cursor-column:offset
   ]
   # cursor moves to end of line
   memory-should-contain [
@@ -2316,8 +2316,8 @@ scenario editor-moves-to-start-of-line-with-ctrl-e [
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    4:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    5:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    4:number <- get *2:address:editor-data, cursor-row:offset
+    5:number <- get *2:address:editor-data, cursor-column:offset
   ]
   memory-should-contain [
     4 <- 1
@@ -2345,8 +2345,8 @@ scenario editor-moves-to-end-of-line-with-ctrl-e-2 [
   replace-in-console 101/e, 3:event/ctrl-e
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    4:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    5:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    4:number <- get *2:address:editor-data, cursor-row:offset
+    5:number <- get *2:address:editor-data, cursor-column:offset
   ]
   # cursor moves to end of line
   memory-should-contain [
@@ -2367,8 +2367,8 @@ scenario editor-moves-to-end-of-line-with-end [
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   # cursor moves to end of line
   memory-should-contain [
@@ -2389,8 +2389,8 @@ scenario editor-moves-to-end-of-line-with-end-2 [
   ]
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
-    3:number <- get 2:address:editor-data/lookup, cursor-row:offset
-    4:number <- get 2:address:editor-data/lookup, cursor-column:offset
+    3:number <- get *2:address:editor-data, cursor-row:offset
+    4:number <- get *2:address:editor-data, cursor-column:offset
   ]
   # cursor moves to end of line
   memory-should-contain [
@@ -2630,10 +2630,10 @@ scenario point-at-multiple-editors [
   # check cursor column in each
   run [
     event-loop screen:address, console:address, 3:address:programming-environment-data
-    4:address:editor-data <- get 3:address:programming-environment-data/lookup, recipes:offset
-    5:number <- get 4:address:editor-data/lookup, cursor-column:offset
-    6:address:editor-data <- get 3:address:programming-environment-data/lookup, current-sandbox:offset
-    7:number <- get 6:address:editor-data/lookup, cursor-column:offset
+    4:address:editor-data <- get *3:address:programming-environment-data, recipes:offset
+    5:number <- get *4:address:editor-data, cursor-column:offset
+    6:address:editor-data <- get *3:address:programming-environment-data, current-sandbox:offset
+    7:number <- get *6:address:editor-data, cursor-column:offset
   ]
   memory-should-contain [
     5 <- 1
@@ -2657,10 +2657,10 @@ scenario edit-multiple-editors [
   ]
   run [
     event-loop screen:address, console:address, 3:address:programming-environment-data
-    4:address:editor-data <- get 3:address:programming-environment-data/lookup, recipes:offset
-    5:number <- get 4:address:editor-data/lookup, cursor-column:offset
-    6:address:editor-data <- get 3:address:programming-environment-data/lookup, current-sandbox:offset
-    7:number <- get 6:address:editor-data/lookup, cursor-column:offset
+    4:address:editor-data <- get *3:address:programming-environment-data, recipes:offset
+    5:number <- get *4:address:editor-data, cursor-column:offset
+    6:address:editor-data <- get *3:address:programming-environment-data, current-sandbox:offset
+    7:number <- get *6:address:editor-data, cursor-column:offset
   ]
   screen-should-contain [
     .           run (F4)           .  # this line has a different background, but we don't test that yet
@@ -2829,57 +2829,57 @@ scenario run-and-show-results [
 recipe run-sandboxes [
   local-scope
   env:address:programming-environment-data <- next-ingredient
-  recipes:address:editor-data <- get env:address:programming-environment-data/lookup, recipes:offset
-  current-sandbox:address:editor-data <- get env:address:programming-environment-data/lookup, current-sandbox:offset
+  recipes:address:editor-data <- get *env, recipes:offset
+  current-sandbox:address:editor-data <- get *env, current-sandbox:offset
   # copy code from recipe editor, persist, load into mu, save any warnings
-  in:address:array:character <- editor-contents recipes:address:editor-data
-  save [recipes.mu], in:address:array:character
-  recipe-warnings:address:address:array:character <- get-address env:address:programming-environment-data/lookup, recipe-warnings:offset
-  recipe-warnings:address:address:array:character/lookup <- reload in:address:array:character
+  in:address:array:character <- editor-contents recipes
+  save [recipes.mu], in
+  recipe-warnings:address:address:array:character <- get-address *env, recipe-warnings:offset
+  *recipe-warnings <- reload in
   # if recipe editor has errors, stop
-  reply-if recipe-warnings:address:address:array:character/lookup
+  reply-if *recipe-warnings
   # check contents of right editor (sandbox)
   {
-    sandbox-contents:address:array:character <- editor-contents current-sandbox:address:editor-data
-    break-unless sandbox-contents:address:array:character
+    sandbox-contents:address:array:character <- editor-contents current-sandbox
+    break-unless sandbox-contents
     # if contents exist, first save them
     # run them and turn them into a new sandbox-data
     new-sandbox:address:sandbox-data <- new sandbox-data:type
-    data:address:address:array:character <- get-address new-sandbox:address:sandbox-data/lookup, data:offset
-    data:address:address:array:character/lookup <- copy sandbox-contents:address:array:character
+    data:address:address:array:character <- get-address *new-sandbox, data:offset
+    *data <- copy sandbox-contents
     # push to head of sandbox list
-    dest:address:address:sandbox-data <- get-address env:address:programming-environment-data/lookup, sandbox:offset
-    next:address:address:sandbox-data <- get-address new-sandbox:address:sandbox-data/lookup, next-sandbox:offset
-    next:address:address:sandbox-data/lookup <- copy dest:address:address:sandbox-data/lookup
-    dest:address:address:sandbox-data/lookup <- copy new-sandbox:address:sandbox-data
+    dest:address:address:sandbox-data <- get-address *env, sandbox:offset
+    next:address:address:sandbox-data <- get-address *new-sandbox, next-sandbox:offset
+    *next <- copy *dest
+    *dest <- copy new-sandbox
     # clear sandbox editor
-    init:address:address:duplex-list <- get-address current-sandbox:address:editor-data/lookup, data:offset
-    init:address:address:duplex-list/lookup <- push-duplex 167/§, 0/tail
+    init:address:address:duplex-list <- get-address *current-sandbox, data:offset
+    *init <- push-duplex 167/§, 0/tail
   }
   # save all sandboxes before running, just in case we die when running
   # first clear previous versions, in case we deleted some sandbox
   $system [rm lesson/[0-9]*]
-  curr:address:sandbox-data <- get env:address:programming-environment-data/lookup, sandbox:offset
+  curr:address:sandbox-data <- get *env, sandbox:offset
   filename:number <- copy 0
   {
-    break-unless curr:address:sandbox-data
-    data:address:address:array:character <- get-address curr:address:sandbox-data/lookup, data:offset
-    save filename:number, data:address:address:array:character/lookup
-    filename:number <- add filename:number, 1
-    curr:address:sandbox-data <- get curr:address:sandbox-data/lookup, next-sandbox:offset
+    break-unless curr
+    data:address:address:array:character <- get-address *curr, data:offset
+    save filename, *data
+    filename <- add filename, 1
+    curr <- get *curr, next-sandbox:offset
     loop
   }
   # run all sandboxes
-  curr:address:sandbox-data <- get env:address:programming-environment-data/lookup, sandbox:offset
+  curr <- get *env, sandbox:offset
   {
-    break-unless curr:address:sandbox-data
-    data:address:address:array:character <- get-address curr:address:sandbox-data/lookup, data:offset
-    response:address:address:array:character <- get-address curr:address:sandbox-data/lookup, response:offset
-    warnings:address:address:array:character <- get-address curr:address:sandbox-data/lookup, warnings:offset
-    fake-screen:address:address:screen <- get-address curr:address:sandbox-data/lookup, screen:offset
-    response:address:address:array:character/lookup, warnings:address:address:array:character/lookup, fake-screen:address:address:screen/lookup <- run-interactive data:address:address:array:character/lookup
-#?     $print warnings:address:address:array:character/lookup, [ ], warnings:address:address:array:character/lookup/lookup, 10/newline
-    curr:address:sandbox-data <- get curr:address:sandbox-data/lookup, next-sandbox:offset
+    break-unless curr
+    data <- get-address *curr, data:offset
+    response:address:address:array:character <- get-address *curr, response:offset
+    warnings:address:address:array:character <- get-address *curr, warnings:offset
+    fake-screen:address:address:screen <- get-address *curr, screen:offset
+    *response, *warnings, *fake-screen <- run-interactive *data
+#?     $print *warnings, [ ], **warnings, 10/newline
+    curr <- get *curr, next-sandbox:offset
     loop
   }
 ]
@@ -2890,29 +2890,29 @@ recipe render-sandbox-side [
   env:address:programming-environment-data <- next-ingredient
   clear:boolean <- next-ingredient
 #?   trace [app], [render sandbox side] #? 1
-  current-sandbox:address:editor-data <- get env:address:programming-environment-data/lookup, current-sandbox:offset
-  left:number <- get current-sandbox:address:editor-data/lookup, left:offset
-  right:number <- get current-sandbox:address:editor-data/lookup, right:offset
-  row:number, screen:address <- render screen:address, current-sandbox:address:editor-data
-  row:number <- add row:number, 1
-  draw-horizontal screen:address, row:number, left:number, right:number, 9473/horizontal-double
-  sandbox:address:sandbox-data <- get env:address:programming-environment-data/lookup, sandbox:offset
-  row:number, screen:address <- render-sandboxes screen:address, sandbox:address:sandbox-data, left:number, right:number, row:number
+  current-sandbox:address:editor-data <- get *env, current-sandbox:offset
+  left:number <- get *current-sandbox, left:offset
+  right:number <- get *current-sandbox, right:offset
+  row:number, screen <- render screen, current-sandbox
+  row <- add row, 1
+  draw-horizontal screen, row, left, right, 9473/horizontal-double
+  sandbox:address:sandbox-data <- get *env, sandbox:offset
+  row, screen <- render-sandboxes screen, sandbox, left, right, row
   # clear next line, in case we just processed a backspace
-  row:number <- add row:number, 1
-  move-cursor screen:address, row:number, left:number
-  clear-line-delimited screen:address, left:number, right:number
-  reply-unless clear:boolean, screen:address/same-as-ingredient:0
-  screen-height:number <- screen-height screen:address
+  row <- add row, 1
+  move-cursor screen, row, left
+  clear-line-delimited screen, left, right
+  reply-unless clear, screen/same-as-ingredient:0
+  screen-height:number <- screen-height screen
   {
-    at-bottom-of-screen?:boolean <- greater-or-equal row:number, screen-height:number
-    break-if at-bottom-of-screen?:boolean
-    move-cursor screen:address, row:number, left:number
-    clear-line-delimited screen:address, left:number, right:number
-    row:number <- add row:number, 1
+    at-bottom-of-screen?:boolean <- greater-or-equal row, screen-height
+    break-if at-bottom-of-screen?
+    move-cursor screen, row, left
+    clear-line-delimited screen, left, right
+    row <- add row, 1
     loop
   }
-  reply screen:address/same-as-ingredient:0
+  reply screen/same-as-ingredient:0
 ]
 
 recipe render-sandboxes [
@@ -2922,49 +2922,49 @@ recipe render-sandboxes [
   left:number <- next-ingredient
   right:number <- next-ingredient
   row:number <- next-ingredient
-  reply-unless sandbox:address:sandbox-data, row:number/same-as-ingredient:4, screen:address/same-as-ingredient:0
-  screen-height:number <- screen-height screen:address
-  at-bottom?:boolean <- greater-or-equal row:number screen-height:number
-  reply-if at-bottom?:boolean, row:number/same-as-ingredient:4, screen:address/same-as-ingredient:0
-#?   $print [rendering sandbox ], sandbox:address:sandbox-data, 10/newline
+  reply-unless sandbox, row/same-as-ingredient:4, screen/same-as-ingredient:0
+  screen-height:number <- screen-height screen
+  at-bottom?:boolean <- greater-or-equal row, screen-height
+  reply-if at-bottom?:boolean, row/same-as-ingredient:4, screen/same-as-ingredient:0
+#?   $print [rendering sandbox ], sandbox, 10/newline
   # render sandbox menu
-  row:number <- add row:number, 1
-  move-cursor screen:address, row:number, left:number
-  clear-line-delimited screen:address, left:number, right:number
-  print-character screen:address, 120/x, 245/grey
+  row <- add row, 1
+  move-cursor screen, row, left
+  clear-line-delimited screen, left, right
+  print-character screen, 120/x, 245/grey
   # save menu row so we can detect clicks to it later
-  starting-row:address:number <- get-address sandbox:address:sandbox-data/lookup, starting-row-on-screen:offset
-  starting-row:address:number/lookup <- copy row:number
+  starting-row:address:number <- get-address *sandbox, starting-row-on-screen:offset
+  *starting-row <- copy row
   # render sandbox contents
-  sandbox-data:address:array:character <- get sandbox:address:sandbox-data/lookup, data:offset
-  row:number, screen:address <- render-string screen:address, sandbox-data:address:array:character, left:number, right:number, 7/white, row:number
+  sandbox-data:address:array:character <- get *sandbox, data:offset
+  row, screen <- render-string screen, sandbox-data, left, right, 7/white, row
   # render sandbox warnings, screen or response, in that order
-  sandbox-response:address:array:character <- get sandbox:address:sandbox-data/lookup, response:offset
-  sandbox-warnings:address:array:character <- get sandbox:address:sandbox-data/lookup, warnings:offset
-  sandbox-screen:address <- get sandbox:address:sandbox-data/lookup, screen:offset
+  sandbox-response:address:array:character <- get *sandbox, response:offset
+  sandbox-warnings:address:array:character <- get *sandbox, warnings:offset
+  sandbox-screen:address <- get *sandbox, screen:offset
   {
-    break-unless sandbox-warnings:address:array:character
-    row:number, screen:address <- render-string screen:address, sandbox-warnings:address:array:character, left:number, right:number, 1/red, row:number
+    break-unless sandbox-warnings
+    row, screen <- render-string screen, sandbox-warnings, left, right, 1/red, row
   }
   {
-    break-if sandbox-warnings:address:array:character
-    empty-screen?:boolean <- fake-screen-is-clear? sandbox-screen:address
-    break-if empty-screen?:boolean
-    row:number, screen:address <- render-screen screen:address, sandbox-screen:address, left:number, right:number, row:number
+    break-if sandbox-warnings
+    empty-screen?:boolean <- fake-screen-is-clear? sandbox-screen
+    break-if empty-screen?
+    row, screen <- render-screen screen, sandbox-screen, left, right, row
   }
   {
-    break-if sandbox-warnings:address:array:character
-    break-unless empty-screen?:boolean
-    row:number, screen:address <- render-string screen:address, sandbox-response:address:array:character, left:number, right:number, 245/grey, row:number
+    break-if sandbox-warnings
+    break-unless empty-screen?
+    row, screen <- render-string screen, sandbox-response, left, right, 245/grey, row
   }
-  at-bottom?:boolean <- greater-or-equal row:number screen-height:number
-  reply-if at-bottom?:boolean, row:number/same-as-ingredient:4, screen:address/same-as-ingredient:0
+  at-bottom?:boolean <- greater-or-equal row, screen-height
+  reply-if at-bottom?, row/same-as-ingredient:4, screen/same-as-ingredient:0
   # draw solid line after sandbox
-  draw-horizontal screen:address, row:number, left:number, right:number, 9473/horizontal-double
+  draw-horizontal screen, row, left, right, 9473/horizontal-double
   # draw next sandbox
-  next-sandbox:address:sandbox-data <- get sandbox:address:sandbox-data/lookup, next-sandbox:offset
-  row:number, screen:address <- render-sandboxes screen:address, next-sandbox:address:sandbox-data, left:number, right:number, row:number
-  reply row:number/same-as-ingredient:4, screen:address/same-as-ingredient:0
+  next-sandbox:address:sandbox-data <- get *sandbox, next-sandbox:offset
+  row, screen <- render-sandboxes screen, next-sandbox, left, right, row
+  reply row/same-as-ingredient:4, screen/same-as-ingredient:0
 ]
 
 # assumes programming environment has no sandboxes; restores them from previous session
@@ -2973,21 +2973,21 @@ recipe restore-sandboxes [
   env:address:programming-environment-data <- next-ingredient
   # read all scenarios, pushing them to end of a list of scenarios
   filename:number <- copy 0
-  curr:address:address:sandbox-data <- get-address env:address:programming-environment-data/lookup, sandbox:offset
+  curr:address:address:sandbox-data <- get-address *env, sandbox:offset
   {
-    contents:address:array:character <- restore filename:number
-    break-unless contents:address:array:character  # stop at first error; assuming file didn't exist
-#?     $print contents:address:array:character, 10/newline
+    contents:address:array:character <- restore filename
+    break-unless contents  # stop at first error; assuming file didn't exist
+#?     $print contents, 10/newline
     # create new sandbox for file
-    curr:address:address:sandbox-data/lookup <- new sandbox-data:type
-    data:address:address:array:character <- get-address curr:address:address:sandbox-data/lookup/lookup, data:offset
-    data:address:address:array:character/lookup <- copy contents:address:array:character
+    *curr <- new sandbox-data:type
+    data:address:address:array:character <- get-address **curr, data:offset
+    *data <- copy contents
     # increment loop variables
-    filename:number <- add filename:number, 1
-    curr:address:address:sandbox-data <- get-address curr:address:address:sandbox-data/lookup/lookup, next-sandbox:offset
+    filename <- add filename, 1
+    curr <- get-address **curr, next-sandbox:offset
     loop
   }
-  reply env:address:programming-environment-data/same-as-ingredient:0
+  reply env/same-as-ingredient:0
 ]
 
 # was-deleted?:boolean <- delete-sandbox t:touch-event, env:address:programming-environment-data
@@ -2995,40 +2995,40 @@ recipe delete-sandbox [
   local-scope
   t:touch-event <- next-ingredient
   env:address:programming-environment-data <- next-ingredient
-  click-column:number <- get t:touch-event, column:offset
-  current-sandbox:address:editor-data <- get env:address:programming-environment-data/lookup, current-sandbox:offset
-  right:number <- get current-sandbox:address:editor-data/lookup, right:offset
-#?   $print [comparing column ], click-column:number, [ vs ], right:number, 10/newline
-  at-right?:boolean <- equal click-column:number, right:number
-  reply-unless at-right?:boolean, 0/false
+  click-column:number <- get t, column:offset
+  current-sandbox:address:editor-data <- get *env, current-sandbox:offset
+  right:number <- get *current-sandbox, right:offset
+#?   $print [comparing column ], click-column, [ vs ], right, 10/newline
+  at-right?:boolean <- equal click-column, right
+  reply-unless at-right?, 0/false
 #?   $print [trying to delete
 #? ] #? 1
-  click-row:number <- get t:touch-event, row:offset
-  prev:address:address:sandbox-data <- get-address env:address:programming-environment-data/lookup, sandbox:offset
-#?   $print [prev: ], prev:address:address:sandbox-data, [ -> ], prev:address:address:sandbox-data/lookup, 10/newline
-  curr:address:sandbox-data <- get env:address:programming-environment-data/lookup, sandbox:offset
+  click-row:number <- get t, row:offset
+  prev:address:address:sandbox-data <- get-address *env, sandbox:offset
+#?   $print [prev: ], prev, [ -> ], *prev, 10/newline
+  curr:address:sandbox-data <- get *env, sandbox:offset
   {
 #?     $print [next sandbox
 #? ] #? 1
-    break-unless curr:address:sandbox-data
+    break-unless curr
     # more sandboxes to check
     {
 #?       $print [checking
 #? ] #? 1
-      target-row:number <- get curr:address:sandbox-data/lookup, starting-row-on-screen:offset
-#?       $print [comparing row ], target-row:number, [ vs ], click-row:number, 10/newline
-      delete-curr?:boolean <- equal target-row:number, click-row:number
-      break-unless delete-curr?:boolean
+      target-row:number <- get *curr, starting-row-on-screen:offset
+#?       $print [comparing row ], target-row, [ vs ], click-row, 10/newline
+      delete-curr?:boolean <- equal target-row, click-row
+      break-unless delete-curr?
 #?       $print [found!
 #? ] #? 1
       # delete this sandbox, rerender and stop
-      prev:address:address:sandbox-data/lookup <- get curr:address:sandbox-data/lookup, next-sandbox:offset
-#?       $print [setting prev: ], prev:address:address:sandbox-data, [ -> ], prev:address:address:sandbox-data/lookup, 10/newline
+      *prev <- get *curr, next-sandbox:offset
+#?       $print [setting prev: ], prev, [ -> ], *prev, 10/newline
       reply 1/true
     }
-    prev:address:address:sandbox-data <- get-address curr:address:sandbox-data/lookup, next-sandbox:offset
-#?     $print [prev: ], prev:address:address:sandbox-data, [ -> ], prev:address:address:sandbox-data/lookup, 10/newline
-    curr:address:sandbox-data <- get curr:address:sandbox-data/lookup, next-sandbox:offset
+    prev <- get-address *curr, next-sandbox:offset
+#?     $print [prev: ], prev, [ -> ], *prev, 10/newline
+    curr <- get *curr, next-sandbox:offset
     loop
   }
   reply 0/false
@@ -3277,20 +3277,20 @@ recipe editor-contents [
   local-scope
   editor:address:editor-data <- next-ingredient
   buf:address:buffer <- new-buffer 80
-  curr:address:duplex-list <- get editor:address:editor-data/lookup, data:offset
+  curr:address:duplex-list <- get *editor, data:offset
   # skip § sentinel
-  assert curr:address:duplex-list, [editor without data is illegal; must have at least a sentinel]
-  curr:address:duplex-list <- next-duplex curr:address:duplex-list
-  reply-unless curr:address:duplex-list, 0
+  assert curr, [editor without data is illegal; must have at least a sentinel]
+  curr <- next-duplex curr
+  reply-unless curr, 0
   {
-    break-unless curr:address:duplex-list
-    c:character <- get curr:address:duplex-list/lookup, value:offset
-    buffer-append buf:address:buffer, c:character
-    curr:address:duplex-list <- next-duplex curr:address:duplex-list
+    break-unless curr
+    c:character <- get *curr, value:offset
+    buffer-append buf, c
+    curr <- next-duplex curr
     loop
   }
-  result:address:array:character <- buffer-to-array buf:address:buffer
-  reply result:address:array:character
+  result:address:array:character <- buffer-to-array buf
+  reply result
 ]
 
 scenario editor-provides-edited-contents [
@@ -3304,7 +3304,7 @@ scenario editor-provides-edited-contents [
   run [
     editor-event-loop screen:address, console:address, 2:address:editor-data
     3:address:array:character <- editor-contents 2:address:editor-data
-    4:array:character <- copy 3:address:array:character/lookup
+    4:array:character <- copy *3:address:array:character
   ]
   memory-should-contain [
     4:string <- [abdefc]
@@ -3358,8 +3358,7 @@ scenario run-shows-missing-type-warnings [
   run [
     x:address:array:character <- new [ 
 recipe foo [
-  x:number <- copy 0
-  copy x
+  x <- copy 0
 ]]
     y:address:array:character <- new [foo]
     env:address:programming-environment-data <- new-programming-environment screen:address, x:address:array:character, y:address:array:character
@@ -3369,10 +3368,9 @@ recipe foo [
     .                                                                                 run (F4)           .
     .                                                  ┊foo                                              .
     .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.
-    .  x:number <- copy 0                              ┊                                                 .
-    .  copy x                                          ┊                                                 .
+    .  x <- copy 0                                     ┊                                                 .
     .]                                                 ┊                                                 .
-    .missing type in 'copy x'                          ┊                                                 .
+    .missing type in 'x <- copy 0'                     ┊                                                 .
     .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊                                                 .
     .                                                  ┊                                                 .
   ]
@@ -3418,7 +3416,7 @@ scenario run-shows-non-literal-get-argument-warnings [
 recipe foo [
   x:number <- copy 0
   y:address:point <- new point:type
-  get y:address:point/lookup, x:number
+  get *y:address:point, x:number
 ]]
     y:address:array:character <- new [foo]
     env:address:programming-environment-data <- new-programming-environment screen:address, x:address:array:character, y:address:array:character
@@ -3430,7 +3428,7 @@ recipe foo [
     .recipe foo [                                      ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.
     .  x:number <- copy 0                              ┊                                                 .
     .  y:address:point <- new point:type               ┊                                                 .
-    .  get y:address:point/lookup, x:number            ┊                                                 .
+    .  get *y:address:point, x:number                  ┊                                                 .
     .]                                                 ┊                                                 .
     .foo: expected ingredient 1 of 'get' to have type ↩┊                                                 .
     .'offset'; got x:number                            ┊                                                 .
@@ -3451,22 +3449,22 @@ recipe draw-box [
   color:number, color-found?:boolean <- next-ingredient
   {
     # default color to white
-    break-if color-found?:boolean
-    color:number <- copy 245/grey
+    break-if color-found?
+    color <- copy 245/grey
   }
   # top border
-  draw-horizontal screen:address, top:number, left:number, right:number, color:number
-  draw-horizontal screen:address, bottom:number, left:number, right:number, color:number
-  draw-vertical screen:address, left:number, top:number, bottom:number, color:number
-  draw-vertical screen:address, right:number, top:number, bottom:number, color:number
-  draw-top-left screen:address, top:number, left:number, color:number
-  draw-top-right screen:address, top:number, right:number, color:number
-  draw-bottom-left screen:address, bottom:number, left:number, color:number
-  draw-bottom-right screen:address, bottom:number, right:number, color:number
+  draw-horizontal screen, top, left, right, color
+  draw-horizontal screen, bottom, left, right, color
+  draw-vertical screen, left, top, bottom, color
+  draw-vertical screen, right, top, bottom, color
+  draw-top-left screen, top, left, color
+  draw-top-right screen, top, right, color
+  draw-bottom-left screen, bottom, left, color
+  draw-bottom-right screen, bottom, right, color
   # position cursor inside box
-  move-cursor screen:address, top:number, left:number
-  cursor-down screen:address
-  cursor-right screen:address
+  move-cursor screen, top, left
+  cursor-down screen
+  cursor-right screen
 ]
 
 recipe draw-horizontal [
@@ -3477,26 +3475,26 @@ recipe draw-horizontal [
   right:number <- next-ingredient
   style:character, style-found?:boolean <- next-ingredient
   {
-    break-if style-found?:boolean
-    style:character <- copy 9472/horizontal
+    break-if style-found?
+    style <- copy 9472/horizontal
   }
   color:number, color-found?:boolean <- next-ingredient
   {
     # default color to white
-    break-if color-found?:boolean
-    color:number <- copy 245/grey
+    break-if color-found?
+    color <- copy 245/grey
   }
   bg-color:number, bg-color-found?:boolean <- next-ingredient
   {
     break-if bg-color-found?:boolean
-    bg-color:number <- copy 0/black
+    bg-color <- copy 0/black
   }
-  move-cursor screen:address, row:number, x:number
+  move-cursor screen, row, x
   {
-    continue?:boolean <- lesser-or-equal x:number, right:number  # right is inclusive, to match editor-data semantics
-    break-unless continue?:boolean
-    print-character screen:address, style:character, color:number, bg-color:number
-    x:number <- add x:number, 1
+    continue?:boolean <- lesser-or-equal x, right  # right is inclusive, to match editor-data semantics
+    break-unless continue?
+    print-character screen, style, color, bg-color
+    x <- add x, 1
     loop
   }
 ]
@@ -3505,25 +3503,25 @@ recipe draw-vertical [
   local-scope
   screen:address <- next-ingredient
   col:number <- next-ingredient
-  x:number <- next-ingredient
+  y:number <- next-ingredient
   bottom:number <- next-ingredient
   style:character, style-found?:boolean <- next-ingredient
   {
-    break-if style-found?:boolean
-    style:character <- copy 9474/vertical
+    break-if style-found?
+    style <- copy 9474/vertical
   }
   color:number, color-found?:boolean <- next-ingredient
   {
     # default color to white
-    break-if color-found?:boolean
-    color:number <- copy 245/grey
+    break-if color-found?
+    color <- copy 245/grey
   }
   {
-    continue?:boolean <- lesser-than x:number, bottom:number
-    break-unless continue?:boolean
-    move-cursor screen:address, x:number, col:number
-    print-character screen:address, style:character, color:number
-    x:number <- add x:number, 1
+    continue?:boolean <- lesser-than y, bottom
+    break-unless continue?
+    move-cursor screen, y, col
+    print-character screen, style, color
+    y <- add y, 1
     loop
   }
 ]
@@ -3536,11 +3534,11 @@ recipe draw-top-left [
   color:number, color-found?:boolean <- next-ingredient
   {
     # default color to white
-    break-if color-found?:boolean
-    color:number <- copy 245/grey
+    break-if color-found?
+    color <- copy 245/grey
   }
-  move-cursor screen:address, top:number, left:number
-  print-character screen:address, 9484/down-right, color:number
+  move-cursor screen, top, left
+  print-character screen, 9484/down-right, color
 ]
 
 recipe draw-top-right [
@@ -3551,11 +3549,11 @@ recipe draw-top-right [
   color:number, color-found?:boolean <- next-ingredient
   {
     # default color to white
-    break-if color-found?:boolean
-    color:number <- copy 245/grey
+    break-if color-found?
+    color <- copy 245/grey
   }
-  move-cursor screen:address, top:number, right:number
-  print-character screen:address, 9488/down-left, color:number
+  move-cursor screen, top, right
+  print-character screen, 9488/down-left, color
 ]
 
 recipe draw-bottom-left [
@@ -3566,11 +3564,11 @@ recipe draw-bottom-left [
   color:number, color-found?:boolean <- next-ingredient
   {
     # default color to white
-    break-if color-found?:boolean
-    color:number <- copy 245/grey
+    break-if color-found?
+    color <- copy 245/grey
   }
-  move-cursor screen:address, bottom:number, left:number
-  print-character screen:address, 9492/up-right, color:number
+  move-cursor screen, bottom, left
+  print-character screen, 9492/up-right, color
 ]
 
 recipe draw-bottom-right [
@@ -3581,11 +3579,11 @@ recipe draw-bottom-right [
   color:number, color-found?:boolean <- next-ingredient
   {
     # default color to white
-    break-if color-found?:boolean
-    color:number <- copy 245/grey
+    break-if color-found?
+    color <- copy 245/grey
   }
-  move-cursor screen:address, bottom:number, right:number
-  print-character screen:address, 9496/up-left, color:number
+  move-cursor screen, bottom, right
+  print-character screen, 9496/up-left, color
 ]
 
 recipe print-string-with-gradient-background [
@@ -3595,24 +3593,24 @@ recipe print-string-with-gradient-background [
   color:number <- next-ingredient
   bg-color1:number <- next-ingredient
   bg-color2:number <- next-ingredient
-  len:number <- length s:address:array:character/lookup
-  color-range:number <- subtract bg-color2:number, bg-color1:number
-  color-quantum:number <- divide color-range:number, len:number
+  len:number <- length *s
+  color-range:number <- subtract bg-color2, bg-color1
+  color-quantum:number <- divide color-range, len
 #?   close-console #? 2
-#?   $print len:number, [, ], color-range:number, [, ], color-quantum:number, 10/newline
+#?   $print len, [, ], color-range, [, ], color-quantum, 10/newline
 #? #?   $exit #? 3
-  bg-color:number <- copy bg-color1:number
+  bg-color:number <- copy bg-color1
   i:number <- copy 0
   {
-    done?:boolean <- greater-or-equal i:number, len:number
-    break-if done?:boolean
-    c:character <- index s:address:array:character/lookup, i:number
-    print-character x:address:screen, c:character, color:number, bg-color:number
-    i:number <- add i:number, 1
-    bg-color:number <- add bg-color:number, color-quantum:number
-#?     $print [=> ], bg-color:number, 10/newline
+    done?:boolean <- greater-or-equal i, len
+    break-if done?
+    c:character <- index *s, i
+    print-character x, c, color, bg-color
+    i <- add i, 1
+    bg-color <- add bg-color, color-quantum
+#?     $print [=> ], bg-color, 10/newline
     loop
   }
 #?   $exit #? 1
-  reply x:address:screen/same-as-ingredient:0
+  reply x/same-as-ingredient:0
 ]
diff --git a/factorial.mu b/factorial.mu
index 23c247e0..31b2f63c 100644
--- a/factorial.mu
+++ b/factorial.mu
@@ -3,7 +3,7 @@
 recipe main [
   local-scope
   x:number <- factorial 5
-  $print [result: ], x:number, [ 
+  $print [result: ], x, [ 
 ]
 ]
 
@@ -12,15 +12,15 @@ recipe factorial [
   n:number <- next-ingredient
   {
     # if n=0 return 1
-    zero?:boolean <- equal n:number, 0
-    break-unless zero?:boolean
+    zero?:boolean <- equal n, 0
+    break-unless zero?
     reply 1
   }
   # return n * factorial(n-1)
-  x:number <- subtract n:number, 1
-  subresult:number <- factorial x:number
-  result:number <- multiply subresult:number, n:number
-  reply result:number
+  x:number <- subtract n, 1
+  subresult:number <- factorial x
+  result:number <- multiply subresult, n
+  reply result
 ]
 
 # unit test
diff --git a/tangle.mu b/tangle.mu
index 121bfbcc..b9d05bee 100644
--- a/tangle.mu
+++ b/tangle.mu
@@ -17,17 +17,17 @@ recipe factorial [
 
 after +base-case [
   # if n=0 return 1
-  zero?:boolean <- equal n:number, 0
-  break-unless zero?:boolean
+  zero?:boolean <- equal n, 0
+  break-unless zero?
   reply 1
 ]
 
 after +recursive-case [
   # return n * factorial(n - 1)
-  x:number <- subtract n:number, 1
-  subresult:number <- factorial x:number
-  result:number <- multiply subresult:number, n:number
-  reply result:number
+  x:number <- subtract n, 1
+  subresult:number <- factorial x
+  result:number <- multiply subresult, n
+  reply result
 ]
 
 recipe main [