Skip to content

Commit 81fbcbc

Browse files
committed
Temp: Implement Number Protocol for PyDictKeys and PyDictItems
1 parent 05317f1 commit 81fbcbc

File tree

1 file changed

+126
-2
lines changed

1 file changed

+126
-2
lines changed

vm/src/builtins/dict.rs

+126-2
Original file line numberDiff line numberDiff line change
@@ -1092,7 +1092,15 @@ trait ViewSetOps: DictView {
10921092
}
10931093

10941094
impl ViewSetOps for PyDictKeys {}
1095-
#[pyclass(with(DictView, Constructor, Comparable, Iterable, ViewSetOps, AsSequence))]
1095+
#[pyclass(with(
1096+
DictView,
1097+
Constructor,
1098+
Comparable,
1099+
Iterable,
1100+
ViewSetOps,
1101+
AsSequence,
1102+
AsNumber
1103+
))]
10961104
impl PyDictKeys {
10971105
#[pymethod(magic)]
10981106
fn contains(zelf: PyRef<Self>, key: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
@@ -1133,8 +1141,70 @@ impl AsSequence for PyDictKeys {
11331141
}
11341142
}
11351143

1144+
impl AsNumber for PyDictKeys {
1145+
fn as_number() -> &'static PyNumberMethods {
1146+
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
1147+
subtract: Some(|num, args, vm| {
1148+
let num = PySetInner::from_iter(
1149+
ArgIterable::try_from_object(vm, num.obj.to_owned())?.iter(vm)?,
1150+
vm,
1151+
)?;
1152+
Ok(PySet {
1153+
inner: num
1154+
.difference(ArgIterable::try_from_object(vm, args.to_owned())?, vm)?,
1155+
}
1156+
.into_pyobject(vm))
1157+
}),
1158+
and: Some(|num, args, vm| {
1159+
let num = PySetInner::from_iter(
1160+
ArgIterable::try_from_object(vm, num.obj.to_owned())?.iter(vm)?,
1161+
vm,
1162+
)?;
1163+
Ok(PySet {
1164+
inner: num
1165+
.intersection(ArgIterable::try_from_object(vm, args.to_owned())?, vm)?,
1166+
}
1167+
.into_pyobject(vm))
1168+
}),
1169+
xor: Some(|num, args, vm| {
1170+
let num = PySetInner::from_iter(
1171+
ArgIterable::try_from_object(vm, num.obj.to_owned())?.iter(vm)?,
1172+
vm,
1173+
)?;
1174+
Ok(PySet {
1175+
inner: num.symmetric_difference(
1176+
ArgIterable::try_from_object(vm, args.to_owned())?,
1177+
vm,
1178+
)?,
1179+
}
1180+
.into_pyobject(vm))
1181+
}),
1182+
or: Some(|num, args, vm| {
1183+
let num = PySetInner::from_iter(
1184+
ArgIterable::try_from_object(vm, num.obj.to_owned())?.iter(vm)?,
1185+
vm,
1186+
)?;
1187+
Ok(PySet {
1188+
inner: num.union(ArgIterable::try_from_object(vm, args.to_owned())?, vm)?,
1189+
}
1190+
.into_pyobject(vm))
1191+
}),
1192+
..PyNumberMethods::NOT_IMPLEMENTED
1193+
};
1194+
&AS_NUMBER
1195+
}
1196+
}
1197+
11361198
impl ViewSetOps for PyDictItems {}
1137-
#[pyclass(with(DictView, Constructor, Comparable, Iterable, ViewSetOps, AsSequence))]
1199+
#[pyclass(with(
1200+
DictView,
1201+
Constructor,
1202+
Comparable,
1203+
Iterable,
1204+
ViewSetOps,
1205+
AsSequence,
1206+
AsNumber
1207+
))]
11381208
impl PyDictItems {
11391209
#[pymethod(magic)]
11401210
fn contains(zelf: PyRef<Self>, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
@@ -1189,6 +1259,60 @@ impl AsSequence for PyDictItems {
11891259
}
11901260
}
11911261

1262+
impl AsNumber for PyDictItems {
1263+
fn as_number() -> &'static PyNumberMethods {
1264+
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
1265+
subtract: Some(|num, args, vm| {
1266+
let num = PySetInner::from_iter(
1267+
ArgIterable::try_from_object(vm, num.obj.to_owned())?.iter(vm)?,
1268+
vm,
1269+
)?;
1270+
Ok(PySet {
1271+
inner: num
1272+
.difference(ArgIterable::try_from_object(vm, args.to_owned())?, vm)?,
1273+
}
1274+
.into_pyobject(vm))
1275+
}),
1276+
and: Some(|num, args, vm| {
1277+
let num = PySetInner::from_iter(
1278+
ArgIterable::try_from_object(vm, num.obj.to_owned())?.iter(vm)?,
1279+
vm,
1280+
)?;
1281+
Ok(PySet {
1282+
inner: num
1283+
.intersection(ArgIterable::try_from_object(vm, args.to_owned())?, vm)?,
1284+
}
1285+
.into_pyobject(vm))
1286+
}),
1287+
xor: Some(|num, args, vm| {
1288+
let num = PySetInner::from_iter(
1289+
ArgIterable::try_from_object(vm, num.obj.to_owned())?.iter(vm)?,
1290+
vm,
1291+
)?;
1292+
Ok(PySet {
1293+
inner: num.symmetric_difference(
1294+
ArgIterable::try_from_object(vm, args.to_owned())?,
1295+
vm,
1296+
)?,
1297+
}
1298+
.into_pyobject(vm))
1299+
}),
1300+
or: Some(|num, args, vm| {
1301+
let num = PySetInner::from_iter(
1302+
ArgIterable::try_from_object(vm, num.obj.to_owned())?.iter(vm)?,
1303+
vm,
1304+
)?;
1305+
Ok(PySet {
1306+
inner: num.union(ArgIterable::try_from_object(vm, args.to_owned())?, vm)?,
1307+
}
1308+
.into_pyobject(vm))
1309+
}),
1310+
..PyNumberMethods::NOT_IMPLEMENTED
1311+
};
1312+
&AS_NUMBER
1313+
}
1314+
}
1315+
11921316
#[pyclass(with(DictView, Constructor, Iterable, AsSequence))]
11931317
impl PyDictValues {
11941318
#[pygetset]

0 commit comments

Comments
 (0)