Skip to content

Commit 4d02fe0

Browse files
committed
static_as_sequence_generic
1 parent 38a36d7 commit 4d02fe0

File tree

10 files changed

+90
-76
lines changed

10 files changed

+90
-76
lines changed

vm/src/builtins/bytes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ impl AsSequence for PyBytes {
602602
let other = <Either<PyBytesInner, PyIntRef>>::try_from_object(vm, other.to_owned())?;
603603
Self::sequence_downcast(seq).contains(other, vm)
604604
}),
605-
..*PySequenceMethods::not_implemented()
605+
..PySequenceMethods::NOT_IMPLEMENTED
606606
};
607607
}
608608

vm/src/builtins/dict.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ impl AsMapping for PyDict {
480480
impl AsSequence for PyDict {
481481
const AS_SEQUENCE: PySequenceMethods = PySequenceMethods {
482482
contains: Some(|seq, target, vm| Self::sequence_downcast(seq).entries.contains(vm, target)),
483-
..*PySequenceMethods::not_implemented()
483+
..PySequenceMethods::NOT_IMPLEMENTED
484484
};
485485
}
486486

@@ -1056,7 +1056,7 @@ impl AsSequence for PyDictKeys {
10561056
.entries
10571057
.contains(vm, target)
10581058
}),
1059-
..*PySequenceMethods::not_implemented()
1059+
..PySequenceMethods::NOT_IMPLEMENTED
10601060
};
10611061
}
10621062

@@ -1105,7 +1105,7 @@ impl AsSequence for PyDictItems {
11051105
.entries
11061106
.contains(vm, target)
11071107
}),
1108-
..*PySequenceMethods::not_implemented()
1108+
..PySequenceMethods::NOT_IMPLEMENTED
11091109
};
11101110
}
11111111

@@ -1116,7 +1116,7 @@ impl Unconstructible for PyDictValues {}
11161116
impl AsSequence for PyDictValues {
11171117
const AS_SEQUENCE: PySequenceMethods = PySequenceMethods {
11181118
length: Some(|seq, _vm| Ok(Self::sequence_downcast(seq).len())),
1119-
..*PySequenceMethods::not_implemented()
1119+
..PySequenceMethods::NOT_IMPLEMENTED
11201120
};
11211121
}
11221122

vm/src/builtins/mappingproxy.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ impl AsMapping for PyMappingProxy {
158158
impl AsSequence for PyMappingProxy {
159159
const AS_SEQUENCE: PySequenceMethods = PySequenceMethods {
160160
contains: Some(|seq, target, vm| Self::sequence_downcast(seq)._contains(target, vm)),
161-
..*PySequenceMethods::not_implemented()
161+
..PySequenceMethods::NOT_IMPLEMENTED
162162
};
163163
}
164164

vm/src/builtins/memory.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,7 @@ impl AsSequence for PyMemoryView {
987987
zelf.try_not_released(vm)?;
988988
zelf.getitem_by_idx(i, vm)
989989
}),
990-
..*PySequenceMethods::not_implemented()
990+
..PySequenceMethods::NOT_IMPLEMENTED
991991
};
992992
}
993993

vm/src/builtins/range.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ impl AsSequence for PyRange {
413413
contains: Some(|seq, needle, vm| {
414414
Ok(Self::sequence_downcast(seq).contains(needle.to_owned(), vm))
415415
}),
416-
..*PySequenceMethods::not_implemented()
416+
..PySequenceMethods::NOT_IMPLEMENTED
417417
};
418418
}
419419

vm/src/builtins/set.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ impl AsSequence for PySet {
665665
const AS_SEQUENCE: PySequenceMethods = PySequenceMethods {
666666
length: Some(|seq, _vm| Ok(Self::sequence_downcast(seq).len())),
667667
contains: Some(|seq, needle, vm| Self::sequence_downcast(seq).inner.contains(needle, vm)),
668-
..*PySequenceMethods::not_implemented()
668+
..PySequenceMethods::NOT_IMPLEMENTED
669669
};
670670
}
671671

@@ -897,7 +897,7 @@ impl AsSequence for PyFrozenSet {
897897
const AS_SEQUENCE: PySequenceMethods = PySequenceMethods {
898898
length: Some(|seq, _vm| Ok(Self::sequence_downcast(seq).len())),
899899
contains: Some(|seq, needle, vm| Self::sequence_downcast(seq).inner.contains(needle, vm)),
900-
..*PySequenceMethods::not_implemented()
900+
..PySequenceMethods::NOT_IMPLEMENTED
901901
};
902902
}
903903

