about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tvix/eval/src/compiler/mod.rs10
-rw-r--r--tvix/eval/src/compiler/scope.rs10
-rw-r--r--tvix/eval/src/observer.rs18
-rw-r--r--tvix/eval/src/value/function.rs16
4 files changed, 39 insertions, 15 deletions
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs
index 2ab76623864b..2985c7e90e0b 100644
--- a/tvix/eval/src/compiler/mod.rs
+++ b/tvix/eval/src/compiler/mod.rs
@@ -54,7 +54,7 @@ struct LambdaCtx {
 impl LambdaCtx {
     fn new() -> Self {
         LambdaCtx {
-            lambda: Lambda::new_anonymous(),
+            lambda: Lambda::default(),
             scope: Default::default(),
             captures_with_stack: false,
         }
@@ -62,7 +62,7 @@ impl LambdaCtx {
 
     fn inherit(&self) -> Self {
         LambdaCtx {
-            lambda: Lambda::new_anonymous(),
+            lambda: Lambda::default(),
             scope: self.scope.inherit(),
             captures_with_stack: false,
         }
@@ -897,7 +897,13 @@ impl Compiler<'_> {
         N: ToSpan,
         F: FnOnce(&mut Compiler, LocalIdx),
     {
+        let name = self.scope()[outer_slot].name();
         self.new_context();
+
+        // Set the (optional) name of the current slot on the lambda that is
+        // being compiled.
+        self.context_mut().lambda.name = name;
+
         let span = self.span_for(node);
         let slot = self.scope_mut().declare_phantom(span, false);
         self.scope_mut().begin_scope();
diff --git a/tvix/eval/src/compiler/scope.rs b/tvix/eval/src/compiler/scope.rs
index 9269a3c44c76..83fba6eed73c 100644
--- a/tvix/eval/src/compiler/scope.rs
+++ b/tvix/eval/src/compiler/scope.rs
@@ -15,6 +15,8 @@ use std::{
     ops::Index,
 };
 
+use smol_str::SmolStr;
+
 use crate::opcode::{StackIdx, UpvalueIdx};
 
 #[derive(Debug)]
@@ -71,6 +73,14 @@ impl Local {
         }
     }
 
+    /// Retrieve the name of the given local (if available).
+    pub fn name(&self) -> Option<SmolStr> {
+        match &self.name {
+            LocalName::Phantom => None,
+            LocalName::Ident(name) => Some(SmolStr::new(name)),
+        }
+    }
+
     /// Is this local intentionally ignored? (i.e. name starts with `_`)
     pub fn is_ignored(&self) -> bool {
         match &self.name {
diff --git a/tvix/eval/src/observer.rs b/tvix/eval/src/observer.rs
index 74ed316a6ac9..1617d61c8752 100644
--- a/tvix/eval/src/observer.rs
+++ b/tvix/eval/src/observer.rs
@@ -137,12 +137,22 @@ impl<W: Write> TracingObserver<W> {
 
 impl<W: Write> RuntimeObserver for TracingObserver<W> {
     fn observe_enter_frame(&mut self, arg_count: usize, lambda: &Rc<Lambda>, call_depth: usize) {
+        let _ = write!(&mut self.writer, "=== entering ");
+
+        let _ = if arg_count == 0 {
+            write!(&mut self.writer, "thunk ")
+        } else {
+            write!(&mut self.writer, "closure ")
+        };
+
+        if let Some(name) = &lambda.name {
+            let _ = write!(&mut self.writer, "'{}' ", name);
+        }
+
         let _ = writeln!(
             &mut self.writer,
-            "=== entering {} frame[{}] @ {:p} ===",
-            if arg_count == 0 { "thunk" } else { "closure" },
-            call_depth,
-            lambda,
+            "in frame[{}] @ {:p} ===",
+            call_depth, lambda
         );
     }
 
diff --git a/tvix/eval/src/value/function.rs b/tvix/eval/src/value/function.rs
index bb33e2962ad5..f282928df9f9 100644
--- a/tvix/eval/src/value/function.rs
+++ b/tvix/eval/src/value/function.rs
@@ -2,6 +2,7 @@
 use std::{collections::HashMap, hash::Hash, rc::Rc};
 
 use codemap::Span;
+use smol_str::SmolStr;
 
 use crate::{chunk::Chunk, upvalues::Upvalues};
 
@@ -38,10 +39,15 @@ impl Formals {
 /// OpThunkSuspended referencing it.  At runtime `Lambda` is usually wrapped
 /// in `Rc` to avoid copying the `Chunk` it holds (which can be
 /// quite large).
-#[derive(Debug, PartialEq)]
+#[derive(Debug, Default, PartialEq)]
 pub struct Lambda {
     pub(crate) chunk: Chunk,
 
+    /// Name of the function (equivalent to the name of the
+    /// identifier (e.g. a value in a let-expression or an attribute
+    /// set entry) it is located in).
+    pub(crate) name: Option<SmolStr>,
+
     /// Number of upvalues which the code in this Lambda closes
     /// over, and which need to be initialised at
     /// runtime.  Information about the variables is emitted using
@@ -51,14 +57,6 @@ pub struct Lambda {
 }
 
 impl Lambda {
-    pub fn new_anonymous() -> Self {
-        Lambda {
-            chunk: Default::default(),
-            upvalue_count: 0,
-            formals: None,
-        }
-    }
-
     pub fn chunk(&mut self) -> &mut Chunk {
         &mut self.chunk
     }