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