vm/src/builtins/str.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1325,7 +1325,7 @@ impl AsSequence for PyStr {
13251325
.map(|x| zelf.new_substr(x.to_string()).into_ref(vm).into())
13261326
}),
13271327
contains: Some(|seq, needle, vm| Self::sequence_downcast(seq)._contains(needle, vm)),
1328-
..*PySequenceMethods::not_implemented()
1328+
..PySequenceMethods::NOT_IMPLEMENTED
13291329
};
13301330
}
13311331

vm/src/builtins/tuple.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ impl AsSequence for PyTuple {
378378
let zelf = Self::sequence_downcast(seq);
379379
zelf._contains(needle, vm)
380380
}),
381-
..*PySequenceMethods::not_implemented()
381+
..PySequenceMethods::NOT_IMPLEMENTED
382382
};
383383
}
384384

vm/src/protocol/sequence.rs

+11-15
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,16 @@ pub struct PySequenceMethods {
3030
}
3131

3232
impl PySequenceMethods {
33-
pub const fn not_implemented() -> &'static Self {
34-
&NOT_IMPLEMENTED
35-
}
33+
pub const NOT_IMPLEMENTED: PySequenceMethods = PySequenceMethods {
34+
length: None,
35+
concat: None,
36+
repeat: None,
37+
item: None,
38+
ass_item: None,
39+
contains: None,
40+
inplace_concat: None,
41+
inplace_repeat: None,
42+
};
3643
}
3744

3845
impl Debug for PySequenceMethods {
@@ -101,7 +108,7 @@ impl PySequence<'_> {
101108
return f(self.obj, vm);
102109
}
103110
}
104-
Cow::Borrowed(PySequenceMethods::not_implemented())
111+
Cow::Borrowed(&PySequenceMethods::NOT_IMPLEMENTED)
105112
})
106113
}
107114

@@ -393,14 +400,3 @@ impl PySequence<'_> {
393400
}
394401
}
395402
}
396-
397-
const NOT_IMPLEMENTED: PySequenceMethods = PySequenceMethods {
398-
length: None,
399-
concat: None,
400-
repeat: None,
401-
item: None,
402-
ass_item: None,
403-
contains: None,
404-
inplace_concat: None,
405-
inplace_repeat: None,
406-
};

vm/src/types/slot.rs

+67-49
Original file line numberDiff line numberDiff line change
@@ -164,16 +164,6 @@ pub(crate) type InitFunc = fn(PyObjectRef, FuncArgs, &VirtualMachine) -> PyResul
164164
pub(crate) type DelFunc = fn(&PyObject, &VirtualMachine) -> PyResult<()>;
165165
pub(crate) type AsSequenceFunc = fn(&PyObject, &VirtualMachine) -> Cow<'static, PySequenceMethods>;
166166

