diff options
-rw-r--r-- | corp/tvixbolt/src/main.rs | 13 | ||||
-rw-r--r-- | tvix/eval/src/builtins/impure.rs | 8 | ||||
-rw-r--r-- | tvix/eval/src/eval.rs | 8 | ||||
-rw-r--r-- | tvix/eval/src/vm.rs | 36 |
4 files changed, 57 insertions, 8 deletions
diff --git a/corp/tvixbolt/src/main.rs b/corp/tvixbolt/src/main.rs index f81ae070a2ce..8099a5238d02 100644 --- a/corp/tvixbolt/src/main.rs +++ b/corp/tvixbolt/src/main.rs @@ -292,7 +292,18 @@ fn eval(trace: bool, code: &str) -> Output { }; match result { - Ok(value) => writeln!(&mut out.output, "{}", value).unwrap(), + Ok(result) => { + for warning in result.warnings { + writeln!( + &mut out.warnings, + "{}\n", + warning.fancy_format_str(&source).trim(), + ) + .unwrap(); + } + + writeln!(&mut out.output, "{}", result.value).unwrap() + } Err(err) => writeln!( &mut out.runtime_errors, "{}", diff --git a/tvix/eval/src/builtins/impure.rs b/tvix/eval/src/builtins/impure.rs index 7c98fcb4e192..d73e5ccfa8f2 100644 --- a/tvix/eval/src/builtins/impure.rs +++ b/tvix/eval/src/builtins/impure.rs @@ -51,7 +51,7 @@ pub fn builtins_import( Builtin::new( "import", &[true], - move |mut args: Vec<Value>, _: &mut VM| { + move |mut args: Vec<Value>, vm: &mut VM| { let path = match args.pop().unwrap() { Value::Path(path) => path, Value::String(_) => { @@ -102,9 +102,9 @@ pub fn builtins_import( }); } - // TODO: deal with runtime *warnings* (most likely through an - // emit_warning function on the VM that might return it together with - // the result) + for warning in result.warnings { + vm.push_warning(warning); + } // Compilation succeeded, we can construct a thunk from whatever it spat // out and return that. diff --git a/tvix/eval/src/eval.rs b/tvix/eval/src/eval.rs index 4e50b7279c38..5af5f9d7588e 100644 --- a/tvix/eval/src/eval.rs +++ b/tvix/eval/src/eval.rs @@ -115,5 +115,11 @@ pub fn interpret(code: &str, location: Option<PathBuf>, options: Options) -> Eva err.fancy_format_stderr(&source); } - result + result.map(|r| { + for warning in r.warnings { + warning.fancy_format_stderr(&source); + } + + r.value + }) } diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs index 41f51a987459..d616b9ce1c5c 100644 --- a/tvix/eval/src/vm.rs +++ b/tvix/eval/src/vm.rs @@ -10,6 +10,7 @@ use crate::{ opcode::{CodeIdx, Count, JumpOffset, OpCode, StackIdx, UpvalueIdx}, upvalues::{UpvalueCarrier, Upvalues}, value::{Builtin, Closure, CoercionKind, Lambda, NixAttrs, NixList, Thunk, Value}, + warnings::{EvalWarning, WarningKind}, }; struct CallFrame { @@ -43,9 +44,18 @@ pub struct VM<'o> { /// dynamically resolved (`with`). with_stack: Vec<usize>, + /// Runtime warnings collected during evaluation. + warnings: Vec<EvalWarning>, + observer: &'o mut dyn RuntimeObserver, } +/// The result of a VM's runtime evaluation. +pub struct RuntimeResult { + pub value: Value, + pub warnings: Vec<EvalWarning>, +} + /// This macro wraps a computation that returns an ErrorKind or a /// result, and wraps the ErrorKind in an Error struct if present. /// @@ -133,6 +143,7 @@ impl<'o> VM<'o> { frames: vec![], stack: vec![], with_stack: vec![], + warnings: vec![], } } @@ -182,6 +193,20 @@ impl<'o> VM<'o> { } } + /// Push an already constructed warning. + pub fn push_warning(&mut self, warning: EvalWarning) { + self.warnings.push(warning); + } + + /// Emit a warning with the given WarningKind and the source span + /// of the current instruction. + pub fn emit_warning(&mut self, kind: WarningKind) { + self.push_warning(EvalWarning { + kind, + span: self.current_span(), + }); + } + /// Execute the given value in this VM's context, if it is a /// callable. /// @@ -780,9 +805,16 @@ fn unwrap_or_clone_rc<T: Clone>(rc: Rc<T>) -> T { Rc::try_unwrap(rc).unwrap_or_else(|rc| (*rc).clone()) } -pub fn run_lambda(observer: &mut dyn RuntimeObserver, lambda: Rc<Lambda>) -> EvalResult<Value> { +pub fn run_lambda( + observer: &mut dyn RuntimeObserver, + lambda: Rc<Lambda>, +) -> EvalResult<RuntimeResult> { let mut vm = VM::new(observer); let value = vm.call(lambda, Upvalues::with_capacity(0), 0)?; vm.force_for_output(&value)?; - Ok(value) + + Ok(RuntimeResult { + value, + warnings: vm.warnings, + }) } |