about summary refs log blame commit diff stats
path: root/html/030container.cc.html
blob: 7bb979a9d00dea1525df45e9b430ea9c8c5893e2 (plain) (tree)
1
2
3
4
5
6
7
8
9
10



                                                                                          
                                   

                                                
                                  

                                                                                         

                       
                                                                                                 
                                                                                            

                                      
                                
                             
                             
                                   
                            

                              
                                  
                                                                           

                               

        





                               

       
                         


                                                                                                  
                                                                                                  
                                                                                                                                                                                                                                         
                                                                                                                                                                    

                                                                                                                                                                                                    

                                                                                                                                                                                                                                                                                                                          
 


                                                                                                    
                                                                                                          

                                                                                                            
                                                                  
                                        

                                                                                                              
                                                                                                                            
 


                                                                 
                                                                                            
                                                           
                                                  
                                        
                                                                                                                   
 
                                                                                                   
 
                                                                                

                                                                                                        
                                                                                                                                                                                                                                                       
                                                                                                                                                                           

                                                                                                                                                                                                                  

                                                                                                                                                                                                                                                                                                                                 

                                                                                 
                                        


                                                                                                               
                                                                                                                                            


                                                                  
                                                                           
                                                           
                                        

                                                                                                            
                                     

                                                                                                               





                                                                                                                



                                                                                                           
                                        






                                                                                                                                                                                                                                                                             


                                                                
                                                                       
                                        






                                                                                                                                                                                                                                                                             


                                                                

                                                                                                           


                                                                                      
                                                                                                                                                        

































                                                                                                                                                                                                                                                                                                                                                
                                














                                                                                                                                                                                                                                                                                                                                         


                                                                                                                                                                                                                                                                                                                                                                    
                                


                                                                                                                                                                                                                                                                

                                                                                                        
                                                                                                                                                                    
                                                                                                                                                                                  
                                                           
                                                                                                                                                                                                                                                                                                                                                                     


                                                                                                                                                                                                        






                                                                                                                                                                                                     


                                                                                                     
                                                                                 
                                                                                                                                          


                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                    

                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                       







                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                 


                                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                       




                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                     
                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                            








                                                                                                                                                                                                                                                                                                            
                                                                                          







                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        


                                                                                                                                                                                                                                                                                                                                                                
















                                                                                                                                                                                                                                                                                                                                                                                          
                                  
                                                                                                                                                                                                                                                                                                                                                                     





                                                                                                                                                                                                                                                                                                                          
                                  
                                               
                                                                                                                                                                                                                                                                                                                                          













                                                                                                                                                                                                                                                                                                                                                                  

                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                            

                                
                                                          
                                        


                                                                                                                                                    
                                                                                                                            


                                                      















                                                                                                                                                                                                                                                                                                           












                                                                                                                                                                                                                                                                                                           















                                                                                                                                                                                                                                                                                                           
                                                                                                                     














































































                                                                                                                                                                                                                                                                                                                   
                                                                                     


                                                                                                       
                                              
                                        

                                                                                                               
                                                                                                                                                                                                                                                                   
 




                                                                                      

                                                                                                                                                                                                    

                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   

                                                                         
                                                                                                                                                                                                                                                                                                                                                                
                                                          



                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  


                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  

                                                                         
                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

                                                                         
                                                                                                                
                                                                                                                                                                                                                                                               
                                                                                                                                        
                                  
                                                                                              

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

                                                                         
                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                 
                                                             
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

                                                                         


                                                                                         
                                                                      
                                                                                                                                                                                                                                                                                                                  
                                                        
                                                                                                                          
                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   

                                                                         

                                                                                                                                   
                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    

                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                      



                                                                                                                                                                                                                                                                                                                                                                                                                                          


                                                                       
                                      
                                                                                                                                                                                                                                                                                     
                                                                                                                           



                                                                                                                                                                                                                                                                           
                                                                                                                              
                                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                              



                                                                                
                                                                                
                                        


                                                                                                               
                                                                                                                                                                                                                                                                          
 

                                                                  

                                                            
                                        


                                                                                                               
                                                                                                                                                                                                                                                                  
 
                                                                                      
 

                                                              
                                        


                                                                                                               
                                                                                                                                                            
 
                                                                                       
 

                                                                    
                                        


                                                                                                               
                                                                                                                                                                                                                                           
 
                                                                                                                                              



                                                                                                         
                                        

                                                                                                               
                                                                                                                                                                                           

                                             
 
                                                                                       
 
                                              
                                        

                                                                                                               
              
                                                                                                                                                                                                                                                              
 

                                                                  
 
                                                                                      
                                   
                                                                                 
                                                                                                                                                                                                    
                                                                                

                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   

                                                                         
                                                                                                                                                                                                                                                                                                 
                                                          



                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  


                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  

                                                                         
                                                                                                                                                                                                                                                                                                   
                                                            
                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

                                                                         
                                                                                                                
                                                                                                                                                                                                                                                                                                
                                                                                                                                        

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          


                                                                           
                                                                   

                                                                                              
                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                


                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          

                                                                         
                                                        


                                                                                         
                                                                      
                                                                                                                                                                                                                                                                                                                  
                                                        
                                                                                                                          
                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   

                                                                         

                                                                                                                                   
                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                      


                                                                                                                                                                                                                                                                                                                                 
                                                            


                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                  
                                                                                         
                                
 

                                                            
                                        


                                                                                                                                                                                  
                                                                                                                                                                                                                                                            


                                                                                                                       



                                                                                   
                                           

                                   
 
                                                                     

                                                                           
 
                                                                          
                                           
                                   
                                   
 
                                           

                                   
 
                                                                     
                                                            
                                                                             

                                                                                           
                                                                          
                                                  
                                                                     
                                                            

                                                                             
 


                                                                                                               
                                           
                                   

                                                         
                                           
                                   
 
                                        

                                                                                                              

                                                                                                                                                                                       



                                                                 
                                                                         
                                                                                                                                                                                                                               
                                                                                                                                                                       

                                







                                                                                                                 
                                      
                                                                                                                                                                                                                                                                                                         
                                                                                                    
                                                                                            

                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                               

                                                                                                                                                                                                                                 
                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                








                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 

                                                                                 
                                                                                                                                                                                

                                                                                                   
                                                                                                                                                                                                                               








                                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                               


                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                  

                                

                                                                                                                                                                                                                                                                                 















                                                                                                                                                                                                                                                                                                                                                                             
                                  

                                
                                                                                                                                                                                                            
                                                                                                 

                                                                                                                                                                                                            

                                

                                                                                   
                                           
                                         


                                                                                                                                                                                               


                                                                                    

                                             

                                   
                                        
                                                                                                              
                                                                                                                                                                                              
















                                                                                                                                                                                                                                                                                                                                                                                 
                                                                                                          
                                                                                      
                                                                                
                                                                                                                                
 



                                                                                                                                                                         
                                                                                                                     





                                                                                                                                                            
                                                                                                                     



                                                                                                                                                

                                                                                                                  
 

                                                                         
                                        
                                                      
                                                                                                                 
 
                                                                                                 

                                                                               
                                        
                                                                                                                    
 
                                           
                                   
 
                                       
 
                                                                                  
                                                                                                                                                                                         

                                      
                                                                                                                                                                                                              
                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                  
                                                                

                                

                                                                                                                                                                                                                                                                                                                                                  
                                                           




                                                                                                                                                                                                                       

                                                                                                                                                                                                                                                                  
                                                                                                                                                               
                                                                                                                                                                                                                                         
                                                                                                                                                                                                                   

                                                                                                                                                                                                                                                                                                                  
                                  


                                                                  
                                                  
                                           
                                   
                                   
 
                                                                 
 
                                                                                 
                                           
                                   
                                               
                                   
 
                                                                     

                                                                           
 
                                                                             
                                           



                                                                                                                                                                            
                                                                      


                                                             


                                                                                                                                                                                                                                                                                                                                                                                 
                                                                     
                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  


                                  

                                                                                                                                                                                                                                                                                                                                                                             




                                                                                                                                                                                                                


                                                                                                                                                                                                                                                                                                                                                    
                                  
                                


       
                                     
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Mu - 030container.cc</title>
<meta name="Generator" content="Vim/7.4">
<meta name="plugin-version" content="vim7.4_v2">
<meta name="syntax" content="cpp">
<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
<meta name="colorscheme" content="minimal">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; }
* { font-size: 12pt; font-size: 1em; }
.Constant { color: #00a0a0; }
.traceAbsent { color: #c00000; }
.cSpecial { color: #008000; }
.muRecipe { color: #ff8700; }
.SalientComment { color: #00ffff; }
.Comment { color: #9090ff; }
.Delimiter { color: #800080; }
.Special { color: #c00000; }
.traceContains { color: #008000; }
.Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; }
.muData { color: #ffff00; }
.Identifier { color: #fcb165; }
-->
</style>

<script type='text/javascript'>
<!--

-->
</script>
</head>
<body>
<pre id='vimCodeElement'>
<span class="Comment">//: Containers contain a fixed number of elements of different types.</span>

<span class="Delimiter">:(before &quot;End Mu Types Initialization&quot;)</span>
<span class="Comment">//: We'll use this container as a running example in scenarios below.</span>
type_ordinal point = put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;point&quot;</span><span class="Delimiter">,</span> Next_type_ordinal++<span class="Delimiter">);</span>
get_or_insert<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point<span class="Delimiter">);</span>  <span class="Comment">// initialize</span>
get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point<span class="Delimiter">).</span>kind = CONTAINER<span class="Delimiter">;</span>
get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point<span class="Delimiter">).</span>name = <span class="Constant">&quot;point&quot;</span><span class="Delimiter">;</span>
get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point<span class="Delimiter">).</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;x:number&quot;</span><span class="Delimiter">));</span>
get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point<span class="Delimiter">).</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;y:number&quot;</span><span class="Delimiter">));</span>

