Skip to content

Commit 57e99eb

Browse files
committed
py: Add simple way of looking up constants in compiler.
Working towards trying to support compile-time constants (see discussion in issue adafruit#227), this patch allows the compiler to look inside arbitrary uPy objects at compile time. The objects to search are given by the macro MICROPY_EXTRA_CONSTANTS (so they must be constant/ROM objects), and the constant folding occures on forms base.attr (both base and attr must be id's). It works, but it breaks strict CPython compatibility, since the lookup will succeed even without importing the namespace.
1 parent ae49105 commit 57e99eb

2 files changed

Lines changed: 42 additions & 4 deletions

File tree

py/compile.c

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,19 @@ STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const cha
7878
comp->had_error = true;
7979
}
8080

81+
STATIC const mp_map_elem_t mp_constants_table[] = {
82+
// Extra constants as defined by a port
83+
MICROPY_EXTRA_CONSTANTS
84+
};
85+
86+
STATIC const mp_map_t mp_constants_map = {
87+
.all_keys_are_qstrs = 1,
88+
.table_is_fixed_array = 1,
89+
.used = sizeof(mp_constants_table) / sizeof(mp_map_elem_t),
90+
.alloc = sizeof(mp_constants_table) / sizeof(mp_map_elem_t),
91+
.table = (mp_map_elem_t*)mp_constants_table,
92+
};
93+
8194
mp_parse_node_t fold_constants(mp_parse_node_t pn) {
8295
if (MP_PARSE_NODE_IS_STRUCT(pn)) {
8396
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
@@ -168,10 +181,12 @@ mp_parse_node_t fold_constants(mp_parse_node_t pn) {
168181
}
169182
break;
170183

171-
#if MICROPY_EMIT_CPYTHON
172184
case PN_power:
173-
// can overflow; enabled only to compare with CPython
174-
if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_NULL(pns->nodes[1]) && !MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
185+
if (0) {
186+
#if MICROPY_EMIT_CPYTHON
187+
} else if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_NULL(pns->nodes[1]) && !MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
188+
// int**x
189+
// can overflow; enabled only to compare with CPython
175190
mp_parse_node_struct_t* pns2 = (mp_parse_node_struct_t*)pns->nodes[2];
176191
if (MP_PARSE_NODE_IS_SMALL_INT(pns2->nodes[0])) {
177192
int power = MP_PARSE_NODE_LEAF_SMALL_INT(pns2->nodes[0]);
@@ -184,9 +199,27 @@ mp_parse_node_t fold_constants(mp_parse_node_t pn) {
184199
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ans);
185200
}
186201
}
202+
#endif
203+
} else if (MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_trailer_period) && MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
204+
// id.id
205+
// look it up in constant table, see if it can be replaced with an integer
206+
mp_parse_node_struct_t* pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
207+
assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
208+
qstr q_base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
209+
qstr q_attr = MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]);
210+
mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&mp_constants_map, MP_OBJ_NEW_QSTR(q_base), MP_MAP_LOOKUP);
211+
if (elem != NULL) {
212+
mp_obj_t dest[2];
213+
mp_load_method_maybe(elem->value, q_attr, dest);
214+
if (MP_OBJ_IS_SMALL_INT(dest[0]) && dest[1] == NULL) {
215+
machine_int_t val = MP_OBJ_SMALL_INT_VALUE(dest[0]);
216+
if (MP_PARSE_FITS_SMALL_INT(val)) {
217+
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, val);
218+
}
219+
}
220+
}
187221
}
188222
break;
189-
#endif
190223
}
191224
}
192225

py/mpconfig.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ typedef double mp_float_t;
150150
#define MICROPY_EXTRA_BUILTIN_MODULES
151151
#endif
152152

153+
// Additional constant definitions for the compiler - see compile.c:mp_constants_table.
154+
#ifndef MICROPY_EXTRA_CONSTANTS
155+
#define MICROPY_EXTRA_CONSTANTS
156+
#endif
157+
153158
/*****************************************************************************/
154159
/* Miscellaneous settings */
155160

0 commit comments

Comments
 (0)