Colin Hogben / micropython

Dependents:   micropython-repl

Committer:
Colin Hogben
Date:
Wed Apr 27 22:11:29 2016 +0100
Revision:
10:33521d742af1
Parent:
0:5868e8752d44
Update README and version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pythontech 0:5868e8752d44 1 /*
pythontech 0:5868e8752d44 2 * This file is part of the Micro Python project, http://micropython.org/
pythontech 0:5868e8752d44 3 *
pythontech 0:5868e8752d44 4 * The MIT License (MIT)
pythontech 0:5868e8752d44 5 *
pythontech 0:5868e8752d44 6 * Copyright (c) 2013, 2014 Damien P. George
pythontech 0:5868e8752d44 7 *
pythontech 0:5868e8752d44 8 * Permission is hereby granted, free of charge, to any person obtaining a copy
pythontech 0:5868e8752d44 9 * of this software and associated documentation files (the "Software"), to deal
pythontech 0:5868e8752d44 10 * in the Software without restriction, including without limitation the rights
pythontech 0:5868e8752d44 11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
pythontech 0:5868e8752d44 12 * copies of the Software, and to permit persons to whom the Software is
pythontech 0:5868e8752d44 13 * furnished to do so, subject to the following conditions:
pythontech 0:5868e8752d44 14 *
pythontech 0:5868e8752d44 15 * The above copyright notice and this permission notice shall be included in
pythontech 0:5868e8752d44 16 * all copies or substantial portions of the Software.
pythontech 0:5868e8752d44 17 *
pythontech 0:5868e8752d44 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
pythontech 0:5868e8752d44 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
pythontech 0:5868e8752d44 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
pythontech 0:5868e8752d44 21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
pythontech 0:5868e8752d44 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
pythontech 0:5868e8752d44 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
pythontech 0:5868e8752d44 24 * THE SOFTWARE.
pythontech 0:5868e8752d44 25 */
pythontech 0:5868e8752d44 26
pythontech 0:5868e8752d44 27 #include <stdlib.h>
pythontech 0:5868e8752d44 28
pythontech 0:5868e8752d44 29 #include "py/nlr.h"
pythontech 0:5868e8752d44 30 #include "py/runtime0.h"
pythontech 0:5868e8752d44 31 #include "py/runtime.h"
pythontech 0:5868e8752d44 32
pythontech 0:5868e8752d44 33 /******************************************************************************/
pythontech 0:5868e8752d44 34 /* range iterator */
pythontech 0:5868e8752d44 35
pythontech 0:5868e8752d44 36 typedef struct _mp_obj_range_it_t {
pythontech 0:5868e8752d44 37 mp_obj_base_t base;
pythontech 0:5868e8752d44 38 // TODO make these values generic objects or something
pythontech 0:5868e8752d44 39 mp_int_t cur;
pythontech 0:5868e8752d44 40 mp_int_t stop;
pythontech 0:5868e8752d44 41 mp_int_t step;
pythontech 0:5868e8752d44 42 } mp_obj_range_it_t;
pythontech 0:5868e8752d44 43
pythontech 0:5868e8752d44 44 STATIC mp_obj_t range_it_iternext(mp_obj_t o_in) {
pythontech 0:5868e8752d44 45 mp_obj_range_it_t *o = MP_OBJ_TO_PTR(o_in);
pythontech 0:5868e8752d44 46 if ((o->step > 0 && o->cur < o->stop) || (o->step < 0 && o->cur > o->stop)) {
pythontech 0:5868e8752d44 47 mp_obj_t o_out = MP_OBJ_NEW_SMALL_INT(o->cur);
pythontech 0:5868e8752d44 48 o->cur += o->step;
pythontech 0:5868e8752d44 49 return o_out;
pythontech 0:5868e8752d44 50 } else {
pythontech 0:5868e8752d44 51 return MP_OBJ_STOP_ITERATION;
pythontech 0:5868e8752d44 52 }
pythontech 0:5868e8752d44 53 }
pythontech 0:5868e8752d44 54
pythontech 0:5868e8752d44 55 STATIC const mp_obj_type_t range_it_type = {
pythontech 0:5868e8752d44 56 { &mp_type_type },
pythontech 0:5868e8752d44 57 .name = MP_QSTR_iterator,
pythontech 0:5868e8752d44 58 .getiter = mp_identity,
pythontech 0:5868e8752d44 59 .iternext = range_it_iternext,
pythontech 0:5868e8752d44 60 };
pythontech 0:5868e8752d44 61
pythontech 0:5868e8752d44 62 STATIC mp_obj_t mp_obj_new_range_iterator(mp_int_t cur, mp_int_t stop, mp_int_t step) {
pythontech 0:5868e8752d44 63 mp_obj_range_it_t *o = m_new_obj(mp_obj_range_it_t);
pythontech 0:5868e8752d44 64 o->base.type = &range_it_type;
pythontech 0:5868e8752d44 65 o->cur = cur;
pythontech 0:5868e8752d44 66 o->stop = stop;
pythontech 0:5868e8752d44 67 o->step = step;
pythontech 0:5868e8752d44 68 return MP_OBJ_FROM_PTR(o);
pythontech 0:5868e8752d44 69 }
pythontech 0:5868e8752d44 70
pythontech 0:5868e8752d44 71 /******************************************************************************/
pythontech 0:5868e8752d44 72 /* range */
pythontech 0:5868e8752d44 73
pythontech 0:5868e8752d44 74 typedef struct _mp_obj_range_t {
pythontech 0:5868e8752d44 75 mp_obj_base_t base;
pythontech 0:5868e8752d44 76 // TODO make these values generic objects or something
pythontech 0:5868e8752d44 77 mp_int_t start;
pythontech 0:5868e8752d44 78 mp_int_t stop;
pythontech 0:5868e8752d44 79 mp_int_t step;
pythontech 0:5868e8752d44 80 } mp_obj_range_t;
pythontech 0:5868e8752d44 81
pythontech 0:5868e8752d44 82 STATIC void range_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pythontech 0:5868e8752d44 83 (void)kind;
pythontech 0:5868e8752d44 84 mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 85 mp_printf(print, "range(" INT_FMT ", " INT_FMT "", self->start, self->stop);
pythontech 0:5868e8752d44 86 if (self->step == 1) {
pythontech 0:5868e8752d44 87 mp_print_str(print, ")");
pythontech 0:5868e8752d44 88 } else {
pythontech 0:5868e8752d44 89 mp_printf(print, ", " INT_FMT ")", self->step);
pythontech 0:5868e8752d44 90 }
pythontech 0:5868e8752d44 91 }
pythontech 0:5868e8752d44 92
pythontech 0:5868e8752d44 93 STATIC mp_obj_t range_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
pythontech 0:5868e8752d44 94 mp_arg_check_num(n_args, n_kw, 1, 3, false);
pythontech 0:5868e8752d44 95
pythontech 0:5868e8752d44 96 mp_obj_range_t *o = m_new_obj(mp_obj_range_t);
pythontech 0:5868e8752d44 97 o->base.type = type;
pythontech 0:5868e8752d44 98 o->start = 0;
pythontech 0:5868e8752d44 99 o->step = 1;
pythontech 0:5868e8752d44 100
pythontech 0:5868e8752d44 101 if (n_args == 1) {
pythontech 0:5868e8752d44 102 o->stop = mp_obj_get_int(args[0]);
pythontech 0:5868e8752d44 103 } else {
pythontech 0:5868e8752d44 104 o->start = mp_obj_get_int(args[0]);
pythontech 0:5868e8752d44 105 o->stop = mp_obj_get_int(args[1]);
pythontech 0:5868e8752d44 106 if (n_args == 3) {
pythontech 0:5868e8752d44 107 // TODO check step is non-zero
pythontech 0:5868e8752d44 108 o->step = mp_obj_get_int(args[2]);
pythontech 0:5868e8752d44 109 }
pythontech 0:5868e8752d44 110 }
pythontech 0:5868e8752d44 111
pythontech 0:5868e8752d44 112 return MP_OBJ_FROM_PTR(o);
pythontech 0:5868e8752d44 113 }
pythontech 0:5868e8752d44 114
pythontech 0:5868e8752d44 115 STATIC mp_int_t range_len(mp_obj_range_t *self) {
pythontech 0:5868e8752d44 116 // When computing length, need to take into account step!=1 and step<0.
pythontech 0:5868e8752d44 117 mp_int_t len = self->stop - self->start + self->step;
pythontech 0:5868e8752d44 118 if (self->step > 0) {
pythontech 0:5868e8752d44 119 len -= 1;
pythontech 0:5868e8752d44 120 } else {
pythontech 0:5868e8752d44 121 len += 1;
pythontech 0:5868e8752d44 122 }
pythontech 0:5868e8752d44 123 len = len / self->step;
pythontech 0:5868e8752d44 124 if (len < 0) {
pythontech 0:5868e8752d44 125 len = 0;
pythontech 0:5868e8752d44 126 }
pythontech 0:5868e8752d44 127 return len;
pythontech 0:5868e8752d44 128 }
pythontech 0:5868e8752d44 129
pythontech 0:5868e8752d44 130 STATIC mp_obj_t range_unary_op(mp_uint_t op, mp_obj_t self_in) {
pythontech 0:5868e8752d44 131 mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 132 mp_int_t len = range_len(self);
pythontech 0:5868e8752d44 133 switch (op) {
pythontech 0:5868e8752d44 134 case MP_UNARY_OP_BOOL: return mp_obj_new_bool(len > 0);
pythontech 0:5868e8752d44 135 case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(len);
pythontech 0:5868e8752d44 136 default: return MP_OBJ_NULL; // op not supported
pythontech 0:5868e8752d44 137 }
pythontech 0:5868e8752d44 138 }
pythontech 0:5868e8752d44 139
pythontech 0:5868e8752d44 140 STATIC mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
pythontech 0:5868e8752d44 141 if (value == MP_OBJ_SENTINEL) {
pythontech 0:5868e8752d44 142 // load
pythontech 0:5868e8752d44 143 mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 144 mp_int_t len = range_len(self);
pythontech 0:5868e8752d44 145 #if MICROPY_PY_BUILTINS_SLICE
pythontech 0:5868e8752d44 146 if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
pythontech 0:5868e8752d44 147 mp_bound_slice_t slice;
pythontech 0:5868e8752d44 148 mp_seq_get_fast_slice_indexes(len, index, &slice);
pythontech 0:5868e8752d44 149 mp_obj_range_t *o = m_new_obj(mp_obj_range_t);
pythontech 0:5868e8752d44 150 o->base.type = &mp_type_range;
pythontech 0:5868e8752d44 151 o->start = self->start + slice.start * self->step;
pythontech 0:5868e8752d44 152 o->stop = self->start + slice.stop * self->step;
pythontech 0:5868e8752d44 153 o->step = slice.step * self->step;
pythontech 0:5868e8752d44 154 return MP_OBJ_FROM_PTR(o);
pythontech 0:5868e8752d44 155 }
pythontech 0:5868e8752d44 156 #endif
pythontech 0:5868e8752d44 157 uint index_val = mp_get_index(self->base.type, len, index, false);
pythontech 0:5868e8752d44 158 return MP_OBJ_NEW_SMALL_INT(self->start + index_val * self->step);
pythontech 0:5868e8752d44 159 } else {
pythontech 0:5868e8752d44 160 return MP_OBJ_NULL; // op not supported
pythontech 0:5868e8752d44 161 }
pythontech 0:5868e8752d44 162 }
pythontech 0:5868e8752d44 163
pythontech 0:5868e8752d44 164 STATIC mp_obj_t range_getiter(mp_obj_t o_in) {
pythontech 0:5868e8752d44 165 mp_obj_range_t *o = MP_OBJ_TO_PTR(o_in);
pythontech 0:5868e8752d44 166 return mp_obj_new_range_iterator(o->start, o->stop, o->step);
pythontech 0:5868e8752d44 167 }
pythontech 0:5868e8752d44 168
pythontech 0:5868e8752d44 169
pythontech 0:5868e8752d44 170 #if MICROPY_PY_BUILTINS_RANGE_ATTRS
pythontech 0:5868e8752d44 171 STATIC void range_attr(mp_obj_t o_in, qstr attr, mp_obj_t *dest) {
pythontech 0:5868e8752d44 172 if (dest[0] != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 173 // not load attribute
pythontech 0:5868e8752d44 174 return;
pythontech 0:5868e8752d44 175 }
pythontech 0:5868e8752d44 176 mp_obj_range_t *o = MP_OBJ_TO_PTR(o_in);
pythontech 0:5868e8752d44 177 if (attr == MP_QSTR_start) {
pythontech 0:5868e8752d44 178 dest[0] = mp_obj_new_int(o->start);
pythontech 0:5868e8752d44 179 } else if (attr == MP_QSTR_stop) {
pythontech 0:5868e8752d44 180 dest[0] = mp_obj_new_int(o->stop);
pythontech 0:5868e8752d44 181 } else if (attr == MP_QSTR_step) {
pythontech 0:5868e8752d44 182 dest[0] = mp_obj_new_int(o->step);
pythontech 0:5868e8752d44 183 }
pythontech 0:5868e8752d44 184 }
pythontech 0:5868e8752d44 185 #endif
pythontech 0:5868e8752d44 186
pythontech 0:5868e8752d44 187 const mp_obj_type_t mp_type_range = {
pythontech 0:5868e8752d44 188 { &mp_type_type },
pythontech 0:5868e8752d44 189 .name = MP_QSTR_range,
pythontech 0:5868e8752d44 190 .print = range_print,
pythontech 0:5868e8752d44 191 .make_new = range_make_new,
pythontech 0:5868e8752d44 192 .unary_op = range_unary_op,
pythontech 0:5868e8752d44 193 .subscr = range_subscr,
pythontech 0:5868e8752d44 194 .getiter = range_getiter,
pythontech 0:5868e8752d44 195 #if MICROPY_PY_BUILTINS_RANGE_ATTRS
pythontech 0:5868e8752d44 196 .attr = range_attr,
pythontech 0:5868e8752d44 197 #endif
pythontech 0:5868e8752d44 198 };