@@ -5,6 +5,7 @@ use crate::common::hash::PyHash;
55use crate :: function:: { IntoPyNativeFunc , OptionalArg , PyFuncArgs , PyNativeFunc } ;
66use crate :: pyobject:: {
77 IdProtocol , PyComparisonValue , PyObjectRef , PyRef , PyResult , PyValue , TryFromObject ,
8+ TypeProtocol ,
89} ;
910use crate :: VirtualMachine ;
1011use crossbeam_utils:: atomic:: AtomicCell ;
@@ -40,18 +41,22 @@ impl Default for PyTpFlags {
4041 }
4142}
4243
44+ type GenericFunc = fn ( & VirtualMachine , PyFuncArgs ) -> PyResult ;
45+ type DescrGetFunc =
46+ fn ( & VirtualMachine , PyObjectRef , Option < PyObjectRef > , OptionalArg < PyObjectRef > ) -> PyResult ;
47+ type HashFunc = Box < py_dyn_fn ! ( dyn Fn ( PyObjectRef , & VirtualMachine ) -> PyResult <PyHash >) > ;
48+
4349#[ derive( Default ) ]
4450pub struct PyClassSlots {
4551 pub flags : PyTpFlags ,
4652 pub name : PyRwLock < Option < String > > , // tp_name, not class name
4753 pub new : Option < PyNativeFunc > ,
48- pub call : AtomicCell < Option < fn ( & VirtualMachine , PyFuncArgs ) -> PyResult > > ,
49- pub descr_get : Option < PyDescrGetFunc > ,
54+ pub call : AtomicCell < Option < GenericFunc > > ,
55+ pub descr_get : AtomicCell < Option < DescrGetFunc > > ,
5056 pub hash : Option < HashFunc > ,
5157 pub cmp : Option < CmpFunc > ,
5258}
5359
54- type HashFunc = Box < py_dyn_fn ! ( dyn Fn ( PyObjectRef , & VirtualMachine ) -> PyResult <PyHash >) > ;
5560type CmpFunc = Box <
5661 py_dyn_fn ! (
5762 dyn Fn (
@@ -75,10 +80,14 @@ impl PyClassSlots {
7580 pub ( crate ) fn update_slot_func ( & self , name : & str ) {
7681 match name {
7782 "__call__" => {
78- self . call
79- . store ( Some ( |vm : & VirtualMachine , args : PyFuncArgs | -> PyResult {
80- IntoPyNativeFunc :: call ( & call_magic_call, vm, args)
81- } as _ ) )
83+ let func: GenericFunc =
84+ |vm, args| { IntoPyNativeFunc :: call ( & call_magic_call, vm, args) } as _ ;
85+ self . call . store ( Some ( func) )
86+ }
87+ "__get__" => {
88+ let func: DescrGetFunc =
89+ |vm, zelf, obj, cls| { call_magic_descr_get ( vm, zelf, obj, cls) } as _ ;
90+ self . descr_get . store ( Some ( func) )
8291 }
8392 _ => ( ) ,
8493 }
@@ -98,17 +107,37 @@ pub trait SlotCall: PyValue {
98107 fn call ( zelf : PyRef < Self > , args : PyFuncArgs , vm : & VirtualMachine ) -> PyResult ;
99108}
100109
101- fn call_magic_call ( zelf : PyObjectRef , args : PyFuncArgs , vm : & VirtualMachine ) -> PyResult {
102- use crate :: obj:: objstr:: PyString ;
103- use crate :: pyobject:: IntoPyRef ;
110+ #[ inline]
111+ fn get_class_magic ( zelf : & PyObjectRef , name : & str ) -> PyObjectRef {
112+ zelf. get_class_attr ( name) . unwrap ( )
113+ // let cls = zelf.lease_class();
114+ // let attrs = cls.attributes.read();
115+ // let attr = attrs.get(name);
116+ // attr.unwrap().clone()
117+ }
104118
105- let magic_call = vm. generic_getattribute ( zelf, PyString :: from ( "__call__" ) . into_pyref ( vm) ) ?;
106- vm. invoke ( & magic_call, args)
119+ fn call_magic_call ( zelf : PyObjectRef , args : PyFuncArgs , vm : & VirtualMachine ) -> PyResult {
120+ let magic = get_class_magic ( & zelf, "__call__" ) ;
121+ let magic = vm. call_if_get_descriptor ( magic, zelf. clone ( ) ) ?;
122+ args. insert ( zelf) ;
123+ vm. invoke ( & magic, args)
124+ }
107125
108- // use crate::pyobject::TypeProtocol;
109- // let magic_call = zelf.get_class_attr("__call__").unwrap();
110- // args.insert( zelf);
111- // vm.invoke(&magic_call, args)
126+ fn call_magic_descr_get (
127+ vm : & VirtualMachine ,
128+ zelf : PyObjectRef ,
129+ obj : Option < PyObjectRef > ,
130+ cls : OptionalArg < PyObjectRef > ,
131+ ) -> PyResult {
132+ let magic = get_class_magic ( & zelf, "__get__" ) ;
133+ vm. invoke (
134+ & magic,
135+ vec ! [
136+ zelf,
137+ vm. unwrap_or_none( obj) ,
138+ vm. unwrap_or_none( cls. into_option( ) ) ,
139+ ] ,
140+ )
112141}
113142
114143pub type PyDescrGetFunc = Box <
0 commit comments