<span class="Comment">//: Containers can be copied around with a single instruction just like</span>
<span class="Comment">//: numbers, no matter how large they are.</span>

<span class="Comment">//: Tests in this layer often explicitly set up memory before reading it as a</span>
<span class="Comment">//: container. Don't do this in general. I'm tagging exceptions with /unsafe to</span>
<span class="Comment">//: skip later checks.</span>
<span class="Delimiter">:(scenario copy_multiple_locations)</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">1</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">2</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">3</span>:point<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:point/unsafe
]
<span class="traceContains">+mem: storing 34 in location 3</span>
<span class="traceContains">+mem: storing 35 in location 4</span>

<span class="Comment">//: trying to copy to a differently-typed destination will fail</span>
<span class="Delimiter">:(scenario copy_checks_size)</span>
<span class="Special">% Hide_errors = true;</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">2</span>:point<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:num
]
<span class="traceContains">+error: main: can't copy '1:num' to '2:point'; types don't match</span>

<span class="Delimiter">:(before &quot;End Mu Types Initialization&quot;)</span>
<span class="Comment">// A more complex example container, containing another container as one of</span>
<span class="Comment">// its elements.</span>
type_ordinal point_number = put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;point-number&quot;</span><span class="Delimiter">,</span> Next_type_ordinal++<span class="Delimiter">);</span>
get_or_insert<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point_number<span class="Delimiter">);</span>  <span class="Comment">// initialize</span>
get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point_number<span class="Delimiter">).</span>kind = CONTAINER<span class="Delimiter">;</span>
get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point_number<span class="Delimiter">).</span>name = <span class="Constant">&quot;point-number&quot;</span><span class="Delimiter">;</span>
get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point_number<span class="Delimiter">).</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;xy:point&quot;</span><span class="Delimiter">));</span>
get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> point_number<span class="Delimiter">).</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;z:number&quot;</span><span class="Delimiter">));</span>

<span class="Delimiter">:(scenario copy_handles_nested_container_elements)</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">12</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">13</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">14</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">36</span>
  <span class="Constant">15</span>:point-number<span class="Special"> &lt;- </span>copy <span class="Constant">12</span>:point-number/unsafe
]
<span class="traceContains">+mem: storing 36 in location 17</span>

<span class="Comment">//: products of recipes can include containers</span>
<span class="Delimiter">:(scenario return_container)</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">3</span>:point<span class="Special"> &lt;- </span>f <span class="Constant">2</span>
]
<span class="muRecipe">def</span> f [
  <span class="Constant">12</span>:num<span class="Special"> &lt;- </span>next-ingredient
  <span class="Constant">13</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Identifier">return</span> <span class="Constant">12</span>:point/<span class="Special">raw</span>
]
<span class="traceContains">+run: result 0 is [2, 35]</span>
<span class="traceContains">+mem: storing 2 in location 3</span>
<span class="traceContains">+mem: storing 35 in location 4</span>

<span class="Comment">//: Containers can be checked for equality with a single instruction just like</span>
<span class="Comment">//: numbers, no matter how large they are.</span>

<span class="Delimiter">:(scenario compare_multiple_locations)</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">1</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>  <span class="Comment"># first</span>
  <span class="Constant">2</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">3</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">36</span>
  <span class="Constant">4</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>  <span class="Comment"># second</span>
  <span class="Constant">5</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">6</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">36</span>
  <span class="Constant">7</span>:<span class="Normal">bool</span><span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">4</span>:point-number/unsafe
]
<span class="traceContains">+mem: storing 1 in location 7</span>

<span class="Delimiter">:(scenario compare_multiple_locations_2)</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">1</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>  <span class="Comment"># first</span>
  <span class="Constant">2</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">3</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">36</span>
  <span class="Constant">4</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>  <span class="Comment"># second</span>
  <span class="Constant">5</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">6</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">37</span>  <span class="Comment"># different</span>
  <span class="Constant">7</span>:<span class="Normal">bool</span><span class="Special"> &lt;- </span>equal <span class="Constant">1</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">4</span>:point-number/unsafe
]
<span class="traceContains">+mem: storing 0 in location 7</span>

<span class="Comment">//: Can't put this in type_info because later layers will add support for more</span>
<span class="Comment">//: complex type trees where metadata depends on *combinations* of types.</span>
<span class="Delimiter">:(before &quot;struct reagent&quot;)</span>
<span class="Normal">struct</span> container_metadata <span class="Delimiter">{</span>
  <span class="Normal">int</span> size<span class="Delimiter">;</span>
  vector&lt;<span class="Normal">int</span>&gt; offset<span class="Delimiter">;</span>  <span class="Comment">// not used by exclusive containers</span>
  <span class="Comment">// End container_metadata Fields</span>
  container_metadata<span class="Delimiter">()</span> :size<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Comment">// End container_metadata Constructor</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">};</span>
<span class="Delimiter">:(before &quot;End reagent Fields&quot;)</span>
container_metadata metadata<span class="Delimiter">;</span>  <span class="Comment">// can't be a pointer into Container_metadata because we keep changing the base storage when we save/restore snapshots</span>
<span class="Delimiter">:(before &quot;End reagent Copy Operator&quot;)</span>
metadata = other<span class="Delimiter">.</span>metadata<span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End reagent Copy Constructor&quot;)</span>
metadata = other<span class="Delimiter">.</span>metadata<span class="Delimiter">;</span>

<span class="Delimiter">:(before &quot;End Globals&quot;)</span>
<span class="Comment">// todo: switch to map after figuring out how to consistently compare type trees</span>
vector&lt;pair&lt;type_tree*<span class="Delimiter">,</span> container_metadata&gt; &gt; Container_metadata<span class="Delimiter">,</span> Container_metadata_snapshot<span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End save_snapshots&quot;)</span>
Container_metadata_snapshot = Container_metadata<span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End restore_snapshots&quot;)</span>
restore_container_metadata<span class="Delimiter">();</span>
<span class="Delimiter">:(before &quot;End One-time Setup&quot;)</span>
atexit<span class="Delimiter">(</span>clear_container_metadata<span class="Delimiter">);</span>
<span class="Delimiter">:(code)</span>
<span class="Comment">// invariant: Container_metadata always contains a superset of Container_metadata_snapshot</span>
<span class="Normal">void</span> restore_container_metadata<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    assert<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>first<span class="Delimiter">);</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>i &lt; SIZE<span class="Delimiter">(</span>Container_metadata_snapshot<span class="Delimiter">))</span> <span class="Delimiter">{</span>
      assert<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>first == Container_metadata_snapshot<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>first<span class="Delimiter">);</span>
      <span class="Identifier">continue</span><span class="Delimiter">;</span>
    <span class="Delimiter">}</span>
    <span class="Normal">delete</span> Container_metadata<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>first<span class="Delimiter">;</span>
    Container_metadata<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>first = <span class="Constant">NULL</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  Container_metadata<span class="Delimiter">.</span>resize<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>Container_metadata_snapshot<span class="Delimiter">));</span>
<span class="Delimiter">}</span>
<span class="Normal">void</span> clear_container_metadata<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  Container_metadata_snapshot<span class="Delimiter">.</span>clear<span class="Delimiter">();</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Normal">delete</span> Container_metadata<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>first<span class="Delimiter">;</span>
    Container_metadata<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>first = <span class="Constant">NULL</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  Container_metadata<span class="Delimiter">.</span>clear<span class="Delimiter">();</span>
<span class="Delimiter">}</span>

<span class="Comment">//: do no work in size_of, simply lookup Container_metadata</span>

<span class="Delimiter">:(before &quot;End size_of(reagent r) Cases&quot;)</span>
<span class="Normal">if</span> <span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>size<span class="Delimiter">)</span> <span class="Identifier">return</span> r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>size<span class="Delimiter">;</span>

<span class="Delimiter">:(before &quot;End size_of(type) Cases&quot;)</span>
<span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value == -<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">1</span><span class="Delimiter">;</span>  <span class="Comment">// error value, but we'll raise it elsewhere</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">1</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Normal">const</span> type_tree* root = root_type<span class="Delimiter">(</span>type<span class="Delimiter">);</span>
<span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> root<span class="Delimiter">-&gt;</span>value<span class="Delimiter">))</span> <span class="Delimiter">{</span>
  raise &lt;&lt; <span class="Constant">&quot;no such type &quot;</span> &lt;&lt; root<span class="Delimiter">-&gt;</span>value &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span>
  <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
type_info t = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> root<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span>
<span class="Normal">if</span> <span class="Delimiter">(</span>t<span class="Delimiter">.</span>kind == CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Comment">// Compute size_of Container</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> type<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">1</span><span class="Delimiter">;</span>  <span class="Comment">// error raised elsewhere</span>
  <span class="Identifier">return</span> get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> type<span class="Delimiter">).</span>size<span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(code)</span>
<span class="Normal">const</span> type_tree* root_type<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* t<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">const</span> type_tree* result = t<span class="Delimiter">-&gt;</span>atom ? t : t<span class="Delimiter">-&gt;</span>left<span class="Delimiter">;</span>
  assert<span class="Delimiter">(</span>result<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span>
  <span class="Identifier">return</span> result<span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Comment">//: precompute Container_metadata before we need size_of</span>
<span class="Comment">//: also store a copy in each reagent in each instruction in each recipe</span>

<span class="Delimiter">:(after &quot;End Type Modifying Transforms&quot;)</span>
Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>compute_container_sizes<span class="Delimiter">);</span>
<span class="Delimiter">:(code)</span>
<span class="Normal">void</span> compute_container_sizes<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  recipe&amp; caller = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span>
  trace<span class="Delimiter">(</span><span class="Constant">9992</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- compute container sizes for &quot;</span> &lt;&lt; caller<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    instruction&amp; inst = caller<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span>
    trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;- compute container sizes for &quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span>
      compute_container_sizes<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span>
    <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span>
      compute_container_sizes<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">}</span>

<span class="Normal">void</span> compute_container_sizes<span class="Delimiter">(</span>reagent&amp; r<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  expand_type_abbreviations<span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>r<span class="Delimiter">)</span> || is_dummy<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
  reagent rcopy = r<span class="Delimiter">;</span>
  <span class="Comment">// Compute Container Size(reagent rcopy)</span>
  set&lt;type_tree&gt; pending_metadata<span class="Delimiter">;</span>  <span class="Comment">// might actually be faster to just convert to string rather than compare type_tree directly; so far the difference is negligible</span>
  compute_container_sizes<span class="Delimiter">(</span>rcopy<span class="Delimiter">.</span>type<span class="Delimiter">,</span> pending_metadata<span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> rcopy<span class="Delimiter">.</span>type<span class="Delimiter">))</span>
    r<span class="Delimiter">.</span>metadata = get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> rcopy<span class="Delimiter">.</span>type<span class="Delimiter">);</span>
<span class="Delimiter">}</span>

<span class="Normal">void</span> compute_container_sizes<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">,</span> set&lt;type_tree&gt;&amp; pending_metadata<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
  trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;compute container sizes for &quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>type<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> type<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>pending_metadata<span class="Delimiter">,</span> *type<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
  pending_metadata<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>*type<span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    assert<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">-&gt;</span>name == <span class="Constant">&quot;address&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
      compute_container_sizes<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">,</span> pending_metadata<span class="Delimiter">);</span>
    <span class="Delimiter">}</span>
    <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">-&gt;</span>name == <span class="Constant">&quot;array&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
      <span class="Normal">const</span> type_tree* element_type = type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">;</span>
      <span class="Comment">// hack: support both array:num:3 and array:address:num</span>
      <span class="Normal">if</span> <span class="Delimiter">(</span>!element_type<span class="Delimiter">-&gt;</span>atom &amp;&amp; element_type<span class="Delimiter">-&gt;</span>right &amp;&amp; element_type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>atom &amp;&amp; is_integer<span class="Delimiter">(</span>element_type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">-&gt;</span>name<span class="Delimiter">))</span>
        element_type = element_type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">;</span>
      compute_container_sizes<span class="Delimiter">(</span>element_type<span class="Delimiter">,</span> pending_metadata<span class="Delimiter">);</span>
    <span class="Delimiter">}</span>
    <span class="Comment">// End compute_container_sizes Non-atom Cases</span>
    <span class="Identifier">return</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  assert<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span>  <span class="Comment">// error raised elsewhere</span>
  type_info&amp; info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    compute_container_sizes<span class="Delimiter">(</span>info<span class="Delimiter">,</span> type<span class="Delimiter">,</span> pending_metadata<span class="Delimiter">);</span>
  <span class="Delimiter">}</span>
  <span class="Comment">// End compute_container_sizes Atom Cases</span>
<span class="Delimiter">}</span>

<span class="Normal">void</span> compute_container_sizes<span class="Delimiter">(</span><span class="Normal">const</span> type_info&amp; container_info<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* full_type<span class="Delimiter">,</span> set&lt;type_tree&gt;&amp; pending_metadata<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  assert<span class="Delimiter">(</span>container_info<span class="Delimiter">.</span>kind == CONTAINER<span class="Delimiter">);</span>
  <span class="Comment">// size of a container is the sum of the sizes of its element</span>
  <span class="Comment">// (So it can only contain arrays if they're static and include their</span>
  <span class="Comment">// length in the type.)</span>
  container_metadata metadata<span class="Delimiter">;</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>container_info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> element = container_info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span>
    <span class="Comment">// Compute Container Size(element, full_type)</span>
    compute_container_sizes<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">,</span> pending_metadata<span class="Delimiter">);</span>
    metadata<span class="Delimiter">.</span>offset<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>metadata<span class="Delimiter">.</span>size<span class="Delimiter">);</span>  <span class="Comment">// save previous size as offset</span>
    metadata<span class="Delimiter">.</span>size += size_of<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">);</span>
  <span class="Delimiter">}</span>
  Container_metadata<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair&lt;type_tree*<span class="Delimiter">,</span> container_metadata&gt;<span class="Delimiter">(</span><span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*full_type<span class="Delimiter">),</span> metadata<span class="Delimiter">));</span>
