about summary refs log tree commit diff stats
ModeNameSize
-rw-r--r--.travis.yml1771log stats plain blame
-rw-r--r--000organization.cc5855log stats plain blame
-rw-r--r--001help.cc10831log stats plain blame
-rw-r--r--002test.cc3140log stats plain blame
-rw-r--r--003trace.cc15053log stats plain blame
-rw-r--r--003trace.test.cc3817log stats plain blame
-rw-r--r--010vm.cc27773log stats plain blame
-rw-r--r--011load.cc11257log stats plain blame
-rw-r--r--012transform.cc3399log stats plain blame
-rw-r--r--013update_operation.cc1351log stats plain blame
-rw-r--r--014literal_string.cc5978log stats plain blame
-rw-r--r--015literal_noninteger.cc1333log stats plain blame
-rw-r--r--016dilated_reagent.cc4217log stats plain blame
-rw-r--r--017parse_tree.cc3076log stats plain blame
-rw-r--r--018constant.cc1305log stats plain blame
-rw-r--r--019type_abbreviations.cc7097log stats plain blame
-rw-r--r--020run.cc15846log stats plain blame
-rw-r--r--021check_instruction.cc7705log stats plain blame
-rw-r--r--022arithmetic.cc25334log stats plain blame
-rw-r--r--023boolean.cc5106log stats plain blame
-rw-r--r--024jump.cc6745log stats plain blame
-rw-r--r--025compare.cc15767log stats plain blame
-rw-r--r--026call.cc7882log stats plain blame
-rw-r--r--027call_ingredient.cc6597log stats plain blame
-rw-r--r--028call_return.cc6662log stats plain blame
-rw-r--r--029tools.cc8424log stats plain blame
-rw-r--r--030container.cc24632log stats plain blame
-rw-r--r--031merge.cc8184log stats plain blame
-rw-r--r--032array.cc19528log stats plain blame
-rw-r--r--033exclusive_container.cc14075log stats plain blame
-rw-r--r--034address.cc16240log stats plain blame
-rw-r--r--035lookup.cc15781log stats plain blame
-rw-r--r--036abandon.cc4754log stats plain blame
-rw-r--r--038new_text.cc7058log stats plain blame
-rw-r--r--040brace.cc11806log stats plain blame
-rw-r--r--041jump_target.cc5271log stats plain blame
-rw-r--r--042name.cc11943log stats plain blame
-rw-r--r--043space.cc10159log stats plain blame
-rw-r--r--044space_surround.cc2739log stats plain blame
-rw-r--r--045closure_name.cc7366log stats plain blame
-rw-r--r--046check_type_by_name.cc6800log stats plain blame
-rw-r--r--050scenario.cc28897log stats plain blame
-rw-r--r--051scenario_test.mu1044log stats plain blame
-rw-r--r--052tangle.cc12093log stats plain blame
-rw-r--r--053recipe_header.cc21553log stats plain blame
-rw-r--r--054static_dispatch.cc19127log stats plain blame
-rw-r--r--055shape_shifting_container.cc20492log stats plain blame
-rw-r--r--056shape_shifting_recipe.cc37114log stats plain blame
-rw-r--r--057immutable.cc20712log stats plain blame
-rw-r--r--058to_text.cc836log stats plain blame
-rw-r--r--059to_text.mu1234log stats plain blame
-rw-r--r--060rewrite_literal_string.cc3095log stats plain blame
-rw-r--r--061text.mu30758log stats plain blame
-rw-r--r--062convert_ingredients_to_text.cc6039log stats plain blame
-rw-r--r--063array.mu3627log stats plain blame
-rw-r--r--064list.mu8374log stats plain blame
-rw-r--r--065duplex_list.mu19731log stats plain blame
-rw-r--r--066stream.mu2088log stats plain blame
-rw-r--r--067random.cc960log stats plain blame
-rw-r--r--068random.mu1976log stats plain blame
-rw-r--r--069hash.cc9475log stats plain blame
-rw-r--r--070table.mu3131log stats plain blame
-rw-r--r--072recipe.cc20347log stats plain blame
-rw-r--r--073scheduler.cc18233log stats plain blame
-rw-r--r--074wait.cc20257log stats plain blame
-rw-r--r--075channel.mu14937log stats plain blame
-rw-r--r--076continuation.cc14835log stats plain blame
-rw-r--r--080display.cc14594log stats plain blame
-rw-r--r--081print.mu24667log stats plain blame
-rw-r--r--082scenario_screen.cc17187log stats plain blame
-rw-r--r--083scenario_screen_test.mu911log stats plain blame
-rw-r--r--084console.mu2963log stats plain blame
-rw-r--r--085scenario_console.cc10708log stats plain blame
-rw-r--r--086scenario_console_test.mu506log stats plain blame
-rw-r--r--087file.cc9508log stats plain blame
-rw-r--r--088file.mu5875log stats plain blame
-rw-r--r--089scenario_filesystem.cc8514log stats plain blame
-rw-r--r--090scenario_filesystem_test.mu2541log stats plain blame
-rw-r--r--091socket.cc13920log stats plain blame
-rw-r--r--092socket.mu4600log stats plain blame
-rw-r--r--099hardware_checks.cc2451log stats plain blame
-rw-r--r--100trace_browser.cc18911log stats plain blame
-rw-r--r--101run_sandboxed.cc20294log stats plain blame
-rw-r--r--998check_type_pointers.cc1774log stats plain blame
-rw-r--r--999spaces.cc3238log stats plain blame
-rw-r--r--Readme.md18169log stats plain blame
d---------arc1213log stats plain
-rwxr-xr-xbuild01583log stats plain blame
-rwxr-xr-xbuild12335log stats plain blame
-rwxr-xr-xbuild25643log stats plain blame
-rwxr-xr-xbuild36417log stats plain blame
-rwxr-xr-xbuild48989log stats plain blame
-rwxr-xr-xbuild_and_test_until397log stats plain blame
-rw-r--r--cannot_write_tests_for675log stats plain blame
-rw-r--r--channel.mu1093log stats plain blame
-rw-r--r--chessboard.mu21343log stats plain blame
-rwxr-xr-xclean310log stats plain blame
d---------cleave71log stats plain
-rw-r--r--console.mu337log stats plain blame
-rw-r--r--continuation1.mu596log stats plain blame
-rw-r--r--continuation2.mu759log stats plain blame
-rw-r--r--continuation3.mu725log stats plain blame
-rw-r--r--continuation4.mu1109log stats plain blame
-rw-r--r--continuation5.mu1123log stats plain blame
-rwxr-xr-xcopy_mu346log stats plain blame
-rw-r--r--counters.mu860log stats plain blame
-rw-r--r--display.mu657log stats plain blame
d---------edit588log stats plain
d---------enumerate74log stats plain
-rw-r--r--example1.mu125log stats plain blame
-rw-r--r--exception1.mu2350log stats plain blame
-rw-r--r--exception2.mu1923log stats plain blame
-rw-r--r--exuberant_ctags_rc510log stats plain blame
-rw-r--r--factorial.mu529log stats plain blame
-rw-r--r--filesystem.mu715log stats plain blame
-rw-r--r--fork.mu162log stats plain blame
-rwxr-xr-xgit_log_filtered234log stats plain blame
d---------html6413log stats plain
-rw-r--r--http-client.mu690log stats plain blame
-rw-r--r--http-server.mu972log stats plain blame
-rw-r--r--immutable-error.mu214log stats plain blame
-rw-r--r--index.html20955log stats plain blame
-rw-r--r--lambda-to-mu.mu15021log stats plain blame
d---------linkify138log stats plain
-rwxr-xr-xmu182log stats plain blame
-rw-r--r--mu.vim4066log stats plain blame
-rw-r--r--mutable.mu170log stats plain blame
-rwxr-xr-xnew_lesson340log stats plain blame
-rw-r--r--nqueens.mu2676log stats plain blame
-rw-r--r--real-files.mu605log stats plain blame
-rwxr-xr-xrelayout1017log stats plain blame
-rw-r--r--same-fringe.mu2164log stats plain blame
d---------sandbox659log stats plain
-rw-r--r--screen.mu871log stats plain blame
-rwxr-xr-xsnapshot_lesson365log stats plain blame
-rw-r--r--static-dispatch.mu574log stats plain blame
d---------subx1460log stats plain
-rw-r--r--tangle.mu741log stats plain blame
d---------tangle313log stats plain
d---------termbox326log stats plain
-rwxr-xr-xtest_layers2216log stats plain blame
-rwxr-xr-xupdate_html2624log stats plain blame
-rw-r--r--vimrc.vim2907log stats plain blame
-rw-r--r--x.mu133log stats plain blame
d'>93d4cc93 ^
cb48c5d7 ^










