Skip to content

Commit 2d127b9

Browse files
committed
Use macro to generate full set of views and iterators.
1 parent 5c4755f commit 2d127b9

File tree

2 files changed

+114
-116
lines changed

2 files changed

+114
-116
lines changed

vm/src/obj/objdict.rs

Lines changed: 96 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -130,16 +130,20 @@ impl PyDictRef {
130130
self.entries.borrow_mut().clear()
131131
}
132132

133-
fn iter(self, vm: &VirtualMachine) -> PyDictKeysIteratorRef {
134-
PyDictKeysIteratorRef::new(self, vm)
133+
fn iter(self, _vm: &VirtualMachine) -> PyDictKeyIterator {
134+
PyDictKeyIterator::new(self)
135135
}
136136

137-
fn values(self, vm: &VirtualMachine) -> PyDictValuesIteratorRef {
138-
PyDictValuesIteratorRef::new(self, vm)
137+
fn keys(self, _vm: &VirtualMachine) -> PyDictKeys {
138+
PyDictKeys::new(self)
139139
}
140140

141-
fn items(self, vm: &VirtualMachine) -> PyDictItemsIteratorRef {
142-
PyDictItemsIteratorRef::new(self, vm)
141+
fn values(self, _vm: &VirtualMachine) -> PyDictValues {
142+
PyDictValues::new(self)
143+
}
144+
145+
fn items(self, _vm: &VirtualMachine) -> PyDictItems {
146+
PyDictItems::new(self)
143147
}
144148

145149
pub fn get_key_value_pairs(&self) -> Vec<(PyObjectRef, PyObjectRef)> {
@@ -243,116 +247,89 @@ impl ItemProtocol for PyDictRef {
243247
}
244248
}
245249

246-
#[derive(Debug)]
247-
struct PyDictKeysIterator {
248-
pub dict: PyDictRef,
249-
pub position: Cell<usize>,
250-
}
251-
type PyDictKeysIteratorRef = PyRef<PyDictKeysIterator>;
252-
253-
impl PyDictKeysIteratorRef {
254-
fn new(dict: PyDictRef, vm: &VirtualMachine) -> PyDictKeysIteratorRef {
255-
PyDictKeysIterator {
256-
position: Cell::new(0),
257-
dict,
250+
macro_rules! dict_iterator {
251+
( $name: ident, $iter_name: ident, $class: ident, $iter_class: ident, $result_fn: expr) => {
252+
#[derive(Debug)]
253+
struct $name {
254+
pub dict: PyDictRef,
258255
}
259-
.into_ref(vm)
260-
}
261256

262-
fn next(self, vm: &VirtualMachine) -> PyResult {
263-
match self.dict.entries.borrow().next_entry(self.position.get()) {
264-
Some((new_position, key, _value)) => {
265-
self.position.set(new_position);
266-
Ok(key.clone())
257+
impl $name {
258+
fn new(dict: PyDictRef) -> Self {
259+
$name { dict: dict }
267260
}
268-
None => Err(objiter::new_stop_iteration(vm)),
269-
}
270-
}
271-
272-
fn iter(self, _vm: &VirtualMachine) -> Self {
273-
self
274-
}
275-
}
276-
277-
impl PyValue for PyDictKeysIterator {
278-
fn class(vm: &VirtualMachine) -> PyClassRef {
279-
vm.ctx.dictkeysiterator_type.clone()
280-
}
281-
}
282-
283-
#[derive(Debug)]
284-
struct PyDictValuesIterator {
285-
pub dict: PyDictRef,
286-
pub position: Cell<usize>,
287-
}
288-
type PyDictValuesIteratorRef = PyRef<PyDictValuesIterator>;
289261

290-
impl PyDictValuesIteratorRef {
291-
fn new(dict: PyDictRef, vm: &VirtualMachine) -> PyDictValuesIteratorRef {
292-
PyDictValuesIterator {
293-
position: Cell::new(0),
294-
dict,
262+
fn iter(&self, _vm: &VirtualMachine) -> $iter_name {
263+
$iter_name::new(self.dict.clone())
264+
}
295265
}
296-
.into_ref(vm)
297-
}
298266

299-
fn next(self, vm: &VirtualMachine) -> PyResult {
300-
match self.dict.entries.borrow().next_entry(self.position.get()) {
301-
Some((new_position, _key, value)) => {
302-
self.position.set(new_position);
303-
Ok(value.clone())
267+
impl PyValue for $name {
268+
fn class(vm: &VirtualMachine) -> PyClassRef {
269+
vm.ctx.$class.clone()
304270
}
305-
None => Err(objiter::new_stop_iteration(vm)),
306271
}
307-
}
308-
309-
fn iter(self, _vm: &VirtualMachine) -> Self {
310-
self
311-
}
312-
}
313272

314-
impl PyValue for PyDictValuesIterator {
315-
fn class(vm: &VirtualMachine) -> PyClassRef {
316-
vm.ctx.dictvaluesiterator_type.clone()
317-
}
318-
}
273+
#[derive(Debug)]
274+
struct $iter_name {
275+
pub dict: PyDictRef,
276+
pub position: Cell<usize>,
277+
}
319278

320-
#[derive(Debug)]
321-
struct PyDictItemsIterator {
322-
pub dict: PyDictRef,
323-
pub position: Cell<usize>,
324-
}
279+
impl $iter_name {
280+
fn new(dict: PyDictRef) -> Self {
281+
$iter_name {
282+
position: Cell::new(0),
283+
dict,
284+
}
285+
}
325286

326-
type PyDictItemsIteratorRef = PyRef<PyDictItemsIterator>;
287+
fn next(&self, vm: &VirtualMachine) -> PyResult {
288+
match self.dict.entries.borrow().next_entry(self.position.get()) {
289+
Some((new_position, key, value)) => {
290+
self.position.set(new_position);
291+
Ok($result_fn(vm, key, value))
292+
}
293+
None => Err(objiter::new_stop_iteration(vm)),
294+
}
295+
}
327296

328-
impl PyDictItemsIteratorRef {
329-
fn new(dict: PyDictRef, vm: &VirtualMachine) -> PyDictItemsIteratorRef {
330-
PyDictItemsIterator {
331-
position: Cell::new(0),
332-
dict,
297+
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
298+
zelf
299+
}
333300
}
334-
.into_ref(vm)
335-
}
336301

337-
fn next(self: PyDictItemsIteratorRef, vm: &VirtualMachine) -> PyResult {
338-
match self.dict.entries.borrow().next_entry(self.position.get()) {
339-
Some((new_position, key, value)) => {
340-
self.position.set(new_position);
341-
Ok(vm.ctx.new_tuple(vec![key.clone(), value.clone()]))
302+
impl PyValue for $iter_name {
303+
fn class(vm: &VirtualMachine) -> PyClassRef {
304+
vm.ctx.$iter_class.clone()
342305
}
343-
None => Err(objiter::new_stop_iteration(vm)),
344306
}
345-
}
307+
};
308+
}
346309

347-
fn iter(self, _vm: &VirtualMachine) -> Self {
348-
self
349-
}
310+
dict_iterator! {
311+
PyDictKeys,
312+
PyDictKeyIterator,
313+
dictkeys_type,
314+
dictkeyiterator_type,
315+
|_vm: &VirtualMachine, key: &PyObjectRef, _value: &PyObjectRef| key.clone()
350316
}
351317

352-
impl PyValue for PyDictItemsIterator {
353-
fn class(vm: &VirtualMachine) -> PyClassRef {
354-
vm.ctx.dictitemsiterator_type.clone()
355-
}
318+
dict_iterator! {
319+
PyDictValues,
320+
PyDictValueIterator,
321+
dictvalues_type,
322+
dictvalueiterator_type,
323+
|_vm: &VirtualMachine, _key: &PyObjectRef, value: &PyObjectRef| value.clone()
324+
}
325+
326+
dict_iterator! {
327+
PyDictItems,
328+
PyDictItemIterator,
329+
dictitems_type,
330+
dictitemiterator_type,
331+
|vm: &VirtualMachine, key: &PyObjectRef, value: &PyObjectRef|
332+
vm.ctx.new_tuple(vec![key.clone(), value.clone()])
356333
}
357334

358335
pub fn init(context: &PyContext) {
@@ -371,24 +348,36 @@ pub fn init(context: &PyContext) {
371348
"values" => context.new_rustfunc(PyDictRef::values),
372349
"items" => context.new_rustfunc(PyDictRef::items),
373350
// TODO: separate type. `keys` should be a live view over the collection, not an iterator.
374-
"keys" => context.new_rustfunc(PyDictRef::iter),
351+
"keys" => context.new_rustfunc(PyDictRef::keys),
375352
"get" => context.new_rustfunc(PyDictRef::get),
376353
"copy" => context.new_rustfunc(PyDictRef::copy),
377354
"update" => context.new_rustfunc(PyDictRef::update),
378355
});
379356

380-
extend_class!(context, &context.dictkeysiterator_type, {
381-
"__next__" => context.new_rustfunc(PyDictKeysIteratorRef::next),
382-
"__iter__" => context.new_rustfunc(PyDictKeysIteratorRef::iter),
357+
extend_class!(context, &context.dictkeys_type, {
358+
"__iter__" => context.new_rustfunc(PyDictKeys::iter),
359+
});
360+
361+
extend_class!(context, &context.dictkeyiterator_type, {
362+
"__next__" => context.new_rustfunc(PyDictKeyIterator::next),
363+
"__iter__" => context.new_rustfunc(PyDictKeyIterator::iter),
364+
});
365+
366+
extend_class!(context, &context.dictvalues_type, {
367+
"__iter__" => context.new_rustfunc(PyDictValues::iter),
368+
});
369+
370+
extend_class!(context, &context.dictvalueiterator_type, {
371+
"__next__" => context.new_rustfunc(PyDictValueIterator::next),
372+
"__iter__" => context.new_rustfunc(PyDictValueIterator::iter),
383373
});
384374

385-
extend_class!(context, &context.dictvaluesiterator_type, {
386-
"__next__" => context.new_rustfunc(PyDictValuesIteratorRef::next),
387-
"__iter__" => context.new_rustfunc(PyDictValuesIteratorRef::iter),
375+
extend_class!(context, &context.dictitems_type, {
376+
"__iter__" => context.new_rustfunc(PyDictItems::iter),
388377
});
389378

390-
extend_class!(context, &context.dictitemsiterator_type, {
391-
"__next__" => context.new_rustfunc(PyDictItemsIteratorRef::next),
392-
"__iter__" => context.new_rustfunc(PyDictItemsIteratorRef::iter),
379+
extend_class!(context, &context.dictitemiterator_type, {
380+
"__next__" => context.new_rustfunc(PyDictItemIterator::next),
381+
"__iter__" => context.new_rustfunc(PyDictItemIterator::iter),
393382
});
394383
}

vm/src/pyobject.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,12 @@ pub struct PyContext {
129129
pub false_value: PyIntRef,
130130
pub list_type: PyClassRef,
131131
pub listiterator_type: PyClassRef,
132-
pub dictkeysiterator_type: PyClassRef,
133-
pub dictvaluesiterator_type: PyClassRef,
134-
pub dictitemsiterator_type: PyClassRef,
132+
pub dictkeyiterator_type: PyClassRef,
133+
pub dictvalueiterator_type: PyClassRef,
134+
pub dictitemiterator_type: PyClassRef,
135+
pub dictkeys_type: PyClassRef,
136+
pub dictvalues_type: PyClassRef,
137+
pub dictitems_type: PyClassRef,
135138
pub map_type: PyClassRef,
136139
pub memoryview_type: PyClassRef,
137140
pub none: PyNoneRef,
@@ -257,9 +260,12 @@ impl PyContext {
257260
let str_type = create_type("str", &type_type, &object_type);
258261
let list_type = create_type("list", &type_type, &object_type);
259262
let listiterator_type = create_type("list_iterator", &type_type, &object_type);
260-
let dictkeysiterator_type = create_type("dict_keys", &type_type, &object_type);
261-
let dictvaluesiterator_type = create_type("dict_values", &type_type, &object_type);
262-
let dictitemsiterator_type = create_type("dict_items", &type_type, &object_type);
263+
let dictkeys_type = create_type("dict_keys", &type_type, &object_type);
264+
let dictvalues_type = create_type("dict_values", &type_type, &object_type);
265+
let dictitems_type = create_type("dict_items", &type_type, &object_type);
266+
let dictkeyiterator_type = create_type("dict_keyiterator", &type_type, &object_type);
267+
let dictvalueiterator_type = create_type("dict_valueiterator", &type_type, &object_type);
268+
let dictitemiterator_type = create_type("dict_itemiterator", &type_type, &object_type);
263269
let set_type = create_type("set", &type_type, &object_type);
264270
let frozenset_type = create_type("frozenset", &type_type, &object_type);
265271
let int_type = create_type("int", &type_type, &object_type);
@@ -319,9 +325,12 @@ impl PyContext {
319325
staticmethod_type,
320326
list_type,
321327
listiterator_type,
322-
dictkeysiterator_type,
323-
dictvaluesiterator_type,
324-
dictitemsiterator_type,
328+
dictkeys_type,
329+
dictvalues_type,
330+
dictitems_type,
331+
dictkeyiterator_type,
332+
dictvalueiterator_type,
333+
dictitemiterator_type,
325334
set_type,
326335
frozenset_type,
327336
true_value,

0 commit comments

Comments
 (0)