From c00d368448e6afbf741d22dacb34acf7763187f1 Mon Sep 17 00:00:00 2001 From: Windel Bouwman Date: Mon, 11 Mar 2019 19:38:26 +0100 Subject: [PATCH] Move classmethod and staticmethod to own files. Also use extend_class more. --- vm/src/obj/mod.rs | 2 + vm/src/obj/objclassmethod.rs | 42 +++++++++++++ vm/src/obj/objfilter.rs | 12 ++-- vm/src/obj/objfunction.rs | 108 +++------------------------------- vm/src/obj/objstaticmethod.rs | 39 ++++++++++++ vm/src/obj/objzip.rs | 6 +- vm/src/pyobject.rs | 4 ++ 7 files changed, 104 insertions(+), 109 deletions(-) create mode 100644 vm/src/obj/objclassmethod.rs create mode 100644 vm/src/obj/objstaticmethod.rs diff --git a/vm/src/obj/mod.rs b/vm/src/obj/mod.rs index f32683fd2..0419d827f 100644 --- a/vm/src/obj/mod.rs +++ b/vm/src/obj/mod.rs @@ -4,6 +4,7 @@ pub mod objbool; pub mod objbuiltinfunc; pub mod objbytearray; pub mod objbytes; +pub mod objclassmethod; pub mod objcode; pub mod objcomplex; pub mod objdict; @@ -27,6 +28,7 @@ pub mod objrange; pub mod objsequence; pub mod objset; pub mod objslice; +pub mod objstaticmethod; pub mod objstr; pub mod objsuper; pub mod objtuple; diff --git a/vm/src/obj/objclassmethod.rs b/vm/src/obj/objclassmethod.rs new file mode 100644 index 000000000..9c8ea3f8f --- /dev/null +++ b/vm/src/obj/objclassmethod.rs @@ -0,0 +1,42 @@ +use crate::pyobject::{AttributeProtocol, PyContext, PyFuncArgs, PyResult, TypeProtocol}; +use crate::vm::VirtualMachine; + +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) + }); +} + +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/objfilter.rs b/vm/src/obj/objfilter.rs index 94cd15bb8..d39373739 100644 --- a/vm/src/obj/objfilter.rs +++ b/vm/src/obj/objfilter.rs @@ -70,11 +70,9 @@ pub fn init(context: &PyContext) { Return an iterator yielding those items of iterable for which function(item)\n\ is true. If function is None, return the items that are true."; - context.set_attr(&filter_type, "__new__", context.new_rustfunc(filter_new)); - context.set_attr( - &filter_type, - "__doc__", - context.new_str(filter_doc.to_string()), - ); - context.set_attr(&filter_type, "__next__", context.new_rustfunc(filter_next)); + extend_class!(context, filter_type, { + "__new__" => context.new_rustfunc(filter_new), + "__doc__" => context.new_str(filter_doc.to_string()), + "__next__" => context.new_rustfunc(filter_next) + }); } diff --git a/vm/src/obj/objfunction.rs b/vm/src/obj/objfunction.rs index ac860857a..f0b551933 100644 --- a/vm/src/obj/objfunction.rs +++ b/vm/src/obj/objfunction.rs @@ -1,7 +1,6 @@ use crate::frame::Scope; use crate::pyobject::{ - AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, PyValue, - TypeProtocol, + IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; @@ -50,44 +49,15 @@ impl PyValue for PyMethod { pub fn init(context: &PyContext) { let function_type = &context.function_type; - context.set_attr(&function_type, "__get__", context.new_rustfunc(bind_method)); - - context.set_attr( - &function_type, - "__code__", - context.new_property(function_code), - ); + extend_class!(context, function_type, { + "__get__" => context.new_rustfunc(bind_method), + "__code__" => context.new_property(function_code) + }); let builtin_function_or_method_type = &context.builtin_function_or_method_type; - context.set_attr( - &builtin_function_or_method_type, - "__get__", - context.new_rustfunc(bind_method), - ); - - let classmethod_type = &context.classmethod_type; - context.set_attr( - &classmethod_type, - "__get__", - context.new_rustfunc(classmethod_get), - ); - context.set_attr( - &classmethod_type, - "__new__", - context.new_rustfunc(classmethod_new), - ); - - let staticmethod_type = &context.staticmethod_type; - context.set_attr( - staticmethod_type, - "__get__", - context.new_rustfunc(staticmethod_get), - ); - context.set_attr( - staticmethod_type, - "__new__", - context.new_rustfunc(staticmethod_new), - ); + extend_class!(context, builtin_function_or_method_type, { + "__get__" => context.new_rustfunc(bind_method) + }); } fn bind_method(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { @@ -110,65 +80,3 @@ fn function_code(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { None => Err(vm.new_type_error("no code".to_string())), } } - -// Classmethod type methods: -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) -} - -// `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) -} diff --git a/vm/src/obj/objstaticmethod.rs b/vm/src/obj/objstaticmethod.rs new file mode 100644 index 000000000..6807a695c --- /dev/null +++ b/vm/src/obj/objstaticmethod.rs @@ -0,0 +1,39 @@ +use crate::pyobject::{AttributeProtocol, PyContext, PyFuncArgs, PyResult, TypeProtocol}; +use crate::vm::VirtualMachine; + +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), + }); +} + +// `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) +} diff --git a/vm/src/obj/objzip.rs b/vm/src/obj/objzip.rs index 8831564a8..f108ef54b 100644 --- a/vm/src/obj/objzip.rs +++ b/vm/src/obj/objzip.rs @@ -49,6 +49,8 @@ fn zip_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { pub fn init(context: &PyContext) { let zip_type = &context.zip_type; objiter::iter_type_init(context, zip_type); - context.set_attr(zip_type, "__new__", context.new_rustfunc(zip_new)); - context.set_attr(zip_type, "__next__", context.new_rustfunc(zip_next)); + extend_class!(context, zip_type, { + "__new__" => context.new_rustfunc(zip_new), + "__next__" => context.new_rustfunc(zip_next) + }); } diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 0d348e1b6..e4506dbe7 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -19,6 +19,7 @@ use crate::obj::objbool; use crate::obj::objbuiltinfunc::PyBuiltinFunction; use crate::obj::objbytearray; use crate::obj::objbytes; +use crate::obj::objclassmethod; use crate::obj::objcode; use crate::obj::objcomplex::{self, PyComplex}; use crate::obj::objdict::{self, PyDict}; @@ -41,6 +42,7 @@ use crate::obj::objproperty; use crate::obj::objrange; use crate::obj::objset::{self, PySet}; use crate::obj::objslice; +use crate::obj::objstaticmethod; use crate::obj::objstr; use crate::obj::objsuper; use crate::obj::objtuple::{self, PyTuple}; @@ -296,6 +298,8 @@ impl PyContext { objobject::init(&context); objdict::init(&context); objfunction::init(&context); + objstaticmethod::init(&context); + objclassmethod::init(&context); objgenerator::init(&context); objint::init(&context); objfloat::init(&context);