Skip to content

Commit 079f3e5

Browse files
committed
py/parse: Allow all constant objects to be used in "X = const(o)".
Now that constant tuples are supported in the parser, eg (1, True, "str"), it's a small step to allow anything that is a constant to be used with the pattern: from micropython import const X = const(obj) This commit makes the required changes to allow the following types of constants: from micropython import const _INT = const(123) _FLOAT = const(1.2) _COMPLEX = const(3.4j) _STR = const("str") _BYTES = const(b"bytes") _TUPLE = const((_INT, _STR, _BYTES)) _TUPLE2 = const((None, False, True, ..., (), _TUPLE)) Prior to this, only integers could be used in const(...). Signed-off-by: Damien George <damien@micropython.org>
1 parent 761d2f6 commit 079f3e5

File tree

4 files changed

+50
-11
lines changed

4 files changed

+50
-11
lines changed

docs/reference/constrained.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ with an underscore as in ``_COLS``: this symbol is not visible outside the
112112
module so will not occupy RAM.
113113

114114
The argument to ``const()`` may be anything which, at compile time, evaluates
115-
to an integer e.g. ``0x100`` or ``1 << 8``. It can even include other const
115+
to a constant e.g. ``0x100``, ``1 << 8`` or ``(True, "string", b"bytes")``
116+
(see section below for details). It can even include other const
116117
symbols that have already been defined, e.g. ``1 << BIT``.
117118

118119
**Constant data structures**

py/parse.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ bool mp_parse_node_get_int_maybe(mp_parse_node_t pn, mp_obj_t *o) {
357357
}
358358
}
359359

360-
#if MICROPY_COMP_CONST_TUPLE
360+
#if MICROPY_COMP_CONST_TUPLE || MICROPY_COMP_CONST
361361
STATIC bool mp_parse_node_is_const(mp_parse_node_t pn) {
362362
if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
363363
// Small integer.
@@ -545,9 +545,9 @@ STATIC mp_parse_node_t make_node_const_object(parser_t *parser, size_t src_line,
545545
return (mp_parse_node_t)pn;
546546
}
547547

548-
// Create a parse node represeting a constant integer value, possibly optimising
549-
// it by putting the (small) integer value directly in the parse node itself.
550-
STATIC mp_parse_node_t make_node_const_int(parser_t *parser, size_t src_line, mp_obj_t obj) {
548+
// Create a parse node represeting a constant object, possibly optimising the case of
549+
// an integer, by putting the (small) integer value directly in the parse node itself.
550+
STATIC mp_parse_node_t make_node_const_object_optimised(parser_t *parser, size_t src_line, mp_obj_t obj) {
551551
if (mp_obj_is_small_int(obj)) {
552552
mp_int_t val = MP_OBJ_SMALL_INT_VALUE(obj);
553553
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
@@ -579,7 +579,7 @@ STATIC void push_result_token(parser_t *parser, uint8_t rule_id) {
579579
mp_map_elem_t *elem;
580580
if (rule_id == RULE_atom
581581
&& (elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP)) != NULL) {
582-
pn = make_node_const_int(parser, lex->tok_line, elem->value);
582+
pn = make_node_const_object_optimised(parser, lex->tok_line, elem->value);
583583
} else {
584584
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id);
585585
}
@@ -589,7 +589,7 @@ STATIC void push_result_token(parser_t *parser, uint8_t rule_id) {
589589
#endif
590590
} else if (lex->tok_kind == MP_TOKEN_INTEGER) {
591591
mp_obj_t o = mp_parse_num_integer(lex->vstr.buf, lex->vstr.len, 0, lex);
592-
pn = make_node_const_int(parser, lex->tok_line, o);
592+
pn = make_node_const_object_optimised(parser, lex->tok_line, o);
593593
} else if (lex->tok_kind == MP_TOKEN_FLOAT_OR_IMAG) {
594594
mp_obj_t o = mp_parse_num_decimal(lex->vstr.buf, lex->vstr.len, true, false, lex);
595595
pn = make_node_const_object(parser, lex->tok_line, o);
@@ -803,14 +803,14 @@ STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) {
803803

804804
// get the value
805805
mp_parse_node_t pn_value = ((mp_parse_node_struct_t *)((mp_parse_node_struct_t *)pn1)->nodes[1])->nodes[0];
806-
mp_obj_t value;
807-
if (!mp_parse_node_get_int_maybe(pn_value, &value)) {
806+
if (!mp_parse_node_is_const(pn_value)) {
808807
mp_obj_t exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,
809-
MP_ERROR_TEXT("constant must be an integer"));
808+
MP_ERROR_TEXT("not a constant"));
810809
mp_obj_exception_add_traceback(exc, parser->lexer->source_name,
811810
((mp_parse_node_struct_t *)pn1)->source_line, MP_QSTRnull);
812811
nlr_raise(exc);
813812
}
813+
mp_obj_t value = mp_parse_node_convert_to_obj(pn_value);
814814

815815
// store the value in the table of dynamic constants
816816
mp_map_elem_t *elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
@@ -872,7 +872,7 @@ STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) {
872872
for (size_t i = num_args; i > 0; i--) {
873873
pop_result(parser);
874874
}
875-
push_result_node(parser, make_node_const_int(parser, 0, arg0));
875+
push_result_node(parser, make_node_const_object_optimised(parser, 0, arg0));
876876

877877
return true;
878878
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Test constant optimisation, with full range of const types.
2+
# This test will only work when MICROPY_COMP_CONST and MICROPY_COMP_CONST_TUPLE are enabled.
3+
4+
from micropython import const
5+
6+
_INT = const(123)
7+
_STR = const("str")
8+
_BYTES = const(b"bytes")
9+
_TUPLE = const((_INT, _STR, _BYTES))
10+
_TUPLE2 = const((None, False, True, ..., (), _TUPLE))
11+
12+
print(_INT)
13+
print(_STR)
14+
print(_BYTES)
15+
print(_TUPLE)
16+
print(_TUPLE2)
17+
18+
x = _TUPLE
19+
print(x is _TUPLE)
20+
print(x is (_INT, _STR, _BYTES))
21+
22+
print(hasattr(globals(), "_INT"))
23+
print(hasattr(globals(), "_STR"))
24+
print(hasattr(globals(), "_BYTES"))
25+
print(hasattr(globals(), "_TUPLE"))
26+
print(hasattr(globals(), "_TUPLE2"))
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
123
2+
str
3+
b'bytes'
4+
(123, 'str', b'bytes')
5+
(None, False, True, Ellipsis, (), (123, 'str', b'bytes'))
6+
True
7+
True
8+
False
9+
False
10+
False
11+
False
12+
False

0 commit comments

Comments
 (0)