Skip to content

Commit e2e3d11

Browse files
committed
py: Fix up number operations and coercion.
1 parent 8137b00 commit e2e3d11

6 files changed

Lines changed: 131 additions & 100 deletions

File tree

examples/mandel.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
@micropython.native
2+
def in_set(c):
3+
z = 0
4+
for i in range(40):
5+
z = z*z + c
6+
if abs(z) > 60:
7+
return False
8+
return True
9+
10+
for v in range(31):
11+
line = []
12+
for u in range(91):
13+
line.append('*' if in_set((u / 30 - 2) + (v / 15 - 1) * 1j) else ' ')
14+
print(''.join(line))

py/asmx64.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ void asm_x64_end_pass(asm_x64_t *as) {
155155
//as->code_base = m_new(byte, as->code_size); need to allocale executable memory
156156
uint actual_alloc;
157157
as->code_base = alloc_mem(as->code_size, &actual_alloc, true);
158-
printf("code_size: %u\n", as->code_size);
158+
//printf("code_size: %u\n", as->code_size);
159159
}
160160

161161
/*

py/obj.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,12 @@ qstr mp_obj_str_get(mp_obj_t self_in);
200200
// float
201201
extern const mp_obj_type_t float_type;
202202
mp_float_t mp_obj_float_get(mp_obj_t self_in);
203+
mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs);
203204

204205
// complex
205206
extern const mp_obj_type_t complex_type;
206207
void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
208+
mp_obj_t mp_obj_complex_binary_op(int op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in);
207209
#endif
208210

209211
// tuple

py/objcomplex.c

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,14 @@ static mp_obj_t complex_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *a
4848
{
4949
mp_float_t real, imag;
5050
if (MP_OBJ_IS_TYPE(args[1], &complex_type)) {
51-
mp_obj_get_complex(args[1], &real, &imag);
51+
mp_obj_complex_get(args[1], &real, &imag);
5252
} else {
5353
real = mp_obj_get_float(args[1]);
5454
imag = 0;
5555
}
5656
if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
5757
mp_float_t real2, imag2;
58-
mp_obj_get_complex(args[0], &real2, &imag2);
58+
mp_obj_complex_get(args[0], &real2, &imag2);
5959
real -= imag2;
6060
imag += real2;
6161
} else {
@@ -80,9 +80,41 @@ static mp_obj_t complex_unary_op(int op, mp_obj_t o_in) {
8080
}
8181

8282
static mp_obj_t complex_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
83-
mp_float_t lhs_real, lhs_imag, rhs_real, rhs_imag;
84-
mp_obj_complex_get(lhs_in, &lhs_real, &lhs_imag);
85-
mp_obj_complex_get(rhs_in, &rhs_real, &rhs_imag);
83+
mp_obj_complex_t *lhs = lhs_in;
84+
return mp_obj_complex_binary_op(op, lhs->real, lhs->imag, rhs_in);
85+
}
86+
87+
const mp_obj_type_t complex_type = {
88+
{ &mp_const_type },
89+
"complex",
90+
complex_print, // print
91+
complex_make_new, // make_new
92+
NULL, // call_n
93+
complex_unary_op, // unary_op
94+
complex_binary_op, // binary_op
95+
NULL, // getiter
96+
NULL, // iternext
97+
.methods = { { NULL, NULL }, },
98+
};
99+
100+
mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag) {
101+
mp_obj_complex_t *o = m_new_obj(mp_obj_complex_t);
102+
o->base.type = &complex_type;
103+
o->real = real;
104+
o->imag = imag;
105+
return o;
106+
}
107+
108+
void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag) {
109+
assert(MP_OBJ_IS_TYPE(self_in, &complex_type));
110+
mp_obj_complex_t *self = self_in;
111+
*real = self->real;
112+
*imag = self->imag;
113+
}
114+
115+
mp_obj_t mp_obj_complex_binary_op(int op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in) {
116+
mp_float_t rhs_real, rhs_imag;
117+
mp_obj_get_complex(rhs_in, &rhs_real, &rhs_imag); // can be any type, this function will convert to float (if possible)
86118
switch (op) {
87119
case RT_BINARY_OP_ADD:
88120
case RT_BINARY_OP_INPLACE_ADD:
@@ -115,32 +147,4 @@ static mp_obj_t complex_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
115147
return mp_obj_new_complex(lhs_real, lhs_imag);
116148
}
117149

118-
const mp_obj_type_t complex_type = {
119-
{ &mp_const_type },
120-
"complex",
121-
complex_print, // print
122-
complex_make_new, // make_new
123-
NULL, // call_n
124-
complex_unary_op, // unary_op
125-
complex_binary_op, // binary_op
126-
NULL, // getiter
127-
NULL, // iternext
128-
.methods = { { NULL, NULL }, },
129-
};
130-
131-
mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag) {
132-
mp_obj_complex_t *o = m_new_obj(mp_obj_complex_t);
133-
o->base.type = &complex_type;
134-
o->real = real;
135-
o->imag = imag;
136-
return o;
137-
}
138-
139-
void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag) {
140-
assert(MP_OBJ_IS_TYPE(self_in, &complex_type));
141-
mp_obj_complex_t *self = self_in;
142-
*real = self->real;
143-
*imag = self->imag;
144-
}
145-
146150
#endif

py/objfloat.c

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -53,27 +53,12 @@ static mp_obj_t float_unary_op(int op, mp_obj_t o_in) {
5353
}
5454

5555
static mp_obj_t float_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
56+
mp_obj_float_t *lhs = lhs_in;
5657
if (MP_OBJ_IS_TYPE(rhs_in, &complex_type)) {
57-
return complex_type.binary_op(op, lhs_in, rhs_in);
58+
return mp_obj_complex_binary_op(op, lhs->value, 0, rhs_in);
59+
} else {
60+
return mp_obj_float_binary_op(op, lhs->value, rhs_in);
5861
}
59-
mp_float_t lhs_val = mp_obj_get_float(lhs_in);
60-
mp_float_t rhs_val = mp_obj_get_float(rhs_in);
61-
switch (op) {
62-
case RT_BINARY_OP_ADD:
63-
case RT_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;
64-
case RT_BINARY_OP_SUBTRACT:
65-
case RT_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;
66-
case RT_BINARY_OP_MULTIPLY:
67-
case RT_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break;
68-
/* TODO floor(?) the value
69-
case RT_BINARY_OP_FLOOR_DIVIDE:
70-
case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break;
71-
*/
72-
case RT_BINARY_OP_TRUE_DIVIDE:
73-
case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: lhs_val /= rhs_val; break;
74-
return NULL; // op not supported
75-
}
76-
return mp_obj_new_float(lhs_val);
7762
}
7863

