aboutsummaryrefslogtreecommitdiff
path: root/py/parse.c
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2017-12-11 22:39:12 +1100
committerDamien George <damien.p.george@gmail.com>2017-12-11 22:39:12 +1100
commit2759bec8587b0c0b7da1fa3a013e4f1b1530ad27 (patch)
tree42d424cc8f3a3024cc020cdcc3aee6e2bd9593e4 /py/parse.c
parent9c027073568d9be43bd1aabcac60a6ff208c4299 (diff)
py: Extend nan-boxing config to have 47-bit small integers.
The nan-boxing representation has an extra 16-bits of space to store small-int values, and making use of it allows to create and manipulate full 32-bit positive integers (ie up to 0xffffffff) without using the heap.
Diffstat (limited to 'py/parse.c')
-rw-r--r--py/parse.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/py/parse.c b/py/parse.c
index f7fe30418..b80cc8fb1 100644
--- a/py/parse.c
+++ b/py/parse.c
@@ -369,6 +369,18 @@ STATIC mp_parse_node_t make_node_const_object(parser_t *parser, size_t src_line,
return (mp_parse_node_t)pn;
}
+STATIC mp_parse_node_t mp_parse_node_new_small_int_checked(parser_t *parser, mp_obj_t o_val) {
+ (void)parser;
+ mp_int_t val = MP_OBJ_SMALL_INT_VALUE(o_val);
+ #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
+ // A parse node is only 32-bits and the small-int value must fit in 31-bits
+ if (((val ^ (val << 1)) & 0xffffffff80000000) != 0) {
+ return make_node_const_object(parser, 0, o_val);
+ }
+ #endif
+ return mp_parse_node_new_small_int(val);
+}
+
STATIC void push_result_token(parser_t *parser, const rule_t *rule) {
mp_parse_node_t pn;
mp_lexer_t *lex = parser->lexer;
@@ -380,7 +392,7 @@ STATIC void push_result_token(parser_t *parser, const rule_t *rule) {
if (rule->rule_id == RULE_atom
&& (elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP)) != NULL) {
if (MP_OBJ_IS_SMALL_INT(elem->value)) {
- pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(elem->value));
+ pn = mp_parse_node_new_small_int_checked(parser, elem->value);
} else {
pn = make_node_const_object(parser, lex->tok_line, elem->value);
}
@@ -394,7 +406,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_small_int(MP_OBJ_SMALL_INT_VALUE(o));
+ pn = mp_parse_node_new_small_int_checked(parser, o);
} else {
pn = make_node_const_object(parser, lex->tok_line, o);
}
@@ -686,7 +698,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_small_int(MP_OBJ_SMALL_INT_VALUE(arg0)));
+ push_result_node(parser, mp_parse_node_new_small_int_checked(parser, arg0));
} else {
// TODO reuse memory for parse node struct?
push_result_node(parser, make_node_const_object(parser, 0, arg0));