diff --git a/py/bc0.h b/py/bc0.h index 773e23d2ea..0a4a49ce66 100644 --- a/py/bc0.h +++ b/py/bc0.h @@ -1,12 +1,16 @@ +// Micro Python byte-codes. +// The comment at the end of the line (if it exists) tells the arguments to the byte-code. + #define MP_BC_LOAD_CONST_FALSE (0x10) #define MP_BC_LOAD_CONST_NONE (0x11) #define MP_BC_LOAD_CONST_TRUE (0x12) -#define MP_BC_LOAD_CONST_SMALL_INT (0x13) // 24-bit, in excess -#define MP_BC_LOAD_CONST_INT (0x14) // qstr -#define MP_BC_LOAD_CONST_DEC (0x15) // qstr -#define MP_BC_LOAD_CONST_ID (0x16) // qstr -#define MP_BC_LOAD_CONST_BYTES (0x17) // qstr -#define MP_BC_LOAD_CONST_STRING (0x18) // qstr +#define MP_BC_LOAD_CONST_ELLIPSIS (0x13) +#define MP_BC_LOAD_CONST_SMALL_INT (0x14) // 24-bit, in excess +#define MP_BC_LOAD_CONST_INT (0x15) // qstr +#define MP_BC_LOAD_CONST_DEC (0x16) // qstr +#define MP_BC_LOAD_CONST_ID (0x17) // qstr +#define MP_BC_LOAD_CONST_BYTES (0x18) // qstr +#define MP_BC_LOAD_CONST_STRING (0x19) // qstr #define MP_BC_LOAD_FAST_0 (0x20) #define MP_BC_LOAD_FAST_1 (0x21) diff --git a/py/emitbc.c b/py/emitbc.c index dc1988582c..c0ec2469a6 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -249,6 +249,7 @@ static void emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) { case MP_TOKEN_KW_FALSE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_FALSE); break; case MP_TOKEN_KW_NONE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_NONE); break; case MP_TOKEN_KW_TRUE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_TRUE); break; + case MP_TOKEN_ELLIPSIS: emit_write_byte_1(emit, MP_BC_LOAD_CONST_ELLIPSIS); break; default: assert(0); } } diff --git a/py/grammar.h b/py/grammar.h index b1faab79e1..4d53bd3fc4 100644 --- a/py/grammar.h +++ b/py/grammar.h @@ -113,11 +113,11 @@ DEF_RULE(import_stmt, nc, or(2), rule(import_name), rule(import_from)) DEF_RULE(import_name, c(import_name), and(2), tok(KW_IMPORT), rule(dotted_as_names)) DEF_RULE(import_from, c(import_from), and(4), tok(KW_FROM), rule(import_from_2), tok(KW_IMPORT), rule(import_from_3)) DEF_RULE(import_from_2, nc, or(2), rule(dotted_name), rule(import_from_2b)) -DEF_RULE(import_from_2b, nc, and(2), rule(one_or_more_period_or_ellipses), opt_rule(dotted_name)) +DEF_RULE(import_from_2b, nc, and(2), rule(one_or_more_period_or_ellipsis), opt_rule(dotted_name)) DEF_RULE(import_from_3, nc, or(3), tok(OP_STAR), rule(import_as_names_paren), rule(import_as_names)) DEF_RULE(import_as_names_paren, nc, and(3), tok(DEL_PAREN_OPEN), rule(import_as_names), tok(DEL_PAREN_CLOSE)) -DEF_RULE(one_or_more_period_or_ellipses, nc, one_or_more, rule(period_or_ellipses)) -DEF_RULE(period_or_ellipses, nc, or(2), tok(DEL_PERIOD), tok(ELLIPSES)) +DEF_RULE(one_or_more_period_or_ellipsis, nc, one_or_more, rule(period_or_ellipsis)) +DEF_RULE(period_or_ellipsis, nc, or(2), tok(DEL_PERIOD), tok(ELLIPSIS)) DEF_RULE(import_as_name, nc, and(2), tok(NAME), opt_rule(as_name)) DEF_RULE(dotted_as_name, nc, and(2), rule(dotted_name), opt_rule(as_name)) DEF_RULE(as_name, nc, and(2), tok(KW_AS), tok(NAME)) @@ -220,7 +220,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(ELLIPSES), tok(KW_NONE), tok(KW_TRUE), tok(KW_FALSE), rule(atom_paren), rule(atom_bracket), rule(atom_brace)) +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_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 4df91b0365..d4205236c3 100644 --- a/py/lexer.c +++ b/py/lexer.c @@ -239,7 +239,7 @@ static const uint8_t tok_enc_kind[] = { MP_TOKEN_OP_CARET, MP_TOKEN_DEL_CARET_EQUAL, MP_TOKEN_DEL_EQUAL, MP_TOKEN_OP_DBL_EQUAL, MP_TOKEN_OP_NOT_EQUAL, - MP_TOKEN_DEL_PERIOD, MP_TOKEN_ELLIPSES, + MP_TOKEN_DEL_PERIOD, MP_TOKEN_ELLIPSIS, }; // must have the same order as enum in lexer.h diff --git a/py/lexer.h b/py/lexer.h index 27244fde96..3cb48ce9e1 100644 --- a/py/lexer.h +++ b/py/lexer.h @@ -20,7 +20,7 @@ typedef enum _mp_token_kind_t { MP_TOKEN_STRING, MP_TOKEN_BYTES, - MP_TOKEN_ELLIPSES, + MP_TOKEN_ELLIPSIS, MP_TOKEN_KW_FALSE, // 12 MP_TOKEN_KW_NONE, diff --git a/py/mpqstrraw.h b/py/mpqstrraw.h index 85cf1ff7bd..e73bd828eb 100644 --- a/py/mpqstrraw.h +++ b/py/mpqstrraw.h @@ -20,6 +20,7 @@ Q(native) Q(viper) Q(asm_thumb) +Q(Ellipsis) Q(StopIteration) Q(AttributeError) diff --git a/py/obj.h b/py/obj.h index 16c7c36dd1..f0ba6999e9 100644 --- a/py/obj.h +++ b/py/obj.h @@ -110,6 +110,7 @@ extern const mp_obj_type_t mp_const_type; extern const mp_obj_t mp_const_none; extern const mp_obj_t mp_const_false; extern const mp_obj_t mp_const_true; +extern const mp_obj_t mp_const_ellipsis; extern const mp_obj_t mp_const_stop_iteration; // special object indicating end of iteration (not StopIteration exception!) // Need to declare this here so we are not dependent on map.h diff --git a/py/objslice.c b/py/objslice.c index 03607e4c3e..d99325fd73 100644 --- a/py/objslice.c +++ b/py/objslice.c @@ -9,6 +9,35 @@ #include "obj.h" #include "runtime0.h" +/******************************************************************************/ +/* ellipsis object, a singleton */ + +typedef struct _mp_obj_ellipsis_t { + mp_obj_base_t base; +} mp_obj_ellipsis_t; + +void ellipsis_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { + print(env, "Ellipsis"); +} + +const mp_obj_type_t ellipsis_type = { + { &mp_const_type }, + "ellipsis", + ellipsis_print, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + {{NULL, NULL},}, // method list +}; + +static const mp_obj_ellipsis_t ellipsis_obj = {{&ellipsis_type}}; +const mp_obj_t mp_const_ellipsis = (mp_obj_t)&ellipsis_obj; + +/******************************************************************************/ +/* slice object */ + #if MICROPY_ENABLE_SLICE // TODO: This implements only variant of slice with 2 integer args only. diff --git a/py/runtime.c b/py/runtime.c index a1f9ee3b7b..72881067d4 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -84,6 +84,9 @@ void rt_init(void) { mp_qstr_map_lookup(&map_builtins, MP_QSTR_SyntaxError, true)->value = mp_obj_new_exception(MP_QSTR_SyntaxError); mp_qstr_map_lookup(&map_builtins, MP_QSTR_ValueError, true)->value = mp_obj_new_exception(MP_QSTR_ValueError); + // built-in objects + mp_qstr_map_lookup(&map_builtins, MP_QSTR_Ellipsis, true)->value = mp_const_ellipsis; + // built-in core functions mp_qstr_map_lookup(&map_builtins, MP_QSTR___build_class__, true)->value = rt_make_function_2(mp_builtin___build_class__); mp_qstr_map_lookup(&map_builtins, MP_QSTR___repl_print__, true)->value = rt_make_function_1(mp_builtin___repl_print__); diff --git a/py/showbc.c b/py/showbc.c index a3bfa2833b..eb7d41b24d 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -46,6 +46,10 @@ void mp_show_byte_code(const byte *ip, int len) { printf("LOAD_CONST_TRUE"); break; + case MP_BC_LOAD_CONST_ELLIPSIS: + printf("LOAD_CONST_ELLIPSIS"); + break; + case MP_BC_LOAD_CONST_SMALL_INT: unum = (ip[0] | (ip[1] << 8) | (ip[2] << 16)) - 0x800000; ip += 3; diff --git a/py/vm.c b/py/vm.c index 382780640b..8e7ef7485b 100644 --- a/py/vm.c +++ b/py/vm.c @@ -99,6 +99,10 @@ bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t ** PUSH(mp_const_true); break; + case MP_BC_LOAD_CONST_ELLIPSIS: + PUSH(mp_const_ellipsis); + break; + case MP_BC_LOAD_CONST_SMALL_INT: unum = (ip[0] | (ip[1] << 8) | (ip[2] << 16)) - 0x800000; ip += 3;