Skip to content

Commit 0f3569a

Browse files
committed
refactor mapping protocol
1 parent 7cc5e0b commit 0f3569a

12 files changed

Lines changed: 277 additions & 424 deletions

File tree

vm/src/builtins/bytearray.rs

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,23 @@ impl PyByteArray {
677677
}
678678
}
679679

680+
impl PyByteArray {
681+
const MAPPING_METHODS: PyMappingMethods = PyMappingMethods {
682+
length: Some(|mapping, vm| Ok(mapping.obj_as::<Self>().len())),
683+
subscript: Some(|mapping, needle, vm| {
684+
mapping.obj_as::<Self>().getitem(needle.to_owned(), vm)
685+
}),
686+
ass_subscript: Some(|mapping, needle, value, vm| {
687+
let zelf = mapping.obj_as::<Self>();
688+
if let Some(value) = value {
689+
Self::setitem(zelf.to_owned(), needle.to_owned(), value, vm)
690+
} else {
691+
zelf.delitem(needle.to_owned(), vm)
692+
}
693+
}),
694+
};
695+
}
696+
680697
impl Comparable for PyByteArray {
681698
fn cmp(
682699
zelf: &crate::PyObjectView<Self>,
@@ -739,36 +756,7 @@ impl<'a> BufferResizeGuard<'a> for PyByteArray {
739756

740757
impl AsMapping for PyByteArray {
741758
fn as_mapping(_zelf: &crate::PyObjectView<Self>, _vm: &VirtualMachine) -> PyMappingMethods {
742-
PyMappingMethods {
743-
length: Some(Self::length),
744-
subscript: Some(Self::subscript),
745-
ass_subscript: Some(Self::ass_subscript),
746-
}
747-
}
748-
749-
#[inline]
750-
fn length(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<usize> {
751-
Self::downcast_ref(&zelf, vm).map(|zelf| Ok(zelf.len()))?
752-
}
753-
754-
#[inline]
755-
fn subscript(zelf: PyObjectRef, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult {
756-
Self::downcast_ref(&zelf, vm).map(|zelf| zelf.getitem(needle, vm))?
757-
}
758-
759-
#[inline]
760-
fn ass_subscript(
761-
zelf: PyObjectRef,
762-
needle: PyObjectRef,
763-
value: Option<PyObjectRef>,
764-
vm: &VirtualMachine,
765-
) -> PyResult<()> {
766-
match value {
767-
Some(value) => {
768-
Self::downcast(zelf, vm).map(|zelf| Self::setitem(zelf, needle, value, vm))
769-
}
770-
None => Self::downcast_ref(&zelf, vm).map(|zelf| zelf.delitem(needle, vm)),
771-
}?
759+
Self::MAPPING_METHODS
772760
}
773761
}
774762

vm/src/builtins/bytes.rs

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,16 @@ impl PyBytes {
523523
}
524524
}
525525

526+
impl PyBytes {
527+
const MAPPING_METHODS: PyMappingMethods = PyMappingMethods {
528+
length: Some(|mapping, vm| Ok(mapping.obj_as::<Self>().len())),
529+
subscript: Some(|mapping, needle, vm| {
530+
mapping.obj_as::<Self>().getitem(needle.to_owned(), vm)
531+
}),
532+
ass_subscript: None,
533+
};
534+
}
535+
526536
static BUFFER_METHODS: BufferMethods = BufferMethods {
527537
obj_bytes: |buffer| buffer.obj_as::<PyBytes>().as_bytes().into(),
528538
obj_bytes_mut: |_| panic!(),
@@ -543,31 +553,7 @@ impl AsBuffer for PyBytes {
543553

544554
impl AsMapping for PyBytes {
545555
fn as_mapping(_zelf: &PyObjectView<Self>, _vm: &VirtualMachine) -> PyMappingMethods {
546-
PyMappingMethods {
547-
length: Some(Self::length),
548-
subscript: Some(Self::subscript),
549-
ass_subscript: None,
550-
}
551-
}
552-
553-
#[inline]
554-
fn length(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<usize> {
555-
Self::downcast_ref(&zelf, vm).map(|zelf| Ok(zelf.len()))?
556-
}
557-
558-
#[inline]
559-
fn subscript(zelf: PyObjectRef, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult {
560-
Self::downcast_ref(&zelf, vm).map(|zelf| zelf.getitem(needle, vm))?
561-
}
562-
563-
#[cold]
564-
fn ass_subscript(
565-
zelf: PyObjectRef,
566-
_needle: PyObjectRef,
567-
_value: Option<PyObjectRef>,
568-
_vm: &VirtualMachine,
569-
) -> PyResult<()> {
570-
unreachable!("ass_subscript not implemented for {}", zelf.class())
556+
Self::MAPPING_METHODS
571557
}
572558
}
573559

vm/src/builtins/dict.rs

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -420,36 +420,27 @@ impl PyDict {
420420
}
421421
}
422422

423+
impl PyDict {
424+
const MAPPING_METHODS: PyMappingMethods = PyMappingMethods {
425+
length: Some(|mapping, vm| Ok(mapping.obj_as::<Self>().len())),
426+
subscript: Some(|mapping, needle, vm| {
427+
let zelf = mapping.obj_as::<Self>();
428+
Self::getitem(zelf.to_owned(), needle.to_owned(), vm)
429+
}),
430+
ass_subscript: Some(|mapping, needle, value, vm| {
431+
let zelf = mapping.obj_as::<Self>();
432+
if let Some(value) = value {
433+
zelf.setitem(needle.to_owned(), value, vm)
434+
} else {
435+
zelf.delitem(needle.to_owned(), vm)
436+
}
437+
}),
438+
};
439+
}
440+
423441
impl AsMapping for PyDict {
424442
fn as_mapping(_zelf: &PyObjectView<Self>, _vm: &VirtualMachine) -> PyMappingMethods {
425-
PyMappingMethods {
426-
length: Some(Self::length),
427-
subscript: Some(Self::subscript),
428-
ass_subscript: Some(Self::ass_subscript),
429-
}
430-
}
431-
432-
#[inline]
433-
fn length(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<usize> {
434-
Self::downcast_ref(&zelf, vm).map(|zelf| Ok(zelf.len()))?
435-
}
436-
437-
#[inline]
438-
fn subscript(zelf: PyObjectRef, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult {
439-
Self::downcast(zelf, vm).map(|zelf| Self::getitem(zelf, needle, vm))?
440-
}
441-
442-
#[inline]
443-
fn ass_subscript(
444-
zelf: PyObjectRef,
445-
needle: PyObjectRef,
446-
value: Option<PyObjectRef>,
447-
vm: &VirtualMachine,
448-
) -> PyResult<()> {
449-
Self::downcast_ref(&zelf, vm).map(|zelf| match value {
450-
Some(value) => zelf.setitem(needle, value, vm),
451-
None => zelf.delitem(needle, vm),
452-
})?
443+
Self::MAPPING_METHODS
453444
}
454445
}
455446

vm/src/builtins/genericalias.rs

Lines changed: 53 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -237,81 +237,68 @@ fn subs_tvars(
237237
.unwrap_or(Ok(obj))
238238
}
239239

240-
impl AsMapping for PyGenericAlias {
241-
fn as_mapping(_zelf: &PyObjectView<Self>, _vm: &VirtualMachine) -> PyMappingMethods {
242-
PyMappingMethods {
243-
length: None,
244-
subscript: Some(Self::subscript),
245-
ass_subscript: None,
240+
impl PyGenericAlias {
241+
fn getitem(&self, needle: &PyObject, vm: &VirtualMachine) -> PyResult {
242+
let num_params = self.parameters.len();
243+
if num_params == 0 {
244+
return Err(vm.new_type_error(format!(
245+
"There are no type variables left in {}",
246+
self.repr(vm)?
247+
)));
246248
}
247-
}
248-
249-
#[cold]
250-
fn length(zelf: PyObjectRef, _vm: &VirtualMachine) -> PyResult<usize> {
251-
unreachable!("length not implemented for {}", zelf.class())
252-
}
253249

254-
fn subscript(zelf: PyObjectRef, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult {
255-
Self::downcast(zelf, vm).map(|zelf| {
256-
let num_params = zelf.parameters.len();
257-
if num_params == 0 {
258-
return Err(vm.new_type_error(format!(
259-
"There are no type variables left in {}",
260-
zelf.repr(vm)?
261-
)));
262-
}
250+
let items = PyTupleRef::try_from_object(vm, needle.clone());
251+
let arg_items = match items {
252+
Ok(ref tuple) => tuple.as_slice(),
253+
Err(_) => std::slice::from_ref(&needle),
254+
};
263255

264-
let items = PyTupleRef::try_from_object(vm, needle.clone());
265-
let arg_items = match items {
266-
Ok(ref tuple) => tuple.as_slice(),
267-
Err(_) => std::slice::from_ref(&needle),
256+
let num_items = arg_items.len();
257+
if num_params != num_items {
258+
let plural = if num_items > num_params {
259+
"many"
260+
} else {
261+
"few"
268262
};
263+
return Err(vm.new_type_error(format!(
264+
"Too {} arguments for {}",
265+
plural,
266+
self.repr(vm)?
267+
)));
268+
}
269269

270-
let num_items = arg_items.len();
271-
if num_params != num_items {
272-
let plural = if num_items > num_params {
273-
"many"
270+
let new_args = self
271+
.args
272+
.as_slice()
273+
.iter()
274+
.map(|arg| {
275+
if is_typevar(arg) {
276+
let idx = tuple_index(&self.parameters, arg).unwrap();
277+
Ok(arg_items[idx].clone())
274278
} else {
275-
"few"
276-
};
277-
return Err(vm.new_type_error(format!(
278-
"Too {} arguments for {}",
279-
plural,
280-
zelf.repr(vm)?
281-
)));
282-
}
279+
subs_tvars(arg.clone(), &self.parameters, arg_items, vm)
280+
}
281+
})
282+
.collect::<PyResult<Vec<_>>>()?;
283283

284-
let new_args = zelf
285-
.args
286-
.as_slice()
287-
.iter()
288-
.map(|arg| {
289-
if is_typevar(arg) {
290-
let idx = tuple_index(&zelf.parameters, arg).unwrap();
291-
Ok(arg_items[idx].clone())
292-
} else {
293-
subs_tvars(arg.clone(), &zelf.parameters, arg_items, vm)
294-
}
295-
})
296-
.collect::<PyResult<Vec<_>>>()?;
297-
298-
Ok(PyGenericAlias::new(
299-
zelf.origin.clone(),
300-
PyTuple::new_ref(new_args, &vm.ctx).into(),
301-
vm,
302-
)
303-
.into_object(vm))
304-
})?
284+
Ok(PyGenericAlias::new(
285+
self.origin.clone(),
286+
PyTuple::new_ref(new_args, &vm.ctx).into(),
287+
vm,
288+
)
289+
.into_object(vm))
305290
}
306291

307-
#[cold]
308-
fn ass_subscript(
309-
zelf: PyObjectRef,
310-
_needle: PyObjectRef,
311-
_value: Option<PyObjectRef>,
312-
_vm: &VirtualMachine,
313-
) -> PyResult<()> {
314-
unreachable!("ass_subscript not implemented for {}", zelf.class())
292+
const MAPPING_METHODS: PyMappingMethods = PyMappingMethods {
293+
length: None,
294+
subscript: Some(|mapping, needle, vm| mapping.obj_as::<Self>().getitem(needle, vm)),
295+
ass_subscript: None,
296+
};
297+
}
298+
299+
impl AsMapping for PyGenericAlias {
300+
fn as_mapping(_zelf: &PyObjectView<Self>, _vm: &VirtualMachine) -> PyMappingMethods {
301+
Self::MAPPING_METHODS
315302
}
316303
}
317304

vm/src/builtins/list.rs

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -389,36 +389,27 @@ impl<'a> MutObjectSequenceOp<'a> for PyList {
389389
}
390390
}
391391

392+
impl PyList {
393+
const MAPPING_METHODS: PyMappingMethods = PyMappingMethods {
394+
length: Some(|mapping, vm| Ok(mapping.obj_as::<Self>().len())),
395+
subscript: Some(|mapping, needle, vm| {
396+
let zelf = mapping.obj_as::<Self>();
397+
Self::getitem(zelf.to_owned(), needle.to_owned(), vm)
398+
}),
399+
ass_subscript: Some(|mapping, needle, value, vm| {
400+
let zelf = mapping.obj_as::<Self>();
401+
if let Some(value) = value {
402+
zelf.setitem(needle.to_owned(), value, vm)
403+
} else {
404+
zelf.delitem(needle.to_owned(), vm)
405+
}
406+
}),
407+
};
408+
}
409+
392410
impl AsMapping for PyList {
393411
fn as_mapping(_zelf: &crate::PyObjectView<Self>, _vm: &VirtualMachine) -> PyMappingMethods {
394-
PyMappingMethods {
395-
length: Some(Self::length),
396-
subscript: Some(Self::subscript),
397-
ass_subscript: Some(Self::ass_subscript),
398-
}
399-
}
400-
401-
#[inline]
402-
fn length(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<usize> {
403-
Self::downcast_ref(&zelf, vm).map(|zelf| Ok(zelf.len()))?
404-
}
405-
406-
#[inline]
407-
fn subscript(zelf: PyObjectRef, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult {
408-
Self::downcast(zelf, vm).map(|zelf| Self::getitem(zelf, needle, vm))?
409-
}
410-
411-
#[inline]
412-
fn ass_subscript(
413-
zelf: PyObjectRef,
414-
needle: PyObjectRef,
415-
value: Option<PyObjectRef>,
416-
vm: &VirtualMachine,
417-
) -> PyResult<()> {
418-
Self::downcast_ref(&zelf, vm).map(|zelf| match value {
419-
Some(value) => zelf.setitem(needle, value, vm),
420-
None => zelf.delitem(needle, vm),
421-
})?
412+
Self::MAPPING_METHODS
422413
}
423414
}
424415

0 commit comments

Comments
 (0)