diff options
author | Vincent Ambo <mail@tazj.in> | 2022-10-05T14·01+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-10-07T14·24+0000 |
commit | 07e03498f26afbf647102d656c90d447f8586820 (patch) | |
tree | 0f891cb5f2601e12bbbe89d10961f4f9b2d16fc1 /tvix/eval/src/vm.rs | |
parent | 4b9178fa2ae4cab718225f6136791df1d11814ee (diff) |
feat(tvix/eval): add method for emitting runtime warnings r/5049
This lets the VM emit warnings when it encounters situations that should only be warned about at runtime. For starters, this is used to pass through compilation warnings that come up when `import` is used. Change-Id: I0c4bc8c534d699999887c430d93629fadfa662c4 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6868 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/eval/src/vm.rs')
-rw-r--r-- | tvix/eval/src/vm.rs | 36 |
1 files changed, 34 insertions, 2 deletions
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, + }) } |