blueloveTH 3 년 전
부모
커밋
faad1d7067
5개의 변경된 파일28개의 추가작업 그리고 6개의 파일을 삭제
  1. 18 4
      src/compiler.h
  2. 1 0
      src/opcodes.h
  3. 1 1
      src/parser.h
  4. 4 0
      src/pocketpy.h
  5. 4 1
      src/vm.h

+ 18 - 4
src/compiler.h

@@ -81,6 +81,7 @@ public:
         rules[TK("False")] =    { METHOD(exprValue),     NO_INFIX };
         rules[TK("lambda")] =   { METHOD(exprLambda),    NO_INFIX };
         rules[TK("None")] =     { METHOD(exprValue),     NO_INFIX };
+        rules[TK("...")] =      { METHOD(exprValue),     NO_INFIX };
         rules[TK("@id")] =      { METHOD(exprName),      NO_INFIX };
         rules[TK("@num")] =     { METHOD(exprLiteral),   NO_INFIX };
         rules[TK("@str")] =     { METHOD(exprLiteral),   NO_INFIX };
@@ -190,10 +191,21 @@ public:
                 case '[': parser->setNextToken(TK("[")); return;
                 case ']': parser->setNextToken(TK("]")); return;
                 case '%': parser->setNextToken(TK("%")); return;
-                case '.': parser->setNextToken(TK(".")); return;
                 case '&': parser->setNextToken(TK("&")); return;
                 case '|': parser->setNextToken(TK("|")); return;
                 case '^': parser->setNextToken(TK("^")); return;
+                case '.': {
+                    if(parser->matchChar('.')) {
+                        if(parser->matchChar('.')) {
+                            parser->setNextToken(TK("..."));
+                        } else {
+                            syntaxError("invalid token '..'");
+                        }
+                    } else {
+                        parser->setNextToken(TK("."));
+                    }
+                    return;
+                }
                 case '=': parser->setNextTwoCharToken('=', TK("="), TK("==")); return;
                 case '+': parser->setNextTwoCharToken('=', TK("+"), TK("+=")); return;
                 case '>': {
@@ -575,9 +587,10 @@ __LISTCOMP:
     void exprValue() {
         _TokenType op = parser->previous.type;
         switch (op) {
-            case TK("None"):  emitCode(OP_LOAD_NONE);  break;
-            case TK("True"):  emitCode(OP_LOAD_TRUE);  break;
-            case TK("False"): emitCode(OP_LOAD_FALSE); break;
+            case TK("None"):    emitCode(OP_LOAD_NONE);  break;
+            case TK("True"):    emitCode(OP_LOAD_TRUE);  break;
+            case TK("False"):   emitCode(OP_LOAD_FALSE); break;
+            case TK("..."):     emitCode(OP_LOAD_ELLIPSIS); break;
             default: UNREACHABLE();
         }
     }
@@ -876,6 +889,7 @@ __LISTCOMP:
         if(match(TK("True"))) return vm->PyBool(true);
         if(match(TK("False"))) return vm->PyBool(false);
         if(match(TK("None"))) return vm->None;
+        if(match(TK("..."))) return vm->Ellipsis;
         syntaxError(_Str("expect a literal, not ") + TK_STR(parser->current.type));
         return nullptr;
     }

+ 1 - 0
src/opcodes.h

@@ -40,6 +40,7 @@ OPCODE(LOAD_TRUE)
 OPCODE(LOAD_FALSE)
 OPCODE(LOAD_EVAL_FN)        // load eval() callable into stack
 OPCODE(LOAD_LAMBDA)         // LOAD_CONST + set __module__ attr
+OPCODE(LOAD_ELLIPSIS)
 
 OPCODE(ASSERT)
 OPCODE(RAISE_ERROR)

+ 1 - 1
src/parser.h

@@ -7,7 +7,7 @@ typedef uint8_t _TokenType;
 constexpr const char* __TOKENS[] = {
     "@error", "@eof", "@eol", "@sof",
     ".", ",", ":", ";", "#", "(", ")", "[", "]", "{", "}", "%",
-    "+", "-", "*", "/", "//", "**", "=", ">", "<",
+    "+", "-", "*", "/", "//", "**", "=", ">", "<", "...",
     "<<", ">>", "&", "|", "^",
     "==", "!=", ">=", "<=",
     "+=", "-=", "*=", "/=", "//=",

+ 4 - 0
src/pocketpy.h

@@ -544,6 +544,10 @@ void __initializeBuiltinFunctions(VM* _vm) {
         bool _obj = vm->PyBool_AS_C(args[1]);
         return vm->PyBool(_self ^ _obj);
     });
+
+    _vm->bindMethod("ellipsis", "__repr__", [](VM* vm, const pkpy::ArgList& args) {
+        return vm->PyStr("Ellipsis");
+    });
 }
 
 #include "builtins.h"

+ 4 - 1
src/vm.h

@@ -212,6 +212,7 @@ private:
             case OP_LOAD_NONE: frame->push(None); break;
             case OP_LOAD_TRUE: frame->push(True); break;
             case OP_LOAD_FALSE: frame->push(False); break;
+            case OP_LOAD_ELLIPSIS: frame->push(Ellipsis); break;
             case OP_ASSERT:
                 {
                     PyVar expr = frame->popValue(this);
@@ -326,7 +327,7 @@ private:
 
 public:
     PyVarDict _types;
-    PyVar None, True, False;
+    PyVar None, True, False, Ellipsis;
 
     bool use_stdio;
     std::ostream* _stdout;
@@ -698,6 +699,7 @@ public:
         _tp_pointer = newClassType("_pointer");
 
         newClassType("NoneType");
+        newClassType("ellipsis");
         
         _tp_function = newClassType("function");
         _tp_native_function = newClassType("_native_function");
@@ -705,6 +707,7 @@ public:
         _tp_bounded_method = newClassType("_bounded_method");
 
         this->None = newObject(_types["NoneType"], (_Int)0);
+        this->Ellipsis = newObject(_types["ellipsis"], (_Int)0);
         this->True = newObject(_tp_bool, true);
         this->False = newObject(_tp_bool, false);
         this->builtins = newModule("builtins");