diff options
Diffstat (limited to 'tvix/eval/src/compiler/bindings.rs')
-rw-r--r-- | tvix/eval/src/compiler/bindings.rs | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/tvix/eval/src/compiler/bindings.rs b/tvix/eval/src/compiler/bindings.rs index 682cf134ce1a..59ca222b7219 100644 --- a/tvix/eval/src/compiler/bindings.rs +++ b/tvix/eval/src/compiler/bindings.rs @@ -685,6 +685,14 @@ impl Compiler<'_> { self.push_op(OpCode::OpAttrsSelect, node); } + /// Is the given identifier defined *by the user* in any current scope? + pub(super) fn is_user_defined(&mut self, ident: &str) -> bool { + matches!( + self.scope_mut().resolve_local(ident), + LocalPosition::Known(_) | LocalPosition::Recursive(_) + ) + } + /// Resolve and compile access to an identifier in the scope. fn compile_identifier_access<N: ToSpan + Clone>( &mut self, @@ -692,15 +700,6 @@ impl Compiler<'_> { ident: &str, node: &N, ) { - // If the identifier is a global, and it is not poisoned, emit the - // global directly. - if let Some(global) = self.globals.get(ident) { - if !self.scope().is_poisoned(ident) { - global.clone()(self, self.span_for(node)); - return; - } - } - match self.scope_mut().resolve_local(ident) { LocalPosition::Unknown => { // Are we possibly dealing with an upvalue? @@ -709,6 +708,15 @@ impl Compiler<'_> { return; } + // Globals are the "upmost upvalues": they behave + // exactly like a `let ... in` prepended to the + // program's text, and the global scope is nothing + // more than the parent scope of the root scope. + if let Some(global) = self.globals.get(ident) { + self.emit_constant(global.clone(), &self.span_for(node)); + return; + } + // If there is a non-empty `with`-stack (or a parent context // with one), emit a runtime dynamic resolution instruction. // |