551d155c ^
5f98a10c ^
1ead3562 ^
192d59d3 ^







551d155c ^
192d59d3 ^
551d155c ^
051c4738 ^
5f98a10c ^
1ead3562 ^
c6520d96 ^
192d59d3 ^





15936c91 ^
551d155c ^
944f4410 ^
a55bbd06 ^
fb85b3b4 ^
5f98a10c ^
1ead3562 ^
fb85b3b4 ^
192d59d3 ^






fb85b3b4 ^
192d59d3 ^
fb85b3b4 ^
5c6840b8 ^


1ead3562 ^
192d59d3 ^




5c6840b8 ^


991d76f3 ^
1848b18f ^
991d76f3 ^
1ead3562 ^
192d59d3 ^




1848b18f ^
991d76f3 ^
1848b18f ^

991d76f3 ^
a55bbd06 ^
991d76f3 ^
b8515e8a ^
991d76f3 ^

8d72e565 ^
e4630643 ^

3473c63a ^
15936c91 ^
1ad3fe9e ^
9dcbec39 ^
46026f62 ^

3473c63a ^
15936c91 ^

9dcbec39 ^
991d76f3 ^

3473c63a ^
15936c91 ^
9f7f62ed ^
3377364a ^
991d76f3 ^
9dcbec39 ^
fb85b3b4 ^