<span class="Delimiter">}</span>

container_metadata&amp; get<span class="Delimiter">(</span>vector&lt;pair&lt;type_tree*<span class="Delimiter">,</span> container_metadata&gt; &gt;&amp; all<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* key<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>all<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>matches<span class="Delimiter">(</span>all<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>first<span class="Delimiter">,</span> key<span class="Delimiter">))</span>
      <span class="Identifier">return</span> all<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>second<span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  tb_shutdown<span class="Delimiter">();</span>
  raise &lt;&lt; <span class="Constant">&quot;unknown size for type '&quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>key<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
  assert<span class="Delimiter">(</span><span class="Constant">false</span><span class="Delimiter">);</span>
<span class="Delimiter">}</span>

<span class="Normal">bool</span> contains_key<span class="Delimiter">(</span><span class="Normal">const</span> vector&lt;pair&lt;type_tree*<span class="Delimiter">,</span> container_metadata&gt; &gt;&amp; all<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* key<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>all<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>matches<span class="Delimiter">(</span>all<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>first<span class="Delimiter">,</span> key<span class="Delimiter">))</span>
      <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Normal">bool</span> matches<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* a<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* b<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>a == b<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!a || !b<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>a<span class="Delimiter">-&gt;</span>atom != b<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>a<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Identifier">return</span> a<span class="Delimiter">-&gt;</span>value == b<span class="Delimiter">-&gt;</span>value<span class="Delimiter">;</span>
  <span class="Identifier">return</span> matches<span class="Delimiter">(</span>a<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> b<span class="Delimiter">-&gt;</span>left<span class="Delimiter">)</span> &amp;&amp; matches<span class="Delimiter">(</span>a<span class="Delimiter">-&gt;</span>right<span class="Delimiter">,</span> b<span class="Delimiter">-&gt;</span>right<span class="Delimiter">);</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(scenario stash_container)</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">1</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>  <span class="Comment"># first</span>
  <span class="Constant">2</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">3</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">36</span>
  stash [foo:]<span class="Delimiter">,</span> <span class="Constant">1</span>:point-number/<span class="Special">raw</span>
]
<span class="traceContains">+app: foo: 34 35 36</span>

<span class="Comment">//: for the following unit tests we'll do the work of the transform by hand</span>

<span class="Delimiter">:(before &quot;End Unit Tests&quot;)</span>
<span class="Normal">void</span> test_container_sizes<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  <span class="Comment">// a container we don't have the size for</span>
  reagent r<span class="Delimiter">(</span><span class="Constant">&quot;x:point&quot;</span><span class="Delimiter">);</span>
  CHECK<span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
  <span class="Comment">// scan</span>
  compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">);</span>
  <span class="Comment">// the reagent we scanned knows its size</span>
  CHECK_EQ<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>size<span class="Delimiter">,</span> <span class="Constant">2</span><span class="Delimiter">);</span>
  <span class="Comment">// the global table also knows its size</span>
  CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
  CHECK_EQ<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">).</span>size<span class="Delimiter">,</span> <span class="Constant">2</span><span class="Delimiter">);</span>
<span class="Delimiter">}</span>

<span class="Normal">void</span> test_container_sizes_through_aliases<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  <span class="Comment">// a new alias for a container</span>
  put<span class="Delimiter">(</span>Type_abbreviations<span class="Delimiter">,</span> <span class="Constant">&quot;pt&quot;</span><span class="Delimiter">,</span> new_type_tree<span class="Delimiter">(</span><span class="Constant">&quot;point&quot;</span><span class="Delimiter">));</span>
  reagent r<span class="Delimiter">(</span><span class="Constant">&quot;x:pt&quot;</span><span class="Delimiter">);</span>
  <span class="Comment">// scan</span>
  compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">);</span>
  <span class="Comment">// the reagent we scanned knows its size</span>
  CHECK_EQ<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>size<span class="Delimiter">,</span> <span class="Constant">2</span><span class="Delimiter">);</span>
  <span class="Comment">// the global table also knows its size</span>
  CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
  CHECK_EQ<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">).</span>size<span class="Delimiter">,</span> <span class="Constant">2</span><span class="Delimiter">);</span>
<span class="Delimiter">}</span>

<span class="Normal">void</span> test_container_sizes_nested<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  <span class="Comment">// a container we don't have the size for</span>
  reagent r<span class="Delimiter">(</span><span class="Constant">&quot;x:point-number&quot;</span><span class="Delimiter">);</span>
  CHECK<span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
  <span class="Comment">// scan</span>
  compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">);</span>
  <span class="Comment">// the reagent we scanned knows its size</span>
  CHECK_EQ<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>size<span class="Delimiter">,</span> <span class="Constant">3</span><span class="Delimiter">);</span>
  <span class="Comment">// the global table also knows its size</span>
  CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
  CHECK_EQ<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> r<span class="Delimiter">.</span>type<span class="Delimiter">).</span>size<span class="Delimiter">,</span> <span class="Constant">3</span><span class="Delimiter">);</span>
<span class="Delimiter">}</span>

<span class="Normal">void</span> test_container_sizes_recursive<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  <span class="Comment">// define a container containing an address to itself</span>
  run<span class="Delimiter">(</span><span class="Constant">&quot;container foo [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span>
      <span class="Constant">&quot;  x:num</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span>
      <span class="Constant">&quot;  y:address:foo</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span>
      <span class="Constant">&quot;]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">);</span>
  reagent r<span class="Delimiter">(</span><span class="Constant">&quot;x:foo&quot;</span><span class="Delimiter">);</span>
  compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">);</span>
  CHECK_EQ<span class="Delimiter">(</span>r<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>size<span class="Delimiter">,</span> <span class="Constant">2</span><span class="Delimiter">);</span>
<span class="Delimiter">}</span>

<span class="Normal">void</span> test_container_sizes_from_address<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  <span class="Comment">// a container we don't have the size for</span>
  reagent container<span class="Delimiter">(</span><span class="Constant">&quot;x:point&quot;</span><span class="Delimiter">);</span>
  CHECK<span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
  <span class="Comment">// scanning an address to the container precomputes the size of the container</span>
  reagent r<span class="Delimiter">(</span><span class="Constant">&quot;x:address:point&quot;</span><span class="Delimiter">);</span>
  compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">);</span>
  CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
  CHECK_EQ<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">).</span>size<span class="Delimiter">,</span> <span class="Constant">2</span><span class="Delimiter">);</span>
<span class="Delimiter">}</span>

<span class="Normal">void</span> test_container_sizes_from_array<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  <span class="Comment">// a container we don't have the size for</span>
  reagent container<span class="Delimiter">(</span><span class="Constant">&quot;x:point&quot;</span><span class="Delimiter">);</span>
  CHECK<span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
  <span class="Comment">// scanning an array of the container precomputes the size of the container</span>
  reagent r<span class="Delimiter">(</span><span class="Constant">&quot;x:array:point&quot;</span><span class="Delimiter">);</span>
  compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">);</span>
  CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
  CHECK_EQ<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">).</span>size<span class="Delimiter">,</span> <span class="Constant">2</span><span class="Delimiter">);</span>
<span class="Delimiter">}</span>

