use crate::{obj::{names::*, prelude::*}, vm::{inst::Inst, Vm}}; use once_cell::sync::Lazy; use shredder::{GcSafeWrapper, Scan}; use std::fmt::{Debug, Formatter, self}; // // struct UserFun // #[derive(Scan)] pub struct UserFun { attrs: Attrs, // Safe because Vec doesn't need to be scanned #[shredder(unsafe_skip)] code: Vec, // Safe because this is just an interner that points to symbols, which aren't GC'd #[shredder(unsafe_skip)] locals: Locals, } impl UserFun { pub fn code(&self) -> &Vec { &self.code } pub fn locals(&self) -> &Locals { &self.locals } } impl_obj!(UserFun, attrs); impl Debug for UserFun { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { fmt.debug_struct("UserFun") .field("attrs", &self.attrs) .field("code", &self.code) .field("locals", &self.locals) .finish() } } // // struct NativeFun // #[derive(Scan)] pub struct NativeFun { #[shredder(skip)] fun: GcSafeWrapper>, attrs: Attrs, } // // impl NativeFun // impl NativeFun { pub fn new(fun: Box) -> ObjRef { let obj_ref = ObjRef::new(Self { fun: GcSafeWrapper::new(fun), attrs: Default::default(), }); { write_obj!(let obj = obj_ref); obj.set_attr(*CALL_MEMBER_SYM, obj_ref.clone()); obj.set_attr(*GET_ATTR_MEMBER_SYM, GET_ATTR_MEMBER_FUN.clone()); } obj_ref } pub fn call(&self, vm: &mut Vm) { (self.fun)(vm) } } // // impl Debug for NativeFun // impl Debug for NativeFun { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { fmt.debug_struct("NativeFun") .field("fun", &format!("(function at {:x})", &self.fun as *const _ as usize)) .field("attrs", &self.attrs) .finish() } } impl_obj!(NativeFun, attrs); // // Native function defs // // __access__ is what the "dot" operator calls // __get_attr__ *should* always bypass the __access__ function and get an attribute directly pub static GET_ATTR_MEMBER_FUN: Lazy> = Lazy::new(|| { NativeFun::new(Box::new(|_vm| { /* * TODO - need SymObj or something like that, which can be used as an ObjRef - since that's * all we'll have access to at runtime anyway let sym_ref = vm.pop(); let obj_ref = vm.pop(); obj_ref.access() */ todo!("__get_attr__ function") })) });