diff --git a/py/parse.c b/py/parse.c index db89fb58450e3..fc14afca0a476 100644 --- a/py/parse.c +++ b/py/parse.c @@ -705,6 +705,15 @@ static bool fold_logical_constants(parser_t *parser, uint8_t rule_id, size_t *nu return false; } +#if MICROPY_COMP_CONST +static bool is_const_atom_expr_normal(mp_parse_node_t node) { + return MP_PARSE_NODE_IS_STRUCT_KIND(node, RULE_atom_expr_normal) + && MP_PARSE_NODE_IS_ID(((mp_parse_node_struct_t *)node)->nodes[0]) + && MP_PARSE_NODE_LEAF_ARG(((mp_parse_node_struct_t *)node)->nodes[0]) == MP_QSTR_const + && MP_PARSE_NODE_IS_STRUCT_KIND(((mp_parse_node_struct_t *)node)->nodes[1], RULE_trailer_paren); +} +#endif + static bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) { // this code does folding of arbitrary integer expressions, eg 1 + 2 * 3 + 4 // it does not do partial folding, eg 1 + 2 + x -> 3 + x @@ -797,21 +806,26 @@ static bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) { if (!MP_PARSE_NODE_IS_NULL(pn1) && !(MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_expr_stmt_augassign) || MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_expr_stmt_assign_list))) { - // this node is of the form = + // this node is of the form = or : int = mp_parse_node_t pn0 = peek_result(parser, 1); if (MP_PARSE_NODE_IS_ID(pn0) - && MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_atom_expr_normal) - && MP_PARSE_NODE_IS_ID(((mp_parse_node_struct_t *)pn1)->nodes[0]) - && MP_PARSE_NODE_LEAF_ARG(((mp_parse_node_struct_t *)pn1)->nodes[0]) == MP_QSTR_const - && MP_PARSE_NODE_IS_STRUCT_KIND(((mp_parse_node_struct_t *)pn1)->nodes[1], RULE_trailer_paren) - ) { + && ((MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_annassign) && + MP_PARSE_NODE_IS_ID(((mp_parse_node_struct_t *)pn1)->nodes[0]) && + MP_PARSE_NODE_LEAF_ARG(((mp_parse_node_struct_t *)pn1)->nodes[0]) == MP_QSTR_int && + is_const_atom_expr_normal(((mp_parse_node_struct_t *)pn1)->nodes[1])) + || is_const_atom_expr_normal(pn1))) { // code to assign dynamic constants: id = const(value) // get the id qstr id = MP_PARSE_NODE_LEAF_ARG(pn0); // get the value - mp_parse_node_t pn_value = ((mp_parse_node_struct_t *)((mp_parse_node_struct_t *)pn1)->nodes[1])->nodes[0]; + mp_parse_node_t pn_value; + if (MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_annassign)) { + pn_value = ((mp_parse_node_struct_t *)(((mp_parse_node_struct_t *)(((mp_parse_node_struct_t *)pn1)->nodes[1]))->nodes[1]))->nodes[0]; + } else { + pn_value = ((mp_parse_node_struct_t *)((mp_parse_node_struct_t *)pn1)->nodes[1])->nodes[0]; + } if (!mp_parse_node_is_const(pn_value)) { mp_obj_t exc = mp_obj_new_exception_msg(&mp_type_SyntaxError, MP_ERROR_TEXT("not a constant")); diff --git a/tests/micropython/const2_annotated.py b/tests/micropython/const2_annotated.py new file mode 100644 index 0000000000000..fde653add7550 --- /dev/null +++ b/tests/micropython/const2_annotated.py @@ -0,0 +1,48 @@ +# check that consts are not replaced in anything except standalone identifiers + +from micropython import const + +X: int = const(1) +Y: int = const(2) +Z: int = const(3) + +# import that uses a constant +import micropython as X + +print(globals()["X"]) + + +# function name that matches a constant +def X(): + print("function X", X) + + +globals()["X"]() + + +# arguments that match a constant +def f(X, *Y, **Z): + pass + + +f(1) + + +# class name that matches a constant +class X: + def f(self): + print("class X", X) + + +globals()["X"]().f() + + +# constant within a class +class A: + C1: int = const(4) + + def X(self): + print("method X", Y, C1, self.C1) + + +A().X() diff --git a/tests/micropython/const2_annotated.py.exp b/tests/micropython/const2_annotated.py.exp new file mode 100644 index 0000000000000..0568f91ce2860 --- /dev/null +++ b/tests/micropython/const2_annotated.py.exp @@ -0,0 +1,4 @@ + +function X 1 +class X 1 +method X 2 4 4 diff --git a/tests/micropython/const_annotated.py b/tests/micropython/const_annotated.py new file mode 100644 index 0000000000000..3af7dd3fceda3 --- /dev/null +++ b/tests/micropython/const_annotated.py @@ -0,0 +1,30 @@ +# test constant optimisation +# This test will only work when MICROPY_COMP_CONST is enabled. + +from micropython import const + +X: int = const(123) +Y: int = const(X + 456) + +print(X, Y + 1) + + +def f(): + print(X, Y + 1) + + +f() + +_X: int = const(12) +_Y: int = const(_X + 34) + +print(_X, _Y) + + +class A: + Z: int = const(1) + _Z: int = const(2) + print(Z, _Z) + + +print(hasattr(A, "Z"), hasattr(A, "_Z")) diff --git a/tests/micropython/const_annotated.py.exp b/tests/micropython/const_annotated.py.exp new file mode 100644 index 0000000000000..ece6a5cb2e552 --- /dev/null +++ b/tests/micropython/const_annotated.py.exp @@ -0,0 +1,5 @@ +123 580 +123 580 +12 46 +1 2 +True False pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy