Implement ROMable modules. Add math module.
mp_module_obj_t can now be put in ROM. Configuration of float type is now similar to longint: can now choose none, float or double as the implementation. math module has basic math functions. For STM port, these are not yet implemented (they are just stub functions).
This commit is contained in:
parent
8fd7d7e102
commit
0c36da0b59
12
py/builtin.c
12
py/builtin.c
|
@ -15,6 +15,10 @@
|
|||
#include "map.h"
|
||||
#include "builtin.h"
|
||||
|
||||
#if MICROPY_ENABLE_FLOAT
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
// args[0] is function from class body
|
||||
// args[1] is class name
|
||||
// args[2:] are base objects
|
||||
|
@ -79,7 +83,7 @@ mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
|
|||
}
|
||||
return MP_OBJ_NEW_SMALL_INT(val);
|
||||
#if MICROPY_ENABLE_FLOAT
|
||||
} else if (MP_OBJ_IS_TYPE(o_in, &float_type)) {
|
||||
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_float)) {
|
||||
mp_float_t value = mp_obj_float_get(o_in);
|
||||
// TODO check for NaN etc
|
||||
if (value < 0) {
|
||||
|
@ -87,10 +91,10 @@ mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
|
|||
} else {
|
||||
return o_in;
|
||||
}
|
||||
} else if (MP_OBJ_IS_TYPE(o_in, &complex_type)) {
|
||||
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_complex)) {
|
||||
mp_float_t real, imag;
|
||||
mp_obj_complex_get(o_in, &real, &imag);
|
||||
return mp_obj_new_float(machine_sqrt(real*real + imag*imag));
|
||||
return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(real*real + imag*imag));
|
||||
#endif
|
||||
} else {
|
||||
assert(0);
|
||||
|
@ -158,7 +162,7 @@ STATIC mp_obj_t mp_builtin_dir(uint n_args, const mp_obj_t *args) {
|
|||
} else { // n_args == 1
|
||||
// make a list of names in the given object
|
||||
mp_obj_type_t *type = mp_obj_get_type(args[0]);
|
||||
if (type == &module_type) {
|
||||
if (type == &mp_type_module) {
|
||||
map = mp_obj_module_get_globals(args[0]);
|
||||
} else if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &dict_type)) {
|
||||
map = mp_obj_dict_get_map(type->locals_dict);
|
||||
|
|
|
@ -34,4 +34,5 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_str_obj);
|
|||
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_namedtuple_obj);
|
||||
|
||||
void mp_module_micropython_init(void);
|
||||
extern const mp_obj_module_t mp_module_math;
|
||||
extern const mp_obj_module_t mp_module_micropython;
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "map.h"
|
||||
#include "builtin.h"
|
||||
|
||||
#if MICROPY_ENABLE_FLOAT
|
||||
|
||||
#define MATH_FUN_1(py_name, c_name) \
|
||||
mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
|
||||
|
||||
#define MATH_FUN_2(py_name, c_name) \
|
||||
mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj), mp_obj_get_float(y_obj))); } \
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_## py_name ## _obj, mp_math_ ## py_name);
|
||||
|
||||
STATIC const mp_obj_float_t mp_math_pi_obj = {{&mp_type_float}, M_PI};
|
||||
|
||||
MATH_FUN_1(sqrt, sqrt)
|
||||
MATH_FUN_2(pow, pow)
|
||||
MATH_FUN_1(exp, exp)
|
||||
MATH_FUN_1(log, log)
|
||||
MATH_FUN_1(log2, log2)
|
||||
MATH_FUN_1(log10, log10)
|
||||
MATH_FUN_1(cosh, cosh)
|
||||
MATH_FUN_1(sinh, sinh)
|
||||
MATH_FUN_1(tanh, tanh)
|
||||
MATH_FUN_1(acosh, acosh)
|
||||
MATH_FUN_1(asinh, asinh)
|
||||
MATH_FUN_1(atanh, atanh)
|
||||
MATH_FUN_1(cos, cos)
|
||||
MATH_FUN_1(sin, sin)
|
||||
MATH_FUN_1(tan, tan)
|
||||
MATH_FUN_1(acos, acos)
|
||||
MATH_FUN_1(asin, asin)
|
||||
MATH_FUN_1(atan, atan)
|
||||
MATH_FUN_2(atan2, atan2)
|
||||
|
||||
STATIC const mp_map_elem_t mp_module_math_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_math) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_pi), (mp_obj_t)&mp_math_pi_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sqrt), (mp_obj_t)&mp_math_sqrt_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_pow), (mp_obj_t)&mp_math_pow_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_exp), (mp_obj_t)&mp_math_exp_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_log), (mp_obj_t)&mp_math_log_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_log2), (mp_obj_t)&mp_math_log2_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_log10), (mp_obj_t)&mp_math_log10_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_cosh), (mp_obj_t)&mp_math_cosh_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sinh), (mp_obj_t)&mp_math_sinh_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_tanh), (mp_obj_t)&mp_math_tanh_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_acosh), (mp_obj_t)&mp_math_acosh_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_asinh), (mp_obj_t)&mp_math_asinh_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_atanh), (mp_obj_t)&mp_math_atanh_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_cos), (mp_obj_t)&mp_math_cos_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sin), (mp_obj_t)&mp_math_sin_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_tan), (mp_obj_t)&mp_math_tan_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_acos), (mp_obj_t)&mp_math_acos_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_asin), (mp_obj_t)&mp_math_asin_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_atan), (mp_obj_t)&mp_math_atan_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_atan2), (mp_obj_t)&mp_math_atan2_obj },
|
||||
};
|
||||
|
||||
STATIC const mp_map_t mp_module_math_globals = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = sizeof(mp_module_math_globals_table) / sizeof(mp_map_elem_t),
|
||||
.alloc = sizeof(mp_module_math_globals_table) / sizeof(mp_map_elem_t),
|
||||
.table = (mp_map_elem_t*)mp_module_math_globals_table,
|
||||
};
|
||||
|
||||
const mp_obj_module_t mp_module_math = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_math,
|
||||
.globals = (mp_map_t*)&mp_module_math_globals,
|
||||
};
|
||||
|
||||
#endif // MICROPY_ENABLE_FLOAT
|
|
@ -1,45 +1,52 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "runtime.h"
|
||||
#include "map.h"
|
||||
#include "builtin.h"
|
||||
|
||||
// Various builtins specific to MicroPython runtime,
|
||||
// living in micropython module
|
||||
|
||||
#if MICROPY_MEM_STATS
|
||||
STATIC mp_obj_t mem_total() {
|
||||
STATIC mp_obj_t mp_micropython_mem_total() {
|
||||
return MP_OBJ_NEW_SMALL_INT((machine_int_t)m_get_total_bytes_allocated());
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mem_current() {
|
||||
STATIC mp_obj_t mp_micropython_mem_current() {
|
||||
return MP_OBJ_NEW_SMALL_INT((machine_int_t)m_get_current_bytes_allocated());
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mem_peak() {
|
||||
STATIC mp_obj_t mp_micropython_mem_peak() {
|
||||
return MP_OBJ_NEW_SMALL_INT((machine_int_t)m_get_peak_bytes_allocated());
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_mem_total_obj, mem_total);
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_mem_current_obj, mem_current);
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_mem_peak_obj, mem_peak);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_total_obj, mp_micropython_mem_total);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_current_obj, mp_micropython_mem_current);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_peak_obj, mp_micropython_mem_peak);
|
||||
#endif
|
||||
|
||||
void mp_module_micropython_init(void) {
|
||||
mp_obj_t m_mp = mp_obj_new_module(MP_QSTR_micropython);
|
||||
rt_store_name(MP_QSTR_micropython, m_mp);
|
||||
|
||||
STATIC const mp_map_elem_t mp_module_micropython_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_micropython) },
|
||||
#if MICROPY_MEM_STATS
|
||||
rt_store_attr(m_mp, QSTR_FROM_STR_STATIC("mem_total"), (mp_obj_t)&mp_builtin_mem_total_obj);
|
||||
rt_store_attr(m_mp, QSTR_FROM_STR_STATIC("mem_current"), (mp_obj_t)&mp_builtin_mem_current_obj);
|
||||
rt_store_attr(m_mp, QSTR_FROM_STR_STATIC("mem_peak"), (mp_obj_t)&mp_builtin_mem_peak_obj);
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_total), (mp_obj_t)&mp_micropython_mem_total_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_current), (mp_obj_t)&mp_micropython_mem_current_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_peak), (mp_obj_t)&mp_micropython_mem_peak_obj },
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
STATIC const mp_map_t mp_module_micropython_globals = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = sizeof(mp_module_micropython_globals_table) / sizeof(mp_map_elem_t),
|
||||
.alloc = sizeof(mp_module_micropython_globals_table) / sizeof(mp_map_elem_t),
|
||||
.table = (mp_map_elem_t*)mp_module_micropython_globals_table,
|
||||
};
|
||||
|
||||
const mp_obj_module_t mp_module_micropython = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_micropython,
|
||||
.globals = (mp_map_t*)&mp_module_micropython_globals,
|
||||
};
|
||||
|
|
|
@ -84,8 +84,24 @@ typedef long long mp_longint_impl_t;
|
|||
#define MICROPY_ENABLE_SOURCE_LINE (0)
|
||||
#endif
|
||||
|
||||
// Whether to support float and complex types
|
||||
#ifndef MICROPY_ENABLE_FLOAT
|
||||
// Float and complex implementation
|
||||
#define MICROPY_FLOAT_IMPL_NONE (0)
|
||||
#define MICROPY_FLOAT_IMPL_FLOAT (1)
|
||||
#define MICROPY_FLOAT_IMPL_DOUBLE (2)
|
||||
|
||||
#ifndef MICROPY_FLOAT_IMPL
|
||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
|
||||
#endif
|
||||
|
||||
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
|
||||
#define MICROPY_ENABLE_FLOAT (1)
|
||||
#define MICROPY_FLOAT_C_FUN(fun) fun##f
|
||||
typedef float mp_float_t;
|
||||
#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
|
||||
#define MICROPY_ENABLE_FLOAT (1)
|
||||
#define MICROPY_FLOAT_C_FUN(fun) fun
|
||||
typedef double mp_float_t;
|
||||
#else
|
||||
#define MICROPY_ENABLE_FLOAT (0)
|
||||
#endif
|
||||
|
||||
|
|
8
py/obj.c
8
py/obj.c
|
@ -165,14 +165,14 @@ machine_int_t mp_obj_get_int(mp_obj_t arg) {
|
|||
}
|
||||
|
||||
#if MICROPY_ENABLE_FLOAT
|
||||
machine_float_t mp_obj_get_float(mp_obj_t arg) {
|
||||
mp_float_t mp_obj_get_float(mp_obj_t arg) {
|
||||
if (arg == mp_const_false) {
|
||||
return 0;
|
||||
} else if (arg == mp_const_true) {
|
||||
return 1;
|
||||
} else if (MP_OBJ_IS_SMALL_INT(arg)) {
|
||||
return MP_OBJ_SMALL_INT_VALUE(arg);
|
||||
} else if (MP_OBJ_IS_TYPE(arg, &float_type)) {
|
||||
} else if (MP_OBJ_IS_TYPE(arg, &mp_type_float)) {
|
||||
return mp_obj_float_get(arg);
|
||||
} else {
|
||||
nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg)));
|
||||
|
@ -189,10 +189,10 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
|
|||
} else if (MP_OBJ_IS_SMALL_INT(arg)) {
|
||||
*real = MP_OBJ_SMALL_INT_VALUE(arg);
|
||||
*imag = 0;
|
||||
} else if (MP_OBJ_IS_TYPE(arg, &float_type)) {
|
||||
} else if (MP_OBJ_IS_TYPE(arg, &mp_type_float)) {
|
||||
*real = mp_obj_float_get(arg);
|
||||
*imag = 0;
|
||||
} else if (MP_OBJ_IS_TYPE(arg, &complex_type)) {
|
||||
} else if (MP_OBJ_IS_TYPE(arg, &mp_type_complex)) {
|
||||
mp_obj_complex_get(arg, real, imag);
|
||||
} else {
|
||||
nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg)));
|
||||
|
|
21
py/obj.h
21
py/obj.h
|
@ -9,12 +9,6 @@ typedef machine_const_ptr_t mp_const_obj_t;
|
|||
|
||||
typedef machine_int_t mp_small_int_t;
|
||||
|
||||
// The machine floating-point type used for float and complex numbers
|
||||
|
||||
#if MICROPY_ENABLE_FLOAT
|
||||
typedef machine_float_t mp_float_t;
|
||||
#endif
|
||||
|
||||
// Anything that wants to be a Micro Python object must have
|
||||
// mp_obj_base_t as its first member (except NULL and small ints)
|
||||
|
||||
|
@ -318,12 +312,16 @@ extern const mp_obj_type_t bytes_type;
|
|||
|
||||
#if MICROPY_ENABLE_FLOAT
|
||||
// float
|
||||
extern const mp_obj_type_t float_type;
|
||||
typedef struct _mp_obj_float_t {
|
||||
mp_obj_base_t base;
|
||||
mp_float_t value;
|
||||
} mp_obj_float_t;
|
||||
extern const mp_obj_type_t mp_type_float;
|
||||
mp_float_t mp_obj_float_get(mp_obj_t self_in);
|
||||
mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs);
|
||||
|
||||
// complex
|
||||
extern const mp_obj_type_t complex_type;
|
||||
extern const mp_obj_type_t mp_type_complex;
|
||||
void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
|
||||
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);
|
||||
#endif
|
||||
|
@ -398,7 +396,12 @@ extern const mp_obj_type_t super_type;
|
|||
extern const mp_obj_type_t gen_instance_type;
|
||||
|
||||
// module
|
||||
extern const mp_obj_type_t module_type;
|
||||
typedef struct _mp_obj_module_t {
|
||||
mp_obj_base_t base;
|
||||
qstr name;
|
||||
struct _mp_map_t *globals;
|
||||
} mp_obj_module_t;
|
||||
extern const mp_obj_type_t mp_type_module;
|
||||
mp_obj_t mp_obj_new_module(qstr module_name);
|
||||
mp_obj_t mp_obj_module_get(qstr module_name);
|
||||
struct _mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in);
|
||||
|
|
|
@ -39,7 +39,7 @@ STATIC mp_obj_t complex_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const
|
|||
|
||||
case 1:
|
||||
// TODO allow string as first arg and parse it
|
||||
if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
|
||||
if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) {
|
||||
return args[0];
|
||||
} else {
|
||||
return mp_obj_new_complex(mp_obj_get_float(args[0]), 0);
|
||||
|
@ -48,13 +48,13 @@ STATIC mp_obj_t complex_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const
|
|||
case 2:
|
||||
{
|
||||
mp_float_t real, imag;
|
||||
if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
|
||||
if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) {
|
||||
mp_obj_complex_get(args[0], &real, &imag);
|
||||
} else {
|
||||
real = mp_obj_get_float(args[0]);
|
||||
imag = 0;
|
||||
}
|
||||
if (MP_OBJ_IS_TYPE(args[1], &complex_type)) {
|
||||
if (MP_OBJ_IS_TYPE(args[1], &mp_type_complex)) {
|
||||
mp_float_t real2, imag2;
|
||||
mp_obj_complex_get(args[1], &real2, &imag2);
|
||||
real -= imag2;
|
||||
|
@ -85,7 +85,7 @@ STATIC mp_obj_t complex_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
|||
return mp_obj_complex_binary_op(op, lhs->real, lhs->imag, rhs_in);
|
||||
}
|
||||
|
||||
const mp_obj_type_t complex_type = {
|
||||
const mp_obj_type_t mp_type_complex = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_complex,
|
||||
.print = complex_print,
|
||||
|
@ -96,14 +96,14 @@ const mp_obj_type_t complex_type = {
|
|||
|
||||
mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag) {
|
||||
mp_obj_complex_t *o = m_new_obj(mp_obj_complex_t);
|
||||
o->base.type = &complex_type;
|
||||
o->base.type = &mp_type_complex;
|
||||
o->real = real;
|
||||
o->imag = imag;
|
||||
return o;
|
||||
}
|
||||
|
||||
void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &complex_type));
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_complex));
|
||||
mp_obj_complex_t *self = self_in;
|
||||
*real = self->real;
|
||||
*imag = self->imag;
|
||||
|
|
|
@ -13,11 +13,6 @@
|
|||
|
||||
#if MICROPY_ENABLE_FLOAT
|
||||
|
||||
typedef struct _mp_obj_float_t {
|
||||
mp_obj_base_t base;
|
||||
mp_float_t value;
|
||||
} mp_obj_float_t;
|
||||
|
||||
mp_obj_t mp_obj_new_float(mp_float_t value);
|
||||
|
||||
STATIC void float_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
|
||||
|
@ -38,7 +33,7 @@ STATIC mp_obj_t float_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m
|
|||
uint l;
|
||||
const char *s = mp_obj_str_get_data(args[0], &l);
|
||||
return mp_parse_num_decimal(s, l);
|
||||
} else if (MP_OBJ_IS_TYPE(args[0], &float_type)) {
|
||||
} else if (MP_OBJ_IS_TYPE(args[0], &mp_type_float)) {
|
||||
return args[0];
|
||||
} else {
|
||||
return mp_obj_new_float(mp_obj_get_float(args[0]));
|
||||
|
@ -61,14 +56,14 @@ STATIC mp_obj_t float_unary_op(int op, mp_obj_t o_in) {
|
|||
|
||||
STATIC mp_obj_t float_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
mp_obj_float_t *lhs = lhs_in;
|
||||
if (MP_OBJ_IS_TYPE(rhs_in, &complex_type)) {
|
||||
if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) {
|
||||
return mp_obj_complex_binary_op(op, lhs->value, 0, rhs_in);
|
||||
} else {
|
||||
return mp_obj_float_binary_op(op, lhs->value, rhs_in);
|
||||
}
|
||||
}
|
||||
|
||||
const mp_obj_type_t float_type = {
|
||||
const mp_obj_type_t mp_type_float = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_float,
|
||||
.print = float_print,
|
||||
|
@ -79,13 +74,13 @@ const mp_obj_type_t float_type = {
|
|||
|
||||
mp_obj_t mp_obj_new_float(mp_float_t value) {
|
||||
mp_obj_float_t *o = m_new(mp_obj_float_t, 1);
|
||||
o->base.type = &float_type;
|
||||
o->base.type = &mp_type_float;
|
||||
o->value = value;
|
||||
return (mp_obj_t)o;
|
||||
}
|
||||
|
||||
mp_float_t mp_obj_float_get(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &float_type));
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_float));
|
||||
mp_obj_float_t *self = self_in;
|
||||
return self->value;
|
||||
}
|
||||
|
|
|
@ -372,7 +372,7 @@ STATIC machine_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
|
|||
uint l;
|
||||
return (machine_uint_t)mp_obj_str_get_data(obj, &l);
|
||||
#if MICROPY_ENABLE_FLOAT
|
||||
} else if (MP_OBJ_IS_TYPE(obj, &float_type)) {
|
||||
} else if (MP_OBJ_IS_TYPE(obj, &mp_type_float)) {
|
||||
// convert float to int (could also pass in float registers)
|
||||
return (machine_int_t)mp_obj_float_get(obj);
|
||||
#endif
|
||||
|
|
|
@ -10,12 +10,7 @@
|
|||
#include "obj.h"
|
||||
#include "runtime.h"
|
||||
#include "map.h"
|
||||
|
||||
typedef struct _mp_obj_module_t {
|
||||
mp_obj_base_t base;
|
||||
qstr name;
|
||||
mp_map_t *globals;
|
||||
} mp_obj_module_t;
|
||||
#include "builtin.h"
|
||||
|
||||
STATIC void module_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
mp_obj_module_t *self = self_in;
|
||||
|
@ -37,7 +32,7 @@ STATIC bool module_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
|
|||
return true;
|
||||
}
|
||||
|
||||
const mp_obj_type_t module_type = {
|
||||
const mp_obj_type_t mp_type_module = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_module,
|
||||
.print = module_print,
|
||||
|
@ -46,32 +41,51 @@ const mp_obj_type_t module_type = {
|
|||
};
|
||||
|
||||
mp_obj_t mp_obj_new_module(qstr module_name) {
|
||||
mp_map_elem_t *el = mp_map_lookup(rt_loaded_modules_get(), MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
|
||||
mp_map_elem_t *el = mp_map_lookup(rt_loaded_modules_get(), MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
|
||||
// We could error out if module already exists, but let C extensions
|
||||
// add new members to existing modules.
|
||||
if (el->value != MP_OBJ_NULL) {
|
||||
return el->value;
|
||||
}
|
||||
|
||||
// create new module object
|
||||
mp_obj_module_t *o = m_new_obj(mp_obj_module_t);
|
||||
o->base.type = &module_type;
|
||||
o->base.type = &mp_type_module;
|
||||
o->name = module_name;
|
||||
o->globals = mp_map_new(1);
|
||||
el->value = o;
|
||||
|
||||
// store __name__ entry in the module
|
||||
mp_map_lookup(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = MP_OBJ_NEW_QSTR(module_name);
|
||||
|
||||
// store the new module into the slot in the global dict holding all modules
|
||||
el->value = o;
|
||||
|
||||
// return the new module
|
||||
return o;
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_module_get(qstr module_name) {
|
||||
// lookup module
|
||||
mp_map_elem_t *el = mp_map_lookup(rt_loaded_modules_get(), MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP);
|
||||
if (el == NULL) {
|
||||
return MP_OBJ_NULL;
|
||||
|
||||
// module found, return it
|
||||
if (el != NULL) {
|
||||
return el->value;
|
||||
}
|
||||
return el->value;
|
||||
|
||||
// module not found, look for builtin module names
|
||||
#if MICROPY_ENABLE_FLOAT
|
||||
if (module_name == MP_QSTR_math) {
|
||||
return (mp_obj_t)&mp_module_math;
|
||||
}
|
||||
#endif
|
||||
|
||||
// no module found, return NULL object
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &module_type));
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_module));
|
||||
mp_obj_module_t *self = self_in;
|
||||
return self->globals;
|
||||
}
|
||||
|
|
1
py/py.mk
1
py/py.mk
|
@ -73,6 +73,7 @@ PY_O_BASENAME = \
|
|||
builtinimport.o \
|
||||
builtinevex.o \
|
||||
builtinmp.o \
|
||||
builtinmath.o \
|
||||
vm.o \
|
||||
showbc.o \
|
||||
repl.o \
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// All the qstr definitions in this file are available as constants.
|
||||
// That is, they are in ROM and you can reference them simple as MP_QSTR_xxxx.
|
||||
// That is, they are in ROM and you can reference them simply as MP_QSTR_xxxx.
|
||||
// TODO make it so we can use #defines here to select only those words that will be used
|
||||
|
||||
Q(__build_class__)
|
||||
Q(__class__)
|
||||
|
@ -115,6 +116,32 @@ Q(iterator)
|
|||
Q(module)
|
||||
Q(slice)
|
||||
|
||||
Q(math)
|
||||
Q(pi)
|
||||
Q(sqrt)
|
||||
Q(pow)
|
||||
Q(exp)
|
||||
Q(log)
|
||||
Q(log2)
|
||||
Q(log10)
|
||||
Q(cosh)
|
||||
Q(sinh)
|
||||
Q(tanh)
|
||||
Q(acosh)
|
||||
Q(asinh)
|
||||
Q(atanh)
|
||||
Q(cos)
|
||||
Q(sin)
|
||||
Q(tan)
|
||||
Q(acos)
|
||||
Q(asin)
|
||||
Q(atan)
|
||||
Q(atan2)
|
||||
|
||||
Q(mem_total)
|
||||
Q(mem_current)
|
||||
Q(mem_peak)
|
||||
|
||||
Q(<module>)
|
||||
Q(<lambda>)
|
||||
Q(<listcomp>)
|
||||
|
|
12
py/runtime.c
12
py/runtime.c
|
@ -92,13 +92,13 @@ STATIC const mp_builtin_elem_t builtin_table[] = {
|
|||
// built-in types
|
||||
{ MP_QSTR_bool, (mp_obj_t)&bool_type },
|
||||
#if MICROPY_ENABLE_FLOAT
|
||||
{ MP_QSTR_complex, (mp_obj_t)&complex_type },
|
||||
{ MP_QSTR_complex, (mp_obj_t)&mp_type_complex },
|
||||
#endif
|
||||
{ MP_QSTR_dict, (mp_obj_t)&dict_type },
|
||||
{ MP_QSTR_enumerate, (mp_obj_t)&enumerate_type },
|
||||
{ MP_QSTR_filter, (mp_obj_t)&filter_type },
|
||||
#if MICROPY_ENABLE_FLOAT
|
||||
{ MP_QSTR_float, (mp_obj_t)&float_type },
|
||||
{ MP_QSTR_float, (mp_obj_t)&mp_type_float },
|
||||
#endif
|
||||
{ MP_QSTR_int, (mp_obj_t)&int_type },
|
||||
{ MP_QSTR_list, (mp_obj_t)&list_type },
|
||||
|
@ -203,7 +203,9 @@ void rt_init(void) {
|
|||
//sys_path = mp_obj_new_list(0, NULL);
|
||||
//rt_store_attr(m_sys, MP_QSTR_path, sys_path);
|
||||
|
||||
mp_module_micropython_init();
|
||||
// we pre-import the micropython module
|
||||
// probably shouldn't do this, so we are compatible with CPython
|
||||
rt_store_name(MP_QSTR_micropython, (mp_obj_t)&mp_module_micropython);
|
||||
|
||||
// TODO: wastes one mp_code_t structure in mem
|
||||
next_unique_code_id = 1; // 0 indicates "no code"
|
||||
|
@ -586,9 +588,9 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
|
|||
}
|
||||
return mp_obj_new_int(lhs_val);
|
||||
#if MICROPY_ENABLE_FLOAT
|
||||
} else if (MP_OBJ_IS_TYPE(rhs, &float_type)) {
|
||||
} else if (MP_OBJ_IS_TYPE(rhs, &mp_type_float)) {
|
||||
return mp_obj_float_binary_op(op, lhs_val, rhs);
|
||||
} else if (MP_OBJ_IS_TYPE(rhs, &complex_type)) {
|
||||
} else if (MP_OBJ_IS_TYPE(rhs, &mp_type_complex)) {
|
||||
return mp_obj_complex_binary_op(op, lhs_val, 0, rhs);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ LIBS =
|
|||
SRC_C = \
|
||||
main.c \
|
||||
printf.c \
|
||||
math.c \
|
||||
system_stm32f4xx.c \
|
||||
stm32fxxx_it.c \
|
||||
string0.c \
|
||||
|
|
25
stm/main.c
25
stm/main.c
|
@ -666,28 +666,3 @@ soft_reset:
|
|||
first_soft_reset = false;
|
||||
goto soft_reset;
|
||||
}
|
||||
|
||||
// these 2 functions seem to actually work... no idea why
|
||||
// replacing with libgcc does not work (probably due to wrong calling conventions)
|
||||
double __aeabi_f2d(float x) {
|
||||
// TODO
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
float __aeabi_d2f(double x) {
|
||||
// TODO
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double sqrt(double x) {
|
||||
// TODO
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
machine_float_t machine_sqrt(machine_float_t x) {
|
||||
asm volatile (
|
||||
"vsqrt.f32 %[r], %[x]\n"
|
||||
: [r] "=t" (x)
|
||||
: [x] "t" (x));
|
||||
return x;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
#include <math.h>
|
||||
|
||||
// these 2 functions seem to actually work... no idea why
|
||||
// replacing with libgcc does not work (probably due to wrong calling conventions)
|
||||
double __aeabi_f2d(float x) {
|
||||
// TODO
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
float __aeabi_d2f(double x) {
|
||||
// TODO
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/*
|
||||
double sqrt(double x) {
|
||||
// TODO
|
||||
return 0.0;
|
||||
}
|
||||
*/
|
||||
|
||||
float sqrtf(float x) {
|
||||
asm volatile (
|
||||
"vsqrt.f32 %[r], %[x]\n"
|
||||
: [r] "=t" (x)
|
||||
: [x] "t" (x));
|
||||
return x;
|
||||
}
|
||||
|
||||
// TODO we need import these functions from some library (eg musl or newlib)
|
||||
float powf(float x, float y) { return 0.0; }
|
||||
float expf(float x) { return 0.0; }
|
||||
float logf(float x) { return 0.0; }
|
||||
float log2f(float x) { return 0.0; }
|
||||
float log10f(float x) { return 0.0; }
|
||||
float coshf(float x) { return 0.0; }
|
||||
float sinhf(float x) { return 0.0; }
|
||||
float tanhf(float x) { return 0.0; }
|
||||
float acoshf(float x) { return 0.0; }
|
||||
float asinhf(float x) { return 0.0; }
|
||||
float atanhf(float x) { return 0.0; }
|
||||
float cosf(float x) { return 0.0; }
|
||||
float sinf(float x) { return 0.0; }
|
||||
float tanf(float x) { return 0.0; }
|
||||
float acosf(float x) { return 0.0; }
|
||||
float asinf(float x) { return 0.0; }
|
||||
float atanf(float x) { return 0.0; }
|
||||
float atan2f(float x, float y) { return 0.0; }
|
|
@ -6,8 +6,8 @@
|
|||
#define MICROPY_EMIT_INLINE_THUMB (1)
|
||||
#define MICROPY_ENABLE_GC (1)
|
||||
#define MICROPY_ENABLE_REPL_HELPERS (1)
|
||||
#define MICROPY_ENABLE_FLOAT (1)
|
||||
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
|
||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
|
||||
#define MICROPY_PATH_MAX (128)
|
||||
/* Enable FatFS LFNs
|
||||
0: Disable LFN feature.
|
||||
|
@ -29,9 +29,6 @@ typedef int32_t machine_int_t; // must be pointer size
|
|||
typedef uint32_t machine_uint_t; // must be pointer size
|
||||
typedef void *machine_ptr_t; // must be of pointer size
|
||||
typedef const void *machine_const_ptr_t; // must be of pointer size
|
||||
typedef float machine_float_t;
|
||||
|
||||
machine_float_t machine_sqrt(machine_float_t x);
|
||||
|
||||
// There is no classical C heap in bare-metal ports, only Python
|
||||
// garbage-collected heap. For completeness, emulate C heap via
|
||||
|
|
|
@ -383,12 +383,6 @@ int main(int argc, char **argv) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// for sqrt
|
||||
#include <math.h>
|
||||
machine_float_t machine_sqrt(machine_float_t x) {
|
||||
return sqrt(x);
|
||||
}
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
uint mp_import_stat(const char *path) {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#define MICROPY_ENABLE_REPL_HELPERS (1)
|
||||
#define MICROPY_ENABLE_LEXER_UNIX (1)
|
||||
#define MICROPY_ENABLE_SOURCE_LINE (1)
|
||||
#define MICROPY_ENABLE_FLOAT (1)
|
||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE)
|
||||
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
|
||||
#define MICROPY_PATH_MAX (PATH_MAX)
|
||||
|
||||
|
@ -28,9 +28,6 @@ typedef unsigned int machine_uint_t; // must be pointer size
|
|||
|
||||
typedef void *machine_ptr_t; // must be of pointer size
|
||||
typedef const void *machine_const_ptr_t; // must be of pointer size
|
||||
typedef double machine_float_t;
|
||||
|
||||
machine_float_t machine_sqrt(machine_float_t x);
|
||||
|
||||
struct _mp_obj_fun_native_t;
|
||||
extern const struct _mp_obj_fun_native_t mp_builtin_open_obj;
|
||||
|
|
|
@ -28,7 +28,7 @@ static MP_DEFINE_CONST_FUN_OBJ_0(mod_time_clock_obj, mod_time_clock);
|
|||
static mp_obj_t mod_time_sleep(mp_obj_t arg) {
|
||||
#if MICROPY_ENABLE_FLOAT
|
||||
struct timeval tv;
|
||||
machine_float_t val = mp_obj_get_float(arg);
|
||||
mp_float_t val = mp_obj_get_float(arg);
|
||||
double ipart;
|
||||
tv.tv_usec = round(modf(val, &ipart) * 1000000);
|
||||
tv.tv_sec = ipart;
|
||||
|
|
Loading…
Reference in New Issue