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