diff --git a/088file.mu b/088file.mu index b7358327..69e72933 100644 --- a/088file.mu +++ b/088file.mu @@ -1,5 +1,12 @@ # Wrappers around file system primitives that take a 'resources' object and # are thus easier to test. +# +# - start-reading - asynchronously open a file, returning a channel source for +# receiving the results +# - start-writing - asynchronously open a file, returning a channel sink for +# the data to write +# - slurp - synchronously read from a file +# - dump - synchronously write to a file container resources [ lock:bool @@ -11,25 +18,42 @@ container resource [ contents:text ] -def start-reading resources:&:resources, filename:text -> contents:&:source:char [ +def start-reading resources:&:resources, filename:text -> contents:&:source:char, error?:bool [ local-scope load-ingredients + error? <- copy 0/false { break-unless resources # fake file system - contents <- start-reading-from-fake-resources resources, filename + contents, error? <- start-reading-from-fake-resource resources, filename return } # real file system file:num <- $open-file-for-reading filename - assert file, [file not found] + return-unless file, 0/contents, 1/error? contents:&:source:char, sink:&:sink:char <- new-channel 30 start-running receive-from-file file, sink ] -def start-reading-from-fake-resources resources:&:resources, resource:text -> contents:&:source:char [ +def slurp resources:&:resources, filename:text -> contents:text, error?:bool [ local-scope load-ingredients + source:&:source:char, error?:bool <- start-reading resources, filename + return-if error?, 0/contents + buf:&:buffer <- new-buffer 30/capacity + { + c:char, done?:bool, source <- read source + break-if done? + buf <- append buf, c + loop + } + contents <- buffer-to-array buf +] + +def start-reading-from-fake-resource resources:&:resources, resource:text -> contents:&:source:char, error?:bool [ + local-scope + load-ingredients + error? <- copy 0/no-error i:num <- copy 0 data:&:@:resource <- get *resources, data:offset len:num <- length *data @@ -46,7 +70,7 @@ def start-reading-from-fake-resources resources:&:resources, resource:text -> co start-running receive-from-text curr-contents, sink return } - return 0/not-found + return 0/not-found, 1/error ] def receive-from-file file:num, sink:&:sink:char -> sink:&:sink:char [ @@ -78,18 +102,20 @@ def receive-from-text contents:text, sink:&:sink:char -> sink:&:sink:char [ sink <- close sink ] -def start-writing resources:&:resources, filename:text -> sink:&:sink:char, routine-id:num [ +def start-writing resources:&:resources, filename:text -> sink:&:sink:char, routine-id:num, error?:bool [ local-scope load-ingredients + error? <- copy 0/false source:&:source:char, sink:&:sink:char <- new-channel 30 { break-unless resources # fake file system - routine-id <- start-running transmit-to-fake-file resources, filename, source + routine-id <- start-running transmit-to-fake-resource resources, filename, source return } # real file system file:num <- $open-file-for-writing filename + return-unless file, 0/sink, 0/routine-id, 1/error? { break-if file msg:text <- append [no such file: ] filename @@ -98,6 +124,29 @@ def start-writing resources:&:resources, filename:text -> sink:&:sink:char, rout routine-id <- start-running transmit-to-file file, source ] +def dump resources:&:resources, filename:text, contents:text -> resources:&:resources, error?:bool [ + local-scope + load-ingredients + # todo: really create an empty file + return-unless contents, resources, 0/no-error + sink-file:&:sink:char, write-routine:num, error?:bool <- start-writing resources, filename + return-if error? + i:num <- copy 0 + len:num <- length *contents + { + done?:bool <- greater-or-equal i, len + break-if done? + c:char <- index *contents, i + sink-file <- write sink-file, c + i <- add i, 1 + loop + } + close sink-file + # make sure to wait for the file to be actually written to disk + # (Mu practices structured concurrency: http://250bpm.com/blog:71) + wait-for-routine write-routine +] + def transmit-to-file file:num, source:&:source:char -> source:&:source:char [ local-scope load-ingredients @@ -110,7 +159,7 @@ def transmit-to-file file:num, source:&:source:char -> source:&:source:char [ file <- $close-file file ] -def transmit-to-fake-file resources:&:resources, filename:text, source:&:source:char -> resources:&:resources, source:&:source:char [ +def transmit-to-fake-resource resources:&:resources, filename:text, source:&:source:char -> resources:&:resources, source:&:source:char [ local-scope load-ingredients lock:location <- get-location *resources, lock:offset diff --git a/090scenario_filesystem_test.mu b/090scenario_filesystem_test.mu index 6d212f88..b487bfe0 100644 --- a/090scenario_filesystem_test.mu +++ b/090scenario_filesystem_test.mu @@ -97,17 +97,3 @@ scenario write-to-existing-file-preserves-other-files [ 11 <- 1 # other files also continue to persist unchanged ] ] - -def slurp resources:&:resources, filename:text -> contents:text [ - local-scope - load-ingredients - source:&:source:char <- start-reading resources, filename - buf:&:buffer <- new-buffer 30/capacity - { - c:char, done?:bool, source <- read source - break-if done? - buf <- append buf, c - loop - } - contents <- buffer-to-array buf -] diff --git a/092socket.mu b/092socket.mu index 6cc43659..e9955f4a 100644 --- a/092socket.mu +++ b/092socket.mu @@ -77,7 +77,7 @@ def start-reading-from-network resources:&:resources, uri:text -> contents:&:sou { break-unless resources # fake network - contents <- start-reading-from-fake-resources resources, uri + contents <- start-reading-from-fake-resource resources, uri return } # real network diff --git a/101run_sandboxed.cc b/101run_sandboxed.cc index 66a19426..a3b6292e 100644 --- a/101run_sandboxed.cc +++ b/101run_sandboxed.cc @@ -427,8 +427,8 @@ int trace_error_contents() { if (*--p->contents.end() != '\n') out << '\n'; } string result = out.str(); - if (result.empty()) return 0; truncate(result); + if (result.empty()) return 0; return new_mu_text(result); } diff --git a/102persist.cc b/102persist.cc deleted file mode 100644 index 642385df..00000000 --- a/102persist.cc +++ /dev/null @@ -1,118 +0,0 @@ -//: Dead simple persistence. -//: 'restore' - reads string from a file -//: 'save' - writes string to a file - -:(before "End Primitive Recipe Declarations") -RESTORE, -:(before "End Primitive Recipe Numbers") -put(Recipe_ordinal, "restore", RESTORE); -:(before "End Primitive Recipe Checks") -case RESTORE: { - if (SIZE(inst.ingredients) != 1) { - raise << maybe(get(Recipe, r).name) << "'restore' requires exactly one ingredient, but got '" << inst.original_string << "'\n" << end(); - break; - } - string filename; - if (is_literal_text(inst.ingredients.at(0))) { - ; - } - else if (is_mu_text(inst.ingredients.at(0))) { - ; - } - else { - raise << maybe(get(Recipe, r).name) << "first ingredient of 'restore' should be a string, but got '" << to_string(inst.ingredients.at(0)) << "'\n" << end(); - break; - } - break; -} -:(before "End Primitive Recipe Implementations") -case RESTORE: { - string filename; - if (is_literal_text(current_instruction().ingredients.at(0))) { - filename = current_instruction().ingredients.at(0).name; - } - else if (is_mu_text(current_instruction().ingredients.at(0))) { - filename = read_mu_text(ingredients.at(0).at(0)); - } - if (Current_scenario) { - // do nothing in tests - products.resize(1); - products.at(0).push_back(0); - break; - } - string contents = slurp("lesson/"+filename); - products.resize(1); - if (contents.empty()) - products.at(0).push_back(0); - else - products.at(0).push_back(new_mu_text(contents)); - break; -} - -:(code) -// http://cpp.indi.frih.net/blog/2014/09/how-to-read-an-entire-file-into-memory-in-cpp -string slurp(const string& filename) { - ifstream fin(filename.c_str()); - fin.peek(); - if (!fin) return ""; // don't bother checking errno - ostringstream result; - result << fin.rdbuf(); - fin.close(); - return result.str(); -} - -:(before "End Primitive Recipe Declarations") -SAVE, -:(before "End Primitive Recipe Numbers") -put(Recipe_ordinal, "save", SAVE); -:(before "End Primitive Recipe Checks") -case SAVE: { - if (SIZE(inst.ingredients) != 2) { - raise << maybe(get(Recipe, r).name) << "'save' requires exactly two ingredients, but got '" << inst.original_string << "'\n" << end(); - break; - } - if (is_literal_text(inst.ingredients.at(0))) { - ; - } - else if (is_mu_text(inst.ingredients.at(0))) { - ; - } - else { - raise << maybe(get(Recipe, r).name) << "first ingredient of 'save' should be a string, but got '" << to_string(inst.ingredients.at(0)) << "'\n" << end(); - break; - } - if (!is_mu_text(inst.ingredients.at(1))) { - raise << maybe(get(Recipe, r).name) << "second ingredient of 'save' should be an address:@:char, but got '" << to_string(inst.ingredients.at(1)) << "'\n" << end(); - break; - } - break; -} -:(before "End Primitive Recipe Implementations") -case SAVE: { - if (Current_scenario) break; // do nothing in tests - string filename; - if (is_literal_text(current_instruction().ingredients.at(0))) { - filename = current_instruction().ingredients.at(0).name; - } - else if (is_mu_text(current_instruction().ingredients.at(0))) { - filename = read_mu_text(ingredients.at(0).at(0)); - } - ofstream fout(("lesson/"+filename).c_str()); - if (!fout) break; - string contents = read_mu_text(ingredients.at(1).at(0)); - fout << contents; - fout.close(); - if (!exists("lesson/.git")) break; - // bug in git: git diff -q messes up --exit-code - // explicitly say '--all' for git 1.9 - int status = system("cd lesson; git add --all .; git diff HEAD --exit-code >/dev/null || git commit -a -m . >/dev/null"); - if (status != 0) - raise << "error in commit: contents " << contents << '\n' << end(); - break; -} - -:(code) -bool exists(const string& filename) { - struct stat dummy; - return 0 == stat(filename.c_str(), &dummy); -} diff --git a/cannot_write_tests_for b/cannot_write_tests_for index 01b5cbe8..1cdaa20a 100644 --- a/cannot_write_tests_for +++ b/cannot_write_tests_for @@ -5,7 +5,7 @@ 4. hide/show screen 5. more touch event types 6. sandbox isolation -7. read/write files +7. errors in reading/writing files (missing directory, others?) termbox issues are implementation-specific and not worth testing: whether we clear junk from other processes diff --git a/edit/004-programming-environment.mu b/edit/004-programming-environment.mu index 332b7e18..7efa3d47 100644 --- a/edit/004-programming-environment.mu +++ b/edit/004-programming-environment.mu @@ -6,12 +6,9 @@ def! main [ local-scope open-console - initial-recipe:text <- restore [recipes.mu] - initial-sandbox:text <- new [] - hide-screen 0/screen - env:&:environment <- new-programming-environment 0/screen, initial-recipe, initial-sandbox + env:&:environment <- new-programming-environment 0/filesystem, 0/screen render-all 0/screen, env, render - event-loop 0/screen, 0/console, env + event-loop 0/screen, 0/console, env, 0/filesystem # never gets here ] @@ -21,24 +18,25 @@ container environment [ sandbox-in-focus?:bool # false => cursor in recipes; true => cursor in current-sandbox ] -def new-programming-environment screen:&:screen, initial-recipe-contents:text, initial-sandbox-contents:text -> result:&:environment [ +def new-programming-environment resources:&:resources, screen:&:screen, test-sandbox-editor-contents:text -> result:&:environment [ local-scope load-ingredients width:num <- screen-width screen result <- new environment:type # recipe editor on the left + initial-recipe-contents:text <- slurp resources, [lesson/recipes.mu] # ignore errors divider:num, _ <- divide-with-remainder width, 2 recipes:&:editor <- new-editor initial-recipe-contents, 0/left, divider/right # sandbox editor on the right sandbox-left:num <- add divider, 1 - current-sandbox:&:editor <- new-editor initial-sandbox-contents, sandbox-left, width/right + current-sandbox:&:editor <- new-editor test-sandbox-editor-contents, sandbox-left, width/right *result <- put *result, recipes:offset, recipes *result <- put *result, current-sandbox:offset, current-sandbox *result <- put *result, sandbox-in-focus?:offset, 0/false ] -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 recipes:&:editor <- get *env, recipes:offset @@ -286,7 +284,12 @@ scenario point-at-multiple-editors [ trace-until 100/app # trace too long assume-screen 30/width, 5/height # initialize both halves of screen - env:&:environment <- new-programming-environment screen, [abc], [def] + assume-resources [ + [lesson/recipes.mu] <- [ + |abc| + ] + ] + env:&:environment <- new-programming-environment resources, screen, [def] # contents of sandbox editor # focus on both sides assume-console [ left-click 1, 1 @@ -294,7 +297,7 @@ scenario point-at-multiple-editors [ ] # check cursor column in each run [ - event-loop screen, console, env + event-loop screen, console, env, resources recipes:&:editor <- get *env, recipes:offset 5:num/raw <- get *recipes, cursor-column:offset sandbox:&:editor <- get *env, current-sandbox:offset @@ -311,7 +314,12 @@ scenario edit-multiple-editors [ trace-until 100/app # trace too long assume-screen 30/width, 5/height # initialize both halves of screen - env:&:environment <- new-programming-environment screen, [abc], [def] + assume-resources [ + [lesson/recipes.mu] <- [ + |abc| + ] + ] + env:&:environment <- new-programming-environment resources, screen, [def] # contents of sandbox render-all screen, env, render # type one letter in each of them assume-console [ @@ -321,7 +329,7 @@ scenario edit-multiple-editors [ type [1] ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources recipes:&:editor <- get *env, recipes:offset 5:num/raw <- get *recipes, cursor-column:offset sandbox:&:editor <- get *env, current-sandbox:offset @@ -330,7 +338,8 @@ scenario edit-multiple-editors [ screen-should-contain [ . run (F4) . # this line has a different background, but we don't test that yet .a0bc ┊d1ef . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊──────────────. + . ┊──────────────. + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . . ┊ . ] memory-should-contain [ @@ -345,39 +354,27 @@ scenario edit-multiple-editors [ screen-should-contain [ . run (F4) . .a0bc ┊d1␣f . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊──────────────. + . ┊──────────────. + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . . ┊ . ] ] -scenario multiple-editors-cover-only-their-own-areas [ - local-scope - trace-until 100/app # trace too long - assume-screen 60/width, 10/height - run [ - env:&:environment <- new-programming-environment screen, [abc], [def] - render-all screen, env, render - ] - # divider isn't messed up - screen-should-contain [ - . run (F4) . - .abc ┊def . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────. - . ┊ . - . ┊ . - ] -] - scenario editor-in-focus-keeps-cursor [ local-scope trace-until 100/app # trace too long assume-screen 30/width, 5/height - env:&:environment <- new-programming-environment screen, [abc], [def] + assume-resources [ + [lesson/recipes.mu] <- [ + |abc| + ] + ] + env:&:environment <- new-programming-environment resources, screen, [def] render-all screen, env, render # initialize programming environment and highlight cursor assume-console [] run [ - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor ] @@ -385,7 +382,8 @@ scenario editor-in-focus-keeps-cursor [ screen-should-contain [ . run (F4) . .␣bc ┊def . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊──────────────. + . ┊──────────────. + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . . ┊ . ] # now try typing a letter @@ -393,7 +391,7 @@ scenario editor-in-focus-keeps-cursor [ type [z] ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor ] @@ -401,7 +399,8 @@ scenario editor-in-focus-keeps-cursor [ screen-should-contain [ . run (F4) . .z␣bc ┊def . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊──────────────. + . ┊──────────────. + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . . ┊ . ] ] @@ -410,10 +409,12 @@ scenario backspace-in-sandbox-editor-joins-lines [ local-scope trace-until 100/app # trace too long assume-screen 30/width, 5/height + assume-resources [ + ] # initialize sandbox side with two lines - s:text <- new [abc + test-sandbox-editor-contents:text <- new [abc def] - env:&:environment <- new-programming-environment screen, [], s:text + env:&:environment <- new-programming-environment resources, screen, test-sandbox-editor-contents render-all screen, env, render screen-should-contain [ . run (F4) . @@ -428,7 +429,7 @@ def] press backspace ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor ] diff --git a/edit/005-sandbox.mu b/edit/005-sandbox.mu index 0b1b82f1..7476875d 100644 --- a/edit/005-sandbox.mu +++ b/edit/005-sandbox.mu @@ -10,13 +10,10 @@ def! main [ local-scope open-console - initial-recipe:text <- restore [recipes.mu] - initial-sandbox:text <- new [] - hide-screen 0/screen - env:&:environment <- new-programming-environment 0/screen, initial-recipe, initial-sandbox + 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 + event-loop 0/screen, 0/console, env, 0/filesystem # never gets here ] @@ -46,14 +43,16 @@ scenario run-and-show-results [ trace-until 100/app # trace too long assume-screen 100/width, 15/height # recipe editor 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 [ @@ -103,7 +102,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 [ @@ -129,7 +128,7 @@ after [ do-run?:bool <- equal k, 65532/F4 break-unless do-run? screen <- update-status screen, [running... ], 245/grey - error?:bool, env, screen <- run-sandboxes env, screen + error?:bool <- run-sandboxes env, resources, screen # F4 might update warnings and results on both sides screen <- render-all screen, env, render { @@ -141,10 +140,10 @@ after [ } ] -def run-sandboxes env:&:environment, screen:&:screen -> 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 + errors-found?:bool <- update-recipes env, resources, screen return-if errors-found? # check contents of right editor (sandbox) @@ -170,7 +169,7 @@ def run-sandboxes env:&:environment, screen:&:screen -> errors-found?:bool, env: *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 @@ -184,14 +183,14 @@ def run-sandboxes env:&:environment, screen:&:screen -> errors-found?:bool, env: ] -# copy code from recipe editor, persist to disk, load +# load code from disk # replaced in a later layer (whereupon errors-found? will actually be set) -def update-recipes env:&:environment, screen:&:screen -> errors-found?:bool, env:&:environment, screen:&:screen [ +def update-recipes env:&:environment, resources:&:resources, screen:&:screen -> errors-found?:bool, env:&:environment, resources:&:resources, screen:&:screen [ local-scope load-ingredients recipes:&:editor <- get *env, recipes:offset in:text <- editor-contents recipes - save [recipes.mu], in # newlayer: persistence + resources <- dump resources, [lesson/recipes.mu], in reload in errors-found? <- copy 0/false ] @@ -213,7 +212,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 @@ -224,8 +223,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 idx <- add idx, 1 curr <- get *curr, next-sandbox:offset @@ -415,7 +414,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 @@ -423,8 +422,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 @@ -519,27 +518,32 @@ scenario run-updates-results [ trace-until 100/app # trace too long assume-screen 100/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, recipes, [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 + event-loop screen, console, env, resources screen-should-contain [ . run (F4) . . ┊ . .recipe foo [ ┊─────────────────────────────────────────────────. - .local-scope ┊0 edit copy delete . - .z:num <- add 2, 2 ┊foo . - .reply z ┊4 . + . local-scope ┊0 edit copy delete . + . z:num <- add 2, 2 ┊foo . + . reply z ┊4 . .] ┊─────────────────────────────────────────────────. + . ┊ . .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . . ┊ . ] @@ -551,17 +555,18 @@ reply z press F4 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # check that screen updates the result on the right screen-should-contain [ . run (F4) . . ┊ . .recipe foo [ ┊─────────────────────────────────────────────────. - .local-scope ┊0 edit copy delete . - .z:num <- add 2, 3 ┊foo . - .reply z ┊5 . + . local-scope ┊0 edit copy delete . + . z:num <- add 2, 3 ┊foo . + . reply z ┊5 . .] ┊─────────────────────────────────────────────────. + . ┊ . .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . . ┊ . ] @@ -571,15 +576,17 @@ scenario run-instruction-manages-screen-per-sandbox [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 20/height - # left editor is empty - # right 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 [ @@ -642,13 +649,15 @@ scenario scrolling-down-past-bottom-of-recipe-editor [ local-scope trace-until 100/app assume-screen 100/width, 10/height - env:&:environment <- new-programming-environment screen, [], [] + assume-resources [ + ] + env:&:environment <- new-programming-environment resources, screen, [] render-all screen, env, render assume-console [ press enter press down-arrow ] - event-loop screen, console, env + event-loop screen, console, env, resources # no scroll screen-should-contain [ . run (F4) . @@ -663,14 +672,16 @@ scenario cursor-down-in-recipe-editor [ local-scope trace-until 100/app assume-screen 100/width, 10/height - env:&:environment <- new-programming-environment screen, [], [] + assume-resources [ + ] + env:&:environment <- new-programming-environment resources, screen, [] render-all screen, env, render assume-console [ press enter press up-arrow press down-arrow # while cursor isn't at bottom ] - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor # cursor moves back to bottom @@ -741,7 +752,9 @@ scenario scrolling-down-past-bottom-of-recipe-editor-2 [ local-scope trace-until 100/app assume-screen 100/width, 10/height - env:&:environment <- new-programming-environment screen, [], [] + assume-resources [ + ] + env:&:environment <- new-programming-environment resources, screen, [] render-all screen, env, render assume-console [ # add a line @@ -751,7 +764,7 @@ scenario scrolling-down-past-bottom-of-recipe-editor-2 [ # try to scroll press page-down # or ctrl-f ] - event-loop screen, console, env + event-loop screen, console, env, resources # no scroll, and cursor remains at top line screen-should-contain [ . run (F4) . @@ -766,7 +779,9 @@ scenario scrolling-down-past-bottom-of-recipe-editor-3 [ local-scope trace-until 100/app assume-screen 100/width, 10/height - env:&:environment <- new-programming-environment screen, [], [ab + assume-resources [ + ] + env:&:environment <- new-programming-environment resources, screen, [ab cd] render-all screen, env, render assume-console [ @@ -777,7 +792,7 @@ cd] # move cursor press down-arrow ] - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor # no scroll on recipe side, cursor moves on sandbox side @@ -796,14 +811,16 @@ scenario scrolling-down-past-bottom-of-sandbox-editor [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 10/height - # initialize sandbox side - env:&:environment <- new-programming-environment screen, [], [add 2, 2] + # initialize + 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) . . ┊ . @@ -817,7 +834,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 ] @@ -835,7 +852,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 ] @@ -924,30 +941,33 @@ def previous-sandbox env:&:environment, in:&:sandbox -> out:&:sandbox [ return curr ] -scenario scrolling-down-on-recipe-side [ +scenario scrolling-down-past-bottom-on-recipe-side [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 10/height # initialize sandbox side and create a sandbox - recipes:text <- new [ -] + assume-resources [ + [lesson/recipes.mu] <- [ + || # file containing just a newline + ] + ] # create a sandbox - env:&:environment <- new-programming-environment screen, recipes:text, [add 2, 2] + env:&:environment <- new-programming-environment resources, screen, [add 2, 2] render-all screen, env, render assume-console [ press F4 ] - event-loop screen, console, env + event-loop screen, console, env, resources # hit 'down' in recipe editor assume-console [ press page-down ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor ] - # cursor moves down on recipe side + # cursor doesn't move when the end is already on-screen screen-should-contain [ . run (F4) . .␣ ┊ . @@ -962,7 +982,9 @@ scenario scrolling-through-multiple-sandboxes [ trace-until 100/app # trace too long assume-screen 100/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 [ @@ -972,7 +994,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 [ @@ -992,7 +1014,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 ] @@ -1014,7 +1036,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 [ @@ -1031,7 +1053,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 [ @@ -1048,7 +1070,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 [ @@ -1067,7 +1089,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 ] @@ -1089,7 +1111,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 ] @@ -1113,7 +1135,9 @@ scenario scrolling-manages-sandbox-index-correctly [ trace-until 100/app # trace too long assume-screen 100/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 a sandbox assume-console [ @@ -1121,7 +1145,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) . . ┊ . @@ -1137,7 +1161,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 @@ -1155,7 +1179,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 [ @@ -1173,7 +1197,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/edit/006-sandbox-copy.mu b/edit/006-sandbox-copy.mu index c966ae78..9df5e625 100644 --- a/edit/006-sandbox-copy.mu +++ b/edit/006-sandbox-copy.mu @@ -5,24 +5,22 @@ scenario copy-a-sandbox-to-editor [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 10/height - # basic recipe - recipes:text <- new [ -recipe foo [ - reply 4 -]] - env:&:environment <- new-programming-environment screen, recipes, [foo] + # 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) . . ┊ . - .recipe foo [ ┊─────────────────────────────────────────────────. - . reply 4 ┊0 edit copy delete . - .] ┊foo . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. + . ┊0 edit copy delete . + . ┊add 1, 1 . + . ┊2 . . ┊─────────────────────────────────────────────────. . ┊ . ] @@ -31,16 +29,16 @@ recipe foo [ left-click 3, 69 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # it copies into editor screen-should-contain [ . run (F4) . - . ┊foo . - .recipe foo [ ┊─────────────────────────────────────────────────. - . reply 4 ┊0 edit copy delete . - .] ┊foo . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 . + . ┊add 1, 1 . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. + . ┊0 edit copy delete . + . ┊add 1, 1 . + . ┊2 . . ┊─────────────────────────────────────────────────. . ┊ . ] @@ -49,15 +47,15 @@ recipe foo [ type [0] ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] screen-should-contain [ . run (F4) . - . ┊0foo . - .recipe foo [ ┊─────────────────────────────────────────────────. - . reply 4 ┊0 edit copy delete . - .] ┊foo . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 . + . ┊0add 1, 1 . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. + . ┊0 edit copy delete . + . ┊add 1, 1 . + . ┊2 . . ┊─────────────────────────────────────────────────. . ┊ . ] @@ -67,24 +65,22 @@ scenario copy-a-sandbox-to-editor-2 [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 10/height - # basic recipe - recipes:text <- new [ -recipe foo [ - reply 4 -]] - env:&:environment <- new-programming-environment screen, recipes, [foo] + # 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) . . ┊ . - .recipe foo [ ┊─────────────────────────────────────────────────. - . reply 4 ┊0 edit copy delete . - .] ┊foo . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. + . ┊0 edit copy delete . + . ┊add 1, 1 . + . ┊2 . . ┊─────────────────────────────────────────────────. . ┊ . ] @@ -93,16 +89,16 @@ recipe foo [ left-click 3, 84 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # it copies into editor screen-should-contain [ . run (F4) . - . ┊foo . - .recipe foo [ ┊─────────────────────────────────────────────────. - . reply 4 ┊0 edit copy delete . - .] ┊foo . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 . + . ┊add 1, 1 . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. + . ┊0 edit copy delete . + . ┊add 1, 1 . + . ┊2 . . ┊─────────────────────────────────────────────────. . ┊ . ] @@ -111,15 +107,15 @@ recipe foo [ type [0] ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] screen-should-contain [ . run (F4) . - . ┊0foo . - .recipe foo [ ┊─────────────────────────────────────────────────. - . reply 4 ┊0 edit copy delete . - .] ┊foo . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 . + . ┊0add 1, 1 . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. + . ┊0 edit copy delete . + . ┊add 1, 1 . + . ┊2 . . ┊─────────────────────────────────────────────────. . ┊ . ] @@ -224,24 +220,22 @@ scenario copy-fails-if-sandbox-editor-not-empty [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 10/height - # basic recipe - recipes:text <- new [ -recipe foo [ - reply 4 -]] - env:&:environment <- new-programming-environment screen, recipes, [foo] + # 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) . . ┊ . - .recipe foo [ ┊─────────────────────────────────────────────────. - . reply 4 ┊0 edit copy delete . - .] ┊foo . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. + . ┊0 edit copy delete . + . ┊add 1, 1 . + . ┊2 . . ┊─────────────────────────────────────────────────. . ┊ . ] @@ -252,16 +246,16 @@ recipe foo [ left-click 3, 70 # click 'copy' button ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # copy doesn't happen screen-should-contain [ . run (F4) . . ┊0 . - .recipe foo [ ┊─────────────────────────────────────────────────. - . reply 4 ┊0 edit copy delete . - .] ┊foo . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. + . ┊0 edit copy delete . + . ┊add 1, 1 . + . ┊2 . . ┊─────────────────────────────────────────────────. . ┊ . ] @@ -270,15 +264,15 @@ recipe foo [ type [1] ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] screen-should-contain [ . run (F4) . . ┊01 . - .recipe foo [ ┊─────────────────────────────────────────────────. - . reply 4 ┊0 edit copy delete . - .] ┊foo . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. + . ┊0 edit copy delete . + . ┊add 1, 1 . + . ┊2 . . ┊─────────────────────────────────────────────────. . ┊ . ] diff --git a/edit/007-sandbox-delete.mu b/edit/007-sandbox-delete.mu index 555d2859..4fa3c37d 100644 --- a/edit/007-sandbox-delete.mu +++ b/edit/007-sandbox-delete.mu @@ -4,7 +4,9 @@ scenario deleting-sandboxes [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 15/height - env:&:environment <- new-programming-environment screen, [], [] + assume-resources [ + ] + env:&:environment <- new-programming-environment resources, screen, [] # run a few commands assume-console [ left-click 1, 80 @@ -13,7 +15,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) . . ┊ . @@ -34,7 +36,7 @@ scenario deleting-sandboxes [ left-click 7, 85 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] screen-should-contain [ . run (F4) . @@ -52,7 +54,7 @@ scenario deleting-sandboxes [ left-click 3, 99 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] screen-should-contain [ . run (F4) . @@ -151,7 +153,9 @@ scenario deleting-sandbox-after-scroll [ trace-until 100/app # trace too long assume-screen 100/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 [ @@ -162,7 +166,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, 99 ] 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 100/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) . . ┊─────────────────────────────────────────────────. @@ -222,7 +228,7 @@ scenario deleting-top-sandbox-after-scroll [ left-click 2, 99 ] 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 [ @@ -241,7 +247,9 @@ scenario deleting-final-sandbox-after-scroll [ trace-until 100/app # trace too long assume-screen 100/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 [ @@ -253,7 +261,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) . . ┊─────────────────────────────────────────────────. @@ -268,7 +276,7 @@ scenario deleting-final-sandbox-after-scroll [ left-click 2, 99 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # implicitly scroll up to first sandbox screen-should-contain [ @@ -288,7 +296,9 @@ scenario deleting-updates-sandbox-count [ trace-until 100/app # trace too long assume-screen 100/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 [ @@ -298,7 +308,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) . . ┊ . @@ -318,7 +328,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/edit/008-sandbox-edit.mu b/edit/008-sandbox-edit.mu index dcd0967d..a857e88c 100644 --- a/edit/008-sandbox-edit.mu +++ b/edit/008-sandbox-edit.mu @@ -1,27 +1,25 @@ ## 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 100/width, 10/height - # basic recipe - recipes:text <- new [ -recipe foo [ - reply 4 -]] - env:&:environment <- new-programming-environment screen, recipes, [foo] + # 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) . . ┊ . - .recipe foo [ ┊─────────────────────────────────────────────────. - . reply 4 ┊0 edit copy delete . - .] ┊foo . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. + . ┊0 edit copy delete . + . ┊add 2, 2 . + . ┊4 . . ┊─────────────────────────────────────────────────. . ┊ . ] @@ -30,16 +28,13 @@ recipe foo [ left-click 3, 55 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # it pops back into editor screen-should-contain [ . run (F4) . - . ┊foo . - .recipe foo [ ┊─────────────────────────────────────────────────. - . reply 4 ┊ . - .] ┊ . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . + . ┊add 2, 2 . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. . ┊ . ] # cursor should be in the right place @@ -47,41 +42,36 @@ recipe foo [ type [0] ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] screen-should-contain [ . run (F4) . - . ┊0foo . - .recipe foo [ ┊─────────────────────────────────────────────────. - . reply 4 ┊ . - .] ┊ . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . + . ┊0add 2, 2 . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. . ┊ . ] ] -scenario clicking-on-a-sandbox-moves-it-to-editor-2 [ +scenario clicking-on-sandbox-edit-button-moves-it-to-editor-2 [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 10/height - # basic recipe - recipes:text <- new [ -recipe foo [ - reply 4 -]] - env:&:environment <- new-programming-environment screen, recipes, [foo] + # 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) . . ┊ . - .recipe foo [ ┊─────────────────────────────────────────────────. - . reply 4 ┊0 edit copy delete . - .] ┊foo . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. + . ┊0 edit copy delete . + . ┊add 2, 2 . + . ┊4 . . ┊─────────────────────────────────────────────────. . ┊ . ] @@ -90,16 +80,13 @@ recipe foo [ left-click 3, 68 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # it pops back into editor screen-should-contain [ . run (F4) . - . ┊foo . - .recipe foo [ ┊─────────────────────────────────────────────────. - . reply 4 ┊ . - .] ┊ . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . + . ┊add 2, 2 . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. . ┊ . ] # cursor should be in the right place @@ -107,15 +94,12 @@ recipe foo [ type [0] ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] screen-should-contain [ . run (F4) . - . ┊0foo . - .recipe foo [ ┊─────────────────────────────────────────────────. - . reply 4 ┊ . - .] ┊ . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . + . ┊0add 2, 2 . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. . ┊ . ] ] @@ -178,13 +162,15 @@ scenario sandbox-with-print-can-be-edited [ trace-until 100/app # trace too long assume-screen 100/width, 20/height # left editor is empty - # right editor contains an instruction - env:&:environment <- new-programming-environment screen, [], [print-integer screen, 4] + 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) . . ┊ . @@ -205,7 +191,7 @@ scenario sandbox-with-print-can-be-edited [ left-click 3, 65 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] screen-should-contain [ . run (F4) . @@ -221,7 +207,9 @@ scenario editing-sandbox-after-scrolling-resets-scroll [ trace-until 100/app # trace too long assume-screen 100/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 [ @@ -233,7 +221,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) . . ┊─────────────────────────────────────────────────. @@ -248,7 +236,7 @@ scenario editing-sandbox-after-scrolling-resets-scroll [ left-click 2, 55 ] 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 [ @@ -268,7 +256,9 @@ scenario editing-sandbox-updates-sandbox-count [ trace-until 100/app # trace too long assume-screen 100/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 [ @@ -278,7 +268,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) . . ┊ . @@ -297,7 +287,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 [ @@ -319,7 +309,7 @@ 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 with the right index (1) screen-should-contain [ diff --git a/edit/009-sandbox-test.mu b/edit/009-sandbox-test.mu index fe9ef059..39b58ecb 100644 --- a/edit/009-sandbox-test.mu +++ b/edit/009-sandbox-test.mu @@ -5,22 +5,25 @@ scenario sandbox-click-on-result-toggles-color-to-green [ trace-until 100/app # trace too long assume-screen 100/width, 10/height # basic recipe - recipes:text <- new [ -recipe foo [ - reply 4 -]] - env:&:environment <- new-programming-environment screen, recipes:text, [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 + event-loop screen, console, env, resources screen-should-contain [ . run (F4) . - . ┊ . - .recipe foo [ ┊─────────────────────────────────────────────────. - . reply 4 ┊0 edit copy delete . - .] ┊foo . + .recipe foo [ ┊ . + . reply 4 ┊─────────────────────────────────────────────────. + .] ┊0 edit copy delete . + . ┊foo . .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 . . ┊─────────────────────────────────────────────────. . ┊ . @@ -30,7 +33,7 @@ recipe foo [ left-click 5, 51 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # color toggles to green screen-should-contain-in-color 2/green, [ @@ -50,26 +53,24 @@ recipe foo [ ] screen-should-contain [ . run (F4) . - .␣ ┊ . - .recipe foo [ ┊─────────────────────────────────────────────────. - . reply 4 ┊0 edit copy delete . - .] ┊foo . + .␣ecipe foo [ ┊ . + . reply 4 ┊─────────────────────────────────────────────────. + .] ┊0 edit copy delete . + . ┊foo . .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 . . ┊─────────────────────────────────────────────────. . ┊ . - . ┊ . - . ┊ . ] # now change the result # then rerun assume-console [ - left-click 3, 11 # cursor to end of line + left-click 2, 11 # cursor to end of line press backspace type [3] press F4 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # result turns red screen-should-contain-in-color 1/red, [ @@ -96,14 +97,14 @@ before [ 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 [ { filename <- append filename, [.out] - contents <- restore filename + contents <- slurp resources, filename break-unless contents *curr <- put *curr, expected-response:offset, contents } @@ -128,7 +129,7 @@ after [ 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, recipes, current-sandbox, sandbox-in-focus?, env diff --git a/edit/010-sandbox-trace.mu b/edit/010-sandbox-trace.mu index 90ee417e..65337127 100644 --- a/edit/010-sandbox-trace.mu +++ b/edit/010-sandbox-trace.mu @@ -5,22 +5,25 @@ scenario sandbox-click-on-code-toggles-app-trace [ trace-until 100/app # trace too long assume-screen 100/width, 10/height # basic recipe - recipes:text <- new [ -recipe foo [ - stash [abc] -]] - env:&:environment <- new-programming-environment screen, recipes, [foo] + assume-resources [ + [lesson/recipes.mu] <- [ + |recipe foo [| + | stash [abc]| + |]| + ] + ] + env:&:environment <- new-programming-environment resources, screen, [foo] # run it assume-console [ press F4 ] - event-loop screen, console, env + event-loop screen, console, env, resources screen-should-contain [ . run (F4) . - . ┊ . - .recipe foo [ ┊─────────────────────────────────────────────────. - . stash [abc] ┊0 edit copy delete . - .] ┊foo . + .recipe foo [ ┊ . + . stash [abc] ┊─────────────────────────────────────────────────. + .] ┊0 edit copy delete . + . ┊foo . .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. . ┊ . ] @@ -29,17 +32,17 @@ recipe foo [ left-click 4, 51 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor ] # trace now printed and cursor shouldn't have budged screen-should-contain [ . run (F4) . - .␣ ┊ . - .recipe foo [ ┊─────────────────────────────────────────────────. - . stash [abc] ┊0 edit copy delete . - .] ┊foo . + .␣ecipe foo [ ┊ . + . stash [abc] ┊─────────────────────────────────────────────────. + .] ┊0 edit copy delete . + . ┊foo . .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊abc . ] screen-should-contain-in-color 245/grey, [ @@ -55,16 +58,16 @@ recipe foo [ left-click 4, 55 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources print screen, cursor ] # trace hidden again screen-should-contain [ . run (F4) . - .␣ ┊ . - .recipe foo [ ┊─────────────────────────────────────────────────. - . stash [abc] ┊0 edit copy delete . - .] ┊foo . + .␣ecipe foo [ ┊ . + . stash [abc] ┊─────────────────────────────────────────────────. + .] ┊0 edit copy delete . + . ┊foo . .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. . ┊ . ] @@ -75,24 +78,27 @@ scenario sandbox-shows-app-trace-and-result [ trace-until 100/app # trace too long assume-screen 100/width, 10/height # basic recipe - recipes:text <- new [ -recipe foo [ - stash [abc] - reply 4 -]] - env:&:environment <- new-programming-environment screen, recipes, [foo] + assume-resources [ + [lesson/recipes.mu] <- [ + |recipe foo [| + | stash [abc]| + | reply 4| + |]| + ] + ] + env:&:environment <- new-programming-environment resources, screen, [foo] # run it assume-console [ press F4 ] - event-loop screen, console, env + event-loop screen, console, env, resources screen-should-contain [ . run (F4) . - . ┊ . - .recipe foo [ ┊─────────────────────────────────────────────────. - . stash [abc] ┊0 edit copy delete . - . reply 4 ┊foo . - .] ┊4 . + .recipe foo [ ┊ . + . stash [abc] ┊─────────────────────────────────────────────────. + . reply 4 ┊0 edit copy delete . + .] ┊foo . + . ┊4 . .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. . ┊ . ] @@ -101,16 +107,16 @@ recipe foo [ left-click 4, 51 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # trace now printed above result screen-should-contain [ . run (F4) . - . ┊ . - .recipe foo [ ┊─────────────────────────────────────────────────. - . stash [abc] ┊0 edit copy delete . - . reply 4 ┊foo . - .] ┊abc . + .recipe foo [ ┊ . + . stash [abc] ┊─────────────────────────────────────────────────. + . reply 4 ┊0 edit copy delete . + .] ┊foo . + . ┊abc . .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊8 instructions run . . ┊4 . . ┊─────────────────────────────────────────────────. @@ -122,13 +128,15 @@ scenario clicking-on-app-trace-does-nothing [ local-scope trace-until 100/app # trace too long assume-screen 100/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, 51 ] - event-loop screen, console, env + event-loop screen, console, env, resources screen-should-contain [ . run (F4) . . ┊ . @@ -142,7 +150,7 @@ scenario clicking-on-app-trace-does-nothing [ left-click 5, 57 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # no change; doesn't die screen-should-contain [ diff --git a/edit/011-errors.mu b/edit/011-errors.mu index b48cd5fa..ad4d8836 100644 --- a/edit/011-errors.mu +++ b/edit/011-errors.mu @@ -5,12 +5,12 @@ container environment [ ] # copy code from recipe editor, persist to disk, load, save any errors -def! update-recipes env:&:environment, screen:&:screen -> errors-found?:bool, env:&:environment, screen:&:screen [ +def! update-recipes env:&:environment, resources:&:resources, screen:&:screen -> errors-found?:bool, env:&:environment, resources:&:resources, screen:&:screen [ local-scope load-ingredients recipes:&:editor <- get *env, recipes:offset in:text <- editor-contents recipes - save [recipes.mu], in + resources <- dump resources, [lesson/recipes.mu], in recipe-errors:text <- reload in *env <- put *env, recipe-errors:offset, recipe-errors # if recipe editor has errors, stop @@ -118,23 +118,36 @@ scenario run-shows-errors-in-get [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 15/height - recipes:text <- new [ -recipe foo [ - get 123:num, foo:offset -]] - env:&:environment <- new-programming-environment screen, recipes, [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) . + .recipe foo [ ┊foo . + . get 123:num, foo:offset ┊─────────────────────────────────────────────────. + .] ┊ . + . ┊ . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . + . ┊ . + ] assume-console [ press F4 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] screen-should-contain [ . errors found run (F4) . - . ┊foo . - .recipe foo [ ┊─────────────────────────────────────────────────. - . get 123:num, foo:offset ┊ . + .recipe foo [ ┊foo . + . get 123:num, foo:offset ┊─────────────────────────────────────────────────. .] ┊ . + . ┊ . .foo: unknown element 'foo' in container 'number' ┊ . .foo: first ingredient of 'get' should be a contai↩┊ . .ner, but got '123:num' ┊ . @@ -158,7 +171,9 @@ scenario run-updates-status-with-first-erroneous-sandbox [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 15/height - env:&:environment <- new-programming-environment screen, [], [] + assume-resources [ + ] + env:&:environment <- new-programming-environment resources, screen, [] assume-console [ left-click 3, 80 # create invalid sandbox 1 @@ -169,7 +184,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 +196,9 @@ scenario run-updates-status-with-first-erroneous-sandbox-2 [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 15/height - env:&:environment <- new-programming-environment screen, [], [] + assume-resources [ + ] + env:&:environment <- new-programming-environment resources, screen, [] assume-console [ left-click 3, 80 # create invalid sandbox 2 @@ -195,7 +212,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 [ @@ -207,13 +224,13 @@ scenario run-hides-errors-from-past-sandboxes [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 15/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 ] - run [ - event-loop screen, console, env - ] + event-loop screen, console, env, resources assume-console [ left-click 3, 58 press ctrl-k @@ -221,7 +238,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 [ @@ -241,26 +258,31 @@ scenario run-updates-errors-for-shape-shifting-recipes [ trace-until 100/app # trace too long assume-screen 100/width, 15/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, recipes, [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 + event-loop screen, console, env, resources screen-should-contain [ . errors found (0) run (F4) . .recipe foo x:_elem -> z:_elem [ ┊ . - .local-scope ┊─────────────────────────────────────────────────. - .load-ingredients ┊0 edit copy delete . - .y:&:num <- copy 0 ┊foo 2 . - .z <- add x, y ┊foo_2: 'add' requires number ingredients, but go↩. + . local-scope ┊─────────────────────────────────────────────────. + . load-ingredients ┊0 edit copy delete . + . y:&:num <- copy 0 ┊foo 2 . + . z <- add x, y ┊foo_2: 'add' requires number ingredients, but go↩. .] ┊t 'y' . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. + . ┊─────────────────────────────────────────────────. + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . . ┊ . ] # now rerun everything @@ -268,18 +290,19 @@ z <- add x, y press F4 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # error should remain unchanged screen-should-contain [ . errors found (0) run (F4) . .recipe foo x:_elem -> z:_elem [ ┊ . - .local-scope ┊─────────────────────────────────────────────────. - .load-ingredients ┊0 edit copy delete . - .y:&:num <- copy 0 ┊foo 2 . - .z <- add x, y ┊foo_3: 'add' requires number ingredients, but go↩. + . local-scope ┊─────────────────────────────────────────────────. + . load-ingredients ┊0 edit copy delete . + . y:&:num <- copy 0 ┊foo 2 . + . z <- add x, y ┊foo_3: 'add' requires number ingredients, but go↩. .] ┊t 'y' . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. + . ┊─────────────────────────────────────────────────. + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . . ┊ . ] ] @@ -289,17 +312,21 @@ scenario run-avoids-spurious-errors-on-reloading-shape-shifting-recipes [ trace-until 100/app # trace too long assume-screen 100/width, 15/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, recipes, sandbox + env:&:environment <- new-programming-environment resources, screen, test-sandbox # run it once assume-console [ press F4 ] - event-loop screen, console, env + 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, [ . . @@ -323,7 +350,7 @@ to-text x] press F4 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # still no errors screen-should-contain-in-color 1/red, [ @@ -349,24 +376,30 @@ scenario run-shows-missing-type-errors [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 15/height - recipes:text <- new [ -recipe foo [ - x <- copy 0 -]] - env:&:environment <- new-programming-environment screen, recipes, [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 + event-loop screen, console, env, resources ] screen-should-contain [ . errors found run (F4) . - . ┊foo . - .recipe foo [ ┊─────────────────────────────────────────────────. - . x <- copy 0 ┊ . + .recipe foo [ ┊foo . + . x <- copy 0 ┊─────────────────────────────────────────────────. .] ┊ . + . ┊ . .foo: missing type for 'x' in 'x <- copy 0' ┊ . + .foo: can't copy '0' to 'x'; types don't match ┊ . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . + . ┊ . ] ] @@ -375,22 +408,23 @@ scenario run-shows-unbalanced-bracket-errors [ trace-until 100/app # trace too long assume-screen 100/width, 15/height # recipe is incomplete (unbalanced '[') - recipes:text <- new [ -recipe foo \\[ - x <- copy 0 -] - env:&:environment <- new-programming-environment screen, recipes, [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 + event-loop screen, console, env, resources ] screen-should-contain [ . errors found run (F4) . - . ┊foo . - .recipe foo \\[ ┊─────────────────────────────────────────────────. - . x <- copy 0 ┊ . + .recipe foo \\[ ┊foo . + . x <- copy 0 ┊─────────────────────────────────────────────────. . ┊ . .9: unbalanced '\\[' for recipe ┊ . .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . @@ -402,27 +436,30 @@ scenario run-shows-get-on-non-container-errors [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 15/height - recipes:text <- new [ -recipe foo [ - local-scope - x:&:point <- new point:type - get x:&:point, 1:offset -]] - env:&:environment <- new-programming-environment screen, recipes, [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 + event-loop screen, console, env, resources ] screen-should-contain [ . errors found run (F4) . - . ┊foo . - .recipe foo [ ┊─────────────────────────────────────────────────. - . local-scope ┊ . + .recipe foo [ ┊foo . + . local-scope ┊─────────────────────────────────────────────────. . x:&:point <- new point:type ┊ . . get x:&:point, 1:offset ┊ . .] ┊ . + . ┊ . .foo: first ingredient of 'get' should be a contai↩┊ . .ner, but got 'x:&:point' ┊ . .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . @@ -434,29 +471,32 @@ scenario run-shows-non-literal-get-argument-errors [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 15/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, recipes, [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 + event-loop screen, console, env, resources ] screen-should-contain [ . errors found run (F4) . - . ┊foo . - .recipe foo [ ┊─────────────────────────────────────────────────. - . local-scope ┊ . + .recipe foo [ ┊foo . + . local-scope ┊─────────────────────────────────────────────────. . x:num <- copy 0 ┊ . . y:&:point <- new point:type ┊ . . get *y:&:point, x:num ┊ . .] ┊ . + . ┊ . .foo: second ingredient of 'get' should have type ↩┊ . .'offset', but got 'x:num' ┊ . .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . @@ -467,25 +507,28 @@ recipe foo [ scenario run-shows-errors-everytime [ local-scope trace-until 100/app # trace too long - # try to run a file with an error assume-screen 100/width, 15/height - recipes:text <- new [ -recipe foo [ - local-scope - x:num <- copy y:num -]] - env:&:environment <- new-programming-environment screen, recipes, [foo] + # try to run a file with an error + 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 + event-loop screen, console, env, resources screen-should-contain [ . errors found run (F4) . - . ┊foo . - .recipe foo [ ┊─────────────────────────────────────────────────. - . local-scope ┊ . + .recipe foo [ ┊foo . + . local-scope ┊─────────────────────────────────────────────────. . x:num <- copy y:num ┊ . .] ┊ . + . ┊ . .foo: tried to read ingredient 'y' in 'x:num <- co↩┊ . .py y:num' but it hasn't been written to yet ┊ . .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . @@ -496,15 +539,15 @@ recipe foo [ press F4 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] screen-should-contain [ . errors found run (F4) . - . ┊foo . - .recipe foo [ ┊─────────────────────────────────────────────────. - . local-scope ┊ . + .recipe foo [ ┊foo . + . local-scope ┊─────────────────────────────────────────────────. . x:num <- copy y:num ┊ . .] ┊ . + . ┊ . .foo: tried to read ingredient 'y' in 'x:num <- co↩┊ . .py y:num' but it hasn't been written to yet ┊ . .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . @@ -516,15 +559,15 @@ scenario run-instruction-and-print-errors [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 10/height - # right editor contains an illegal instruction - sandbox:text <- new [get 1234:num, foo:offset] - env:&:environment <- new-programming-environment screen, [], sandbox - # run the code in the editors + assume-resources [ + ] + # sandbox editor contains an illegal instruction + env:&:environment <- new-programming-environment resources, screen, [get 1234:num, foo: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 [ @@ -578,16 +621,17 @@ scenario run-instruction-and-print-errors-only-once [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 10/height - # right editor contains an illegal instruction - sandbox:text <- new [get 1234:num, foo:offset] - env:&:environment <- new-programming-environment screen, [], sandbox + assume-resources [ + ] + # sandbox editor contains an illegal instruction + 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 [ @@ -608,20 +652,23 @@ scenario sandbox-can-handle-infinite-loop [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 20/height - # left editor is empty - recipes:text <- new [recipe foo [ - { - loop - } -]] - # right editor contains an instruction - env:&:environment <- new-programming-environment screen, recipes, [foo] + # sandbox editor will trigger an infinite loop + assume-resources [ + [lesson/recipes.mu] <- [ + |recipe foo [| + | {| + | loop| + | }| + |]| + ] + ] + env:&:environment <- new-programming-environment resources, screen, [foo] # 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) . @@ -630,7 +677,8 @@ scenario sandbox-can-handle-infinite-loop [ . loop ┊0 edit copy delete . . } ┊foo . .] ┊took too long! . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. + . ┊─────────────────────────────────────────────────. + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . . ┊ . ] ] @@ -640,50 +688,55 @@ scenario sandbox-with-errors-shows-trace [ trace-until 100/app # trace too long assume-screen 100/width, 10/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, recipes, [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 + event-loop screen, console, env, resources # screen prints error message screen-should-contain [ . errors found (0) run (F4) . .recipe foo [ ┊ . - .local-scope ┊─────────────────────────────────────────────────. - .a:num <- next-ingredient ┊0 edit copy delete . - .b:num <- next-ingredient ┊foo 4, 0 . - .stash [dividing by], b ┊foo: divide by zero in '_, c:num <- divide-with-↩. - ._, c:num <- divide-with-remainder a, b ┊remainder a, b' . - .reply b ┊─────────────────────────────────────────────────. + . local-scope ┊─────────────────────────────────────────────────. + . a:num <- next-ingredient ┊0 edit copy delete . + . b:num <- next-ingredient ┊foo 4, 0 . + . stash [dividing by], b ┊foo: divide by zero in '_, c:num <- divide-with-↩. + . _, c:num <- divide-with-remainder a, b ┊remainder a, b' . + . reply b ┊─────────────────────────────────────────────────. .] ┊ . + . ┊ . ] # click on the call in the sandbox assume-console [ left-click 4, 55 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # screen should expand trace screen-should-contain [ . errors found (0) run (F4) . .recipe foo [ ┊ . - .local-scope ┊─────────────────────────────────────────────────. - .a:num <- next-ingredient ┊0 edit copy delete . - .b:num <- next-ingredient ┊foo 4, 0 . - .stash [dividing by], b ┊dividing by 0 . - ._, c:num <- divide-with-remainder a, b ┊14 instructions run . - .reply b ┊foo: divide by zero in '_, c:num <- divide-with-↩. + . local-scope ┊─────────────────────────────────────────────────. + . a:num <- next-ingredient ┊0 edit copy delete . + . b:num <- next-ingredient ┊foo 4, 0 . + . stash [dividing by], b ┊dividing by 0 . + . _, c:num <- divide-with-remainder a, b ┊14 instructions run . + . reply b ┊foo: divide by zero in '_, c:num <- divide-with-↩. .] ┊remainder a, b' . - .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊─────────────────────────────────────────────────. + . ┊─────────────────────────────────────────────────. ] ] diff --git a/html/088file.mu.html b/html/088file.mu.html index 49801745..aae7cae6 100644 --- a/html/088file.mu.html +++ b/html/088file.mu.html @@ -33,6 +33,13 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
 # Wrappers around file system primitives that take a 'resources' object and
 # are thus easier to test.
