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 <assert.h>
28 : :
29 : : #include "py/emit.h"
30 : : #include "py/nativeglue.h"
31 : :
32 : : #if MICROPY_ENABLE_COMPILER
33 : :
34 : : #if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
35 : 418779 : qstr_short_t mp_emit_common_use_qstr(mp_emit_common_t *emit, qstr qst) {
36 : 418779 : mp_map_elem_t *elem = mp_map_lookup(&emit->qstr_map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
37 [ + + ]: 418782 : if (elem->value == MP_OBJ_NULL) {
38 : 36686 : elem->value = MP_OBJ_NEW_SMALL_INT(emit->qstr_map.used - 1);
39 : : }
40 : 418782 : return MP_OBJ_SMALL_INT_VALUE(elem->value);
41 : : }
42 : : #endif
43 : :
44 : : // Compare two objects for strict equality, including equality of type. This is
45 : : // different to the semantics of mp_obj_equal which, eg, has (True,) == (1.0,).
46 : 216119 : static bool strictly_equal(mp_obj_t a, mp_obj_t b) {
47 [ + + ]: 216119 : if (a == b) {
48 : : return true;
49 : : }
50 : :
51 : : #if MICROPY_EMIT_NATIVE
52 [ + - + + ]: 185112 : if (a == MP_OBJ_FROM_PTR(&mp_fun_table) || b == MP_OBJ_FROM_PTR(&mp_fun_table)) {
53 : : return false;
54 : : }
55 : : #endif
56 : :
57 : 150942 : const mp_obj_type_t *a_type = mp_obj_get_type(a);
58 : 150942 : const mp_obj_type_t *b_type = mp_obj_get_type(b);
59 [ + + ]: 150942 : if (a_type != b_type) {
60 : : return false;
61 : : }
62 [ + + ]: 120888 : if (a_type == &mp_type_tuple) {
63 : 9423 : mp_obj_tuple_t *a_tuple = MP_OBJ_TO_PTR(a);
64 : 9423 : mp_obj_tuple_t *b_tuple = MP_OBJ_TO_PTR(b);
65 [ + + ]: 9423 : if (a_tuple->len != b_tuple->len) {
66 : : return false;
67 : : }
68 [ + + ]: 8907 : for (size_t i = 0; i < a_tuple->len; ++i) {
69 [ + + ]: 7709 : if (!strictly_equal(a_tuple->items[i], b_tuple->items[i])) {
70 : : return false;
71 : : }
72 : : }
73 : : return true;
74 : : } else {
75 : 111465 : return mp_obj_equal(a, b);
76 : : }
77 : : }
78 : :
79 : 44937 : size_t mp_emit_common_use_const_obj(mp_emit_common_t *emit, mp_obj_t const_obj) {
80 [ + + ]: 215019 : for (size_t i = 0; i < emit->const_obj_list.len; ++i) {
81 [ + + ]: 208410 : if (strictly_equal(emit->const_obj_list.items[i], const_obj)) {
82 : : return i;
83 : : }
84 : : }
85 : 6609 : mp_obj_list_append(MP_OBJ_FROM_PTR(&emit->const_obj_list), const_obj);
86 : 6609 : return emit->const_obj_list.len - 1;
87 : : }
88 : :
89 : 23663 : id_info_t *mp_emit_common_get_id_for_modification(scope_t *scope, qstr qst) {
90 : : // name adding/lookup
91 : 23663 : id_info_t *id = scope_find_or_add_id(scope, qst, ID_INFO_KIND_GLOBAL_IMPLICIT);
92 [ + + ]: 23663 : if (id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
93 [ + + ]: 16934 : if (SCOPE_IS_FUNC_LIKE(scope->kind)) {
94 : : // rebind as a local variable
95 : 3598 : id->kind = ID_INFO_KIND_LOCAL;
96 : : } else {
97 : : // mark this as assigned, to prevent it from being closed over
98 : 13336 : id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT_ASSIGNED;
99 : : }
100 : : }
101 : 23663 : return id;
102 : : }
103 : :
104 : 439021 : void mp_emit_common_id_op(emit_t *emit, const mp_emit_method_table_id_ops_t *emit_method_table, scope_t *scope, qstr qst) {
105 : : // assumes pass is greater than 1, ie that all identifiers are defined in the scope
106 : :
107 : 439021 : id_info_t *id = scope_find(scope, qst);
108 [ - + ]: 439022 : assert(id != NULL);
109 : :
110 : : // call the emit backend with the correct code
111 [ + + ]: 439022 : if (id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT || id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT_ASSIGNED) {
112 : 325626 : emit_method_table->global(emit, qst, MP_EMIT_IDOP_GLOBAL_NAME);
113 [ + + ]: 113396 : } else if (id->kind == ID_INFO_KIND_GLOBAL_EXPLICIT) {
114 : 38805 : emit_method_table->global(emit, qst, MP_EMIT_IDOP_GLOBAL_GLOBAL);
115 [ + + ]: 74591 : } else if (id->kind == ID_INFO_KIND_LOCAL) {
116 : 72456 : emit_method_table->local(emit, qst, id->local_num, MP_EMIT_IDOP_LOCAL_FAST);
117 : : } else {
118 [ - + ]: 2135 : assert(id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE);
119 : 2135 : emit_method_table->local(emit, qst, id->local_num, MP_EMIT_IDOP_LOCAL_DEREF);
120 : : }
121 : 439023 : }
122 : :
123 : : #endif // MICROPY_ENABLE_COMPILER
|