fc19980d ^

0d219477 ^


fc19980d ^
b8515e8a ^


991d76f3 ^
3473c63a ^
15936c91 ^
b24eb476 ^
18e626df ^
acc4792d ^
18e626df ^

3473c63a ^
15936c91 ^

15936c91 ^
9393ccc8 ^
551d155c ^

9f7f62ed ^
991d76f3 ^



6e793202 ^
6c96a437 ^
991d76f3 ^



a55bbd06 ^
c8a58cdc ^
991d76f3 ^
5f98a10c ^
1ead3562 ^
c6520d96 ^
192d59d3 ^





991d76f3 ^

551d155c ^
9393ccc8 ^
551d155c ^
991d76f3 ^
5f98a10c ^
1ead3562 ^
c6520d96 ^
192d59d3 ^





991d76f3 ^

551d155c ^
9393ccc8 ^
551d155c ^
0d219477 ^




192d59d3 ^

0d219477 ^
192d59d3 ^
0d219477 ^
c8a58cdc ^


1ead3562 ^
192d59d3 ^




c8a58cdc ^





795f5244 ^
b8515e8a ^
c8a58cdc ^
b8515e8a ^
8d72e565 ^
e4630643 ^

3473c63a ^
15936c91 ^

9dcbec39 ^
c8a58cdc ^

b8515e8a ^



3473c63a ^
15936c91 ^

acc4792d ^
18e626df ^

cfb142b9 ^
15936c91 ^
c8a58cdc ^

e74a2940 ^




991d76f3 ^
e74a2940 ^
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646

                                                                              



                                                                               
 

                                               
          
                                                                                   
                               





                                             
                                                  
                                       
                    
                              
                                                                                                                                                    

          
                                                
                                         
                              
                                                                                                                                   

          
                             
                                                                                                               


                                                                   

                                                                 
                                                                                                                    

          


                                                          
                                                                                                                                                                                         

          



                                                
                                                                 
                                       
                                   



                                                                 
                                                       
                                                                                               
                                                                
                                               
                                                                   
                     
                                                 
                                   
   

                              

 
                      
                                                                          
                               



                                                                              
          




                                   
 



                              
 
                       
          




                               


                     



                                                                                
                                                
                                                                                               
                       
                                                                                                             
             
   
                                                                                
 
 



                                                                                      

                                                                                                                                                           
                         
                                                      




                                  

                                                                          
                                              
                                                                                               
 
                             


                                                                           
                                                  
               
               


         




                                                                                                                        
                                                     

                     
             
 
                                                            
 











                                                                                                                                        
                                                                                                     



                                                                                                                              

 

                                                                             
                                              






                                                                                              

               

          

                                   


           
                                 
                     
                
                             
 
         
                   
                                 


               



                                                              

                                                                                              






























































                                                                                                            

                                                
                 
          



                               
                                                                                        
 

                              


                                                 



                                                           


                              
                               
          





                                   
 

                              

                                             
                                        
                                    
                                       
             
                                    
                                                                                                                                  

          
                                                
                               
                           
                                                                                                                

          
                                                 

                                
                                                                                                                                                   

          
                                   
                                                
                                  
                           
                                               
                                           
                                                                                                                                                                                                                                   

          



                                                
                                                                 
                             
                                
                                                                    
                          
                                                                                                                                              

          
                                                                  

                                               
                                                                                      
                                                                                                                                                                          

          




                                                                                             

                                           


        
       
                                                      



                                                 
                      








                                                                                                                      
                             
   
                     

 
                                    
                                   


                                                                                                                                                                       
                         
                                                        
   
                                               


                                        
                          




                                   
                                                                       



                               




                                 










                                                       
                               
                     
          







                                                                                                        
 
                                                         
 
                                 
                     
          
                                 





                  
                         
 
                                                           
 
                                       
                     
          
                                 






                                 
 
                                                                                          
 


                                                                              
          




                               


                
                                               
 
                     
          




                                             
 
                              

                                             
          
                                        
                                            
                                       

                                    
                                                                                                                                      

          
                                                
                                   
                           
                                                                                                                    

          
                                                 

                                    
                                                                                                                                                                               

          
                                                 
                                    
                           
                                               
                                         
                                                                                                                                                                                                                                                                                                                  

          

                                                                


                                                                                                                                                                                                                    
                                 


                                                
                 
                                                                 
                                 
                                
                          
                                                                                                                                              

          
                                                                  

                                               
                                                                                      
                                                                                                                                                                          

          
                                                                                                    



                                                                              
                                     
                                           



                                                                                                            
 
 
                                   
                     
          
                                 





                  

                                                                                                                                             
 
                                                                                       
 
                                     
                     
          
                                 





                  

                                                       
 
                                                                                         
 




                                   

                                                 
 
                                                                                                      
 


                                   
          




                               





                                             
                                      
                                       
              
                                    
                                                                                                                                   

          
                                                 

                                 
                                                                                                   

          



                                                
                                                                  

                               
                                                                                                                                              

          
                     
                                                               

        




                                                                             
                                                                     
               
//: Arrays contain a variable number of elements of the same type. Their value
//: starts with the length of the array.
//:
//: You can create arrays of containers, but containers can only contain
//: elements of a fixed size, so you can't create containers containing arrays.
//: Create containers containing addresses to arrays instead.

//: You can create arrays using 'create-array'.
:(scenario create_array)
def main [
  # create an array occupying locations 1 (for the size) and 2-4 (for the elements)
  1:array:num:3 <- create-array
]
+run: creating array of size 4

:(before "End Primitive Recipe Declarations")
CREATE_ARRAY,
:(before "End Primitive Recipe Numbers")
put(Recipe_ordinal, "create-array", CREATE_ARRAY);
:(before "End Primitive Recipe Checks")
case CREATE_ARRAY: {
  if (inst.products.empty()) {
    raise << maybe(get(Recipe, r).name) << "'create-array' needs one product and no ingredients but got '" << inst.original_string << '\n' << end();
    break;
  }
  reagent/*copy*/ product = inst.products.at(0);
  // Update CREATE_ARRAY product in Check
  if (!is_mu_array(product)) {
    raise << maybe(get(Recipe, r).name) << "'create-array' cannot create non-array '" << product.original_string << "'\n" << end();
    break;
  }
  if (!product.type->right) {
    raise << maybe(get(Recipe, r).name) << "create array of what? '" << inst.original_string << "'\n" << end();
    break;
  }
  // 'create-array' will need to check properties rather than types
  type_tree* array_length_from_type = product.type->right->right;
  if (!array_length_from_type) {
    raise << maybe(get(Recipe, r).name) << "create array of what size? '" << inst.original_string << "'\n" << end();
    break;
  }
  if (!product.type->right->right->atom)
    array_length_from_type = array_length_from_type->left;
  if (!is_integer(array_length_from_type->name)) {
    raise << maybe(get(Recipe, r).name) << "'create-array' product should specify size of array after its element type, but got '" << product.type->right->right->name << "'\n" << end();
    break;
  }
  break;
}
:(before "End Primitive Recipe Implementations")
case CREATE_ARRAY: {
  reagent/*copy*/ product = current_instruction().products.at(0);
  // Update CREATE_ARRAY product in Run
  int base_address = product.value;
  type_tree* array_length_from_type = product.type->right->right;
  if (!product.type->right->right->atom)
    array_length_from_type = array_length_from_type->left;
  int array_length = to_integer(array_length_from_type->name);
  // initialize array length, so that size_of will work
  trace(9999, "mem") << "storing " << array_length << " in location " << base_address << end();
  put(Memory, base_address, array_length);  // in array elements
  int size = size_of(product);  // in locations
  trace(9998, "run") << "creating array of size " << size << end();
  // initialize array
  for (int i = 1;  i <= size_of(product);  ++i) {
    put(Memory, base_address+i, 0);
  }
  // no need to update product
  goto finish_instruction;
}

:(scenario copy_array)
# Arrays can be copied around with a single instruction just like numbers,
# no matter how large they are.
# You don't need to pass the size around, since each array variable stores its
# size in memory at run-time. We'll call a variable with an explicit size a
# 'static' array, and one without a 'dynamic' array since it can contain
# arrays of many different sizes.
def main [
  1:array:num:3 <- create-array
  2:num <- copy 14
  3:num <- copy 15
  4:num <- copy 16
  5:array:num <- copy 1:array:num:3
]
+mem: storing 3 in location 5
+mem: storing 14 in location 6
+mem: storing 15 in location 7
+mem: storing 16 in location 8

:(scenario stash_array)
def main [
  1:array:num:3 <- create-array
  2:num <- copy 14
  3:num <- copy 15
  4:num <- copy 16
  stash [foo:], 1:array:num:3
]
+app: foo: 3 14 15 16

:(before "End types_coercible Special-cases")
if (is_mu_array(from) && is_mu_array(to))
  return types_strictly_match(array_element(from.type), array_element(to.type));

:(before "End size_of(reagent r) Special-cases")
if (!r.type->atom && r.type->left->atom && r.type->left->value == get(Type_ordinal, "array")) {
  if (!r.type->right) {
    raise << maybe(current_recipe_name()) << "'" << r.original_string << "' is an array of what?\n" << end();
    return 1;
  }
  return /*space for length*/1 + array_length(r)*size_of(array_element(r.type));
}