167-
macro_rules! then_some_closure {
168-
($cond:expr, $closure:expr) => {
169-
if $cond {
170-
Some($closure)
171-
} else {
172-
None
173-
}
174-
};
175-
}
176-
177167
fn length_wrapper(obj: &PyObject, vm: &VirtualMachine) -> PyResult<usize> {
178168
let ret = vm.call_special_method(obj.to_owned(), identifier!(vm, __len__), ())?;
179169
let len = ret.payload::<PyInt>().ok_or_else(|| {
@@ -282,45 +272,73 @@ fn as_mapping_generic(zelf: &PyObject, vm: &VirtualMachine) -> &'static PyMappin
282272
static_as_mapping_generic(has_length, has_subscript, has_ass_subscript)
283273
}
284274

285-
fn as_sequence_wrapper(zelf: &PyObject, vm: &VirtualMachine) -> Cow<'static, PySequenceMethods> {
275+
pub(crate) fn static_as_sequence_generic(
276+
has_length: bool,
277+
has_ass_item: bool,
278+
) -> &'static PySequenceMethods {
279+
static METHODS: &[PySequenceMethods] = &[
280+
new_generic(false, false),
281+
new_generic(true, false),
282+
new_generic(false, true),
283+
new_generic(true, true),
284+
];
285+
286+
fn length(seq: &PySequence, vm: &VirtualMachine) -> PyResult<usize> {
287+
length_wrapper(seq.obj, vm)
288+
}
289+
fn item(seq: &PySequence, i: isize, vm: &VirtualMachine) -> PyResult {
290+
vm.call_special_method(seq.obj.to_owned(), identifier!(vm, __getitem__), (i,))
291+
}
292+
fn ass_item(
293+
seq: &PySequence,
294+
i: isize,
295+
value: Option<PyObjectRef>,
296+
vm: &VirtualMachine,
297+
) -> PyResult<()> {
298+
match value {
299+
Some(value) => vm
300+
.call_special_method(
301+
seq.obj.to_owned(),
302+
identifier!(vm, __setitem__),
303+
(i.to_pyobject(vm), value),
304+
)
305+
.map(|_| Ok(()))?,
306+
None => vm
307+
.call_special_method(
308+
seq.obj.to_owned(),
309+
identifier!(vm, __delitem__),
310+
(i.to_pyobject(vm),),
311+
)
312+
.map(|_| Ok(()))?,
313+
}
314+
}
315+
316+
const fn new_generic(has_length: bool, has_ass_item: bool) -> PySequenceMethods {
317+
PySequenceMethods {
318+
length: if has_length { Some(length) } else { None },
319+
item: Some(item),
320+
ass_item: if has_ass_item { Some(ass_item) } else { None },
321+
..PySequenceMethods::NOT_IMPLEMENTED
322+
}
323+
}
324+
325+
let key = bool_int(has_length) | (bool_int(has_ass_item) << 1);
326+
327+
&METHODS[key]
328+
}
329+
330+
fn as_sequence_generic(zelf: &PyObject, vm: &VirtualMachine) -> Cow<'static, PySequenceMethods> {
286331
if !zelf.class().has_attr(identifier!(vm, __getitem__)) {
287-
return Cow::Borrowed(PySequenceMethods::not_implemented());
288-
}
289-
290-
Cow::Owned(PySequenceMethods {
291-
length: then_some_closure!(
292-
zelf.class().has_attr(identifier!(vm, __len__)),
293-
|seq, vm| { length_wrapper(seq.obj, vm) }
294-
),
295-
item: Some(|seq, i, vm| {
296-
vm.call_special_method(
297-
seq.obj.to_owned(),
298-
identifier!(vm, __getitem__),
299-
(i.to_pyobject(vm),),
300-
)
301-
}),
302-
ass_item: then_some_closure!(
303-
zelf.class().has_attr(identifier!(vm, __setitem__))
304-
| zelf.class().has_attr(identifier!(vm, __delitem__)),
305-
|seq, i, value, vm| match value {
306-
Some(value) => vm
307-
.call_special_method(
308-
seq.obj.to_owned(),
309-
identifier!(vm, __setitem__),
310-
(i.to_pyobject(vm), value),
311-
)
312-
.map(|_| Ok(()))?,
313-
None => vm
314-
.call_special_method(
315-
seq.obj.to_owned(),
316-
identifier!(vm, __delitem__),
317-
(i.to_pyobject(vm),)
318-
)
319-
.map(|_| Ok(()))?,
320-
}
321-
),
322-
..Default::default()
323-
})
332+
return Cow::Borrowed(&PySequenceMethods::NOT_IMPLEMENTED);
333+
}
334+
335+
let (has_length, has_ass_item) = (
336+
zelf.class().has_attr(identifier!(vm, __len__)),
337+
zelf.class().has_attr(identifier!(vm, __setitem__))
338+
| zelf.class().has_attr(identifier!(vm, __delitem__)),
339+
);
340+
341+
Cow::Borrowed(static_as_sequence_generic(has_length, has_ass_item))
324342
}
325343

326344
fn hash_wrapper(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<PyHash> {
@@ -436,7 +454,7 @@ impl PyType {
436454
match name.as_str() {
437455
"__len__" | "__getitem__" | "__setitem__" | "__delitem__" => {
438456
update_slot!(as_mapping, as_mapping_generic);
439-
update_slot!(as_sequence, as_sequence_wrapper);
457+
update_slot!(as_sequence, as_sequence_generic);
440458
}
441459
"__hash__" => {
442460
update_slot!(hash, hash_wrapper);

0 commit comments

Comments
 (0)