clean up functions and methods

This commit is contained in:
Jeong YunWon committed 2021-10-11 16:10:01 +09:00
1 parent 589d2b0e1b
commit 5cd375aaa9
14 files changed
+115 -104

No files matched your search

+1 -1
View File
@@ -290,7 +290,7 @@ impl ModuleItem for FunctionItem {
#doc
.into_function()
.with_module(vm.ctx.new_utf8_str(#module.to_owned()))
.build(&vm.ctx)
.into_ref(&vm.ctx)
);
quote! {
vm.__module_set_attr(&module, #py_name, #new_func).unwrap();
+1 -1
View File
@@ -43,7 +43,7 @@ fn run(vm: &vm::VirtualMachine) -> vm::PyResult<()> {
// typing `quit()` is too long, let's make `on(False)` work instead.
scope
.globals
.set_item("on", vm.ctx.new_function("on", on), vm)?;
.set_item("on", vm.ctx.new_function("on", on).into(), vm)?;
// let's include a fibonacci function, but let's be lazy and write it in Python
add_python_function!(
+1 -1
View File
@@ -25,7 +25,7 @@ macro_rules! create_property {
move |this: &PyExpatLikeXmlParser, func: PyObjectRef| *this.$element.write() = func,
);
$attributes.insert($name.to_owned(), attr);
$attributes.insert($name.to_owned(), attr.into());
};
}
+33 -23
View File
@@ -1,9 +1,9 @@
use super::{pytype, PyClassMethod, PyStrRef, PyTypeRef};
use super::{pytype, PyClassMethod, PyStr, PyStrRef, PyTypeRef};
use crate::{
function::{FuncArgs, PyNativeFunc},
builtins::PyBoundMethod,
function::{FuncArgs, IntoPyNativeFunc, PyNativeFunc},
slots::{Callable, SlotDescriptor},
PyClassImpl, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
VirtualMachine,
PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol, VirtualMachine,
};
use std::fmt;
@@ -21,34 +21,29 @@ impl PyNativeFuncDef {
doc: None,
}
}
}
impl PyNativeFuncDef {
pub fn with_doc(mut self, doc: String, ctx: &PyContext) -> Self {
self.doc = Some(ctx.new_stringref(doc));
self.doc = Some(PyStr::new_ref(doc, ctx));
self
}
pub fn into_function(self) -> PyBuiltinFunction {
self.into()
}
pub fn build_function(self, ctx: &PyContext) -> PyObjectRef {
self.into_function().build(ctx)
pub fn build_function(self, ctx: &PyContext) -> PyRef<PyBuiltinFunction> {
self.into_function().into_ref(ctx)
}
pub fn build_method(self, ctx: &PyContext, class: PyTypeRef) -> PyObjectRef {
PyObject::new(
pub fn build_method(self, ctx: &PyContext, class: PyTypeRef) -> PyRef<PyBuiltinMethod> {
PyRef::new_ref(
PyBuiltinMethod { value: self, class },
ctx.types.method_descriptor_type.clone(),
None,
)
}
pub fn build_classmethod(self, ctx: &PyContext, class: PyTypeRef) -> PyObjectRef {
pub fn build_classmethod(self, ctx: &PyContext, class: PyTypeRef) -> PyRef<PyClassMethod> {
// TODO: classmethod_descriptor
PyObject::new(
PyClassMethod::from(self.build_method(ctx, class)),
ctx.types.classmethod_type.clone(),
None,
)
let callable = self.build_method(ctx, class).into();
PyClassMethod::new_ref(callable, ctx)
}
}
@@ -85,8 +80,8 @@ impl PyBuiltinFunction {
self
}
pub fn build(self, ctx: &PyContext) -> PyObjectRef {
PyObject::new(
pub fn into_ref(self, ctx: &PyContext) -> PyRef<Self> {
PyRef::new_ref(
self,
ctx.types.builtin_function_or_method_type.clone(),
None,
@@ -183,11 +178,12 @@ impl SlotDescriptor for PyBuiltinMethod {
Ok(obj) => obj,
Err(result) => return result,
};
if vm.is_none(&obj) && !Self::_cls_is(&cls, &obj.class()) {
Ok(zelf.into())
let r = if vm.is_none(&obj) && !Self::_cls_is(&cls, &obj.class()) {
zelf.into()
} else {
Ok(vm.ctx.new_bound_method(zelf.into(), obj))
}
PyBoundMethod::new_ref(obj, zelf.into(), &vm.ctx).into()
};
Ok(r)
}
}
@@ -197,6 +193,20 @@ impl Callable for PyBuiltinMethod {
}
}
impl PyBuiltinMethod {
pub fn new_ref<F, FKind>(
name: impl Into<PyStr>,
class: PyTypeRef,
f: F,
ctx: &PyContext,
) -> PyRef<Self>
where
F: IntoPyNativeFunc<FKind>,
{
ctx.make_funcdef(name, f).build_method(ctx, class)
}
}
#[pyimpl(with(SlotDescriptor, Callable), flags(METHOD_DESCR))]
impl PyBuiltinMethod {
#[pyproperty(magic)]
+5 -5
View File
@@ -92,11 +92,6 @@ impl PyValue for PyByteArray {
/// Fill bytearray class methods dictionary.
pub(crate) fn init(context: &PyContext) {
PyByteArray::extend_class(context, &context.types.bytearray_type);
let bytearray_type = &context.types.bytearray_type;
extend_class!(context, bytearray_type, {
"maketrans" => context.new_method("maketrans", bytearray_type.clone(), PyBytesInner::maketrans),
});
PyByteArrayIterator::extend_class(context, &context.types.bytearray_iterator_type);
}
@@ -227,6 +222,11 @@ impl PyByteArray {
}
}
#[pymethod]
fn maketrans(from: PyBytesInner, to: PyBytesInner, vm: &VirtualMachine) -> PyResult {
PyBytesInner::maketrans(from, to, vm)
}
#[pymethod]
fn pop(zelf: PyRef<Self>, index: OptionalArg<isize>, vm: &VirtualMachine) -> PyResult<u8> {
let elements = &mut zelf.try_resizable(vm)?.elements;
+5 -4
View File
@@ -90,10 +90,6 @@ impl PyValue for PyBytes {
pub(crate) fn init(context: &PyContext) {
PyBytes::extend_class(context, &context.types.bytes_type);
let bytes_type = &context.types.bytes_type;
extend_class!(context, bytes_type, {
"maketrans" => context.new_method("maketrans", bytes_type.clone(), PyBytesInner::maketrans),
});
PyBytesIterator::extend_class(context, &context.types.bytes_iterator_type);
}
@@ -159,6 +155,11 @@ impl PyBytes {
self.inner.contains(needle, vm)
}
#[pymethod]
fn maketrans(from: PyBytesInner, to: PyBytesInner, vm: &VirtualMachine) -> PyResult {
PyBytesInner::maketrans(from, to, vm)
}
#[pymethod(magic)]
fn getitem(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult {
self.inner.getitem("byte", needle, vm) // byte != Self::NAME
+9 -2
View File
@@ -1,7 +1,8 @@
use super::PyTypeRef;
use crate::{
builtins::PyBoundMethod,
slots::{SlotConstructor, SlotDescriptor},
PyClassImpl, PyContext, PyObjectRef, PyResult, PyValue, TypeProtocol, VirtualMachine,
PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol, VirtualMachine,
};
/// classmethod(function) -> method
@@ -51,7 +52,7 @@ impl SlotDescriptor for PyClassMethod {
) -> PyResult {
let (zelf, obj) = Self::_unwrap(zelf, obj, vm)?;
let cls = cls.unwrap_or_else(|| obj.clone_class().into());
Ok(vm.ctx.new_bound_method(zelf.callable.clone(), cls))
Ok(PyBoundMethod::new_ref(cls, zelf.callable.clone(), &vm.ctx).into())
}
}
@@ -63,6 +64,12 @@ impl SlotConstructor for PyClassMethod {
}
}
impl PyClassMethod {
pub fn new_ref(callable: PyObjectRef, ctx: &PyContext) -> PyRef<Self> {
PyRef::new_ref(Self { callable }, ctx.types.classmethod_type.clone(), None)
}
}
#[pyimpl(with(SlotDescriptor, SlotConstructor), flags(BASETYPE, HAS_DICT))]
impl PyClassMethod {
#[pyproperty(magic)]
+16 -7
View File
@@ -408,7 +408,7 @@ impl SlotDescriptor for PyFunction {
let obj = if vm.is_none(&obj) && !Self::_cls_is(&cls, &obj.class()) {
zelf.into()
} else {
vm.ctx.new_bound_method(zelf.into(), obj)
PyBoundMethod::new_ref(obj, zelf.into(), &vm.ctx).into()
};
Ok(obj)
}
@@ -423,9 +423,8 @@ impl Callable for PyFunction {
#[pyclass(module = false, name = "method")]
#[derive(Debug)]
pub struct PyBoundMethod {
// TODO: these shouldn't be public
object: PyObjectRef,
pub function: PyObjectRef,
function: PyObjectRef,
}
impl Callable for PyBoundMethod {
@@ -480,15 +479,25 @@ impl SlotConstructor for PyBoundMethod {
}
}
impl PyBoundMethod {
fn new(object: PyObjectRef, function: PyObjectRef) -> Self {
PyBoundMethod { object, function }
}
pub fn new_ref(object: PyObjectRef, function: PyObjectRef, ctx: &PyContext) -> PyRef<Self> {
PyRef::new_ref(
Self::new(object, function),
ctx.types.bound_method_type.clone(),
None,
)
}
}
#[pyimpl(
with(Callable, Comparable, SlotGetattro, SlotConstructor),
flags(HAS_DICT)
)]
impl PyBoundMethod {
pub fn new(object: PyObjectRef, function: PyObjectRef) -> Self {
PyBoundMethod { object, function }
}
#[pymethod(magic)]
fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
let funcname =
+8 -6
View File
@@ -595,12 +595,14 @@ impl PyType {
if !attributes.contains_key("__dict__") {
attributes.insert(
"__dict__".to_owned(),
vm.ctx.new_getset(
"__dict__",
vm.ctx.types.object_type.clone(),
subtype_get_dict,
subtype_set_dict,
),
vm.ctx
.new_getset(
"__dict__",
vm.ctx.types.object_type.clone(),
subtype_get_dict,
subtype_set_dict,
)
.into(),
);
}
+2 -1
View File
@@ -1,5 +1,6 @@
use super::{PyStr, PyTypeRef};
use crate::{
builtins::builtinfunc::PyBuiltinMethod,
function::IntoPyNativeFunc,
slots::{SlotConstructor, SlotDescriptor},
PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, VirtualMachine,
@@ -53,7 +54,7 @@ impl PyStaticMethod {
where
F: IntoPyNativeFunc<FKind>,
{
let callable = ctx.new_method(name, class, f);
let callable = PyBuiltinMethod::new_ref(name, class, f, ctx).into();
PyRef::new_ref(Self { callable }, ctx.types.staticmethod_type.clone(), None)
}
}
+1 -1
View File
@@ -173,7 +173,7 @@ impl CodecsRegistry {
),
];
let errors = std::array::IntoIter::new(errors)
.map(|(name, f)| (name.to_owned(), f))
.map(|(name, f)| (name.to_owned(), f.into()))
.collect();
let inner = RegistryInner {
search_path: Vec::new(),
+1 -1
View File
@@ -225,7 +225,7 @@ macro_rules! named_function {
)
.into_function()
.with_module(ctx.new_utf8_str(stringify!($module).to_owned()))
.build(ctx)
.into_ref(ctx)
}
}};
}
+12 -33
View File
@@ -6,7 +6,7 @@ use crate::common::{
pub use crate::pyobjectrc::{PyObject, PyObjectRef, PyObjectWeak, PyObjectWrap, PyRef, PyWeakRef};
use crate::{
builtins::{
builtinfunc::PyNativeFuncDef,
builtinfunc::{PyBuiltinFunction, PyBuiltinMethod, PyNativeFuncDef},
bytearray, bytes,
code::{self, PyCode},
getset::{IntoPyGetterFunc, IntoPySetterFunc, PyGetSet},
@@ -249,10 +249,6 @@ impl PyContext {
create_type_with_slots(name, &self.types.type_type, base, slots)
}
pub(crate) fn new_stringref(&self, s: String) -> pystr::PyStrRef {
PyRef::new_ref(pystr::PyStr::from(s), self.types.str_type.clone(), None)
}
#[inline]
pub fn make_funcdef<F, FKind>(&self, name: impl Into<PyStr>, f: F) -> PyNativeFuncDef
where
@@ -261,7 +257,8 @@ impl PyContext {
PyNativeFuncDef::new(f.into_func(), PyStr::new_ref(name, self))
}
pub fn new_function<F, FKind>(&self, name: impl Into<PyStr>, f: F) -> PyObjectRef
// #[deprecated]
pub fn new_function<F, FKind>(&self, name: impl Into<PyStr>, f: F) -> PyRef<PyBuiltinFunction>
where
F: IntoPyNativeFunc<FKind>,
{
@@ -273,23 +270,11 @@ impl PyContext {
name: impl Into<PyStr>,
class: PyTypeRef,
f: F,
) -> PyObjectRef
) -> PyRef<PyBuiltinMethod>
where
F: IntoPyNativeFunc<FKind>,
{
self.make_funcdef(name, f).build_method(self, class)
}
pub fn new_classmethod<F, FKind>(
&self,
name: impl Into<PyStr>,
class: PyTypeRef,
f: F,
) -> PyObjectRef
where
F: IntoPyNativeFunc<FKind>,
{
self.make_funcdef(name, f).build_classmethod(self, class)
PyBuiltinMethod::new_ref(name, class, f, self)
}
pub fn new_readonly_getset<F, T>(
@@ -297,11 +282,11 @@ impl PyContext {
name: impl Into<String>,
class: PyTypeRef,
f: F,
) -> PyObjectRef
) -> PyRef<PyGetSet>
where
F: IntoPyGetterFunc<T>,
{
PyObject::new(
PyRef::new_ref(
PyGetSet::new(name.into(), class).with_get(f),
self.types.getset_type.clone(),
None,
@@ -314,12 +299,12 @@ impl PyContext {
class: PyTypeRef,
g: G,
s: S,
) -> PyObjectRef
) -> PyRef<PyGetSet>
where
G: IntoPyGetterFunc<T>,
S: IntoPySetterFunc<U>,
{
PyObject::new(
PyRef::new_ref(
PyGetSet::new(name.into(), class).with_get(g).with_set(s),
self.types.getset_type.clone(),
None,
@@ -333,14 +318,6 @@ impl PyContext {
PyRef::new_ref(PyCode::new(code), self.types.code_type.clone(), None)
}
pub fn new_bound_method(&self, function: PyObjectRef, object: PyObjectRef) -> PyObjectRef {
PyObject::new(
PyBoundMethod::new(object, function),
self.types.bound_method_type.clone(),
None,
)
}
pub fn new_base_object(&self, class: PyTypeRef, dict: Option<PyDictRef>) -> PyObjectRef {
PyObject::new(object::PyBaseObject, class, dict)
}
@@ -960,7 +937,9 @@ pub trait PyClassImpl: PyClassDef {
class.set_str_attr("__module__", ctx.new_utf8_str(module_name));
}
if class.slots.new.load().is_some() {
let bound = ctx.new_bound_method(ctx.slot_new_wrapper.clone(), class.clone().into());
let bound: PyObjectRef =
PyBoundMethod::new_ref(class.clone().into(), ctx.slot_new_wrapper.clone(), ctx)
.into();
class.set_str_attr("__new__", bound);
}
}
+20 -18
View File
@@ -215,24 +215,26 @@ pub fn js_to_py(vm: &VirtualMachine, js_val: JsValue) -> PyObjectRef {
}
} else if js_val.is_function() {
let func = js_sys::Function::from(js_val);
vm.ctx.new_function(
func.name(),
move |args: FuncArgs, vm: &VirtualMachine| -> PyResult {
let this = Object::new();
for (k, v) in args.kwargs {
Reflect::set(&this, &k.into(), &py_to_js(vm, v))
.expect("property to be settable");
}
let js_args = args
.args
.into_iter()
.map(|v| py_to_js(vm, v))
.collect::<Array>();
func.apply(&this, &js_args)
.map(|val| js_to_py(vm, val))
.map_err(|err| js_err_to_py_err(vm, &err))
},
)
vm.ctx
.new_function(
String::from(func.name()),
move |args: FuncArgs, vm: &VirtualMachine| -> PyResult {
let this = Object::new();
for (k, v) in args.kwargs {
Reflect::set(&this, &k.into(), &py_to_js(vm, v))
.expect("property to be settable");
}
let js_args = args
.args
.into_iter()
.map(|v| py_to_js(vm, v))
.collect::<Array>();
func.apply(&this, &js_args)
.map(|val| js_to_py(vm, val))
.map_err(|err| js_err_to_py_err(vm, &err))
},
)
.into()
} else if let Some(err) = js_val.dyn_ref::<js_sys::Error>() {
js_err_to_py_err(vm, err).into()
} else if js_val.is_undefined() {