use crate::{obj::{reserved::*, prelude::*}, vm::{inst::Inst, Vm}}; use once_cell::sync::Lazy; use shredder::{GcSafeWrapper, Scan}; use std::fmt::{Debug, Formatter, self}; #[derive(Debug, Scan)] pub struct Method { vtable: Vtable, attrs: Attrs, } impl Method { pub fn new(this: ObjRef, func: ObjRef) -> Self { Self { vtable: Default::default(), attrs: attrs! { SELF_MEMBER_NAME.sym => this, FUNC_MEMBER_NAME.sym => func, } } } } impl_obj!(Method); pub static CALL_METHOD_WRAPPER_FUN: Lazy> = Lazy::new(|| { NativeFun::new_obj(Box::new(|_vm, _fun, _args| { todo!("__call__ function") })) }); // // struct UserFun // pub type UserFunRef = ObjRef; #[derive(Scan)] pub struct UserFun { vtable: Vtable, 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: Names, } impl UserFun { pub fn code(&self) -> &Vec { &self.code } pub fn locals(&self) -> &Names { &self.locals } } impl_obj!(UserFun); 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 // pub type NativeFunPtr = Box) + Send + Sync>; #[derive(Scan)] pub struct NativeFun { vtable: Vtable, attrs: Attrs, #[shredder(skip)] fun: GcSafeWrapper, } // // impl NativeFun // impl NativeFun { pub fn new_obj(fun: NativeFunPtr) -> ObjRef { ObjRef::new(Self { // TODO : vtable for NativeFun vtable: Default::default(), attrs: Default::default(), fun: GcSafeWrapper::new(fun), }) } } // // 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); // // 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_obj(Box::new(|_vm, _fun, _args| { /* let sym_ref = vm.pop(); let obj_ref = vm.pop(); obj_ref.access() */ todo!("__get_attr__ function") })) });