docs(tvix/eval): add some notes on recursive attribute sets
Change-Id: I36b826f12854a22e60a27ed1982ab5528c58bdad Reviewed-on: https://cl.tvl.fyi/c/depot/+/6489 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
This commit is contained in:
		
							parent
							
								
									e944c341a7
								
							
						
					
					
						commit
						b4309f5b8a
					
				
					 1 changed files with 60 additions and 0 deletions
				
			
		
							
								
								
									
										60
									
								
								tvix/eval/docs/recursive-attrs.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								tvix/eval/docs/recursive-attrs.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,60 @@
 | 
				
			||||||
 | 
					Recursive attribute sets
 | 
				
			||||||
 | 
					========================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The construction behaviour of recursive attribute sets is very
 | 
				
			||||||
 | 
					specific, and a bit peculiar.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In essence, there are multiple "phases" of scoping that take place
 | 
				
			||||||
 | 
					during attribute set construction:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. Every inherited value without an explicit source is inherited only
 | 
				
			||||||
 | 
					   from the **outer** scope in which the attribute set is enclosed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2. A new scope is opened in which all recursive keys are evaluated.
 | 
				
			||||||
 | 
					   This only considers **statically known keys**, attributes can
 | 
				
			||||||
 | 
					   **not** recurse into dynamic keys in `self`!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   For example, this code is invalid in C++ Nix:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   ```
 | 
				
			||||||
 | 
					   nix-repl> rec { ${"a"+""} = 2; b = a * 10; }
 | 
				
			||||||
 | 
					   error: undefined variable 'a' at (string):1:26
 | 
				
			||||||
 | 
					   ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					3. Finally, a third scope is opened in which dynamic keys are
 | 
				
			||||||
 | 
					   evaluated.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This behaviour, while possibly a bit strange and unexpected, actually
 | 
				
			||||||
 | 
					simplifies the implementation of recursive attribute sets in Tvix as
 | 
				
			||||||
 | 
					well.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Essentially, a recursive attribute set like this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```nix
 | 
				
			||||||
 | 
					rec {
 | 
				
			||||||
 | 
					  inherit a;
 | 
				
			||||||
 | 
					  b = a * 10;
 | 
				
			||||||
 | 
					  ${"c" + ""} = b * 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Can be compiled like the following expression:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```nix
 | 
				
			||||||
 | 
					let
 | 
				
			||||||
 | 
					  inherit a;
 | 
				
			||||||
 | 
					in let
 | 
				
			||||||
 | 
					  b = a * 10;
 | 
				
			||||||
 | 
					  in {
 | 
				
			||||||
 | 
					    inherit a b;
 | 
				
			||||||
 | 
					    ${"c" + ""} = b * 2;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Completely deferring the resolution of recursive identifiers to the
 | 
				
			||||||
 | 
					existing handling of recursive scopes (i.e. deferred access) in let
 | 
				
			||||||
 | 
					bindings.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In practice, we can further specialise this and compile each scope
 | 
				
			||||||
 | 
					directly into the form expected by `OpAttrs` (that is, leaving
 | 
				
			||||||
 | 
					attribute names on the stack) before each value's position.
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue