py: Parse big-int/float/imag constants directly in parser.
Previous to this patch, a big-int, float or imag constant was interned (made into a qstr) and then parsed at runtime to create an object each time it was needed. This is wasteful in RAM and not efficient. Now, these constants are parsed straight away in the parser and turned into objects. This allows constants with large numbers of digits (so addresses issue #1103) and takes us a step closer to #722.
This commit is contained in:
parent
5f97aaeca4
commit
7d414a1b52
|
@ -161,9 +161,9 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
|
|||
vstr_add_byte(&vstr, *s);
|
||||
}
|
||||
if (flt) {
|
||||
next = mp_parse_num_decimal(vstr.buf, vstr.len, false, false);
|
||||
next = mp_parse_num_decimal(vstr.buf, vstr.len, false, false, NULL);
|
||||
} else {
|
||||
next = mp_parse_num_integer(vstr.buf, vstr.len, 10);
|
||||
next = mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
10
py/bc0.h
10
py/bc0.h
|
@ -34,12 +34,10 @@
|
|||
#define MP_BC_LOAD_CONST_TRUE (0x12)
|
||||
#define MP_BC_LOAD_CONST_ELLIPSIS (0x13)
|
||||
#define MP_BC_LOAD_CONST_SMALL_INT (0x14) // signed var-int
|
||||
#define MP_BC_LOAD_CONST_INT (0x15) // qstr
|
||||
#define MP_BC_LOAD_CONST_DEC (0x16) // qstr
|
||||
#define MP_BC_LOAD_CONST_BYTES (0x17) // qstr
|
||||
#define MP_BC_LOAD_CONST_STRING (0x18) // qstr
|
||||
#define MP_BC_LOAD_CONST_OBJ (0x09) // ptr; TODO renumber to be in order
|
||||
#define MP_BC_LOAD_NULL (0x19)
|
||||
#define MP_BC_LOAD_CONST_BYTES (0x15) // qstr
|
||||
#define MP_BC_LOAD_CONST_STRING (0x16) // qstr
|
||||
#define MP_BC_LOAD_CONST_OBJ (0x17) // ptr
|
||||
#define MP_BC_LOAD_NULL (0x18)
|
||||
|
||||
#define MP_BC_LOAD_FAST_N (0x1a) // uint
|
||||
#define MP_BC_LOAD_DEREF (0x1b) // uint
|
||||
|
|
23
py/compile.c
23
py/compile.c
|
@ -47,6 +47,7 @@ typedef enum {
|
|||
PN_maximum_number_of,
|
||||
PN_string, // special node for non-interned string
|
||||
PN_bytes, // special node for non-interned bytes
|
||||
PN_const_object, // special node for a constant, generic Python object
|
||||
} pn_kind_t;
|
||||
|
||||
#define EMIT(fun) (comp->emit_method_table->fun(comp->emit))
|
||||
|
@ -174,6 +175,7 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
|
|||
#endif
|
||||
case PN_string:
|
||||
case PN_bytes:
|
||||
case PN_const_object:
|
||||
return pn;
|
||||
}
|
||||
|
||||
|
@ -432,6 +434,9 @@ STATIC bool cpython_c_tuple_is_const(mp_parse_node_t pn) {
|
|||
if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_bytes)) {
|
||||
return true;
|
||||
}
|
||||
if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_const_object)) {
|
||||
return true;
|
||||
}
|
||||
if (!MP_PARSE_NODE_IS_LEAF(pn)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -486,6 +491,12 @@ STATIC void cpython_c_tuple_emit_const(compiler_t *comp, mp_parse_node_t pn, vst
|
|||
return;
|
||||
}
|
||||
|
||||
if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_const_object)) {
|
||||
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
|
||||
mp_obj_print((mp_obj_t)pns->nodes[0], PRINT_REPR);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(MP_PARSE_NODE_IS_LEAF(pn));
|
||||
if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
|
||||
vstr_printf(vstr, INT_FMT, MP_PARSE_NODE_LEAF_SMALL_INT(pn));
|
||||
|
@ -495,8 +506,6 @@ STATIC void cpython_c_tuple_emit_const(compiler_t *comp, mp_parse_node_t pn, vst
|
|||
mp_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
|
||||
switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
|
||||
case MP_PARSE_NODE_ID: assert(0);
|
||||
case MP_PARSE_NODE_INTEGER: vstr_printf(vstr, "%s", qstr_str(arg)); break;
|
||||
case MP_PARSE_NODE_DECIMAL: vstr_printf(vstr, "%s", qstr_str(arg)); break;
|
||||
case MP_PARSE_NODE_STRING:
|
||||
case MP_PARSE_NODE_BYTES: {
|
||||
mp_uint_t len;
|
||||
|
@ -2159,7 +2168,8 @@ STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
|||
// for non-REPL, evaluate then discard the expression
|
||||
if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0]))
|
||||
|| MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_string)
|
||||
|| MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_bytes)) {
|
||||
|| MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_bytes)
|
||||
|| MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)) {
|
||||
// do nothing with a lonely constant
|
||||
} else {
|
||||
compile_node(comp, pns->nodes[0]); // just an expression
|
||||
|
@ -2954,6 +2964,10 @@ STATIC void compile_bytes(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
|||
}
|
||||
}
|
||||
|
||||
STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
EMIT_ARG(load_const_obj, (mp_obj_t)pns->nodes[0]);
|
||||
}
|
||||
|
||||
typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
|
||||
STATIC compile_function_t compile_function[] = {
|
||||
#define nc NULL
|
||||
|
@ -2966,6 +2980,7 @@ STATIC compile_function_t compile_function[] = {
|
|||
NULL,
|
||||
compile_string,
|
||||
compile_bytes,
|
||||
compile_const_object,
|
||||
};
|
||||
|
||||
STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) {
|
||||
|
@ -2978,8 +2993,6 @@ STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) {
|
|||
mp_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
|
||||
switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
|
||||
case MP_PARSE_NODE_ID: EMIT_ARG(load_id, arg); break;
|
||||
case MP_PARSE_NODE_INTEGER: EMIT_ARG(load_const_int, arg); break;
|
||||
case MP_PARSE_NODE_DECIMAL: EMIT_ARG(load_const_dec, arg); break;
|
||||
case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg, false); break;
|
||||
case MP_PARSE_NODE_BYTES: EMIT_ARG(load_const_str, arg, true); break;
|
||||
case MP_PARSE_NODE_TOKEN: default:
|
||||
|
|
|
@ -77,8 +77,6 @@ typedef struct _emit_method_table_t {
|
|||
void (*import_star)(emit_t *emit);
|
||||
void (*load_const_tok)(emit_t *emit, mp_token_kind_t tok);
|
||||
void (*load_const_small_int)(emit_t *emit, mp_int_t arg);
|
||||
void (*load_const_int)(emit_t *emit, qstr qst);
|
||||
void (*load_const_dec)(emit_t *emit, qstr qst);
|
||||
void (*load_const_str)(emit_t *emit, qstr qst, bool bytes);
|
||||
void (*load_const_obj)(emit_t *emit, void *obj);
|
||||
void (*load_null)(emit_t *emit);
|
||||
|
|
12
py/emitbc.c
12
py/emitbc.c
|
@ -473,16 +473,6 @@ STATIC void emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg) {
|
|||
}
|
||||
}
|
||||
|
||||
STATIC void emit_bc_load_const_int(emit_t *emit, qstr qst) {
|
||||
emit_bc_pre(emit, 1);
|
||||
emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_CONST_INT, qst);
|
||||
}
|
||||
|
||||
STATIC void emit_bc_load_const_dec(emit_t *emit, qstr qst) {
|
||||
emit_bc_pre(emit, 1);
|
||||
emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_CONST_DEC, qst);
|
||||
}
|
||||
|
||||
STATIC void emit_bc_load_const_str(emit_t *emit, qstr qst, bool bytes) {
|
||||
emit_bc_pre(emit, 1);
|
||||
if (bytes) {
|
||||
|
@ -932,8 +922,6 @@ const emit_method_table_t emit_bc_method_table = {
|
|||
emit_bc_import_star,
|
||||
emit_bc_load_const_tok,
|
||||
emit_bc_load_const_small_int,
|
||||
emit_bc_load_const_int,
|
||||
emit_bc_load_const_dec,
|
||||
emit_bc_load_const_str,
|
||||
emit_bc_load_const_obj,
|
||||
emit_bc_load_null,
|
||||
|
|
16
py/emitcpy.c
16
py/emitcpy.c
|
@ -171,20 +171,6 @@ STATIC void emit_cpy_load_const_small_int(emit_t *emit, mp_int_t arg) {
|
|||
}
|
||||
}
|
||||
|
||||
STATIC void emit_cpy_load_const_int(emit_t *emit, qstr qst) {
|
||||
emit_pre(emit, 1, 3);
|
||||
if (emit->pass == MP_PASS_EMIT) {
|
||||
printf("LOAD_CONST %s\n", qstr_str(qst));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void emit_cpy_load_const_dec(emit_t *emit, qstr qst) {
|
||||
emit_pre(emit, 1, 3);
|
||||
if (emit->pass == MP_PASS_EMIT) {
|
||||
printf("LOAD_CONST %s\n", qstr_str(qst));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void print_quoted_str(qstr qst, bool bytes) {
|
||||
const char *str = qstr_str(qst);
|
||||
int len = strlen(str);
|
||||
|
@ -839,8 +825,6 @@ const emit_method_table_t emit_cpython_method_table = {
|
|||
emit_cpy_import_star,
|
||||
emit_cpy_load_const_tok,
|
||||
emit_cpy_load_const_small_int,
|
||||
emit_cpy_load_const_int,
|
||||
emit_cpy_load_const_dec,
|
||||
emit_cpy_load_const_str,
|
||||
emit_cpy_load_const_obj,
|
||||
emit_cpy_load_null,
|
||||
|
|
|
@ -1142,21 +1142,6 @@ STATIC void emit_native_load_const_small_int(emit_t *emit, mp_int_t arg) {
|
|||
}
|
||||
}
|
||||
|
||||
STATIC void emit_native_load_const_int(emit_t *emit, qstr qst) {
|
||||
DEBUG_printf("load_const_int %s\n", qstr_str(qst));
|
||||
// for viper: load integer, check fits in 32 bits
|
||||
emit_native_pre(emit);
|
||||
emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_INT, qst, REG_ARG_1);
|
||||
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||
}
|
||||
|
||||
STATIC void emit_native_load_const_dec(emit_t *emit, qstr qst) {
|
||||
// for viper, a float/complex is just a Python object
|
||||
emit_native_pre(emit);
|
||||
emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_DEC, qst, REG_ARG_1);
|
||||
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||
}
|
||||
|
||||
STATIC void emit_native_load_const_str(emit_t *emit, qstr qst, bool bytes) {
|
||||
emit_native_pre(emit);
|
||||
// TODO: Eventually we want to be able to work with raw pointers in viper to
|
||||
|
@ -2317,8 +2302,6 @@ const emit_method_table_t EXPORT_FUN(method_table) = {
|
|||
emit_native_import_star,
|
||||
emit_native_load_const_tok,
|
||||
emit_native_load_const_small_int,
|
||||
emit_native_load_const_int,
|
||||
emit_native_load_const_dec,
|
||||
emit_native_load_const_str,
|
||||
emit_native_load_const_obj,
|
||||
emit_native_load_null,
|
||||
|
|
|
@ -192,8 +192,6 @@ const emit_method_table_t emit_pass1_method_table = {
|
|||
(void*)emit_pass1_dummy,
|
||||
(void*)emit_pass1_dummy,
|
||||
(void*)emit_pass1_dummy,
|
||||
(void*)emit_pass1_dummy,
|
||||
(void*)emit_pass1_dummy,
|
||||
#if MICROPY_PY_BUILTINS_SET
|
||||
(void*)emit_pass1_dummy,
|
||||
(void*)emit_pass1_dummy,
|
||||
|
|
|
@ -248,7 +248,7 @@ DEF_RULE(power_dbl_star, c(power_dbl_star), and(2), tok(OP_DBL_STAR), rule(facto
|
|||
// testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
|
||||
// trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
|
||||
|
||||
DEF_RULE(atom, nc, or(10), tok(NAME), tok(NUMBER), rule(atom_string), tok(ELLIPSIS), tok(KW_NONE), tok(KW_TRUE), tok(KW_FALSE), rule(atom_paren), rule(atom_bracket), rule(atom_brace))
|
||||
DEF_RULE(atom, nc, or(11), tok(NAME), tok(INTEGER), tok(FLOAT_OR_IMAG), rule(atom_string), tok(ELLIPSIS), tok(KW_NONE), tok(KW_TRUE), tok(KW_FALSE), rule(atom_paren), rule(atom_bracket), rule(atom_brace))
|
||||
DEF_RULE(atom_string, c(atom_string), one_or_more, rule(string_or_bytes))
|
||||
DEF_RULE(string_or_bytes, nc, or(2), tok(STRING), tok(BYTES))
|
||||
DEF_RULE(atom_paren, c(atom_paren), and(3), tok(DEL_PAREN_OPEN), opt_rule(atom_2b), tok(DEL_PAREN_CLOSE))
|
||||
|
|
22
py/lexer.c
22
py/lexer.c
|
@ -104,6 +104,10 @@ STATIC bool is_following_digit(mp_lexer_t *lex) {
|
|||
return unichar_isdigit(lex->chr1);
|
||||
}
|
||||
|
||||
STATIC bool is_following_letter(mp_lexer_t *lex) {
|
||||
return unichar_isalpha(lex->chr1);
|
||||
}
|
||||
|
||||
STATIC bool is_following_odigit(mp_lexer_t *lex) {
|
||||
return lex->chr1 >= '0' && lex->chr1 <= '7';
|
||||
}
|
||||
|
@ -540,7 +544,15 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, bool first_token) {
|
|||
}
|
||||
|
||||
} else if (is_digit(lex) || (is_char(lex, '.') && is_following_digit(lex))) {
|
||||
lex->tok_kind = MP_TOKEN_NUMBER;
|
||||
bool forced_integer = false;
|
||||
if (is_char(lex, '.')) {
|
||||
lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG;
|
||||
} else {
|
||||
lex->tok_kind = MP_TOKEN_INTEGER;
|
||||
if (is_char(lex, '0') && is_following_letter(lex)) {
|
||||
forced_integer = true;
|
||||
}
|
||||
}
|
||||
|
||||
// get first char
|
||||
vstr_add_char(&lex->vstr, CUR_CHAR(lex));
|
||||
|
@ -548,14 +560,18 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, bool first_token) {
|
|||
|
||||
// get tail chars
|
||||
while (!is_end(lex)) {
|
||||
if (is_char_or(lex, 'e', 'E')) {
|
||||
if (!forced_integer && is_char_or(lex, 'e', 'E')) {
|
||||
lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG;
|
||||
vstr_add_char(&lex->vstr, 'e');
|
||||
next_char(lex);
|
||||
if (is_char(lex, '+') || is_char(lex, '-')) {
|
||||
vstr_add_char(&lex->vstr, CUR_CHAR(lex));
|
||||
next_char(lex);
|
||||
}
|
||||
} else if (is_letter(lex) || is_digit(lex) || is_char_or(lex, '_', '.')) {
|
||||
} else if (is_letter(lex) || is_digit(lex) || is_char(lex, '.')) {
|
||||
if (is_char_or3(lex, '.', 'j', 'J')) {
|
||||
lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG;
|
||||
}
|
||||
vstr_add_char(&lex->vstr, CUR_CHAR(lex));
|
||||
next_char(lex);
|
||||
} else {
|
||||
|
|
21
py/lexer.h
21
py/lexer.h
|
@ -50,13 +50,14 @@ typedef enum _mp_token_kind_t {
|
|||
MP_TOKEN_DEDENT, // 7
|
||||
|
||||
MP_TOKEN_NAME, // 8
|
||||
MP_TOKEN_NUMBER,
|
||||
MP_TOKEN_INTEGER,
|
||||
MP_TOKEN_FLOAT_OR_IMAG,
|
||||
MP_TOKEN_STRING,
|
||||
MP_TOKEN_BYTES,
|
||||
|
||||
MP_TOKEN_ELLIPSIS,
|
||||
|
||||
MP_TOKEN_KW_FALSE, // 13
|
||||
MP_TOKEN_KW_FALSE, // 14
|
||||
MP_TOKEN_KW_NONE,
|
||||
MP_TOKEN_KW_TRUE,
|
||||
MP_TOKEN_KW_AND,
|
||||
|
@ -65,7 +66,7 @@ typedef enum _mp_token_kind_t {
|
|||
MP_TOKEN_KW_BREAK,
|
||||
MP_TOKEN_KW_CLASS,
|
||||
MP_TOKEN_KW_CONTINUE,
|
||||
MP_TOKEN_KW_DEF, // 22
|
||||
MP_TOKEN_KW_DEF, // 23
|
||||
MP_TOKEN_KW_DEL,
|
||||
MP_TOKEN_KW_ELIF,
|
||||
MP_TOKEN_KW_ELSE,
|
||||
|
@ -75,7 +76,7 @@ typedef enum _mp_token_kind_t {
|
|||
MP_TOKEN_KW_FROM,
|
||||
MP_TOKEN_KW_GLOBAL,
|
||||
MP_TOKEN_KW_IF,
|
||||
MP_TOKEN_KW_IMPORT, // 32
|
||||
MP_TOKEN_KW_IMPORT, // 33
|
||||
MP_TOKEN_KW_IN,
|
||||
MP_TOKEN_KW_IS,
|
||||
MP_TOKEN_KW_LAMBDA,
|
||||
|
@ -85,12 +86,12 @@ typedef enum _mp_token_kind_t {
|
|||
MP_TOKEN_KW_PASS,
|
||||
MP_TOKEN_KW_RAISE,
|
||||
MP_TOKEN_KW_RETURN,
|
||||
MP_TOKEN_KW_TRY, // 42
|
||||
MP_TOKEN_KW_TRY, // 43
|
||||
MP_TOKEN_KW_WHILE,
|
||||
MP_TOKEN_KW_WITH,
|
||||
MP_TOKEN_KW_YIELD,
|
||||
|
||||
MP_TOKEN_OP_PLUS, // 46
|
||||
MP_TOKEN_OP_PLUS, // 47
|
||||
MP_TOKEN_OP_MINUS,
|
||||
MP_TOKEN_OP_STAR,
|
||||
MP_TOKEN_OP_DBL_STAR,
|
||||
|
@ -100,7 +101,7 @@ typedef enum _mp_token_kind_t {
|
|||
MP_TOKEN_OP_LESS,
|
||||
MP_TOKEN_OP_DBL_LESS,
|
||||
MP_TOKEN_OP_MORE,
|
||||
MP_TOKEN_OP_DBL_MORE, // 56
|
||||
MP_TOKEN_OP_DBL_MORE, // 57
|
||||
MP_TOKEN_OP_AMPERSAND,
|
||||
MP_TOKEN_OP_PIPE,
|
||||
MP_TOKEN_OP_CARET,
|
||||
|
@ -110,7 +111,7 @@ typedef enum _mp_token_kind_t {
|
|||
MP_TOKEN_OP_DBL_EQUAL,
|
||||
MP_TOKEN_OP_NOT_EQUAL,
|
||||
|
||||
MP_TOKEN_DEL_PAREN_OPEN, // 65
|
||||
MP_TOKEN_DEL_PAREN_OPEN, // 66
|
||||
MP_TOKEN_DEL_PAREN_CLOSE,
|
||||
MP_TOKEN_DEL_BRACKET_OPEN,
|
||||
MP_TOKEN_DEL_BRACKET_CLOSE,
|
||||
|
@ -120,7 +121,7 @@ typedef enum _mp_token_kind_t {
|
|||
MP_TOKEN_DEL_COLON,
|
||||
MP_TOKEN_DEL_PERIOD,
|
||||
MP_TOKEN_DEL_SEMICOLON,
|
||||
MP_TOKEN_DEL_AT, // 75
|
||||
MP_TOKEN_DEL_AT, // 76
|
||||
MP_TOKEN_DEL_EQUAL,
|
||||
MP_TOKEN_DEL_PLUS_EQUAL,
|
||||
MP_TOKEN_DEL_MINUS_EQUAL,
|
||||
|
@ -130,7 +131,7 @@ typedef enum _mp_token_kind_t {
|
|||
MP_TOKEN_DEL_PERCENT_EQUAL,
|
||||
MP_TOKEN_DEL_AMPERSAND_EQUAL,
|
||||
MP_TOKEN_DEL_PIPE_EQUAL,
|
||||
MP_TOKEN_DEL_CARET_EQUAL, // 85
|
||||
MP_TOKEN_DEL_CARET_EQUAL, // 86
|
||||
MP_TOKEN_DEL_DBL_MORE_EQUAL,
|
||||
MP_TOKEN_DEL_DBL_LESS_EQUAL,
|
||||
MP_TOKEN_DEL_DBL_STAR_EQUAL,
|
||||
|
|
|
@ -76,7 +76,7 @@ STATIC mp_uint_t get_fmt_num(const char **p) {
|
|||
while (unichar_isdigit(*++num)) {
|
||||
len++;
|
||||
}
|
||||
mp_uint_t val = (mp_uint_t)MP_OBJ_SMALL_INT_VALUE(mp_parse_num_integer(*p, len, 10));
|
||||
mp_uint_t val = (mp_uint_t)MP_OBJ_SMALL_INT_VALUE(mp_parse_num_integer(*p, len, 10, NULL));
|
||||
*p = num;
|
||||
return val;
|
||||
}
|
||||
|
|
|
@ -91,8 +91,6 @@ void mp_native_raise(mp_obj_t o) {
|
|||
void *const mp_fun_table[MP_F_NUMBER_OF] = {
|
||||
mp_convert_obj_to_native,
|
||||
mp_convert_native_to_obj,
|
||||
mp_load_const_int,
|
||||
mp_load_const_dec,
|
||||
mp_load_const_str,
|
||||
mp_load_const_bytes,
|
||||
mp_load_name,
|
||||
|
|
|
@ -95,7 +95,7 @@ STATIC mp_obj_t complex_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n
|
|||
// a string, parse it
|
||||
mp_uint_t l;
|
||||
const char *s = mp_obj_str_get_data(args[0], &l);
|
||||
return mp_parse_num_decimal(s, l, true, true);
|
||||
return mp_parse_num_decimal(s, l, true, true, NULL);
|
||||
} else if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) {
|
||||
// a complex, just return it
|
||||
return args[0];
|
||||
|
|
|
@ -77,7 +77,7 @@ STATIC mp_obj_t float_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_k
|
|||
// a string, parse it
|
||||
mp_uint_t l;
|
||||
const char *s = mp_obj_str_get_data(args[0], &l);
|
||||
return mp_parse_num_decimal(s, l, false, false);
|
||||
return mp_parse_num_decimal(s, l, false, false, NULL);
|
||||
} else if (MP_OBJ_IS_TYPE(args[0], &mp_type_float)) {
|
||||
// a float, just return it
|
||||
return args[0];
|
||||
|
|
|
@ -57,7 +57,7 @@ STATIC mp_obj_t mp_obj_int_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_
|
|||
// a string, parse it
|
||||
mp_uint_t l;
|
||||
const char *s = mp_obj_str_get_data(args[0], &l);
|
||||
return mp_parse_num_integer(s, l, 0);
|
||||
return mp_parse_num_integer(s, l, 0, NULL);
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
} else if (MP_OBJ_IS_TYPE(args[0], &mp_type_float)) {
|
||||
return mp_obj_new_int_from_float(mp_obj_float_get(args[0]));
|
||||
|
@ -73,7 +73,7 @@ STATIC mp_obj_t mp_obj_int_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_
|
|||
// TODO proper error checking of argument types
|
||||
mp_uint_t l;
|
||||
const char *s = mp_obj_str_get_data(args[0], &l);
|
||||
return mp_parse_num_integer(s, l, mp_obj_get_int(args[1]));
|
||||
return mp_parse_num_integer(s, l, mp_obj_get_int(args[1]), NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
75
py/parse.c
75
py/parse.c
|
@ -72,6 +72,7 @@ enum {
|
|||
RULE_maximum_number_of,
|
||||
RULE_string, // special node for non-interned string
|
||||
RULE_bytes, // special node for non-interned bytes
|
||||
RULE_const_object, // special node for a constant, generic Python object
|
||||
};
|
||||
|
||||
#define ident (RULE_ACT_ALLOW_IDENT)
|
||||
|
@ -170,7 +171,7 @@ mp_parse_node_t mp_parse_node_new_leaf(mp_int_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 << 5));
|
||||
return (mp_parse_node_t)(kind | (arg << 4));
|
||||
}
|
||||
|
||||
void mp_parse_node_free(mp_parse_node_t pn) {
|
||||
|
@ -180,6 +181,8 @@ void mp_parse_node_free(mp_parse_node_t pn) {
|
|||
mp_uint_t rule_id = MP_PARSE_NODE_STRUCT_KIND(pns);
|
||||
if (rule_id == RULE_string || rule_id == RULE_bytes) {
|
||||
m_del(char, (char*)pns->nodes[0], (mp_uint_t)pns->nodes[1]);
|
||||
} else if (rule_id == RULE_const_object) {
|
||||
// don't free the const object since it's probably used by the compiled code
|
||||
} else {
|
||||
bool adjust = ADD_BLANK_NODE(rules[rule_id]);
|
||||
if (adjust) {
|
||||
|
@ -215,8 +218,6 @@ void mp_parse_node_print(mp_parse_node_t pn, mp_uint_t indent) {
|
|||
mp_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
|
||||
switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
|
||||
case MP_PARSE_NODE_ID: printf("id(%s)\n", qstr_str(arg)); break;
|
||||
case MP_PARSE_NODE_INTEGER: printf("int(%s)\n", qstr_str(arg)); break;
|
||||
case MP_PARSE_NODE_DECIMAL: printf("dec(%s)\n", qstr_str(arg)); break;
|
||||
case MP_PARSE_NODE_STRING: printf("str(%s)\n", qstr_str(arg)); break;
|
||||
case MP_PARSE_NODE_BYTES: printf("bytes(%s)\n", qstr_str(arg)); break;
|
||||
case MP_PARSE_NODE_TOKEN: printf("tok(" INT_FMT ")\n", arg); break;
|
||||
|
@ -229,6 +230,8 @@ void mp_parse_node_print(mp_parse_node_t pn, mp_uint_t indent) {
|
|||
printf("literal str(%.*s)\n", (int)pns->nodes[1], (char*)pns->nodes[0]);
|
||||
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_bytes) {
|
||||
printf("literal bytes(%.*s)\n", (int)pns->nodes[1], (char*)pns->nodes[0]);
|
||||
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_const_object) {
|
||||
printf("literal const(%p)\n", (mp_obj_t)pns->nodes[0]);
|
||||
} else {
|
||||
mp_uint_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||
#ifdef USE_RULE_NAME
|
||||
|
@ -285,11 +288,11 @@ STATIC void push_result_node(parser_t *parser, mp_parse_node_t pn) {
|
|||
parser->result_stack[parser->result_stack_top++] = pn;
|
||||
}
|
||||
|
||||
STATIC void push_result_string_bytes(parser_t *parser, mp_uint_t src_line, mp_uint_t rule_kind, const char *str, mp_uint_t len) {
|
||||
STATIC mp_parse_node_t make_node_string_bytes(parser_t *parser, mp_uint_t src_line, mp_uint_t rule_kind, const char *str, mp_uint_t len) {
|
||||
mp_parse_node_struct_t *pn = m_new_obj_var_maybe(mp_parse_node_struct_t, mp_parse_node_t, 2);
|
||||
if (pn == NULL) {
|
||||
memory_error(parser);
|
||||
return;
|
||||
return MP_PARSE_NODE_NULL;
|
||||
}
|
||||
pn->source_line = src_line;
|
||||
pn->kind_num_nodes = rule_kind | (2 << 8);
|
||||
|
@ -297,7 +300,19 @@ STATIC void push_result_string_bytes(parser_t *parser, mp_uint_t src_line, mp_ui
|
|||
memcpy(p, str, len);
|
||||
pn->nodes[0] = (mp_int_t)p;
|
||||
pn->nodes[1] = len;
|
||||
push_result_node(parser, (mp_parse_node_t)pn);
|
||||
return (mp_parse_node_t)pn;
|
||||
}
|
||||
|
||||
STATIC mp_parse_node_t make_node_const_object(parser_t *parser, mp_uint_t src_line, mp_obj_t obj) {
|
||||
mp_parse_node_struct_t *pn = m_new_obj_var_maybe(mp_parse_node_struct_t, mp_parse_node_t, 1);
|
||||
if (pn == NULL) {
|
||||
memory_error(parser);
|
||||
return MP_PARSE_NODE_NULL;
|
||||
}
|
||||
pn->source_line = src_line;
|
||||
pn->kind_num_nodes = RULE_const_object | (1 << 8);
|
||||
pn->nodes[0] = (mp_uint_t)obj;
|
||||
return (mp_parse_node_t)pn;
|
||||
}
|
||||
|
||||
STATIC void push_result_token(parser_t *parser) {
|
||||
|
@ -305,45 +320,16 @@ STATIC void push_result_token(parser_t *parser) {
|
|||
mp_lexer_t *lex = parser->lexer;
|
||||
if (lex->tok_kind == MP_TOKEN_NAME) {
|
||||
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, qstr_from_strn(lex->vstr.buf, lex->vstr.len));
|
||||
} else if (lex->tok_kind == MP_TOKEN_NUMBER) {
|
||||
bool dec = false;
|
||||
bool small_int = true;
|
||||
mp_int_t int_val = 0;
|
||||
mp_uint_t len = lex->vstr.len;
|
||||
const char *str = lex->vstr.buf;
|
||||
mp_uint_t base = 0;
|
||||
mp_uint_t i = mp_parse_num_base(str, len, &base);
|
||||
bool overflow = false;
|
||||
for (; i < len; i++) {
|
||||
mp_uint_t dig;
|
||||
int clower = str[i] | 0x20;
|
||||
if (unichar_isdigit(str[i]) && (mp_uint_t)(str[i] - '0') < base) {
|
||||
dig = str[i] - '0';
|
||||
} else if (base == 16 && 'a' <= clower && clower <= 'f') {
|
||||
dig = clower - 'a' + 10;
|
||||
} else if (str[i] == '.' || clower == 'e' || clower == 'j') {
|
||||
dec = true;
|
||||
break;
|
||||
} else {
|
||||
small_int = false;
|
||||
break;
|
||||
}
|
||||
// add next digi and check for overflow
|
||||
if (mp_small_int_mul_overflow(int_val, base)) {
|
||||
overflow = true;
|
||||
}
|
||||
int_val = int_val * base + dig;
|
||||
if (!MP_SMALL_INT_FITS(int_val)) {
|
||||
overflow = true;
|
||||
}
|
||||
}
|
||||
if (dec) {
|
||||
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_DECIMAL, qstr_from_strn(str, len));
|
||||
} else if (small_int && !overflow && MP_SMALL_INT_FITS(int_val)) {
|
||||
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, int_val);
|
||||
} 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));
|
||||
} else {
|
||||
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_INTEGER, qstr_from_strn(str, len));
|
||||
pn = make_node_const_object(parser, lex->tok_line, o);
|
||||
}
|
||||
} else if (lex->tok_kind == MP_TOKEN_FLOAT_OR_IMAG) {
|
||||
mp_obj_t o = mp_parse_num_decimal(lex->vstr.buf, lex->vstr.len, true, false, lex);
|
||||
pn = make_node_const_object(parser, lex->tok_line, o);
|
||||
} else if (lex->tok_kind == MP_TOKEN_STRING || lex->tok_kind == MP_TOKEN_BYTES) {
|
||||
// Don't automatically intern all strings/bytes. doc strings (which are usually large)
|
||||
// will be discarded by the compiler, and so we shouldn't intern them.
|
||||
|
@ -360,8 +346,7 @@ STATIC void push_result_token(parser_t *parser) {
|
|||
pn = mp_parse_node_new_leaf(lex->tok_kind == MP_TOKEN_STRING ? MP_PARSE_NODE_STRING : MP_PARSE_NODE_BYTES, qst);
|
||||
} else {
|
||||
// not interned, make a node holding a pointer to the string/bytes data
|
||||
push_result_string_bytes(parser, lex->tok_line, lex->tok_kind == MP_TOKEN_STRING ? RULE_string : RULE_bytes, lex->vstr.buf, lex->vstr.len);
|
||||
return;
|
||||
pn = make_node_string_bytes(parser, lex->tok_line, lex->tok_kind == MP_TOKEN_STRING ? RULE_string : RULE_bytes, lex->vstr.buf, lex->vstr.len);
|
||||
}
|
||||
} else {
|
||||
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, lex->tok_kind);
|
||||
|
|
28
py/parse.h
28
py/parse.h
|
@ -36,21 +36,17 @@ struct _mp_lexer_t;
|
|||
// - 0000...0000: no node
|
||||
// - xxxx...xxx1: a small integer; bits 1 and above are the signed value, 2's complement
|
||||
// - xxxx...xx00: pointer to mp_parse_node_struct_t
|
||||
// - xx...x00010: an identifier; bits 5 and above are the qstr
|
||||
// - xx...x00110: an integer; bits 5 and above are the qstr holding the value
|
||||
// - xx...x01010: a decimal; bits 5 and above are the qstr holding the value
|
||||
// - xx...x01110: a string; bits 5 and above are the qstr holding the value
|
||||
// - xx...x10010: a string of bytes; bits 5 and above are the qstr holding the value
|
||||
// - xx...x10110: a token; bits 5 and above are mp_token_kind_t
|
||||
// - xx...xx0010: an identifier; bits 4 and above are the qstr
|
||||
// - xx...xx0110: a string; bits 4 and above are the qstr holding the value
|
||||
// - xx...xx1010: a string of bytes; bits 4 and above are the qstr holding the value
|
||||
// - xx...xx1110: a token; bits 4 and above are mp_token_kind_t
|
||||
|
||||
#define MP_PARSE_NODE_NULL (0)
|
||||
#define MP_PARSE_NODE_SMALL_INT (0x1)
|
||||
#define MP_PARSE_NODE_ID (0x02)
|
||||
#define MP_PARSE_NODE_INTEGER (0x06)
|
||||
#define MP_PARSE_NODE_DECIMAL (0x0a)
|
||||
#define MP_PARSE_NODE_STRING (0x0e)
|
||||
#define MP_PARSE_NODE_BYTES (0x12)
|
||||
#define MP_PARSE_NODE_TOKEN (0x16)
|
||||
#define MP_PARSE_NODE_STRING (0x06)
|
||||
#define MP_PARSE_NODE_BYTES (0x0a)
|
||||
#define MP_PARSE_NODE_TOKEN (0x0e)
|
||||
|
||||
typedef mp_uint_t mp_parse_node_t; // must be pointer size
|
||||
|
||||
|
@ -69,12 +65,12 @@ typedef struct _mp_parse_node_struct_t {
|
|||
#define MP_PARSE_NODE_IS_STRUCT_KIND(pn, k) ((pn) != MP_PARSE_NODE_NULL && ((pn) & 3) == 0 && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)(pn)) == (k))
|
||||
|
||||
#define MP_PARSE_NODE_IS_SMALL_INT(pn) (((pn) & 0x1) == MP_PARSE_NODE_SMALL_INT)
|
||||
#define MP_PARSE_NODE_IS_ID(pn) (((pn) & 0x1f) == MP_PARSE_NODE_ID)
|
||||
#define MP_PARSE_NODE_IS_TOKEN(pn) (((pn) & 0x1f) == MP_PARSE_NODE_TOKEN)
|
||||
#define MP_PARSE_NODE_IS_TOKEN_KIND(pn, k) ((pn) == (MP_PARSE_NODE_TOKEN | ((k) << 5)))
|
||||
#define MP_PARSE_NODE_IS_ID(pn) (((pn) & 0x0f) == MP_PARSE_NODE_ID)
|
||||
#define MP_PARSE_NODE_IS_TOKEN(pn) (((pn) & 0x0f) == MP_PARSE_NODE_TOKEN)
|
||||
#define MP_PARSE_NODE_IS_TOKEN_KIND(pn, k) ((pn) == (MP_PARSE_NODE_TOKEN | ((k) << 4)))
|
||||
|
||||
#define MP_PARSE_NODE_LEAF_KIND(pn) ((pn) & 0x1f)
|
||||
#define MP_PARSE_NODE_LEAF_ARG(pn) (((mp_uint_t)(pn)) >> 5)
|
||||
#define MP_PARSE_NODE_LEAF_KIND(pn) ((pn) & 0x0f)
|
||||
#define MP_PARSE_NODE_LEAF_ARG(pn) (((mp_uint_t)(pn)) >> 4)
|
||||
#define MP_PARSE_NODE_LEAF_SMALL_INT(pn) (((mp_int_t)(pn)) >> 1)
|
||||
#define MP_PARSE_NODE_STRUCT_KIND(pns) ((pns)->kind_num_nodes & 0xff)
|
||||
#define MP_PARSE_NODE_STRUCT_NUM_NODES(pns) ((pns)->kind_num_nodes >> 8)
|
||||
|
|
|
@ -35,7 +35,16 @@
|
|||
#include <math.h>
|
||||
#endif
|
||||
|
||||
mp_obj_t mp_parse_num_integer(const char *restrict str_, mp_uint_t len, mp_uint_t base) {
|
||||
STATIC NORETURN void raise(mp_obj_t exc, mp_lexer_t *lex) {
|
||||
// if lex!=NULL then the parser called us and we need to make a SyntaxError with traceback
|
||||
if (lex != NULL) {
|
||||
((mp_obj_base_t*)exc)->type = &mp_type_SyntaxError;
|
||||
mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTR_NULL);
|
||||
}
|
||||
nlr_raise(exc);
|
||||
}
|
||||
|
||||
mp_obj_t mp_parse_num_integer(const char *restrict str_, mp_uint_t len, mp_uint_t base, mp_lexer_t *lex) {
|
||||
const byte *restrict str = (const byte *)str_;
|
||||
const byte *restrict top = str + len;
|
||||
bool neg = false;
|
||||
|
@ -43,6 +52,7 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, mp_uint_t len, mp_uint_
|
|||
|
||||
// check radix base
|
||||
if ((base != 0 && base < 2) || base > 36) {
|
||||
// this won't be reached if lex!=NULL
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "int() arg 2 must be >= 2 and <= 36"));
|
||||
}
|
||||
|
||||
|
@ -132,12 +142,15 @@ overflow:
|
|||
}
|
||||
|
||||
value_error:
|
||||
// if lex!=NULL then the parser called us and we need to make a SyntaxError with traceback
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"invalid syntax for integer"));
|
||||
mp_obj_t exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,
|
||||
"invalid syntax for integer");
|
||||
raise(exc, lex);
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"invalid syntax for integer with base %d: '%s'", base, str));
|
||||
mp_obj_t exc = mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"invalid syntax for integer with base %d: '%s'", base, str_val_start);
|
||||
raise(exc, lex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,7 +160,7 @@ typedef enum {
|
|||
PARSE_DEC_IN_EXP,
|
||||
} parse_dec_in_t;
|
||||
|
||||
mp_obj_t mp_parse_num_decimal(const char *str, mp_uint_t len, bool allow_imag, bool force_complex) {
|
||||
mp_obj_t mp_parse_num_decimal(const char *str, mp_uint_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex) {
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
const char *top = str + len;
|
||||
mp_float_t dec_val = 0;
|
||||
|
@ -168,6 +181,8 @@ mp_obj_t mp_parse_num_decimal(const char *str, mp_uint_t len, bool allow_imag, b
|
|||
}
|
||||
}
|
||||
|
||||
const char *str_val_start = str;
|
||||
|
||||
// determine what the string is
|
||||
if (str < top && (str[0] | 0x20) == 'i') {
|
||||
// string starts with 'i', should be 'inf' or 'infinity' (case insensitive)
|
||||
|
@ -191,36 +206,43 @@ mp_obj_t mp_parse_num_decimal(const char *str, mp_uint_t len, bool allow_imag, b
|
|||
// string should be a decimal number
|
||||
parse_dec_in_t in = PARSE_DEC_IN_INTG;
|
||||
bool exp_neg = false;
|
||||
mp_float_t frac_mult = 0.1;
|
||||
mp_int_t exp_val = 0;
|
||||
mp_int_t exp_extra = 0;
|
||||
for (; str < top; str++) {
|
||||
mp_uint_t dig = *str;
|
||||
while (str < top) {
|
||||
mp_uint_t dig = *str++;
|
||||
if ('0' <= dig && dig <= '9') {
|
||||
dig -= '0';
|
||||
if (in == PARSE_DEC_IN_EXP) {
|
||||
exp_val = 10 * exp_val + dig;
|
||||
} else {
|
||||
dec_val = 10 * dec_val + dig;
|
||||
if (in == PARSE_DEC_IN_FRAC) {
|
||||
exp_extra -= 1;
|
||||
dec_val += dig * frac_mult;
|
||||
frac_mult *= 0.1;
|
||||
} else {
|
||||
dec_val = 10 * dec_val + dig;
|
||||
}
|
||||
}
|
||||
} else if (in == PARSE_DEC_IN_INTG && dig == '.') {
|
||||
in = PARSE_DEC_IN_FRAC;
|
||||
} else if (in != PARSE_DEC_IN_EXP && ((dig | 0x20) == 'e')) {
|
||||
in = PARSE_DEC_IN_EXP;
|
||||
if (str[1] == '+') {
|
||||
str++;
|
||||
} else if (str[1] == '-') {
|
||||
str++;
|
||||
exp_neg = true;
|
||||
if (str < top) {
|
||||
if (str[0] == '+') {
|
||||
str++;
|
||||
} else if (str[0] == '-') {
|
||||
str++;
|
||||
exp_neg = true;
|
||||
}
|
||||
}
|
||||
if (str == top) {
|
||||
goto value_error;
|
||||
}
|
||||
} else if (allow_imag && (dig | 0x20) == 'j') {
|
||||
str++;
|
||||
imag = true;
|
||||
break;
|
||||
} else {
|
||||
// unknown character
|
||||
str--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -229,7 +251,6 @@ mp_obj_t mp_parse_num_decimal(const char *str, mp_uint_t len, bool allow_imag, b
|
|||
if (exp_neg) {
|
||||
exp_val = -exp_val;
|
||||
}
|
||||
exp_val += exp_extra;
|
||||
|
||||
// apply the exponent
|
||||
for (; exp_val > 0; exp_val--) {
|
||||
|
@ -245,13 +266,18 @@ mp_obj_t mp_parse_num_decimal(const char *str, mp_uint_t len, bool allow_imag, b
|
|||
dec_val = -dec_val;
|
||||
}
|
||||
|
||||
// check we parsed something
|
||||
if (str == str_val_start) {
|
||||
goto value_error;
|
||||
}
|
||||
|
||||
// skip trailing space
|
||||
for (; str < top && unichar_isspace(*str); str++) {
|
||||
}
|
||||
|
||||
// check we reached the end of the string
|
||||
if (str != top) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_SyntaxError, "invalid syntax for number"));
|
||||
goto value_error;
|
||||
}
|
||||
|
||||
// return the object
|
||||
|
@ -262,13 +288,16 @@ mp_obj_t mp_parse_num_decimal(const char *str, mp_uint_t len, bool allow_imag, b
|
|||
return mp_obj_new_complex(dec_val, 0);
|
||||
#else
|
||||
if (imag || force_complex) {
|
||||
mp_not_implemented("complex values not supported");
|
||||
raise(mp_obj_new_exception_msg(&mp_type_ValueError, "complex values not supported"), lex);
|
||||
#endif
|
||||
} else {
|
||||
return mp_obj_new_float(dec_val);
|
||||
}
|
||||
|
||||
value_error:
|
||||
raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid syntax for number"), lex);
|
||||
|
||||
#else
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_SyntaxError, "decimal numbers not supported"));
|
||||
raise(mp_obj_new_exception_msg(&mp_type_ValueError, "decimal numbers not supported"), lex);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -27,10 +27,13 @@
|
|||
#define __MICROPY_INCLUDED_PY_PARSENUM_H__
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#include "py/lexer.h"
|
||||
#include "py/obj.h"
|
||||
|
||||
mp_uint_t mp_parse_num_base(const char *str, mp_uint_t len, mp_uint_t *base);
|
||||
mp_obj_t mp_parse_num_integer(const char *restrict str, mp_uint_t len, mp_uint_t base);
|
||||
mp_obj_t mp_parse_num_decimal(const char *str, mp_uint_t len, bool allow_imag, bool force_complex);
|
||||
|
||||
// these functions raise a SyntaxError if lex!=NULL, else a ValueError
|
||||
mp_obj_t mp_parse_num_integer(const char *restrict str, mp_uint_t len, mp_uint_t base, mp_lexer_t *lex);
|
||||
mp_obj_t mp_parse_num_decimal(const char *str, mp_uint_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex);
|
||||
|
||||
#endif // __MICROPY_INCLUDED_PY_PARSENUM_H__
|
||||
|
|
|
@ -29,8 +29,10 @@
|
|||
// find real radix base, and strip preceding '0x', '0o' and '0b'
|
||||
// puts base in *base, and returns number of bytes to skip the prefix
|
||||
mp_uint_t mp_parse_num_base(const char *str, mp_uint_t len, mp_uint_t *base) {
|
||||
(void)len; // TODO use given len?
|
||||
const byte *p = (const byte*)str;
|
||||
if (len <= 1) {
|
||||
goto no_prefix;
|
||||
}
|
||||
unichar c = *(p++);
|
||||
if ((*base == 0 || *base == 16) && c == '0') {
|
||||
c = *(p++);
|
||||
|
@ -57,10 +59,11 @@ mp_uint_t mp_parse_num_base(const char *str, mp_uint_t len, mp_uint_t *base) {
|
|||
p -= 2;
|
||||
}
|
||||
} else {
|
||||
p--;
|
||||
no_prefix:
|
||||
if (*base == 0) {
|
||||
*base = 10;
|
||||
}
|
||||
p--;
|
||||
}
|
||||
return p - (const byte*)str;
|
||||
}
|
||||
|
|
14
py/runtime.c
14
py/runtime.c
|
@ -103,20 +103,6 @@ void mp_deinit(void) {
|
|||
#endif
|
||||
}
|
||||
|
||||
mp_obj_t mp_load_const_int(qstr qst) {
|
||||
DEBUG_OP_printf("load '%s'\n", qstr_str(qst));
|
||||
mp_uint_t len;
|
||||
const byte* data = qstr_data(qst, &len);
|
||||
return mp_parse_num_integer((const char*)data, len, 0);
|
||||
}
|
||||
|
||||
mp_obj_t mp_load_const_dec(qstr qst) {
|
||||
DEBUG_OP_printf("load '%s'\n", qstr_str(qst));
|
||||
mp_uint_t len;
|
||||
const byte* data = qstr_data(qst, &len);
|
||||
return mp_parse_num_decimal((const char*)data, len, true, false);
|
||||
}
|
||||
|
||||
mp_obj_t mp_load_const_str(qstr qst) {
|
||||
DEBUG_OP_printf("load '%s'\n", qstr_str(qst));
|
||||
return MP_OBJ_NEW_QSTR(qst);
|
||||
|
|
|
@ -107,8 +107,6 @@ typedef enum {
|
|||
typedef enum {
|
||||
MP_F_CONVERT_OBJ_TO_NATIVE = 0,
|
||||
MP_F_CONVERT_NATIVE_TO_OBJ,
|
||||
MP_F_LOAD_CONST_INT,
|
||||
MP_F_LOAD_CONST_DEC,
|
||||
MP_F_LOAD_CONST_STR,
|
||||
MP_F_LOAD_CONST_BYTES,
|
||||
MP_F_LOAD_NAME,
|
||||
|
|
10
py/showbc.c
10
py/showbc.c
|
@ -161,16 +161,6 @@ const byte *mp_bytecode_print_str(const byte *ip) {
|
|||
break;
|
||||
}
|
||||
|
||||
case MP_BC_LOAD_CONST_INT:
|
||||
DECODE_QSTR;
|
||||
printf("LOAD_CONST_INT %s", qstr_str(qst));
|
||||
break;
|
||||
|
||||
case MP_BC_LOAD_CONST_DEC:
|
||||
DECODE_QSTR;
|
||||
printf("LOAD_CONST_DEC %s", qstr_str(qst));
|
||||
break;
|
||||
|
||||
case MP_BC_LOAD_CONST_BYTES:
|
||||
DECODE_QSTR;
|
||||
printf("LOAD_CONST_BYTES %s", qstr_str(qst));
|
||||
|
|
13
py/vm.c
13
py/vm.c
|
@ -199,19 +199,6 @@ dispatch_loop:
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
ENTRY(MP_BC_LOAD_CONST_INT): {
|
||||
DECODE_QSTR;
|
||||
PUSH(mp_load_const_int(qst));
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
ENTRY(MP_BC_LOAD_CONST_DEC): {
|
||||
MARK_EXC_IP_SELECTIVE();
|
||||
DECODE_QSTR;
|
||||
PUSH(mp_load_const_dec(qst));
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
ENTRY(MP_BC_LOAD_CONST_BYTES): {
|
||||
DECODE_QSTR;
|
||||
PUSH(mp_load_const_bytes(qst));
|
||||
|
|
|
@ -36,8 +36,6 @@ static void* entry_table[256] = {
|
|||
[MP_BC_LOAD_CONST_TRUE] = &&entry_MP_BC_LOAD_CONST_TRUE,
|
||||
[MP_BC_LOAD_CONST_ELLIPSIS] = &&entry_MP_BC_LOAD_CONST_ELLIPSIS,
|
||||
[MP_BC_LOAD_CONST_SMALL_INT] = &&entry_MP_BC_LOAD_CONST_SMALL_INT,
|
||||
[MP_BC_LOAD_CONST_INT] = &&entry_MP_BC_LOAD_CONST_INT,
|
||||
[MP_BC_LOAD_CONST_DEC] = &&entry_MP_BC_LOAD_CONST_DEC,
|
||||
[MP_BC_LOAD_CONST_BYTES] = &&entry_MP_BC_LOAD_CONST_BYTES,
|
||||
[MP_BC_LOAD_CONST_STRING] = &&entry_MP_BC_LOAD_CONST_STRING,
|
||||
[MP_BC_LOAD_CONST_OBJ] = &&entry_MP_BC_LOAD_CONST_OBJ,
|
||||
|
|
|
@ -78,3 +78,6 @@ test('0b2', 2)
|
|||
test('0o8', 8)
|
||||
test('0xg', 16)
|
||||
test('1 1', 16)
|
||||
|
||||
# check that we don't parse this as a floating point number
|
||||
print(0x1e+1)
|
||||
|
|
|
@ -55,3 +55,7 @@ for i in range(8):
|
|||
print(-10000000000000000000000002 >> i)
|
||||
print(-10000000000000000000000003 >> i)
|
||||
print(-10000000000000000000000004 >> i)
|
||||
|
||||
# test constant integer with more than 255 chars
|
||||
x = 0x84ce72aa8699df436059f052ac51b6398d2511e49631bcb7e71f89c499b9ee425dfbc13a5f6d408471b054f2655617cbbaf7937b7c80cd8865cf02c8487d30d2b0fbd8b2c4e102e16d828374bbc47b93852f212d5043c3ea720f086178ff798cc4f63f787b9c2e419efa033e7644ea7936f54462dc21a6c4580725f7f0e7d1aaaaaaa
|
||||
print(x)
|
||||
|
|
|
@ -12,7 +12,7 @@ print("%.5g" % e)
|
|||
print("%.5g" % pi)
|
||||
|
||||
test_values_non_zero = []
|
||||
base_values = (0.0, 0.5, 1.23456, 10.)
|
||||
base_values = (0.0, 0.5, 1.2345, 10.)
|
||||
for r in base_values:
|
||||
for i in base_values:
|
||||
if r != 0. or i != 0.:
|
||||
|
|
|
@ -14,3 +14,7 @@ try:
|
|||
1.0 // 0
|
||||
except ZeroDivisionError:
|
||||
print("ZeroDivisionError")
|
||||
|
||||
# test constant float with more than 255 chars
|
||||
x = 1.84728699436059052516398251149631771898472869943605905251639825114963177189847286994360590525163982511496317718984728699436059052516398251149631771898472869943605905251639825114963177189847286994360590525163982511496317718984728699436059052516398251149631771898472869943605905251639825114963177189
|
||||
print("%.5f" % x)
|
||||
|
|
Loading…
Reference in New Issue