summaryrefslogtreecommitdiffstatshomepage
path: root/py/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'py/parse.c')
-rw-r--r--py/parse.c80
1 files changed, 72 insertions, 8 deletions
diff --git a/py/parse.c b/py/parse.c
index 397d46d9f0..dc360e40ce 100644
--- a/py/parse.c
+++ b/py/parse.c
@@ -227,11 +227,14 @@ STATIC void pop_rule(parser_t *parser, const rule_t **rule, size_t *arg_i, size_
*src_line = parser->rule_stack[parser->rule_stack_top].src_line;
}
-mp_parse_node_t mp_parse_node_new_leaf(size_t kind, mp_int_t arg) {
- if (kind == MP_PARSE_NODE_SMALL_INT) {
- return (mp_parse_node_t)(kind | (arg << 1));
- }
- return (mp_parse_node_t)(kind | (arg << 4));
+bool mp_parse_node_is_const_false(mp_parse_node_t pn) {
+ return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE)
+ || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) == 0);
+}
+
+bool mp_parse_node_is_const_true(mp_parse_node_t pn) {
+ return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_TRUE)
+ || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) != 0);
}
bool mp_parse_node_get_int_maybe(mp_parse_node_t pn, mp_obj_t *o) {
@@ -408,7 +411,7 @@ STATIC void push_result_token(parser_t *parser, const rule_t *rule) {
mp_map_elem_t *elem;
if (rule->rule_id == RULE_atom
&& (elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP)) != NULL) {
- pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, MP_OBJ_SMALL_INT_VALUE(elem->value));
+ pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(elem->value));
} else {
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id);
}
@@ -419,7 +422,7 @@ STATIC void push_result_token(parser_t *parser, const rule_t *rule) {
} else if (lex->tok_kind == MP_TOKEN_INTEGER) {
mp_obj_t o = mp_parse_num_integer(lex->vstr.buf, lex->vstr.len, 0, lex);
if (MP_OBJ_IS_SMALL_INT(o)) {
- pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, MP_OBJ_SMALL_INT_VALUE(o));
+ pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(o));
} else {
pn = make_node_const_object(parser, lex->tok_line, o);
}
@@ -467,6 +470,63 @@ STATIC MP_DEFINE_CONST_MAP(mp_constants_map, mp_constants_table);
STATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t num_args);
#if MICROPY_COMP_CONST_FOLDING
+STATIC bool fold_logical_constants(parser_t *parser, const rule_t *rule, size_t *num_args) {
+ if (rule->rule_id == RULE_or_test
+ || rule->rule_id == RULE_and_test) {
+ // folding for binary logical ops: or and
+ size_t copy_to = *num_args;
+ for (size_t i = copy_to; i > 0;) {
+ mp_parse_node_t pn = peek_result(parser, --i);
+ parser->result_stack[parser->result_stack_top - copy_to] = pn;
+ if (i == 0) {
+ // always need to keep the last value
+ break;
+ }
+ if (rule->rule_id == RULE_or_test) {
+ if (mp_parse_node_is_const_true(pn)) {
+ //
+ break;
+ } else if (!mp_parse_node_is_const_false(pn)) {
+ copy_to -= 1;
+ }
+ } else {
+ // RULE_and_test
+ if (mp_parse_node_is_const_false(pn)) {
+ break;
+ } else if (!mp_parse_node_is_const_true(pn)) {
+ copy_to -= 1;
+ }
+ }
+ }
+ copy_to -= 1; // copy_to now contains number of args to pop
+
+ // pop and discard all the short-circuited expressions
+ for (size_t i = 0; i < copy_to; ++i) {
+ pop_result(parser);
+ }
+ *num_args -= copy_to;
+
+ // we did a complete folding if there's only 1 arg left
+ return *num_args == 1;
+
+ } else if (rule->rule_id == RULE_not_test_2) {
+ // folding for unary logical op: not
+ mp_parse_node_t pn = peek_result(parser, 0);
+ if (mp_parse_node_is_const_false(pn)) {
+ pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, MP_TOKEN_KW_TRUE);
+ } else if (mp_parse_node_is_const_true(pn)) {
+ pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, MP_TOKEN_KW_FALSE);
+ } else {
+ return false;
+ }
+ pop_result(parser);
+ push_result_node(parser, pn);
+ return true;
+ }
+
+ return false;
+}
+
STATIC bool fold_constants(parser_t *parser, const rule_t *rule, 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
@@ -648,7 +708,7 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args
pop_result(parser);
}
if (MP_OBJ_IS_SMALL_INT(arg0)) {
- push_result_node(parser, mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, MP_OBJ_SMALL_INT_VALUE(arg0)));
+ push_result_node(parser, mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(arg0)));
} else {
// TODO reuse memory for parse node struct?
push_result_node(parser, make_node_const_object(parser, 0, arg0));
@@ -674,6 +734,10 @@ STATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *ru
}
#if MICROPY_COMP_CONST_FOLDING
+ if (fold_logical_constants(parser, rule, &num_args)) {
+ // we folded this rule so return straight away
+ return;
+ }
if (fold_constants(parser, rule, num_args)) {
// we folded this rule so return straight away
return;