use gc_arena::{Gc, Mutation, RefLock}; use crate::{BytecodeReader, Step, ThunkState, Value}; impl<'gc> crate::Vm<'gc> { #[inline(always)] pub(crate) fn op_make_thunk( &mut self, reader: &mut BytecodeReader<'_>, mc: &Mutation<'gc>, ) -> Step { let entry_point = reader.read_u32(); let thunk = Gc::new( mc, RefLock::new(ThunkState::Pending { ip: entry_point as usize, env: self.env, with_env: self.with_env, }), ); self.push(Value::new_gc(thunk)); Step::Continue(()) } #[inline(always)] pub(crate) fn op_make_closure( &mut self, reader: &mut BytecodeReader<'_>, mc: &Mutation<'gc>, ) -> Step { let entry_point = reader.read_u32(); let n_locals = reader.read_u32(); let closure = Gc::new( mc, crate::Closure { ip: entry_point, n_locals, env: self.env, pattern: None, }, ); self.push(Value::new_gc(closure)); Step::Continue(()) } #[inline(always)] pub(crate) fn op_make_pattern_closure( &mut self, reader: &mut BytecodeReader<'_>, mc: &Mutation<'gc>, ) -> Step { let entry_point = reader.read_u32(); let n_locals = reader.read_u32(); let req_count = reader.read_u16() as usize; let opt_count = reader.read_u16() as usize; let has_ellipsis = reader.read_u8() != 0; let mut required = smallvec::SmallVec::new(); for _ in 0..req_count { required.push(reader.read_string_id()); } let mut optional = smallvec::SmallVec::new(); for _ in 0..opt_count { optional.push(reader.read_string_id()); } let total = req_count + opt_count; let mut param_spans = Vec::with_capacity(total); for _ in 0..total { let name = reader.read_string_id(); let span_id = reader.read_u32(); param_spans.push((name, span_id)); } let pattern = Gc::new( mc, crate::PatternInfo { required, optional, ellipsis: has_ellipsis, param_spans: param_spans.into_boxed_slice(), }, ); let closure = Gc::new( mc, crate::Closure { ip: entry_point, n_locals, env: self.env, pattern: Some(pattern), }, ); self.push(Value::new_gc(closure)); Step::Continue(()) } }