+#
+# - start-reading - asynchronously open a file, returning a channel source for
+#   receiving the results
+# - start-writing - asynchronously open a file, returning a channel sink for
+#   the data to write
+# - slurp - synchronously read from a file
+# - dump - synchronously write to a file
 
 container resources [
   lock:bool
@@ -44,25 +51,42 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   contents:text
 ]
 
-def start-reading resources:&:resources, filename:text -> contents:&:source:char [
+def start-reading resources:&:resources, filename:text -> contents:&:source:char, error?:bool [
   local-scope
   load-ingredients
+  error? <- copy 0/false
   {
     break-unless resources
     # fake file system
-    contents <- start-reading-from-fake-resources resources, filename
+    contents, error? <- start-reading-from-fake-resource resources, filename
     return
   }
   # real file system
   file:num <- $open-file-for-reading filename
-  assert file, [file not found]
+  return-unless file, 0/contents, 1/error?
   contents:&:source:char, sink:&:sink:char <- new-channel 30
   start-running receive-from-file file, sink
 ]
 
-def start-reading-from-fake-resources resources:&:resources, resource:text -> contents:&:source:char [
+def slurp resources:&:resources, filename:text -> contents:text, error?:bool [
   local-scope
   load-ingredients
+  source:&:source:char, error?:bool <- start-reading resources, filename
+  return-if error?, 0/contents
+  buf:&:buffer <- new-buffer 30/capacity
+  {
+    c:char, done?:bool, source <- read source
+    break-if done?
+    buf <- append buf, c
+    loop
+  }
+  contents <- buffer-to-array buf
+]
+
+def start-reading-from-fake-resource resources:&:resources, resource:text -> contents:&:source:char, error?:bool [
+  local-scope
+  load-ingredients
+  error? <- copy 0/no-error
   i:num <- copy 0
   data:&:@:resource <- get *resources, data:offset
   len:num <- length *data
@@ -79,7 +103,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     start-running receive-from-text curr-contents, sink
     return
   }
-  return 0/not-found
+  return 0/not-found, 1/error
 ]
 
 def receive-from-file file:num, sink:&:sink:char -> sink:&:sink:char [
@@ -111,18 +135,20 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   sink <- close sink
 ]
 
-def start-writing resources:&:resources, filename:text -> sink:&:sink:char, routine-id:num [
+def start-writing resources:&:resources, filename:text -> sink:&:sink:char, routine-id:num, error?:bool [
   local-scope
   load-ingredients
+  error? <- copy 0/false
   source:&:source:char, sink:&:sink:char <- new-channel 30
   {
     break-unless resources
     # fake file system
-    routine-id <- start-running transmit-to-fake-file resources, filename, source
+    routine-id <- start-running transmit-to-fake-resource resources, filename, source
     return
   }
   # real file system
   file:num <- $open-file-for-writing filename
+  return-unless file, 0/sink, 0/routine-id, 1/error?
   {
     break-if file
     msg:text <- append [no such file: ] filename
@@ -131,6 +157,29 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   routine-id <- start-running transmit-to-file file, source
 ]
 
+def dump resources:&:resources, filename:text, contents:text -> resources:&:resources, error?:bool [
+  local-scope
+  load-ingredients
+  # todo: really create an empty file
+  return-unless contents, resources, 0/no-error
+  sink-file:&:sink:char, write-routine:num, error?:bool <- start-writing resources, filename
+  return-if error?
+  i:num <- copy 0
+  len:num <- length *contents
+  {
+    done?:bool <- greater-or-equal i, len
+    break-if done?
+    c:char <- index *contents, i
+    sink-file <- write sink-file, c
+    i <- add i, 1
+    loop
+  }
+  close sink-file
+  # make sure to wait for the file to be actually written to disk
+  # (Mu practices structured concurrency: http://250bpm.com/blog:71)
+  wait-for-routine write-routine
+]
+
 def transmit-to-file file:num, source:&:source:char -> source:&:source:char [
   local-scope
   load-ingredients
@@ -143,7 +192,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   file <- $close-file file
 ]
 
-def transmit-to-fake-file resources:&:resources, filename:text, source:&:source:char -> resources:&:resources, source:&:source:char [
+def transmit-to-fake-resource resources:&:resources, filename:text, source:&:source:char -> resources:&:resources, source:&:source:char [
   local-scope
   load-ingredients
   lock:location <- get-location *resources, lock:offset
diff --git a/html/090scenario_filesystem_test.mu.html b/html/090scenario_filesystem_test.mu.html
index 91d039bb..20aad6a6 100644
--- a/html/090scenario_filesystem_test.mu.html
+++ b/html/090scenario_filesystem_test.mu.html
@@ -13,12 +13,9 @@
 pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
 body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; }
 * { font-size: 12pt; font-size: 1em; }
-.Delimiter { color: #800080; }
-.muControl { color: #c0a020; }
 .Comment { color: #9090ff; }
 .Constant { color: #00a0a0; }
 .Special { color: #c00000; }
-.muRecipe { color: #ff8700; }
 .muScenario { color: #00af00; }
 -->
 
@@ -130,20 +127,6 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     11 <- 1  # other files also continue to persist unchanged
   ]
 ]
-
-def slurp resources:&:resources, filename:text -> contents:text [
-  local-scope
-  load-ingredients
-  source:&:source:char <- start-reading resources, filename
-  buf:&:buffer <- new-buffer 30/capacity
-  {
-    c:char, done?:bool, source <- read source
-    break-if done?
-    buf <- append buf, c
-    loop
-  }
-  contents <- buffer-to-array buf
-]
 
diff --git a/html/092socket.mu.html b/html/092socket.mu.html index f33fb8bd..cbff28cc 100644 --- a/html/092socket.mu.html +++ b/html/092socket.mu.html @@ -111,7 +111,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color { break-unless resources # fake network - contents <- start-reading-from-fake-resources resources, uri + contents <- start-reading-from-fake-resource resources, uri return } # real network diff --git a/html/101run_sandboxed.cc.html b/html/101run_sandboxed.cc.html index 7b5da51b..0090e189 100644 --- a/html/101run_sandboxed.cc.html +++ b/html/101run_sandboxed.cc.html @@ -463,8 +463,8 @@ string strip_comments(string inif (*--p->contents.end() != '\n') out << '\n'; } string result = out.str(); - if (result.empty()) return 0; truncate(result); + if (result.empty()) return 0; return new_mu_text(result); } diff --git a/html/102persist.cc.html b/html/102persist.cc.html deleted file mode 100644 index 863546d2..00000000 --- a/html/102persist.cc.html +++ /dev/null @@ -1,154 +0,0 @@ - - - - -Mu - 102persist.cc - - - - - - - - - - -
-//: Dead simple persistence.
-//:   'restore' - reads string from a file
-//:   'save' - writes string to a file
-
-:(before "End Primitive Recipe Declarations")
-RESTORE,
-:(before "End Primitive Recipe Numbers")
-put(Recipe_ordinal, "restore", RESTORE);
-:(before "End Primitive Recipe Checks")
-case RESTORE: {
-  if (SIZE(inst.ingredients) != 1) {
-    raise << maybe(get(Recipe, r).name) << "'restore' requires exactly one ingredient, but got '" << inst.original_string << "'\n" << end();
-    break;
-  }
-  string filename;
-  if (is_literal_text(inst.ingredients.at(0))) {
-    ;
-  }
-  else if (is_mu_text(inst.ingredients.at(0))) {
-    ;
-  }
-  else {
-    raise << maybe(get(Recipe, r).name) << "first ingredient of 'restore' should be a string, but got '" << to_string(inst.ingredients.at(0)) << "'\n" << end();
-    break;
-  }
-  break;
-}
-:(before "End Primitive Recipe Implementations")
-case RESTORE: {
-  string filename;
-  if (is_literal_text(current_instruction().ingredients.at(0))) {
-    filename = current_instruction().ingredients.at(0).name;
-  }
-  else if (is_mu_text(current_instruction().ingredients.at(0))) {
-    filename = read_mu_text(ingredients.at(0).at(0));
-  }
-  if (Current_scenario) {
-    // do nothing in tests
-    products.resize(1);
-    products.at(0).push_back(0);
-    break;
-  }
-  string contents = slurp("lesson/"+filename);
-  products.resize(1);
-  if (contents.empty())
-    products.at(0).push_back(0);
-  else
-    products.at(0).push_back(new_mu_text(contents));
-  break;
-}
-
-:(code)
-// http://cpp.indi.frih.net/blog/2014/09/how-to-read-an-entire-file-into-memory-in-cpp
-string slurp(const string& filename) {
-  ifstream fin(filename.c_str());
-  fin.peek();
-  if (!fin) return "";  // don't bother checking errno
-  ostringstream result;
-  result << fin.rdbuf();
-  fin.close();
-  return result.str();
-}
-
-:(before "End Primitive Recipe Declarations")
-SAVE,
-:(before "End Primitive Recipe Numbers")
-put(Recipe_ordinal, "save", SAVE);
-:(before "End Primitive Recipe Checks")
-case SAVE: {
-  if (SIZE(inst.ingredients) != 2) {
-    raise << maybe(get(Recipe, r).name) << "'save' requires exactly two ingredients, but got '" << inst.original_string << "'\n" << end();
-    break;
-  }
-  if (is_literal_text(inst.ingredients.at(0))) {
-    ;
-  }
-  else if (is_mu_text(inst.ingredients.at(0))) {
-    ;
-  }
-  else {
-    raise << maybe(get(Recipe, r).name) << "first ingredient of 'save' should be a string, but got '" << to_string(inst.ingredients.at(0)) << "'\n" << end();
-    break;
-  }
-  if (!is_mu_text(inst.ingredients.at(1))) {
-    raise << maybe(get(Recipe, r).name) << "second ingredient of 'save' should be an address:@:char, but got '" << to_string(inst.ingredients.at(1)) << "'\n" << end();
-    break;
-  }
-  break;
-}
-:(before "End Primitive Recipe Implementations")
-case SAVE: {
-  if (Current_scenario) break;  // do nothing in tests
-  string filename;
-  if (is_literal_text(current_instruction().ingredients.at(0))) {
-    filename = current_instruction().ingredients.at(0).name;
-  }
-  else if (is_mu_text(current_instruction().ingredients.at(0))) {
-    filename = read_mu_text(ingredients.at(0).at(0));
-  }
-  ofstream fout(("lesson/"+filename).c_str());
-  if (!fout) break;
-  string contents = read_mu_text(ingredients.at(1).at(0));
-  fout << contents;
-  fout.close();
-  if (!exists("lesson/.git")) break;
-  // bug in git: git diff -q messes up --exit-code
-  // explicitly say '--all' for git 1.9
-  int status = system("cd lesson; git add --all .; git diff HEAD --exit-code >/dev/null || git commit -a -m . >/dev/null");
-  if (status != 0)
-    raise << "error in commit: contents " << contents << '\n' << end();
-  break;
-}
-
-:(code)
-bool exists(const string& filename) {
-  struct stat dummy;
-  return 0 == stat(filename.c_str(), &dummy);
-}
-
- - - diff --git a/html/edit/004-programming-environment.mu.html b/html/edit/004-programming-environment.mu.html index 776c336e..9cbe6f6f 100644 --- a/html/edit/004-programming-environment.mu.html +++ b/html/edit/004-programming-environment.mu.html @@ -41,12 +41,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color def! main [ local-scope open-console - initial-recipe:text <- restore [recipes.mu] - initial-sandbox:text <- new [] - hide-screen 0/screen - env:&:environment <- new-programming-environment 0/screen, initial-recipe, initial-sandbox + env:&:environment <- new-programming-environment 0/filesystem, 0/screen render-all 0/screen, env, render - event-loop 0/screen, 0/console, env + event-loop 0/screen, 0/console, env, 0/filesystem # never gets here ] @@ -56,24 +53,25 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color sandbox-in-focus?:bool # false => cursor in recipes; true => cursor in current-sandbox ] -def new-programming-environment screen:&:screen, initial-recipe-contents:text, initial-sandbox-contents:text -> result:&:environment [ +def new-programming-environment resources:&:resources, screen:&:screen, test-sandbox-editor-contents:text -> result:&:environment [ local-scope load-ingredients width:num <- screen-width screen result <- new environment:type # recipe editor on the left + initial-recipe-contents:text <- slurp resources, [lesson/recipes.mu] # ignore errors divider:num, _ <- divide-with-remainder width, 2 recipes:&:editor <- new-editor initial-recipe-contents, 0/left, divider/right # sandbox editor on the right sandbox-left:num <- add divider, 1 - current-sandbox:&:editor <- new-editor initial-sandbox-contents, sandbox-left, width/right + current-sandbox:&:editor <- new-editor test-sandbox-editor-contents, sandbox-left, width/right *result <- put *result, recipes:offset, recipes *result <- put *result, current-sandbox:offset, current-sandbox *result <- put *result, sandbox-in-focus?:offset, 0/false <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 recipes:&:editor <- get *env, recipes:offset @@ -321,7 +319,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color trace-until 100/app # trace too long assume-screen 30/width, 5/height # initialize both halves of screen - env:&:environment <- new-programming-environment screen, [abc], [def] + assume-resources [ + [lesson/recipes.mu] <- [ + |abc| + ] + ] + env:&:environment <- new-programming-environment resources, screen, [def] # contents of sandbox editor # focus on both sides assume-console [ left-click 1, 1 @@ -329,7 +332,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] # check cursor column in each run [ - event-loop screen, console, env + event-loop screen, console, env, resources recipes:&:editor <- get *env, recipes:offset 5:num/raw <- get *recipes, cursor-column:offset sandbox:&:editor <- get *env, current-sandbox:offset @@ -346,7 +349,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color trace-until 100/app # trace too long assume-screen 30/width, 5/height # initialize both halves of screen - env:&:environment <- new-programming-environment screen, [abc], [def] + assume-resources [ + [lesson/recipes.mu] <- [ + |abc| + ] + ] + env:&:environment <- new-programming-environment resources, screen, [def] # contents of sandbox render-all screen, env, render # type one letter in each of them assume-console [ @@ -356,7 +364,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [1] ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources recipes:&:editor <- get *env, recipes:offset 5:num/raw <- get *recipes, cursor-column:offset sandbox:&:editor <- get *env, current-sandbox:offset @@ -365,7 +373,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color screen-should-contain [ . run (F4) . # this line has a different background, but we don't test that yet .a0bc ╎d1ef . - .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎──────────────. + . ╎──────────────. + .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . . ╎ . ] memory-should-contain [ @@ -380,39 +389,27 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color screen-should-contain [ . run (F4) . .a0bc ╎d1␣f . - .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎──────────────. + . ╎──────────────. + .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . . ╎ . ] ] -scenario multiple-editors-cover-only-their-own-areas [ - local-scope - trace-until 100/app # trace too long - assume-screen 60/width, 10/height - run [ - env:&:environment <- new-programming-environment screen, [abc], [def] - render-all screen, env, render - ] - # divider isn't messed up - screen-should-contain [ - . run (F4) . - .abc ╎def . - .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────. - . ╎ . - . ╎ . - ] -] - scenario editor-in-focus-keeps-cursor [ local-scope trace-until 100/app # trace too long assume-screen 30/width, 5/height - env:&:environment <- new-programming-environment screen, [abc], [def] + assume-resources [ + [lesson/recipes.mu] <- [ + |abc| + ] + ] + env:&:environment <- new-programming-environment resources, screen, [def] render-all screen, env, render # initialize programming environment and highlight cursor assume-console [] run [ - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor ] @@ -420,7 +417,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color screen-should-contain [ . run (F4) . .␣bc ╎def . - .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎──────────────. + . ╎──────────────. + .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . . ╎ . ] # now try typing a letter @@ -428,7 +426,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [z] ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor ] @@ -436,7 +434,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color screen-should-contain [ . run (F4) . .z␣bc ╎def . - .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎──────────────. + . ╎──────────────. + .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . . ╎ . ] ] @@ -445,10 +444,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color local-scope trace-until 100/app # trace too long assume-screen 30/width, 5/height + assume-resources [ + ] # initialize sandbox side with two lines - s:text <- new [abc + test-sandbox-editor-contents:text <- new [abc def] - env:&:environment <- new-programming-environment screen, [], s:text + env:&:environment <- new-programming-environment resources, screen, test-sandbox-editor-contents render-all screen, env, render screen-should-contain [ . run (F4) . @@ -463,7 +464,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press backspace ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor ] diff --git a/html/edit/005-sandbox.mu.html b/html/edit/005-sandbox.mu.html index b7afa986..095fa72d 100644 --- a/html/edit/005-sandbox.mu.html +++ b/html/edit/005-sandbox.mu.html @@ -45,13 +45,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color def! main [ local-scope open-console - initial-recipe:text <- restore [recipes.mu] - initial-sandbox:text <- new [] - hide-screen 0/screen - env:&:environment <- new-programming-environment 0/screen, initial-recipe, initial-sandbox + 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 + event-loop 0/screen, 0/console, env, 0/filesystem # never gets here ] @@ -81,14 +78,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color trace-until 100/app # trace too long assume-screen 100/width, 15/height # recipe editor 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 [ @@ -138,7 +137,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press F4 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # check that screen prints both sandboxes screen-should-contain [ @@ -164,7 +163,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color do-run?:bool <- equal k, 65532/F4 break-unless do-run? screen <- update-status screen, [running... ], 245/grey - error?:bool, env, screen <- run-sandboxes env, screen + error?:bool <- run-sandboxes env, resources, screen # F4 might update warnings and results on both sides screen <- render-all screen, env, render { @@ -176,10 +175,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color } ] -def run-sandboxes env:&:environment, screen:&:screen -> 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 + errors-found?:bool <- update-recipes env, resources, screen return-if errors-found? # check contents of right editor (sandbox) <run-sandboxes-begin> @@ -205,7 +204,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color *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 @@ -219,14 +218,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <run-sandboxes-end> ] -# copy code from recipe editor, persist to disk, load +# load code from disk # replaced in a later layer (whereupon errors-found? will actually be set) -def update-recipes env:&:environment, screen:&:screen -> errors-found?:bool, env:&:environment, screen:&:screen [ +def update-recipes env:&:environment, resources:&:resources, screen:&:screen -> errors-found?:bool, env:&:environment, resources:&:resources, screen:&:screen [ local-scope load-ingredients recipes:&:editor <- get *env, recipes:offset in:text <- editor-contents recipes - save [recipes.mu], in # newlayer: persistence + resources <- dump resources, [lesson/recipes.mu], in reload in errors-found? <- copy 0/false ] @@ -248,7 +247,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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 @@ -259,8 +258,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color { 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 @@ -450,7 +449,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] # 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 @@ -458,8 +457,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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 @@ -554,27 +553,32 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color trace-until 100/app # trace too long assume-screen 100/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, recipes, [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 + event-loop screen, console, env, resources screen-should-contain [ . run (F4) . . ╎ . .recipe foo [ ╎─────────────────────────────────────────────────. - .local-scope ╎0 edit copy delete . - .z:num <- add 2, 2 ╎foo . - .reply z ╎4 . + . local-scope ╎0 edit copy delete . + . z:num <- add 2, 2 ╎foo . + . reply z ╎4 . .] ╎─────────────────────────────────────────────────. + . ╎ . .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . . ╎ . ] @@ -586,17 +590,18 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press F4 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # check that screen updates the result on the right screen-should-contain [ . run (F4) . . ╎ . .recipe foo [ ╎─────────────────────────────────────────────────. - .local-scope ╎0 edit copy delete . - .z:num <- add 2, 3 ╎foo . - .reply z ╎5 . + . local-scope ╎0 edit copy delete . + . z:num <- add 2, 3 ╎foo . + . reply z ╎5 . .] ╎─────────────────────────────────────────────────. + . ╎ . .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . . ╎ . ] @@ -606,15 +611,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color local-scope trace-until 100/app # trace too long assume-screen 100/width, 20/height - # left editor is empty - # right 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 [ @@ -677,13 +684,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color local-scope trace-until 100/app assume-screen 100/width, 10/height - env:&:environment <- new-programming-environment screen, [], [] + assume-resources [ + ] + env:&:environment <- new-programming-environment resources, screen, [] render-all screen, env, render assume-console [ press enter press down-arrow ] - event-loop screen, console, env + event-loop screen, console, env, resources # no scroll screen-should-contain [ . run (F4) . @@ -698,14 +707,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color local-scope trace-until 100/app assume-screen 100/width, 10/height - env:&:environment <- new-programming-environment screen, [], [] + assume-resources [ + ] + env:&:environment <- new-programming-environment resources, screen, [] render-all screen, env, render assume-console [ press enter press up-arrow press down-arrow # while cursor isn't at bottom ] - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor # cursor moves back to bottom @@ -776,7 +787,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color local-scope trace-until 100/app assume-screen 100/width, 10/height - env:&:environment <- new-programming-environment screen, [], [] + assume-resources [ + ] + env:&:environment <- new-programming-environment resources, screen, [] render-all screen, env, render assume-console [ # add a line @@ -786,7 +799,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color # try to scroll press page-down # or ctrl-f ] - event-loop screen, console, env + event-loop screen, console, env, resources # no scroll, and cursor remains at top line screen-should-contain [ . run (F4) . @@ -801,7 +814,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color local-scope trace-until 100/app assume-screen 100/width, 10/height - env:&:environment <- new-programming-environment screen, [], [ab + assume-resources [ + ] + env:&:environment <- new-programming-environment resources, screen, [ab cd] render-all screen, env, render assume-console [ @@ -812,7 +827,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color # move cursor press down-arrow ] - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor # no scroll on recipe side, cursor moves on sandbox side @@ -831,14 +846,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color local-scope trace-until 100/app # trace too long assume-screen 100/width, 10/height - # initialize sandbox side - env:&:environment <- new-programming-environment screen, [], [add 2, 2] + # initialize + 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) . . ╎ . @@ -852,7 +869,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press page-down ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor ] @@ -870,7 +887,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press page-up ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor ] @@ -959,30 +976,33 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color return curr ] -scenario scrolling-down-on-recipe-side [ +scenario scrolling-down-past-bottom-on-recipe-side [ local-scope trace-until 100/app # trace too long assume-screen 100/width, 10/height # initialize sandbox side and create a sandbox - recipes:text <- new [ -] + assume-resources [ + [lesson/recipes.mu] <- [ + || # file containing just a newline + ] + ] # create a sandbox - env:&:environment <- new-programming-environment screen, recipes:text, [add 2, 2] + env:&:environment <- new-programming-environment resources, screen, [add 2, 2] render-all screen, env, render assume-console [ press F4 ] - event-loop screen, console, env + event-loop screen, console, env, resources # hit 'down' in recipe editor assume-console [ press page-down ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor ] - # cursor moves down on recipe side + # cursor doesn't move when the end is already on-screen screen-should-contain [ . run (F4) . .␣ ╎ . @@ -997,7 +1017,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color trace-until 100/app # trace too long assume-screen 100/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 [ @@ -1007,7 +1029,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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 [ @@ -1027,7 +1049,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press page-down ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor ] @@ -1049,7 +1071,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press page-down ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # just second sandbox displayed screen-should-contain [ @@ -1066,7 +1088,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press page-down ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # no change screen-should-contain [ @@ -1083,7 +1105,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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 [ @@ -1102,7 +1124,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press page-up ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor ] @@ -1124,7 +1146,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press page-up ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources cursor:char <- copy 9251/␣ print screen, cursor ] @@ -1148,7 +1170,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color trace-until 100/app # trace too long assume-screen 100/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 a sandbox assume-console [ @@ -1156,7 +1180,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [add 1, 1] press F4 ] - event-loop screen, console, env + event-loop screen, console, env, resources screen-should-contain [ . run (F4) . . ╎ . @@ -1172,7 +1196,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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 @@ -1190,7 +1214,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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 [ @@ -1208,7 +1232,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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/html/edit/006-sandbox-copy.mu.html b/html/edit/006-sandbox-copy.mu.html index 3459f1f2..b6e9f280 100644 --- a/html/edit/006-sandbox-copy.mu.html +++ b/html/edit/006-sandbox-copy.mu.html @@ -39,24 +39,22 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color local-scope trace-until 100/app # trace too long assume-screen 100/width, 10/height - # basic recipe - recipes:text <- new [ -recipe foo [ - reply 4 -]] - env:&:environment <- new-programming-environment screen, recipes, [foo] + # 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) . . ╎ . - .recipe foo [ ╎─────────────────────────────────────────────────. - . reply 4 ╎0 edit copy delete . - .] ╎foo . - .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎4 . + .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. + . ╎0 edit copy delete . + . ╎add 1, 1 . + . ╎2 . . ╎─────────────────────────────────────────────────. . ╎ . ] @@ -65,16 +63,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click 3, 69 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # it copies into editor screen-should-contain [ . run (F4) . - . ╎foo . - .recipe foo [ ╎─────────────────────────────────────────────────. - . reply 4 ╎0 edit copy delete . - .] ╎foo . - .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎4 . + . ╎add 1, 1 . + .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. + . ╎0 edit copy delete . + . ╎add 1, 1 . + . ╎2 . . ╎─────────────────────────────────────────────────. . ╎ . ] @@ -83,15 +81,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [0] ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] screen-should-contain [ . run (F4) . - . ╎0foo . - .recipe foo [ ╎─────────────────────────────────────────────────. - . reply 4 ╎0 edit copy delete . - .] ╎foo . - .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎4 . + . ╎0add 1, 1 . + .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. + . ╎0 edit copy delete . + . ╎add 1, 1 . + . ╎2 . . ╎─────────────────────────────────────────────────. . ╎ . ] @@ -101,24 +99,22 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color local-scope trace-until 100/app # trace too long assume-screen 100/width, 10/height - # basic recipe - recipes:text <- new [ -recipe foo [ - reply 4 -]] - env:&:environment <- new-programming-environment screen, recipes, [foo] + # 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) . . ╎ . - .recipe foo [ ╎─────────────────────────────────────────────────. - . reply 4 ╎0 edit copy delete . - .] ╎foo . - .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎4 . + .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. + . ╎0 edit copy delete . + . ╎add 1, 1 . + . ╎2 . . ╎─────────────────────────────────────────────────. . ╎ . ] @@ -127,16 +123,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click 3, 84 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # it copies into editor screen-should-contain [ . run (F4) . - . ╎foo . - .recipe foo [ ╎─────────────────────────────────────────────────. - . reply 4 ╎0 edit copy delete . - .] ╎foo . - .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎4 . + . ╎add 1, 1 . + .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. + . ╎0 edit copy delete . + . ╎add 1, 1 . + . ╎2 . . ╎─────────────────────────────────────────────────. . ╎ . ] @@ -145,15 +141,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [0] ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] screen-should-contain [ . run (F4) . - . ╎0foo . - .recipe foo [ ╎─────────────────────────────────────────────────. - . reply 4 ╎0 edit copy delete . - .] ╎foo . - .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎4 . + . ╎0add 1, 1 . + .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. + . ╎0 edit copy delete . + . ╎add 1, 1 . + . ╎2 . . ╎─────────────────────────────────────────────────. . ╎ . ] @@ -258,24 +254,22 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color local-scope trace-until 100/app # trace too long assume-screen 100/width, 10/height - # basic recipe - recipes:text <- new [ -recipe foo [ - reply 4 -]] - env:&:environment <- new-programming-environment screen, recipes, [foo] + # 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) . . ╎ . - .recipe foo [ ╎─────────────────────────────────────────────────. - . reply 4 ╎0 edit copy delete . - .] ╎foo . - .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎4 . + .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. + . ╎0 edit copy delete . + . ╎add 1, 1 . + . ╎2 . . ╎─────────────────────────────────────────────────. . ╎ . ] @@ -286,16 +280,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click 3, 70 # click 'copy' button ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # copy doesn't happen screen-should-contain [ . run (F4) . . ╎0 . - .recipe foo [ ╎─────────────────────────────────────────────────. - . reply 4 ╎0 edit copy delete . - .] ╎foo . - .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎4 . + .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. + . ╎0 edit copy delete . + . ╎add 1, 1 . + . ╎2 . . ╎─────────────────────────────────────────────────. . ╎ . ] @@ -304,15 +298,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [1] ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] screen-should-contain [ . run (F4) . . ╎01 . - .recipe foo [ ╎─────────────────────────────────────────────────. - . reply 4 ╎0 edit copy delete . - .] ╎foo . - .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎4 . + .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. + . ╎0 edit copy delete . + . ╎add 1, 1 . + . ╎2 . . ╎─────────────────────────────────────────────────. . ╎ . ] diff --git a/html/edit/007-sandbox-delete.mu.html b/html/edit/007-sandbox-delete.mu.html index 48028d51..06dd8fc5 100644 --- a/html/edit/007-sandbox-delete.mu.html +++ b/html/edit/007-sandbox-delete.mu.html @@ -38,7 +38,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color local-scope trace-until 100/app # trace too long assume-screen 100/width, 15/height - env:&:environment <- new-programming-environment screen, [], [] + assume-resources [ + ] + env:&:environment <- new-programming-environment resources, screen, [] # run a few commands assume-console [ left-click 1, 80 @@ -47,7 +49,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [add 2, 2] press F4 ] - event-loop screen, console, env + event-loop screen, console, env, resources screen-should-contain [ . run (F4) . . ╎ . @@ -68,7 +70,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click 7, 85 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] screen-should-contain [ . run (F4) . @@ -86,7 +88,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click 3, 99 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] screen-should-contain [ . run (F4) . @@ -185,7 +187,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color trace-until 100/app # trace too long assume-screen 100/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 [ @@ -196,7 +200,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press F4 press page-down ] - event-loop screen, console, env + event-loop screen, console, env, resources screen-should-contain [ . run (F4) . . ╎─────────────────────────────────────────────────. @@ -211,7 +215,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click 6, 99 ] 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 [ @@ -230,7 +234,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color trace-until 100/app # trace too long assume-screen 100/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 [ @@ -241,7 +247,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press F4 press page-down ] - event-loop screen, console, env + event-loop screen, console, env, resources screen-should-contain [ . run (F4) . . ╎─────────────────────────────────────────────────. @@ -256,7 +262,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click 2, 99 ] 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 [ @@ -275,7 +281,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color trace-until 100/app # trace too long assume-screen 100/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 [ @@ -287,7 +295,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color press page-down press page-down ] - event-loop screen, console, env + event-loop screen, console, env, resources screen-should-contain [ . run (F4) . . ╎─────────────────────────────────────────────────. @@ -302,7 +310,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color left-click 2, 99 ] run [ - event-loop screen, console, env + event-loop screen, console, env, resources ] # implicitly scroll up to first sandbox screen-should-contain [ @@ -322,7 +330,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color trace-until 100/app # trace too long assume-screen 100/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 [ @@ -332,7 +342,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color type [add 1, 1] press F4 ] - event-loop screen, console, env + event-loop screen, console, env, resources screen-should-contain [ . run (F4) . . ╎ . @@ -352,7 +362,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color 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/html/edit/008-sandbox-edit.mu.html b/html/edit/008-sandbox-edit.mu.html index 97ca51e3..3725c7ce 100644 --- a/html/edit/008-sandbox-edit.mu.html +++ b/html/edit/008-sandbox-edit.mu.html @@ -34,28 +34,26 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
 ## 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 100/width, 10/height
-  # basic recipe
-  recipes:text <- new [ 
-recipe foo [
-  reply 4
-]]
-  env:&:environment <- new-programming-environment screen, recipes, [foo]
+  # 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)           .
     .                                                  ╎                                                 .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  reply 4                                         ╎0   edit          copy            delete         .
-    .]                                                 ╎foo                                              .
-    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎4                                                .
+    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
+    .                                                  ╎0   edit          copy            delete         .
+    .                                                  ╎add 2, 2                                         .
+    .                                                  ╎4                                                .
     .                                                  ╎─────────────────────────────────────────────────.
     .                                                  ╎                                                 .
   ]
@@ -64,16 +62,13 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     left-click 3, 55
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # it pops back into editor
   screen-should-contain [
     .                                                                                 run (F4)           .
-    .                                                  ╎foo                                              .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  reply 4                                         ╎                                                 .
-    .]                                                 ╎                                                 .
-    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
+    .                                                  ╎add 2, 2                                         .
+    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
     .                                                  ╎                                                 .
   ]
   # cursor should be in the right place
@@ -81,41 +76,36 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     type [0]
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .                                                                                 run (F4)           .
-    .                                                  ╎0foo                                             .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  reply 4                                         ╎                                                 .
-    .]                                                 ╎                                                 .
-    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
+    .                                                  ╎0add 2, 2                                        .
+    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
     .                                                  ╎                                                 .
   ]
 ]
 
-scenario clicking-on-a-sandbox-moves-it-to-editor-2 [
+scenario clicking-on-sandbox-edit-button-moves-it-to-editor-2 [
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 100/width, 10/height
-  # basic recipe
-  recipes:text <- new [ 
-recipe foo [
-  reply 4
-]]
-  env:&:environment <- new-programming-environment screen, recipes, [foo]
+  # 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)           .
     .                                                  ╎                                                 .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  reply 4                                         ╎0   edit          copy            delete         .
-    .]                                                 ╎foo                                              .
-    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎4                                                .
+    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
+    .                                                  ╎0   edit          copy            delete         .
+    .                                                  ╎add 2, 2                                         .
+    .                                                  ╎4                                                .
     .                                                  ╎─────────────────────────────────────────────────.
     .                                                  ╎                                                 .
   ]
@@ -124,16 +114,13 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     left-click 3, 68
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # it pops back into editor
   screen-should-contain [
     .                                                                                 run (F4)           .
-    .                                                  ╎foo                                              .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  reply 4                                         ╎                                                 .
-    .]                                                 ╎                                                 .
-    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
+    .                                                  ╎add 2, 2                                         .
+    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
     .                                                  ╎                                                 .
   ]
   # cursor should be in the right place
@@ -141,15 +128,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     type [0]
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .                                                                                 run (F4)           .
-    .                                                  ╎0foo                                             .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  reply 4                                         ╎                                                 .
-    .]                                                 ╎                                                 .
-    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
+    .                                                  ╎0add 2, 2                                        .
+    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
     .                                                  ╎                                                 .
   ]
 ]
@@ -212,13 +196,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   trace-until 100/app  # trace too long
   assume-screen 100/width, 20/height
   # left editor is empty
-  # right editor contains an instruction
-  env:&:environment <- new-programming-environment screen, [], [print-integer screen, 4]
+  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)           .
     .                                                  ╎                                                 .