:(before "End size_of(type) Non-atom Special-cases")
if (type->left->value == get(Type_ordinal, "array")) return static_array_length(type);
:(code)
int static_array_length(const type_tree* type) {
  if (!type->atom && type->right && !type->right->atom && type->right->right && !type->right->right->atom && !type->right->right->right  // exactly 3 types
      && type->right->right->left && type->right->right->left->atom && is_integer(type->right->right->left->name)) {  // third 'type' is a number
    // get size from type
    return to_integer(type->right->right->left->name);
  }
  cerr << to_string(type) << '\n';
  assert(false);
}

//: disable the size mismatch check for arrays since the destination array
//: need not be initialized
:(before "End size_mismatch(x) Special-cases")
if (x.type && !x.type->atom && x.type->left->value == get(Type_ordinal, "array")) return false;

//:: arrays inside containers
//: arrays are disallowed inside containers unless their length is fixed in
//: advance

:(scenario container_permits_static_array_element)
container foo [
  x:array:num:3
]
$error: 0

:(before "End insert_container Special-cases")
else if (is_integer(type->name)) {  // sometimes types will contain non-type tags, like numbers for the size of an array
  type->value = 0;
}

:(scenario container_disallows_dynamic_array_element)
% Hide_errors = true;
container foo [
  x:array:num
]
+error: container 'foo' cannot determine size of element 'x'

:(before "End Load Container Element Definition")
{
  const type_tree* type = info.elements.back().type;
  if (type && type->atom && type->name == "array") {
    raise << "container '" << name << "' doesn't specify type of array elements for '" << info.elements.back().name << "'\n" << end();
    continue;
  }
  if (type && !type->atom && type->left->atom && type->left->name == "array") {
    if (!type->right) {
      raise << "container '" << name << "' doesn't specify type of array elements for '" << info.elements.back().name << "'\n" << end();
      continue;
    }
    if (!type->right->right || !is_integer(type->right->right->left->name)) {  // array has no length
      raise << "container '" << name << "' cannot determine size of element '" << info.elements.back().name << "'\n" << end();
      continue;
    }
  }
}

//: disable the size mismatch check for 'merge' instructions since containers
//: can contain arrays, and since we already do plenty of checking for them
:(before "End size_mismatch(x) Special-cases")
if (current_call().running_step_index < SIZE(get(Recipe, current_call().running_recipe).steps)
    && current_instruction().operation == MERGE) {
  return false;
}

:(scenario merge_static_array_into_container)
container foo [
  x:num
  y:array:num:3
]
def main [
  1:array:num:3 <- create-array
  10:foo <- merge 34, 1:array:num:3
]
# no errors

:(scenario code_inside_container)
% Hide_errors = true;
container card [
  rank:num <- next-ingredient
]
def foo [
  1:card <- merge 3
  2:num <- get 1:card rank:offset
]
# shouldn't die

//:: containers inside arrays
//: make sure we compute container sizes inside arrays

:(before "End compute_container_sizes Non-atom Special-cases")
else if (type->left->name == "array")
  compute_container_sizes(array_element(type), pending_metadata, location_for_error_messages);

:(before "End Unit Tests")
void test_container_sizes_from_array() {
  // a container we don't have the size for
  reagent container("x:point");
  CHECK(!contains_key(Container_metadata, container.type));
  // scanning an array of the container precomputes the size of the container
  reagent r("x:array:point");
  compute_container_sizes(r, "");
  CHECK(contains_key(Container_metadata, container.type));
  CHECK_EQ(get(Container_metadata, container.type).size, 2);
}

void test_container_sizes_from_address_to_array() {
  // a container we don't have the size for
  reagent container("x:point");
  CHECK(!contains_key(Container_metadata, container.type));
  // scanning an address to an array of the container precomputes the size of the container
  reagent r("x:address:array:point");
  compute_container_sizes(r, "");
  CHECK(contains_key(Container_metadata, container.type));
  CHECK_EQ(get(Container_metadata, container.type).size, 2);
}

void test_container_sizes_from_static_array() {
  // a container we don't have the size for
  reagent container("x:point");
  int old_size = SIZE(Container_metadata);
  // scanning an address to an array of the container precomputes the size of the container
  reagent r("x:array:point:10");
  compute_container_sizes(r, "");
  CHECK(contains_key(Container_metadata, container.type));
  CHECK_EQ(get(Container_metadata, container.type).size, 2);
  // no non-container types precomputed
  CHECK_EQ(SIZE(Container_metadata)-old_size, 1);
}

void test_container_sizes_from_address_to_static_array() {
  // a container we don't have the size for
  reagent container("x:point");
  int old_size = SIZE(Container_metadata);
  // scanning an address to an array of the container precomputes the size of the container
  reagent r("x:address:array:point:10");
  compute_container_sizes(r, "");
  CHECK(contains_key(Container_metadata, container.type));
  CHECK_EQ(get(Container_metadata, container.type).size, 2);
  // no non-container types precomputed
  CHECK_EQ(SIZE(Container_metadata)-old_size, 1);
}