<span class="Normal">void</span> test_container_sizes_from_address_to_array<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  <span class="Comment">// a container we don't have the size for</span>
  reagent container<span class="Delimiter">(</span><span class="Constant">&quot;x:point&quot;</span><span class="Delimiter">);</span>
  CHECK<span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
  <span class="Comment">// scanning an address to an array of the container precomputes the size of the container</span>
  reagent r<span class="Delimiter">(</span><span class="Constant">&quot;x:address:array:point&quot;</span><span class="Delimiter">);</span>
  compute_container_sizes<span class="Delimiter">(</span>r<span class="Delimiter">);</span>
  CHECK<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">));</span>
  CHECK_EQ<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">).</span>size<span class="Delimiter">,</span> <span class="Constant">2</span><span class="Delimiter">);</span>
<span class="Delimiter">}</span>

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

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

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

<span class="SalientComment">//:: To access elements of a container, use 'get'</span>
<span class="Comment">//: 'get' takes a 'base' container and an 'offset' into it and returns the</span>
<span class="Comment">//: appropriate element of the container value.</span>

<span class="Delimiter">:(scenario get)</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">12</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">13</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">15</span>:num<span class="Special"> &lt;- </span>get <span class="Constant">12</span>:point/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">1:offset</span>  <span class="Comment"># unsafe</span>
]
<span class="traceContains">+mem: storing 35 in location 15</span>

<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
GET<span class="Delimiter">,</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;get&quot;</span><span class="Delimiter">,</span> GET<span class="Delimiter">);</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span>
<span class="Normal">case</span> GET: <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'get' expects exactly 2 ingredients in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> base = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>  <span class="Comment">// new copy for every invocation</span>
  <span class="Comment">// Update GET base in Check</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!base<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;first ingredient of 'get' should be a container, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">const</span> type_tree* base_type = base<span class="Delimiter">.</span>type<span class="Delimiter">;</span>
  <span class="Comment">// Update GET base_type in Check</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!base_type<span class="Delimiter">-&gt;</span>atom || base_type<span class="Delimiter">-&gt;</span>value == <span class="Constant">0</span> || !contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">)</span> || get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>kind != CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;first ingredient of 'get' should be a container, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">const</span> reagent&amp; offset = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</span>offset<span class="Delimiter">)</span> || !is_mu_scalar<span class="Delimiter">(</span>offset<span class="Delimiter">))</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;second ingredient of 'get' should have type 'offset', but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">int</span> offset_value = <span class="Constant">0</span><span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>offset<span class="Delimiter">.</span>name<span class="Delimiter">))</span>  <span class="Comment">// later layers permit non-integer offsets</span>
    offset_value = to_integer<span class="Delimiter">(</span>offset<span class="Delimiter">.</span>name<span class="Delimiter">);</span>
  <span class="Normal">else</span>
    offset_value = offset<span class="Delimiter">.</span>value<span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>offset_value &lt; <span class="Constant">0</span> || offset_value &gt;= SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>elements<span class="Delimiter">))</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;invalid offset '&quot;</span> &lt;&lt; offset_value &lt;&lt; <span class="Constant">&quot;' for '&quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span>
  reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> product = inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
  <span class="Comment">// Update GET product in Check</span>
  <span class="Normal">const</span> reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> element = element_type<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">,</span> offset_value<span class="Delimiter">);</span>  <span class="Comment">// not just base_type because later layers will introduce compound types</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!types_coercible<span class="Delimiter">(</span>product<span class="Delimiter">,</span> element<span class="Delimiter">))</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'get &quot;</span> &lt;&lt; base<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; offset<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;' should write to &quot;</span> &lt;&lt; names_to_string_without_quotes<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; but '&quot;</span> &lt;&lt; product<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot;' has type &quot;</span> &lt;&lt; names_to_string_without_quotes<span class="Delimiter">(</span>product<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
<span class="Normal">case</span> GET: <span class="Delimiter">{</span>
  reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> base = current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
  <span class="Comment">// Update GET base in Run</span>
  <span class="Normal">int</span> base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>base_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;tried to access location 0 in '&quot;</span> &lt;&lt; to_original_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">const</span> type_tree* base_type = base<span class="Delimiter">.</span>type<span class="Delimiter">;</span>
  <span class="Comment">// Update GET base_type in Run</span>
  <span class="Normal">int</span> offset = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>offset &lt; <span class="Constant">0</span> || offset &gt;= SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>elements<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span>  <span class="Comment">// copied from Check above</span>
  assert<span class="Delimiter">(</span>base<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>size<span class="Delimiter">);</span>
  <span class="Normal">int</span> src = base_address + base<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>offset<span class="Delimiter">.</span>at<span class="Delimiter">(</span>offset<span class="Delimiter">);</span>
  trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;address to copy is &quot;</span> &lt;&lt; src &lt;&lt; end<span class="Delimiter">();</span>
  reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> element = element_type<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">,</span> offset<span class="Delimiter">);</span>  <span class="Comment">// not just base_type because later layers will introduce compound types</span>
  element<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>src<span class="Delimiter">);</span>
  trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;its type is &quot;</span> &lt;&lt; names_to_string<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span>
  <span class="Comment">// Read element</span>
  products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>element<span class="Delimiter">));</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(code)</span>
<span class="Normal">const</span> reagent element_type<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">,</span> <span class="Normal">int</span> offset_value<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  assert<span class="Delimiter">(</span>offset_value &gt;= <span class="Constant">0</span><span class="Delimiter">);</span>
  <span class="Normal">const</span> type_tree* root = root_type<span class="Delimiter">(</span>type<span class="Delimiter">);</span>
  assert<span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> root<span class="Delimiter">-&gt;</span>value<span class="Delimiter">));</span>
  assert<span class="Delimiter">(</span>!get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> root<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>name<span class="Delimiter">.</span>empty<span class="Delimiter">());</span>
  <span class="Normal">const</span> type_info&amp; info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> root<span class="Delimiter">-&gt;</span>value<span class="Delimiter">);</span>
  assert<span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == CONTAINER<span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>offset_value &gt;= SIZE<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">))</span> <span class="Identifier">return</span> reagent<span class="Delimiter">();</span>  <span class="Comment">// error handled elsewhere</span>
  reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> element = info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>offset_value<span class="Delimiter">);</span>
  <span class="Comment">// End element_type Special-cases</span>
  <span class="Identifier">return</span> element<span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(scenario get_handles_nested_container_elements)</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">12</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">13</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">14</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">36</span>
  <span class="Constant">15</span>:num<span class="Special"> &lt;- </span>get <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">1:offset</span>  <span class="Comment"># unsafe</span>
]
<span class="traceContains">+mem: storing 36 in location 15</span>

<span class="Delimiter">:(scenario get_out_of_bounds)</span>
<span class="Special">% Hide_errors = true;</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">12</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">13</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">14</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">36</span>
  get <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">2:offset</span>  <span class="Comment"># point-number occupies 3 locations but has only 2 fields; out of bounds</span>
]
<span class="traceContains">+error: main: invalid offset '2' for 'point-number'</span>

<span class="Delimiter">:(scenario get_out_of_bounds_2)</span>
<span class="Special">% Hide_errors = true;</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">12</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">13</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">14</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">36</span>
  get <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">-1:offset</span>
]
<span class="traceContains">+error: main: invalid offset '-1' for 'point-number'</span>

<span class="Delimiter">:(scenario get_product_type_mismatch)</span>
<span class="Special">% Hide_errors = true;</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">12</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">13</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">14</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">36</span>
  <span class="Constant">15</span>:address:num<span class="Special"> &lt;- </span>get <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">1:offset</span>
]
<span class="traceContains">+error: main: 'get 12:point-number/raw, 1:offset' should write to number but '15' has type (address number)</span>

<span class="Comment">//: we might want to call 'get' without saving the results, say in a sandbox</span>

