diff --git a/extmod/modujson.c b/extmod/modujson.c index d1d103237..b5384bbc4 100644 --- a/extmod/modujson.c +++ b/extmod/modujson.c @@ -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; } diff --git a/py/bc0.h b/py/bc0.h index f1c7baac4..c4b0d1d6a 100644 --- a/py/bc0.h +++ b/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 diff --git a/py/compile.c b/py/compile.c index 7023e9c40..b82fea732 100644 --- a/py/compile.c +++ b/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: diff --git a/py/emit.h b/py/emit.h index 772ee0473..5bfeaacb1 100644 --- a/py/emit.h +++ b/py/emit.h @@ -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); diff --git a/py/emitbc.c b/py/emitbc.c index f7f2b8d19..53cae59ee 100644 --- a/py/emitbc.c +++ b/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, diff --git a/py/emitcpy.c b/py/emitcpy.c index 09a0e006f..355ed1051 100644 --- a/py/emitcpy.c +++ b/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, diff --git a/py/emitnative.c b/py/emitnative.c index b1135f96d..ca6dd186e 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -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, diff --git a/py/emitpass1.c b/py/emitpass1.c index c6d92783a..b5e5f8e7a 100644 --- a/py/emitpass1.c +++ b/py/emitpass1.c @@ -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, diff --git a/py/grammar.h b/py/grammar.h index eb2f03c66..3698abc15 100644 --- a/py/grammar.h +++ b/py/grammar.h @@ -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)) diff --git a/py/lexer.c b/py/lexer.c index e3d52e714..e77851020 100644 --- a/py/lexer.c +++ b/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 { diff --git a/py/lexer.h b/py/lexer.h index 3ec6b6d74..3118df62c 100644 --- a/py/lexer.h +++ b/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, diff --git a/py/modstruct.c b/py/modstruct.c index 681c58577..1103e40a5 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -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; } diff --git a/py/nativeglue.c b/py/nativeglue.c index 43e7d699f..14638d4ef 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -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, diff --git a/py/objcomplex.c b/py/objcomplex.c index 6a403f626..141506843 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -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]; diff --git a/py/objfloat.c b/py/objfloat.c index 4323cec54..2e8b7f74e 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -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]; diff --git a/py/objint.c b/py/objint.c index fd0b2be55..4a4a21aaf 100644 --- a/py/objint.c +++ b/py/objint.c @@ -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); } } } diff --git a/py/parse.c b/py/parse.c index 569cf257a..54e199e59 100644 --- a/py/parse.c +++ b/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); diff --git a/py/parse.h b/py/parse.h index ee0025a7b..5d992a6b9 100644 --- a/py/parse.h +++ b/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) diff --git a/py/parsenum.c b/py/parsenum.c index 4706fef81..ffd065df4 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -35,7 +35,16 @@ #include #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 } diff --git a/py/parsenum.h b/py/parsenum.h index a769bdd83..26aac49bc 100644 --- a/py/parsenum.h +++ b/py/parsenum.h @@ -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__ diff --git a/py/parsenumbase.c b/py/parsenumbase.c index cb524057f..31e4a9164 100644 --- a/py/parsenumbase.c +++ b/py/parsenumbase.c @@ -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; } diff --git a/py/runtime.c b/py/runtime.c index 080d061cd..75dd46750 100644 --- a/py/runtime.c +++ b/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); diff --git a/py/runtime0.h b/py/runtime0.h index dc4a526d1..b96e9c384 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -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, diff --git a/py/showbc.c b/py/showbc.c index 1bdb96aaa..adfa7544f 100644 --- a/py/showbc.c +++ b/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)); diff --git a/py/vm.c b/py/vm.c index 2dcc5378b..587948f73 100644 --- a/py/vm.c +++ b/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)); diff --git a/py/vmentrytable.h b/py/vmentrytable.h index 7173c2df0..d2a6abee3 100644 --- a/py/vmentrytable.h +++ b/py/vmentrytable.h @@ -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, diff --git a/tests/basics/int1.py b/tests/basics/int1.py index 89d4fd9d4..fd9902f93 100644 --- a/tests/basics/int1.py +++ b/tests/basics/int1.py @@ -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) diff --git a/tests/basics/int_mpz.py b/tests/basics/int_mpz.py index 0500d794c..ee172edff 100644 --- a/tests/basics/int_mpz.py +++ b/tests/basics/int_mpz.py @@ -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) diff --git a/tests/float/cmath_fun.py b/tests/float/cmath_fun.py index e13271372..dfb6c56bd 100644 --- a/tests/float/cmath_fun.py +++ b/tests/float/cmath_fun.py @@ -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.: diff --git a/tests/float/float1.py b/tests/float/float1.py index bf1305c3d..5971e6d0a 100644 --- a/tests/float/float1.py +++ b/tests/float/float1.py @@ -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)