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 *recipes, 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?
 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   ¦ .foo: unknown element 'foo' in container 'number'  ╎                                                 .
150   ¦ .foo: first ingredient of 'get' should be a contai↩╎                                                 .
151   ¦ .ner, but got '123:num'                            ╎                                                 .
152   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
153   ¦ .                                                  ╎                                                 .
154   ]
155   screen-should-contain-in-color 1/red, [
156   ¦ .  errors found                                                                                      .
157   ¦ .                                                                                                    .
158   ¦ .                                                                                                    .
159   ¦ .                                                                                                    .
160   ¦ .foo: unknown element 'foo' in container 'number'                                                    .
161   ¦ .foo: first ingredient of 'get' should be a contai                                                   .
162   ¦ .ner, but got '123:num'                                                                              .
163   ¦ .                                                                                                    .
164   ]
165 ]
166 
167 scenario run-updates-status-with-first-erroneous-sandbox [
168   local-scope
169   trace-until 100/app  # trace too long
170   assume-screen 100/width, 15/height
171   assume-resources [
172   ]
173   env:&:environment <- new-programming-environment resources, screen, []
174   render-all screen, env, render
175   assume-console [
176   ¦ left-click 3, 80
177   ¦ # create invalid sandbox 1
178   ¦ type [get foo, x:offset]
179   ¦ press F4
180   ¦ # create invalid sandbox 0
181   ¦ type [get foo, x:offset]
182   ¦ press F4
183   ]
184   run [
185   ¦ event-loop screen, console, env, resources
186   ]
187   # status line shows that error is in first sandbox
188   screen-should-contain [
189   ¦ .  errors found (0)                                                               run (F4)           .
190   ]
191 ]
192 
193 scenario run-updates-status-with-first-erroneous-sandbox-2 [
194   local-scope
195   trace-until 100/app  # trace too long
196   assume-screen 100/width, 15/height
197   assume-resources [
198   ]
199   env:&:environment <- new-programming-environment resources, screen, []
200   render-all screen, env, render
201   assume-console [
202   ¦ left-click 3, 80
203   ¦ # create invalid sandbox 2
204   ¦ type [get foo, x:offset]
205   ¦ press F4
206   ¦ # create invalid sandbox 1
207   ¦ type [get foo, x:offset]
208   ¦ press F4
209   ¦ # create valid sandbox 0
210   ¦ type [add 2, 2]
211   ¦ press F4
212   ]
213   run [
214   ¦ event-loop screen, console, env, resources
215   ]
216   # status line shows that error is in second sandbox
217   screen-should-contain [
218   ¦ .  errors found (1)                                                               run (F4)           .
219   ]
220 ]
221 
222 scenario run-hides-errors-from-past-sandboxes [
223   local-scope
224   trace-until 100/app  # trace too long
225   assume-screen 100/width, 15/height
226   assume-resources [
227   ]
228   env:&:environment <- new-programming-environment resources, screen, [get foo, x:offset]  # invalid
229   render-all screen, env, render
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       to recipe    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   render-all screen, env, render
273   assume-console [
274   ¦ press F4
275   ]
276   event-loop screen, console, env, resources
277   screen-should-contain [
278   ¦ .  errors found (0)                                                               run (F4)           .
279   ¦ .recipe foo x:_elem -> z:_elem [                   ╎                                                 .
280   ¦ .  local-scope                                     ╎─────────────────────────────────────────────────.
281   ¦ .  load-ingredients                                ╎0   edit       copy       to recipe    delete    .
282   ¦ .  y:&:num <- copy 0                               ╎foo 2                                            .
283   ¦ .  z <- add x, y                                   ╎foo_2: 'add' requires number ingredients, but go↩.
284   ¦ .]                                                 ╎t 'y'                                            .
285   ¦ .                                                  ╎─────────────────────────────────────────────────.
286   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
287   ¦ .                                                  ╎                                                 .
288   ]
289   # now rerun everything
290   assume-console [
291   ¦ press F4
292   ]
293   run [
294   ¦ event-loop screen, console, env, resources
295   ]
296   # error should remain unchanged
297   screen-should-contain [
298   ¦ .  errors found (0)                                                               run (F4)           .
299   ¦ .recipe foo x:_elem -> z:_elem [                   ╎                                                 .
300   ¦ .  local-scope                                     ╎─────────────────────────────────────────────────.
301   ¦ .  load-ingredients                                ╎0   edit       copy       to recipe    delete    .
302   ¦ .  y:&:num <- copy 0                               ╎foo 2                                            .
303   ¦ .  z <- add x, y                                   ╎foo_3: 'add' requires number ingredients, but go↩.
304   ¦ .]                                                 ╎t 'y'                                            .
305   ¦ .                                                  ╎─────────────────────────────────────────────────.
306   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
307   ¦ .                                                  ╎                                                 .
308   ]
309 ]
310 
311 scenario run-avoids-spurious-errors-on-reloading-shape-shifting-recipes [
312   local-scope
313   trace-until 100/app  # trace too long
314   assume-screen 100/width, 15/height
315   # overload a well-known shape-shifting recipe
316   assume-resources [
317   ¦ [lesson/recipes.mu] <- [
318   ¦ ¦ |recipe length l:&:list:_elem -> n:num [|
319   ¦ ¦ |]|
320   ¦ ]
321   ]
322   # call code that uses other variants of it, but not it itself
323   test-sandbox:text <- new [x:&:list:num <- copy 0
324 to-text x]
325   env:&:environment <- new-programming-environment resources, screen, test-sandbox
326   render-all screen, env, render
327   # run it once
328   assume-console [
329   ¦ press F4
330   ]
331   event-loop screen, console, env, resources
332   # no errors anywhere on screen (can't check anything else, since to-text will return an address)
333   screen-should-contain-in-color 1/red, [
334   ¦ .                                                                                                    .
335   ¦ .                                                                                                    .
336   ¦ .                                                                                                    .
337   ¦ .                                                                                                    .
338   ¦ .                                                                <-                                  .
339   ¦ .                                                                                                    .
340   ¦ .                                                                                                    .
341   ¦ .                                                                                                    .
342   ¦ .                                                                                                    .
343   ¦ .                                                                                                    .
344   ¦ .                                                                                                    .
345   ¦ .                                                                                                    .
346   ¦ .                                                                                                    .
347   ¦ .                                                                                                    .
348   ¦ .                                                                                                    .
349   ]
350   # rerun everything
351   assume-console [
352   ¦ press F4
353   ]
354   run [
355   ¦ event-loop screen, console, env, resources
356   ]
357   # still no errors
358   screen-should-contain-in-color 1/red, [
359   ¦ .                                                                                                    .
360   ¦ .                                                                                                    .
361   ¦ .                                                                                                    .
362   ¦ .                                                                                                    .
363   ¦ .                                                                <-                                  .
364   ¦ .                                                                                                    .
365   ¦ .                                                                                                    .
366   ¦ .                                                                                                    .
367   ¦ .                                                                                                    .
368   ¦ .                                                                                                    .
369   ¦ .                                                                                                    .
370   ¦ .                                                                                                    .
371   ¦ .                                                                                                    .
372   ¦ .                                                                                                    .
373   ¦ .                                                                                                    .
374   ]
375 ]
376 
377 scenario run-shows-missing-type-errors [
378   local-scope
379   trace-until 100/app  # trace too long
380   assume-screen 100/width, 15/height
381   assume-resources [
382   ¦ [lesson/recipes.mu] <- [
383   ¦ ¦ |recipe foo [|
384   ¦ ¦ |  x <- copy 0|
385   ¦ ¦ |]|
386   ¦ ]
387   ]
388   env:&:environment <- new-programming-environment resources, screen, [foo]
389   render-all screen, env, render
390   assume-console [
391   ¦ press F4
392   ]
393   run [
394   ¦ event-loop screen, console, env, resources
395   ]
396   screen-should-contain [
397   ¦ .  errors found                                                                   run (F4)           .
398   ¦ .recipe foo [                                      ╎foo                                              .
399   ¦ .  x <- copy 0                                     ╎─────────────────────────────────────────────────.
400   ¦ .]                                                 ╎                                                 .
401   ¦ .foo: missing type for 'x' in 'x <- copy 0'        ╎                                                 .
402   ¦ .foo: can't copy '0' to 'x'; types don't match     ╎                                                 .
403   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
404   ¦ .                                                  ╎                                                 .
405   ]
406 ]
407 
408 scenario run-shows-unbalanced-bracket-errors [
409   local-scope
410   trace-until 100/app  # trace too long
411   assume-screen 100/width, 15/height
412   # recipe is incomplete (unbalanced '[')
413   assume-resources [
414   ¦ [lesson/recipes.mu] <- [
415   ¦ ¦ |recipe foo \\\[|
416   ¦ ¦ |  x <- copy 0|
417   ¦ ]
418   ]
419   env:&:environment <- new-programming-environment resources, screen, [foo]
420   render-all screen, env, render
421   assume-console [
422   ¦ press F4
423   ]
424   run [
425   ¦ event-loop screen, console, env, resources
426   ]
427   screen-should-contain [
428   ¦ .  errors found                                                                   run (F4)           .
429   ¦ .recipe foo \\[                                      ╎foo                                              .
430   ¦ .  x <- copy 0                                     ╎─────────────────────────────────────────────────.
431   ¦ .9: unbalanced '\\[' for recipe                      ╎                                                 .
432   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
433   ¦ .                                                  ╎                                                 .
434   ]
435 ]
436 
437 scenario run-shows-get-on-non-container-errors [
438   local-scope
439   trace-until 100/app  # trace too long
440   assume-screen 100/width, 15/height
441   assume-resources [
442   ¦ [lesson/recipes.mu] <- [
443   ¦ ¦ |recipe foo [|
444   ¦ ¦ |  local-scope|
445   ¦ ¦ |  x:&:point <- new point:type|
446   ¦ ¦ |  get x:&:point, 1:offset|
447   ¦ ¦ |]|
448   ¦ ]
449   ]
450   env:&:environment <- new-programming-environment resources, screen, [foo]
451   render-all screen, env, render
452   assume-console [
453   ¦ press F4
454   ]
455   run [
456   ¦ event-loop screen, console, env, resources
457   ]
458   screen-should-contain [
459   ¦ .  errors found                                                                   run (F4)           .
460   ¦ .recipe foo [                                      ╎foo                                              .
461   ¦ .  local-scope                                     ╎─────────────────────────────────────────────────.
462   ¦ .  x:&:point <- new point:type                     ╎                                                 .
463   ¦ .  get x:&:point, 1:offset                         ╎                                                 .
464   ¦ .]                                                 ╎                                                 .
465   ¦ .foo: first ingredient of 'get' should be a contai↩╎                                                 .
466   ¦ .ner, but got 'x:&:point'                          ╎                                                 .
467   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
468   ¦ .                                                  ╎                                                 .
469   ]
470 ]
471 
472 scenario run-shows-non-literal-get-argument-errors [
473   local-scope
474   trace-until 100/app  # trace too long
475   assume-screen 100/width, 15/height
476   assume-resources [
477   ¦ [lesson/recipes.mu] <- [
478   ¦ ¦ |recipe foo [|
479   ¦ ¦ |  local-scope|
480   ¦ ¦ |  x:num <- copy 0|
481   ¦ ¦ |  y:&:point <- new point:type|
482   ¦ ¦ |  get *y:&:point, x:num|
483   ¦ ¦ |]|
484   ¦ ]
485   ]
486   env:&:environment <- new-programming-environment resources, screen, [foo]
487   render-all screen, env, render
488   assume-console [
489   ¦ press F4
490   ]
491   run [
492   ¦ event-loop screen, console, env, resources
493   ]
494   screen-should-contain [
495   ¦ .  errors found                                                                   run (F4)           .
496   ¦ .recipe foo [                                      ╎foo                                              .
497   ¦ .  local-scope                                     ╎─────────────────────────────────────────────────.
498   ¦ .  x:num <- copy 0                                 ╎                                                 .
499   ¦ .  y:&:point <- new point:type                     ╎                                                 .
500   ¦ .  get *y:&:point, x:num                           ╎                                                 .
501   ¦ .]                                                 ╎                                                 .
502   ¦ .foo: second ingredient of 'get' should have type ↩╎                                                 .
503   ¦ .'offset', but got 'x:num'                         ╎                                                 .
504   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
505   ¦ .                                                  ╎                                                 .
506   ]
507 ]
508 
509 scenario run-shows-errors-everytime [
510   local-scope
511   trace-until 100/app  # trace too long
512   assume-screen 100/width, 15/height
513   # try to run a file with an error
514   assume-resources [
515   ¦ [lesson/recipes.mu] <- [
516   ¦ ¦ |recipe foo [|
517   ¦ ¦ |  local-scope|
518   ¦ ¦ |  x:num <- copy y:num|
519   ¦ ¦ |]|
520   ¦ ]
521   ]
522   env:&:environment <- new-programming-environment resources, screen, [foo]
523   render-all screen, env, render
524   assume-console [
525   ¦ press F4
526   ]
527   event-loop screen, console, env, resources
528   screen-should-contain [
529   ¦ .  errors found                                                                   run (F4)           .
530   ¦ .recipe foo [                                      ╎foo                                              .
531   ¦ .  local-scope                                     ╎─────────────────────────────────────────────────.
532   ¦ .  x:num <- copy y:num                             ╎                                                 .
533   ¦ .]                                                 ╎                                                 .
534   ¦ .foo: tried to read ingredient 'y' in 'x:num <- co↩╎                                                 .
535   ¦ .py y:num' but it hasn't been written to yet       ╎                                                 .
536   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
537   ¦ .                                                  ╎                                                 .
538   ]
539   # rerun the file, check for the same error
540   assume-console [
541   ¦ press F4
542   ]
543   run [
544   ¦ event-loop screen, console, env, resources
545   ]
546   screen-should-contain [
547   ¦ .  errors found                                                                   run (F4)           .
548   ¦ .recipe foo [                                      ╎foo                                              .
549   ¦ .  local-scope                                     ╎─────────────────────────────────────────────────.
550   ¦ .  x:num <- copy y:num                             ╎                                                 .
551   ¦ .]                                                 ╎                                                 .
552   ¦ .foo: tried to read ingredient 'y' in 'x:num <- co↩╎                                                 .
553   ¦ .py y:num' but it hasn't been written to yet       ╎                                                 .
554   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
555   ¦ .                                                  ╎                                                 .
556   ]
557 ]
558 
559 scenario run-instruction-and-print-errors [
560   local-scope
561   trace-until 100/app  # trace too long
562   assume-screen 100/width, 10/height
563   assume-resources [
564   ]
565   # sandbox editor contains an illegal instruction
566   env:&:environment <- new-programming-environment resources, screen, [get 1234:num, foo:offset]
567   render-all screen, env, render
568   assume-console [
569   ¦ press F4
570   ]
571   run [
572   ¦ event-loop screen, console, env, resources
573   ]
574   # check that screen prints error message in red
575   screen-should-contain [
576   ¦ .  errors found (0)                                                               run (F4)           .
577   ¦ .                                                  ╎                                                 .
578   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
579   ¦ .                                                  ╎0   edit       copy       to recipe    delete    .
580   ¦ .                                                  ╎get 1234:num, foo:offset                         .
581   ¦ .                                                  ╎unknown element 'foo' in container 'number'      .
582   ¦ .                                                  ╎first ingredient of 'get' should be a container,↩.
583   ¦ .                                                  ╎ but got '1234:num'                              .
584   ¦ .                                                  ╎─────────────────────────────────────────────────.
585   ¦ .                                                  ╎                                                 .
586   ]
587   screen-should-contain-in-color 7/white, [
588   ¦ .                                                                                                    .
589   ¦ .                                                                                                    .
590   ¦ .                                                                                                    .
591   ¦ .                                                                                                    .
592   ¦ .                                                   get 1234:num, foo:offset                         .
593   ¦ .                                                                                                    .
594   ¦ .                                                                                                    .
595   ¦ .                                                                                                    .
596   ]
597   screen-should-contain-in-color 1/red, [
598   ¦ .  errors found (0)                                                                                  .
599   ¦ .                                                                                                    .
600   ¦ .                                                                                                    .
601   ¦ .                                                                                                    .
602   ¦ .                                                                                                    .
603   ¦ .                                                   unknown element 'foo' in container 'number'      .
604   ¦ .                                                   first ingredient of 'get' should be a container, .
605   ¦ .                                                    but got '1234:num'                              .
606   ¦ .                                                                                                    .
607   ]
608   screen-should-contain-in-color 245/grey, [
609   ¦ .                                                                                                    .
610   ¦ .                                                  ╎                                                 .
611   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
612   ¦ .                                                  ╎                                                 .
613   ¦ .                                                  ╎                                                 .
614   ¦ .                                                  ╎                                                 .
615   ¦ .                                                  ╎                                                ↩.
616   ¦ .                                                  ╎                                                 .
617   ¦ .                                                  ╎─────────────────────────────────────────────────.
618   ¦ .                                                  ╎                                                 .
619   ]
620 ]
621 
622 scenario run-instruction-and-print-errors-only-once [
623   local-scope
624   trace-until 100/app  # trace too long
625   assume-screen 100/width, 10/height
626   assume-resources [
627   ]
628   # sandbox editor contains an illegal instruction
629   env:&:environment <- new-programming-environment resources, screen, [get 1234:num, foo:offset]
630   render-all screen, env, render
631   # run the code in the editors multiple times
632   assume-console [
633   ¦ press F4
634   ¦ press F4
635   ]
636   run [
637   ¦ event-loop screen, console, env, resources
638   ]
639   # check that screen prints error message just once
640   screen-should-contain [
641   ¦ .  errors found (0)                                                               run (F4)           .
642   ¦ .                                                  ╎                                                 .
643   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────.
644   ¦ .                                                  ╎0   edit       copy       to recipe    delete    .
645   ¦ .                                                  ╎get 1234:num, foo:offset                         .
646   ¦ .                                                  ╎unknown element 'foo' in container 'number'      .
647   ¦ .                                                  ╎first ingredient of 'get' should be a container,↩.
648   ¦ .                                                  ╎ but got '1234:num'                              .
649   ¦ .                                                  ╎─────────────────────────────────────────────────.
650   ¦ .                                                  ╎                                                 .
651   ]
652 ]
653 
654 scenario sandbox-can-handle-infinite-loop [
655   local-scope
656   trace-until 100/app  # trace too long
657   assume-screen 100/width, 20/height
658   # sandbox editor will trigger an infinite loop
659   assume-resources [
660   ¦ [lesson/recipes.mu] <- [
661   ¦ ¦ |recipe foo [|
662   ¦ ¦ |  {|
663   ¦ ¦ |    loop|
664   ¦ ¦ |  }|
665   ¦ ¦ |]|
666   ¦ ]
667   ]
668   env:&:environment <- new-programming-environment resources, screen, [foo]
669   render-all screen, env, render
670   # run the sandbox
671   assume-console [
672   ¦ press F4
673   ]
674   run [
675   ¦ event-loop screen, console, env, resources
676   ]
677   screen-should-contain [
678   ¦ .  errors found (0)                                                               run (F4)           .
679   ¦ .recipe foo [                                      ╎                                                 .
680   ¦ .  {                                               ╎─────────────────────────────────────────────────.
681   ¦ .    loop                                          ╎0   edit       copy       to recipe    delete    .
682   ¦ .  }                                               ╎foo                                              .
683   ¦ .]                                                 ╎took too long!                                   .
684   ¦ .                                                  ╎─────────────────────────────────────────────────.
685   ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎                                                 .
686   ¦ .                                                  ╎                                                 .
687   ]
688 ]
689 
690 scenario sandbox-with-errors-shows-trace [
691   local-scope
692   trace-until 100/app  # trace too long
693   assume-screen 100/width, 10/height
694   # generate a stash and a error
695   assume-resources [
696   ¦ [lesson/recipes.mu] <- [
697   ¦ ¦ |recipe foo [|
698   ¦ ¦ |  local-scope|
699   ¦ ¦ |  a:num <- next-ingredient|
700   ¦ ¦ |  b:num <- next-ingredient|
701   ¦ ¦ |  stash [dividing by], b|
702   ¦ ¦ |  _, c:num <- divide-with-remainder a, b|
703   ¦ ¦ |  reply b|
704   ¦ ¦ |]|
705   ¦ ]
706   ]
707   env:&:environment <- new-programming-environment resources, screen, [foo 4, 0]
708   render-all screen, env, render
709   # run
710   assume-console [
711   ¦ press F4
712   ]
713   event-loop screen, console, env, resources
714   # screen prints error message
715   screen-should-contain [
716   ¦ .  errors found (0)                                                               run (F4)           .
717   ¦ .recipe foo [                                      ╎                                                 .
718   ¦ .  local-scope                                     ╎─────────────────────────────────────────────────.
719   ¦ .  a:num <- next-ingredient                        ╎0   edit       copy       to recipe    delete    .
720   ¦ .  b:num <- next-ingredient                        ╎foo 4, 0                                         .
721   ¦ .  stash [dividing by], b                          ╎foo: divide by zero in '_, c:num <- divide-with-↩.
722   ¦ .  _, c:num <- divide-with-remainder a, b          ╎remainder a, b'                                  .
723   ¦ .  reply b                                         ╎─────────────────────────────────────────────────.
724   ¦ .]                                                 ╎                                                 .
725   ¦ .                                                  ╎                                                 .
726   ]
727   # click on the call in the sandbox
728   assume-console [
729   ¦ left-click 4, 55
730   ]
731   run [
732   ¦ event-loop screen, console, env, resources
733   ]
734   # screen should expand trace
735   screen-should-contain [
736   ¦ .  errors found (0)                                                               run (F4)           .
737   ¦ .recipe foo [                                      ╎                                                 .
738   ¦ .  local-scope                                     ╎─────────────────────────────────────────────────.
739   ¦ .  a:num <- next-ingredient                        ╎0   edit       copy       to recipe    delete    .
740   ¦ .  b:num <- next-ingredient                        ╎foo 4, 0                                         .
741   ¦ .  stash [dividing by], b                          ╎dividing by 0                                    .
742   ¦ .  _, c:num <- divide-with-remainder a, b          ╎14 instructions run                              .
743   ¦ .  reply b                                         ╎foo: divide by zero in '_, c:num <- divide-with-↩.
744   ¦ .]                                                 ╎remainder a, b'                                  .
745   ¦ .                                                  ╎─────────────────────────────────────────────────.
746   ]
747 ]