<span class="Delimiter">:(scenario get_without_product)</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">12</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">13</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  get <span class="Constant">12</span>:point/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">1:offset</span>  <span class="Comment"># unsafe</span>
]
<span class="Comment"># just don't die</span>

<span class="SalientComment">//:: To write to elements of containers, use 'put'.</span>

<span class="Delimiter">:(scenario put)</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">12</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">13</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  $clear-trace
  <span class="Constant">12</span>:point<span class="Special"> &lt;- </span>put <span class="Constant">12</span>:point<span class="Delimiter">,</span> <span class="Constant">1:offset</span><span class="Delimiter">,</span> <span class="Constant">36</span>
]
<span class="traceContains">+mem: storing 36 in location 13</span>
<span class="traceAbsent">-mem: storing 34 in location 12</span>

<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
PUT<span class="Delimiter">,</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;put&quot;</span><span class="Delimiter">,</span> PUT<span class="Delimiter">);</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span>
<span class="Normal">case</span> PUT: <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">3</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'put' expects exactly 3 ingredients in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> base = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
  <span class="Comment">// Update PUT base in Check</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!base<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;first ingredient of 'put' should be a container, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">const</span> type_tree* base_type = base<span class="Delimiter">.</span>type<span class="Delimiter">;</span>
  <span class="Comment">// Update PUT base_type in Check</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!base_type<span class="Delimiter">-&gt;</span>atom || base_type<span class="Delimiter">-&gt;</span>value == <span class="Constant">0</span> || !contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">)</span> || get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>kind != CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;first ingredient of 'put' should be a container, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> offset = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span>
  <span class="Comment">// Update PUT offset in Check</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</span>offset<span class="Delimiter">)</span> || !is_mu_scalar<span class="Delimiter">(</span>offset<span class="Delimiter">))</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;second ingredient of 'put' should have type 'offset', but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">int</span> offset_value = <span class="Constant">0</span><span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>offset<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span>  <span class="Comment">// later layers permit non-integer offsets</span>
    offset_value = to_integer<span class="Delimiter">(</span>offset<span class="Delimiter">.</span>name<span class="Delimiter">);</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>offset_value &lt; <span class="Constant">0</span> || offset_value &gt;= SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>elements<span class="Delimiter">))</span> <span class="Delimiter">{</span>
      raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;invalid offset '&quot;</span> &lt;&lt; offset_value &lt;&lt; <span class="Constant">&quot;' for '&quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
      <span class="Identifier">break</span><span class="Delimiter">;</span>
    <span class="Delimiter">}</span>
  <span class="Delimiter">}</span>
  <span class="Normal">else</span> <span class="Delimiter">{</span>
    offset_value = offset<span class="Delimiter">.</span>value<span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">const</span> reagent&amp; value = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">);</span>
  <span class="Normal">const</span> reagent&amp; element = element_type<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">,</span> offset_value<span class="Delimiter">);</span>  <span class="Comment">// not just base_type because later layers will introduce compound types</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!types_coercible<span class="Delimiter">(</span>element<span class="Delimiter">,</span> value<span class="Delimiter">))</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'put &quot;</span> &lt;&lt; base<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; offset<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;' should write to &quot;</span> &lt;&lt; names_to_string_without_quotes<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; but '&quot;</span> &lt;&lt; value<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot;' has type &quot;</span> &lt;&lt; names_to_string_without_quotes<span class="Delimiter">(</span>value<span class="Delimiter">.</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span>  <span class="Comment">// no more checks necessary</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name != inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;product of 'put' must be first ingredient '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;', but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Comment">// End PUT Product Checks</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
<span class="Normal">case</span> PUT: <span class="Delimiter">{</span>
  reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> base = current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
  <span class="Comment">// Update PUT base in Run</span>
  <span class="Normal">int</span> base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>base_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;tried to access location 0 in '&quot;</span> &lt;&lt; to_original_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">const</span> type_tree* base_type = base<span class="Delimiter">.</span>type<span class="Delimiter">;</span>
  <span class="Comment">// Update PUT base_type in Run</span>
  <span class="Normal">int</span> offset = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>offset &lt; <span class="Constant">0</span> || offset &gt;= SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>elements<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span>  <span class="Comment">// copied from Check above</span>
  <span class="Normal">int</span> address = base_address + base<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>offset<span class="Delimiter">.</span>at<span class="Delimiter">(</span>offset<span class="Delimiter">);</span>
  trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;address to copy to is &quot;</span> &lt;&lt; address &lt;&lt; end<span class="Delimiter">();</span>
  <span class="Comment">// optimization: directly write the element rather than updating 'product'</span>
  <span class="Comment">// and writing the entire container</span>
  <span class="Comment">// Write Memory in PUT in Run</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">));</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;storing &quot;</span> &lt;&lt; no_scientific<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> &lt;&lt; <span class="Constant">&quot; in location &quot;</span> &lt;&lt; address+i &lt;&lt; end<span class="Delimiter">();</span>
    put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address+i<span class="Delimiter">,</span> ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">goto</span> finish_instruction<span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(scenario put_product_error)</span>
<span class="Special">% Hide_errors = true;</span>
<span class="muRecipe">def</span> main [
  local-scope
  load-ingredients
  <span class="Constant">1</span>:point<span class="Special"> &lt;- </span>merge <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">35</span>
  <span class="Constant">3</span>:point<span class="Special"> &lt;- </span>put <span class="Constant">1</span>:point<span class="Delimiter">,</span> <span class="Constant">x:offset</span><span class="Delimiter">,</span> <span class="Constant">36</span>
]
<span class="traceContains">+error: main: product of 'put' must be first ingredient '1:point', but got '3:point'</span>

<span class="SalientComment">//:: Allow containers to be defined in mu code.</span>

<span class="Delimiter">:(scenarios load)</span>
<span class="Delimiter">:(scenario container)</span>
<span class="muData">container</span> foo [
  <span class="Normal">x</span>:num
  <span class="Normal">y</span>:num
]
<span class="traceContains">+parse: --- defining container foo</span>
<span class="traceContains">+parse: element: {x: &quot;number&quot;}</span>
<span class="traceContains">+parse: element: {y: &quot;number&quot;}</span>

<span class="Delimiter">:(scenario container_use_before_definition)</span>
<span class="muData">container</span> foo [
  <span class="Normal">x</span>:num
  <span class="Normal">y</span>:bar
]
<span class="muData">container</span> bar [
  <span class="Normal">x</span>:num
  <span class="Normal">y</span>:num
]
<span class="traceContains">+parse: --- defining container foo</span>
<span class="traceContains">+parse: type number: 1000</span>
<span class="traceContains">+parse:   element: {x: &quot;number&quot;}</span>
<span class="Comment"># todo: brittle</span>
<span class="Comment"># type bar is unknown at this point, but we assign it a number</span>
<span class="traceContains">+parse:   element: {y: &quot;bar&quot;}</span>
<span class="Comment"># later type bar geon</span>
<span class="traceContains">+parse: --- defining container bar</span>
<span class="traceContains">+parse: type number: 1001</span>
<span class="traceContains">+parse:   element: {x: &quot;number&quot;}</span>
<span class="traceContains">+parse:   element: {y: &quot;number&quot;}</span>

<span class="Comment">//: if a container is defined again, the new fields add to the original definition</span>
<span class="Delimiter">:(scenarios run)</span>
<span class="Delimiter">:(scenario container_extend)</span>
<span class="muData">container</span> foo [
  <span class="Normal">x</span>:num
]
<span class="Comment"># add to previous definition</span>
<span class="muData">container</span> foo [
  <span class="Normal">y</span>:num
]
<span class="muRecipe">def</span> main [
  <span class="Constant">1</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">2</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">3</span>:num<span class="Special"> &lt;- </span>get <span class="Constant">1</span>:foo<span class="Delimiter">,</span> <span class="Constant">0:offset</span>
  <span class="Constant">4</span>:num<span class="Special"> &lt;- </span>get <span class="Constant">1</span>:foo<span class="Delimiter">,</span> <span class="Constant">1:offset</span>
]
<span class="traceContains">+mem: storing 34 in location 3</span>
<span class="traceContains">+mem: storing 35 in location 4</span>

<span class="Delimiter">:(before &quot;End Command Handlers&quot;)</span>
<span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>command == <span class="Constant">&quot;container&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
  insert_container<span class="Delimiter">(</span>command<span class="Delimiter">,</span> CONTAINER<span class="Delimiter">,</span> in<span class="Delimiter">);</span>
<span class="Delimiter">}</span>

