about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-12-28 08:44:36 -0800
committerKartik K. Agaram <vc@akkartik.com>2015-12-28 08:44:36 -0800
commitbbe0801ab1e0b0859c3529ed33fde40b139addd6 (patch)
treefa534bbbb3b345d154432746cd585f9262bd80cd
parente94453100dda87a42dee36b2671f850ab6824f54 (diff)
downloadmu-bbe0801ab1e0b0859c3529ed33fde40b139addd6.tar.gz
2548 - teach 'print' to print integers
Still can't print non-integer numbers, so this is a bit hacky.

The big consequence is that you can't print literal characters anymore
because of our rules about how we pick which variant to statically
dispatch to. You have to save to a character variable first.

Maybe I can add an annotation to literals..
-rw-r--r--081print.mu126
-rw-r--r--082scenario_screen.cc21
-rw-r--r--083scenario_screen_test.mu6
-rw-r--r--chessboard.mu3
-rw-r--r--edit/001-editor.mu6
-rw-r--r--edit/003-shortcuts.mu6
-rw-r--r--edit/004-programming-environment.mu24
-rw-r--r--edit/005-sandbox.mu15
-rw-r--r--edit/008-sandbox-test.mu3
-rw-r--r--edit/009-sandbox-trace.mu5
-rw-r--r--sandbox/001-editor.mu6
-rw-r--r--sandbox/003-shortcuts.mu6
-rw-r--r--sandbox/004-programming-environment.mu12
-rw-r--r--sandbox/005-sandbox.mu15
-rw-r--r--sandbox/009-sandbox-trace.mu5
-rw-r--r--screen.mu3
16 files changed, 164 insertions, 98 deletions
diff --git a/081print.mu b/081print.mu
index af49b012..445b6fa6 100644
--- a/081print.mu
+++ b/081print.mu
@@ -187,7 +187,8 @@ recipe print screen:address:screen, c:character -> screen:address:screen [
 scenario print-character-at-top-left [
   run [
     1:address:screen <- new-fake-screen 3/width, 2/height
-    1:address:screen <- print 1:address:screen, 97  # 'a'
+    11:character <- copy 97/a
+    1:address:screen <- print 1:address:screen, 11:character/a
     2:address:array:screen-cell <- get *1:address:screen, data:offset
     3:array:screen-cell <- copy *2:address:array:screen-cell
   ]
@@ -202,7 +203,8 @@ scenario print-character-at-top-left [
 scenario print-character-in-color [
   run [
     1:address:screen <- new-fake-screen 3/width, 2/height
-    1:address:screen <- print 1:address:screen, 97/a, 1/red
+    11:character <- copy 97/a
+    1:address:screen <- print 1:address:screen, 11:character/a, 1/red
     2:address:array:screen-cell <- get *1:address:screen, data:offset
     3:array:screen-cell <- copy *2:address:array:screen-cell
   ]
@@ -217,8 +219,10 @@ scenario print-character-in-color [
 scenario print-backspace-character [
   run [
     1:address:screen <- new-fake-screen 3/width, 2/height
-    1:address:screen <- print 1:address:screen, 97  # 'a'
-    1:address:screen <- print 1:address:screen, 8  # backspace
+    11:character <- copy 97/a
+    1:address:screen <- print 1:address:screen, 11:character/a
+    12:character <- copy 8/backspace
+    1:address:screen <- print 1:address:screen, 12:character/backspace
     2:number <- get *1:address:screen, cursor-column:offset
     3:address:array:screen-cell <- get *1:address:screen, data:offset
     4:array:screen-cell <- copy *3:address:array:screen-cell
@@ -235,9 +239,12 @@ scenario print-backspace-character [
 scenario print-extra-backspace-character [
   run [
     1:address:screen <- new-fake-screen 3/width, 2/height
-    1:address:screen <- print 1:address:screen, 97  # 'a'
-    1:address:screen <- print 1:address:screen, 8  # backspace
-    1:address:screen <- print 1:address:screen, 8  # backspace
+    11:character <- copy 97/a
+    1:address:screen <- print 1:address:screen, 11:character/a
+    12:character <- copy 8/backspace
+    1:address:screen <- print 1:address:screen, 12:character/backspace
+    12:character <- copy 8/backspace
+    1:address:screen <- print 1:address:screen, 12:character/backspace
     2:number <- get *1:address:screen, cursor-column:offset
     3:address:array:screen-cell <- get *1:address:screen, data:offset
     4:array:screen-cell <- copy *3:address:array:screen-cell
@@ -254,9 +261,12 @@ scenario print-extra-backspace-character [
 scenario print-character-at-right-margin [
   run [
     1:address:screen <- new-fake-screen 2/width, 2/height
-    1:address:screen <- print 1:address:screen, 97  # 'a'
-    1:address:screen <- print 1:address:screen, 98  # 'b'
-    1:address:screen <- print 1:address:screen, 99  # 'c'
+    11:character <- copy 97/a
+    1:address:screen <- print 1:address:screen, 11:character/a
+    12:character <- copy 98/b
+    1:address:screen <- print 1:address:screen, 12:character/b
+    13:character <- copy 99/b
+    1:address:screen <- print 1:address:screen, 13:character/c
     2:number <- get *1:address:screen, cursor-column:offset
     3:address:array:screen-cell <- get *1:address:screen, data:offset
     4:array:screen-cell <- copy *3:address:array:screen-cell
@@ -275,8 +285,10 @@ scenario print-character-at-right-margin [
 scenario print-newline-character [
   run [
     1:address:screen <- new-fake-screen 3/width, 2/height
-    1:address:screen <- print 1:address:screen, 97  # 'a'
-    1:address:screen <- print 1:address:screen, 10/newline
+    10:character <- copy 10/newline
+    11:character <- copy 97/a
+    1:address:screen <- print 1:address:screen, 11:character/a
+    1:address:screen <- print 1:address:screen, 10:character/newline
     2:number <- get *1:address:screen, cursor-row:offset
     3:number <- get *1:address:screen, cursor-column:offset
     4:address:array:screen-cell <- get *1:address:screen, data:offset
@@ -295,9 +307,10 @@ scenario print-newline-character [
 scenario print-newline-at-bottom-line [
   run [
     1:address:screen <- new-fake-screen 3/width, 2/height
-    1:address:screen <- print 1:address:screen, 10/newline
-    1:address:screen <- print 1:address:screen, 10/newline
-    1:address:screen <- print 1:address:screen, 10/newline
+    10:character <- copy 10/newline
+    1:address:screen <- print 1:address:screen, 10:character/newline
+    1:address:screen <- print 1:address:screen, 10:character/newline
+    1:address:screen <- print 1:address:screen, 10:character/newline
     2:number <- get *1:address:screen, cursor-row:offset
     3:number <- get *1:address:screen, cursor-column:offset
   ]
@@ -310,36 +323,42 @@ scenario print-newline-at-bottom-line [
 scenario print-character-at-bottom-right [
   run [
     1:address:screen <- new-fake-screen 2/width, 2/height
-    1:address:screen <- print 1:address:screen, 10/newline
-    1:address:screen <- print 1:address:screen, 97  # 'a'
-    1:address:screen <- print 1:address:screen, 98  # 'b'
-    1:address:screen <- print 1:address:screen, 99  # 'c'
-    1:address:screen <- print 1:address:screen, 10/newline
-    1:address:screen <- print 1:address:screen, 100  # 'd'
+    10:character <- copy 10/newline
+    1:address:screen <- print 1:address:screen, 10:character/newline
+    11:character <- copy 97/a
+    1:address:screen <- print 1:address:screen, 11:character/a
+    12:character <- copy 98/b
+    1:address:screen <- print 1:address:screen, 12:character/b
+    13:character <- copy 99/c
+    1:address:screen <- print 1:address:screen, 13:character/c
+    1:address:screen <- print 1:address:screen, 10:character/newline
+    14:character <- copy 100/d
+    1:address:screen <- print 1:address:screen, 14:character/d
     2:number <- get *1:address:screen, cursor-row:offset
     3:number <- get *1:address:screen, cursor-column:offset
     4:address:array:screen-cell <- get *1:address:screen, data:offset
-    5:array:screen-cell <- copy *4:address:array:screen-cell
+    20:array:screen-cell <- copy *4:address:array:screen-cell
   ]
   memory-should-contain [
     2 <- 1  # cursor row
     3 <- 1  # cursor column
-    5 <- 4  # width*height
-    6 <- 0  # unused
-    7 <- 7  # white
-    8 <- 0  # unused
-    9 <- 7  # white
-    10 <- 97 # 'a'
-    11 <- 7  # white
-    12 <- 100  # 'd' over 'b' and 'c' and newline
-    13 <- 7  # white
-    14 <- 0
+    20 <- 4  # width*height
+    21 <- 0  # unused
+    22 <- 7  # white
+    23 <- 0  # unused
+    24 <- 7  # white
+    25 <- 97 # 'a'
+    26 <- 7  # white
+    27 <- 100  # 'd' over 'b' and 'c' and newline
+    28 <- 7  # white
+    29 <- 0
   ]
 ]
 
 recipe clear-line screen:address:screen -> screen:address:screen [
   local-scope
   load-ingredients
+  space:character <- copy 0/nul
   # if x exists, clear line in fake screen
   {
     break-unless screen
@@ -351,7 +370,7 @@ recipe clear-line screen:address:screen -> screen:address:screen [
       right:number <- subtract width, 1
       done?:boolean <- greater-or-equal *column, right
       break-if done?
-      print screen, [ ]  # implicitly updates 'column'
+      print screen, space  # implicitly updates 'column'
       loop
     }
     # now back to where the cursor was
@@ -395,29 +414,30 @@ scenario clear-line-erases-printed-characters [
   run [
     1:address:screen <- new-fake-screen 3/width, 2/height
     # print a character
-    1:address:screen <- print 1:address:screen, 97  # 'a'
+    10:character <- copy 97/a
+    1:address:screen <- print 1:address:screen, 10:character/a
     # move cursor to start of line
     1:address:screen <- move-cursor 1:address:screen, 0/row, 0/column
     # clear line
     1:address:screen <- clear-line 1:address:screen
     2:address:array:screen-cell <- get *1:address:screen, data:offset
-    3:array:screen-cell <- copy *2:address:array:screen-cell
+    20:array:screen-cell <- copy *2:address:array:screen-cell
   ]
   # screen should be blank
   memory-should-contain [
-    3 <- 6  # width*height
-    4 <- 0
-    5 <- 7
-    6 <- 0
-    7 <- 7
-    8 <- 0
-    9 <- 7
-    10 <- 0
-    11 <- 7
-    12 <- 0
-    13 <- 7
-    14 <- 0
-    15 <- 7
+    20 <- 6  # width*height
+    21 <- 0
+    22 <- 7
+    23 <- 0
+    24 <- 7
+    25 <- 0
+    26 <- 7
+    27 <- 0
+    28 <- 7
+    29 <- 0
+    30 <- 7
+    31 <- 0
+    32 <- 7
   ]
 ]
 
@@ -641,8 +661,7 @@ scenario print-text-stops-at-right-margin [
 
 recipe print-integer screen:address:screen, n:number -> screen:address:screen [
   local-scope
-  screen:address:screen <- next-ingredient
-  n:number <- next-ingredient
+  load-ingredients
   color:number, color-found?:boolean <- next-ingredient
   {
     # default color to white
@@ -659,3 +678,10 @@ recipe print-integer screen:address:screen, n:number -> screen:address:screen [
   s:address:array:character <- to-text n
   screen <- print screen, s, color, bg-color
 ]
+
+# for now, we can only print integers
+recipe print screen:address:screen, n:number -> screen:address:screen [
+  local-scope
+  load-ingredients
+  screen <- print-integer screen, n
+]
diff --git a/082scenario_screen.cc b/082scenario_screen.cc
index 433b37c8..fc667311 100644
--- a/082scenario_screen.cc
+++ b/082scenario_screen.cc
@@ -9,7 +9,8 @@
 scenario screen-in-scenario [
   assume-screen 5/width, 3/height
   run [
-    screen:address:screen <- print screen:address:screen, 97  # 'a'
+    1:character <- copy 97/a
+    screen:address:screen <- print screen:address:screen, 1:character/a
   ]
   screen-should-contain [
   #  01234
@@ -23,8 +24,10 @@ scenario screen-in-scenario [
 scenario screen-in-scenario-unicode-color [
   assume-screen 5/width, 3/height
   run [
-    screen:address:screen <- print screen:address:screen, 955/greek-small-lambda, 1/red
-    screen:address:screen <- print screen:address:screen, 97/a
+    1:character <- copy 955/greek-small-lambda
+    screen:address:screen <- print screen:address:screen, 1:character/lambda, 1/red
+    2:character <- copy 97/a
+    screen:address:screen <- print screen:address:screen, 2:character/a
   ]
   screen-should-contain [
   #  01234
@@ -39,8 +42,10 @@ scenario screen-in-scenario-unicode-color [
 scenario screen-in-scenario-color [
   assume-screen 5/width, 3/height
   run [
-    screen:address:screen <- print screen:address:screen, 955/greek-small-lambda, 1/red
-    screen:address:screen <- print screen:address:screen, 97/a, 7/white
+    1:character <- copy 955/greek-small-lambda
+    screen:address:screen <- print screen:address:screen, 1:character/lambda, 1/red
+    2:character <- copy 97/a
+    screen:address:screen <- print screen:address:screen, 2:character/a, 7/white
   ]
   # screen-should-contain shows everything
   screen-should-contain [
@@ -72,7 +77,8 @@ scenario screen-in-scenario-color [
 scenario screen-in-scenario-error [
   assume-screen 5/width, 3/height
   run [
-    screen:address:screen <- print screen:address:screen, 97  # 'a'
+    1:character <- copy 97/a
+    screen:address:screen <- print screen:address:screen, 1:character/a
   ]
   screen-should-contain [
   #  01234
@@ -90,7 +96,8 @@ scenario screen-in-scenario-error [
 scenario screen-in-scenario-color [
   assume-screen 5/width, 3/height
   run [
-    screen:address:screen <- print screen:address:screen, 97/a, 1/red
+    1:character <- copy 97/a
+    screen:address:screen <- print screen:address:screen, 1:character/a, 1/red
   ]
   screen-should-contain-in-color 2/green, [
   #  01234
diff --git a/083scenario_screen_test.mu b/083scenario_screen_test.mu
index 17a3f140..9679e9cf 100644
--- a/083scenario_screen_test.mu
+++ b/083scenario_screen_test.mu
@@ -3,7 +3,8 @@
 scenario print-character-at-top-left-2 [
   assume-screen 3/width, 2/height
   run [
-    screen:address:screen <- print screen:address:screen, 97/a
+    1:character <- copy 97/a
+    screen:address:screen <- print screen:address:screen, 1:character/a
   ]
   screen-should-contain [
     .a  .
@@ -15,7 +16,8 @@ scenario clear-line-erases-printed-characters-2 [
   assume-screen 5/width, 3/height
   run [
     # print a character
-    screen:address:screen <- print screen:address:screen, 97/a
+    1:character <- copy 97/a
+    screen:address:screen <- print screen:address:screen, 1:character/a
     # move cursor to start of line
     screen:address:screen <- move-cursor screen:address:screen, 0/row, 0/column
     # clear line
diff --git a/chessboard.mu b/chessboard.mu
index c8c84eed..e5f894fa 100644
--- a/chessboard.mu
+++ b/chessboard.mu
@@ -149,6 +149,7 @@ recipe print-board screen:address:screen, board:address:array:address:array:char
   local-scope
   load-ingredients
   row:number <- copy 7  # start printing from the top of the board
+  space:character <- copy 32/space
   # print each row
   {
     done?:boolean <- lesser-than row, 0
@@ -166,7 +167,7 @@ recipe print-board screen:address:screen, board:address:array:address:array:char
       f:address:array:character <- index *board, col
       c:character <- index *f, row
       print screen, c
-      print screen, 32/space
+      print screen, space
       col <- add col, 1
       loop
     }
diff --git a/edit/001-editor.mu b/edit/001-editor.mu
index 4ef9be36..fd44d493 100644
--- a/edit/001-editor.mu
+++ b/edit/001-editor.mu
@@ -193,7 +193,8 @@ recipe render screen:address:screen, editor:address:editor-data -> last-row:numb
       at-right?:boolean <- equal column, right
       break-unless at-right?
       # print wrap icon
-      print screen, 8617/loop-back-to-left, 245/grey
+      wrap-icon:character <- copy 8617/loop-back-to-left
+      print screen, wrap-icon, 245/grey
       column <- copy left
       row <- add row, 1
       screen <- move-cursor screen, row, column
@@ -227,10 +228,11 @@ recipe render screen:address:screen, editor:address:editor-data -> last-row:numb
 recipe clear-line-delimited screen:address:screen, column:number, right:number -> screen:address:screen [
   local-scope
   load-ingredients
+  space:character <- copy 32/space
   {
     done?:boolean <- greater-than column, right
     break-if done?
-    screen <- print screen, 32/space
+    screen <- print screen, space
     column <- add column, 1
     loop
   }
diff --git a/edit/003-shortcuts.mu b/edit/003-shortcuts.mu
index 79d53b2a..feab04ea 100644
--- a/edit/003-shortcuts.mu
+++ b/edit/003-shortcuts.mu
@@ -125,7 +125,8 @@ recipe delete-before-cursor editor:address:editor-data, screen:address:screen ->
     loop
   }
   # we're guaranteed not to be at the right margin
-  screen <- print screen, 32/space
+  space:character <- copy 32/space
+  screen <- print screen, space
   go-render? <- copy 0/false
 ]
 
@@ -366,7 +367,8 @@ recipe delete-at-cursor editor:address:editor-data, screen:address:screen -> edi
     loop
   }
   # we're guaranteed not to be at the right margin
-  screen <- print screen, 32/space
+  space:character <- copy 32/space
+  screen <- print screen, space
   go-render? <- copy 0/false
 ]
 
diff --git a/edit/004-programming-environment.mu b/edit/004-programming-environment.mu
index 44a812c5..7ed6376e 100644
--- a/edit/004-programming-environment.mu
+++ b/edit/004-programming-environment.mu
@@ -267,7 +267,8 @@ scenario edit-multiple-editors [
   ]
   # show the cursor at the right window
   run [
-    print screen:address:screen, 9251/␣/cursor
+    8:character/cursor <- copy 9251/␣
+    print screen:address:screen, 8:character/cursor
   ]
   screen-should-contain [
     .           run (F4)           .
@@ -307,7 +308,8 @@ scenario editor-in-focus-keeps-cursor [
   assume-console []
   run [
     event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
-    print screen:address:screen, 9251/␣/cursor
+    4:character/cursor <- copy 9251/␣
+    print screen:address:screen, 4:character/cursor
   ]
   # is cursor at the right place?
   screen-should-contain [
@@ -322,7 +324,8 @@ scenario editor-in-focus-keeps-cursor [
   ]
   run [
     event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
-    print screen:address:screen, 9251/␣/cursor
+    4:character/cursor <- copy 9251/␣
+    print screen:address:screen, 4:character/cursor
   ]
   # cursor should still be right
   screen-should-contain [
@@ -356,7 +359,8 @@ def]
   ]
   run [
     event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
-    print screen:address:screen, 9251/␣/cursor
+    4:character/cursor <- copy 9251/␣
+    print screen:address:screen, 4:character/cursor
   ]
   # cursor moves to end of old line
   screen-should-contain [
@@ -473,7 +477,8 @@ recipe render screen:address:screen, s:address:array:character, left:number, rig
       at-right?:boolean <- equal column, right
       break-unless at-right?
       # print wrap icon
-      print screen, 8617/loop-back-to-left, 245/grey
+      wrap-icon:character <- copy 8617/loop-back-to-left
+      print screen, wrap-icon, 245/grey
       column <- copy left
       row <- add row, 1
       screen <- move-cursor screen, row, column
@@ -488,7 +493,8 @@ recipe render screen:address:screen, s:address:array:character, left:number, rig
       {
         done?:boolean <- greater-than column, right
         break-if done?
-        print screen, 32/space
+        space:character <- copy 32/space
+        print screen, space
         column <- add column, 1
         loop
       }
@@ -534,7 +540,8 @@ recipe render-code screen:address:screen, s:address:array:character, left:number
       at-right?:boolean <- equal column, right
       break-unless at-right?
       # print wrap icon
-      print screen, 8617/loop-back-to-left, 245/grey
+      wrap-icon:character <- copy 8617/loop-back-to-left
+      print screen, wrap-icon, 245/grey
       column <- copy left
       row <- add row, 1
       screen <- move-cursor screen, row, column
@@ -549,7 +556,8 @@ recipe render-code screen:address:screen, s:address:array:character, left:number
       {
         done?:boolean <- greater-than column, right
         break-if done?
-        print screen, 32/space
+        space:character <- copy 32/space
+        print screen, space
         column <- add column, 1
         loop
       }
diff --git a/edit/005-sandbox.mu b/edit/005-sandbox.mu
index a8a4c5a3..3929fb76 100644
--- a/edit/005-sandbox.mu
+++ b/edit/005-sandbox.mu
@@ -253,7 +253,8 @@ recipe render-sandboxes screen:address:screen, sandbox:address:sandbox-data, lef
   row <- add row, 1
   screen <- move-cursor screen, row, left
   clear-line-delimited screen, left, right
-  print screen, 120/x, 245/grey
+  delete-icon:character <- copy 120/x
+  print screen, delete-icon, 245/grey
   # save menu row so we can detect clicks to it later
   starting-row:address:number <- get-address *sandbox, starting-row-on-screen:offset
   *starting-row <- copy row
@@ -349,9 +350,11 @@ recipe render-screen screen:address:screen, sandbox-screen:address:screen, left:
     column <- copy left
     screen <- move-cursor screen, row, column
     # initial leader for each row: two spaces and a '.'
-    print screen, 32/space, 245/grey
-    print screen, 32/space, 245/grey
-    print screen, 46/full-stop, 245/grey
+    space:character <- copy 32/space
+    print screen, space, 245/grey
+    print screen, space, 245/grey
+    full-stop:character <- copy 46/period
+    print screen, full-stop, 245/grey
     column <- add left, 3
     {
       # print row
@@ -372,13 +375,13 @@ recipe render-screen screen:address:screen, sandbox-screen:address:screen, left:
       loop
     }
     # print final '.'
-    print screen, 46/full-stop, 245/grey
+    print screen, full-stop, 245/grey
     column <- add column, 1
     {
       # clear rest of current line
       line-done?:boolean <- greater-than column, right
       break-if line-done?
-      print screen, 32/space
+      print screen, space
       column <- add column, 1
       loop
     }
diff --git a/edit/008-sandbox-test.mu b/edit/008-sandbox-test.mu
index 0ba1941e..77cac2ce 100644
--- a/edit/008-sandbox-test.mu
+++ b/edit/008-sandbox-test.mu
@@ -45,7 +45,8 @@ recipe foo [
   ]
   # cursor should remain unmoved
   run [
-    print screen:address:screen, 9251/␣/cursor
+    4:character/cursor <- copy 9251/␣
+    print screen:address:screen, 4:character/cursor
   ]
   screen-should-contain [
     .                     run (F4)           .
diff --git a/edit/009-sandbox-trace.mu b/edit/009-sandbox-trace.mu
index f3e78701..03bde749 100644
--- a/edit/009-sandbox-trace.mu
+++ b/edit/009-sandbox-trace.mu
@@ -30,7 +30,8 @@ recipe foo [
   ]
   run [
     event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
-    print screen:address:screen, 9251/␣/cursor
+    4:character/cursor-icon <- copy 9251/␣
+    print screen:address:screen, 4:character/cursor-icon
   ]
   # trace now printed and cursor shouldn't have budged
   screen-should-contain [
@@ -59,7 +60,7 @@ recipe foo [
   ]
   run [
     event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
-    print screen:address:screen, 9251/␣/cursor
+    print screen:address:screen, 4:character/cursor-icon
   ]
   # trace hidden again
   screen-should-contain [
diff --git a/sandbox/001-editor.mu b/sandbox/001-editor.mu
index 4ef9be36..fd44d493 100644
--- a/sandbox/001-editor.mu
+++ b/sandbox/001-editor.mu
@@ -193,7 +193,8 @@ recipe render screen:address:screen, editor:address:editor-data -> last-row:numb
       at-right?:boolean <- equal column, right
       break-unless at-right?
       # print wrap icon
-      print screen, 8617/loop-back-to-left, 245/grey
+      wrap-icon:character <- copy 8617/loop-back-to-left
+      print screen, wrap-icon, 245/grey
       column <- copy left
       row <- add row, 1
       screen <- move-cursor screen, row, column
@@ -227,10 +228,11 @@ recipe render screen:address:screen, editor:address:editor-data -> last-row:numb
 recipe clear-line-delimited screen:address:screen, column:number, right:number -> screen:address:screen [
   local-scope
   load-ingredients
+  space:character <- copy 32/space
   {
     done?:boolean <- greater-than column, right
     break-if done?
-    screen <- print screen, 32/space
+    screen <- print screen, space
     column <- add column, 1
     loop
   }
diff --git a/sandbox/003-shortcuts.mu b/sandbox/003-shortcuts.mu
index 79d53b2a..feab04ea 100644
--- a/sandbox/003-shortcuts.mu
+++ b/sandbox/003-shortcuts.mu
@@ -125,7 +125,8 @@ recipe delete-before-cursor editor:address:editor-data, screen:address:screen ->
     loop
   }
   # we're guaranteed not to be at the right margin
-  screen <- print screen, 32/space
+  space:character <- copy 32/space
+  screen <- print screen, space
   go-render? <- copy 0/false
 ]
 
@@ -366,7 +367,8 @@ recipe delete-at-cursor editor:address:editor-data, screen:address:screen -> edi
     loop
   }
   # we're guaranteed not to be at the right margin
-  screen <- print screen, 32/space
+  space:character <- copy 32/space
+  screen <- print screen, space
   go-render? <- copy 0/false
 ]
 
diff --git a/sandbox/004-programming-environment.mu b/sandbox/004-programming-environment.mu
index 1535e75c..4a16d2fa 100644
--- a/sandbox/004-programming-environment.mu
+++ b/sandbox/004-programming-environment.mu
@@ -223,7 +223,8 @@ recipe render screen:address:screen, s:address:array:character, left:number, rig
       at-right?:boolean <- equal column, right
       break-unless at-right?
       # print wrap icon
-      print screen, 8617/loop-back-to-left, 245/grey
+      wrap-icon:character <- copy 8617/loop-back-to-left
+      print screen, wrap-icon, 245/grey
       column <- copy left
       row <- add row, 1
       screen <- move-cursor screen, row, column
@@ -238,7 +239,8 @@ recipe render screen:address:screen, s:address:array:character, left:number, rig
       {
         done?:boolean <- greater-than column, right
         break-if done?
-        print screen, 32/space
+        space:character <- copy 32/space
+        print screen, space
         column <- add column, 1
         loop
       }
@@ -284,7 +286,8 @@ recipe render-code screen:address:screen, s:address:array:character, left:number
       at-right?:boolean <- equal column, right
       break-unless at-right?
       # print wrap icon
-      print screen, 8617/loop-back-to-left, 245/grey
+      wrap-icon:character <- copy 8617/loop-back-to-left
+      print screen, wrap-icon, 245/grey
       column <- copy left
       row <- add row, 1
       screen <- move-cursor screen, row, column
@@ -299,7 +302,8 @@ recipe render-code screen:address:screen, s:address:array:character, left:number
       {
         done?:boolean <- greater-than column, right
         break-if done?
-        print screen, 32/space
+        space:character <- copy 32/space
+        print screen, space
         column <- add column, 1
         loop
       }
diff --git a/sandbox/005-sandbox.mu b/sandbox/005-sandbox.mu
index db0a195b..a424209a 100644
--- a/sandbox/005-sandbox.mu
+++ b/sandbox/005-sandbox.mu
@@ -234,7 +234,8 @@ recipe render-sandboxes screen:address:screen, sandbox:address:sandbox-data, lef
   row <- add row, 1
   screen <- move-cursor screen, row, left
   clear-line-delimited screen, left, right
-  print screen, 120/x, 245/grey
+  delete-icon:character <- copy 120/x
+  print screen, delete-icon, 245/grey
   # save menu row so we can detect clicks to it later
   starting-row:address:number <- get-address *sandbox, starting-row-on-screen:offset
   *starting-row <- copy row
@@ -330,9 +331,11 @@ recipe render-screen screen:address:screen, sandbox-screen:address:screen, left:
     column <- copy left
     screen <- move-cursor screen, row, column
     # initial leader for each row: two spaces and a '.'
-    print screen, 32/space, 245/grey
-    print screen, 32/space, 245/grey
-    print screen, 46/full-stop, 245/grey
+    space:character <- copy 32/space
+    print screen, space, 245/grey
+    print screen, space, 245/grey
+    full-stop:character <- copy 46/period
+    print screen, full-stop, 245/grey
     column <- add left, 3
     {
       # print row
@@ -353,13 +356,13 @@ recipe render-screen screen:address:screen, sandbox-screen:address:screen, left:
       loop
     }
     # print final '.'
-    print screen, 46/full-stop, 245/grey
+    print screen, full-stop, 245/grey
     column <- add column, 1
     {
       # clear rest of current line
       line-done?:boolean <- greater-than column, right
       break-if line-done?
-      print screen, 32/space
+      print screen, space
       column <- add column, 1
       loop
     }
diff --git a/sandbox/009-sandbox-trace.mu b/sandbox/009-sandbox-trace.mu
index df74df47..45759b75 100644
--- a/sandbox/009-sandbox-trace.mu
+++ b/sandbox/009-sandbox-trace.mu
@@ -25,7 +25,8 @@ scenario sandbox-click-on-code-toggles-app-trace [
   ]
   run [
     event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
-    print screen:address:screen, 9251/␣/cursor
+    4:character/cursor-icon <- copy 9251/␣
+    print screen:address:screen, 4:character/cursor-icon
   ]
   # trace now printed and cursor shouldn't have budged
   screen-should-contain [
@@ -54,7 +55,7 @@ scenario sandbox-click-on-code-toggles-app-trace [
   ]
   run [
     event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
-    print screen:address:screen, 9251/␣/cursor
+    print screen:address:screen, 4:character/cursor-icon
   ]
   # trace hidden again
   screen-should-contain [
diff --git a/screen.mu b/screen.mu
index 665822ac..1061d191 100644
--- a/screen.mu
+++ b/screen.mu
@@ -5,7 +5,8 @@
 
 recipe main [
   open-console
-  print 0/screen, 97/a, 2/red
+  10:character <- copy 97/a
+  print 0/screen, 10:character/a, 2/red
   1:number/raw, 2:number/raw <- cursor-position 0/screen
   wait-for-event 0/console
   clear-screen 0/screen