diff options
Diffstat (limited to 'tvix/eval/src/vm')
-rw-r--r-- | tvix/eval/src/vm/generators.rs | 64 | ||||
-rw-r--r-- | tvix/eval/src/vm/macros.rs | 2 | ||||
-rw-r--r-- | tvix/eval/src/vm/mod.rs | 74 |
3 files changed, 63 insertions, 77 deletions
diff --git a/tvix/eval/src/vm/generators.rs b/tvix/eval/src/vm/generators.rs index dbf7703bf002..36b837dbee6e 100644 --- a/tvix/eval/src/vm/generators.rs +++ b/tvix/eval/src/vm/generators.rs @@ -81,7 +81,7 @@ pub enum VMRequest { EnterLambda { lambda: Rc<Lambda>, upvalues: Rc<Upvalues>, - light_span: LightSpan, + span: Span, }, /// Emit a runtime warning (already containing a span) through the VM. @@ -198,7 +198,7 @@ pub enum VMResponse { Directory(Vec<(bytes::Bytes, FileType)>), /// VM response with a span to use at the current point. - Span(LightSpan), + Span(Span), /// [std::io::Reader] produced by the VM in response to some IO operation. Reader(Box<dyn std::io::Read>), @@ -234,7 +234,7 @@ where { /// Helper function to re-enqueue the current generator while it /// is awaiting a value. - fn reenqueue_generator(&mut self, name: &'static str, span: LightSpan, generator: Generator) { + fn reenqueue_generator(&mut self, name: &'static str, span: Span, generator: Generator) { self.frames.push(Frame::Generator { name, generator, @@ -244,7 +244,7 @@ where } /// Helper function to enqueue a new generator. - pub(super) fn enqueue_generator<F, G>(&mut self, name: &'static str, span: LightSpan, gen: G) + pub(super) fn enqueue_generator<F, G>(&mut self, name: &'static str, span: Span, gen: G) where F: Future<Output = Result<Value, ErrorKind>> + 'static, G: FnOnce(GenCo) -> F, @@ -265,7 +265,7 @@ where pub(crate) fn run_generator( &mut self, name: &'static str, - span: LightSpan, + span: Span, frame_id: usize, state: GeneratorState, mut generator: Generator, @@ -302,8 +302,8 @@ where // this function prepares the frame stack and yields // back to the outer VM loop. VMRequest::ForceValue(value) => { - self.reenqueue_generator(name, span.clone(), generator); - self.enqueue_generator("force", span.clone(), |co| { + self.reenqueue_generator(name, span, generator); + self.enqueue_generator("force", span, |co| { value.force_owned_genco(co, span) }); return Ok(false); @@ -311,8 +311,8 @@ where // Generator has requested a deep-force. VMRequest::DeepForceValue(value) => { - self.reenqueue_generator(name, span.clone(), generator); - self.enqueue_generator("deep_force", span.clone(), |co| { + self.reenqueue_generator(name, span, generator); + self.enqueue_generator("deep_force", span, |co| { value.deep_force(co, span) }); return Ok(false); @@ -322,10 +322,10 @@ where // Logic is similar to `ForceValue`, except with the // value being taken from that stack. VMRequest::WithValue(idx) => { - self.reenqueue_generator(name, span.clone(), generator); + self.reenqueue_generator(name, span, generator); let value = self.stack[self.with_stack[idx]].clone(); - self.enqueue_generator("force", span.clone(), |co| { + self.enqueue_generator("force", span, |co| { value.force_owned_genco(co, span) }); @@ -336,13 +336,13 @@ where // with-stack. Logic is same as above, except for the // value being from that stack. VMRequest::CapturedWithValue(idx) => { - self.reenqueue_generator(name, span.clone(), generator); + self.reenqueue_generator(name, span, generator); let call_frame = self.last_call_frame() .expect("Tvix bug: generator requested captured with-value, but there is no call frame"); let value = call_frame.upvalues.with_stack().unwrap()[idx].clone(); - self.enqueue_generator("force", span.clone(), |co| { + self.enqueue_generator("force", span, |co| { value.force_owned_genco(co, span) }); @@ -351,23 +351,23 @@ where VMRequest::NixEquality(values, ptr_eq) => { let values = *values; - self.reenqueue_generator(name, span.clone(), generator); - self.enqueue_generator("nix_eq", span.clone(), |co| { + self.reenqueue_generator(name, span, generator); + self.enqueue_generator("nix_eq", span, |co| { values.0.nix_eq_owned_genco(values.1, co, ptr_eq, span) }); return Ok(false); } VMRequest::StringCoerce(val, kind) => { - self.reenqueue_generator(name, span.clone(), generator); - self.enqueue_generator("coerce_to_string", span.clone(), |co| { + self.reenqueue_generator(name, span, generator); + self.enqueue_generator("coerce_to_string", span, |co| { val.coerce_to_string(co, kind, span) }); return Ok(false); } VMRequest::Call(callable) => { - self.reenqueue_generator(name, span.clone(), generator); + self.reenqueue_generator(name, span, generator); self.call_value(span, None, callable)?; return Ok(false); } @@ -375,12 +375,12 @@ where VMRequest::EnterLambda { lambda, upvalues, - light_span, + span, } => { self.reenqueue_generator(name, span, generator); self.frames.push(Frame::CallFrame { - span: light_span, + span, call_frame: CallFrame { lambda, upvalues, @@ -424,7 +424,7 @@ where path: Some(path), error: e.into(), }) - .with_span(&span, self)?; + .with_span(span, self)?; message = VMResponse::Path(imported); } @@ -438,7 +438,7 @@ where path: Some(path), error: e.into(), }) - .with_span(&span, self)?; + .with_span(span, self)?; message = VMResponse::Reader(reader) } @@ -453,7 +453,7 @@ where error: e.into(), }) .map(Value::Bool) - .with_span(&span, self)?; + .with_span(span, self)?; message = VMResponse::Value(exists); } @@ -467,31 +467,31 @@ where path: Some(path), error: e.into(), }) - .with_span(&span, self)?; + .with_span(span, self)?; message = VMResponse::Directory(dir); } VMRequest::Span => { - message = VMResponse::Span(self.reasonable_light_span()); + message = VMResponse::Span(self.reasonable_span); } VMRequest::TryForce(value) => { self.try_eval_frames.push(frame_id); - self.reenqueue_generator(name, span.clone(), generator); + self.reenqueue_generator(name, span, generator); debug_assert!( self.frames.len() == frame_id + 1, "generator should be reenqueued with the same frame ID" ); - self.enqueue_generator("force", span.clone(), |co| { + self.enqueue_generator("force", span, |co| { value.force_owned_genco(co, span) }); return Ok(false); } VMRequest::ToJson(value) => { - self.reenqueue_generator(name, span.clone(), generator); + self.reenqueue_generator(name, span, generator); self.enqueue_generator("to_json", span, |co| { value.into_contextful_json_generator(co) }); @@ -503,7 +503,7 @@ where // Generator has completed, and its result value should // be left on the stack. genawaiter::GeneratorState::Complete(result) => { - let value = result.with_span(&span, self)?; + let value = result.with_span(span, self)?; self.stack.push(value); return Ok(true); } @@ -683,12 +683,12 @@ pub(crate) async fn request_enter_lambda( co: &GenCo, lambda: Rc<Lambda>, upvalues: Rc<Upvalues>, - light_span: LightSpan, + span: Span, ) -> Value { let msg = VMRequest::EnterLambda { lambda, upvalues, - light_span, + span, }; match co.yield_(msg).await { @@ -767,7 +767,7 @@ pub(crate) async fn request_read_dir(co: &GenCo, path: PathBuf) -> Vec<(bytes::B } } -pub(crate) async fn request_span(co: &GenCo) -> LightSpan { +pub(crate) async fn request_span(co: &GenCo) -> Span { match co.yield_(VMRequest::Span).await { VMResponse::Span(span) => span, msg => panic!( diff --git a/tvix/eval/src/vm/macros.rs b/tvix/eval/src/vm/macros.rs index d8a09706ab9c..f9c084d41f91 100644 --- a/tvix/eval/src/vm/macros.rs +++ b/tvix/eval/src/vm/macros.rs @@ -49,7 +49,7 @@ macro_rules! cmp_op { } } - let gen_span = $frame.current_light_span(); + let gen_span = $frame.current_span(); $vm.push_call_frame($span, $frame); $vm.enqueue_generator("compare", gen_span, |co| compare(a, b, co)); return Ok(false); diff --git a/tvix/eval/src/vm/mod.rs b/tvix/eval/src/vm/mod.rs index 48dcdfc8df47..65117b79a0bc 100644 --- a/tvix/eval/src/vm/mod.rs +++ b/tvix/eval/src/vm/mod.rs @@ -28,7 +28,6 @@ use crate::{ nix_search_path::NixSearchPath, observer::RuntimeObserver, opcode::{CodeIdx, Count, JumpOffset, OpCode, StackIdx, UpvalueIdx}, - spans::LightSpan, upvalues::Upvalues, value::{ Builtin, BuiltinResult, Closure, CoercionKind, Lambda, NixAttrs, NixContext, NixList, @@ -51,7 +50,7 @@ trait GetSpan { impl<'o, IO> GetSpan for &VM<'o, IO> { fn get_span(self) -> Span { - self.reasonable_span.span() + self.reasonable_span } } @@ -61,9 +60,9 @@ impl GetSpan for &CallFrame { } } -impl GetSpan for &LightSpan { +impl GetSpan for &Span { fn get_span(self) -> Span { - self.span() + *self } } @@ -94,7 +93,7 @@ impl<T, S: GetSpan, IO> WithSpan<T, S, IO> for Result<T, ErrorKind> { Frame::CallFrame { span, .. } => { error = Error::new( ErrorKind::BytecodeError(Box::new(error)), - span.span(), + *span, vm.source.clone(), ); } @@ -104,7 +103,7 @@ impl<T, S: GetSpan, IO> WithSpan<T, S, IO> for Result<T, ErrorKind> { err: Box::new(error), gen_type: name, }, - span.span(), + *span, vm.source.clone(), ); } @@ -163,13 +162,6 @@ impl CallFrame { pub fn current_span(&self) -> Span { self.chunk().get_span(self.ip - 1) } - - /// Returns the information needed to calculate the current span, - /// but without performing that calculation. - // TODO: why pub? - pub(crate) fn current_light_span(&self) -> LightSpan { - LightSpan::new_actual(self.current_span()) - } } /// A frame represents an execution state of the VM. The VM has a stack of @@ -187,7 +179,7 @@ enum Frame { call_frame: CallFrame, /// Span from which the call frame was launched. - span: LightSpan, + span: Span, }, /// Generator represents a frame that can yield further @@ -201,7 +193,7 @@ enum Frame { name: &'static str, /// Span from which the generator was launched. - span: LightSpan, + span: Span, state: GeneratorState, @@ -211,9 +203,9 @@ enum Frame { } impl Frame { - pub fn span(&self) -> LightSpan { + pub fn span(&self) -> Span { match self { - Frame::CallFrame { span, .. } | Frame::Generator { span, .. } => span.clone(), + Frame::CallFrame { span, .. } | Frame::Generator { span, .. } => *span, } } } @@ -309,7 +301,7 @@ struct VM<'o, IO> { /// /// The VM should update this whenever control flow changes take place (i.e. /// entering or exiting a frame to yield control somewhere). - reasonable_span: LightSpan, + reasonable_span: Span, /// This field is responsible for handling `builtins.tryEval`. When that /// builtin is encountered, it sends a special message to the VM which @@ -343,7 +335,7 @@ where observer: &'o mut dyn RuntimeObserver, source: SourceCode, globals: Rc<GlobalsMap>, - reasonable_span: LightSpan, + reasonable_span: Span, ) -> Self { Self { nix_search_path, @@ -362,7 +354,7 @@ where } /// Push a call frame onto the frame stack. - fn push_call_frame(&mut self, span: LightSpan, call_frame: CallFrame) { + fn push_call_frame(&mut self, span: Span, call_frame: CallFrame) { self.frames.push(Frame::CallFrame { span, call_frame }) } @@ -444,7 +436,7 @@ where /// /// The return value indicates whether the bytecode has been executed to /// completion, or whether it has been suspended in favour of a generator. - fn execute_bytecode(&mut self, span: LightSpan, mut frame: CallFrame) -> EvalResult<bool> { + fn execute_bytecode(&mut self, span: Span, mut frame: CallFrame) -> EvalResult<bool> { loop { let op = frame.inc_ip(); self.observer.observe_execute_op(frame.ip, &op, &self.stack); @@ -464,7 +456,7 @@ where ); Thunk::new_closure(blueprint) } else { - Thunk::new_suspended(blueprint, frame.current_light_span()) + Thunk::new_suspended(blueprint, frame.current_span()) }; let upvalues = thunk.upvalues_mut(); self.stack.push(Value::Thunk(thunk.clone())); @@ -484,10 +476,10 @@ where _ => unreachable!(), }; - let gen_span = frame.current_light_span(); + let gen_span = frame.current_span(); self.push_call_frame(span, frame); - self.enqueue_generator("force", gen_span.clone(), |co| { + self.enqueue_generator("force", gen_span, |co| { Thunk::force(thunk, co, gen_span) }); @@ -515,7 +507,7 @@ where OpCode::OpCall => { let callable = self.stack_pop(); - self.call_value(frame.current_light_span(), Some((span, frame)), callable)?; + self.call_value(frame.current_span(), Some((span, frame)), callable)?; // exit this loop and let the outer loop enter the new call return Ok(true); @@ -640,9 +632,9 @@ where OpCode::OpEqual => lifted_pop! { self(b, a) => { - let gen_span = frame.current_light_span(); + let gen_span = frame.current_span(); self.push_call_frame(span, frame); - self.enqueue_generator("nix_eq", gen_span.clone(), |co| { + self.enqueue_generator("nix_eq", gen_span, |co| { a.nix_eq_owned_genco(b, co, PointerEquality::ForbidAll, gen_span) }); return Ok(false); @@ -739,7 +731,7 @@ where let ident = self.stack_pop().to_str().with_span(&frame, self)?; // Re-enqueue this frame. - let op_span = frame.current_light_span(); + let op_span = frame.current_span(); self.push_call_frame(span, frame); // Construct a generator frame doing the lookup in constant @@ -770,10 +762,10 @@ where OpCode::OpCoerceToString(kind) => { let value = self.stack_pop(); - let gen_span = frame.current_light_span(); + let gen_span = frame.current_span(); self.push_call_frame(span, frame); - self.enqueue_generator("coerce_to_string", gen_span.clone(), |co| { + self.enqueue_generator("coerce_to_string", gen_span, |co| { value.coerce_to_string(co, kind, gen_span) }); @@ -808,7 +800,7 @@ where OpCode::OpAdd => lifted_pop! { self(b, a) => { - let gen_span = frame.current_light_span(); + let gen_span = frame.current_span(); self.push_call_frame(span, frame); // OpAdd can add not just numbers, but also string-like @@ -1004,12 +996,6 @@ where Ok(()) } - /// Returns a reasonable light span for the current situation that the VM is - /// in. - pub fn reasonable_light_span(&self) -> LightSpan { - self.reasonable_span.clone() - } - /// Apply an argument from the stack to a builtin, and attempt to call it. /// /// All calls are tail-calls in Tvix, as every function application is a @@ -1017,7 +1003,7 @@ where /// /// Due to this, once control flow exits this function, the generator will /// automatically be run by the VM. - fn call_builtin(&mut self, span: LightSpan, mut builtin: Builtin) -> EvalResult<()> { + fn call_builtin(&mut self, span: Span, mut builtin: Builtin) -> EvalResult<()> { let builtin_name = builtin.name(); self.observer.observe_enter_builtin(builtin_name); @@ -1041,8 +1027,8 @@ where fn call_value( &mut self, - span: LightSpan, - parent: Option<(LightSpan, CallFrame)>, + span: Span, + parent: Option<(Span, CallFrame)>, callable: Value, ) -> EvalResult<()> { match callable { @@ -1098,7 +1084,7 @@ where Ok(()) } - v => Err(ErrorKind::NotCallable(v.type_of())).with_span(&span, self), + v => Err(ErrorKind::NotCallable(v.type_of())).with_span(span, self), } } @@ -1345,17 +1331,17 @@ where observer, source, globals, - root_span.into(), + root_span, ); // When evaluating strictly, synthesise a frame that will instruct // the VM to deep-force the final value before returning it. if strict { - vm.enqueue_generator("final_deep_force", root_span.into(), final_deep_force); + vm.enqueue_generator("final_deep_force", root_span, final_deep_force); } vm.frames.push(Frame::CallFrame { - span: root_span.into(), + span: root_span, call_frame: CallFrame { lambda, upvalues: Rc::new(Upvalues::with_capacity(0)), |