From e9906ac3d771a312b05d76e42aee8e806dd0d128 Mon Sep 17 00:00:00 2001
From: Damien George <damien.p.george@gmail.com>
Date: Sat, 4 Jan 2014 18:44:46 +0000
Subject: [PATCH] Add ellipsis object.

---
 py/bc0.h       | 16 ++++++++++------
 py/emitbc.c    |  1 +
 py/grammar.h   |  8 ++++----
 py/lexer.c     |  2 +-
 py/lexer.h     |  2 +-
 py/mpqstrraw.h |  1 +
 py/obj.h       |  1 +
 py/objslice.c  | 29 +++++++++++++++++++++++++++++
 py/runtime.c   |  3 +++
 py/showbc.c    |  4 ++++
 py/vm.c        |  4 ++++
 11 files changed, 59 insertions(+), 12 deletions(-)

diff --git a/py/bc0.h b/py/bc0.h
index 773e23d2e..0a4a49ce6 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 dc1988582..c0ec2469a 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 b1faab79e..4d53bd3fc 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 4df91b036..d4205236c 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 27244fde9..3cb48ce9e 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 85cf1ff7b..e73bd828e 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 16c7c36dd..f0ba6999e 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 03607e4c3..d99325fd7 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 a1f9ee3b7..72881067d 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 a3bfa2833..eb7d41b24 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 382780640..8e7ef7485 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;
-- 
GitLab