Skip to content

Commit e0ac7a4

Browse files
committed
add mapping protocol methods to update_slot
Signed-off-by: snowapril <sinjihng@gmail.com>
1 parent 92c781c commit e0ac7a4

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

vm/src/builtins/pytype.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ use super::{
44
};
55
use crate::common::{ascii, lock::PyRwLock};
66
use crate::{
7+
builtins::dict::PyMapping,
78
function::{FuncArgs, KwArgs, OptionalArg},
89
slots::{self, Callable, PyTpFlags, PyTypeSlots, SlotGetattro, SlotSetattro},
910
utils::Either,
1011
IdProtocol, PyAttributes, PyClassImpl, PyContext, PyLease, PyObjectRef, PyRef, PyResult,
1112
PyValue, TryFromObject, TypeProtocol, VirtualMachine,
1213
};
1314
use itertools::Itertools;
15+
use num_traits::ToPrimitive;
1416
use std::collections::HashSet;
1517
use std::fmt;
1618
use std::ops::Deref;
@@ -265,6 +267,54 @@ impl PyType {
265267
|zelf, vm| vm.call_special_method(zelf.clone(), "__next__", ());
266268
update_slot!(iternext, func);
267269
}
270+
"__len__" | "__getitem__" | "__setitem__" | "__delitem__" => {
271+
macro_rules! then_some_closure {
272+
($cond:expr, $closure:expr) => {
273+
if $cond {
274+
Some($closure)
275+
} else {
276+
None
277+
}
278+
};
279+
}
280+
281+
let func: slots::MappingFunc = |zelf, _vm| {
282+
Ok(PyMapping {
283+
length: then_some_closure!(zelf.has_class_attr("__len__"), |zelf, vm| {
284+
vm.call_special_method(zelf, "__len__", ()).map(|obj| {
285+
obj.payload_if_subclass::<PyInt>(vm)
286+
.map(|length_obj| {
287+
length_obj.as_bigint().to_usize().ok_or_else(|| {
288+
vm.new_value_error(
289+
"__len__() should return >= 0".to_owned(),
290+
)
291+
})
292+
})
293+
.unwrap()
294+
})?
295+
}),
296+
subscript: then_some_closure!(
297+
zelf.has_class_attr("__getitem__"),
298+
|zelf: PyObjectRef, needle: PyObjectRef, vm: &VirtualMachine| {
299+
vm.call_special_method(zelf, "__getitem__", (needle,))
300+
}
301+
),
302+
ass_subscript: then_some_closure!(
303+
zelf.has_class_attr("__setitem__") | zelf.has_class_attr("__delitem__"),
304+
|zelf, needle, value, vm| match value {
305+
Some(value) => vm
306+
.call_special_method(zelf, "__setitem__", (needle, value),)
307+
.map(|_| Ok(()))?,
308+
None => vm
309+
.call_special_method(zelf, "__delitem__", (needle,))
310+
.map(|_| Ok(()))?,
311+
}
312+
),
313+
})
314+
};
315+
update_slot!(as_mapping, func);
316+
// TODO: need to update sequence protocol too
317+
}
268318
_ => {}
269319
}
270320
}

0 commit comments

Comments
 (0)