about summary refs log tree commit diff stats
path: root/sandbox
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-12-11 16:18:18 -0800
committerKartik K. Agaram <vc@akkartik.com>2016-12-11 16:18:18 -0800
commit294b2ab35983ebe95698835bb54bca8bd3eec101 (patch)
treefbc74bea6cefd7b8f527d36a7b7c6804dd886414 /sandbox
parentd5c86dfd8706e6b3ceee7843464797e6fcad4259 (diff)
downloadmu-294b2ab35983ebe95698835bb54bca8bd3eec101.tar.gz
3705 - switch to tested file-system primitives
Diffstat (limited to 'sandbox')
-rw-r--r--sandbox/004-programming-environment.mu31
-rw-r--r--sandbox/005-sandbox.mu143
-rw-r--r--sandbox/006-sandbox-copy.mu34
-rw-r--r--sandbox/007-sandbox-delete.mu42
-rw-r--r--sandbox/008-sandbox-edit.mu102
-rw-r--r--sandbox/009-sandbox-test.mu36
-rw-r--r--sandbox/010-sandbox-trace.mu28
-rw-r--r--sandbox/011-errors.mu233
8 files changed, 393 insertions, 256 deletions
diff --git a/sandbox/004-programming-environment.mu b/sandbox/004-programming-environment.mu
index 84898f71..13502d2a 100644
--- a/sandbox/004-programming-environment.mu
+++ b/sandbox/004-programming-environment.mu
@@ -3,15 +3,9 @@
 def! main [
   local-scope
   open-console
-  initial-sandbox:text <- new []
-  hide-screen 0/screen
-  env:&:environment <- new-programming-environment 0/screen, initial-sandbox
-  env <- restore-sandboxes env
-  render-sandbox-side 0/screen, env, render
-  current-sandbox:&:editor <- get *env, current-sandbox:offset
-  update-cursor 0/screen, current-sandbox, env
-  show-screen 0/screen
-  event-loop 0/screen, 0/console, env
+  env:&:environment <- new-programming-environment 0/filesystem, 0/screen
+  render-all 0/screen, env, render
+  event-loop 0/screen, 0/console, env, 0/filesystem
   # never gets here
 ]
 
@@ -19,26 +13,18 @@ container environment [
   current-sandbox:&:editor
 ]
 
