Просмотр исходного кода

move str.join | add partial support of tuple

blueloveTH 3 лет назад
Родитель
Сommit
a4dc943c7b
5 измененных файлов с 78 добавлено и 60 удалено
  1. 12 14
      src/builtins.h
  2. 51 40
      src/compiler.h
  3. 1 1
      src/main.cpp
  4. 3 5
      src/parser.h
  5. 11 0
      src/pocketpy.h

+ 12 - 14
src/builtins.h

@@ -4,20 +4,11 @@ const char* __BUILTINS_CODE = R"(
 def len(x):
     return x.__len__()
 
-def __str4join(self, seq):
-    s = ""
-    for i in seq:
-        s += str(i) + self  # in Python3, it uses 'i' instead of 'str(i)'
-    if len(self) > 0:
-        s = s[:-len(self)]
-    return s
-str.join = __str4join
-
 def __str4__mul__(self, n):
-    s = ""
+    a = []
     for i in range(n):
-        s += self
-    return s
+        a.append(self)
+    return ''.join(a)
 str.__mul__ = __str4__mul__
 
 def __str4split(self, sep):
@@ -40,9 +31,16 @@ def __list4__str__(self):
     a = []
     for i in self:
         a.append(str(i))
-    return "[" + ", ".join(a) + "]"
+    return '[' + ', '.join(a) + ']'
 list.__str__ = __list4__str__
 
+def __tuple4__str__(self):
+    a = []
+    for i in self:
+        a.append(str(i))
+    return '(' + ', '.join(a) + ')'
+tuple.__str__ = __tuple4__str__
+
 def __list4extend(self, other):
     for i in other:
         self.append(i)
@@ -91,7 +89,7 @@ class dict:
             if self._a[i][0] == key:
                 return [True, i]
             i = ((5*i) + 1) % self._capacity
-        return [False, i]
+        return False,i
 
     def __getitem__(self, key):
         ret = self.__probe(key)

+ 51 - 40
src/compiler.h

@@ -72,39 +72,39 @@ public:
 
 // http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
 #define METHOD(name) &Compiler::name