void test_container_sizes_from_repeated_address_and_array_types() {
  // a container we don't have the size for
  reagent container("x:point");
  int old_size = SIZE(Container_metadata);
  // scanning repeated address and array types modifying the container precomputes the size of the container
  reagent r("x:address:array:address:array:point:10");
  compute_container_sizes(r, "");
  CHECK(contains_key(Container_metadata, container.type));
  CHECK_EQ(get(Container_metadata, container.type).size, 2);
  // no non-container types precomputed
  CHECK_EQ(SIZE(Container_metadata)-old_size, 1);
}

//:: To access elements of an array, use 'index'

:(scenario index)
def main [
  1:array:num:3 <- create-array
  2:num <- copy 14
  3:num <- copy 15
  4:num <- copy 16
  5:num <- index 1:array:num:3, 0/index  # the index must be a non-negative whole number
]
+mem: storing 14 in location 5

:(scenario index_compound_element)
def main [
  {1: (array (address number) 3)} <- create-array
  2:num <- copy 14
  3:num <- copy 15
  4:num <- copy 16
  5:address:num <- index {1: (array (address number) 3)}, 0
]
+mem: storing 14 in location 5

:(scenario index_direct_offset)
def main [
  1:array:num:3 <- create-array
  2:num <- copy 14
  3:num <- copy 15
  4:num <- copy 16
  5:num <- copy 0
  6:num <- index 1:array:num, 5:num
]
+mem: storing 14 in location 6

:(before "End Primitive Recipe Declarations")
INDEX,
:(before "End Primitive Recipe Numbers")
put(Recipe_ordinal, "index", INDEX);
:(before "End Primitive Recipe Checks")
case INDEX: {
  if (SIZE(inst.ingredients) != 2) {
    raise << maybe(get(Recipe, r).name) << "'index' expects exactly 2 ingredients in '" << inst.original_string << "'\n" << end();
    break;
  }
  reagent/*copy*/ base = inst.ingredients.at(0);
  // Update INDEX base in Check
  if (!is_mu_array(base)) {
    raise << maybe(get(Recipe, r).name) << "'index' on a non-array '" << base.original_string << "'\n" << end();
    break;
  }
  reagent/*copy*/ index = inst.ingredients.at(1);
  // Update INDEX index in Check
  if (!is_mu_number(index)) {
    raise << maybe(get(Recipe, r).name) << "second ingredient of 'index' should be a number, but got '" << index.original_string << "'\n" << end();
    break;
  }
  if (inst.products.empty()) break;
  reagent/*copy*/ product = inst.products.at(0);
  // Update INDEX product in Check
  reagent/*local*/ element;
  element.type = copy_array_element(base.type);
  if (!types_coercible(product, element)) {
    raise << maybe(get(Recipe, r).name) << "'index' on '" << base.original_string << "' can't be saved in '" << product.original_string << "'; type should be '" << names_to_string_without_quotes(element.type) << "'\n" << end();
    break;
  }
  break;
}
:(before "End Primitive Recipe Implementations")
case INDEX: {
  reagent/*copy*/ base = current_instruction().ingredients.at(0);
  // Update INDEX base in Run
  int base_address = base.value;
  trace(9998, "run") << "base address is " << base_address << end();
  if (base_address == 0) {
    raise << maybe(current_recipe_name()) << "tried to access location 0 in '" << to_original_string(current_instruction()) << "'\n" << end();
    break;
  }
  reagent/*copy*/ index = current_instruction().ingredients.at(1);
  // Update INDEX index in Run
  vector<double> index_val(read_memory(index));
  if (index_val.at(0) < 0 || index_val.at(0) >= get_or_insert(Memory, base_address)) {
    raise << maybe(current_recipe_name()) << "invalid index " << no_scientific(index_val.at(0)) << " in '" << to_original_string(current_instruction()) << "'\n" << end();
    break;
  }
  reagent/*local*/ element;
  element.type = copy_array_element(base.type);
  element.set_value(base_address + /*skip length*/1 + index_val.at(0)*size_of(element.type));
  trace(9998, "run") << "address to copy is " << element.value << end();
  trace(9998, "run") << "its type is " << to_string(element.type) << end();
  // Read element
  products.push_back(read_memory(element));
  break;
}

:(code)
type_tree* copy_array_element(const type_tree* type) {
  return new type_tree(*array_element(type));
}

type_tree* array_element(const type_tree* type) {
  assert(type->right);
  if (type->right->atom) {
    return type->right;
  }
  else if (!type->right->right) {
    return type->right->left;
  }
  // hack: support array:num:3 without requiring extra parens
  else if (type->right->right->left && type->right->right->left->atom && is_integer(type->right->right->left->name)) {
    assert(!type->right->right->right);
    return type->right->left;
  }
  return type->right;
}