<span class="Comment">//: Even though we allow containers to be extended, we don't allow this after</span>
<span class="Comment">//: a call to transform_all. But we do want to detect this situation and raise</span>
<span class="Comment">//: an error. This field will help us raise such errors.</span>
<span class="Delimiter">:(before &quot;End type_info Fields&quot;)</span>
<span class="Normal">int</span> Num_calls_to_transform_all_at_first_definition<span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End type_info Constructor&quot;)</span>
Num_calls_to_transform_all_at_first_definition = -<span class="Constant">1</span><span class="Delimiter">;</span>

<span class="Delimiter">:(code)</span>
<span class="Normal">void</span> insert_container<span class="Delimiter">(</span><span class="Normal">const</span> string&amp; command<span class="Delimiter">,</span> kind_of_type kind<span class="Delimiter">,</span> istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  skip_whitespace_but_not_newline<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
  string name = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
  <span class="Comment">// End container Name Refinements</span>
  trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- defining &quot;</span> &lt;&lt; command &lt;&lt; <span class="Constant">' '</span> &lt;&lt; name &lt;&lt; end<span class="Delimiter">();</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">)</span>
      || get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">)</span> == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">,</span> Next_type_ordinal++<span class="Delimiter">);</span>
  <span class="Delimiter">}</span>
  trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;type number: &quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span>
  skip_bracket<span class="Delimiter">(</span>in<span class="Delimiter">,</span> <span class="Constant">&quot;'&quot;</span>+command+<span class="Constant">&quot;' must begin with '['&quot;</span><span class="Delimiter">);</span>
  type_info&amp; info = get_or_insert<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">));</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>Num_calls_to_transform_all_at_first_definition == -<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Comment">// initial definition of this container</span>
    info<span class="Delimiter">.</span>Num_calls_to_transform_all_at_first_definition = Num_calls_to_transform_all<span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>Num_calls_to_transform_all_at_first_definition != Num_calls_to_transform_all<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Comment">// extension after transform_all</span>
    raise &lt;&lt; <span class="Constant">&quot;there was a call to transform_all() between the definition of container '&quot;</span> &lt;&lt; name &lt;&lt; <span class="Constant">&quot;' and a subsequent extension. This is not supported, since any recipes that used '&quot;</span> &lt;&lt; name &lt;&lt; <span class="Constant">&quot;' values have already been transformed and </span><span class="cSpecial">\&quot;</span><span class="Constant">frozen</span><span class="cSpecial">\&quot;</span><span class="Constant">.</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">return</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  info<span class="Delimiter">.</span>name = name<span class="Delimiter">;</span>
  info<span class="Delimiter">.</span>kind = kind<span class="Delimiter">;</span>
  <span class="Normal">while</span> <span class="Delimiter">(</span>has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Delimiter">{</span>
    skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
    string element = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>element == <span class="Constant">&quot;]&quot;</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
      raise &lt;&lt; command &lt;&lt; <span class="Constant">&quot; '&quot;</span> &lt;&lt; name &lt;&lt; <span class="Constant">&quot;' contains multiple elements on a single line. Containers and exclusive containers must only contain elements, one to a line, no code.</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
      <span class="Comment">// skip rest of container declaration</span>
      <span class="Normal">while</span> <span class="Delimiter">(</span>has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Delimiter">{</span>
        skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
        <span class="Normal">if</span> <span class="Delimiter">(</span>next_word<span class="Delimiter">(</span>in<span class="Delimiter">)</span> == <span class="Constant">&quot;]&quot;</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span>
      <span class="Delimiter">}</span>
      <span class="Identifier">break</span><span class="Delimiter">;</span>
    <span class="Delimiter">}</span>
    info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span>element<span class="Delimiter">));</span>
    expand_type_abbreviations<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>back<span class="Delimiter">().</span>type<span class="Delimiter">);</span>  <span class="Comment">// todo: use abbreviation before declaration</span>
    replace_unknown_types_with_unique_ordinals<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>back<span class="Delimiter">().</span>type<span class="Delimiter">,</span> info<span class="Delimiter">);</span>
    trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;  element: &quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>back<span class="Delimiter">())</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Comment">// End Load Container Element Definition</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">}</span>

<span class="Normal">void</span> replace_unknown_types_with_unique_ordinals<span class="Delimiter">(</span>type_tree* type<span class="Delimiter">,</span> <span class="Normal">const</span> type_info&amp; info<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    replace_unknown_types_with_unique_ordinals<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> info<span class="Delimiter">);</span>
    replace_unknown_types_with_unique_ordinals<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">,</span> info<span class="Delimiter">);</span>
    <span class="Identifier">return</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  assert<span class="Delimiter">(</span>!type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">.</span>empty<span class="Delimiter">());</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span>
    type<span class="Delimiter">-&gt;</span>value = get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">);</span>
  <span class="Delimiter">}</span>
  <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span>  <span class="Comment">// sometimes types will contain non-type tags, like numbers for the size of an array</span>
    type<span class="Delimiter">-&gt;</span>value = <span class="Constant">0</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Comment">// End insert_container Special-cases</span>
  <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>name != <span class="Constant">&quot;-&gt;&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>  <span class="Comment">// used in recipe types</span>
    put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">,</span> Next_type_ordinal++<span class="Delimiter">);</span>
    type<span class="Delimiter">-&gt;</span>value = get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">);</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">}</span>

<span class="Normal">void</span> skip_bracket<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">,</span> string message<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>in<span class="Delimiter">.</span>get<span class="Delimiter">()</span> != <span class="Constant">'['</span><span class="Delimiter">)</span>
    raise &lt;&lt; message &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(scenario multi_word_line_in_container_declaration)</span>
<span class="Special">% Hide_errors = true;</span>
<span class="muData">container</span> foo [
  <span class="Normal">x</span>:num y:num
]
<span class="traceContains">+error: container 'foo' contains multiple elements on a single line. Containers and exclusive containers must only contain elements, one to a line, no code.</span>

<span class="Comment">//: support type abbreviations in container definitions</span>

<span class="Delimiter">:(scenario type_abbreviations_in_containers)</span>
<span class="muData">type</span> foo = number
<span class="muData">container</span> bar [
  <span class="Normal">x</span>:foo
]
<span class="muRecipe">def</span> main [
  <span class="Constant">1</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">2</span>:foo<span class="Special"> &lt;- </span>get <span class="Constant">1</span>:bar/unsafe<span class="Delimiter">,</span> <span class="Constant">0:offset</span>
]
<span class="traceContains">+mem: storing 34 in location 2</span>

<span class="Delimiter">:(after &quot;Transform.push_back(expand_type_abbreviations)&quot;)</span>
Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>expand_type_abbreviations_in_containers<span class="Delimiter">);</span>
<span class="Delimiter">:(code)</span>
<span class="Comment">// extremely inefficient; we process all types over and over again, once for every single recipe</span>
<span class="Comment">// but it doesn't seem to cause any noticeable slowdown</span>
<span class="Normal">void</span> expand_type_abbreviations_in_containers<span class="Delimiter">(</span>unused <span class="Normal">const</span> recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span>map&lt;type_ordinal<span class="Delimiter">,</span> type_info&gt;::iterator p = Type<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Type<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span>
      expand_type_abbreviations<span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">);</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">}</span>