@@ -239,7 +225,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     left-click 3, 65
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .                                                                                 run (F4)           .
@@ -255,7 +241,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   trace-until 100/app  # trace too long
   assume-screen 100/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 [
@@ -267,7 +255,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     press page-down
     press page-down
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                                                                                 run (F4)           .
     .                                                  ╎─────────────────────────────────────────────────.
@@ -282,7 +270,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     left-click 2, 55
   ]
   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 [
@@ -302,7 +290,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   trace-until 100/app  # trace too long
   assume-screen 100/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 [
@@ -312,7 +302,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     type [add 1, 1]
     press F4
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                                                                                 run (F4)           .
     .                                                  ╎                                                 .
@@ -331,7 +321,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     press F4
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # no change in contents
   screen-should-contain [
@@ -353,7 +343,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     press page-down
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # screen should show just final sandbox with the right index (1)
   screen-should-contain [
diff --git a/html/edit/009-sandbox-test.mu.html b/html/edit/009-sandbox-test.mu.html
index 30c731ea..b6e0ab9b 100644
--- a/html/edit/009-sandbox-test.mu.html
+++ b/html/edit/009-sandbox-test.mu.html
@@ -40,22 +40,25 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   trace-until 100/app  # trace too long
   assume-screen 100/width, 10/height
   # basic recipe
-  recipes:text <- new [ 
-recipe foo [
-  reply 4
-]]
-  env:&:environment <- new-programming-environment screen, recipes:text, [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
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                                                                                 run (F4)           .
-    .                                                  ╎                                                 .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  reply 4                                         ╎0   edit          copy            delete         .
-    .]                                                 ╎foo                                              .
+    .recipe foo [                                      ╎                                                 .
+    .  reply 4                                         ╎─────────────────────────────────────────────────.
+    .]                                                 ╎0   edit          copy            delete         .
+    .                                                  ╎foo                                              .
     .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎4                                                .
     .                                                  ╎─────────────────────────────────────────────────.
     .                                                  ╎                                                 .
@@ -65,7 +68,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     left-click 5, 51
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # color toggles to green
   screen-should-contain-in-color 2/green, [
@@ -85,26 +88,24 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   ]
   screen-should-contain [
     .                                                                                 run (F4)           .
-    .␣                                                 ╎                                                 .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  reply 4                                         ╎0   edit          copy            delete         .
-    .]                                                 ╎foo                                              .
+    .␣ecipe foo [                                      ╎                                                 .
+    .  reply 4                                         ╎─────────────────────────────────────────────────.
+    .]                                                 ╎0   edit          copy            delete         .
+    .                                                  ╎foo                                              .
     .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎4                                                .
     .                                                  ╎─────────────────────────────────────────────────.
     .                                                  ╎                                                 .
-    .                                                  ╎                                                 .
-    .                                                  ╎                                                 .
   ]
   # now change the result
   # then rerun
   assume-console [
-    left-click 3, 11  # cursor to end of line
+    left-click 2, 11  # cursor to end of line
     press backspace
     type [3]
     press F4
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # result turns red
   screen-should-contain-in-color 1/red, [
@@ -131,14 +132,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     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
   }
@@ -163,7 +164,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     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, recipes, current-sandbox, sandbox-in-focus?, env
diff --git a/html/edit/010-sandbox-trace.mu.html b/html/edit/010-sandbox-trace.mu.html
index 66943462..ab32cbf0 100644
--- a/html/edit/010-sandbox-trace.mu.html
+++ b/html/edit/010-sandbox-trace.mu.html
@@ -40,22 +40,25 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   trace-until 100/app  # trace too long
   assume-screen 100/width, 10/height
   # basic recipe
-  recipes:text <- new [ 
-recipe foo [
-  stash [abc]
-]]
-  env:&:environment <- new-programming-environment screen, recipes, [foo]
+  assume-resources [
+    [lesson/recipes.mu] <- [
+      |recipe foo [|
+      |  stash [abc]|
+      |]|
+    ]
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [foo]
   # run it
   assume-console [
     press F4
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                                                                                 run (F4)           .
-    .                                                  ╎                                                 .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  stash [abc]                                     ╎0   edit          copy            delete         .
-    .]                                                 ╎foo                                              .
+    .recipe foo [                                      ╎                                                 .
+    .  stash [abc]                                     ╎─────────────────────────────────────────────────.
+    .]                                                 ╎0   edit          copy            delete         .
+    .                                                  ╎foo                                              .
     .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
     .                                                  ╎                                                 .
   ]
@@ -64,17 +67,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     left-click 4, 51
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
     cursor:char <- copy 9251/␣
     print screen, cursor
   ]
   # trace now printed and cursor shouldn't have budged
   screen-should-contain [
     .                                                                                 run (F4)           .
-    .␣                                                 ╎                                                 .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  stash [abc]                                     ╎0   edit          copy            delete         .
-    .]                                                 ╎foo                                              .
+    .␣ecipe foo [                                      ╎                                                 .
+    .  stash [abc]                                     ╎─────────────────────────────────────────────────.
+    .]                                                 ╎0   edit          copy            delete         .
+    .                                                  ╎foo                                              .
     .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎abc                                              .
   ]
   screen-should-contain-in-color 245/grey, [
@@ -90,16 +93,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     left-click 4, 55
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
     print screen, cursor
   ]
   # trace hidden again
   screen-should-contain [
     .                                                                                 run (F4)           .
-    .␣                                                 ╎                                                 .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  stash [abc]                                     ╎0   edit          copy            delete         .
-    .]                                                 ╎foo                                              .
+    .␣ecipe foo [                                      ╎                                                 .
+    .  stash [abc]                                     ╎─────────────────────────────────────────────────.
+    .]                                                 ╎0   edit          copy            delete         .
+    .                                                  ╎foo                                              .
     .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
     .                                                  ╎                                                 .
   ]
@@ -110,24 +113,27 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   trace-until 100/app  # trace too long
   assume-screen 100/width, 10/height
   # basic recipe
-  recipes:text <- new [ 
-recipe foo [
-  stash [abc]
-  reply 4
-]]
-  env:&:environment <- new-programming-environment screen, recipes, [foo]
+  assume-resources [
+    [lesson/recipes.mu] <- [
+      |recipe foo [|
+      |  stash [abc]|
+      |  reply 4|
+      |]|
+    ]
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [foo]
   # run it
   assume-console [
     press F4
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                                                                                 run (F4)           .
-    .                                                  ╎                                                 .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  stash [abc]                                     ╎0   edit          copy            delete         .
-    .  reply 4                                         ╎foo                                              .
-    .]                                                 ╎4                                                .
+    .recipe foo [                                      ╎                                                 .
+    .  stash [abc]                                     ╎─────────────────────────────────────────────────.
+    .  reply 4                                         ╎0   edit          copy            delete         .
+    .]                                                 ╎foo                                              .
+    .                                                  ╎4                                                .
     .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
     .                                                  ╎                                                 .
   ]
@@ -136,16 +142,16 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     left-click 4, 51
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # trace now printed above result
   screen-should-contain [
     .                                                                                 run (F4)           .
-    .                                                  ╎                                                 .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  stash [abc]                                     ╎0   edit          copy            delete         .
-    .  reply 4                                         ╎foo                                              .
-    .]                                                 ╎abc                                              .
+    .recipe foo [                                      ╎                                                 .
+    .  stash [abc]                                     ╎─────────────────────────────────────────────────.
+    .  reply 4                                         ╎0   edit          copy            delete         .
+    .]                                                 ╎foo                                              .
+    .                                                  ╎abc                                              .
     .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎8 instructions run                               .
     .                                                  ╎4                                                .
     .                                                  ╎─────────────────────────────────────────────────.
@@ -157,13 +163,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 100/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, 51
   ]