7964
const mp_obj_type_t float_type = {
@@ -99,4 +84,24 @@ mp_float_t mp_obj_float_get(mp_obj_t self_in) {
9984
return self->value;
10085
}
10186

87+
mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs_in) {
88+
mp_float_t rhs_val = mp_obj_get_float(rhs_in); // can be any type, this function will convert to float (if possible)
89+
switch (op) {
90+
case RT_BINARY_OP_ADD:
91+
case RT_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;
92+
case RT_BINARY_OP_SUBTRACT:
93+
case RT_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;
94+
case RT_BINARY_OP_MULTIPLY:
95+
case RT_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break;
96+
/* TODO floor(?) the value
97+
case RT_BINARY_OP_FLOOR_DIVIDE:
98+
case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break;
99+
*/
100+
case RT_BINARY_OP_TRUE_DIVIDE:
101+
case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: lhs_val /= rhs_val; break;
102+
return NULL; // op not supported
103+
}
104+
return mp_obj_new_float(lhs_val);
105+
}
106+
102107
#endif

py/runtime.c

Lines changed: 53 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -452,57 +452,63 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
452452
// then fail
453453
// note that list does not implement + or +=, so that inplace_concat is reached first for +=
454454

455-
if (MP_OBJ_IS_SMALL_INT(lhs) && MP_OBJ_IS_SMALL_INT(rhs)) {
455+
if (MP_OBJ_IS_SMALL_INT(lhs)) {
456456
mp_small_int_t lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs);
457-
mp_small_int_t rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs);
458-
switch (op) {
459-
case RT_BINARY_OP_OR:
460-
case RT_BINARY_OP_INPLACE_OR: lhs_val |= rhs_val; break;
461-
case RT_BINARY_OP_XOR:
462-
case RT_BINARY_OP_INPLACE_XOR: lhs_val ^= rhs_val; break;
463-
case RT_BINARY_OP_AND:
464-
case RT_BINARY_OP_INPLACE_AND: lhs_val &= rhs_val; break;
465-
case RT_BINARY_OP_LSHIFT:
466-
case RT_BINARY_OP_INPLACE_LSHIFT: lhs_val <<= rhs_val; break;
467-
case RT_BINARY_OP_RSHIFT:
468-
case RT_BINARY_OP_INPLACE_RSHIFT: lhs_val >>= rhs_val; break;
469-
case RT_BINARY_OP_ADD:
470-
case RT_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;
471-
case RT_BINARY_OP_SUBTRACT:
472-
case RT_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;
473-
case RT_BINARY_OP_MULTIPLY:
474-
case RT_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break;
475-
case RT_BINARY_OP_FLOOR_DIVIDE:
476-
case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: lhs_val /= rhs_val; break;
477-
#if MICROPY_ENABLE_FLOAT
478-
case RT_BINARY_OP_TRUE_DIVIDE:
479-
case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: return mp_obj_new_float((mp_float_t)lhs_val / (mp_float_t)rhs_val);
480-
#endif
481-
482-
// TODO implement modulo as specified by Python
483-
case RT_BINARY_OP_MODULO:
484-
case RT_BINARY_OP_INPLACE_MODULO: lhs_val %= rhs_val; break;
485-
486-
// TODO check for negative power, and overflow
487-
case RT_BINARY_OP_POWER:
488-
case RT_BINARY_OP_INPLACE_POWER:
489-
{
490-
int ans = 1;
491-
while (rhs_val > 0) {
492-
if (rhs_val & 1) {
493-
ans *= lhs_val;
457+
if (MP_OBJ_IS_SMALL_INT(rhs)) {
458+
mp_small_int_t rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs);
459+
switch (op) {
460+
case RT_BINARY_OP_OR:
461+
case RT_BINARY_OP_INPLACE_OR: lhs_val |= rhs_val; break;
462+
case RT_BINARY_OP_XOR:
463+
case RT_BINARY_OP_INPLACE_XOR: lhs_val ^= rhs_val; break;
464+
case RT_BINARY_OP_AND:
465+
case RT_BINARY_OP_INPLACE_AND: lhs_val &= rhs_val; break;
466+
case RT_BINARY_OP_LSHIFT:
467+
case RT_BINARY_OP_INPLACE_LSHIFT: lhs_val <<= rhs_val; break;
468+
case RT_BINARY_OP_RSHIFT:
469+
case RT_BINARY_OP_INPLACE_RSHIFT: lhs_val >>= rhs_val; break;
470+
case RT_BINARY_OP_ADD:
471+
case RT_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;
472+
case RT_BINARY_OP_SUBTRACT:
473+
case RT_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;
474+
case RT_BINARY_OP_MULTIPLY:
475+
case RT_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break;
476+
case RT_BINARY_OP_FLOOR_DIVIDE:
477+
case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: lhs_val /= rhs_val; break;
478+
#if MICROPY_ENABLE_FLOAT
479+
case RT_BINARY_OP_TRUE_DIVIDE:
480+
case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: return mp_obj_new_float((mp_float_t)lhs_val / (mp_float_t)rhs_val);
481+
#endif
482+
483+
// TODO implement modulo as specified by Python
484+
case RT_BINARY_OP_MODULO:
485+
case RT_BINARY_OP_INPLACE_MODULO: lhs_val %= rhs_val; break;
486+
487+
// TODO check for negative power, and overflow
488+
case RT_BINARY_OP_POWER:
489+
case RT_BINARY_OP_INPLACE_POWER:
490+
{
491+
int ans = 1;
492+
while (rhs_val > 0) {
493+
if (rhs_val & 1) {
494+
ans *= lhs_val;
495+
}
496+
lhs_val *= lhs_val;
497+
rhs_val /= 2;
494498
}
495-
lhs_val *= lhs_val;
496-
rhs_val /= 2;
499+
lhs_val = ans;
500+
break;
497501
}
498-
lhs_val = ans;
499-
break;
500-
}
501502

502-
default: assert(0);
503-
}
504-
if (fit_small_int(lhs_val)) {
505-
return MP_OBJ_NEW_SMALL_INT(lhs_val);
503+
default: assert(0);
504+
}
505+
if (fit_small_int(lhs_val)) {
506+
return MP_OBJ_NEW_SMALL_INT(lhs_val);
507+
}
508+
} else if (MP_OBJ_IS_TYPE(rhs, &float_type)) {
509+
return mp_obj_float_binary_op(op, lhs_val, rhs);
510+
} else if (MP_OBJ_IS_TYPE(rhs, &complex_type)) {
511+
return mp_obj_complex_binary_op(op, lhs_val, 0, rhs);
506512
}
507513
} else if (MP_OBJ_IS_OBJ(lhs)) {
508514
mp_obj_base_t *o = lhs;

0 commit comments

Comments
 (0)