-#define NO_INFIX PREC_NONE
-        for(_TokenType i=0; i<__TOKENS_LEN; i++) rules[i] = { nullptr, nullptr, PREC_NONE };
-        rules[TK(".")] = { nullptr,               METHOD(exprAttrib),         PREC_ATTRIB };
-        rules[TK("(")] = { METHOD(exprGrouping),  METHOD(exprCall),           PREC_CALL };
-        rules[TK("[")] = { METHOD(exprList),      METHOD(exprSubscript),      PREC_SUBSCRIPT };
-        rules[TK("{")] = { METHOD(exprMap),       nullptr,                    NO_INFIX };
-        rules[TK("%")] = { nullptr,               METHOD(exprBinaryOp),       PREC_FACTOR };
-        rules[TK("+")] = { nullptr,               METHOD(exprBinaryOp),       PREC_TERM };
-        rules[TK("-")] = { METHOD(exprUnaryOp),   METHOD(exprBinaryOp),       PREC_TERM };
-        rules[TK("*")] = { nullptr,               METHOD(exprBinaryOp),       PREC_FACTOR };
-        rules[TK("/")] = { nullptr,               METHOD(exprBinaryOp),       PREC_FACTOR };
-        rules[TK("//")] = { nullptr,               METHOD(exprBinaryOp),       PREC_FACTOR };
-        rules[TK("**")] = { nullptr,               METHOD(exprBinaryOp),       PREC_EXPONENT };
-        rules[TK(">")] = { nullptr,               METHOD(exprBinaryOp),       PREC_COMPARISION };
-        rules[TK("<")] = { nullptr,               METHOD(exprBinaryOp),       PREC_COMPARISION };
-        rules[TK("==")] = { nullptr,               METHOD(exprBinaryOp),       PREC_EQUALITY };
-        rules[TK("!=")] = { nullptr,               METHOD(exprBinaryOp),       PREC_EQUALITY };
-        rules[TK(">=")] = { nullptr,               METHOD(exprBinaryOp),       PREC_COMPARISION };
-        rules[TK("<=")] = { nullptr,               METHOD(exprBinaryOp),       PREC_COMPARISION };
-        rules[TK("lambda")] = { METHOD(exprLambda),    nullptr,                    NO_INFIX };
-        rules[TK("None")] = { METHOD(exprValue),     nullptr,                    NO_INFIX };
-        rules[TK("in")] = { nullptr,               METHOD(exprBinaryOp),       PREC_TEST };
-        rules[TK("is")] = { nullptr,               METHOD(exprBinaryOp),       PREC_TEST };
-        rules[TK("not in")] = { nullptr,               METHOD(exprBinaryOp),       PREC_TEST };
-        rules[TK("is not")] = { nullptr,               METHOD(exprBinaryOp),       PREC_TEST };
-        rules[TK("and")] = { nullptr,               METHOD(exprAnd),            PREC_LOGICAL_AND };
-        rules[TK("or")] = { nullptr,               METHOD(exprOr),             PREC_LOGICAL_OR };
-        rules[TK("not")] = { METHOD(exprUnaryOp),   nullptr,                    PREC_UNARY };
-        rules[TK("True")] = { METHOD(exprValue),     nullptr,                    NO_INFIX };
-        rules[TK("False")] = { METHOD(exprValue),     nullptr,                    NO_INFIX };
-        rules[TK("@id")] = { METHOD(exprName),      nullptr,                    NO_INFIX };
-        rules[TK("@num")] = { METHOD(exprLiteral),   nullptr,                    NO_INFIX };
-        rules[TK("@str")] = { METHOD(exprLiteral),   nullptr,                    NO_INFIX };
+#define NO_INFIX nullptr, PREC_NONE
+        for(_TokenType i=0; i<__TOKENS_LEN; i++) rules[i] = { nullptr, NO_INFIX };
+        rules[TK(".")] =    { nullptr,               METHOD(exprAttrib),         PREC_ATTRIB };
+        rules[TK("(")] =    { METHOD(exprGrouping),  METHOD(exprCall),           PREC_CALL };
+        rules[TK("[")] =    { METHOD(exprList),      METHOD(exprSubscript),      PREC_SUBSCRIPT };
+        rules[TK("{")] =    { METHOD(exprMap),       NO_INFIX };
+        rules[TK("%")] =    { nullptr,               METHOD(exprBinaryOp),       PREC_FACTOR };
+        rules[TK("+")] =    { nullptr,               METHOD(exprBinaryOp),       PREC_TERM };
+        rules[TK("-")] =    { METHOD(exprUnaryOp),   METHOD(exprBinaryOp),       PREC_TERM };
+        rules[TK("*")] =    { nullptr,               METHOD(exprBinaryOp),       PREC_FACTOR };
+        rules[TK("/")] =    { nullptr,               METHOD(exprBinaryOp),       PREC_FACTOR };
+        rules[TK("//")] =   { nullptr,               METHOD(exprBinaryOp),       PREC_FACTOR };
+        rules[TK("**")] =   { nullptr,               METHOD(exprBinaryOp),       PREC_EXPONENT };
+        rules[TK(">")] =    { nullptr,               METHOD(exprBinaryOp),       PREC_COMPARISION };
+        rules[TK("<")] =    { nullptr,               METHOD(exprBinaryOp),       PREC_COMPARISION };
+        rules[TK("==")] =   { nullptr,               METHOD(exprBinaryOp),       PREC_EQUALITY };
+        rules[TK("!=")] =   { nullptr,               METHOD(exprBinaryOp),       PREC_EQUALITY };
+        rules[TK(">=")] =   { nullptr,               METHOD(exprBinaryOp),       PREC_COMPARISION };
+        rules[TK("<=")] =   { nullptr,               METHOD(exprBinaryOp),       PREC_COMPARISION };
+        rules[TK("in")] =   { nullptr,               METHOD(exprBinaryOp),       PREC_TEST };
+        rules[TK("is")] =   { nullptr,               METHOD(exprBinaryOp),       PREC_TEST };
+        rules[TK("not in")] =   { nullptr,               METHOD(exprBinaryOp),       PREC_TEST };
+        rules[TK("is not")] =   { nullptr,               METHOD(exprBinaryOp),       PREC_TEST };
+        rules[TK("and") ] =     { nullptr,               METHOD(exprAnd),            PREC_LOGICAL_AND };
+        rules[TK("or")] =       { nullptr,               METHOD(exprOr),             PREC_LOGICAL_OR };
+        rules[TK("not")] =      { METHOD(exprUnaryOp),   nullptr,                    PREC_UNARY };
+        rules[TK("True")] =     { METHOD(exprValue),     NO_INFIX };
+        rules[TK("False")] =    { METHOD(exprValue),     NO_INFIX };
+        rules[TK("lambda")] =   { METHOD(exprLambda),    NO_INFIX };
+        rules[TK("None")] =     { 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 };
 #undef METHOD
 #undef NO_INFIX
     }