-  event-loop screen, console, env
+  event-loop screen, console, env, resources
   screen-should-contain [
     .                                                                                 run (F4)           .
     .                                                  ╎                                                 .
@@ -177,7 +185,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     left-click 5, 57
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # no change; doesn't die
   screen-should-contain [
diff --git a/html/edit/011-errors.mu.html b/html/edit/011-errors.mu.html
index 91e48c57..72f21172 100644
--- a/html/edit/011-errors.mu.html
+++ b/html/edit/011-errors.mu.html
@@ -40,12 +40,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
 ]
 
 # copy code from recipe editor, persist to disk, load, save any errors
-def! update-recipes env:&:environment, screen:&:screen -> errors-found?:bool, env:&:environment, screen:&:screen [
+def! update-recipes env:&:environment, resources:&:resources, screen:&:screen -> errors-found?:bool, env:&:environment, resources:&:resources, screen:&:screen [
   local-scope
   load-ingredients
   recipes:&:editor <- get *env, recipes:offset
   in:text <- editor-contents recipes
-  save [recipes.mu], in
+  resources <- dump resources, [lesson/recipes.mu], in
   recipe-errors:text <- reload in
   *env <- put *env, recipe-errors:offset, recipe-errors
   # if recipe editor has errors, stop
@@ -153,23 +153,36 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 100/width, 15/height
-  recipes:text <- new [ 
-recipe foo [
-  get 123:num, foo:offset
-]]
-  env:&:environment <- new-programming-environment screen, recipes, [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)           .
+    .recipe foo [                                      ╎foo                                              .
+    .  get 123:num, foo:offset                         ╎─────────────────────────────────────────────────.
+    .]                                                 ╎                                                 .
+    .                                                  ╎                                                 .
+    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
+    .                                                  ╎                                                 .
+  ]
   assume-console [
     press F4
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .  errors found                                                                   run (F4)           .
-    .                                                  ╎foo                                              .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  get 123:num, foo:offset                         ╎                                                 .
+    .recipe foo [                                      ╎foo                                              .
+    .  get 123:num, foo:offset                         ╎─────────────────────────────────────────────────.
     .]                                                 ╎                                                 .
+    .                                                  ╎                                                 .
     .foo: unknown element 'foo' in container 'number'  ╎                                                 .
     .foo: first ingredient of 'get' should be a contai↩╎                                                 .
     .ner, but got '123:num'                            ╎                                                 .
@@ -193,7 +206,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 100/width, 15/height
-  env:&:environment <- new-programming-environment screen, [], []
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, []
   assume-console [
     left-click 3, 80
     # create invalid sandbox 1
@@ -204,7 +219,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     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 [
@@ -216,7 +231,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 100/width, 15/height
-  env:&:environment <- new-programming-environment screen, [], []
+  assume-resources [
+  ]
+  env:&:environment <- new-programming-environment resources, screen, []
   assume-console [
     left-click 3, 80
     # create invalid sandbox 2
@@ -230,7 +247,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     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 [
@@ -242,13 +259,13 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 100/width, 15/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
   ]
-  run [
-    event-loop screen, console, env
-  ]
+  event-loop screen, console, env, resources
   assume-console [
     left-click 3, 58
     press ctrl-k
@@ -256,7 +273,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     press F4  # update sandbox
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # error should disappear
   screen-should-contain [
@@ -276,26 +293,31 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   trace-until 100/app  # trace too long
   assume-screen 100/width, 15/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, recipes, [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
+  event-loop screen, console, env, resources
   screen-should-contain [
     .  errors found (0)                                                               run (F4)           .
     .recipe foo x:_elem -> z:_elem [                   ╎                                                 .
-    .local-scope                                       ╎─────────────────────────────────────────────────.
-    .load-ingredients                                  ╎0   edit          copy            delete         .
-    .y:&:num <- copy 0                                 ╎foo 2                                            .
-    .z <- add x, y                                     ╎foo_2: 'add' requires number ingredients, but go↩.
+    .  local-scope                                     ╎─────────────────────────────────────────────────.
+    .  load-ingredients                                ╎0   edit          copy            delete         .
+    .  y:&:num <- copy 0                               ╎foo 2                                            .
+    .  z <- add x, y                                   ╎foo_2: 'add' requires number ingredients, but go↩.
     .]                                                 ╎t 'y'                                            .
-    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
+    .                                                  ╎─────────────────────────────────────────────────.
+    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
     .                                                  ╎                                                 .
   ]
   # now rerun everything
@@ -303,18 +325,19 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     press F4
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # error should remain unchanged
   screen-should-contain [
     .  errors found (0)                                                               run (F4)           .
     .recipe foo x:_elem -> z:_elem [                   ╎                                                 .
-    .local-scope                                       ╎─────────────────────────────────────────────────.
-    .load-ingredients                                  ╎0   edit          copy            delete         .
-    .y:&:num <- copy 0                                 ╎foo 2                                            .
-    .z <- add x, y                                     ╎foo_3: 'add' requires number ingredients, but go↩.
+    .  local-scope                                     ╎─────────────────────────────────────────────────.
+    .  load-ingredients                                ╎0   edit          copy            delete         .
+    .  y:&:num <- copy 0                               ╎foo 2                                            .
+    .  z <- add x, y                                   ╎foo_3: 'add' requires number ingredients, but go↩.
     .]                                                 ╎t 'y'                                            .
-    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
+    .                                                  ╎─────────────────────────────────────────────────.
+    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
     .                                                  ╎                                                 .
   ]
 ]
@@ -324,17 +347,21 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   trace-until 100/app  # trace too long
   assume-screen 100/width, 15/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, recipes, sandbox
+  env:&:environment <- new-programming-environment resources, screen, test-sandbox
   # run it once
   assume-console [
     press F4
   ]
-  event-loop screen, console, env
+  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, [
     .                                                                                                    .
@@ -358,7 +385,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     press F4
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # still no errors
   screen-should-contain-in-color 1/red, [
@@ -384,24 +411,30 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 100/width, 15/height
-  recipes:text <- new [ 
-recipe foo [
-  x <- copy 0
-]]
-  env:&:environment <- new-programming-environment screen, recipes, [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
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .  errors found                                                                   run (F4)           .
-    .                                                  ╎foo                                              .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  x <- copy 0                                     ╎                                                 .
+    .recipe foo [                                      ╎foo                                              .
+    .  x <- copy 0                                     ╎─────────────────────────────────────────────────.
     .]                                                 ╎                                                 .
+    .                                                  ╎                                                 .
     .foo: missing type for 'x' in 'x <- copy 0'        ╎                                                 .
+    .foo: can't copy '0' to 'x'; types don't match     ╎                                                 .
+    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
+    .                                                  ╎                                                 .
   ]
 ]
 
@@ -410,22 +443,23 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   trace-until 100/app  # trace too long
   assume-screen 100/width, 15/height
   # recipe is incomplete (unbalanced '[')
-  recipes:text <- new [ 
-recipe foo \\[
-  x <- copy 0
-]
-  env:&:environment <- new-programming-environment screen, recipes, [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
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .  errors found                                                                   run (F4)           .
-    .                                                  ╎foo                                              .
-    .recipe foo \\[                                      ╎─────────────────────────────────────────────────.
-    .  x <- copy 0                                     ╎                                                 .
+    .recipe foo \\[                                      ╎foo                                              .
+    .  x <- copy 0                                     ╎─────────────────────────────────────────────────.
     .                                                  ╎                                                 .
     .9: unbalanced '\\[' for recipe                      ╎                                                 .
     .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
@@ -437,27 +471,30 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 100/width, 15/height
-  recipes:text <- new [ 
-recipe foo [
-  local-scope
-  x:&:point <- new point:type
-  get x:&:point, 1:offset
-]]
-  env:&:environment <- new-programming-environment screen, recipes, [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
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .  errors found                                                                   run (F4)           .
-    .                                                  ╎foo                                              .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  local-scope                                     ╎                                                 .
+    .recipe foo [                                      ╎foo                                              .
+    .  local-scope                                     ╎─────────────────────────────────────────────────.
     .  x:&:point <- new point:type                     ╎                                                 .
     .  get x:&:point, 1:offset                         ╎                                                 .
     .]                                                 ╎                                                 .
+    .                                                  ╎                                                 .
     .foo: first ingredient of 'get' should be a contai↩╎                                                 .
     .ner, but got 'x:&:point'                          ╎                                                 .
     .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
@@ -469,29 +506,32 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 100/width, 15/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, recipes, [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
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .  errors found                                                                   run (F4)           .
-    .                                                  ╎foo                                              .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  local-scope                                     ╎                                                 .
+    .recipe foo [                                      ╎foo                                              .
+    .  local-scope                                     ╎─────────────────────────────────────────────────.
     .  x:num <- copy 0                                 ╎                                                 .
     .  y:&:point <- new point:type                     ╎                                                 .
     .  get *y:&:point, x:num                           ╎                                                 .
     .]                                                 ╎                                                 .
+    .                                                  ╎                                                 .
     .foo: second ingredient of 'get' should have type ↩╎                                                 .
     .'offset', but got 'x:num'                         ╎                                                 .
     .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
@@ -502,25 +542,28 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
 scenario run-shows-errors-everytime [
   local-scope
   trace-until 100/app  # trace too long
-  # try to run a file with an error
   assume-screen 100/width, 15/height
-  recipes:text <- new [ 
-recipe foo [
-  local-scope
-  x:num <- copy y:num
-]]
-  env:&:environment <- new-programming-environment screen, recipes, [foo]
+  # try to run a file with an error
+  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
+  event-loop screen, console, env, resources
   screen-should-contain [
     .  errors found                                                                   run (F4)           .
-    .                                                  ╎foo                                              .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  local-scope                                     ╎                                                 .
+    .recipe foo [                                      ╎foo                                              .
+    .  local-scope                                     ╎─────────────────────────────────────────────────.
     .  x:num <- copy y:num                             ╎                                                 .
     .]                                                 ╎                                                 .
+    .                                                  ╎                                                 .
     .foo: tried to read ingredient 'y' in 'x:num <- co↩╎                                                 .
     .py y:num' but it hasn't been written to yet       ╎                                                 .
     .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
@@ -531,15 +574,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     press F4
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   screen-should-contain [
     .  errors found                                                                   run (F4)           .
-    .                                                  ╎foo                                              .
-    .recipe foo [                                      ╎─────────────────────────────────────────────────.
-    .  local-scope                                     ╎                                                 .
+    .recipe foo [                                      ╎foo                                              .
+    .  local-scope                                     ╎─────────────────────────────────────────────────.
     .  x:num <- copy y:num                             ╎                                                 .
     .]                                                 ╎                                                 .
+    .                                                  ╎                                                 .
     .foo: tried to read ingredient 'y' in 'x:num <- co↩╎                                                 .
     .py y:num' but it hasn't been written to yet       ╎                                                 .
     .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
@@ -551,15 +594,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 100/width, 10/height
-  # right editor contains an illegal instruction
-  sandbox:text <- new [get 1234:num, foo:offset]
-  env:&:environment <- new-programming-environment screen, [], sandbox
-  # run the code in the editors
+  assume-resources [
+  ]
+  # sandbox editor contains an illegal instruction
+  env:&:environment <- new-programming-environment resources, screen, [get 1234:num, foo: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 [
@@ -613,16 +656,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 100/width, 10/height
-  # right editor contains an illegal instruction
-  sandbox:text <- new [get 1234:num, foo:offset]
-  env:&:environment <- new-programming-environment screen, [], sandbox
+  assume-resources [
+  ]
+  # sandbox editor contains an illegal instruction
+  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 [
@@ -643,20 +687,23 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   local-scope
   trace-until 100/app  # trace too long
   assume-screen 100/width, 20/height
-  # left editor is empty
-  recipes:text <- new [recipe foo [
-  {
-    loop
-  }
-]]
-  # right editor contains an instruction
-  env:&:environment <- new-programming-environment screen, recipes, [foo]
+  # sandbox editor will trigger an infinite loop
+  assume-resources [
+    [lesson/recipes.mu] <- [
+      |recipe foo [|
+      |  {|
+      |    loop|
+      |  }|
+      |]|
+    ]
+  ]
+  env:&:environment <- new-programming-environment resources, screen, [foo]
   # 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)           .
@@ -665,7 +712,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
     .    loop                                          ╎0   edit          copy            delete         .
     .  }                                               ╎foo                                              .
     .]                                                 ╎took too long!                                   .
-    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
+    .                                                  ╎─────────────────────────────────────────────────.
+    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
     .                                                  ╎                                                 .
   ]
 ]
@@ -675,51 +723,56 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   trace-until 100/app  # trace too long
   assume-screen 100/width, 10/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, recipes, [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
+  event-loop screen, console, env, resources
   # screen prints error message
   screen-should-contain [
     .  errors found (0)                                                               run (F4)           .
     .recipe foo [                                      ╎                                                 .
-    .local-scope                                       ╎─────────────────────────────────────────────────.
-    .a:num <- next-ingredient                          ╎0   edit          copy            delete         .
-    .b:num <- next-ingredient                          ╎foo 4, 0                                         .
-    .stash [dividing by], b                            ╎foo: divide by zero in '_, c:num <- divide-with-↩.
-    ._, c:num <- divide-with-remainder a, b            ╎remainder a, b'                                  .
-    .reply b                                           ╎─────────────────────────────────────────────────.
+    .  local-scope                                     ╎─────────────────────────────────────────────────.
+    .  a:num <- next-ingredient                        ╎0   edit          copy            delete         .
+    .  b:num <- next-ingredient                        ╎foo 4, 0                                         .
+    .  stash [dividing by], b                          ╎foo: divide by zero in '_, c:num <- divide-with-↩.
+    .  _, c:num <- divide-with-remainder a, b          ╎remainder a, b'                                  .
+    .  reply b                                         ╎─────────────────────────────────────────────────.
     .]                                                 ╎                                                 .
+    .                                                  ╎                                                 .
   ]
   # click on the call in the sandbox
   assume-console [
     left-click 4, 55
   ]
   run [
-    event-loop screen, console, env
+    event-loop screen, console, env, resources
   ]
   # screen should expand trace
   screen-should-contain [
     .  errors found (0)                                                               run (F4)           .
     .recipe foo [                                      ╎                                                 .
-    .local-scope                                       ╎─────────────────────────────────────────────────.
-    .a:num <- next-ingredient                          ╎0   edit          copy            delete         .
-    .b:num <- next-ingredient                          ╎foo 4, 0                                         .
-    .stash [dividing by], b                            ╎dividing by 0                                    .
-    ._, c:num <- divide-with-remainder a, b            ╎14 instructions run                              .
-    .reply b                                           ╎foo: divide by zero in '_, c:num <- divide-with-↩.
+    .  local-scope                                     ╎─────────────────────────────────────────────────.
+    .  a:num <- next-ingredient                        ╎0   edit          copy            delete         .
+    .  b:num <- next-ingredient                        ╎foo 4, 0                                         .
+    .  stash [dividing by], b                          ╎dividing by 0                                    .
+    .  _, c:num <- divide-with-remainder a, b          ╎14 instructions run                              .
+    .  reply b                                         ╎foo: divide by zero in '_, c:num <- divide-with-↩.
     .]                                                 ╎remainder a, b'                                  .
-    .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
+    .                                                  ╎─────────────────────────────────────────────────.
   ]
 ]
 
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 ] -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 [ 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 [ 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 [ } ] -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 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 ] -# 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 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,12 @@ 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 [ @@ -39,7 +42,59 @@ 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) . + .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 [ + . 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) . @@ -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 [ 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 [ { 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 [ 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 [