From 19fc202e1aad16a80a415ec48baaec0fa0d076a0 Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Thu, 21 Mar 2019 13:03:51 +0000 Subject: [PATCH] Classmethod/staticmethod - rewrite using structs and new style methods. --- vm/src/obj/objclassmethod.rs | 71 +++++++++++++++++------------------ vm/src/obj/objstaticmethod.rs | 66 ++++++++++++++++---------------- 2 files changed, 68 insertions(+), 69 deletions(-) diff --git a/vm/src/obj/objclassmethod.rs b/vm/src/obj/objclassmethod.rs index c2322b183..8a1baad31 100644 --- a/vm/src/obj/objclassmethod.rs +++ b/vm/src/obj/objclassmethod.rs @@ -1,43 +1,42 @@ -use crate::function::PyFuncArgs; -use crate::pyobject::{AttributeProtocol, PyContext, PyResult, TypeProtocol}; +use super::objtype::PyClassRef; +use crate::pyobject::{PyContext, PyObjectRef, PyRef, PyResult, PyValue}; use crate::vm::VirtualMachine; +#[derive(Clone, Debug)] +pub struct PyClassMethod { + pub callable: PyObjectRef, +} +pub type PyClassMethodRef = PyRef; + +impl PyValue for PyClassMethod { + fn class(vm: &mut VirtualMachine) -> PyObjectRef { + vm.ctx.classmethod_type() + } +} + +impl PyClassMethodRef { + fn new( + cls: PyClassRef, + callable: PyObjectRef, + vm: &mut VirtualMachine, + ) -> PyResult { + PyClassMethod { + callable: callable.clone(), + } + .into_ref_with_type(vm, cls) + } + + fn get(self, _inst: PyObjectRef, owner: PyObjectRef, vm: &mut VirtualMachine) -> PyResult { + Ok(vm + .ctx + .new_bound_method(self.callable.clone(), owner.clone())) + } +} + pub fn init(context: &PyContext) { let classmethod_type = &context.classmethod_type; extend_class!(context, classmethod_type, { - "__get__" => context.new_rustfunc(classmethod_get), - "__new__" => context.new_rustfunc(classmethod_new) + "__get__" => context.new_rustfunc(PyClassMethodRef::get), + "__new__" => context.new_rustfunc(PyClassMethodRef::new) }); } - -fn classmethod_get(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - trace!("classmethod.__get__ {:?}", args.args); - arg_check!( - vm, - args, - required = [ - (cls, Some(vm.ctx.classmethod_type())), - (_inst, None), - (owner, None) - ] - ); - match cls.get_attr("function") { - Some(function) => { - let py_obj = owner.clone(); - let py_method = vm.ctx.new_bound_method(function, py_obj); - Ok(py_method) - } - None => Err(vm.new_attribute_error( - "Attribute Error: classmethod must have 'function' attribute".to_string(), - )), - } -} - -fn classmethod_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - trace!("classmethod.__new__ {:?}", args.args); - arg_check!(vm, args, required = [(cls, None), (callable, None)]); - - let py_obj = vm.ctx.new_instance(cls.clone(), None); - vm.ctx.set_attr(&py_obj, "function", callable.clone()); - Ok(py_obj) -} diff --git a/vm/src/obj/objstaticmethod.rs b/vm/src/obj/objstaticmethod.rs index 9d1a96ed2..78307bcc3 100644 --- a/vm/src/obj/objstaticmethod.rs +++ b/vm/src/obj/objstaticmethod.rs @@ -1,40 +1,40 @@ -use crate::function::PyFuncArgs; -use crate::pyobject::{AttributeProtocol, PyContext, PyResult, TypeProtocol}; +use super::objtype::PyClassRef; +use crate::pyobject::{PyContext, PyObjectRef, PyRef, PyResult, PyValue}; use crate::vm::VirtualMachine; +#[derive(Clone, Debug)] +pub struct PyStaticMethod { + pub callable: PyObjectRef, +} +pub type PyStaticMethodRef = PyRef; + +impl PyValue for PyStaticMethod { + fn class(vm: &mut VirtualMachine) -> PyObjectRef { + vm.ctx.staticmethod_type() + } +} + +impl PyStaticMethodRef { + fn new( + cls: PyClassRef, + callable: PyObjectRef, + vm: &mut VirtualMachine, + ) -> PyResult { + PyStaticMethod { + callable: callable.clone(), + } + .into_ref_with_type(vm, cls) + } + + fn get(self, _inst: PyObjectRef, _owner: PyObjectRef, _vm: &mut VirtualMachine) -> PyResult { + Ok(self.callable.clone()) + } +} + pub fn init(context: &PyContext) { let staticmethod_type = &context.staticmethod_type; extend_class!(context, staticmethod_type, { - "__get__" => context.new_rustfunc(staticmethod_get), - "__new__" => context.new_rustfunc(staticmethod_new), + "__get__" => context.new_rustfunc(PyStaticMethodRef::get), + "__new__" => context.new_rustfunc(PyStaticMethodRef::new), }); } - -// `staticmethod` methods. -fn staticmethod_get(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - trace!("staticmethod.__get__ {:?}", args.args); - arg_check!( - vm, - args, - required = [ - (cls, Some(vm.ctx.staticmethod_type())), - (_inst, None), - (_owner, None) - ] - ); - match cls.get_attr("function") { - Some(function) => Ok(function), - None => Err(vm.new_attribute_error( - "Attribute Error: staticmethod must have 'function' attribute".to_string(), - )), - } -} - -fn staticmethod_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - trace!("staticmethod.__new__ {:?}", args.args); - arg_check!(vm, args, required = [(cls, None), (callable, None)]); - - let py_obj = vm.ctx.new_instance(cls.clone(), None); - vm.ctx.set_attr(&py_obj, "function", callable.clone()); - Ok(py_obj) -}