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 | |
27 | #include <stdint.h> |
28 | |
29 | #include "py/objfun.h" |
30 | #include "py/compile.h" |
31 | #include "py/runtime.h" |
32 | #include "py/builtin.h" |
33 | |
34 | #if MICROPY_PY_BUILTINS_COMPILE |
35 | |
36 | typedef struct _mp_obj_code_t { |
37 | mp_obj_base_t base; |
38 | mp_obj_t module_fun; |
39 | } mp_obj_code_t; |
40 | |
41 | STATIC const mp_obj_type_t mp_type_code = { |
42 | { &mp_type_type }, |
43 | .name = MP_QSTR_code, |
44 | }; |
45 | |
46 | STATIC mp_obj_t code_execute(mp_obj_code_t *self, mp_obj_dict_t *globals, mp_obj_dict_t *locals) { |
47 | // save context and set new context |
48 | mp_obj_dict_t *old_globals = mp_globals_get(); |
49 | mp_obj_dict_t *old_locals = mp_locals_get(); |
50 | mp_globals_set(globals); |
51 | mp_locals_set(locals); |
52 | |
53 | // a bit of a hack: fun_bc will re-set globals, so need to make sure it's |
54 | // the correct one |
55 | if (mp_obj_is_type(self->module_fun, &mp_type_fun_bc)) { |
56 | mp_obj_fun_bc_t *fun_bc = MP_OBJ_TO_PTR(self->module_fun); |
57 | fun_bc->globals = globals; |
58 | } |
59 | |
60 | // execute code |
61 | nlr_buf_t nlr; |
62 | if (nlr_push(&nlr) == 0) { |
63 | mp_obj_t ret = mp_call_function_0(self->module_fun); |
64 | nlr_pop(); |
65 | mp_globals_set(old_globals); |
66 | mp_locals_set(old_locals); |
67 | return ret; |
68 | } else { |
69 | // exception; restore context and re-raise same exception |
70 | mp_globals_set(old_globals); |
71 | mp_locals_set(old_locals); |
72 | nlr_jump(nlr.ret_val); |
73 | } |
74 | } |
75 | |
76 | STATIC mp_obj_t mp_builtin_compile(size_t n_args, const mp_obj_t *args) { |
77 | (void)n_args; |
78 | |
79 | // get the source |
80 | size_t str_len; |
81 | const char *str = mp_obj_str_get_data(args[0], &str_len); |
82 | |
83 | // get the filename |
84 | qstr filename = mp_obj_str_get_qstr(args[1]); |
85 | |
86 | // create the lexer |
87 | mp_lexer_t *lex = mp_lexer_new_from_str_len(filename, str, str_len, 0); |
88 | |
89 | // get the compile mode |
90 | qstr mode = mp_obj_str_get_qstr(args[2]); |
91 | mp_parse_input_kind_t parse_input_kind; |
92 | switch (mode) { |
93 | case MP_QSTR_single: |
94 | parse_input_kind = MP_PARSE_SINGLE_INPUT; |
95 | break; |
96 | case MP_QSTR_exec: |
97 | parse_input_kind = MP_PARSE_FILE_INPUT; |
98 | break; |
99 | case MP_QSTR_eval: |
100 | parse_input_kind = MP_PARSE_EVAL_INPUT; |
101 | break; |
102 | default: |
103 | mp_raise_ValueError(MP_ERROR_TEXT("bad compile mode" )); |
104 | } |
105 | |
106 | mp_obj_code_t *code = m_new_obj(mp_obj_code_t); |
107 | code->base.type = &mp_type_code; |
108 | code->module_fun = mp_parse_compile_execute(lex, parse_input_kind, NULL, NULL); |
109 | return MP_OBJ_FROM_PTR(code); |
110 | } |
111 | MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_compile_obj, 3, 6, mp_builtin_compile); |
112 | |
113 | #endif // MICROPY_PY_BUILTINS_COMPILE |
114 | |
115 | #if MICROPY_PY_BUILTINS_EVAL_EXEC |
116 | |
117 | STATIC mp_obj_t eval_exec_helper(size_t n_args, const mp_obj_t *args, mp_parse_input_kind_t parse_input_kind) { |
118 | // work out the context |
119 | mp_obj_dict_t *globals = mp_globals_get(); |
120 | mp_obj_dict_t *locals = mp_locals_get(); |
121 | for (size_t i = 1; i < 3 && i < n_args; ++i) { |
122 | if (args[i] != mp_const_none) { |
123 | if (!mp_obj_is_type(args[i], &mp_type_dict)) { |
124 | mp_raise_TypeError(NULL); |
125 | } |
126 | locals = MP_OBJ_TO_PTR(args[i]); |
127 | if (i == 1) { |
128 | globals = locals; |
129 | } |
130 | } |
131 | } |
132 | |
133 | #if MICROPY_PY_BUILTINS_COMPILE |
134 | if (mp_obj_is_type(args[0], &mp_type_code)) { |
135 | return code_execute(MP_OBJ_TO_PTR(args[0]), globals, locals); |
136 | } |
137 | #endif |
138 | |
139 | // Extract the source code. |
140 | mp_buffer_info_t bufinfo; |
141 | mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); |
142 | |
143 | // create the lexer |
144 | // MP_PARSE_SINGLE_INPUT is used to indicate a file input |
145 | mp_lexer_t *lex; |
146 | if (MICROPY_PY_BUILTINS_EXECFILE && parse_input_kind == MP_PARSE_SINGLE_INPUT) { |
147 | lex = mp_lexer_new_from_file(bufinfo.buf); |
148 | parse_input_kind = MP_PARSE_FILE_INPUT; |
149 | } else { |
150 | lex = mp_lexer_new_from_str_len(MP_QSTR__lt_string_gt_, bufinfo.buf, bufinfo.len, 0); |
151 | } |
152 | |
153 | return mp_parse_compile_execute(lex, parse_input_kind, globals, locals); |
154 | } |
155 | |
156 | STATIC mp_obj_t mp_builtin_eval(size_t n_args, const mp_obj_t *args) { |
157 | return eval_exec_helper(n_args, args, MP_PARSE_EVAL_INPUT); |
158 | } |
159 | MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_eval_obj, 1, 3, mp_builtin_eval); |
160 | |
161 | STATIC mp_obj_t mp_builtin_exec(size_t n_args, const mp_obj_t *args) { |
162 | return eval_exec_helper(n_args, args, MP_PARSE_FILE_INPUT); |
163 | } |
164 | MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_exec_obj, 1, 3, mp_builtin_exec); |
165 | |
166 | #endif // MICROPY_PY_BUILTINS_EVAL_EXEC |
167 | |
168 | #if MICROPY_PY_BUILTINS_EXECFILE |
169 | STATIC mp_obj_t mp_builtin_execfile(size_t n_args, const mp_obj_t *args) { |
170 | // MP_PARSE_SINGLE_INPUT is used to indicate a file input |
171 | return eval_exec_helper(n_args, args, MP_PARSE_SINGLE_INPUT); |
172 | } |
173 | MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_execfile_obj, 1, 3, mp_builtin_execfile); |
174 | #endif |
175 | |