1 ## handling malformed programs
  2 
  3 container environment [
  4   recipe-errors:text
  5 ]
  6 
  7 # copy code from recipe editor, persist to disk, load, save any errors
  8 def! update-recipes env:&:environment, resources:&:resources, screen:&:screen -> errors-found?:bool, env:&:environment, resources:&:resources, screen:&:screen [
  9   local-scope
 10   load-ingredients
 11   recipes:&:editor <- get *env, recipes:offset
 12   in:text <- editor-contents recipes
 13   resources <- dump resources, [lesson/recipes.mu], in
 14   recipe-errors:text <- reload in
 15   *env <- put *env, recipe-errors:offset, recipe-errors
 16   # if recipe editor has errors, stop
 17   {
 18   ¦ break-unless recipe-errors
 19   ¦ update-status screen, [errors found     ], 1/red
 20   ¦ errors-found? <- copy 1/true
 21   ¦ return
 22   }
 23   errors-found? <- copy 0/false
 24 ]
 25 
 26 before <render-components-end> [
 27   trace 11, [app], [render status]
 28   recipe-errors:text <- get *env, recipe-errors:offset
 29   {
 30   ¦ break-unless recipe-errors
 31   ¦ update-status screen, [errors found     ], 1/red
 32   }
 33 ]
 34 
 35 before <render-recipe-components-end> [
 36   {
 37   ¦ recipe-errors:text <- get *env, recipe-errors:offset
 38   ¦ break-unless recipe-errors
 39   ¦ row, screen <- render-text screen, recipe-errors, left, right, 1/red, row
 40   }
 41 ]
 42 
 43 container environment [
 44   error-index:num  # index of first sandbox with an error (or -1 if none)
 45 ]
 46 
 47 after <programming-environment-initialization> [
 48   *result <- put *result, error-index:offset, -1
 49 ]
 50 
 51 after <run-sandboxes-begin> [
 52   *env <- put *env, error-index:offset, -1
 53 ]
 54 
 55 before <run-sandboxes-end> [
 56   {
 57   ¦ error-index:num <- get *env, error-index:offset
 58   ¦ sandboxes-completed-successfully?:bool <- equal error-index, -1
 59   ¦ break-if sandboxes-completed-successfully?
 60   ¦ errors-found? <- copy 1/true
 61   }
 62 ]
 63 
 64 before <render-components-end> [
 65   {
 66   ¦ break-if recipe-errors
 67   ¦ error-index:num <- get *env, error-index:offset
 68   ¦ sandboxes-completed-successfully?:bool <- equal error-index, -1
 69   ¦ break-if sandboxes-completed-successfully?
 70   ¦ error-index-text:text <- to-text error-index
 71   ¦ status:text <- interpolate [errors found (_)    ], error-index-text
 72   ¦ update-status screen, status, 1/red
 73   }
 74 ]
 75 
 76 container sandbox [
 77   errors:text
 78 ]
 79 
 80 def! update-sandbox sandbox:&:sandbox, env:&:environment, idx:num -> sandbox:&:sandbox, env:&:environment [
 81   local-scope
 82   load-ingredients
 83   data:text <- get *sandbox, data:offset
 84   response:text, errors:text, fake-screen:&:screen, trace:text, completed?:bool <- run-sandboxed data
 85   *sandbox <- put *sandbox, response:offset, response
 86   *sandbox <- put *sandbox, errors:offset, errors
 87   *sandbox <- put *sandbox, screen:offset, fake-screen
 88   *sandbox <- put *sandbox, trace:offset, trace
 89   {
 90   ¦ break-if errors
 91   ¦ break-if completed?:bool
 92   ¦ errors <- new [took too long!
 93 ]
 94   ¦ *sandbox <- put *sandbox, errors:offset, errors
 95   }
 96   {
 97   ¦ break-unless errors
 98   ¦ error-index:num <- get *env, error-index:offset
 99   ¦ error-not-set?:bool <- equal error-index, -1
100   ¦ break-unless error-not-set?
101   ¦ *env <- put *env, error-index:offset, idx
102   }
103 ]
104 
105 # make sure we render any trace
106 after <render-sandbox-trace-done> [
107   {
108   ¦ sandbox-errors:text <- get *sandbox, errors:offset
109   ¦ break-unless sandbox-errors
110   ¦ *sandbox <- put *sandbox, response-starting-row-on-screen:offset, 0  # no response
111   ¦ row, screen <- render-text screen, sandbox-errors, left, right, 1/red, row
112   ¦ # don't try to print anything more for this sandbox
113   ¦ jump +render-sandbox-end
114   }
115 ]
116 
117 scenario run-shows-errors-in-get [
118   local-scope
119   trace-until 100/app  # trace too long
120   assume-screen 100/width, 15/height
121   assume-resources [
122   ¦ [lesson/recipes.mu] <- [
123   ¦ ¦ |recipe foo [|
124   ¦ ¦ |  get 123:num, foo:offset|
125   ¦ ¦ |]|
126   ¦ ]
127   ]
128   env:&:environment <- new-programming-environment resources, screen, [foo]
129   render-all screen, env, render
130   screen-should-contain [
131   ¦ .                                                                                 run (F4)           .
132   ¦ .recipe foo [                                      ╎foo                                              .
133   ¦ .  get 123:num, foo:offset                         ╎─────────────────────────────────────────────────.
134   ¦ .]                                                 ╎                                                 .
135   ¦ .                                                  ╎                                                 .
136   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
137   ¦ .                                                  ╎                                                 .
138   ]
139   assume-console [
140   ¦ press F4
141   ]
142   run [
143   ¦ event-loop screen, console, env, resources
144   ]
145   screen-should-contain [
146   ¦ .  errors found                                                                   run (F4)           .
147   ¦ .recipe foo [                                      ╎foo                                              .
148   ¦ .  get 123:num, foo:offset                         ╎─────────────────────────────────────────────────.
149   ¦ .]                                                 ╎                                                 .
150   ¦ .                                                  ╎                                                 .
151   ¦ .foo: unknown element 'foo' in container 'number'  ╎                                                 .
152   ¦ .foo: first ingredient of 'get' should be a contai↩╎                                                 .
153   ¦ .ner, but got '123:num'                            ╎                                                 .
154   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
155   ¦ .                                                  ╎                                                 .
156   ]
157   screen-should-contain-in-color 1/red, [
158   ¦ .  errors found                                                                                      .
159   ¦ .                                                                                                    .
160   ¦ .                                                                                                    .
161   ¦ .                                                                                                    .
162   ¦ .                                                                                                    .
163   ¦ .foo: unknown element 'foo' in container 'number'                                                    .
164   ¦ .foo: first ingredient of 'get' should be a contai                                                   .
165   ¦ .ner, but got '123:num'                                                                              .
166   ¦ .                                                                                                    .
167   ]
168 ]
169 
170 scenario run-updates-status-with-first-erroneous-sandbox [
171   local-scope
172   trace-until 100/app  # trace too long
173   assume-screen 100/width, 15/height
174   assume-resources [
175   ]
176   env:&:environment <- new-programming-environment resources, screen, []
177   assume-console [
178   ¦ left-click 3, 80
179   ¦ # create invalid sandbox 1
180   ¦ type [get foo, x:offset]
181   ¦ press F4
182   ¦ # create invalid sandbox 0
183   ¦ type [get foo, x:offset]
184   ¦ press F4
185   ]
186   run [
187   ¦ event-loop screen, console, env, resources
188   ]
189   # status line shows that error is in first sandbox
190   screen-should-contain [
191   ¦ .  errors found (0)                                                               run (F4)           .
192   ]
193 ]
194 
195 scenario run-updates-status-with-first-erroneous-sandbox-2 [
196   local-scope
197   trace-until 100/app  # trace too long
198   assume-screen 100/width, 15/height
199   assume-resources [
200   ]
201   env:&:environment <- new-programming-environment resources, screen, []
202   assume-console [
203   ¦ left-click 3, 80
204   ¦ # create invalid sandbox 2
205   ¦ type [get foo, x:offset]
206   ¦ press F4
207   ¦ # create invalid sandbox 1
208   ¦ type [get foo, x:offset]
209   ¦ press F4
210   ¦ # create valid sandbox 0
211   ¦ type [add 2, 2]
212   ¦ press F4
213   ]
214   run [
215   ¦ event-loop screen, console, env, resources
216   ]
217   # status line shows that error is in second sandbox
218   screen-should-contain [
219   ¦ .  errors found (1)                                                               run (F4)           .
220   ]
221 ]
222 
223 scenario run-hides-errors-from-past-sandboxes [
224   local-scope
225   trace-until 100/app  # trace too long
226   assume-screen 100/width, 15/height
227   assume-resources [
228   ]
229   env:&:environment <- new-programming-environment resources, screen, [get foo, x:offset]  # invalid
230   assume-console [
231   ¦ press F4  # generate error
232   ]
233   event-loop screen, console, env, resources
234   assume-console [
235   ¦ left-click 3, 58
236   ¦ press ctrl-k
237   ¦ type [add 2, 2]  # valid code
238   ¦ press F4  # update sandbox
239   ]
240   run [
241   ¦ event-loop screen, console, env, resources
242   ]
243   # error should disappear
244   screen-should-contain [
245   ¦ .                                                                                 run (F4)           .
246   ¦ .                                                  ╎                                                 .
247   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
248   ¦ .                                                  ╎0   edit          copy            delete         .
249   ¦ .                                                  ╎add 2, 2                                         .
250   ¦ .                                                  ╎4                                                .
251   ¦ .                                                  ╎─────────────────────────────────────────────────.
252   ¦ .                                                  ╎                                                 .
253   ]
254 ]
255 
256 scenario run-updates-errors-for-shape-shifting-recipes [
257   local-scope
258   trace-until 100/app  # trace too long
259   assume-screen 100/width, 15/height
260   # define a shape-shifting recipe with an error
261   assume-resources [
262   ¦ [lesson/recipes.mu] <- [
263   ¦ ¦ |recipe foo x:_elem -> z:_elem [|
264   ¦ ¦ |  local-scope|
265   ¦ ¦ |  load-ingredients|
266   ¦ ¦ |  y:&:num <- copy 0|
267   ¦ ¦ |  z <- add x, y|
268   ¦ ¦ |]|
269   ¦ ]
270   ]
271   env:&:environment <- new-programming-environment resources, screen, [foo 2]
272   assume-console [
273   ¦ press F4
274   ]
275   event-loop screen, console, env, resources
276   screen-should-contain [
277   ¦ .  errors found (0)                                                               run (F4)           .
278   ¦ .recipe foo x:_elem -> z:_elem [                   ╎                                                 .
279   ¦ .  local-scope                                     ╎─────────────────────────────────────────────────.
280   ¦ .  load-ingredients                                ╎0   edit          copy            delete         .
281   ¦ .  y:&:num <- copy 0                               ╎foo 2                                            .
282   ¦ .  z <- add x, y                                   ╎foo_2: 'add' requires number ingredients, but go↩.
283   ¦ .]                                                 ╎t 'y'                                            .
284   ¦ .                                                  ╎─────────────────────────────────────────────────.
285   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
286   ¦ .                                                  ╎                                                 .
287   ]
288   # now rerun everything
289   assume-console [
290   ¦ press F4
291   ]
292   run [
293   ¦ event-loop screen, console, env, resources
294   ]
295   # error should remain unchanged
296   screen-should-contain [
297   ¦ .  errors found (0)                                                               run (F4)           .
298   ¦ .recipe foo x:_elem -> z:_elem [                   ╎                                                 .
299   ¦ .  local-scope                                     ╎─────────────────────────────────────────────────.
300   ¦ .  load-ingredients                                ╎0   edit          copy            delete         .
301   ¦ .  y:&:num <- copy 0                               ╎foo 2                                            .
302   ¦ .  z <- add x, y                                   ╎foo_3: 'add' requires number ingredients, but go↩.
303   ¦ .]                                                 ╎t 'y'                                            .
304   ¦ .                                                  ╎─────────────────────────────────────────────────.
305   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
306   ¦ .                                                  ╎                                                 .
307   ]
308 ]
309 
310 scenario run-avoids-spurious-errors-on-reloading-shape-shifting-recipes [
311   local-scope
312   trace-until 100/app  # trace too long
313   assume-screen 100/width, 15/height
314   # overload a well-known shape-shifting recipe
315   assume-resources [
316   ¦ [lesson/recipes.mu] <- [
317   ¦ ¦ |recipe length l:&:list:_elem -> n:num [|
318   ¦ ¦ |]|
319   ¦ ]
320   ]
321   # call code that uses other variants of it, but not it itself
322   test-sandbox:text <- new [x:&:list:num <- copy 0
323 to-text x]
324   env:&:environment <- new-programming-environment resources, screen, test-sandbox
325   # run it once
326   assume-console [
327   ¦ press F4
328   ]
329   event-loop screen, console, env, resources
330   # no errors anywhere on screen (can't check anything else, since to-text will return an address)
331   screen-should-contain-in-color 1/red, [
332   ¦ .                                                                                                    .
333   ¦ .                                                                                                    .
334   ¦ .                                                                                                    .
335   ¦ .                                                                                                    .
336   ¦ .                                                                <-                                  .
337   ¦ .                                                                                                    .
338   ¦ .                                                                                                    .
339   ¦ .                                                                                                    .
340   ¦ .                                                                                                    .
341   ¦ .                                                                                                    .
342   ¦ .                                                                                                    .
343   ¦ .                                                                                                    .
344   ¦ .                                                                                                    .
345   ¦ .                                                                                                    .
346   ¦ .                                                                                                    .
347   ]
348   # rerun everything
349   assume-console [
350   ¦ press F4
351   ]
352   run [
353   ¦ event-loop screen, console, env, resources
354   ]
355   # still no errors
356   screen-should-contain-in-color 1/red, [
357   ¦ .                                                                                                    .
358   ¦ .                                                                                                    .
359   ¦ .                                                                                                    .
360   ¦ .                                                                                                    .
361   ¦ .                                                                <-                                  .
362   ¦ .                                                                                                    .
363   ¦ .                                                                                                    .
364   ¦ .                                                                                                    .
365   ¦ .                                                                                                    .
366   ¦ .                                                                                                    .
367   ¦ .                                                                                                    .
368   ¦ .                                                                                                    .
369   ¦ .                                                                                                    .
370   ¦ .                                                                                                    .
371   ¦ .                                                                                                    .
372   ]
373 ]
374 
375 scenario run-shows-missing-type-errors [
376   local-scope
377   trace-until 100/app  # trace too long
378   assume-screen 100/width, 15/height
379   assume-resources [
380   ¦ [lesson/recipes.mu] <- [
381   ¦ ¦ |recipe foo [|
382   ¦ ¦ |  x <- copy 0|
383   ¦ ¦ |]|
384   ¦ ]
385   ]
386   env:&:environment <- new-programming-environment resources, screen, [foo]
387   assume-console [
388   ¦ press F4
389   ]
390   run [
391   ¦ event-loop screen, console, env, resources
392   ]
393   screen-should-contain [
394   ¦ .  errors found                                                                   run (F4)           .
395   ¦ .recipe foo [                                      ╎foo                                              .
396   ¦ .  x <- copy 0                                     ╎─────────────────────────────────────────────────.
397   ¦ .]                                                 ╎                                                 .
398   ¦ .                                                  ╎                                                 .
399   ¦ .foo: missing type for 'x' in 'x <- copy 0'        ╎                                                 .
400   ¦ .foo: can't copy '0' to 'x'; types don't match     ╎                                                 .
401   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
402   ¦ .                                                  ╎                                                 .
403   ]
404 ]
405 
406 scenario run-shows-unbalanced-bracket-errors [
407   local-scope
408   trace-until 100/app  # trace too long
409   assume-screen 100/width, 15/height
410   # recipe is incomplete (unbalanced '[')
411   assume-resources [
412   ¦ [lesson/recipes.mu] <- [
413   ¦ ¦ |recipe foo \\\[|
414   ¦ ¦ |  x <- copy 0|
415   ¦ ]
416   ]
417   env:&:environment <- new-programming-environment resources, screen, [foo]
418   assume-console [
419   ¦ press F4
420   ]
421   run [
422   ¦ event-loop screen, console, env, resources
423   ]
424   screen-should-contain [
425   ¦ .  errors found                                                                   run (F4)           .
426   ¦ .recipe foo \\[                                      ╎foo                                              .
427   ¦ .  x <- copy 0                                     ╎─────────────────────────────────────────────────.
428   ¦ .                                                  ╎                                                 .
429   ¦ .9: unbalanced '\\[' for recipe                      ╎                                                 .
430   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
431   ¦ .                                                  ╎                                                 .
432   ]
433 ]
434 
435 scenario run-shows-get-on-non-container-errors [
436   local-scope
437   trace-until 100/app  # trace too long
438   assume-screen 100/width, 15/height
439   assume-resources [
440   ¦ [lesson/recipes.mu] <- [
441   ¦ ¦ |recipe foo [|
442   ¦ ¦ |  local-scope|
443   ¦ ¦ |  x:&:point <- new point:type|
444   ¦ ¦ |  get x:&:point, 1:offset|
445   ¦ ¦ |]|
446   ¦ ]
447   ]
448   env:&:environment <- new-programming-environment resources, screen, [foo]
449   assume-console [
450   ¦ press F4
451   ]
452   run [
453   ¦ event-loop screen, console, env, resources
454   ]
455   screen-should-contain [
456   ¦ .  errors found                                                                   run (F4)           .
457   ¦ .recipe foo [                                      ╎foo                                              .
458   ¦ .  local-scope                                     ╎─────────────────────────────────────────────────.
459   ¦ .  x:&:point <- new point:type                     ╎                                                 .
460   ¦ .  get x:&:point, 1:offset                         ╎                                                 .
461   ¦ .]                                                 ╎                                                 .
462   ¦ .                                                  ╎                                                 .
463   ¦ .foo: first ingredient of 'get' should be a contai↩╎                                                 .
464   ¦ .ner, but got 'x:&:point'                          ╎                                                 .
465   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
466   ¦ .                                                  ╎                                                 .
467   ]
468 ]
469 
470 scenario run-shows-non-literal-get-argument-errors [
471   local-scope
472   trace-until 100/app  # trace too long
473   assume-screen 100/width, 15/height
474   assume-resources [
475   ¦ [lesson/recipes.mu] <- [
476   ¦ ¦ |recipe foo [|
477   ¦ ¦ |  local-scope|
478   ¦ ¦ |  x:num <- copy 0|
479   ¦ ¦ |  y:&:point <- new point:type|
480   ¦ ¦ |  get *y:&:point, x:num|
481   ¦ ¦ |]|
482   ¦ ]
483   ]
484   env:&:environment <- new-programming-environment resources, screen, [foo]
485   assume-console [
486   ¦ press F4
487   ]
488   run [
489   ¦ event-loop screen, console, env, resources
490   ]
491   screen-should-contain [
492   ¦ .  errors found                                                                   run (F4)           .
493   ¦ .recipe foo [                                      ╎foo                                              .
494   ¦ .  local-scope                                     ╎─────────────────────────────────────────────────.
495   ¦ .  x:num <- copy 0                                 ╎                                                 .
496   ¦ .  y:&:point <- new point:type                     ╎                                                 .
497   ¦ .  get *y:&:point, x:num                           ╎                                                 .
498   ¦ .]                                                 ╎                                                 .
499   ¦ .                                                  ╎                                                 .
500   ¦ .foo: second ingredient of 'get' should have type ↩╎                                                 .
501   ¦ .'offset', but got 'x:num'                         ╎                                                 .
502   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
503   ¦ .                                                  ╎                                                 .
504   ]
505 ]
506 
507 scenario run-shows-errors-everytime [
508   local-scope
509   trace-until 100/app  # trace too long
510   assume-screen 100/width, 15/height
511   # try to run a file with an error
512   assume-resources [
513   ¦ [lesson/recipes.mu] <- [
514   ¦ ¦ |recipe foo [|
515   ¦ ¦ |  local-scope|
516   ¦ ¦ |  x:num <- copy y:num|
517   ¦ ¦ |]|
518   ¦ ]
519   ]
520   env:&:environment <- new-programming-environment resources, screen, [foo]
521   assume-console [
522   ¦ press F4
523   ]
524   event-loop screen, console, env, resources
525   screen-should-contain [
526   ¦ .  errors found                                                                   run (F4)           .
527   ¦ .recipe foo [                                      ╎foo                                              .
528   ¦ .  local-scope                                     ╎─────────────────────────────────────────────────.
529   ¦ .  x:num <- copy y:num                             ╎                                                 .
530   ¦ .]                                                 ╎                                                 .
531   ¦ .                                                  ╎                                                 .
532   ¦ .foo: tried to read ingredient 'y' in 'x:num <- co↩╎                                                 .
533   ¦ .py y:num' but it hasn't been written to yet       ╎                                                 .
534   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
535   ¦ .                                                  ╎                                                 .
536   ]
537   # rerun the file, check for the same error
538   assume-console [
539   ¦ press F4
540   ]
541   run [
542   ¦ event-loop screen, console, env, resources
543   ]
544   screen-should-contain [
545   ¦ .  errors found                                                                   run (F4)           .
546   ¦ .recipe foo [                                      ╎foo                                              .
547   ¦ .  local-scope                                     ╎─────────────────────────────────────────────────.
548   ¦ .  x:num <- copy y:num                             ╎                                                 .
549   ¦ .]                                                 ╎                                                 .
550   ¦ .                                                  ╎                                                 .
551   ¦ .foo: tried to read ingredient 'y' in 'x:num <- co↩╎                                                 .
552   ¦ .py y:num' but it hasn't been written to yet       ╎                                                 .
553   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
554   ¦ .                                                  ╎                                                 .
555   ]
556 ]
557 
558 scenario run-instruction-and-print-errors [
559   local-scope
560   trace-until 100/app  # trace too long
561   assume-screen 100/width, 10/height
562   assume-resources [
563   ]
564   # sandbox editor contains an illegal instruction
565   env:&:environment <- new-programming-environment resources, screen, [get 1234:num, foo:offset]
566   assume-console [
567   ¦ press F4
568   ]
569   run [
570   ¦ event-loop screen, console, env, resources
571   ]
572   # check that screen prints error message in red
573   screen-should-contain [
574   ¦ .  errors found (0)                                                               run (F4)           .
575   ¦ .                                                  ╎                                                 .
576   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
577   ¦ .                                                  ╎0   edit          copy            delete         .
578   ¦ .                                                  ╎get 1234:num, foo:offset                         .
579   ¦ .                                                  ╎unknown element 'foo' in container 'number'      .
580   ¦ .                                                  ╎first ingredient of 'get' should be a container,↩.
581   ¦ .                                                  ╎ but got '1234:num'                              .
582   ¦ .                                                  ╎─────────────────────────────────────────────────.
583   ¦ .                                                  ╎                                                 .
584   ]
585   screen-should-contain-in-color 7/white, [
586   ¦ .                                                                                                    .
587   ¦ .                                                                                                    .
588   ¦ .                                                                                                    .
589   ¦ .                                                                                                    .
590   ¦ .                                                   get 1234:num, foo:offset                         .
591   ¦ .                                                                                                    .
592   ¦ .                                                                                                    .
593   ¦ .                                                                                                    .
594   ]
595   screen-should-contain-in-color 1/red, [
596   ¦ .  errors found (0)                                                                                  .
597   ¦ .                                                                                                    .
598   ¦ .                                                                                                    .
599   ¦ .                                                                                                    .
600   ¦ .                                                                                                    .
601   ¦ .                                                   unknown element 'foo' in container 'number'      .
602   ¦ .                                                   first ingredient of 'get' should be a container, .
603   ¦ .                                                    but got '1234:num'                              .
604   ¦ .                                                                                                    .
605   ]
606   screen-should-contain-in-color 245/grey, [
607   ¦ .                                                                                                    .
608   ¦ .                                                  ╎                                                 .
609   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
610   ¦ .                                                  ╎                                                 .
611   ¦ .                                                  ╎                                                 .
612   ¦ .                                                  ╎                                                 .
613   ¦ .                                                  ╎                                                ↩.
614   ¦ .                                                  ╎                                                 .
615   ¦ .                                                  ╎─────────────────────────────────────────────────.
616   ¦ .                                                  ╎                                                 .
617   ]
618 ]
619 
620 scenario run-instruction-and-print-errors-only-once [
621   local-scope
622   trace-until 100/app  # trace too long
623   assume-screen 100/width, 10/height
624   assume-resources [
625   ]
626   # sandbox editor contains an illegal instruction
627   env:&:environment <- new-programming-environment resources, screen, [get 1234:num, foo:offset]
628   # run the code in the editors multiple times
629   assume-console [
630   ¦ press F4
631   ¦ press F4
632   ]
633   run [
634   ¦ event-loop screen, console, env, resources
635   ]
636   # check that screen prints error message just once
637   screen-should-contain [
638   ¦ .  errors found (0)                                                               run (F4)           .
639   ¦ .                                                  ╎                                                 .
640   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
641   ¦ .                                                  ╎0   edit          copy            delete         .
642   ¦ .                                                  ╎get 1234:num, foo:offset                         .
643   ¦ .                                                  ╎unknown element 'foo' in container 'number'      .
644   ¦ .                                                  ╎first ingredient of 'get' should be a container,↩.
645   ¦ .                                                  ╎ but got '1234:num'                              .
646   ¦ .                                                  ╎─────────────────────────────────────────────────.
647   ¦ .                                                  ╎                                                 .
648   ]
649 ]
650 
651 scenario sandbox-can-handle-infinite-loop [
652   local-scope
653   trace-until 100/app  # trace too long
654   assume-screen 100/width, 20/height
655   # sandbox editor will trigger an infinite loop
656   assume-resources [
657   ¦ [lesson/recipes.mu] <- [
658   ¦ ¦ |recipe foo [|
659   ¦ ¦ |  {|
660   ¦ ¦ |    loop|
661   ¦ ¦ |  }|
662   ¦ ¦ |]|
663   ¦ ]
664   ]
665   env:&:environment <- new-programming-environment resources, screen, [foo]
666   # run the sandbox
667   assume-console [
668   ¦ press F4
669   ]
670   run [
671   ¦ event-loop screen, console, env, resources
672   ]
673   screen-should-contain [
674   ¦ .  errors found (0)                                                               run (F4)           .
675   ¦ .recipe foo [                                      ╎                                                 .
676   ¦ .  {                                               ╎─────────────────────────────────────────────────.
677   ¦ .    loop                                          ╎0   edit          copy            delete         .
678   ¦ .  }                                               ╎foo                                              .
679   ¦ .]                                                 ╎took too long!                                   .
680   ¦ .                                                  ╎─────────────────────────────────────────────────.
681   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
682   ¦ .                                                  ╎                                                 .
683   ]
684 ]
685 
686 scenario sandbox-with-errors-shows-trace [
687   local-scope
688   trace-until 100/app  # trace too long
689   assume-screen 100/width, 10/height
690   # generate a stash and a error
691   assume-resources [
692   ¦ [lesson/recipes.mu] <- [
693   ¦ ¦ |recipe foo [|
694   ¦ ¦ |  local-scope|
695   ¦ ¦ |  a:num <- next-ingredient|
696   ¦ ¦ |  b:num <- next-ingredient|
697   ¦ ¦ |  stash [dividing by], b|
698   ¦ ¦ |  _, c:num <- divide-with-remainder a, b|
699   ¦ ¦ |  reply b|
700   ¦ ¦ |]|
701   ¦ ]
702   ]
703   env:&:environment <- new-programming-environment resources, screen, [foo 4, 0]
704   # run
705   assume-console [
706   ¦ press F4
707   ]
708   event-loop screen, console, env, resources
709   # screen prints error message
710   screen-should-contain [
711   ¦ .  errors found (0)                                                               run (F4)           .
712   ¦ .recipe foo [                                      ╎                                                 .
713   ¦ .  local-scope                                     ╎─────────────────────────────────────────────────.
714   ¦ .  a:num <- next-ingredient                        ╎0   edit          copy            delete         .
715   ¦ .  b:num <- next-ingredient                        ╎foo 4, 0                                         .
716   ¦ .  stash [dividing by], b                          ╎foo: divide by zero in '_, c:num <- divide-with-↩.
717   ¦ .  _, c:num <- divide-with-remainder a, b          ╎remainder a, b'                                  .
718   ¦ .  reply b                                         ╎─────────────────────────────────────────────────.
719   ¦ .]                                                 ╎                                                 .
720   ¦ .                                                  ╎                                                 .
721   ]
722   # click on the call in the sandbox
723   assume-console [
724   ¦ left-click 4, 55
725   ]
726   run [
727   ¦ event-loop screen, console, env, resources
728   ]
729   # screen should expand trace
730   screen-should-contain [
731   ¦ .  errors found (0)                                                               run (F4)           .
732   ¦ .recipe foo [                                      ╎                                                 .
733   ¦ .  local-scope                                     ╎─────────────────────────────────────────────────.
734   ¦ .  a:num <- next-ingredient                        ╎0   edit          copy            delete         .
735   ¦ .  b:num <- next-ingredient                        ╎foo 4, 0                                         .
736   ¦ .  stash [dividing by], b                          ╎dividing by 0                                    .
737   ¦ .  _, c:num <- divide-with-remainder a, b          ╎14 instructions run                              .
738   ¦ .  reply b                                         ╎foo: divide by zero in '_, c:num <- divide-with-↩.
739   ¦ .]                                                 ╎remainder a, b'                                  .
740   ¦ .                                                  ╎─────────────────────────────────────────────────.
741   ]
742 ]