int array_length(const reagent& x) {
  // x should already be canonized.
  // hack: look for length in type
  if (!x.type->atom && x.type->right && !x.type->right->atom && x.type->right->right && !x.type->right->right->atom && !x.type->right->right->right  // exactly 3 types
      && x.type->right->right->left && x.type->right->right->left->atom && is_integer(x.type->right->right->left->name)) {  // third 'type' is a number
    // get size from type
    return to_integer(x.type->right->right->left->name);
  }
  // this should never happen at transform time
  return get_or_insert(Memory, x.value);
}

:(before "End Unit Tests")
void test_array_length_compound() {
  put(Memory, 1, 3);
  put(Memory, 2, 14);
  put(Memory, 3, 15);
  put(Memory, 4, 16);
  reagent x("1:array:address:num");  // 3 types, but not a static array
  populate_value(x);
  CHECK_EQ(array_length(x), 3);
}

void test_array_length_static() {
  reagent x("1:array:num:3");
  CHECK_EQ(array_length(x), 3);
}

:(scenario index_truncates)
def main [
  1:array:num:3 <- create-array
  2:num <- copy 14
  3:num <- copy 15
  4:num <- copy 16
  5:num <- index 1:array:num:3, 1.5  # non-whole number
]
# fraction is truncated away
+mem: storing 15 in location 5

:(scenario index_out_of_bounds)
% Hide_errors = true;
def main [
  1:array:num:3 <- create-array
  2:num <- copy 14
  3:num <- copy 15
  4:num <- copy 16
  5:num <- copy 14
  6:num <- copy 15
  7:num <- copy 16
  index 1:array:num:3, 4  # less than size of array in locations, but larger than its length in elements
]
+error: main: invalid index 4 in 'index 1:array:num:3, 4'

:(scenario index_out_of_bounds_2)
% Hide_errors = true;
def main [
  1:array:point:3 <- create-array
  2:num <- copy 14
  3:num <- copy 15
  4:num <- copy 16
  5:num <- copy 14
  6:num <- copy 15
  7:num <- copy 16
  index 1:array:point, -1
]
+error: main: invalid index -1 in 'index 1:array:point, -1'

:(scenario index_product_type_mismatch)
% Hide_errors = true;
def main [
  1:array:point:3 <- create-array
  2:num <- copy 14
  3:num <- copy 15
  4:num <- copy 16
  5:num <- copy 14
  6:num <- copy 15
  7:num <- copy 16
  9:num <- index 1:array:point, 0
]
+error: main: 'index' on '1:array:point' can't be saved in '9:num'; type should be 'point'

//: we might want to call 'index' without saving the results, say in a sandbox

:(scenario index_without_product)
def main [
  1:array:num:3 <- create-array
  2:num <- copy 14
  3:num <- copy 15
  4:num <- copy 16
  index 1:array:num:3, 0
]
# just don't die

//:: To write to elements of arrays, use 'put'.

:(scenario put_index)
def main [
  1:array:num:3 <- create-array
  2:num <- copy 14
  3:num <- copy 15
  4:num <- copy 16
  1:array:num <- put-index 1:array:num, 1, 34
]
+mem: storing 34 in location 3

:(before "End Primitive Recipe Declarations")
PUT_INDEX,
:(before "End Primitive Recipe Numbers")
put(Recipe_ordinal, "put-index", PUT_INDEX);
:(before "End Primitive Recipe Checks")
case PUT_INDEX: {
  if (SIZE(inst.ingredients) != 3) {
    raise << maybe(get(Recipe, r).name) << "'put-index' expects exactly 3 ingredients in '" << inst.original_string << "'\n" << end();
    break;
  }
  reagent/*copy*/ base = inst.ingredients.at(0);
  // Update PUT_INDEX base in Check
  if (!is_mu_array(base)) {
    raise << maybe(get(Recipe, r).name) << "'put-index' on a non-array '" << base.original_string << "'\n" << end();
    break;
  }
  reagent/*copy*/ index = inst.ingredients.at(1);
  // Update PUT_INDEX index in Check
  if (!is_mu_number(index)) {
    raise << maybe(get(Recipe, r).name) << "second ingredient of 'put-index' should have type 'number', but got '" << inst.ingredients.at(1).original_string << "'\n" << end();
    break;
  }
  reagent/*copy*/ value = inst.ingredients.at(2);
  // Update PUT_INDEX value in Check
  reagent/*local*/ element;
  element.type = copy_array_element(base.type);
  if (!types_coercible(element, value)) {
    raise << maybe(get(Recipe, r).name) << "'put-index " << base.original_string << ", " << inst.ingredients.at(1).original_string << "' should store " << names_to_string_without_quotes(element.type) << " but '" << value.name << "' has type " << names_to_string_without_quotes(value.type) << '\n' << end();
    break;
  }
  if (inst.products.empty()) break;  // no more checks necessary
  if (inst.products.at(0).name != inst.ingredients.at(0).name) {
    raise << maybe(get(Recipe, r).name) << "product of 'put-index' must be first ingredient '" << inst.ingredients.at(0).original_string << "', but got '" << inst.products.at(0).original_string << "'\n" << end();
    break;
  }
  // End PUT_INDEX Product Checks
  break;
}
:(before "End Primitive Recipe Implementations")
case PUT_INDEX: {
  reagent/*copy*/ base = current_instruction().ingredients.at(0);
  // Update PUT_INDEX base in Run
  int base_address = base.value;
  if (base_address == 0) {
    raise << maybe(current_recipe_name()) << "tried to access location 0 in '" << to_original_string(current_instruction()) << "'\n" << end();
    break;
  }
  reagent/*copy*/ index = current_instruction().ingredients.at(1);
  // Update PUT_INDEX index in Run
  vector<double> index_val(read_memory(index));
  if (index_val.at(0) < 0 || index_val.at(0) >= get_or_insert(Memory, base_address)) {
    raise << maybe(current_recipe_name()) << "invalid index " << no_scientific(index_val.at(0)) << " in '" << to_original_string(current_instruction()) << "'\n" << end();
    break;
  }
  int address = base_address + /*skip length*/1 + index_val.at(0)*size_of(array_element(base.type));
  trace(9998, "run") << "address to copy to is " << address << end();
  // optimization: directly write the element rather than updating 'product'
  // and writing the entire array
  vector<double> value = read_memory(current_instruction().ingredients.at(2));
  // Write Memory in PUT_INDEX in Run
  for (int i = 0;  i < SIZE(value);  ++i) {
    trace(9999, "mem") << "storing " << no_scientific(value.at(i)) << " in location " << address+i << end();
    put(Memory, address+i, value.at(i));
  }
  goto finish_instruction;
}

