1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
use std::fmt; use crate::function::{OptionalArg, PyFuncArgs, PyNativeFunc}; use crate::obj::objtype::PyClassRef; use crate::pyobject::{ IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::slots::{SlotCall, SlotDescriptor}; use crate::vm::VirtualMachine; #[pyclass] pub struct PyBuiltinFunction { value: PyNativeFunc, } impl PyValue for PyBuiltinFunction { fn class(vm: &VirtualMachine) -> PyClassRef { vm.ctx.builtin_function_or_method_type() } } impl fmt::Debug for PyBuiltinFunction { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "builtin function") } } impl PyBuiltinFunction { pub fn new(value: PyNativeFunc) -> Self { Self { value } } pub fn as_func(&self) -> &PyNativeFunc { &self.value } } impl SlotCall for PyBuiltinFunction { fn call(&self, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult { (self.value)(vm, args) } } #[pyimpl(with(SlotCall))] impl PyBuiltinFunction {} #[pyclass] pub struct PyBuiltinMethod { function: PyBuiltinFunction, } impl PyValue for PyBuiltinMethod { fn class(vm: &VirtualMachine) -> PyClassRef { vm.ctx.method_descriptor_type() } } impl fmt::Debug for PyBuiltinMethod { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "method descriptor") } } impl PyBuiltinMethod { pub fn new(value: PyNativeFunc) -> Self { Self { function: PyBuiltinFunction { value }, } } pub fn as_func(&self) -> &PyNativeFunc { &self.function.value } } impl SlotDescriptor for PyBuiltinMethod { fn descr_get( vm: &VirtualMachine, zelf: PyObjectRef, obj: Option<PyObjectRef>, cls: OptionalArg<PyObjectRef>, ) -> PyResult { let (zelf, obj) = match Self::_check(zelf, obj, vm) { Ok(obj) => obj, Err(result) => return result, }; if obj.is(&vm.get_none()) && !Self::_cls_is(&cls, &obj.class()) { Ok(zelf.into_object()) } else { Ok(vm.ctx.new_bound_method(zelf.into_object(), obj)) } } } impl SlotCall for PyBuiltinMethod { fn call(&self, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult { (self.function.value)(vm, args) } } #[pyimpl(with(SlotDescriptor, SlotCall))] impl PyBuiltinMethod {} pub fn init(context: &PyContext) { PyBuiltinFunction::extend_class(context, &context.types.builtin_function_or_method_type); PyBuiltinMethod::extend_class(context, &context.types.method_descriptor_type); }