about summary refs log tree commit diff
path: root/tvix
diff options
context:
space:
mode:
Diffstat (limited to 'tvix')
-rw-r--r--tvix/eval/src/observer.rs92
-rw-r--r--tvix/eval/src/vm.rs4
2 files changed, 89 insertions, 7 deletions
diff --git a/tvix/eval/src/observer.rs b/tvix/eval/src/observer.rs
index 6bd4609b0998..533182f09531 100644
--- a/tvix/eval/src/observer.rs
+++ b/tvix/eval/src/observer.rs
@@ -13,6 +13,7 @@ use tabwriter::TabWriter;
 use crate::chunk::Chunk;
 use crate::opcode::{CodeIdx, OpCode};
 use crate::value::Lambda;
+use crate::vm::generators::GeneratorRequest;
 use crate::SourceCode;
 use crate::Value;
 
@@ -39,10 +40,25 @@ pub trait CompilerObserver {
 /// the Tvix virtual machine at runtime.
 pub trait RuntimeObserver {
     /// Called when the runtime enters a new call frame.
-    fn observe_enter_frame(&mut self, _arg_count: usize, _: &Rc<Lambda>, _call_depth: usize) {}
+    fn observe_enter_call_frame(&mut self, _arg_count: usize, _: &Rc<Lambda>, _call_depth: usize) {}
 
     /// Called when the runtime exits a call frame.
-    fn observe_exit_frame(&mut self, _frame_at: usize, _stack: &[Value]) {}
+    fn observe_exit_call_frame(&mut self, _frame_at: usize, _stack: &[Value]) {}
+
+    /// Called when the runtime suspends a call frame.
+    fn observe_suspend_call_frame(&mut self, _frame_at: usize, _stack: &[Value]) {}
+
+    /// Called when the runtime enters a generator frame.
+    fn observe_enter_generator(&mut self, _frame_at: usize, _stack: &[Value]) {}
+
+    /// Called when the runtime exits a generator frame.
+    fn observe_exit_generator(&mut self, _frame_at: usize, _stack: &[Value]) {}
+
+    /// Called when the runtime suspends a generator frame.
+    fn observe_suspend_generator(&mut self, _frame_at: usize, _stack: &[Value]) {}
+
+    /// Called when a generator requests an action from the VM.
+    fn observe_generator_request(&mut self, _msg: &GeneratorRequest) {}
 
     /// Called when the runtime replaces the current call frame for a
     /// tail call.
@@ -136,7 +152,12 @@ 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) {
+    fn observe_enter_call_frame(
+        &mut self,
+        arg_count: usize,
+        lambda: &Rc<Lambda>,
+        call_depth: usize,
+    ) {
         let _ = write!(&mut self.writer, "=== entering ");
 
         let _ = if arg_count == 0 {
@@ -156,7 +177,8 @@ impl<W: Write> RuntimeObserver for TracingObserver<W> {
         );
     }
 
-    fn observe_exit_frame(&mut self, frame_at: usize, stack: &[Value]) {
+    /// Called when the runtime exits a call frame.
+    fn observe_exit_call_frame(&mut self, frame_at: usize, stack: &[Value]) {
         let _ = write!(&mut self.writer, "=== exiting frame {} ===\t[ ", frame_at);
 
         for val in stack {
@@ -166,6 +188,66 @@ impl<W: Write> RuntimeObserver for TracingObserver<W> {
         let _ = writeln!(&mut self.writer, "]");
     }
 
+    fn observe_suspend_call_frame(&mut self, frame_at: usize, stack: &[Value]) {
+        let _ = write!(
+            &mut self.writer,
+            "=== suspending frame {} ===\t[ ",
+            frame_at
+        );
+
+        for val in stack {
+            let _ = write!(&mut self.writer, "{} ", val);
+        }
+
+        let _ = writeln!(&mut self.writer, "]");
+    }
+
+    fn observe_enter_generator(&mut self, frame_at: usize, stack: &[Value]) {
+        let _ = write!(
+            &mut self.writer,
+            "=== entering generator frame {} ===\t[ ",
+            frame_at
+        );
+
+        for val in stack {
+            let _ = write!(&mut self.writer, "{} ", val);
+        }
+
+        let _ = writeln!(&mut self.writer, "]");
+    }
+
+    fn observe_exit_generator(&mut self, frame_at: usize, stack: &[Value]) {
+        let _ = write!(
+            &mut self.writer,
+            "=== exiting generator {} ===\t[ ",
+            frame_at
+        );
+
+        for val in stack {
+            let _ = write!(&mut self.writer, "{} ", val);
+        }
+
+        let _ = writeln!(&mut self.writer, "]");
+    }
+
+    fn observe_suspend_generator(&mut self, frame_at: usize, stack: &[Value]) {
+        let _ = write!(
+            &mut self.writer,
+            "=== suspending generator {} ===\t[ ",
+            frame_at
+        );
+
+        for val in stack {
+            let _ = write!(&mut self.writer, "{} ", val);
+        }
+
+        let _ = writeln!(&mut self.writer, "]");
+    }
+
+    fn observe_generator_request(&mut self, msg: &GeneratorRequest) {
+        let _ = writeln!(&mut self.writer, "=== generator requested {} ===", msg);
+    }
+
     fn observe_enter_builtin(&mut self, name: &'static str) {
         let _ = writeln!(&mut self.writer, "=== entering builtin {} ===", name);
     }
@@ -184,7 +266,7 @@ impl<W: Write> RuntimeObserver for TracingObserver<W> {
         let _ = writeln!(
             &mut self.writer,
             "=== tail-calling {:p} in frame[{}] ===",
-            lambda, frame_at
+            *lambda, frame_at
         );
     }
 
diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs
index 3e3052555639..f5107f9ed738 100644
--- a/tvix/eval/src/vm.rs
+++ b/tvix/eval/src/vm.rs
@@ -436,7 +436,7 @@ impl<'o> VM<'o> {
         arg_count: usize,
     ) -> EvalResult<()> {
         self.observer
-            .observe_enter_frame(arg_count, &lambda, self.frames.len() + 1);
+            .observe_enter_call_frame(arg_count, &lambda, self.frames.len() + 1);
 
         let frame = CallFrame {
             lambda,
@@ -472,7 +472,7 @@ impl<'o> VM<'o> {
         };
 
         self.observer
-            .observe_exit_frame(self.frames.len() + 1, &self.stack);
+            .observe_exit_call_frame(self.frames.len() + 1, &self.stack);
 
         result
     }