From faad1d70679097784d77043eabad77f640994e87 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 20 Nov 2022 18:41:57 +0800 Subject: [PATCH] add ... --- src/compiler.h | 22 ++++++++++++++++++---- src/opcodes.h | 1 + src/parser.h | 2 +- src/pocketpy.h | 4 ++++ src/vm.h | 5 ++++- 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/compiler.h b/src/compiler.h index cc3b8402..03b6665f 100644 --- a/src/compiler.h +++ b/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; } diff --git a/src/opcodes.h b/src/opcodes.h index b7cf01d5..30754267 100644 --- a/src/opcodes.h +++ b/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) diff --git a/src/parser.h b/src/parser.h index 5b09be0d..b5b528a8 100644 --- a/src/parser.h +++ b/src/parser.h @@ -7,7 +7,7 @@ typedef uint8_t _TokenType; constexpr const char* __TOKENS[] = { "@error", "@eof", "@eol", "@sof", ".", ",", ":", ";", "#", "(", ")", "[", "]", "{", "}", "%", - "+", "-", "*", "/", "//", "**", "=", ">", "<", + "+", "-", "*", "/", "//", "**", "=", ">", "<", "...", "<<", ">>", "&", "|", "^", "==", "!=", ">=", "<=", "+=", "-=", "*=", "/=", "//=", diff --git a/src/pocketpy.h b/src/pocketpy.h index 29f84e3d..193773d0 100644 --- a/src/pocketpy.h +++ b/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" diff --git a/src/vm.h b/src/vm.h index 47ce6155..1d282469 100644 --- a/src/vm.h +++ b/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");