blob: 40ed1a1520753e7689531f75b4eb857e669e8940 [file] [log] [blame]
Damien George7c9c6672014-01-25 00:17:36 +00001#include <stdlib.h>
2#include <stdint.h>
3
4#include "nlr.h"
5#include "misc.h"
6#include "mpconfig.h"
7#include "qstr.h"
8#include "obj.h"
9#include "runtime.h"
10
11// this is a wrapper object that is turns something that has a __getitem__ method into an iterator
12
13typedef struct _mp_obj_getitem_iter_t {
14 mp_obj_base_t base;
15 mp_obj_t args[3];
16} mp_obj_getitem_iter_t;
17
18static mp_obj_t it_iternext(mp_obj_t self_in) {
19 mp_obj_getitem_iter_t *self = self_in;
20 nlr_buf_t nlr;
21 if (nlr_push(&nlr) == 0) {
22 // try to get next item
23 mp_obj_t value = rt_call_method_n_kw(1, 0, self->args);
24 self->args[2] = MP_OBJ_NEW_SMALL_INT(MP_OBJ_SMALL_INT_VALUE(self->args[2]) + 1);
25 nlr_pop();
26 return value;
27 } else {
28 // an exception was raised
29 if (MP_OBJ_IS_TYPE(nlr.ret_val, &exception_type) && mp_obj_exception_get_type(nlr.ret_val) == MP_QSTR_StopIteration) {
30 // return mp_const_stop_iteration instead of raising StopIteration
31 return mp_const_stop_iteration;
32 } else {
33 // re-raise exception
34 nlr_jump(nlr.ret_val);
35 }
36 }
37}
38
39static const mp_obj_type_t it_type = {
40 { &mp_const_type },
41 "iterator",
42 .iternext = it_iternext
43};
44
45// args are those returned from rt_load_method_maybe (ie either an attribute or a method)
46mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args) {
47 mp_obj_getitem_iter_t *o = m_new_obj(mp_obj_getitem_iter_t);
48 o->base.type = &it_type;
49 o->args[0] = args[0];
50 o->args[1] = args[1];
51 o->args[2] = MP_OBJ_NEW_SMALL_INT(0);
52 return o;
53}