https://github.com/akkartik/mu/blob/master/edit/011-errors.mu

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