kopia lustrzana https://github.com/micropython/micropython
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).pull/335/head
rodzic
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;
|
||||
|
|
Ładowanie…
Reference in New Issue