refactor(tvix/eval): Factor out bind_values helper
				
					
				
			This is responsible for actually setting up `TrackedBinding`s on the stack, i.e. in some sense "actually compiling" values in bindings. There is no functionality change to before, i.e. this is a salami slice. Change-Id: Idb0312038e004470a7d130c020ae0fe87c55c218 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6774 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
This commit is contained in:
		
							parent
							
								
									7e9169bcf7
								
							
						
					
					
						commit
						f40283e098
					
				
					 1 changed files with 55 additions and 47 deletions
				
			
		| 
						 | 
				
			
			@ -434,6 +434,59 @@ impl Compiler<'_> {
 | 
			
		|||
        self.scope_mut().end_scope();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Actually binds all tracked bindings by emitting the bytecode that places
 | 
			
		||||
    /// them in their stack slots.
 | 
			
		||||
    fn bind_values(&mut self, bindings: Vec<TrackedBinding>) {
 | 
			
		||||
        let mut value_indices: Vec<LocalIdx> = vec![];
 | 
			
		||||
 | 
			
		||||
        for binding in bindings.into_iter() {
 | 
			
		||||
            value_indices.push(binding.value_slot);
 | 
			
		||||
 | 
			
		||||
            if let Some(key_slot) = binding.key_slot {
 | 
			
		||||
                let span = self.scope()[key_slot.slot].span;
 | 
			
		||||
                self.emit_constant(Value::String(key_slot.name.into()), &span);
 | 
			
		||||
                self.scope_mut().mark_initialised(key_slot.slot);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            match binding.binding {
 | 
			
		||||
                // This entry is an inherit (from) expr. The value is
 | 
			
		||||
                // placed on the stack by selecting an attribute.
 | 
			
		||||
                Binding::InheritFrom {
 | 
			
		||||
                    namespace,
 | 
			
		||||
                    name,
 | 
			
		||||
                    span,
 | 
			
		||||
                } => {
 | 
			
		||||
                    // Create a thunk wrapping value (which may be one as well) to
 | 
			
		||||
                    // avoid forcing the from expr too early.
 | 
			
		||||
                    self.thunk(binding.value_slot, &namespace, move |c, n, s| {
 | 
			
		||||
                        c.compile(s, n.clone());
 | 
			
		||||
                        c.emit_force(n);
 | 
			
		||||
 | 
			
		||||
                        c.emit_constant(Value::String(name.into()), &span);
 | 
			
		||||
                        c.push_op(OpCode::OpAttrsSelect, &span);
 | 
			
		||||
                    })
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Binding is "just" a plain expression that needs to
 | 
			
		||||
                // be compiled.
 | 
			
		||||
                Binding::Plain { expr } => self.compile(binding.value_slot, expr),
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Any code after this point will observe the value in the
 | 
			
		||||
            // right stack slot, so mark it as initialised.
 | 
			
		||||
            self.scope_mut().mark_initialised(binding.value_slot);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Final pass to emit finaliser instructions if necessary.
 | 
			
		||||
        for idx in value_indices {
 | 
			
		||||
            if self.scope()[idx].needs_finaliser {
 | 
			
		||||
                let stack_idx = self.scope().stack_index(idx);
 | 
			
		||||
                let span = self.scope()[idx].span;
 | 
			
		||||
                self.push_op(OpCode::OpFinalise(stack_idx), &span);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn compile_recursive_scope<N>(&mut self, slot: LocalIdx, kind: BindingsKind, node: &N) -> usize
 | 
			
		||||
    where
 | 
			
		||||
        N: ToSpan + ast::HasEntry,
 | 
			
		||||
| 
						 | 
				
			
			@ -488,53 +541,8 @@ impl Compiler<'_> {
 | 
			
		|||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Third pass to place the values in the correct stack slots.
 | 
			
		||||
        let mut value_indices: Vec<LocalIdx> = vec![];
 | 
			
		||||
        for binding in bindings.into_iter() {
 | 
			
		||||
            value_indices.push(binding.value_slot);
 | 
			
		||||
 | 
			
		||||
            if let Some(key_slot) = binding.key_slot {
 | 
			
		||||
                let span = self.scope()[key_slot.slot].span;
 | 
			
		||||
                self.emit_constant(Value::String(key_slot.name.into()), &span);
 | 
			
		||||
                self.scope_mut().mark_initialised(key_slot.slot);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            match binding.binding {
 | 
			
		||||
                // This entry is an inherit (from) expr. The value is
 | 
			
		||||
                // placed on the stack by selecting an attribute.
 | 
			
		||||
                Binding::InheritFrom {
 | 
			
		||||
                    namespace,
 | 
			
		||||
                    name,
 | 
			
		||||
                    span,
 | 
			
		||||
                } => {
 | 
			
		||||
                    // Create a thunk wrapping value (which may be one as well) to
 | 
			
		||||
                    // avoid forcing the from expr too early.
 | 
			
		||||
                    self.thunk(binding.value_slot, &namespace, move |c, n, s| {
 | 
			
		||||
                        c.compile(s, n.clone());
 | 
			
		||||
                        c.emit_force(n);
 | 
			
		||||
 | 
			
		||||
                        c.emit_constant(Value::String(name.into()), &span);
 | 
			
		||||
                        c.push_op(OpCode::OpAttrsSelect, &span);
 | 
			
		||||
                    })
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Binding is "just" a plain expression that needs to
 | 
			
		||||
                // be compiled.
 | 
			
		||||
                Binding::Plain { expr } => self.compile(binding.value_slot, expr),
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Any code after this point will observe the value in the
 | 
			
		||||
            // right stack slot, so mark it as initialised.
 | 
			
		||||
            self.scope_mut().mark_initialised(binding.value_slot);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Fourth pass to emit finaliser instructions if necessary.
 | 
			
		||||
        for idx in value_indices {
 | 
			
		||||
            if self.scope()[idx].needs_finaliser {
 | 
			
		||||
                let stack_idx = self.scope().stack_index(idx);
 | 
			
		||||
                self.push_op(OpCode::OpFinalise(stack_idx), node);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Actually bind values and ensure they are on the stack.
 | 
			
		||||
        self.bind_values(bindings);
 | 
			
		||||
 | 
			
		||||
        count
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue