Skip to content

Commit 1aa2c10

Browse files
committed
Merge branch 'master' of github.com:micropython/micropython
2 parents 523b575 + 6ded55a commit 1aa2c10

8 files changed

Lines changed: 79 additions & 41 deletions

File tree

py/compile.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,9 @@ mp_parse_node_t fold_constants(mp_parse_node_t pn) {
145145
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) {
146146
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, python_modulo(arg0, arg1));
147147
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) {
148-
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, python_floor_divide(arg0, arg1));
148+
if (arg1 != 0) {
149+
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, python_floor_divide(arg0, arg1));
150+
}
149151
} else {
150152
// shouldn't happen
151153
assert(0);

py/obj.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ void mp_obj_print_exception(mp_obj_t exc) {
6262
}
6363
}
6464
}
65-
mp_obj_print(exc, PRINT_REPR);
65+
mp_obj_print(exc, PRINT_EXC);
6666
printf("\n");
6767
}
6868

py/obj.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,9 @@ typedef mp_obj_t (*mp_fun_var_t)(uint n, const mp_obj_t *);
141141
typedef mp_obj_t (*mp_fun_kw_t)(uint n, const mp_obj_t *, mp_map_t *);
142142

143143
typedef enum {
144-
PRINT_STR, PRINT_REPR
144+
PRINT_STR,
145+
PRINT_REPR,
146+
PRINT_EXC, // Special format for printing exception in unhandled exception message
145147
} mp_print_kind_t;
146148

147149
typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o, mp_print_kind_t kind);

py/objexcept.c

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,42 +11,34 @@
1111
#include "runtime.h"
1212
#include "runtime0.h"
1313

14-
// This is unified class for C-level and Python-level exceptions
15-
// Python-level exceptions have empty ->msg and all arguments are in
16-
// args tuple. C-level exceptions likely have ->msg set, and args is empty.
1714
typedef struct _mp_obj_exception_t {
1815
mp_obj_base_t base;
1916
mp_obj_t traceback; // a list object, holding (file,line,block) as numbers (not Python objects); a hack for now
20-
vstr_t *msg;
2117
mp_obj_tuple_t args;
2218
} mp_obj_exception_t;
2319

2420
// Instance of GeneratorExit exception - needed by generator.close()
2521
// This would belong to objgenerator.c, but to keep mp_obj_exception_t
2622
// definition module-private so far, have it here.
27-
const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, MP_OBJ_NULL, NULL, {{&mp_type_tuple}, 0}};
23+
const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, MP_OBJ_NULL, {{&mp_type_tuple}, 0}};
2824

2925
STATIC void mp_obj_exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
3026
mp_obj_exception_t *o = o_in;
31-
if (o->msg != NULL) {
32-
print(env, "%s: %s", qstr_str(o->base.type->name), vstr_str(o->msg));
33-
} else {
34-
// Yes, that's how CPython has it
35-
// TODO now that exceptions are classes and instances, I think this needs to be changed to match CPython
36-
if (kind == PRINT_REPR) {
37-
print(env, "%s", qstr_str(o->base.type->name));
38-
}
39-
if (kind == PRINT_STR) {
40-
if (o->args.len == 0) {
41-
print(env, "");
42-
return;
43-
} else if (o->args.len == 1) {
44-
mp_obj_print_helper(print, env, o->args.items[0], PRINT_STR);
45-
return;
46-
}
27+
if (kind == PRINT_REPR) {
28+
print(env, "%s", qstr_str(o->base.type->name));
29+
} else if (kind == PRINT_EXC) {
30+
print(env, "%s: ", qstr_str(o->base.type->name));
31+
}
32+
if (kind == PRINT_STR || kind == PRINT_EXC) {
33+
if (o->args.len == 0) {
34+
print(env, "");
35+
return;
36+
} else if (o->args.len == 1) {
37+
mp_obj_print_helper(print, env, o->args.items[0], PRINT_STR);
38+
return;
4739
}
48-
tuple_print(print, env, &o->args, kind);
4940
}
41+
tuple_print(print, env, &o->args, kind);
5042
}
5143

5244
STATIC mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
@@ -59,7 +51,6 @@ STATIC mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, uint n_args, uint n_
5951
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t, n_args);
6052
o->base.type = type;
6153
o->traceback = MP_OBJ_NULL;
62-
o->msg = NULL;
6354
o->args.base.type = &mp_type_tuple;
6455
o->args.len = n_args;
6556
memcpy(o->args.items, args, n_args * sizeof(mp_obj_t));
@@ -185,7 +176,7 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
185176
*/
186177

187178
mp_obj_t mp_obj_new_exception(const mp_obj_type_t *exc_type) {
188-
return mp_obj_new_exception_msg_varg(exc_type, NULL);
179+
return mp_obj_new_exception_args(exc_type, 0, NULL);
189180
}
190181

191182
mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, uint n_args, const mp_obj_t *args) {
@@ -202,22 +193,25 @@ mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char
202193
assert(exc_type->make_new == mp_obj_exception_make_new);
203194

204195
// make exception object
205-
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t, 0);
196+
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t, 1);
206197
o->base.type = exc_type;
207198
o->traceback = MP_OBJ_NULL;
208199
o->args.base.type = &mp_type_tuple;
209-
o->args.len = 0;
200+
o->args.len = 1;
210201

211202
if (fmt == NULL) {
212203
// no message
213-
o->msg = NULL;
204+
assert(0);
214205
} else {
215-
// render exception message
216-
o->msg = vstr_new();
206+
// render exception message and store as .args[0]
207+
// TODO: optimize bufferbloat
208+
vstr_t *vstr = vstr_new();
217209
va_list ap;
218210
va_start(ap, fmt);
219-
vstr_vprintf(o->msg, fmt, ap);
211+
vstr_vprintf(vstr, fmt, ap);
220212
va_end(ap);
213+
o->args.items[0] = mp_obj_new_str((byte*)vstr->buf, vstr->len, false);
214+
vstr_free(vstr);
221215
}
222216

223217
return o;

py/objfloat.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#include <stdlib.h>
2+
#include <stdio.h>
3+
#include <string.h>
24
#include <assert.h>
35
#include <math.h>
46

@@ -23,7 +25,13 @@ STATIC void float_print(void (*print)(void *env, const char *fmt, ...), void *en
2325
format_float(o->value, buf, sizeof(buf), 'g', 6, '\0');
2426
print(env, "%s", buf);
2527
#else
26-
print(env, "%.8g", (double) o->value);
28+
char buf[32];
29+
sprintf(buf, "%.8g", (double) o->value);
30+
print(env, buf);
31+
if (strchr(buf, '.') == NULL) {
32+
// Python floats always have decimal point
33+
print(env, ".0");
34+
}
2735
#endif
2836
}
2937

@@ -103,13 +111,15 @@ mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs_in) {
103111
case MP_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;
104112
case MP_BINARY_OP_MULTIPLY:
105113
case MP_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break;
106-
/* TODO floor(?) the value
114+
// TODO: verify that C floor matches Python semantics
107115
case MP_BINARY_OP_FLOOR_DIVIDE:
108-
case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break;
109-
*/
116+
case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE:
117+
lhs_val = MICROPY_FLOAT_C_FUN(floor)(lhs_val / rhs_val);
118+
goto check_zero_division;
110119
case MP_BINARY_OP_TRUE_DIVIDE:
111120
case MP_BINARY_OP_INPLACE_TRUE_DIVIDE:
112121
lhs_val /= rhs_val;
122+
check_zero_division:
113123
if (isinf(lhs_val)){ // check for division by zero
114124
nlr_jump(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "float division by zero"));
115125
}
@@ -119,7 +129,8 @@ mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs_in) {
119129
case MP_BINARY_OP_LESS_EQUAL: return MP_BOOL(lhs_val <= rhs_val);
120130
case MP_BINARY_OP_MORE_EQUAL: return MP_BOOL(lhs_val >= rhs_val);
121131

122-
return NULL; // op not supported
132+
default:
133+
return NULL; // op not supported
123134
}
124135
return mp_obj_new_float(lhs_val);
125136
}

py/runtime.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,13 +348,20 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
348348
}
349349
case MP_BINARY_OP_FLOOR_DIVIDE:
350350
case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE:
351-
{
351+
if (rhs_val == 0) {
352+
goto zero_division;
353+
}
352354
lhs_val = python_floor_divide(lhs_val, rhs_val);
353355
break;
354-
}
356+
355357
#if MICROPY_ENABLE_FLOAT
356358
case MP_BINARY_OP_TRUE_DIVIDE:
357-
case MP_BINARY_OP_INPLACE_TRUE_DIVIDE: return mp_obj_new_float((mp_float_t)lhs_val / (mp_float_t)rhs_val);
359+
case MP_BINARY_OP_INPLACE_TRUE_DIVIDE:
360+
if (rhs_val == 0) {
361+
zero_division:
362+
nlr_jump(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "division by zero"));
363+
}
364+
return mp_obj_new_float((mp_float_t)lhs_val / (mp_float_t)rhs_val);
358365
#endif
359366

360367
case MP_BINARY_OP_MODULO:

tests/basics/float1.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
11
# basic float
22
x = 1 / 2
33
print(x)
4+
5+
print(1.0 // 2)
6+
print(2.0 // 2)
7+
8+
try:
9+
1.0 / 0
10+
except ZeroDivisionError:
11+
print("ZeroDivisionError")
12+
13+
try:
14+
1.0 // 0
15+
except ZeroDivisionError:
16+
print("ZeroDivisionError")

tests/basics/int-divzero.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
try:
2+
1 / 0
3+
except ZeroDivisionError:
4+
print("ZeroDivisionError")
5+
6+
try:
7+
1 // 0
8+
except ZeroDivisionError:
9+
print("ZeroDivisionError")

0 commit comments

Comments
 (0)