@@ -313,7 +313,7 @@ public:
             _TokenType assignment = parser->previous.type;
             matchNewLines();
             if (assignment == TK("=")) { // name = (expr);
-                compileExpression();
+                compileExpressionTuple();
             } else { // name += / -= / *= ... = (expr);
                 emitCode(OP_LOAD_NAME, index);
                 compileExpression();
@@ -392,7 +392,7 @@ public:
 
     void exprGrouping() {
         matchNewLines();
-        compileExpression();
+        compileExpressionTuple();
         matchNewLines();
         consume(TK(")"));
     }
@@ -442,7 +442,7 @@ public:
                 compileExpression();
                 emitAssignOp(assignment);
             } else {
-                compileExpression();
+                compileExpressionTuple();
             }
             emitCode(OP_STORE_ATTR, index);
         } else {
@@ -488,7 +488,7 @@ public:
             if (assignment != TK("=")) {
                 UNREACHABLE();
             } else {
-                compileExpression();
+                compileExpressionTuple();
             }
             emitCode(OP_STORE_SUBSCR);
         } else {
@@ -593,6 +593,17 @@ public:
         parsePrecedence(PREC_LOWEST);
     }
 
+    // Compiles an expression. Support tuple syntax.
+    void compileExpressionTuple() {
+        int size = 0;
+        while (true) {
+            compileExpression();
+            size++;
+            if (!match(TK(","))) break;
+        }
+        if(size > 1) emitCode(OP_BUILD_TUPLE, size);
+    }
+
     void compileIfStatement() {
         matchNewLines();
         compileExpression(); //< Condition.
@@ -642,7 +653,7 @@ public:
         const _Str& iterName = parser->previous.str();
         int iterIndex = getCode()->addName(iterName);
         consume(TK("in"));
-        compileExpression();
+        compileExpressionTuple();
         emitCode(OP_GET_ITER);
         Loop& loop = enterLoop(true);
         int patch = emitCode(OP_FOR_ITER);
@@ -672,7 +683,7 @@ public:
             if(matchEndStatement()){
                 emitCode(OP_LOAD_NONE);
             }else{
-                compileExpression();
+                compileExpressionTuple();
                 consumeEndStatement();
             }
             emitCode(OP_RETURN_VALUE);
@@ -706,7 +717,7 @@ public:
         } else if(match(TK("pass"))){
             consumeEndStatement();
         } else {
-            compileExpression();
+            compileExpressionTuple();
             consumeEndStatement();
 
             // If last op is not an assignment, pop the result.

+ 1 - 1
src/main.cpp

@@ -4,7 +4,7 @@
 #include <chrono>
 #include "pocketpy.h"
 
-//#define PK_DEBUG
+#define PK_DEBUG
 //#define PK_DEBUG_TIME
 
 class Timer{

+ 3 - 5
src/parser.h

@@ -26,7 +26,7 @@ constexpr const char* __TOKENS[] = {
 
 const _TokenType __TOKENS_LEN = sizeof(__TOKENS) / sizeof(__TOKENS[0]);
 
-constexpr _TokenType __tokenIndex(const char* token) {
+constexpr _TokenType TK(const char* const token) {
     for(int k=0; k<__TOKENS_LEN; k++){
         const char* i = __TOKENS[k];
         const char* j = token;
@@ -38,12 +38,10 @@ constexpr _TokenType __tokenIndex(const char* token) {
     return 0;
 }
 
-
-#define TK(s) __tokenIndex(s)
 #define TK_STR(t) __TOKENS[t]
 
-const _TokenType __KW_BEGIN = __tokenIndex("class");
-const _TokenType __KW_END = __tokenIndex("raise");
+const _TokenType __KW_BEGIN = TK("class");
+const _TokenType __KW_END = TK("raise");
 
 const std::unordered_map<std::string_view, _TokenType> __KW_MAP = [](){
     std::unordered_map<std::string_view, _TokenType> map;

+ 11 - 0
src/pocketpy.h

@@ -277,6 +277,17 @@ void __initializeBuiltinFunctions(VM* _vm) {
         return vm->PyBool(_self.str().rfind(_suffix.str()) == _self.str().length() - _suffix.str().length());
     });
 
+    _vm->bindMethod("str", "join", [](VM* vm, PyVarList args) {
+        const _Str& _self = vm->PyStr_AS_C(args[0]);
+        const PyVarList& _list = vm->PyList_AS_C(args[1]);
+        _StrStream ss;
+        for(int i = 0; i < _list.size(); i++){
+            if(i > 0) ss << _self;
+            ss << vm->PyStr_AS_C(vm->asStr(_list[i]));
+        }
+        return vm->PyStr(ss);
+    });
+
     /************ PyList ************/
     _vm->bindMethod("list", "__iter__", [](VM* vm, PyVarList args) {
         vm->__checkType(args.at(0), vm->_tp_list);