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 : :
27 : : #include <stdint.h>
28 : :
29 : : #include "py/objcode.h"
30 : : #include "py/objfun.h"
31 : : #include "py/compile.h"
32 : : #include "py/runtime.h"
33 : : #include "py/builtin.h"
34 : :
35 : : #if MICROPY_PY_BUILTINS_COMPILE
36 : :
37 : 36 : static mp_obj_t code_execute(mp_obj_code_t *self, mp_obj_dict_t *globals, mp_obj_dict_t *locals) {
38 : : // save context
39 : 36 : nlr_jump_callback_node_globals_locals_t ctx;
40 : 36 : ctx.globals = mp_globals_get();
41 : 36 : ctx.locals = mp_locals_get();
42 : :
43 : : // set new context
44 : 36 : mp_globals_set(globals);
45 : 36 : mp_locals_set(locals);
46 : :
47 : : // set exception handler to restore context if an exception is raised
48 : 36 : nlr_push_jump_callback(&ctx.callback, mp_globals_locals_set_from_nlr_jump_callback);
49 : :
50 : : #if MICROPY_PY_BUILTINS_CODE >= MICROPY_PY_BUILTINS_CODE_BASIC
51 : 36 : mp_module_context_t *module_context = m_new_obj(mp_module_context_t);
52 : 36 : module_context->module.base.type = &mp_type_module;
53 : 36 : module_context->module.globals = globals;
54 : 36 : module_context->constants = *mp_code_get_constants(self);
55 : 36 : mp_obj_t module_fun = mp_make_function_from_proto_fun(mp_code_get_proto_fun(self), module_context, NULL);
56 : : #else
57 : : // The call to mp_parse_compile_execute() in mp_builtin_compile() below passes
58 : : // NULL for the globals, so repopulate that entry now with the correct globals.
59 : : mp_obj_t module_fun = self->module_fun;
60 : : if (mp_obj_is_type(self->module_fun, &mp_type_fun_bc)
61 : : #if MICROPY_EMIT_NATIVE
62 : : || mp_obj_is_type(self->module_fun, &mp_type_fun_native)
63 : : #endif
64 : : ) {
65 : : mp_obj_fun_bc_t *fun_bc = MP_OBJ_TO_PTR(module_fun);
66 : : ((mp_module_context_t *)fun_bc->context)->module.globals = globals;
67 : : }
68 : : #endif
69 : :
70 : : // execute code
71 : 36 : mp_obj_t ret = mp_call_function_0(module_fun);
72 : :
73 : : // deregister exception handler and restore context
74 : 28 : nlr_pop_jump_callback(true);
75 : :
76 : : // return value
77 : 28 : return ret;
78 : : }
79 : :
80 : 55 : static mp_obj_t mp_builtin_compile(size_t n_args, const mp_obj_t *args) {
81 : 55 : (void)n_args;
82 : :
83 : : // get the source
84 : 55 : size_t str_len;
85 : 55 : const char *str = mp_obj_str_get_data(args[0], &str_len);
86 : :
87 : : // get the filename
88 : 55 : qstr filename = mp_obj_str_get_qstr(args[1]);
89 : :
90 : : // create the lexer
91 : 55 : mp_lexer_t *lex = mp_lexer_new_from_str_len(filename, str, str_len, 0);
92 : :
93 : : // get the compile mode
94 : 55 : qstr mode = mp_obj_str_get_qstr(args[2]);
95 : 55 : mp_parse_input_kind_t parse_input_kind;
96 [ + + + + ]: 55 : switch (mode) {
97 : : case MP_QSTR_single:
98 : : parse_input_kind = MP_PARSE_SINGLE_INPUT;
99 : : break;
100 : 27 : case MP_QSTR_exec:
101 : 27 : parse_input_kind = MP_PARSE_FILE_INPUT;
102 : 27 : break;
103 : 12 : case MP_QSTR_eval:
104 : 12 : parse_input_kind = MP_PARSE_EVAL_INPUT;
105 : 12 : break;
106 : : default:
107 : 4 : mp_raise_ValueError(MP_ERROR_TEXT("bad compile mode"));
108 : : }
109 : :
110 : : #if MICROPY_PY_BUILTINS_CODE >= MICROPY_PY_BUILTINS_CODE_BASIC
111 : :
112 : 51 : mp_parse_tree_t parse_tree = mp_parse(lex, parse_input_kind);
113 : 39 : mp_module_context_t ctx;
114 : 39 : ctx.module.globals = NULL;
115 : 39 : mp_compiled_module_t cm;
116 : 39 : cm.context = &ctx;
117 : 39 : mp_compile_to_raw_code(&parse_tree, lex->source_name, parse_input_kind == MP_PARSE_SINGLE_INPUT, &cm);
118 : :
119 : : #if MICROPY_PY_BUILTINS_CODE >= MICROPY_PY_BUILTINS_CODE_FULL
120 : : mp_module_context_t *ctx_ptr = m_new_obj(mp_module_context_t);
121 : : *ctx_ptr = ctx;
122 : : return mp_obj_new_code(ctx_ptr, cm.rc, true);
123 : : #else
124 : 39 : return mp_obj_new_code(ctx.constants, cm.rc);
125 : : #endif
126 : :
127 : : #else
128 : :
129 : : mp_obj_t module_fun = mp_parse_compile_execute(lex, parse_input_kind, NULL, NULL);
130 : : return mp_obj_new_code(module_fun);
131 : :
132 : : #endif
133 : : }
134 : : MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_compile_obj, 3, 6, mp_builtin_compile);
135 : :
136 : : #endif // MICROPY_PY_BUILTINS_COMPILE
137 : :
138 : : #if MICROPY_PY_BUILTINS_EVAL_EXEC
139 : :
140 : 1517 : static mp_obj_t eval_exec_helper(size_t n_args, const mp_obj_t *args, mp_parse_input_kind_t parse_input_kind) {
141 : : // work out the context
142 : 1517 : mp_obj_dict_t *globals = mp_globals_get();
143 : 1517 : mp_obj_dict_t *locals = mp_locals_get();
144 [ + + ]: 1596 : for (size_t i = 1; i < 3 && i < n_args; ++i) {
145 [ + + ]: 87 : if (args[i] != mp_const_none) {
146 [ - + - + : 63 : if (!mp_obj_is_type(args[i], &mp_type_dict)) {
- + - + +
+ - + ]
147 : 8 : mp_raise_TypeError(NULL);
148 : : }
149 : 55 : locals = MP_OBJ_TO_PTR(args[i]);
150 [ + + ]: 55 : if (i == 1) {
151 : 39 : globals = locals;
152 : : }
153 : : }
154 : : }
155 : :
156 : : #if MICROPY_PY_BUILTINS_COMPILE
157 [ - + - + : 1509 : if (mp_obj_is_type(args[0], &mp_type_code)) {
- + - + +
+ + + ]
158 : 36 : return code_execute(MP_OBJ_TO_PTR(args[0]), globals, locals);
159 : : }
160 : : #endif
161 : :
162 : :
163 : : // create the lexer
164 : : // MP_PARSE_SINGLE_INPUT is used to indicate a file input
165 : 1473 : mp_lexer_t *lex;
166 [ + + ]: 1473 : if (MICROPY_PY_BUILTINS_EXECFILE && parse_input_kind == MP_PARSE_SINGLE_INPUT) {
167 : 12 : lex = mp_lexer_new_from_file(mp_obj_str_get_qstr(args[0]));
168 : 8 : parse_input_kind = MP_PARSE_FILE_INPUT;
169 : : } else {
170 : : // Extract the source code.
171 : 1461 : mp_buffer_info_t bufinfo;
172 : 1461 : mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
173 : :
174 : 1461 : lex = mp_lexer_new_from_str_len(MP_QSTR__lt_string_gt_, bufinfo.buf, bufinfo.len, 0);
175 : : }
176 : :
177 : 1463 : return mp_parse_compile_execute(lex, parse_input_kind, globals, locals);
178 : : }
179 : :
180 : 378 : static mp_obj_t mp_builtin_eval(size_t n_args, const mp_obj_t *args) {
181 : 378 : return eval_exec_helper(n_args, args, MP_PARSE_EVAL_INPUT);
182 : : }
183 : : MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_eval_obj, 1, 3, mp_builtin_eval);
184 : :
185 : 1126 : static mp_obj_t mp_builtin_exec(size_t n_args, const mp_obj_t *args) {
186 : 1126 : return eval_exec_helper(n_args, args, MP_PARSE_FILE_INPUT);
187 : : }
188 : : MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_exec_obj, 1, 3, mp_builtin_exec);
189 : :
190 : : #endif // MICROPY_PY_BUILTINS_EVAL_EXEC
191 : :
192 : : #if MICROPY_PY_BUILTINS_EXECFILE
193 : 12 : static mp_obj_t mp_builtin_execfile(size_t n_args, const mp_obj_t *args) {
194 : : // MP_PARSE_SINGLE_INPUT is used to indicate a file input
195 : 12 : return eval_exec_helper(n_args, args, MP_PARSE_SINGLE_INPUT);
196 : : }
197 : : MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_execfile_obj, 1, 3, mp_builtin_execfile);
198 : : #endif
|