Branch data Line data Source code
1 : : /*
2 : : * This file is part of the MicroPython project, http://micropython.org/
3 : : *
4 : : * The MIT License (MIT)
5 : : *
6 : : * Copyright (c) 2013, 2014 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_RUNTIME_H
27 : : #define MICROPY_INCLUDED_PY_RUNTIME_H
28 : :
29 : : #include "py/mpstate.h"
30 : : #include "py/pystack.h"
31 : : #include "py/cstack.h"
32 : :
33 : : // For use with mp_call_function_1_from_nlr_jump_callback.
34 : : #define MP_DEFINE_NLR_JUMP_CALLBACK_FUNCTION_1(ctx, f, a) \
35 : : nlr_jump_callback_node_call_function_1_t ctx = { \
36 : : .func = (void (*)(void *))(f), \
37 : : .arg = (a), \
38 : : }
39 : :
40 : : typedef enum {
41 : : MP_VM_RETURN_NORMAL,
42 : : MP_VM_RETURN_YIELD,
43 : : MP_VM_RETURN_EXCEPTION,
44 : : } mp_vm_return_kind_t;
45 : :
46 : : typedef enum {
47 : : MP_ARG_BOOL = 0x001,
48 : : MP_ARG_INT = 0x002,
49 : : MP_ARG_OBJ = 0x003,
50 : : MP_ARG_KIND_MASK = 0x0ff,
51 : : MP_ARG_REQUIRED = 0x100,
52 : : MP_ARG_KW_ONLY = 0x200,
53 : : } mp_arg_flag_t;
54 : :
55 : : typedef union _mp_arg_val_t {
56 : : bool u_bool;
57 : : mp_int_t u_int;
58 : : mp_obj_t u_obj;
59 : : mp_rom_obj_t u_rom_obj;
60 : : } mp_arg_val_t;
61 : :
62 : : typedef struct _mp_arg_t {
63 : : uint16_t qst;
64 : : uint16_t flags;
65 : : mp_arg_val_t defval;
66 : : } mp_arg_t;
67 : :
68 : : struct _mp_sched_node_t;
69 : :
70 : : typedef void (*mp_sched_callback_t)(struct _mp_sched_node_t *);
71 : :
72 : : typedef struct _mp_sched_node_t {
73 : : mp_sched_callback_t callback;
74 : : struct _mp_sched_node_t *next;
75 : : } mp_sched_node_t;
76 : :
77 : : // For use with mp_globals_locals_set_from_nlr_jump_callback.
78 : : typedef struct _nlr_jump_callback_node_globals_locals_t {
79 : : nlr_jump_callback_node_t callback;
80 : : mp_obj_dict_t *globals;
81 : : mp_obj_dict_t *locals;
82 : : } nlr_jump_callback_node_globals_locals_t;
83 : :
84 : : // For use with mp_call_function_1_from_nlr_jump_callback.
85 : : typedef struct _nlr_jump_callback_node_call_function_1_t {
86 : : nlr_jump_callback_node_t callback;
87 : : void (*func)(void *);
88 : : void *arg;
89 : : } nlr_jump_callback_node_call_function_1_t;
90 : :
91 : : // Tables mapping operator enums to qstrs, defined in objtype.c
92 : : extern const byte mp_unary_op_method_name[];
93 : : extern const byte mp_binary_op_method_name[];
94 : :
95 : : void mp_init(void);
96 : : void mp_deinit(void);
97 : :
98 : : void mp_sched_exception(mp_obj_t exc);
99 : : void mp_sched_keyboard_interrupt(void);
100 : : #if MICROPY_ENABLE_VM_ABORT
101 : : void mp_sched_vm_abort(void);
102 : : #endif
103 : : void mp_handle_pending(bool raise_exc);
104 : :
105 : : #if MICROPY_ENABLE_SCHEDULER
106 : : void mp_sched_lock(void);
107 : : void mp_sched_unlock(void);
108 : : #define mp_sched_num_pending() (MP_STATE_VM(sched_len))
109 : : bool mp_sched_schedule(mp_obj_t function, mp_obj_t arg);
110 : : bool mp_sched_schedule_node(mp_sched_node_t *node, mp_sched_callback_t callback);
111 : : #endif
112 : :
113 : : // Handles any pending MicroPython events without waiting for an interrupt or event.
114 : : void mp_event_handle_nowait(void);
115 : :
116 : : // Handles any pending MicroPython events and then suspends execution until the
117 : : // next interrupt or event.
118 : : //
119 : : // Note: on "tickless" ports this can suspend execution for a long time,
120 : : // don't call unless you know an interrupt is coming to continue execution.
121 : : // On "ticked" ports it may return early due to the tick interrupt.
122 : : void mp_event_wait_indefinite(void);
123 : :
124 : : // Handle any pending MicroPython events and then suspends execution until the
125 : : // next interrupt or event, or until timeout_ms milliseconds have elapsed.
126 : : //
127 : : // On "ticked" ports it may return early due to the tick interrupt.
128 : : void mp_event_wait_ms(mp_uint_t timeout_ms);
129 : :
130 : : // extra printing method specifically for mp_obj_t's which are integral type
131 : : int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec);
132 : :
133 : : void mp_arg_check_num_sig(size_t n_args, size_t n_kw, uint32_t sig);
134 : 1505343 : static inline void mp_arg_check_num(size_t n_args, size_t n_kw, size_t n_args_min, size_t n_args_max, bool takes_kw) {
135 : 1505343 : mp_arg_check_num_sig(n_args, n_kw, MP_OBJ_FUN_MAKE_SIG(n_args_min, n_args_max, takes_kw));
136 : : }
137 : : void mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals);
138 : : void mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args, size_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals);
139 : : NORETURN void mp_arg_error_terse_mismatch(void);
140 : : NORETURN void mp_arg_error_unimpl_kw(void);
141 : :
142 : 1757925 : static inline mp_obj_dict_t *mp_locals_get(void) {
143 : 1757925 : return MP_STATE_THREAD(dict_locals);
144 : : }
145 : 13557 : static inline void mp_locals_set(mp_obj_dict_t *d) {
146 [ + + ]: 12566 : MP_STATE_THREAD(dict_locals) = d;
147 : : }
148 : 29398057 : static inline mp_obj_dict_t *mp_globals_get(void) {
149 [ + + ]: 30008747 : return MP_STATE_THREAD(dict_globals);
150 : : }
151 : 16246674 : static inline void mp_globals_set(mp_obj_dict_t *d) {
152 [ + + + + : 8771551 : MP_STATE_THREAD(dict_globals) = d;
+ ]
153 : : }
154 : :
155 : : void mp_globals_locals_set_from_nlr_jump_callback(void *ctx_in);
156 : : void mp_call_function_1_from_nlr_jump_callback(void *ctx_in);
157 : :
158 : : #if MICROPY_PY_THREAD
159 : 595 : static inline void mp_thread_init_state(mp_state_thread_t *ts, size_t stack_size, mp_obj_dict_t *locals, mp_obj_dict_t *globals) {
160 : 595 : mp_thread_set_state(ts);
161 : :
162 : 595 : mp_cstack_init_with_top(ts + 1, stack_size); // need to include ts in root-pointer scan
163 : :
164 : : // GC starts off unlocked
165 : 595 : ts->gc_lock_depth = 0;
166 : :
167 : : // There are no pending jump callbacks or exceptions yet
168 : 595 : ts->nlr_jump_callback_top = NULL;
169 : 595 : ts->mp_pending_exception = MP_OBJ_NULL;
170 : :
171 : : // If locals/globals are not given, inherit from main thread
172 [ - + ]: 595 : if (locals == NULL) {
173 : 0 : locals = mp_state_ctx.thread.dict_locals;
174 : : }
175 [ - + ]: 595 : if (globals == NULL) {
176 : 0 : globals = mp_state_ctx.thread.dict_globals;
177 : : }
178 : 595 : mp_locals_set(locals);
179 : 595 : mp_globals_set(globals);
180 : 595 : }
181 : : #endif
182 : :
183 : : mp_obj_t mp_load_name(qstr qst);
184 : : mp_obj_t mp_load_global(qstr qst);
185 : : mp_obj_t mp_load_build_class(void);
186 : : void mp_store_name(qstr qst, mp_obj_t obj);
187 : : void mp_store_global(qstr qst, mp_obj_t obj);
188 : : void mp_delete_name(qstr qst);
189 : : void mp_delete_global(qstr qst);
190 : :
191 : : mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg);
192 : : mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs);
193 : :
194 : : mp_obj_t mp_call_function_0(mp_obj_t fun);
195 : : mp_obj_t mp_call_function_1(mp_obj_t fun, mp_obj_t arg);
196 : : mp_obj_t mp_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2);
197 : : mp_obj_t mp_call_function_n_kw(mp_obj_t fun, size_t n_args, size_t n_kw, const mp_obj_t *args);
198 : : mp_obj_t mp_call_method_n_kw(size_t n_args, size_t n_kw, const mp_obj_t *args);
199 : : mp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args);
200 : : mp_obj_t mp_call_method_self_n_kw(mp_obj_t meth, mp_obj_t self, size_t n_args, size_t n_kw, const mp_obj_t *args);
201 : : // Call function and catch/dump exception - for Python callbacks from C code
202 : : // (return MP_OBJ_NULL in case of exception).
203 : : mp_obj_t mp_call_function_1_protected(mp_obj_t fun, mp_obj_t arg);
204 : : mp_obj_t mp_call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2);
205 : :
206 : : typedef struct _mp_call_args_t {
207 : : mp_obj_t fun;
208 : : size_t n_args, n_kw, n_alloc;
209 : : mp_obj_t *args;
210 : : } mp_call_args_t;
211 : :
212 : : #if MICROPY_STACKLESS
213 : : // Takes arguments which are the most general mix of Python arg types, and
214 : : // prepares argument array suitable for passing to ->call() method of a
215 : : // function object (and mp_call_function_n_kw()).
216 : : // (Only needed in stackless mode.)
217 : : void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args, mp_call_args_t *out_args);
218 : : #endif
219 : :
220 : : void mp_unpack_sequence(mp_obj_t seq, size_t num, mp_obj_t *items);
221 : : void mp_unpack_ex(mp_obj_t seq, size_t num, mp_obj_t *items);
222 : : mp_obj_t mp_store_map(mp_obj_t map, mp_obj_t key, mp_obj_t value);
223 : : mp_obj_t mp_load_attr(mp_obj_t base, qstr attr);
224 : : void mp_convert_member_lookup(mp_obj_t obj, const mp_obj_type_t *type, mp_obj_t member, mp_obj_t *dest);
225 : : void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest);
226 : : void mp_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest);
227 : : void mp_load_method_protected(mp_obj_t obj, qstr attr, mp_obj_t *dest, bool catch_all_exc);
228 : : void mp_load_super_method(qstr attr, mp_obj_t *dest);
229 : : void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t val);
230 : :
231 : : mp_obj_t mp_getiter(mp_obj_t o, mp_obj_iter_buf_t *iter_buf);
232 : : mp_obj_t mp_iternext_allow_raise(mp_obj_t o); // may return MP_OBJ_STOP_ITERATION instead of raising StopIteration()
233 : : mp_obj_t mp_iternext(mp_obj_t o); // will always return MP_OBJ_STOP_ITERATION instead of raising StopIteration(...)
234 : : mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val);
235 : :
236 : 533 : static inline mp_obj_t mp_make_stop_iteration(mp_obj_t o) {
237 : 533 : MP_STATE_THREAD(stop_iteration_arg) = o;
238 : 533 : return MP_OBJ_STOP_ITERATION;
239 : : }
240 : :
241 : : mp_obj_t mp_make_raise_obj(mp_obj_t o);
242 : :
243 : : mp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level);
244 : : mp_obj_t mp_import_from(mp_obj_t module, qstr name);
245 : : void mp_import_all(mp_obj_t module);
246 : :
247 : : #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NONE
248 : : NORETURN void mp_raise_type(const mp_obj_type_t *exc_type);
249 : : NORETURN void mp_raise_ValueError_no_msg(void);
250 : : NORETURN void mp_raise_TypeError_no_msg(void);
251 : : NORETURN void mp_raise_NotImplementedError_no_msg(void);
252 : : #define mp_raise_msg(exc_type, msg) mp_raise_type(exc_type)
253 : : #define mp_raise_msg_varg(exc_type, ...) mp_raise_type(exc_type)
254 : : #define mp_raise_ValueError(msg) mp_raise_ValueError_no_msg()
255 : : #define mp_raise_TypeError(msg) mp_raise_TypeError_no_msg()
256 : : #define mp_raise_NotImplementedError(msg) mp_raise_NotImplementedError_no_msg()
257 : : #else
258 : : #define mp_raise_type(exc_type) mp_raise_msg(exc_type, NULL)
259 : : NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, mp_rom_error_text_t msg);
260 : : NORETURN void mp_raise_msg_varg(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, ...);
261 : : NORETURN void mp_raise_ValueError(mp_rom_error_text_t msg);
262 : : NORETURN void mp_raise_TypeError(mp_rom_error_text_t msg);
263 : : NORETURN void mp_raise_NotImplementedError(mp_rom_error_text_t msg);
264 : : #endif
265 : :
266 : : NORETURN void mp_raise_type_arg(const mp_obj_type_t *exc_type, mp_obj_t arg);
267 : : NORETURN void mp_raise_StopIteration(mp_obj_t arg);
268 : : NORETURN void mp_raise_TypeError_int_conversion(mp_const_obj_t arg);
269 : : NORETURN void mp_raise_OSError(int errno_);
270 : : NORETURN void mp_raise_OSError_with_filename(int errno_, const char *filename);
271 : : NORETURN void mp_raise_recursion_depth(void);
272 : :
273 : : #if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG
274 : : #undef mp_check_self
275 : : #define mp_check_self(pred)
276 : : #else
277 : : // A port may define to raise TypeError for example
278 : : #ifndef mp_check_self
279 : : #define mp_check_self(pred) assert(pred)
280 : : #endif
281 : : #endif
282 : :
283 : : // helper functions for native/viper code
284 : : int mp_native_type_from_qstr(qstr qst);
285 : : mp_uint_t mp_native_from_obj(mp_obj_t obj, mp_uint_t type);
286 : : mp_obj_t mp_native_to_obj(mp_uint_t val, mp_uint_t type);
287 : :
288 : : #if MICROPY_PY_SYS_PATH
289 : : #define mp_sys_path (MP_STATE_VM(sys_mutable[MP_SYS_MUTABLE_PATH]))
290 : : #endif
291 : :
292 : : #if MICROPY_PY_SYS_ARGV
293 : : #define mp_sys_argv (MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_sys_argv_obj)))
294 : : #endif
295 : :
296 : : #if MICROPY_WARNINGS
297 : : #ifndef mp_warning
298 : : void mp_warning(const char *category, const char *msg, ...);
299 : : #endif
300 : : #else
301 : : #define mp_warning(...)
302 : : #endif
303 : :
304 : : #endif // MICROPY_INCLUDED_PY_RUNTIME_H
|