:(scenario put_index_out_of_bounds)
% Hide_errors = true;
def main [
  1:array:point:3 <- create-array
  2:num <- copy 14
  3:num <- copy 15
  4:num <- copy 16
  5:num <- copy 14
  6:num <- copy 15
  7:num <- copy 16
  8:point <- merge 34, 35
  1:array:point <- put-index 1:array:point, 4, 8:point  # '4' is less than size of array in locations, but larger than its length in elements
]
+error: main: invalid index 4 in '1:array:point <- put-index 1:array:point, 4, 8:point'

:(scenario put_index_out_of_bounds_2)
% Hide_errors = true;
def main [
  1:array:point:3 <- create-array
  2:num <- copy 14
  3:num <- copy 15
  4:num <- copy 16
  5:num <- copy 14
  6:num <- copy 15
  7:num <- copy 16
  8:point <- merge 34, 35
  1:array:point <- put-index 1:array:point, -1, 8:point
]
+error: main: invalid index -1 in '1:array:point <- put-index 1:array:point, -1, 8:point'

:(scenario put_index_product_error)
% Hide_errors = true;
def main [
  local-scope
  load-ingredients
  1:array:num:3 <- create-array
  4:array:num:3 <- put-index 1:array:num:3, 0, 34
]
+error: main: product of 'put-index' must be first ingredient '1:array:num:3', but got '4:array:num:3'

//:: compute the length of an array

:(scenario array_length)
def main [
  1:array:num:3 <- create-array
  2:num <- copy 14
  3:num <- copy 15
  4:num <- copy 16
  5:num <- length 1:array:num:3
]
+mem: storing 3 in location 5

:(before "End Primitive Recipe Declarations")
LENGTH,
:(before "End Primitive Recipe Numbers")
put(Recipe_ordinal, "length", LENGTH);
:(before "End Primitive Recipe Checks")
case LENGTH: {
  if (SIZE(inst.ingredients) != 1) {
    raise << maybe(get(Recipe, r).name) << "'length' expects exactly 2 ingredients in '" << inst.original_string << "'\n" << end();
    break;
  }
  reagent/*copy*/ array = inst.ingredients.at(0);
  // Update LENGTH array in Check
  if (!is_mu_array(array)) {
    raise << "tried to calculate length of non-array '" << array.original_string << "'\n" << end();
    break;
  }
  break;
}
:(before "End Primitive Recipe Implementations")
case LENGTH: {
  reagent/*copy*/ array = current_instruction().ingredients.at(0);
  // Update LENGTH array in Run
  if (array.value == 0) {
    raise << maybe(current_recipe_name()) << "tried to access location 0 in '" << to_original_string(current_instruction()) << "'\n" << end();
    break;
  }
  products.resize(1);
  products.at(0).push_back(get_or_insert(Memory, array.value));
  break;
}

//: optimization: none of the instructions in this layer use 'ingredients' so
//: stop copying potentially huge arrays into it.
:(before "End should_copy_ingredients Special-cases")
recipe_ordinal r = current_instruction().operation;
if (r == CREATE_ARRAY || r == INDEX || r == PUT_INDEX || r == LENGTH)
  return false;