dynruntime.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /*
  2. * This file is part of the MicroPython project, http://micropython.org/
  3. *
  4. * The MIT License (MIT)
  5. *
  6. * Copyright (c) 2019 Damien P. George
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #ifndef MICROPY_INCLUDED_PY_DYNRUNTIME_H
  27. #define MICROPY_INCLUDED_PY_DYNRUNTIME_H
  28. // This header file contains definitions to dynamically implement the static
  29. // MicroPython runtime API defined in py/obj.h and py/runtime.h.
  30. #include "py/binary.h"
  31. #include "py/nativeglue.h"
  32. #include "py/objfun.h"
  33. #include "py/objstr.h"
  34. #include "py/objtype.h"
  35. #if !MICROPY_ENABLE_DYNRUNTIME
  36. #error "dynruntime.h included in non-dynamic-module build."
  37. #endif
  38. #undef MP_ROM_QSTR
  39. #undef MP_OBJ_QSTR_VALUE
  40. #undef MP_OBJ_NEW_QSTR
  41. #undef mp_const_none
  42. #undef mp_const_false
  43. #undef mp_const_true
  44. #undef mp_const_empty_bytes
  45. #undef mp_const_empty_tuple
  46. #undef nlr_raise
  47. /******************************************************************************/
  48. // Memory allocation
  49. #define m_malloc(n) (m_malloc_dyn((n)))
  50. #define m_free(ptr) (m_free_dyn((ptr)))
  51. #define m_realloc(ptr, new_num_bytes) (m_realloc_dyn((ptr), (new_num_bytes)))
  52. static inline void *m_malloc_dyn(size_t n) {
  53. // TODO won't raise on OOM
  54. return mp_fun_table.realloc_(NULL, n, false);
  55. }
  56. static inline void m_free_dyn(void *ptr) {
  57. mp_fun_table.realloc_(ptr, 0, false);
  58. }
  59. static inline void *m_realloc_dyn(void *ptr, size_t new_num_bytes) {
  60. // TODO won't raise on OOM
  61. return mp_fun_table.realloc_(ptr, new_num_bytes, true);
  62. }
  63. /******************************************************************************/
  64. // Printing
  65. #define mp_plat_print (*mp_fun_table.plat_print)
  66. #define mp_printf(p, ...) (mp_fun_table.printf_((p), __VA_ARGS__))
  67. #define mp_vprintf(p, fmt, args) (mp_fun_table.vprintf_((p), (fmt), (args)))
  68. /******************************************************************************/
  69. // Types and objects
  70. #define MP_OBJ_NEW_QSTR(x) (mp_fun_table.native_to_obj(x, MP_NATIVE_TYPE_QSTR))
  71. #define mp_type_type (*mp_fun_table.type_type)
  72. #define mp_type_NoneType (*mp_obj_get_type(mp_const_none))
  73. #define mp_type_bool (*mp_obj_get_type(mp_const_false))
  74. #define mp_type_int (*(mp_obj_type_t *)(mp_load_global(MP_QSTR_int)))
  75. #define mp_type_str (*mp_fun_table.type_str)
  76. #define mp_type_bytes (*(mp_obj_type_t *)(mp_load_global(MP_QSTR_bytes)))
  77. #define mp_type_bytearray (*(mp_obj_type_t *)(mp_load_global(MP_QSTR_bytearray)))
  78. #define mp_type_tuple (*((mp_obj_base_t *)mp_const_empty_tuple)->type)
  79. #define mp_type_list (*mp_fun_table.type_list)
  80. #define mp_type_Exception (*mp_fun_table.type_Exception)
  81. #define mp_type_EOFError (*(mp_obj_type_t *)(mp_load_global(MP_QSTR_EOFError)))
  82. #define mp_type_IndexError (*(mp_obj_type_t *)(mp_load_global(MP_QSTR_IndexError)))
  83. #define mp_type_KeyError (*(mp_obj_type_t *)(mp_load_global(MP_QSTR_KeyError)))
  84. #define mp_type_NotImplementedError (*(mp_obj_type_t *)(mp_load_global(MP_QSTR_NotImplementedError)))
  85. #define mp_type_RuntimeError (*(mp_obj_type_t *)(mp_load_global(MP_QSTR_RuntimeError)))
  86. #define mp_type_TypeError (*(mp_obj_type_t *)(mp_load_global(MP_QSTR_TypeError)))
  87. #define mp_type_ValueError (*(mp_obj_type_t *)(mp_load_global(MP_QSTR_ValueError)))
  88. #define mp_stream_read_obj (*mp_fun_table.stream_read_obj)
  89. #define mp_stream_readinto_obj (*mp_fun_table.stream_readinto_obj)
  90. #define mp_stream_unbuffered_readline_obj (*mp_fun_table.stream_unbuffered_readline_obj)
  91. #define mp_stream_write_obj (*mp_fun_table.stream_write_obj)
  92. #define mp_const_none ((mp_obj_t)mp_fun_table.const_none)
  93. #define mp_const_false ((mp_obj_t)mp_fun_table.const_false)
  94. #define mp_const_true ((mp_obj_t)mp_fun_table.const_true)
  95. #define mp_const_empty_bytes (MP_OBJ_TYPE_GET_SLOT(&mp_type_bytes, make_new)(NULL, 0, 0, NULL))
  96. #define mp_const_empty_tuple (mp_fun_table.new_tuple(0, NULL))
  97. #define mp_obj_new_bool(b) ((b) ? (mp_obj_t)mp_fun_table.const_true : (mp_obj_t)mp_fun_table.const_false)
  98. #define mp_obj_new_int(i) (mp_fun_table.native_to_obj(i, MP_NATIVE_TYPE_INT))
  99. #define mp_obj_new_int_from_uint(i) (mp_fun_table.native_to_obj(i, MP_NATIVE_TYPE_UINT))
  100. #define mp_obj_new_str(data, len) (mp_fun_table.obj_new_str((data), (len)))
  101. #define mp_obj_new_str_of_type(t, d, l) (mp_obj_new_str_of_type_dyn((t), (d), (l)))
  102. #define mp_obj_new_bytes(data, len) (mp_fun_table.obj_new_bytes((data), (len)))
  103. #define mp_obj_new_bytearray_by_ref(n, i) (mp_fun_table.obj_new_bytearray_by_ref((n), (i)))
  104. #define mp_obj_new_tuple(n, items) (mp_fun_table.new_tuple((n), (items)))
  105. #define mp_obj_new_list(n, items) (mp_fun_table.new_list((n), (items)))
  106. #define mp_obj_new_dict(n) (mp_fun_table.new_dict((n)))
  107. #define mp_obj_get_type(o) (mp_fun_table.obj_get_type((o)))
  108. #define mp_obj_cast_to_native_base(o, t) (mp_obj_cast_to_native_base_dyn((o), (t)))
  109. #define mp_obj_get_int(o) (mp_fun_table.native_from_obj(o, MP_NATIVE_TYPE_INT))
  110. #define mp_obj_get_int_truncated(o) (mp_fun_table.native_from_obj(o, MP_NATIVE_TYPE_UINT))
  111. #define mp_obj_str_get_str(s) (mp_obj_str_get_data_dyn((s), NULL))
  112. #define mp_obj_str_get_data(o, len) (mp_obj_str_get_data_dyn((o), (len)))
  113. #define mp_get_buffer(o, bufinfo, fl) (mp_fun_table.get_buffer((o), (bufinfo), (fl)))
  114. #define mp_get_buffer_raise(o, bufinfo, fl) (mp_fun_table.get_buffer((o), (bufinfo), (fl) | MP_BUFFER_RAISE_IF_UNSUPPORTED))
  115. #define mp_get_stream_raise(s, flags) (mp_fun_table.get_stream_raise((s), (flags)))
  116. #define mp_obj_is_true(o) (mp_fun_table.native_from_obj(o, MP_NATIVE_TYPE_BOOL))
  117. #define mp_obj_len(o) (mp_obj_len_dyn(o))
  118. #define mp_obj_subscr(base, index, val) (mp_fun_table.obj_subscr((base), (index), (val)))
  119. #define mp_obj_get_array(o, len, items) (mp_obj_get_array_dyn((o), (len), (items)))
  120. #define mp_obj_list_append(list, item) (mp_fun_table.list_append((list), (item)))
  121. #define mp_obj_dict_store(dict, key, val) (mp_fun_table.dict_store((dict), (key), (val)))
  122. #define mp_obj_malloc_helper(n, t) (mp_obj_malloc_helper_dyn(n, t))
  123. static inline mp_obj_t mp_obj_new_str_of_type_dyn(const mp_obj_type_t *type, const byte *data, size_t len) {
  124. if (type == &mp_type_str) {
  125. return mp_obj_new_str((const char *)data, len);
  126. } else {
  127. return mp_obj_new_bytes(data, len);
  128. }
  129. }
  130. static inline mp_obj_t mp_obj_cast_to_native_base_dyn(mp_obj_t self_in, mp_const_obj_t native_type) {
  131. const mp_obj_type_t *self_type = mp_obj_get_type(self_in);
  132. if (MP_OBJ_FROM_PTR(self_type) == native_type) {
  133. return self_in;
  134. } else if (MP_OBJ_TYPE_GET_SLOT_OR_NULL(self_type, parent) != native_type) {
  135. // The self_in object is not a direct descendant of native_type, so fail the cast.
  136. // This is a very simple version of mp_obj_is_subclass_fast that could be improved.
  137. return MP_OBJ_NULL;
  138. } else {
  139. mp_obj_instance_t *self = (mp_obj_instance_t *)MP_OBJ_TO_PTR(self_in);
  140. return self->subobj[0];
  141. }
  142. }
  143. static inline void *mp_obj_str_get_data_dyn(mp_obj_t o, size_t *l) {
  144. mp_buffer_info_t bufinfo;
  145. mp_get_buffer_raise(o, &bufinfo, MP_BUFFER_READ);
  146. if (l != NULL) {
  147. *l = bufinfo.len;
  148. }
  149. return bufinfo.buf;
  150. }
  151. static inline mp_obj_t mp_obj_len_dyn(mp_obj_t o) {
  152. // If bytes implemented MP_UNARY_OP_LEN could use: mp_unary_op(MP_UNARY_OP_LEN, o)
  153. return mp_fun_table.call_function_n_kw(mp_fun_table.load_name(MP_QSTR_len), 1, &o);
  154. }
  155. static inline void *mp_obj_malloc_helper_dyn(size_t num_bytes, const mp_obj_type_t *type) {
  156. mp_obj_base_t *base = (mp_obj_base_t *)m_malloc(num_bytes);
  157. base->type = type;
  158. return base;
  159. }
  160. /******************************************************************************/
  161. // General runtime functions
  162. #define mp_binary_get_size(struct_type, val_type, palign) (mp_fun_table.binary_get_size((struct_type), (val_type), (palign)))
  163. #define mp_binary_get_val_array(typecode, p, index) (mp_fun_table.binary_get_val_array((typecode), (p), (index)))
  164. #define mp_binary_set_val_array(typecode, p, index, val_in) (mp_fun_table.binary_set_val_array((typecode), (p), (index), (val_in)))
  165. #define mp_load_name(qst) (mp_fun_table.load_name((qst)))
  166. #define mp_load_global(qst) (mp_fun_table.load_global((qst)))
  167. #define mp_load_attr(base, attr) (mp_fun_table.load_attr((base), (attr)))
  168. #define mp_load_method(base, attr, dest) (mp_fun_table.load_method((base), (attr), (dest)))
  169. #define mp_load_method_maybe(base, attr, dest) (mp_fun_table.load_method_maybe((base), (attr), (dest)))
  170. #define mp_load_super_method(attr, dest) (mp_fun_table.load_super_method((attr), (dest)))
  171. #define mp_store_name(qst, obj) (mp_fun_table.store_name((qst), (obj)))
  172. #define mp_store_global(qst, obj) (mp_fun_table.store_global((qst), (obj)))
  173. #define mp_store_attr(base, attr, val) (mp_fun_table.store_attr((base), (attr), (val)))
  174. #define mp_unary_op(op, obj) (mp_fun_table.unary_op((op), (obj)))
  175. #define mp_binary_op(op, lhs, rhs) (mp_fun_table.binary_op((op), (lhs), (rhs)))
  176. #define mp_make_function_from_proto_fun(rc, context, def_args) \
  177. (mp_fun_table.make_function_from_proto_fun((rc), (context), (def_args)))
  178. #define mp_call_function_n_kw(fun, n_args, n_kw, args) \
  179. (mp_fun_table.call_function_n_kw((fun), (n_args) | ((n_kw) << 8), args))
  180. #define mp_arg_check_num(n_args, n_kw, n_args_min, n_args_max, takes_kw) \
  181. (mp_fun_table.arg_check_num_sig((n_args), (n_kw), MP_OBJ_FUN_MAKE_SIG((n_args_min), (n_args_max), (takes_kw))))
  182. #define mp_arg_parse_all(n_pos, pos, kws, n_allowed, allowed, out_vals) \
  183. (mp_fun_table.arg_parse_all((n_pos), (pos), (kws), (n_allowed), (allowed), (out_vals)))
  184. #define mp_arg_parse_all_kw_array(n_pos, n_kw, args, n_allowed, allowed, out_vals) \
  185. (mp_fun_table.arg_parse_all_kw_array((n_pos), (n_kw), (args), (n_allowed), (allowed), (out_vals)))
  186. #define MP_DYNRUNTIME_INIT_ENTRY \
  187. mp_obj_t old_globals = mp_fun_table.swap_globals(self->context->module.globals); \
  188. mp_raw_code_truncated_t rc; \
  189. rc.proto_fun_indicator[0] = MP_PROTO_FUN_INDICATOR_RAW_CODE_0; \
  190. rc.proto_fun_indicator[1] = MP_PROTO_FUN_INDICATOR_RAW_CODE_1; \
  191. rc.kind = MP_CODE_NATIVE_VIPER; \
  192. rc.is_generator = 0; \
  193. (void)rc;
  194. #define MP_DYNRUNTIME_INIT_EXIT \
  195. mp_fun_table.swap_globals(old_globals); \
  196. return mp_const_none;
  197. #define MP_DYNRUNTIME_MAKE_FUNCTION(f) \
  198. (mp_make_function_from_proto_fun((rc.fun_data = (f), (const mp_raw_code_t *)&rc), self->context, NULL))
  199. #define mp_import_name(name, fromlist, level) \
  200. (mp_fun_table.import_name((name), (fromlist), (level)))
  201. #define mp_import_from(module, name) \
  202. (mp_fun_table.import_from((module), (name)))
  203. #define mp_import_all(module) \
  204. (mp_fun_table.import_all((module))
  205. /******************************************************************************/
  206. // Exceptions
  207. #define mp_obj_exception_make_new (MP_OBJ_TYPE_GET_SLOT(&mp_type_Exception, make_new))
  208. #define mp_obj_exception_print (MP_OBJ_TYPE_GET_SLOT(&mp_type_Exception, print))
  209. #define mp_obj_exception_attr (MP_OBJ_TYPE_GET_SLOT(&mp_type_Exception, attr))
  210. #define mp_obj_new_exception(o) ((mp_obj_t)(o)) // Assumes returned object will be raised, will create instance then
  211. #define mp_obj_new_exception_arg1(e_type, arg) (mp_obj_new_exception_arg1_dyn((e_type), (arg)))
  212. #define nlr_raise(o) (mp_raise_dyn(o))
  213. #define mp_raise_type_arg(type, arg) (mp_raise_dyn(mp_obj_new_exception_arg1_dyn((type), (arg))))
  214. #define mp_raise_msg(type, msg) (mp_fun_table.raise_msg((type), (msg)))
  215. #define mp_raise_OSError(er) (mp_raise_OSError_dyn(er))
  216. #define mp_raise_NotImplementedError(msg) (mp_raise_msg(&mp_type_NotImplementedError, (msg)))
  217. #define mp_raise_TypeError(msg) (mp_raise_msg(&mp_type_TypeError, (msg)))
  218. #define mp_raise_ValueError(msg) (mp_raise_msg(&mp_type_ValueError, (msg)))
  219. static inline mp_obj_t mp_obj_new_exception_arg1_dyn(const mp_obj_type_t *exc_type, mp_obj_t arg) {
  220. mp_obj_t args[1] = { arg };
  221. return mp_call_function_n_kw(MP_OBJ_FROM_PTR(exc_type), 1, 0, &args[0]);
  222. }
  223. static NORETURN inline void mp_raise_dyn(mp_obj_t o) {
  224. mp_fun_table.raise(o);
  225. for (;;) {
  226. }
  227. }
  228. static inline void mp_raise_OSError_dyn(int er) {
  229. mp_obj_t args[1] = { MP_OBJ_NEW_SMALL_INT(er) };
  230. nlr_raise(mp_call_function_n_kw(mp_load_global(MP_QSTR_OSError), 1, 0, &args[0]));
  231. }
  232. static inline void mp_obj_exception_init(mp_obj_full_type_t *exc, qstr name, const mp_obj_type_t *base) {
  233. exc->base.type = &mp_type_type;
  234. exc->flags = MP_TYPE_FLAG_NONE;
  235. exc->name = name;
  236. MP_OBJ_TYPE_SET_SLOT(exc, make_new, mp_obj_exception_make_new, 0);
  237. MP_OBJ_TYPE_SET_SLOT(exc, print, mp_obj_exception_print, 1);
  238. MP_OBJ_TYPE_SET_SLOT(exc, attr, mp_obj_exception_attr, 2);
  239. MP_OBJ_TYPE_SET_SLOT(exc, parent, base, 3);
  240. }
  241. /******************************************************************************/
  242. // Floating point
  243. #define mp_obj_new_float_from_f(f) (mp_fun_table.obj_new_float_from_f((f)))
  244. #define mp_obj_new_float_from_d(d) (mp_fun_table.obj_new_float_from_d((d)))
  245. #define mp_obj_get_float_to_f(o) (mp_fun_table.obj_get_float_to_f((o)))
  246. #define mp_obj_get_float_to_d(o) (mp_fun_table.obj_get_float_to_d((o)))
  247. #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
  248. #define mp_obj_new_float(f) (mp_obj_new_float_from_f((f)))
  249. #define mp_obj_get_float(o) (mp_obj_get_float_to_f((o)))
  250. #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
  251. #define mp_obj_new_float(f) (mp_obj_new_float_from_d((f)))
  252. #define mp_obj_get_float(o) (mp_obj_get_float_to_d((o)))
  253. #endif
  254. /******************************************************************************/
  255. // Inline function definitions.
  256. // *items may point inside a GC block
  257. static inline void mp_obj_get_array_dyn(mp_obj_t o, size_t *len, mp_obj_t **items) {
  258. const mp_obj_type_t *type = mp_obj_get_type(o);
  259. if (type == &mp_type_tuple) {
  260. mp_obj_tuple_t *t = MP_OBJ_TO_PTR(o);
  261. *len = t->len;
  262. *items = &t->items[0];
  263. } else if (type == &mp_type_list) {
  264. mp_obj_list_t *l = MP_OBJ_TO_PTR(o);
  265. *len = l->len;
  266. *items = l->items;
  267. } else {
  268. mp_raise_TypeError("expected tuple/list");
  269. }
  270. }
  271. #endif // MICROPY_INCLUDED_PY_DYNRUNTIME_H