Commit ff8007c7 authored by John R. Lenton's avatar John R. Lenton
Browse files

Merge remote-tracking branch 'upstream/master' into builtins

parents 9daa7894 c6920d31
The Micro Python project
========================
<p align="center">
<img src="https://raw2.github.com/micropython/micropython/master/logo/upython-with-micro.png" alt="MicroPython Logo"/>
</p>
This is the Micro Python project, which aims to put an implementation
of Python 3.x on a microcontroller.
......
......@@ -339,7 +339,7 @@ static mp_obj_t mp_builtin_sorted(mp_obj_t args, mp_map_t *kwargs) {
}
mp_obj_t self = list_type.make_new((mp_obj_t)&list_type, 1, args_items);
mp_obj_t new_args = rt_build_tuple(1, &self);
list_sort(new_args, kwargs);
mp_obj_list_sort(new_args, kwargs);
return self;
}
......
......@@ -614,7 +614,7 @@ mp_lexer_t *mp_lexer_new(const char *src_name, void *stream_data, mp_lexer_strea
lex->num_indent_level = 1;
lex->indent_level = m_new(uint16_t, lex->alloc_indent_level);
lex->indent_level[0] = 0;
vstr_init(&lex->vstr);
vstr_init(&lex->vstr, 32);
// preload characters
lex->chr0 = stream_next_char(stream_data);
......
......@@ -59,15 +59,19 @@ typedef struct _vstr_t {
bool had_error;
} vstr_t;
void vstr_init(vstr_t *vstr);
void vstr_init(vstr_t *vstr, int alloc);
void vstr_clear(vstr_t *vstr);
vstr_t *vstr_new(void);
vstr_t *vstr_new_size(int alloc);
void vstr_free(vstr_t *vstr);
void vstr_reset(vstr_t *vstr);
bool vstr_had_error(vstr_t *vstr);
char *vstr_str(vstr_t *vstr);
int vstr_len(vstr_t *vstr);
void vstr_hint_size(vstr_t *vstr, int size);
char *vstr_extend(vstr_t *vstr, int size);
bool vstr_set_size(vstr_t *vstr, int size);
bool vstr_shrink(vstr_t *vstr);
char *vstr_add_len(vstr_t *vstr, int len);
void vstr_add_byte(vstr_t *vstr, byte v);
void vstr_add_char(vstr_t *vstr, unichar chr);
......
......@@ -292,7 +292,7 @@ extern const mp_obj_type_t list_type;
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg);
void mp_obj_list_get(mp_obj_t self_in, uint *len, mp_obj_t **items);
void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value);
mp_obj_t list_sort(mp_obj_t args, struct _mp_map_t *kwargs);
mp_obj_t mp_obj_list_sort(mp_obj_t args, struct _mp_map_t *kwargs);
// enumerate
extern const mp_obj_type_t enumerate_type;
......
......@@ -57,6 +57,12 @@ static mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
return elem->value;
}
}
case RT_COMPARE_OP_IN:
case RT_COMPARE_OP_NOT_IN:
{
mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP);
return MP_BOOL((op == RT_COMPARE_OP_IN) ^ (elem == NULL));
}
default:
// op not supported
return NULL;
......@@ -362,10 +368,20 @@ static void dict_view_print(void (*print)(void *env, const char *fmt, ...), void
print(env, "])");
}
static mp_obj_t dict_view_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
/* only supported for the 'keys' kind until sets and dicts are refactored */
mp_obj_dict_view_t *o = lhs_in;
if (o->kind != MP_DICT_VIEW_KEYS) return NULL;
if (op != RT_COMPARE_OP_IN && op != RT_COMPARE_OP_NOT_IN) return NULL;
return dict_binary_op(op, o->dict, rhs_in);
}
static const mp_obj_type_t dict_view_type = {
{ &mp_const_type },
"dict_view",
.print = dict_view_print,
.binary_op = dict_view_binary_op,
.getiter = dict_view_getiter,
};
......
......@@ -8,105 +8,86 @@
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "objtuple.h"
// This is unified class for C-level and Python-level exceptions
// Python-level exception have empty ->msg and all arguments are in
// args tuple. C-level excepttion likely have ->msg, and may as well
// have args tuple (or otherwise have it as NULL).
typedef struct mp_obj_exception_t {
mp_obj_base_t base;
qstr id;
int n_args;
const void *args[];
qstr msg;
mp_obj_tuple_t args;
} mp_obj_exception_t;
void exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
mp_obj_exception_t *o = o_in;
switch (o->n_args) {
case 0:
print(env, "%s", qstr_str(o->id));
break;
case 1:
print(env, "%s: %s", qstr_str(o->id), (const char*)o->args[0]);
break;
case 2:
print(env, "%s: ", qstr_str(o->id));
print(env, (const char*)o->args[0], o->args[1]);
break;
default: // here we just assume at least 3 args, but only use first 3
print(env, "%s: ", qstr_str(o->id));
print(env, (const char*)o->args[0], o->args[1], o->args[2]);
break;
if (o->msg != 0) {
print(env, "%s: %s", qstr_str(o->id), qstr_str(o->msg));
} else {
print(env, "%s", qstr_str(o->id));
tuple_print(print, env, &o->args);
}
}
// args in reversed order
static mp_obj_t exception_call(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_exception_t *base = self_in;
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t*, n_args);
o->base.type = &exception_type;
o->id = base->id;
o->msg = 0;
o->args.len = n_args;
// TODO: factor out as reusable copy_reversed()
int j = 0;
for (int i = n_args - 1; i >= 0; i--) {
o->args.items[i] = args[j++];
}
return o;
}
const mp_obj_type_t exception_type = {
{ &mp_const_type },
"exception",
.print = exception_print,
.call_n = exception_call,
};
mp_obj_t mp_obj_new_exception(qstr id) {
mp_obj_exception_t *o = m_new_obj(mp_obj_exception_t);
o->base.type = &exception_type;
o->id = id;
o->n_args = 0;
return o;
return mp_obj_new_exception_msg_varg(id, NULL);
}
mp_obj_t mp_obj_new_exception_msg(qstr id, const char *msg) {
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 1);
o->base.type = &exception_type;
o->id = id;
o->n_args = 1;
o->args[0] = msg;
return o;
return mp_obj_new_exception_msg_varg(id, msg);
}
mp_obj_t mp_obj_new_exception_msg_1_arg(qstr id, const char *fmt, const char *a1) {
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 2);
o->base.type = &exception_type;
o->id = id;
o->n_args = 2;
o->args[0] = fmt;
o->args[1] = a1;
return o;
return mp_obj_new_exception_msg_varg(id, fmt, a1);
}
mp_obj_t mp_obj_new_exception_msg_2_args(qstr id, const char *fmt, const char *a1, const char *a2) {
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 3);
o->base.type = &exception_type;
o->id = id;
o->n_args = 3;
o->args[0] = fmt;
o->args[1] = a1;
o->args[2] = a2;
return o;
return mp_obj_new_exception_msg_varg(id, fmt, a1, a2);
}
mp_obj_t mp_obj_new_exception_msg_varg(qstr id, const char *fmt, ...) {
// count number of arguments by number of % signs, excluding %%
int n_args = 1; // count fmt
for (const char *s = fmt; *s; s++) {
if (*s == '%') {
if (s[1] == '%') {
s += 1;
} else {
n_args += 1;
}
}
}
// make exception object
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, n_args);
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t*, 0);
o->base.type = &exception_type;
o->id = id;
o->n_args = n_args;
o->args[0] = fmt;
// extract args and store them
va_list ap;
va_start(ap, fmt);
for (int i = 1; i < n_args; i++) {
o->args[i] = va_arg(ap, void*);
o->args.len = 0;
if (fmt == NULL) {
o->msg = 0;
} else {
// render exception message
vstr_t *vstr = vstr_new();
va_list ap;
va_start(ap, fmt);
vstr_vprintf(vstr, fmt, ap);
va_end(ap);
o->msg = qstr_from_str_take(vstr->buf, vstr->alloc);
}
va_end(ap);
return o;
}
......
......@@ -248,7 +248,7 @@ static void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, bool r
}
}
mp_obj_t list_sort(mp_obj_t args, mp_map_t *kwargs) {
mp_obj_t mp_obj_list_sort(mp_obj_t args, mp_map_t *kwargs) {
mp_obj_t *args_items = NULL;
uint args_len = 0;
......@@ -381,7 +381,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(list_insert_obj, list_insert);
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(list_pop_obj, 1, 2, list_pop);
static MP_DEFINE_CONST_FUN_OBJ_2(list_remove_obj, list_remove);
static MP_DEFINE_CONST_FUN_OBJ_1(list_reverse_obj, list_reverse);
static MP_DEFINE_CONST_FUN_OBJ_KW(list_sort_obj, 0, list_sort);
static MP_DEFINE_CONST_FUN_OBJ_KW(list_sort_obj, 0, mp_obj_list_sort);
static const mp_method_t list_type_methods[] = {
{ "append", &list_append_obj },
......
......@@ -45,6 +45,7 @@ void set_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj
print(env, "}");
}
static mp_obj_t set_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
switch (n_args) {
case 0:
......@@ -405,6 +406,13 @@ static mp_obj_t set_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
return set_issuperset(lhs, rhs);
case RT_COMPARE_OP_NOT_EQUAL:
return MP_BOOL(set_equal(lhs, rhs) == mp_const_false);
case RT_COMPARE_OP_IN:
case RT_COMPARE_OP_NOT_IN:
{
mp_obj_set_t *o = lhs;
mp_obj_t elem = mp_set_lookup(&o->set, rhs, MP_MAP_LOOKUP);
return MP_BOOL((op == RT_COMPARE_OP_IN) ^ (elem == NULL));
}
default:
// op not supported
return NULL;
......
......@@ -85,6 +85,15 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
return mp_obj_new_str(qstr_from_str_take(val, alloc_len));
}
break;
case RT_COMPARE_OP_IN:
case RT_COMPARE_OP_NOT_IN:
/* NOTE `a in b` is `b.__contains__(a)` */
if (MP_OBJ_IS_TYPE(rhs_in, &str_type)) {
const char *rhs_str = qstr_str(((mp_obj_str_t*)rhs_in)->qstr);
/* FIXME \0 in strs */
return MP_BOOL((op == RT_COMPARE_OP_IN) ^ (strstr(lhs_str, rhs_str) == NULL));
}
break;
}
return MP_OBJ_NULL; // op not supported
......
......@@ -12,12 +12,6 @@ typedef struct _mp_obj_zip_t {
mp_obj_t iters[];
} mp_obj_zip_t;
static mp_obj_t zip_getiter(mp_obj_t self_in) {
return self_in;
}
static mp_obj_t zip_iternext(mp_obj_t self_in);
static mp_obj_t zip_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
/* NOTE: args are backwards */
mp_obj_zip_t *o = m_new_obj_var(mp_obj_zip_t, mp_obj_t, n_args);
......@@ -29,13 +23,9 @@ static mp_obj_t zip_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args)
return o;
}
const mp_obj_type_t zip_type = {
{ &mp_const_type },
"zip",
.make_new = zip_make_new,
.iternext = zip_iternext,
.getiter = zip_getiter,
};
static mp_obj_t zip_getiter(mp_obj_t self_in) {
return self_in;
}
static mp_obj_t zip_iternext(mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &zip_type));
......@@ -57,3 +47,11 @@ static mp_obj_t zip_iternext(mp_obj_t self_in) {
}
return o;
}
const mp_obj_type_t zip_type = {
{ &mp_const_type },
"zip",
.make_new = zip_make_new,
.getiter = zip_getiter,
.iternext = zip_iternext,
};
......@@ -569,22 +569,57 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
} else if (MP_OBJ_IS_TYPE(rhs, &complex_type)) {
return mp_obj_complex_binary_op(op, lhs_val, 0, rhs);
}
} else {
if (MP_OBJ_IS_OBJ(lhs)) {
mp_obj_base_t *o = lhs;
}
/* deal with `in` and `not in`
*
* NOTE `a in b` is `b.__contains__(a)`, hence why the generic dispatch
* needs to go below
*/
if (op == RT_COMPARE_OP_IN || op == RT_COMPARE_OP_NOT_IN) {
if (!MP_OBJ_IS_SMALL_INT(rhs)) {
mp_obj_base_t *o = rhs;
if (o->type->binary_op != NULL) {
mp_obj_t result = o->type->binary_op(op, lhs, rhs);
if (result != NULL) {
return result;
mp_obj_t res = o->type->binary_op(op, rhs, lhs);
if (res != NULL) {
return res;
}
}
if (o->type->getiter != NULL) {
/* second attempt, walk the iterator */
mp_obj_t next = NULL;
mp_obj_t iter = rt_getiter(rhs);
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
if (mp_obj_equal(next, lhs)) {
return MP_BOOL(op == RT_COMPARE_OP_IN);
}
}
return MP_BOOL(op != RT_COMPARE_OP_IN);
}
}
nlr_jump(mp_obj_new_exception_msg_varg(
MP_QSTR_TypeError, "'%s' object is not iterable",
mp_obj_get_type_str(rhs)));
return mp_const_none;
}
if (MP_OBJ_IS_OBJ(lhs)) {
mp_obj_base_t *o = lhs;
if (o->type->binary_op != NULL) {
mp_obj_t result = o->type->binary_op(op, lhs, rhs);
if (result != NULL) {
return result;
}
}
// TODO implement dispatch for reverse binary ops
}
// TODO specify in error message what the operator is
nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError,
"unsupported operand types for binary operator: '%s', '%s'",
mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs)));
return mp_const_none;
}
mp_obj_t rt_make_function_from_id(int unique_code_id) {
......
......@@ -51,5 +51,47 @@ static mp_obj_t stream_write(mp_obj_t self_in, mp_obj_t arg) {
}
}
// TODO: should be in mpconfig.h
#define READ_SIZE 256
static mp_obj_t stream_readall(mp_obj_t self_in) {
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)self_in;
if (o->type->stream_p.read == NULL) {
// CPython: io.UnsupportedOperation, OSError subclass
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_OSError, "Operation not supported"));
}
int total_size = 0;
vstr_t *vstr = vstr_new_size(READ_SIZE);
char *buf = vstr_str(vstr);
char *p = buf;
int error;
int current_read = READ_SIZE;
while (true) {
machine_int_t out_sz = o->type->stream_p.read(self_in, p, current_read, &error);
if (out_sz == -1) {
nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", error));
}
if (out_sz == 0) {
break;
}
total_size += out_sz;
if (out_sz < current_read) {
current_read -= out_sz;
p += out_sz;
} else {
current_read = READ_SIZE;
p = vstr_extend(vstr, current_read);
if (p == NULL) {
// TODO
nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError/*MP_QSTR_RuntimeError*/, "Out of memory"));
}
}
}
vstr_set_size(vstr, total_size + 1); // TODO: for \0
buf[total_size] = 0;
return mp_obj_new_str(qstr_from_str_take(buf, total_size + 1));
}
MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_read_obj, stream_read);
MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_readall_obj, stream_readall);
MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_write_obj, stream_write);
extern const mp_obj_fun_native_t mp_stream_read_obj;
extern const mp_obj_fun_native_t mp_stream_readall_obj;
extern const mp_obj_fun_native_t mp_stream_write_obj;
......@@ -6,8 +6,8 @@
// returned value is always at least 1 greater than argument
#define ROUND_ALLOC(a) (((a) & ((~0) - 7)) + 8)
void vstr_init(vstr_t *vstr) {
vstr->alloc = 32;
void vstr_init(vstr_t *vstr, int alloc) {
vstr->alloc = alloc;
vstr->len = 0;
vstr->buf = m_new(char, vstr->alloc);
if (vstr->buf == NULL) {
......@@ -28,7 +28,16 @@ vstr_t *vstr_new(void) {
if (vstr == NULL) {
return NULL;
}
vstr_init(vstr);
vstr_init(vstr, 32);
return vstr;
}
vstr_t *vstr_new_size(int alloc) {
vstr_t *vstr = m_new(vstr_t, 1);
if (vstr == NULL) {
return NULL;
}
vstr_init(vstr, alloc);
return vstr;
}
......@@ -63,6 +72,36 @@ int vstr_len(vstr_t *vstr) {
return vstr->len;
}
// Extend vstr strictly to by requested size, return pointer to newly added chunk
char *vstr_extend(vstr_t *vstr, int size) {
char *new_buf = m_renew(char, vstr->buf, vstr->alloc, vstr->alloc + size);
if (new_buf == NULL) {
vstr->had_error = true;
return NULL;
}
char *p = new_buf + vstr->alloc;
vstr->alloc += size;
vstr->buf = new_buf;
return p;
}
// Shrink vstr to be given size
bool vstr_set_size(vstr_t *vstr, int size) {
char *new_buf = m_renew(char, vstr->buf, vstr->alloc, size);
if (new_buf == NULL) {
vstr->had_error = true;
return false;
}
vstr->buf = new_buf;
vstr->alloc = vstr->len = size;
return true;
}
// Shrink vstr allocation to its actual length
bool vstr_shrink(vstr_t *vstr) {
return vstr_set_size(vstr, vstr->len);
}
bool vstr_ensure_extra(vstr_t *vstr, int size) {
if (vstr->len + size + 1 > vstr->alloc) {
int new_alloc = ROUND_ALLOC((vstr->len + size + 1) * 2);
......
......@@ -33,6 +33,7 @@ CFLAGS += -Os -DNDEBUG
endif
LDFLAGS = --nostdlib -T stm32f405.ld
LIBS = $(shell $(CC) -print-libgcc-file-name)
SRC_C = \
main.c \
......@@ -57,6 +58,7 @@ SRC_C = \
pybwlan.c \
i2c.c \
usrsw.c \
adc.c \
SRC_S = \
startup_stm32f40xx.s \
......@@ -100,6 +102,7 @@ SRC_STM = \
usbd_storage_msd.c \
stm324x7i_eval.c \
stm324x7i_eval_sdio_sd.c \
stm32f4xx_adc.c \
#SRC_STM_OTG = \
# usb_hcd.c \
......@@ -143,7 +146,7 @@ $(BUILD)/flash1.bin: $(BUILD)/flash.elf
$(BUILD)/flash.elf: $(OBJ)
$(ECHO) "LINK $@"
$(Q)$(LD) $(LDFLAGS) -o $@ $(OBJ)
$(Q)$(LD) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
$(Q)$(SIZE) $@
$(BUILD)/%.o: %.s
......
#include <stdio.h>
#include <stm32f4xx_rcc.h>
#include <stm32f4xx_gpio.h>
#include <stm32f4xx_adc.h>
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "adc.h"
/* ADC defintions */
#define ADCx (ADC1)
#define ADCx_CLK (RCC_APB2Periph_ADC1)
#define ADC_NUM_CHANNELS (16)
/* Internally connected ADC channels Temp/VBAT/VREF*/
#if defined (STM32F40XX) || defined(STM32F41XX)
#define ADC_TEMP_CHANNEL (16)
#define ADC_VBAT_CHANNEL (18)
#define ADC_VREF_CHANNEL (17)
#elif defined (STM32F42XX) || defined(STM32F43XX)
#define ADC_TEMP_CHANNEL (18)
#define ADC_VBAT_CHANNEL (18) /* same channel as TEMP */
#define ADC_VREF_CHANNEL (17)
#endif
/* Core temperature sensor definitions */
#define CORE_TEMP_V25 (943) /* (0.76v/3.3v)*(2^ADC resoultion) */
#define CORE_TEMP_AVG_SLOPE (3) /* (2.5mv/3.3v)*(2^ADC resoultion) */
/* VBAT divider */
#if defined (STM32F40XX) || defined(STM32F41XX)
#define VBAT_DIV (2)
#elif defined (STM32F42XX) || defined(STM32F43XX)
#define VBAT_DIV (4)
#endif
/* GPIO struct */
typedef struct {
GPIO_TypeDef* port;
uint32_t pin;
} gpio_t;
/* ADC GPIOs */
static gpio_t adc_gpio[] = {
{GPIOA, GPIO_Pin_0}, /* ADC123_IN0 */
{GPIOA, GPIO_Pin_1}, /* ADC123_IN1 */
{GPIOA, GPIO_Pin_2}, /* ADC123_IN2 */
{GPIOA, GPIO_Pin_3}, /* ADC123_IN3 */
{GPIOA, GPIO_Pin_4}, /* ADC12_IN4 */
{GPIOA, GPIO_Pin_5}, /* ADC12_IN5 */
{GPIOA, GPIO_Pin_6}, /* ADC12_IN6 */
{GPIOA, GPIO_Pin_7}, /* ADC12_IN7 */
{GPIOB, GPIO_Pin_0}, /* ADC12_IN8 */