use fix_builtins::BuiltinId; use fix_common::StringId; use num_enum::TryFromPrimitive; use crate::value::{NixString, StrictValue}; use crate::{BytecodeReader, PrimOp, Step, Value, VmRuntimeCtx}; impl<'gc> crate::Vm<'gc> { #[inline(always)] pub(crate) fn op_load_builtins(&mut self) -> Step { self.push(self.builtins); Step::Continue(()) } #[inline(always)] pub(crate) fn op_load_builtin(&mut self, reader: &mut BytecodeReader<'_>) -> Step { let Ok(id) = BuiltinId::try_from_primitive(reader.read_u8()) .map_err(|err| panic!("unknown builtin id: {}", err.number)); self.push(Value::new_inline(PrimOp { id, arity: fix_builtins::BUILTINS[id as usize].1, dispatch_ip: id.entry_phase().ip(), })); Step::Continue(()) } #[inline(always)] pub(crate) fn op_load_repl_binding(&mut self, reader: &mut BytecodeReader<'_>) -> Step { let _name = reader.read_string_id(); todo!("LoadReplBinding"); } #[inline(always)] pub(crate) fn op_load_scoped_binding(&mut self, reader: &mut BytecodeReader<'_>) -> Step { let _name = reader.read_string_id(); todo!("LoadScopedBinding"); } #[inline(always)] pub(crate) fn op_coerce_to_string( &mut self, reader: &mut BytecodeReader<'_>, mc: &gc_arena::Mutation<'gc>, ) -> Step { let val = self.force_and_retry::(reader, mc)?; if val.is::() || val.is::() { self.push(val.relax()); } else { todo!("coerce other types to string: {:?}", val.ty()); } Step::Continue(()) } #[inline(always)] pub(crate) fn op_concat_strings( &mut self, ctx: &mut impl VmRuntimeCtx, reader: &mut BytecodeReader<'_>, _mc: &gc_arena::Mutation<'gc>, ) -> Step { use crate::VmRuntimeCtxExt; let count = reader.read_u16() as usize; let _force_string = reader.read_u8() != 0; let mut total_len = 0; for i in 0..count { let val = self.peek_forced(count - 1 - i); let s = ctx.get_string(val).expect("coerced"); total_len += s.len(); } let mut result = String::with_capacity(total_len); for i in 0..count { let val = self.peek_forced(count - 1 - i); let s = ctx.get_string(val).expect("coerced"); result.push_str(s); } self.stack.truncate(self.stack.len() - count); let sid = ctx.intern_string(result); self.push(Value::new_inline(sid)); Step::Continue(()) } #[inline(always)] pub(crate) fn op_resolve_path(&mut self, _ctx: &mut impl VmRuntimeCtx) -> Step { todo!("implement ResolvePath"); } }