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