about summary refs log tree commit diff
path: root/tvix/eval/src
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-12-09T09·58+0300
committertazjin <tazjin@tvl.su>2022-12-21T13·23+0000
commit59e695a9d907aba0db23fb6ac71acd80f7713cd0 (patch)
tree441afdae76b8e404f6ec9a075b1625e47016629b /tvix/eval/src
parent9bc1e6ef055bc1d835d258a2e21e6cfe6ae63cb9 (diff)
feat(tvix/eval): add observer configuration to public API r/5444
With this change, it should be possible to have both existing
use-cases (CLI & Tvixbolt) use the same API.

Change-Id: I2195264f08cc892177b559a28660dc5f98e48e41
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7545
Autosubmit: tazjin <tazjin@tvl.su>
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
Diffstat (limited to 'tvix/eval/src')
-rw-r--r--tvix/eval/src/lib.rs32
1 files changed, 21 insertions, 11 deletions
diff --git a/tvix/eval/src/lib.rs b/tvix/eval/src/lib.rs
index c4c3e06901f4..aef6f5f06b2e 100644
--- a/tvix/eval/src/lib.rs
+++ b/tvix/eval/src/lib.rs
@@ -44,6 +44,7 @@ use std::sync::Arc;
 pub use crate::builtins::global_builtins;
 pub use crate::compiler::{compile, prepare_globals};
 pub use crate::errors::{Error, ErrorKind, EvalResult};
+use crate::observer::{CompilerObserver, RuntimeObserver};
 pub use crate::pretty_ast::pretty_print_expr;
 pub use crate::source::SourceCode;
 pub use crate::value::Value;
@@ -69,10 +70,9 @@ pub(crate) fn unwrap_or_clone_rc<T: Clone>(rc: Rc<T>) -> T {
 ///
 /// Public fields are intended to be set by the caller. Setting all
 /// fields is optional.
-#[derive(Clone)]
-pub struct Evaluation<'a> {
+pub struct Evaluation<'code, 'co, 'ro> {
     /// The Nix source code to be evaluated.
-    code: &'a str,
+    code: &'code str,
 
     /// Optional location of the source code (i.e. path to the file it was read
     /// from). Used for error reporting, and for resolving relative paths in
@@ -91,6 +91,14 @@ pub struct Evaluation<'a> {
     /// (optional) Nix search path, e.g. the value of `NIX_PATH` used
     /// for resolving items on the search path (such as `<nixpkgs>`).
     pub nix_path: Option<String>,
+
+    /// (optional) compiler observer for reporting on compilation
+    /// details, like the emitted bytecode.
+    pub compiler_observer: Option<&'co mut dyn CompilerObserver>,
+
+    /// (optional) runtime observer, for reporting on execution steps
+    /// of Nix code.
+    pub runtime_observer: Option<&'ro mut dyn RuntimeObserver>,
 }
 
 /// Result of evaluating a piece of Nix code. If evaluation succeeded, a value
@@ -109,11 +117,11 @@ pub struct EvaluationResult {
     pub warnings: Vec<EvalWarning>,
 }
 
-impl<'a> Evaluation<'a> {
+impl<'code, 'co, 'ro> Evaluation<'code, 'co, 'ro> {
     /// Initialise an `Evaluation` for the given Nix source code snippet, and
     /// an optional code location.
     /// reporting the location of errors in the code.
-    pub fn new(code: &'a str, location: Option<PathBuf>) -> Self {
+    pub fn new(code: &'code str, location: Option<PathBuf>) -> Self {
         let source_map = SourceCode::new();
 
         let location_str = location
@@ -130,6 +138,8 @@ impl<'a> Evaluation<'a> {
             file,
             expr: None,
             nix_path: None,
+            compiler_observer: None,
+            runtime_observer: None,
         }
     }
 
@@ -163,12 +173,15 @@ impl<'a> Evaluation<'a> {
         let builtins =
             crate::compiler::prepare_globals(Box::new(global_builtins(self.source_map())));
 
+        let mut noop_observer = observer::NoOpObserver::default();
+        let compiler_observer = self.compiler_observer.take().unwrap_or(&mut noop_observer);
+
         let compiler_result = match compiler::compile(
             self.expr.as_ref().unwrap(),
             self.location.take(),
             self.file.clone(),
             builtins,
-            &mut observer::NoOpObserver::default(), // TODO: compilation observer
+            compiler_observer,
         ) {
             Ok(result) => result,
             Err(err) => {
@@ -202,11 +215,8 @@ impl<'a> Evaluation<'a> {
             })
             .unwrap_or_else(|| Default::default());
 
-        let vm_result = run_lambda(
-            nix_path,
-            &mut observer::NoOpObserver::default(), // TODO: runtime observer
-            compiler_result.lambda,
-        );
+        let runtime_observer = self.runtime_observer.take().unwrap_or(&mut noop_observer);
+        let vm_result = run_lambda(nix_path, runtime_observer, compiler_result.lambda);
 
         match vm_result {
             Ok(mut runtime_result) => {