Explorar o código

fix parse err for 'test'.split()[0]

add test
pikastech %!s(int64=2) %!d(string=hai) anos
pai
achega
bf129bb398

+ 1 - 1
package/PikaStdLib/PikaStdData.pyi

@@ -130,7 +130,7 @@ class String:
     def isalnum(self) -> int: ...
     def isalpha(self) -> int: ...
     def isspace(self) -> int: ...
-    def split(self, s: str) -> List: ...
+    def split(self, *s) -> List: ...
     def replace(self, old: str, new: str) -> str: ...
     def strip(self, *chrs) -> str: ...
     def format(self, *vars) -> str: ...

+ 8 - 2
package/PikaStdLib/PikaStdData_String.c

@@ -234,7 +234,13 @@ int PikaStdData_String_isspace(PikaObj* self) {
     return 1;
 }
 
-PikaObj* PikaStdData_String_split(PikaObj* self, char* s) {
+PikaObj* PikaStdData_String_split(PikaObj* self, PikaTuple* s_) {
+    char* s = NULL;
+    if (pikaTuple_getSize(s_) == 0) {
+        s = " ";
+    } else {
+        s = pikaTuple_getStr(s_, 0);
+    }
     /* 创建 list 对象 */
     PikaObj* list = newNormalObj(New_PikaStdData_List);
     /* 初始化 list */
@@ -859,7 +865,7 @@ char* PikaStdData_String_join(PikaObj* self, Arg* val) {
     return sRes;
 }
 
-int PikaStdData_String_find(PikaObj *self, char* sub){
+int PikaStdData_String_find(PikaObj* self, char* sub) {
     char* str = obj_getStr(self, "str");
     char* res = strstr(str, sub);
     if (res == NULL) {

+ 1 - 2
port/linux/.vscode/launch.json

@@ -19,8 +19,7 @@
                 // "--gtest_filter=thread.test1"
                 // "--gtest_filter=eventloop.test1"
                 // "--gtest_filter=parser.tuple_single"
-                // "--gtest_filter=parser.*"
-                "--gtest_filter=builtin.max_min"
+                "--gtest_filter=parser.split_slice"
             ],
             "stopAtEntry": false,
             "cwd": "${workspaceFolder}",

+ 1 - 1
port/linux/package/pikascript/PikaStdData.pyi

@@ -130,7 +130,7 @@ class String:
     def isalnum(self) -> int: ...
     def isalpha(self) -> int: ...
     def isspace(self) -> int: ...
-    def split(self, s: str) -> List: ...
+    def split(self, *s) -> List: ...
     def replace(self, old: str, new: str) -> str: ...
     def strip(self, *chrs) -> str: ...
     def format(self, *vars) -> str: ...

+ 8 - 2
port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdData_String.c

@@ -234,7 +234,13 @@ int PikaStdData_String_isspace(PikaObj* self) {
     return 1;
 }
 
-PikaObj* PikaStdData_String_split(PikaObj* self, char* s) {
+PikaObj* PikaStdData_String_split(PikaObj* self, PikaTuple* s_) {
+    char* s = NULL;
+    if (pikaTuple_getSize(s_) == 0) {
+        s = " ";
+    } else {
+        s = pikaTuple_getStr(s_, 0);
+    }
     /* 创建 list 对象 */
     PikaObj* list = newNormalObj(New_PikaStdData_List);
     /* 初始化 list */
@@ -859,7 +865,7 @@ char* PikaStdData_String_join(PikaObj* self, Arg* val) {
     return sRes;
 }
 
-int PikaStdData_String_find(PikaObj *self, char* sub){
+int PikaStdData_String_find(PikaObj* self, char* sub) {
     char* str = obj_getStr(self, "str");
     char* res = strstr(str, sub);
     if (res == NULL) {

+ 4 - 0
src/PikaObj.c

@@ -695,6 +695,10 @@ PikaObj* newRootObj(char* name, NewFun newObjFun) {
     signal(SIGHUP, signal_handler);   // 捕获 SIGHUP 信号
     signal(SIGSEGV, signal_handler);  // 捕获 SIGHUP 信号
     signal(SIGABRT, signal_handler);
+    signal(SIGQUIT, signal_handler);
+    signal(SIGKILL, signal_handler);
+    signal(SIGTRAP, signal_handler);
+    signal(SIGHUP, signal_handler);
     enable_raw_mode();
 #endif
     PikaObj* newObj = newNormalObj(newObjFun);

+ 12 - 8
src/PikaParser.c

@@ -203,7 +203,9 @@ static enum StmtType Lexer_matchStmtType(char* right) {
                 TOKEN_literal == cs.token1.type ||
                 strEqu(cs.token1.pyload, "]") ||
                 strEqu(cs.token1.pyload, ")")) {
+                /* keep the last one of the chain or slice */
                 is_get_slice = PIKA_TRUE;
+                is_get_chain = PIKA_FALSE;
                 goto iter_continue;
             }
             /* ( <,> | <=> ) + <[> */
@@ -224,7 +226,9 @@ static enum StmtType Lexer_matchStmtType(char* right) {
 
         if (strIsStartWith(cs.token1.pyload, ".")) {
             if (cs.iter_index != 1) {
+                /* keep the last one of the chain or slice */
                 is_get_chain = PIKA_TRUE;
+                is_get_slice = PIKA_FALSE;
                 goto iter_continue;
             }
         }
@@ -270,14 +274,14 @@ static enum StmtType Lexer_matchStmtType(char* right) {
         stmtType = STMT_operator;
         goto exit;
     }
-    if (is_get_chain) {
-        stmtType = STMT_chain;
-        goto exit;
-    }
     if (is_get_slice) {
         stmtType = STMT_slice;
         goto exit;
     }
+    if (is_get_chain) {
+        stmtType = STMT_chain;
+        goto exit;
+    }
     if (is_get_list) {
         stmtType = STMT_list;
         goto exit;
@@ -1755,10 +1759,10 @@ AST* AST_parseStmt(AST* ast, char* stmt) {
 
     /* solve method chain */
     if (STMT_chain == stmtType) {
-        char* stmt = strsCopy(&buffs, right);
-        char* lastStmt = Parser_popLastSubStmt(&buffs, &stmt, ".");
-        AST_parseSubStmt(ast, stmt);
-        AST_parseStmt(ast, lastStmt);
+        char* sHost = strsCopy(&buffs, right);
+        char* sMethodStmt = Parser_popLastSubStmt(&buffs, &sHost, ".");
+        AST_parseSubStmt(ast, sHost);
+        AST_parseStmt(ast, sMethodStmt);
         goto exit;
     }
 

+ 4 - 1
src/PikaPlatform.c

@@ -178,7 +178,10 @@ static int _no_buff_vprintf(char* fmt, va_list args) {
         if (*fmt == '%') {
             ++fmt;
             if (*fmt == 's') {
-                const char* str = va_arg(args, const char*);
+                char* str = va_arg(args, char*);
+                if (str == NULL) {
+                    str = "(null)";
+                }
                 int len = strlen(str);
                 written += len;
                 for (int i = 0; i < len; i++) {

+ 8 - 0
src/PikaVM.c

@@ -806,6 +806,14 @@ static Arg* VM_instruction_handler_SLC(PikaObj* self,
     if (n_input == 3) {
         Arg* end = stack_popArg_alloc(&vm->stack);
         Arg* start = stack_popArg_alloc(&vm->stack);
+        if (arg_getType(start) != ARG_TYPE_INT ||
+            arg_getType(end) != ARG_TYPE_INT) {
+            VMState_setErrorCode(vm, PIKA_RES_ERR_INVALID_PARAM);
+            pika_platform_printf("TypeError: slice indices must be integers\n");
+            arg_deinit(end);
+            arg_deinit(start);
+            return arg_newNull();
+        }
         Arg* obj = stack_popArg_alloc(&vm->stack);
         Arg* res = _vm_slice(vm, self, end, obj, start, 1);
         arg_deinit(end);

+ 17 - 0
test/builtin-test.cpp

@@ -202,6 +202,23 @@ TEST_RUN_SINGLE_FILE_PASS(builtin,
 
 TEST_RUN_SINGLE_FILE_PASS(builtin, max_min, "test/python/builtin/max_min.py")
 
+TEST_RUN_SINGLE_FILE_PASS(builtin, split, "test/python/builtin/split.py")
+
+TEST_RUN_LINES_EXCEPT_OUTPUT(builtin,
+                             split_slice,
+                             "'test'.split('e')[0]",
+                             "'t'\r\n")
+
+TEST_RUN_LINES_EXCEPT_OUTPUT(builtin,
+                             split_slice_1,
+                             "'test'.split('e')[1]",
+                             "'st'\r\n")
+
+TEST_RUN_LINES_EXCEPT_OUTPUT(builtin,
+                             replace_split_0,
+                             "'a b c d'.replace(' ', ',').split(',')[0]",
+                             "'a'\r\n")
+
 #endif
 
 TEST_END

+ 22 - 2
test/parse-test.cpp

@@ -5623,8 +5623,28 @@ TEST_LINES2ASM(is_not,
                "0 OPT  not \n"
                "B0\n")
 
-TEST_LINES2ASM_NOCHECK(split_collect,
-                       "'test'.replace('te', 'qq').split('s')[0]")
+TEST_LINES2ASM(split_collect,
+               "'test'.replace('te', 'qq').split('s')[0]",
+               "B0\n"
+               "3 STR test\n"
+               "3 STR te\n"
+               "3 STR qq\n"
+               "2 RUN .replace\n"
+               "2 STR s\n"
+               "1 RUN .split\n"
+               "1 NUM 0\n"
+               "0 SLC \n"
+               "B0\n");
+
+TEST_LINES2ASM(split_slice,
+               "'test'.split('s')[0]",
+               "B0\n"
+               "2 STR test\n"
+               "2 STR s\n"
+               "1 RUN .split\n"
+               "1 NUM 0\n"
+               "0 SLC \n"
+               "B0\n")
 
 #endif
 

+ 9 - 0
test/python/builtin/split.py

@@ -0,0 +1,9 @@
+a, b = 'test asd'.split()
+assert a == 'test'
+assert b == 'asd'
+
+a, b = 'test asd'.split(' ')
+assert a == 'test'
+assert b == 'asd'
+
+print('PASS')