From 7e15e5e202203e8864443d616751439a03fac3f2 Mon Sep 17 00:00:00 2001 From: pikastech Date: Tue, 16 Aug 2022 17:40:11 +0800 Subject: [PATCH] support `__add__()` for list --- package/PikaStdLib/PikaStdData.pyi | 3 + package/PikaStdLib/PikaStdData_List.c | 17 ++++ port/linux/.vscode/launch.json | 3 +- port/linux/package/pikascript/PikaStdData.pyi | 3 + .../PikaStdLib/PikaStdData_List.c | 17 ++++ port/linux/test/VM-test.cpp | 13 +++ port/linux/test/compile-test.cpp | 12 +++ port/linux/test/parse-test.cpp | 25 ++++++ src/PikaParser.c | 2 +- src/PikaVM.c | 81 +++++++++++++++++++ src/dataArg.c | 5 -- src/dataArgs.c | 5 ++ 12 files changed, 178 insertions(+), 8 deletions(-) diff --git a/package/PikaStdLib/PikaStdData.pyi b/package/PikaStdLib/PikaStdData.pyi index 0f47d6fc2..fde1201ef 100644 --- a/package/PikaStdLib/PikaStdData.pyi +++ b/package/PikaStdLib/PikaStdData.pyi @@ -38,6 +38,9 @@ class List(Tuple): def __str__(self) -> str: ... + def __add__(self, others: List) -> List: + """ support list + list""" + class Dict: def __init__(self): ... diff --git a/package/PikaStdLib/PikaStdData_List.c b/package/PikaStdLib/PikaStdData_List.c index ebcab8a26..877de58ff 100644 --- a/package/PikaStdLib/PikaStdData_List.c +++ b/package/PikaStdLib/PikaStdData_List.c @@ -60,3 +60,20 @@ void PikaStdData_List_reverse(PikaObj* self) { PikaList* list = obj_getPtr(self, "list"); list_reverse(list); } + +PikaObj* PikaStdData_List___add__(PikaObj* self, PikaObj* others) { + PikaObj* res = newNormalObj(New_PikaStdData_List); + PikaStdData_List___init__(res); + PikaList* list_res = obj_getPtr(res, "list"); + PikaList* list1 = obj_getPtr(self, "list"); + PikaList* list2 = obj_getPtr(others, "list"); + for (size_t i = 0; i < list_getSize(list1); i++) { + Arg* arg = list_getArg(list1, i); + list_append(list_res, arg); + } + for (size_t i = 0; i < list_getSize(list2); i++) { + Arg* arg = list_getArg(list2, i); + list_append(list_res, arg); + } + return res; +} diff --git a/port/linux/.vscode/launch.json b/port/linux/.vscode/launch.json index d4eadda84..f5e80e88c 100644 --- a/port/linux/.vscode/launch.json +++ b/port/linux/.vscode/launch.json @@ -11,8 +11,7 @@ "program": "${workspaceFolder}/build/test/pikascript_test", // "program": "${workspaceFolder}/build/boot/demo06-pikamain/pikascript_demo06-pikamain", "args": [ - "--gtest_filter=VM.vars_runtime" - // "--gtest_filter=parser.*" + // "--gtest_filter=parser.issues_I5MIFO" ], "stopAtEntry": false, "cwd": "${workspaceFolder}", diff --git a/port/linux/package/pikascript/PikaStdData.pyi b/port/linux/package/pikascript/PikaStdData.pyi index 0f47d6fc2..fde1201ef 100644 --- a/port/linux/package/pikascript/PikaStdData.pyi +++ b/port/linux/package/pikascript/PikaStdData.pyi @@ -38,6 +38,9 @@ class List(Tuple): def __str__(self) -> str: ... + def __add__(self, others: List) -> List: + """ support list + list""" + class Dict: def __init__(self): ... diff --git a/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdData_List.c b/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdData_List.c index ebcab8a26..877de58ff 100644 --- a/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdData_List.c +++ b/port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdData_List.c @@ -60,3 +60,20 @@ void PikaStdData_List_reverse(PikaObj* self) { PikaList* list = obj_getPtr(self, "list"); list_reverse(list); } + +PikaObj* PikaStdData_List___add__(PikaObj* self, PikaObj* others) { + PikaObj* res = newNormalObj(New_PikaStdData_List); + PikaStdData_List___init__(res); + PikaList* list_res = obj_getPtr(res, "list"); + PikaList* list1 = obj_getPtr(self, "list"); + PikaList* list2 = obj_getPtr(others, "list"); + for (size_t i = 0; i < list_getSize(list1); i++) { + Arg* arg = list_getArg(list1, i); + list_append(list_res, arg); + } + for (size_t i = 0; i < list_getSize(list2); i++) { + Arg* arg = list_getArg(list2, i); + list_append(list_res, arg); + } + return res; +} diff --git a/port/linux/test/VM-test.cpp b/port/linux/test/VM-test.cpp index 5d817a555..d3f0edaf3 100644 --- a/port/linux/test/VM-test.cpp +++ b/port/linux/test/VM-test.cpp @@ -1160,3 +1160,16 @@ TEST(VM, vars_runtime) { obj_deinit(self); EXPECT_EQ(pikaMemNow(), 0); } + +#if PIKA_BUILTIN_STRUCT_ENABLE +TEST(VM, list_add) { + char* line = "[1, 2, 3] + [4, 5, 6]"; + PikaObj* self = newRootObj("root", New_PikaStdLib_SysObj); + obj_run(self, line); + /* collect */ + /* assert */ + /* deinit */ + obj_deinit(self); + EXPECT_EQ(pikaMemNow(), 0); +} +#endif diff --git a/port/linux/test/compile-test.cpp b/port/linux/test/compile-test.cpp index 97940dee6..8d6d9c3cb 100644 --- a/port/linux/test/compile-test.cpp +++ b/port/linux/test/compile-test.cpp @@ -588,3 +588,15 @@ TEST(compiler, __getitem__) { Parser_linesToArray(lines); EXPECT_EQ(pikaMemNow(), 0); } + +TEST(compiler, __add__) { + char* lines = "__res = __add__(__others)"; + Parser_linesToArray(lines); + EXPECT_EQ(pikaMemNow(), 0); +} + +TEST(compiler, __sub__) { + char* lines = "__res = __sub__(__others)"; + Parser_linesToArray(lines); + EXPECT_EQ(pikaMemNow(), 0); +} diff --git a/port/linux/test/parse-test.cpp b/port/linux/test/parse-test.cpp index 984015bc5..6ec8a0ad8 100644 --- a/port/linux/test/parse-test.cpp +++ b/port/linux/test/parse-test.cpp @@ -3921,3 +3921,28 @@ TEST(parser, vars_runtime) { args_deinit(buffs); EXPECT_EQ(pikaMemNow(), 0); } + +#if PIKA_BUILTIN_STRUCT_ENABLE +TEST(parser, issues_I5MIFO) { + pikaMemInfo.heapUsedMax = 0; + Args* buffs = New_strBuff(); + char* lines = "[1, 2, 3] + [4, 5, 6]"; + __platform_printf("%s\n", lines); + char* pikaAsm = Parser_linesToAsm(buffs, lines); + __platform_printf("%s", pikaAsm); + EXPECT_STREQ(pikaAsm, + "B0\n" + "2 NUM 1\n" + "2 NUM 2\n" + "2 NUM 3\n" + "1 LST \n" + "2 NUM 4\n" + "2 NUM 5\n" + "2 NUM 6\n" + "1 LST \n" + "0 OPT +\n" + "B0\n"); + args_deinit(buffs); + EXPECT_EQ(pikaMemNow(), 0); +} +#endif diff --git a/src/PikaParser.c b/src/PikaParser.c index c66588e85..11a35d413 100644 --- a/src/PikaParser.c +++ b/src/PikaParser.c @@ -216,7 +216,6 @@ static enum StmtType Lexer_matchStmtType(char* right) { } /* ( <,> | <=> ) + <[> */ is_get_list = PIKA_TRUE; - goto iter_continue; } if (strEqu(ps.token1.pyload, "[") && ps.iter_index == 1) { /* VOID + <[> */ @@ -1472,6 +1471,7 @@ AST* AST_parseStmt(AST* ast, char* stmt) { char* laststmt = Parser_popLastSubStmt(&buffs, &stmt, "["); AST_parseSubStmt(ast, stmt); char* slice_list = strsCut(&buffs, laststmt, '[', ']'); + pika_assert(slice_list != NULL); slice_list = strsAppend(&buffs, slice_list, ":"); int index = 0; while (1) { diff --git a/src/PikaVM.c b/src/PikaVM.c index e0ca572dd..8e385ee85 100644 --- a/src/PikaVM.c +++ b/src/PikaVM.c @@ -1272,6 +1272,47 @@ void operatorInfo_init(OperatorInfo* info, } static void _OPT_ADD(OperatorInfo* op) { + if (argType_isObject(op->t1)) { + if (!argType_isObject(op->t2)) { + VMState_setErrorCode(op->vm, PIKA_RES_ERR_OPERATION_FAILED); + __platform_printf("TypeError: unsupported operand +\n"); + op->res = NULL; + return; + } + PikaObj* obj1 = arg_getPtr(op->a1); + Arg* method_add = obj_getMethodArg(obj1, "__add__"); + if (NULL == method_add) { + VMState_setErrorCode(op->vm, PIKA_RES_ERR_OPERATION_FAILED); + __platform_printf("TypeError: unsupported operand +\n"); + op->res = NULL; + return; + } + arg_deinit(method_add); + PikaObj* obj2 = arg_getPtr(op->a2); + obj_setPtr(obj1, "__others", obj2); + /* clang-format off */ + PIKA_PYTHON( + __res = __add__(__others) + ) + /* clang-format on */ + const uint8_t bytes[] = { + 0x0c, 0x00, /* instruct array size */ + 0x10, 0x81, 0x01, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x04, 0x12, + 0x00, + /* instruct array */ + 0x18, 0x00, /* const pool size */ + 0x00, 0x5f, 0x5f, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x73, 0x00, 0x5f, + 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x5f, 0x00, 0x5f, 0x5f, 0x72, 0x65, + 0x73, 0x00, /* const pool */ + }; + pikaVM_runByteCode(obj1, (uint8_t*)bytes); + Arg* __res = arg_copy(obj_getArg(obj1, "__res")); + op->res = __res; + obj_removeArg(obj1, "__others"); + obj_removeArg(obj1, "__res"); + return; + } + if ((op->t1 == ARG_TYPE_STRING) && (op->t2 == ARG_TYPE_STRING)) { char* num1_s = NULL; char* num2_s = NULL; @@ -1294,6 +1335,46 @@ static void _OPT_ADD(OperatorInfo* op) { } static void _OPT_SUB(OperatorInfo* op) { + if (argType_isObject(op->t1)) { + if (!argType_isObject(op->t2)) { + VMState_setErrorCode(op->vm, PIKA_RES_ERR_OPERATION_FAILED); + __platform_printf("TypeError: unsupported operand +\n"); + op->res = NULL; + return; + } + PikaObj* obj1 = arg_getPtr(op->a1); + Arg* method_sub = obj_getMethodArg(obj1, "__sub__"); + if (NULL == method_sub) { + VMState_setErrorCode(op->vm, PIKA_RES_ERR_OPERATION_FAILED); + __platform_printf("TypeError: unsupported operand +\n"); + op->res = NULL; + return; + } + arg_deinit(method_sub); + PikaObj* obj2 = arg_getPtr(op->a2); + obj_setPtr(obj1, "__others", obj2); + /* clang-format off */ + PIKA_PYTHON( + __res = __sub__(__others) + ) + /* clang-format on */ + const uint8_t bytes[] = { + 0x0c, 0x00, /* instruct array size */ + 0x10, 0x81, 0x01, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x04, 0x12, + 0x00, + /* instruct array */ + 0x18, 0x00, /* const pool size */ + 0x00, 0x5f, 0x5f, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x73, 0x00, 0x5f, + 0x5f, 0x73, 0x75, 0x62, 0x5f, 0x5f, 0x00, 0x5f, 0x5f, 0x72, 0x65, + 0x73, 0x00, /* const pool */ + }; + pikaVM_runByteCode(obj1, (uint8_t*)bytes); + Arg* __res = arg_copy(obj_getArg(obj1, "__res")); + op->res = __res; + obj_removeArg(obj1, "__others"); + obj_removeArg(obj1, "__res"); + return; + } if (op->t2 == ARG_TYPE_NONE) { if (op->t1 == ARG_TYPE_INT) { op->res = arg_setInt(op->res, "", -op->i1); diff --git a/src/dataArg.c b/src/dataArg.c index 9e4a0070c..600ceb539 100644 --- a/src/dataArg.c +++ b/src/dataArg.c @@ -429,8 +429,3 @@ void arg_deinit(Arg* self) { /* free the ref */ arg_freeContent(self); } - -PikaTuple* args_getTuple(Args* self, char* name) { - PikaObj* tuple_obj = args_getPtr(self, name); - return obj_getPtr(tuple_obj, "list"); -} diff --git a/src/dataArgs.c b/src/dataArgs.c index 976357456..7e3a49f26 100644 --- a/src/dataArgs.c +++ b/src/dataArgs.c @@ -694,3 +694,8 @@ exit: arg_deinit(res_buff); return res; } + +PikaTuple* args_getTuple(Args* self, char* name) { + PikaObj* tuple_obj = args_getPtr(self, name); + return obj_getPtr(tuple_obj, "list"); +}