-def new-programming-environment screen:&:screen, initial-sandbox-contents:text -> result:&:environment, screen:&:screen [
+def new-programming-environment resources:&:resources, screen:&:screen, test-sandbox-editor-contents:text -> result:&:environment [
   local-scope
   load-ingredients
   width:num <- screen-width screen
-  height:num <- screen-height screen
-  # top menu
   result <- new environment:type
-  draw-horizontal screen, 0, 0/left, width, 32/space, 0/black, 238/grey
-  button-start:num <- subtract width, 20
-  button-on-screen?:bool <- greater-or-equal button-start, 0
-  assert button-on-screen?, [screen too narrow for menu]
-  screen <- move-cursor screen, 0/row, button-start
-  print screen, [ run (F4) ], 255/white, 161/reddish
   # sandbox editor
-  current-sandbox:&:editor <- new-editor initial-sandbox-contents, 0, width/right
+  current-sandbox:&:editor <- new-editor test-sandbox-editor-contents, 0/left, width/right
   *result <- put *result, current-sandbox:offset, current-sandbox
   <programming-environment-initialization>
 ]
 
-def event-loop screen:&:screen, console:&:console, env:&:environment -> screen:&:screen, console:&:console, env:&:environment [
+def event-loop screen:&:screen, console:&:console, env:&:environment, resources:&:resources -> screen:&:screen, console:&:console, env:&:environment, resources:&:resources [
   local-scope
   load-ingredients
   current-sandbox:&:editor <- get *env, current-sandbox:offset
@@ -357,8 +343,3 @@ after <global-type> [
     loop +next-event
   }
 ]
-
-# dummy
-def restore-sandboxes env:&:environment -> env:&:environment [
-  # do nothing; redefined later
-]
diff --git a/sandbox/005-sandbox.mu b/sandbox/005-sandbox.mu
index 9fd2a08b..b5ccd98f 100644
--- a/sandbox/005-sandbox.mu
+++ b/sandbox/005-sandbox.mu
@@ -7,6 +7,16 @@
 # This layer draws the menubar buttons in non-editable sandboxes but they
 # don't do anything yet. Later layers implement each button.
 
+def! main [
+  local-scope
+  open-console
+  env:&:environment <- new-programming-environment 0/filesystem, 0/screen
+  env <- restore-sandboxes env
+  render-all 0/screen, env, render
+  event-loop 0/screen, 0/console, env, 0/filesystem
+  # never gets here
+]
+
 container environment [
   sandbox:&:sandbox  # list of sandboxes, from top to bottom. TODO: switch to &:list:sandbox
   render-from:num
@@ -32,14 +42,17 @@ scenario run-and-show-results [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 50/width, 15/height
+  # recipes.mu is empty
+  assume-resources [
+  ]
   # sandbox editor contains an instruction without storing outputs
-  env:&:environment <- new-programming-environment screen, [divide-with-remainder 11, 3]
+  env:&:environment <- new-programming-environment resources, screen, [divide-with-remainder 11, 3]
   # run the code in the editors
   assume-console [
     press F4
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # check that screen prints the results
   screen-should-contain [
@@ -82,7 +95,7 @@ scenario run-and-show-results [
     press F4
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # check that screen prints both sandboxes
   screen-should-contain [
@@ -108,9 +121,7 @@ after <global-keypress> [
     do-run?:bool <- equal k, 65532/F4
     break-unless do-run?
     screen <- update-status screen, [running...       ], 245/grey
-    test-recipes:text, _/optional <- next-ingredient
-    error?:bool, env, screen <- run-sandboxes env, screen, test-recipes
-    test-recipes <- copy 0  # abandon
+    error?:bool <- run-sandboxes env, resources, screen
     # F4 might update warnings and results on both sides
     screen <- render-all screen, env, render
     {
@@ -122,10 +133,10 @@ after <global-keypress> [
   }
 ]
 
-def run-sandboxes env:&:environment, screen:&:screen, test-recipes:text -> errors-found?:bool, env:&:environment, screen:&:screen [
+def run-sandboxes env:&:environment, resources:&:resources, screen:&:screen -> errors-found?:bool, env:&:environment, resources:&:resources, screen:&:screen [
   local-scope
   load-ingredients
-  errors-found?:bool, env, screen <- update-recipes env, screen, test-recipes
+  errors-found?:bool <- update-recipes env, resources, screen
   # check contents of editor
   <run-sandboxes-begin>
   current-sandbox:&:editor <- get *env, current-sandbox:offset
@@ -150,7 +161,7 @@ def run-sandboxes env:&:environment, screen:&:screen, test-recipes:text -> error
     *current-sandbox <- put *current-sandbox, top-of-screen:offset, init
   }
   # save all sandboxes before running, just in case we die when running
-  save-sandboxes env
+  save-sandboxes env, resources
   # run all sandboxes
   curr:&:sandbox <- get *env, sandbox:offset
   idx:num <- copy 0
@@ -164,20 +175,13 @@ def run-sandboxes env:&:environment, screen:&:screen, test-recipes:text -> error
   <run-sandboxes-end>
 ]
 
-# load code from recipes.mu, or from test-recipes in tests
+# load code from disk
 # replaced in a later layer (whereupon errors-found? will actually be set)
-def update-recipes env:&:environment, screen:&:screen, test-recipes:text -> errors-found?:bool, env:&:environment, screen:&:screen [
+def update-recipes env:&:environment, resources:&:resources, screen:&:screen -> errors-found?:bool, env:&:environment, screen:&:screen [
   local-scope
   load-ingredients
-  {
-    break-if test-recipes
-    in:text <- restore [recipes.mu]  # newlayer: persistence
-    reload in
-  }
-  {
-    break-unless test-recipes
-    reload test-recipes
-  }
+  in:text <- slurp resources, [lesson/recipes.mu]
+  reload in
   errors-found? <- copy 0/false
 ]
 
@@ -198,7 +202,7 @@ def update-status screen:&:screen, msg:text, color:num -> screen:&:screen [
   screen <- print screen, msg, color, 238/grey/background
 ]
 
-def save-sandboxes env:&:environment [
+def save-sandboxes env:&:environment, resources:&:resources -> resources:&:resources [
   local-scope
   load-ingredients
   current-sandbox:&:editor <- get *env, current-sandbox:offset
@@ -209,8 +213,8 @@ def save-sandboxes env:&:environment [
   {
     break-unless curr
     data:text <- get *curr, data:offset
-    filename:text <- to-text idx
-    save filename, data
+    filename:text <- append [lesson/], idx
+    resources <- dump resources, filename, data
     <end-save-sandbox>
     idx <- add idx, 1
     curr <- get *curr, next-sandbox:offset
@@ -401,7 +405,7 @@ def render-text screen:&:screen, s:text, left:num, right:num, color:num, row:num
 ]
 
 # assumes programming environment has no sandboxes; restores them from previous session
-def! restore-sandboxes env:&:environment -> env:&:environment [
+def restore-sandboxes env:&:environment, resources:&:resources -> env:&:environment [
   local-scope
   load-ingredients
   # read all scenarios, pushing them to end of a list of scenarios
@@ -409,8 +413,8 @@ def! restore-sandboxes env:&:environment -> env:&:environment [
   curr:&:sandbox <- copy 0
   prev:&:sandbox <- copy 0
   {
-    filename:text <- to-text idx
-    contents:text <- restore filename
+    filename:text <- append [lesson/], idx
+    contents:text <- slurp resources, filename
     break-unless contents  # stop at first error; assuming file didn't exist
                            # todo: handle empty sandbox
     # create new sandbox for file
@@ -505,19 +509,23 @@ scenario run-updates-results [
   trace-until 100/app  # trace too long
   assume-screen 50/width, 12/height
   # define a recipe (no indent for the 'add' line below so column numbers are more obvious)
-  recipes:text <- new [ 
-recipe foo [
-local-scope
-z:num <- add 2, 2
-reply z
-]]
+  assume-resources [
+    [lesson/recipes.mu] <- [
+      ||
+      |recipe foo [|
+      |  local-scope|
+      |  z:num <- add 2, 2|
+      |  reply z|
+      |]|
+    ]
+  ]
   # sandbox editor contains an instruction without storing outputs
-  env:&:environment <- new-programming-environment screen, [foo]
+  env:&:environment <- new-programming-environment resources, screen, [foo]  # contents of sandbox editor
   # run the code in the editors
   assume-console [
     press F4
   ]
-  event-loop screen, console, env, recipes
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .                                                  .
@@ -529,17 +537,21 @@ reply z
     .                                                  .
   ]
   # make a change (incrementing one of the args to 'add'), then rerun
-  recipes:text <- new [ 
-def foo [
-local-scope
-z:num <- add 2, 3
-return z
-]]
+  assume-resources [
+    [lesson/recipes.mu] <- [
+      ||
+      |recipe foo [|
+      |  local-scope|
+      |  z:num <- add 2, 3|
+      |  reply z|
+      |]|
+    ]
+  ]
   assume-console [
     press F4
   ]
   run [
-    event-loop screen, console, env, recipes
+    event-loop screen, console, env, resources
   ]
   # check that screen updates the result on the right
   screen-should-contain [
@@ -558,14 +570,17 @@ scenario run-instruction-manages-screen-per-sandbox [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
-  # editor contains an instruction
-  env:&:environment <- new-programming-environment screen, [print-integer screen, 4]
+  # empty recipes
+  assume-resources [
+  ]
+  # sandbox editor contains an instruction
+  env:&:environment <- new-programming-environment resources, screen, [print-integer screen, 4]  # contents of sandbox editor
   # run the code in the editor
   assume-console [
     press F4
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # check that it prints a little toy screen
   screen-should-contain [
@@ -629,13 +644,15 @@ scenario scrolling-down-past-bottom-of-sandbox-editor [
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
   # initialize
-  env:&:environment <- new-programming-environment screen, [add 2, 2]
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [add 2, 2]
   render-all screen, env, render
   assume-console [
     # create a sandbox
     press F4
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .                                                  .
@@ -651,7 +668,7 @@ scenario scrolling-down-past-bottom-of-sandbox-editor [
     press page-down
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
     cursor:char <- copy 9251/␣
     print screen, cursor
   ]
@@ -671,7 +688,7 @@ scenario scrolling-down-past-bottom-of-sandbox-editor [
     press page-up
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
     cursor:char <- copy 9251/␣
     print screen, cursor
   ]
@@ -765,7 +782,9 @@ scenario scrolling-through-multiple-sandboxes [
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
   # initialize environment
-  env:&:environment <- new-programming-environment screen, []
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, []
   render-all screen, env, render
   # create 2 sandboxes
   assume-console [
@@ -775,7 +794,7 @@ scenario scrolling-through-multiple-sandboxes [
     type [add 1, 1]
     press F4
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   cursor:char <- copy 9251/␣
   print screen, cursor
   screen-should-contain [
@@ -797,7 +816,7 @@ scenario scrolling-through-multiple-sandboxes [
     press page-down
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
     cursor:char <- copy 9251/␣
     print screen, cursor
   ]
@@ -821,7 +840,7 @@ scenario scrolling-through-multiple-sandboxes [
     press page-down
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # just second sandbox displayed
   screen-should-contain [
@@ -838,7 +857,7 @@ scenario scrolling-through-multiple-sandboxes [
     press page-down
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # no change
   screen-should-contain [
@@ -855,7 +874,7 @@ scenario scrolling-through-multiple-sandboxes [
     press page-up
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # back to displaying both sandboxes without editor
   screen-should-contain [
@@ -876,7 +895,7 @@ scenario scrolling-through-multiple-sandboxes [
     press page-up
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
     cursor:char <- copy 9251/␣
     print screen, cursor
   ]
@@ -900,7 +919,7 @@ scenario scrolling-through-multiple-sandboxes [
     press page-up
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
     cursor:char <- copy 9251/␣
     print screen, cursor
   ]
@@ -926,7 +945,9 @@ scenario scrolling-manages-sandbox-index-correctly [
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
   # initialize environment
-  env:&:environment <- new-programming-environment screen, []
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, []
   render-all screen, env, render
   # create a sandbox
   assume-console [
@@ -934,7 +955,7 @@ scenario scrolling-manages-sandbox-index-correctly [
     type [add 1, 1]
     press F4
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .                                                  .
@@ -950,7 +971,7 @@ scenario scrolling-manages-sandbox-index-correctly [
     press page-down
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # sandbox editor hidden; first sandbox displayed
   # cursor moves to first sandbox
@@ -968,7 +989,7 @@ scenario scrolling-manages-sandbox-index-correctly [
     press page-up
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # back to displaying both sandboxes as well as editor
   screen-should-contain [
@@ -986,7 +1007,7 @@ scenario scrolling-manages-sandbox-index-correctly [
     press page-down
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # sandbox editor hidden; first sandbox displayed
   # cursor moves to first sandbox
diff --git a/sandbox/006-sandbox-copy.mu b/sandbox/006-sandbox-copy.mu
index 7201afd7..995f4c7c 100644
--- a/sandbox/006-sandbox-copy.mu
+++ b/sandbox/006-sandbox-copy.mu
@@ -5,11 +5,15 @@ scenario copy-a-sandbox-to-editor [
   local-scope
   trace-until 50/app  # trace too long
   assume-screen 50/width, 10/height
-  env:&:environment <- new-programming-environment screen, [add 1, 1]
+  # empty recipes
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [add 1, 1]  # contents of sandbox editor
+  # run it
   assume-console [
     press F4
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .                                                  .
@@ -47,7 +51,7 @@ scenario copy-a-sandbox-to-editor [
     type [0]
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .                               run (F4)           .
@@ -67,11 +71,15 @@ scenario copy-a-sandbox-to-editor-2 [
   local-scope
   trace-until 50/app  # trace too long
   assume-screen 50/width, 10/height
-  env:&:environment <- new-programming-environment screen, [add 1, 1]
+  # empty recipes
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [add 1, 1]  # contents of sandbox editor
+  # run it
   assume-console [
     press F4
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .                                                  .
@@ -84,12 +92,12 @@ scenario copy-a-sandbox-to-editor-2 [
     .                                                  .
     .                                                  .
   ]
-  # click at right edge of 'copy' button
+  # click at right edge of 'copy' button (just before 'delete')
   assume-console [
     left-click 3, 33
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # it copies into editor
   screen-should-contain [
@@ -109,7 +117,7 @@ scenario copy-a-sandbox-to-editor-2 [
     type [0]
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .                               run (F4)           .
@@ -218,11 +226,15 @@ scenario copy-fails-if-sandbox-editor-not-empty [
   local-scope
   trace-until 50/app  # trace too long
   assume-screen 50/width, 10/height
-  env:&:environment <- new-programming-environment screen, [add 1, 1]
+  # empty recipes
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [add 1, 1]  # contents of sandbox editor
+  # run it
   assume-console [
     press F4
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .                                                  .
@@ -258,7 +270,7 @@ scenario copy-fails-if-sandbox-editor-not-empty [
     type [1]
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .                               run (F4)           .
diff --git a/sandbox/007-sandbox-delete.mu b/sandbox/007-sandbox-delete.mu
index 576d6761..ddfbf692 100644
--- a/sandbox/007-sandbox-delete.mu
+++ b/sandbox/007-sandbox-delete.mu
@@ -4,7 +4,9 @@ scenario deleting-sandboxes [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 50/width, 15/height
-  env:&:environment <- new-programming-environment screen, []
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, []
   # run a few commands
   assume-console [
     type [divide-with-remainder 11, 3]
@@ -12,7 +14,7 @@ scenario deleting-sandboxes [
     type [add 2, 2]
     press F4
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .                                                  .
@@ -33,7 +35,7 @@ scenario deleting-sandboxes [
     left-click 7, 34
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .                               run (F4)           .
@@ -50,7 +52,7 @@ scenario deleting-sandboxes [
     left-click 3, 49
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .                               run (F4)           .
@@ -148,7 +150,9 @@ scenario deleting-sandbox-after-scroll [
   trace-until 100/app  # trace too long
   assume-screen 50/width, 10/height
   # initialize environment
-  env:&:environment <- new-programming-environment screen, []
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, []
   render-all screen, env, render
   # create 2 sandboxes and scroll to second
   assume-console [
@@ -159,7 +163,7 @@ scenario deleting-sandbox-after-scroll [
     press F4
     press page-down
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .──────────────────────────────────────────────────.
@@ -177,7 +181,7 @@ scenario deleting-sandbox-after-scroll [
     left-click 6, 34
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # second sandbox shows in editor; scroll resets to display first sandbox
   screen-should-contain [
@@ -196,7 +200,9 @@ scenario deleting-top-sandbox-after-scroll [
   trace-until 100/app  # trace too long
   assume-screen 50/width, 10/height
   # initialize environment
-  env:&:environment <- new-programming-environment screen, []
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, []
   render-all screen, env, render
   # create 2 sandboxes and scroll to second
   assume-console [
@@ -207,7 +213,7 @@ scenario deleting-top-sandbox-after-scroll [
     press F4
     press page-down
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .──────────────────────────────────────────────────.
@@ -225,7 +231,7 @@ scenario deleting-top-sandbox-after-scroll [
     left-click 2, 34
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # second sandbox shows in editor; scroll resets to display first sandbox
   screen-should-contain [
@@ -244,7 +250,9 @@ scenario deleting-final-sandbox-after-scroll [
   trace-until 100/app  # trace too long
   assume-screen 50/width, 10/height
   # initialize environment
-  env:&:environment <- new-programming-environment screen, []
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, []
   render-all screen, env, render
   # create 2 sandboxes and scroll to second
   assume-console [
@@ -256,7 +264,7 @@ scenario deleting-final-sandbox-after-scroll [
     press page-down
     press page-down
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .──────────────────────────────────────────────────.
@@ -271,7 +279,7 @@ scenario deleting-final-sandbox-after-scroll [
     left-click 2, 34
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # implicitly scroll up to first sandbox
   screen-should-contain [
@@ -291,7 +299,9 @@ scenario deleting-updates-sandbox-count [
   trace-until 100/app  # trace too long
   assume-screen 50/width, 10/height
   # initialize environment
-  env:&:environment <- new-programming-environment screen, []
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, []
   render-all screen, env, render
   # create 2 sandboxes
   assume-console [
@@ -301,7 +311,7 @@ scenario deleting-updates-sandbox-count [
     type [add 1, 1]
     press F4
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .                                                  .
@@ -321,7 +331,7 @@ scenario deleting-updates-sandbox-count [
     press page-down
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # shouldn't go past last sandbox
   screen-should-contain [
diff --git a/sandbox/008-sandbox-edit.mu b/sandbox/008-sandbox-edit.mu
index 7565e391..ff45d87b 100644
--- a/sandbox/008-sandbox-edit.mu
+++ b/sandbox/008-sandbox-edit.mu
@@ -1,15 +1,18 @@
 ## editing sandboxes after they've been created
 
-scenario clicking-on-a-sandbox-moves-it-to-editor [
+scenario clicking-on-sandbox-edit-button-moves-it-to-editor [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 50/width, 10/height
-  # run something
-  env:&:environment <- new-programming-environment screen, [add 2, 2]
+  # empty recipes
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [add 2, 2]
+  # run it
   assume-console [
     press F4
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .                                                  .
@@ -20,12 +23,64 @@ scenario clicking-on-a-sandbox-moves-it-to-editor [
     .──────────────────────────────────────────────────.
     .                                                  .
   ]
-  # click somewhere on the sandbox
+  # click at left edge of 'edit' button
   assume-console [
     left-click 3, 4
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
+  ]
+  # it pops back into editor
+  screen-should-contain [
+    .                               run (F4)           .
+    .add 2, 2                                          .
+    .──────────────────────────────────────────────────.
+    .                                                  .
+  ]
+  # cursor should be in the right place
+  assume-console [
+    type [0]
+  ]
+  run [
+    event-loop screen, console, env, resources
+  ]
+  screen-should-contain [
+    .                               run (F4)           .
+    .0add 2, 2                                         .
+    .──────────────────────────────────────────────────.
+    .                                                  .
+  ]
+]
+
+scenario clicking-on-sandbox-edit-button-moves-it-to-editor-2 [
+  local-scope
+  trace-until 100/app  # trace too long
+  assume-screen 50/width, 10/height
+  # empty recipes
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [add 2, 2]
+  # run it
+  assume-console [
+    press F4
+  ]
+  event-loop screen, console, env, resources
+  screen-should-contain [
+    .                               run (F4)           .
+    .                                                  .
+    .──────────────────────────────────────────────────.
+    .0   edit           copy           delete          .
+    .add 2, 2                                          .
+    .4                                                 .
+    .──────────────────────────────────────────────────.
+    .                                                  .
+  ]
+  # click at right edge of 'edit' button (just before 'copy')
+  assume-console [
+    left-click 3, 18
+  ]
+  run [
+    event-loop screen, console, env, resources
   ]
   # it pops back into editor
   screen-should-contain [
@@ -39,7 +94,7 @@ scenario clicking-on-a-sandbox-moves-it-to-editor [
     type [0]
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .                               run (F4)           .
@@ -104,13 +159,16 @@ scenario sandbox-with-print-can-be-edited [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
-  # run a print instruction
-  env:&:environment <- new-programming-environment screen, [print-integer screen, 4]
+  # empty recipes
+  assume-resources [
+  ]
+  # right editor contains a print instruction
+  env:&:environment <- new-programming-environment resources, screen, [print-integer screen, 4]
   # run the sandbox
   assume-console [
     press F4
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .                                                  .
@@ -131,7 +189,7 @@ scenario sandbox-with-print-can-be-edited [
     left-click 3, 18
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .                               run (F4)           .
@@ -147,7 +205,9 @@ scenario editing-sandbox-after-scrolling-resets-scroll [
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
   # initialize environment
-  env:&:environment <- new-programming-environment screen, []
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, []
   render-all screen, env, render
   # create 2 sandboxes and scroll to second
   assume-console [
@@ -159,7 +219,7 @@ scenario editing-sandbox-after-scrolling-resets-scroll [
     press page-down
     press page-down
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .──────────────────────────────────────────────────.
@@ -174,7 +234,7 @@ scenario editing-sandbox-after-scrolling-resets-scroll [
     left-click 2, 10
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # second sandbox shows in editor; scroll resets to display first sandbox
   screen-should-contain [
@@ -194,9 +254,11 @@ scenario editing-sandbox-updates-sandbox-count [
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
   # initialize environment
-  env:&:environment <- new-programming-environment screen, []
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, []
   render-all screen, env, render
-  # create 2 sandboxes and scroll to second
+  # create 2 sandboxes
   assume-console [
     press ctrl-n
     type [add 2, 2]
@@ -204,7 +266,7 @@ scenario editing-sandbox-updates-sandbox-count [
     type [add 1, 1]
     press F4
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .                                                  .
@@ -221,7 +283,7 @@ scenario editing-sandbox-updates-sandbox-count [
     press F4
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # no change in contents
   screen-should-contain [
@@ -241,9 +303,9 @@ scenario editing-sandbox-updates-sandbox-count [
     press page-down
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
-  # screen should show just final sandbox
+  # screen should show just final sandbox with the right index (1)
   screen-should-contain [
     .                               run (F4)           .
     .──────────────────────────────────────────────────.
diff --git a/sandbox/009-sandbox-test.mu b/sandbox/009-sandbox-test.mu
index 1c36a769..2ee45a1e 100644
--- a/sandbox/009-sandbox-test.mu
+++ b/sandbox/009-sandbox-test.mu
@@ -5,16 +5,19 @@ scenario sandbox-click-on-result-toggles-color-to-green [
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
   # basic recipe
-  recipes:text <- new [ 
-recipe foo [
-  reply 4
-]]
-  env:&:environment <- new-programming-environment screen, [foo]
+  assume-resources [
+    [lesson/recipes.mu] <- [
+      |recipe foo [|
+      |  reply 4|
+      |]|
+    ]
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [foo]
   # run it
   assume-console [
     press F4
   ]
-  event-loop screen, console, env, recipes
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .                                                  .
@@ -30,7 +33,7 @@ recipe foo [
     left-click 5, 21
   ]
   run [
-    event-loop screen, console, env, recipes
+    event-loop screen, console, env, resources
   ]
   # color toggles to green
   screen-should-contain-in-color 2/green, [
@@ -58,16 +61,19 @@ recipe foo [
     .                                                  .
   ]
   # now change the result
-  new-recipes:text <- new [ 
-recipe foo [
-  reply 3
-]]
+  assume-resources [
+    [lesson/recipes.mu] <- [
+      |recipe foo [|
+      |  reply 3|
+      |]|
+    ]
+  ]
   # then rerun
   assume-console [
     press F4
   ]
   run [
-    event-loop screen, console, env, new-recipes
+    event-loop screen, console, env, resources
   ]
   # result turns red
   screen-should-contain-in-color 1/red, [
@@ -93,14 +99,14 @@ before <end-save-sandbox> [
     expected-response:text <- get *curr, expected-response:offset
     break-unless expected-response
     filename <- append filename, [.out]
-    save filename, expected-response
+    resources <- dump resources, filename, expected-response
   }
 ]
 
 before <end-restore-sandbox> [
   {
     filename <- append filename, [.out]
-    contents <- restore filename
+    contents <- slurp resources, filename
     break-unless contents
     *curr <- put *curr, expected-response:offset, contents
   }
@@ -125,7 +131,7 @@ after <global-touch> [
     break-unless sandbox
     # toggle its expected-response, and save session
     sandbox <- toggle-expected-response sandbox
-    save-sandboxes env
+    save-sandboxes env, resources
     hide-screen screen
     screen <- render-sandbox-side screen, env, render
     screen <- update-cursor screen, current-sandbox, env
diff --git a/sandbox/010-sandbox-trace.mu b/sandbox/010-sandbox-trace.mu
index 3368c491..72f6fe03 100644
--- a/sandbox/010-sandbox-trace.mu
+++ b/sandbox/010-sandbox-trace.mu
@@ -4,12 +4,14 @@ scenario sandbox-click-on-code-toggles-app-trace [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 50/width, 10/height
-  env:&:environment <- new-programming-environment screen, [stash [abc]]
   # run a stash instruction
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [stash [abc]]
   assume-console [
     press F4
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .                                                  .
@@ -24,7 +26,7 @@ scenario sandbox-click-on-code-toggles-app-trace [
     left-click 4, 21
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
     cursor:char <- copy 9251/␣
     print screen, cursor
   ]
@@ -50,7 +52,7 @@ scenario sandbox-click-on-code-toggles-app-trace [
     left-click 4, 25
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
     print screen, cursor
   ]
   # trace hidden again
@@ -70,13 +72,15 @@ scenario sandbox-shows-app-trace-and-result [
   trace-until 100/app  # trace too long
   assume-screen 50/width, 10/height
   # run a stash instruction and some code
-  sandbox:text <- new [stash [abc]
+  assume-resources [
+  ]
+  test-sandbox:text <- new [stash [abc]
 add 2, 2]
+  env:&:environment <- new-programming-environment resources, screen, test-sandbox
   assume-console [
     press F4
   ]
-  env:&:environment <- new-programming-environment screen, sandbox
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .                                                  .
@@ -93,7 +97,7 @@ add 2, 2]
     left-click 4, 21
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # trace now printed above result
   screen-should-contain [
@@ -114,13 +118,15 @@ scenario clicking-on-app-trace-does-nothing [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 50/width, 10/height
-  env:&:environment <- new-programming-environment screen, [stash 123456789]
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [stash 123456789]
   # create and expand the trace
   assume-console [
     press F4
     left-click 4, 1
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                               run (F4)           .
     .                                                  .
@@ -134,7 +140,7 @@ scenario clicking-on-app-trace-does-nothing [
     left-click 5, 7
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # no change; doesn't die
   screen-should-contain [
diff --git a/sandbox/011-errors.mu b/sandbox/011-errors.mu
index 7e620e55..7c04621d 100644
--- a/sandbox/011-errors.mu
+++ b/sandbox/011-errors.mu
@@ -4,21 +4,12 @@ container environment [
   recipe-errors:text
 ]
 
-# copy code from recipe editor, save to disk, load, save any errors
-# test-recipes is a hook for testing
-def! update-recipes env:&:environment, screen:&:screen, test-recipes:text -> errors-found?:bool, env:&:environment, screen:&:screen [
+# load code from disk, save any errors
+def! update-recipes env:&:environment, resources:&:resources, screen:&:screen -> errors-found?:bool, env:&:environment, screen:&:screen [
   local-scope
   load-ingredients
-  {
-    break-if test-recipes
-    in:text <- restore [recipes.mu]
-    recipe-errors:text <- reload in
-    *env <- put *env, recipe-errors:offset, recipe-errors
-  }
-  {
-    break-unless test-recipes
-    recipe-errors:text <- reload test-recipes
-  }
+  in:text <- slurp resources, [lesson/recipes.mu]
+  recipe-errors:text <- reload in
   *env <- put *env, recipe-errors:offset, recipe-errors
   # if recipe editor has errors, stop
   {
@@ -128,16 +119,26 @@ scenario run-shows-errors-in-get [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
-  recipes:text <- new [ 
-recipe foo [
-  get 123:num, foo:offset
-]]
-  env:&:environment <- new-programming-environment screen, [foo]
+  assume-resources [
+    [lesson/recipes.mu] <- [
+      |recipe foo [|
+      |  get 123:num, foo:offset|
+      |]|
+    ]
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [foo]
+  render-all screen, env, render
+  screen-should-contain [
+    .                               run (F4)           .
+    .foo                                               .
+    .──────────────────────────────────────────────────.
+    .                                                  .
+  ]
   assume-console [
     press F4
   ]
   run [
-    event-loop screen, console, env, recipes
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .  errors found                 run (F4)           .
@@ -159,7 +160,9 @@ scenario run-updates-status-with-first-erroneous-sandbox [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
-  env:&:environment <- new-programming-environment screen, []
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, []
   assume-console [
     # create invalid sandbox 1
     type [get foo, x:offset]
@@ -169,7 +172,7 @@ scenario run-updates-status-with-first-erroneous-sandbox [
     press F4
   ]
   run [
-    event-loop screen, console, env, []
+    event-loop screen, console, env, resources
   ]
   # status line shows that error is in first sandbox
   screen-should-contain [
@@ -181,7 +184,9 @@ scenario run-updates-status-with-first-erroneous-sandbox-2 [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
-  env:&:environment <- new-programming-environment screen, []
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, []
   assume-console [
     # create invalid sandbox 2
     type [get foo, x:offset]
@@ -194,7 +199,7 @@ scenario run-updates-status-with-first-erroneous-sandbox-2 [
     press F4
   ]
   run [
-    event-loop screen, console, env, []
+    event-loop screen, console, env, resources
   ]
   # status line shows that error is in second sandbox
   screen-should-contain [
@@ -206,11 +211,13 @@ scenario run-hides-errors-from-past-sandboxes [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
-  env:&:environment <- new-programming-environment screen, [get foo, x:offset]   # invalid
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [get foo, x:offset]  # invalid
   assume-console [
     press F4  # generate error
   ]
-  event-loop screen, console, env, []
+  event-loop screen, console, env, resources
   assume-console [
     left-click 3, 10
     press ctrl-k
@@ -218,7 +225,7 @@ scenario run-hides-errors-from-past-sandboxes [
     press F4  # update sandbox
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # error should disappear
   screen-should-contain [
@@ -238,17 +245,21 @@ scenario run-updates-errors-for-shape-shifting-recipes [
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
   # define a shape-shifting recipe with an error
-  recipes:text <- new [recipe foo x:_elem -> z:_elem [
-local-scope
-load-ingredients
-y:&:num <- copy 0
-z <- add x, y
-]]
-  env:&:environment <- new-programming-environment screen, [foo 2]
+  assume-resources [
+    [lesson/recipes.mu] <- [
+      |recipe foo x:_elem -> z:_elem [|
+      |  local-scope|
+      |  load-ingredients|
+      |  y:&:num <- copy 0|
+      |  z <- add x, y|
+      |]|
+    ]
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [foo 2]
   assume-console [
     press F4
   ]
-  event-loop screen, console, env, recipes
+  event-loop screen, console, env, resources
   screen-should-contain [
     .  errors found (0)             run (F4)           .
     .                                                  .
@@ -265,7 +276,7 @@ z <- add x, y
     press F4
   ]
   run [
-    event-loop screen, console, env, recipes
+    event-loop screen, console, env, resources
   ]
   # error should remain unchanged
   screen-should-contain [
@@ -286,17 +297,21 @@ scenario run-avoids-spurious-errors-on-reloading-shape-shifting-recipes [
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
   # overload a well-known shape-shifting recipe
-  recipes:text <- new [recipe length l:&:list:_elem -> n:num [
-]]
+  assume-resources [
+    [lesson/recipes.mu] <- [
+      |recipe length l:&:list:_elem -> n:num [|
+      |]|
+    ]
+  ]
   # call code that uses other variants of it, but not it itself
-  sandbox:text <- new [x:&:list:num <- copy 0
+  test-sandbox:text <- new [x:&:list:num <- copy 0
 to-text x]
-  env:&:environment <- new-programming-environment screen, sandbox
+  env:&:environment <- new-programming-environment resources, screen, test-sandbox
   # run it once
   assume-console [
     press F4
   ]
-  event-loop screen, console, env, recipes
+  event-loop screen, console, env, resources
   # no errors anywhere on screen (can't check anything else, since to-text will return an address)
   screen-should-contain-in-color 1/red, [
     .                                                  .
@@ -314,7 +329,7 @@ to-text x]
     press F4
   ]
   run [
-    event-loop screen, console, env, recipes
+    event-loop screen, console, env, resources
   ]
   # still no errors
   screen-should-contain-in-color 1/red, [
@@ -334,16 +349,19 @@ scenario run-shows-missing-type-errors [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
-  recipes:text <- new [ 
-recipe foo [
-  x <- copy 0
-]]
-  env:&:environment <- new-programming-environment screen, [foo]
+  assume-resources [
+    [lesson/recipes.mu] <- [
+      |recipe foo [|
+      |  x <- copy 0|
+      |]|
+    ]
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [foo]
   assume-console [
     press F4
   ]
   run [
-    event-loop screen, console, env, recipes
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .  errors found                 run (F4)           .
@@ -360,16 +378,18 @@ scenario run-shows-unbalanced-bracket-errors [
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
   # recipe is incomplete (unbalanced '[')
-  recipes:text <- new [ 
-recipe foo \\[
-  x <- copy 0
-]
-  env:&:environment <- new-programming-environment screen, [foo]
+  assume-resources [
+    [lesson/recipes.mu] <- [
+      |recipe foo \\\[|
+      |  x <- copy 0|
+    ]
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [foo]
   assume-console [
     press F4
   ]
   run [
-    event-loop screen, console, env, recipes
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .  errors found                 run (F4)           .
@@ -388,18 +408,21 @@ scenario run-shows-get-on-non-container-errors [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
-  recipes:text <- new [ 
-recipe foo [
-  local-scope
-  x:&:point <- new point:type
-  get x:&:point, 1:offset
-]]
-  env:&:environment <- new-programming-environment screen, [foo]
+  assume-resources [
+    [lesson/recipes.mu] <- [
+      |recipe foo [|
+      |  local-scope|
+      |  x:&:point <- new point:type|
+      |  get x:&:point, 1:offset|
+      |]|
+    ]
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [foo]
   assume-console [
     press F4
   ]
   run [
-    event-loop screen, console, env, recipes
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .  errors found                 run (F4)           .
@@ -416,19 +439,22 @@ scenario run-shows-non-literal-get-argument-errors [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
-  recipes:text <- new [ 
-recipe foo [
-  local-scope
-  x:num <- copy 0
-  y:&:point <- new point:type
-  get *y:&:point, x:num
-]]
-  env:&:environment <- new-programming-environment screen, [foo]
+  assume-resources [
+    [lesson/recipes.mu] <- [
+      |recipe foo [|
+      |  local-scope|
+      |  x:num <- copy 0|
+      |  y:&:point <- new point:type|
+      |  get *y:&:point, x:num|
+      |]|
+    ]
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [foo]
   assume-console [
     press F4
   ]
   run [
-    event-loop screen, console, env, recipes
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .  errors found                 run (F4)           .
@@ -446,16 +472,19 @@ scenario run-shows-errors-everytime [
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
   # try to run a file with an error
-  recipes:text <- new [ 
-recipe foo [
-  local-scope
-  x:num <- copy y:num
-]]
-  env:&:environment <- new-programming-environment screen, [foo]
+  assume-resources [
+    [lesson/recipes.mu] <- [
+      |recipe foo [|
+      |  local-scope|
+      |  x:num <- copy y:num|
+      |]|
+    ]
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [foo]
   assume-console [
     press F4
   ]
-  event-loop screen, console, env, recipes
+  event-loop screen, console, env, resources
   screen-should-contain [
     .  errors found                 run (F4)           .
     .                                                  .
@@ -470,7 +499,7 @@ recipe foo [
     press F4
   ]
   run [
-    event-loop screen, console, env, recipes
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .  errors found                 run (F4)           .
@@ -487,12 +516,15 @@ scenario run-instruction-and-print-errors [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 50/width, 15/height
-  env:&:environment <- new-programming-environment screen, [get 1:&:point, 1:offset]
+  assume-resources [
+  ]
+  # editor contains an illegal instruction
+  env:&:environment <- new-programming-environment resources, screen, [get 1:&:point, 1:offset]
   assume-console [
     press F4
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # check that screen prints error message in red
   screen-should-contain [
@@ -523,16 +555,17 @@ scenario run-instruction-and-print-errors-only-once [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 50/width, 10/height
+  assume-resources [
+  ]
   # editor contains an illegal instruction
-  sandbox:text <- new [get 1234:num, foo:offset]
-  env:&:environment <- new-programming-environment screen, sandbox
+  env:&:environment <- new-programming-environment resources, screen, [get 1234:num, foo:offset]
   # run the code in the editors multiple times
   assume-console [
     press F4
     press F4
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # check that screen prints error message just once
   screen-should-contain [
@@ -553,17 +586,19 @@ scenario sandbox-can-handle-infinite-loop [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
+  assume-resources [
+  ]
   # editor contains an infinite loop
-  sandbox:text <- new [{
+  test-sandbox:text <- new [{
 loop
 }]
-  env:&:environment <- new-programming-environment screen, sandbox
+  env:&:environment <- new-programming-environment resources, screen, test-sandbox
   # run the sandbox
   assume-console [
     press F4
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .  errors found (0)             run (F4)           .
@@ -584,20 +619,24 @@ scenario sandbox-with-errors-shows-trace [
   trace-until 100/app  # trace too long
   assume-screen 50/width, 20/height
   # generate a stash and a error
-  recipes:text <- new [recipe foo [
-local-scope
-a:num <- next-ingredient
-b:num <- next-ingredient
-stash [dividing by], b
-_, c:num <- divide-with-remainder a, b
-reply b
-]]
-  env:&:environment <- new-programming-environment screen, [foo 4, 0]
+  assume-resources [
+    [lesson/recipes.mu] <- [
+      |recipe foo [|
+      |  local-scope|
+      |  a:num <- next-ingredient|
+      |  b:num <- next-ingredient|
+      |  stash [dividing by], b|
+      |  _, c:num <- divide-with-remainder a, b|
+      |  reply b|
+      |]|
+    ]
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [foo 4, 0]
   # run
   assume-console [
     press F4
   ]
-  event-loop screen, console, env, recipes
+  event-loop screen, console, env, resources
   # screen prints error message
   screen-should-contain [
     .  errors found (0)             run (F4)           .
@@ -615,7 +654,7 @@ reply b
     left-click 4, 15
   ]
   run [
-    event-loop screen, console, env, recipes
+    event-loop screen, console, env, resources
   ]
   # screen should expand trace
   screen-should-contain [