diff --git a/port/linux/test/parse-test.cpp b/port/linux/test/parse-test.cpp index 245778e4d..c64196d03 100644 --- a/port/linux/test/parse-test.cpp +++ b/port/linux/test/parse-test.cpp @@ -2059,7 +2059,7 @@ TEST(parser, class_) { printf("%s", pikaAsm); EXPECT_STREQ(pikaAsm, (char* ) "B0\n" - "0 DEF Test()\n" + "0 CLS Test()\n" "0 JMP 1\n" "B1\n" "0 RUN PikaStdLib.PikaObj\n" @@ -2096,7 +2096,7 @@ TEST(parser, class_def) { EXPECT_STREQ(pikaAsm, (char*) "B0\n" - "0 DEF Test()\n" + "0 CLS Test()\n" "0 JMP 1\n" "B1\n" "0 RUN PikaStdLib.PikaObj\n" @@ -2510,7 +2510,7 @@ TEST(parser, class_def_void_line) { EXPECT_STREQ(pikaAsm, (char*) "B0\n" - "0 DEF Test()\n" + "0 CLS Test()\n" "0 JMP 1\n" "B1\n" "0 RUN PikaStdLib.PikaObj\n" diff --git a/port/linux/test/pikaMain-test.cpp b/port/linux/test/pikaMain-test.cpp index 430102c29..a9f78c6d5 100644 --- a/port/linux/test/pikaMain-test.cpp +++ b/port/linux/test/pikaMain-test.cpp @@ -1135,29 +1135,29 @@ TEST(pikaMain, class_demo_1) { EXPECT_EQ(pikaMemNow(), 0); } -// TEST(pikaMain, class_demo_2) { -// /* init */ -// pikaMemInfo.heapUsedMax = 0; -// /* run */ -// PikaObj* self = newRootObj((char*)"pikaMain", New_PikaMain); -// __platform_printf((char*)"BEGIN\r\n"); -// obj_run(self, (char*) -// "class Complex:\n" -// " def __init__(self):\n" -// " self.r = 3.0\n" -// " self.i = -4.5\n" -// "x = Complex()\n" -// "print(x.r)\n" -// "print(x.i)\n" -// ); -// /* assert */ -// EXPECT_STREQ(log_buff[0], (char*)"-4.500000\r\n"); -// EXPECT_STREQ(log_buff[1], (char*)"3.000000\r\n"); -// EXPECT_STREQ(log_buff[2], (char*)"BEGIN\r\n"); -// /* deinit */ -// obj_deinit(self); -// EXPECT_EQ(pikaMemNow(), 0); -// } +TEST(pikaMain, class_demo_2) { + /* init */ + pikaMemInfo.heapUsedMax = 0; + /* run */ + PikaObj* self = newRootObj((char*)"pikaMain", New_PikaMain); + __platform_printf((char*)"BEGIN\r\n"); + obj_run(self, (char*) + "class Complex:\n" + " def __init__(self):\n" + " self.r = 3.0\n" + " self.i = -4.5\n" + "x = Complex()\n" + "print(x.r)\n" + "print(x.i)\n" + ); + /* assert */ + EXPECT_STREQ(log_buff[0], (char*)"-4.500000\r\n"); + EXPECT_STREQ(log_buff[1], (char*)"3.000000\r\n"); + EXPECT_STREQ(log_buff[2], (char*)"BEGIN\r\n"); + /* deinit */ + obj_deinit(self); + EXPECT_EQ(pikaMemNow(), 0); +} TEST(pikaMain, class_demo_3) { /* init */ @@ -1411,3 +1411,27 @@ TEST(pikaMain, self_operator) { /* mem check */ EXPECT_EQ(pikaMemNow(), 0); } + +TEST(pikaMain, class_demo_2_initwitharg) { + /* init */ + pikaMemInfo.heapUsedMax = 0; + /* run */ + PikaObj* self = newRootObj((char*)"pikaMain", New_PikaMain); + __platform_printf((char*)"BEGIN\r\n"); + obj_run(self, (char*) + "class Complex:\n" + " def __init__(self, r, i):\n" + " self.r = r\n" + " self.i = i\n" + "x = Complex(3.0, -4.5)\n" + "print(x.r)\n" + "print(x.i)\n" + ); + /* assert */ + EXPECT_STREQ(log_buff[0], (char*)"-4.500000\r\n"); + EXPECT_STREQ(log_buff[1], (char*)"3.000000\r\n"); + EXPECT_STREQ(log_buff[2], (char*)"BEGIN\r\n"); + /* deinit */ + obj_deinit(self); + EXPECT_EQ(pikaMemNow(), 0); +} diff --git a/src/PikaObj.c b/src/PikaObj.c index 27e0fb220..28bd6e160 100644 --- a/src/PikaObj.c +++ b/src/PikaObj.c @@ -508,7 +508,7 @@ int32_t class_defineConstructor(PikaObj* self, char* declearation, Method methodPtr) { return __class_defineMethodWithType(self, declearation, methodPtr, - ARG_TYPE_CONSTRUCTOR_METHOD, NULL); + ARG_TYPE_NATIVE_CONSTRUCTOR_METHOD, NULL); } /* define a native method as default */ @@ -519,6 +519,16 @@ int32_t class_defineMethod(PikaObj* self, ARG_TYPE_NATIVE_METHOD, NULL); } +/* define object method, object method is which startwith (self) */ +int32_t class_defineRunTimeConstructor(PikaObj* self, + char* declearation, + Method methodPtr, + ByteCodeFrame* bytecode_frame) { + return __class_defineMethodWithType(self, declearation, methodPtr, + ARG_TYPE_CONSTRUCTOR_METHOD, + bytecode_frame); +} + /* define object method, object method is which startwith (self) */ int32_t class_defineObjectMethod(PikaObj* self, char* declearation, diff --git a/src/PikaObj.h b/src/PikaObj.h index 8066e8a6f..6b6e367d0 100644 --- a/src/PikaObj.h +++ b/src/PikaObj.h @@ -156,6 +156,11 @@ int32_t class_defineConstructor(PikaObj* self, char* declearation, Method methodPtr); +int32_t class_defineRunTimeConstructor(PikaObj* self, + char* declearation, + Method methodPtr, + ByteCodeFrame* bytecode_frame); + int32_t obj_removeArg(PikaObj* self, char* argPath); int32_t obj_isArgExist(PikaObj* self, char* argPath); PikaObj* obj_getClassObjByNewFun(PikaObj* self, char* name, NewFun newClassFun); diff --git a/src/PikaParser.c b/src/PikaParser.c index 6519d8cfd..b03e3d94e 100644 --- a/src/PikaParser.c +++ b/src/PikaParser.c @@ -1576,7 +1576,7 @@ char* AST_toPikaASM(AST* ast, Args* outBuffs) { /* default superClass */ superClass = "PikaStdLib.PikaObj"; } - pikaAsm = strsAppend(&buffs, pikaAsm, "0 DEF "); + pikaAsm = strsAppend(&buffs, pikaAsm, "0 CLS "); pikaAsm = strsAppend(&buffs, pikaAsm, strsAppend(&buffs, thisClass, "()\n" diff --git a/src/PikaVM.c b/src/PikaVM.c index 9102fb164..0c8ae23cf 100644 --- a/src/PikaVM.c +++ b/src/PikaVM.c @@ -182,10 +182,50 @@ static Arg* VM_instruction_handler_REF(PikaObj* self, VMState* vs, char* data) { return arg; } +static Arg* VMState_runMethodArg(VMState* vs, + PikaObj* method_host_obj, + PikaObj* sub_locals, + Arg* method_arg) { + Arg* return_arg = NULL; + /* get method Ptr */ + Method method_ptr = methodArg_getPtr(method_arg); + /* get method type list */ + ArgType method_type = arg_getType(method_arg); + ByteCodeFrame* method_bytecodeFrame = + methodArg_getBytecodeFrame(method_arg); + obj_setErrorCode(method_host_obj, 0); + + /* run method */ + if (method_type == ARG_TYPE_NATIVE_METHOD) { + /* native method */ + method_ptr(method_host_obj, sub_locals->list); + /* get method return */ + return_arg = arg_copy(args_getArg(sub_locals->list, (char*)"return")); + } else if (method_type == ARG_TYPE_NATIVE_CONSTRUCTOR_METHOD) { + /* native method */ + method_ptr(method_host_obj, sub_locals->list); + /* get method return */ + return_arg = arg_copy(args_getArg(sub_locals->list, (char*)"return")); + } else { + /* static method and object method */ + /* byteCode */ + uint16_t pc = (uintptr_t)method_ptr - + (uintptr_t)instructArray_getByOffset( + &(method_bytecodeFrame->instruct_array), 0); + sub_locals = pikaVM_runByteCodeWithState( + method_host_obj, sub_locals, vs->globals, method_bytecodeFrame, pc); + + /* get method return */ + return_arg = arg_copy(args_getArg(sub_locals->list, (char*)"return")); + } + return return_arg; +} + static void VMState_loadArgsFromMethodArg(VMState* vs, PikaObj* method_host_obj, Args* args, - Arg* method_arg) { + Arg* method_arg, + char* method_name) { Args buffs = {0}; /* get method type list */ char* type_list = methodArg_getTypeList(method_arg, &buffs); @@ -203,16 +243,17 @@ static void VMState_loadArgsFromMethodArg(VMState* vs, uint8_t arg_num_input = VMState_getInputArgNum(vs); /* check arg num */ - if (method_type == ARG_TYPE_CONSTRUCTOR_METHOD) { + if (method_type == ARG_TYPE_NATIVE_CONSTRUCTOR_METHOD || + method_type == ARG_TYPE_CONSTRUCTOR_METHOD) { /* not check decleard arg num for constrctor */ } else { /* check arg num decleard and input */ if (arg_num_dec != arg_num_input) { VMState_setErrorCode(vs, 3); __platform_printf( - "TypeError: method takes %d positional argument but %d were " + "TypeError: %s() takes %d positional argument but %d were " "given\r\n", - arg_num_dec, arg_num_input); + method_name, arg_num_dec, arg_num_input); goto exit; } } @@ -244,10 +285,7 @@ static Arg* VM_instruction_handler_RUN(PikaObj* self, VMState* vs, char* data) { char* methodPath = data; PikaObj* method_host_obj; Arg* method_arg = NULL; - Method method_ptr; - ArgType method_type = ARG_TYPE_NULL; char* sys_out; - ByteCodeFrame* method_bytecodeFrame; /* return arg directly */ if (strEqu(data, "")) { return_arg = stack_popArg(&(vs->stack)); @@ -278,42 +316,15 @@ static Arg* VM_instruction_handler_RUN(PikaObj* self, VMState* vs, char* data) { goto exit; } - /* get method Ptr */ - method_ptr = methodArg_getPtr(method_arg); - /* get method type list */ - method_type = arg_getType(method_arg); - method_bytecodeFrame = methodArg_getBytecodeFrame(method_arg); sub_locals = New_PikaObj(); /* load args from vmState to sub_local->list */ VMState_loadArgsFromMethodArg(vs, method_host_obj, sub_locals->list, - method_arg); + method_arg, data); - obj_setErrorCode(method_host_obj, 0); - - /* run method */ - if (method_type == ARG_TYPE_NATIVE_METHOD) { - /* native method */ - method_ptr(method_host_obj, sub_locals->list); - /* get method return */ - return_arg = arg_copy(args_getArg(sub_locals->list, (char*)"return")); - } else if (method_type == ARG_TYPE_CONSTRUCTOR_METHOD) { - /* native method */ - method_ptr(method_host_obj, sub_locals->list); - /* get method return */ - return_arg = arg_copy(args_getArg(sub_locals->list, (char*)"return")); - } else { - /* static method and object method */ - /* byteCode */ - uint16_t pc = (uintptr_t)method_ptr - - (uintptr_t)instructArray_getByOffset( - &(method_bytecodeFrame->instruct_array), 0); - sub_locals = pikaVM_runByteCodeWithState( - method_host_obj, sub_locals, vs->globals, method_bytecodeFrame, pc); - - /* get method return */ - return_arg = arg_copy(args_getArg(sub_locals->list, (char*)"return")); - } + /* run method arg */ + return_arg = + VMState_runMethodArg(vs, method_host_obj, sub_locals, method_arg); /* __init__() */ if (arg_getType(return_arg) == ARG_TYPE_FREE_OBJECT) { @@ -321,12 +332,13 @@ static Arg* VM_instruction_handler_RUN(PikaObj* self, VMState* vs, char* data) { PikaObj* new_obj = arg_getPtr(return_arg); Arg* method_arg = obj_getMethodArg(new_obj, "__init__"); if (NULL != method_arg) { - Args method_args = {0}; - VMState_loadArgsFromMethodArg(vs, new_obj, &method_args, - method_arg); - Method method_ptr = methodArg_getPtr(method_arg); - method_ptr(new_obj, &method_args); - args_deinit_stack(&method_args); + PikaObj* sub_locals = New_PikaObj(); + VMState_loadArgsFromMethodArg(vs, new_obj, sub_locals->list, + method_arg, "__init__"); + Arg* return_arg = + VMState_runMethodArg(vs, new_obj, sub_locals, method_arg); + arg_deinit(return_arg); + obj_deinit(sub_locals); arg_deinit(method_arg); } } @@ -676,7 +688,10 @@ OPT_exit: return NULL; } -static Arg* VM_instruction_handler_DEF(PikaObj* self, VMState* vs, char* data) { +static Arg* __VM_instruction_handler_DEF(PikaObj* self, + VMState* vs, + char* data, + uint8_t is_class) { int thisBlockDeepth = VMState_getBlockDeepthNow(vs); PikaObj* hostObj = vs->locals; @@ -699,8 +714,15 @@ static Arg* VM_instruction_handler_DEF(PikaObj* self, VMState* vs, char* data) { class_defineObjectMethod(hostObj, data, (Method)ins_unit_now, vs->bytecode_frame); } else { - class_defineStaticMethod(hostObj, data, (Method)ins_unit_now, - vs->bytecode_frame); + if (is_class) { + class_defineRunTimeConstructor(hostObj, data, + (Method)ins_unit_now, + vs->bytecode_frame); + } else { + class_defineStaticMethod(hostObj, data, + (Method)ins_unit_now, + vs->bytecode_frame); + } } break; } @@ -710,6 +732,14 @@ static Arg* VM_instruction_handler_DEF(PikaObj* self, VMState* vs, char* data) { return NULL; } +static Arg* VM_instruction_handler_DEF(PikaObj* self, VMState* vs, char* data) { + return __VM_instruction_handler_DEF(self, vs, data, 0); +} + +static Arg* VM_instruction_handler_CLS(PikaObj* self, VMState* vs, char* data) { + return __VM_instruction_handler_DEF(self, vs, data, 1); +} + static Arg* VM_instruction_handler_RET(PikaObj* self, VMState* vs, char* data) { /* exit jmp signal */ vs->jmp = -999; diff --git a/src/__instruction_table.cfg b/src/__instruction_table.cfg index 3403b9e14..8ffca1c4f 100644 --- a/src/__instruction_table.cfg +++ b/src/__instruction_table.cfg @@ -46,3 +46,4 @@ def_ins(CTN) def_ins(GLB) def_ins(RAS) def_ins(NEW) +def_ins(CLS) diff --git a/src/dataArg.h b/src/dataArg.h index f5dc83e29..ca9b64c3c 100644 --- a/src/dataArg.h +++ b/src/dataArg.h @@ -44,6 +44,7 @@ typedef enum { ARG_TYPE_MATE_OBJECT, ARG_TYPE_FREE_OBJECT, ARG_TYPE_NATIVE_METHOD, + ARG_TYPE_NATIVE_CONSTRUCTOR_METHOD, ARG_TYPE_CONSTRUCTOR_METHOD, ARG_TYPE_OBJECT_METHOD, ARG_TYPE_STATIC_METHOD,