From 9cb53919d190d7bb2864a523a34da72016506b93 Mon Sep 17 00:00:00 2001 From: Kangzhi Shi Date: Sat, 16 Oct 2021 15:23:05 +0200 Subject: [PATCH] fix sequence_wrapper --- vm/src/builtins/memory.rs | 2 +- vm/src/protocol/sequence.rs | 34 +++++++++++++++------------------- vm/src/types/slot.rs | 26 ++------------------------ 3 files changed, 18 insertions(+), 44 deletions(-) diff --git a/vm/src/builtins/memory.rs b/vm/src/builtins/memory.rs index f54e3ec8c..b2d839709 100644 --- a/vm/src/builtins/memory.rs +++ b/vm/src/builtins/memory.rs @@ -59,7 +59,7 @@ impl Constructor for PyMemoryView { } } -#[pyimpl(with(Hashable, Comparable, AsBuffer, AsMapping, Constructor))] +#[pyimpl(with(Hashable, Comparable, AsBuffer, AsMapping, AsSequence, Constructor))] impl PyMemoryView { fn parse_format(format: &str, vm: &VirtualMachine) -> PyResult { FormatSpec::parse(format.as_bytes(), vm) diff --git a/vm/src/protocol/sequence.rs b/vm/src/protocol/sequence.rs index f7ac3b250..f270e213a 100644 --- a/vm/src/protocol/sequence.rs +++ b/vm/src/protocol/sequence.rs @@ -4,6 +4,7 @@ use itertools::Itertools; use crate::{ builtins::{PyList, PySlice}, + common::static_cell, function::IntoPyObject, IdProtocol, PyArithmeticValue, PyObjectRef, PyResult, PyValue, TypeProtocol, VirtualMachine, }; @@ -25,6 +26,15 @@ pub struct PySequenceMethods { pub contains: Option PyResult>, } +impl PySequenceMethods { + pub fn not_implemented() -> &'static Self { + static_cell! { + static NOT_IMPLEMENTED: PySequenceMethods; + } + NOT_IMPLEMENTED.get_or_init(Self::default) + } +} + pub struct PySequence { obj: PyObjectRef, methods: Cow<'static, PySequenceMethods>, @@ -37,13 +47,7 @@ impl PySequence { return false; } cls.mro_find_map(|x| x.slots.as_sequence.load()) - .map(|f| { - // FIXME: we may avoid the check if we assume all the builtins - // implement fn item() for the sequence protocol - // all the python class must has __getitem__ if they ident as - // sequence protocol implemented - f(obj, vm).item.is_some() - }) + .map(|f| f(obj, vm).item.is_some()) .unwrap_or(false) } @@ -287,11 +291,7 @@ impl PySequence { } } -pub(crate) fn try_add_for_concat( - a: &PyObjectRef, - b: &PyObjectRef, - vm: &VirtualMachine, -) -> PyResult { +pub fn try_add_for_concat(a: &PyObjectRef, b: &PyObjectRef, vm: &VirtualMachine) -> PyResult { if PySequence::check(b, vm) { let ret = vm._add(a, b)?; if let PyArithmeticValue::Implemented(ret) = PyArithmeticValue::from_object(vm, ret) { @@ -304,7 +304,7 @@ pub(crate) fn try_add_for_concat( ))) } -pub(crate) fn try_mul_for_repeat(a: &PyObjectRef, n: usize, vm: &VirtualMachine) -> PyResult { +pub fn try_mul_for_repeat(a: &PyObjectRef, n: usize, vm: &VirtualMachine) -> PyResult { let ret = vm._mul(a, &n.into_pyobject(vm))?; if let PyArithmeticValue::Implemented(ret) = PyArithmeticValue::from_object(vm, ret) { return Ok(ret); @@ -312,7 +312,7 @@ pub(crate) fn try_mul_for_repeat(a: &PyObjectRef, n: usize, vm: &VirtualMachine) Err(vm.new_type_error(format!("'{}' object can't be repeated", a.class().name()))) } -pub(crate) fn try_iadd_for_inplace_concat( +pub fn try_iadd_for_inplace_concat( a: &PyObjectRef, b: &PyObjectRef, vm: &VirtualMachine, @@ -329,11 +329,7 @@ pub(crate) fn try_iadd_for_inplace_concat( ))) } -pub(crate) fn try_imul_for_inplace_repeat( - a: &PyObjectRef, - n: usize, - vm: &VirtualMachine, -) -> PyResult { +pub fn try_imul_for_inplace_repeat(a: &PyObjectRef, n: usize, vm: &VirtualMachine) -> PyResult { let ret = vm._imul(a, &n.into_pyobject(vm))?; if let PyArithmeticValue::Implemented(ret) = PyArithmeticValue::from_object(vm, ret) { return Ok(ret); diff --git a/vm/src/types/slot.rs b/vm/src/types/slot.rs index 40840b977..0a2ebadd6 100644 --- a/vm/src/types/slot.rs +++ b/vm/src/types/slot.rs @@ -9,7 +9,6 @@ use crate::{ }; use crossbeam_utils::atomic::AtomicCell; use num_traits::ToPrimitive; -use rustpython_common::static_cell; use std::borrow::Cow; use std::cmp::Ordering; @@ -207,31 +206,14 @@ fn as_mapping_wrapper(zelf: &PyObject, _vm: &VirtualMachine) -> PyMappingMethods } fn as_sequence_wrapper(zelf: &PyObject, _vm: &VirtualMachine) -> Cow<'static, PySequenceMethods> { - static_cell! { - static EMPTY: PySequenceMethods; - } if !zelf.has_class_attr("__getitem__") { - return Cow::Borrowed(EMPTY.get_or_init(PySequenceMethods::default)); + return Cow::Borrowed(PySequenceMethods::not_implemented()); } Cow::Owned(PySequenceMethods { length: then_some_closure!(zelf.has_class_attr("__len__"), |zelf, vm| { vm.obj_len_opt(zelf).unwrap() }), - concat: then_some_closure!(zelf.has_class_attr("__add__"), |zelf, other, vm| { - try_add_for_concat(zelf, other, vm) - }), - repeat: then_some_closure!(zelf.has_class_attr("__mul__"), |zelf, n, vm| { - try_mul_for_repeat(zelf, n, vm) - }), - inplace_concat: then_some_closure!( - zelf.has_class_attr("__iadd__") || zelf.has_class_attr("__add__"), - |zelf, other, vm| { try_iadd_for_inplace_concat(zelf, other, vm) } - ), - inplace_repeat: then_some_closure!( - zelf.has_class_attr("__imul__") || zelf.has_class_attr("__mul__"), - |zelf, n, vm| { try_imul_for_inplace_repeat(zelf, n, vm) } - ), item: Some(|zelf, i, vm| { vm.call_special_method(zelf.clone(), "__getitem__", (i.into_pyobject(vm),)) }), @@ -246,8 +228,7 @@ fn as_sequence_wrapper(zelf: &PyObject, _vm: &VirtualMachine) -> Cow<'static, Py .map(|_| Ok(()))?, } ), - // TODO: IterSearch - contains: None, + ..Default::default() }) } @@ -353,9 +334,6 @@ impl PyType { update_slot!(as_mapping, as_mapping_wrapper); update_slot!(as_sequence, as_sequence_wrapper); } - "__add__" | "__iadd__" | "__mul__" | "__imul__" => { - update_slot!(as_sequence, as_sequence_wrapper); - } "__hash__" => { update_slot!(hash, hash_wrapper); }