<span class="Comment">//: ensure scenarios are consistent by always starting new container</span>
<span class="Comment">//: declarations at the same type number</span>
<span class="Delimiter">:(before &quot;End Setup&quot;)</span>  <span class="Comment">//: for tests</span>
Next_type_ordinal = <span class="Constant">1000</span><span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End Test Run Initialization&quot;)</span>
assert<span class="Delimiter">(</span>Next_type_ordinal &lt; <span class="Constant">1000</span><span class="Delimiter">);</span>

<span class="Delimiter">:(code)</span>
<span class="Normal">void</span> test_error_on_transform_all_between_container_definition_and_extension<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  <span class="Comment">// define a container</span>
  run<span class="Delimiter">(</span><span class="Constant">&quot;container foo [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span>
      <span class="Constant">&quot;  a:num</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span>
      <span class="Constant">&quot;]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">);</span>
  <span class="Comment">// try to extend the container after transform</span>
  transform_all<span class="Delimiter">();</span>
  CHECK_TRACE_DOESNT_CONTAIN_ERROR<span class="Delimiter">();</span>
  Hide_errors = <span class="Constant">true</span><span class="Delimiter">;</span>
  run<span class="Delimiter">(</span><span class="Constant">&quot;container foo [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span>
      <span class="Constant">&quot;  b:num</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span>
      <span class="Constant">&quot;]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">);</span>
  CHECK_TRACE_CONTAINS_ERROR<span class="Delimiter">();</span>
<span class="Delimiter">}</span>

<span class="SalientComment">//:: Allow container definitions anywhere in the codebase, but complain if you</span>
<span class="SalientComment">//:: can't find a definition at the end.</span>

<span class="Delimiter">:(scenario run_complains_on_unknown_types)</span>
<span class="Special">% Hide_errors = true;</span>
<span class="muRecipe">def</span> main [
  <span class="Comment"># integer is not a type</span>
  <span class="Constant">1</span>:integer<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
]
<span class="traceContains">+error: main: unknown type integer in '1:integer &lt;- copy 0'</span>

<span class="Delimiter">:(scenario run_allows_type_definition_after_use)</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">1</span>:bar<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>/unsafe
]
<span class="muData">container</span> bar [
  <span class="Normal">x</span>:num
]
$error: <span class="Constant">0</span>

<span class="Delimiter">:(before &quot;End Type Modifying Transforms&quot;)</span>
Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>check_or_set_invalid_types<span class="Delimiter">);</span>  <span class="Comment">// idempotent</span>

<span class="Delimiter">:(code)</span>
<span class="Normal">void</span> check_or_set_invalid_types<span class="Delimiter">(</span><span class="Normal">const</span> recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  recipe&amp; caller = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">);</span>
  trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">&quot;transform&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;--- check for invalid types in recipe &quot;</span> &lt;&lt; caller<span class="Delimiter">.</span>name &lt;&lt; end<span class="Delimiter">();</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> index = <span class="Constant">0</span><span class="Delimiter">;</span> index &lt; SIZE<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    instruction&amp; inst = caller<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span>
    <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span>
      check_or_set_invalid_types<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">,</span> maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">),</span> <span class="Constant">&quot;'&quot;</span>+inst<span class="Delimiter">.</span>original_string+<span class="Constant">&quot;'&quot;</span><span class="Delimiter">);</span>
    <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span>
      check_or_set_invalid_types<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">,</span> maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">),</span> <span class="Constant">&quot;'&quot;</span>+inst<span class="Delimiter">.</span>original_string+<span class="Constant">&quot;'&quot;</span><span class="Delimiter">);</span>
  <span class="Delimiter">}</span>
  <span class="Comment">// End check_or_set_invalid_types</span>
<span class="Delimiter">}</span>

<span class="Normal">void</span> check_or_set_invalid_types<span class="Delimiter">(</span>type_tree* type<span class="Delimiter">,</span> <span class="Normal">const</span> string&amp; block<span class="Delimiter">,</span> <span class="Normal">const</span> string&amp; name<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span>  <span class="Comment">// will throw a more precise error elsewhere</span>
  <span class="Comment">// End Container Type Checks</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    check_or_set_invalid_types<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> block<span class="Delimiter">,</span> name<span class="Delimiter">);</span>
    check_or_set_invalid_types<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">,</span> block<span class="Delimiter">,</span> name<span class="Delimiter">);</span>
    <span class="Identifier">return</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">))</span> <span class="Delimiter">{</span>
    assert<span class="Delimiter">(</span>!type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">.</span>empty<span class="Delimiter">());</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">))</span>
      type<span class="Delimiter">-&gt;</span>value = get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>name<span class="Delimiter">);</span>
    <span class="Normal">else</span>
      raise &lt;&lt; block &lt;&lt; <span class="Constant">&quot;unknown type &quot;</span> &lt;&lt; type<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot; in &quot;</span> &lt;&lt; name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(scenario container_unknown_field)</span>
<span class="Special">% Hide_errors = true;</span>
<span class="muData">container</span> foo [
  <span class="Normal">x</span>:num
  <span class="Normal">y</span>:bar
]
<span class="traceContains">+error: foo: unknown type in y</span>

<span class="Delimiter">:(scenario read_container_with_bracket_in_comment)</span>
<span class="muData">container</span> foo [
  <span class="Normal">x</span>:num
  <span class="Comment"># ']' in comment</span>
  <span class="Normal">y</span>:num
]
<span class="traceContains">+parse: --- defining container foo</span>
<span class="traceContains">+parse: element: {x: &quot;number&quot;}</span>
<span class="traceContains">+parse: element: {y: &quot;number&quot;}</span>

<span class="Delimiter">:(scenario container_with_compound_field_type)</span>
<span class="muData">container</span> foo [
  <span class="Delimiter">{</span>x: <span class="Delimiter">(</span>address array <span class="Delimiter">(</span>address array character<span class="Delimiter">))}</span>
]
$error: <span class="Constant">0</span>

<span class="Delimiter">:(before &quot;End transform_all&quot;)</span>
check_container_field_types<span class="Delimiter">();</span>

<span class="Delimiter">:(code)</span>
<span class="Normal">void</span> check_container_field_types<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span>map&lt;type_ordinal<span class="Delimiter">,</span> type_info&gt;::iterator p = Type<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Type<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Normal">const</span> type_info&amp; info = p<span class="Delimiter">-&gt;</span>second<span class="Delimiter">;</span>
    <span class="Comment">// Check Container Field Types(info)</span>
    <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span>
      check_invalid_types<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>type<span class="Delimiter">,</span> maybe<span class="Delimiter">(</span>info<span class="Delimiter">.</span>name<span class="Delimiter">),</span> info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>name<span class="Delimiter">);</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">}</span>

<span class="Normal">void</span> check_invalid_types<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">,</span> <span class="Normal">const</span> string&amp; block<span class="Delimiter">,</span> <span class="Normal">const</span> string&amp; name<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span>  <span class="Comment">// will throw a more precise error elsewhere</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">-&gt;</span>atom<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    check_invalid_types<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">,</span> block<span class="Delimiter">,</span> name<span class="Delimiter">);</span>
    check_invalid_types<span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">,</span> block<span class="Delimiter">,</span> name<span class="Delimiter">);</span>
    <span class="Identifier">return</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-&gt;</span>value != <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>  <span class="Comment">// value 0 = compound types (layer parse_tree) or type ingredients (layer shape_shifting_container)</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">))</span>
      raise &lt;&lt; block &lt;&lt; <span class="Constant">&quot;unknown type in &quot;</span> &lt;&lt; name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; end<span class="Delimiter">();</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">}</span>
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->