From 442e51e314e02fee180a0f079c381786affe3b3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=82?= Date: Fri, 24 Jun 2022 05:44:50 +0000 Subject: [PATCH] !35 support try raise the first step * Merge branch 'master' into trydev * Merge branch 'master' into trydev * Merge branch 'master' into trydev * Merge branch 'master' into trydev * Merge branch 'master' into trydev * raise in function not ok * support except * add GER ins * try raise is test ok * support default raise RuntimeError * add except test * jmp to skip except block after try * add parse --- port/linux/.vscode/launch.json | 2 +- port/linux/test/except-test.cpp | 75 +++++++++++++++ port/linux/test/parse-test.cpp | 42 +++++++++ src/PikaParser.c | 71 +++++++++++++- src/PikaPlatform.h | 29 +++--- src/PikaVM.c | 160 ++++++++++++++++++++++++-------- src/PikaVM.h | 15 +++ src/__instruction_table.cfg | 33 +++++++ 8 files changed, 369 insertions(+), 58 deletions(-) create mode 100644 port/linux/test/except-test.cpp diff --git a/port/linux/.vscode/launch.json b/port/linux/.vscode/launch.json index 8f8027bea..7a6e35d2d 100644 --- a/port/linux/.vscode/launch.json +++ b/port/linux/.vscode/launch.json @@ -11,7 +11,7 @@ "program": "${workspaceFolder}/build/test/pikascript_test", // "program": "${workspaceFolder}/build/boot/demo06-pikamain/pikascript_demo06-pikamain", "args": [ - // "--gtest_filter=class.class_par" + "--gtest_filter=except.trydef1" ], "stopAtEntry": false, "cwd": "${workspaceFolder}", diff --git a/port/linux/test/except-test.cpp b/port/linux/test/except-test.cpp new file mode 100644 index 000000000..f4d04218d --- /dev/null +++ b/port/linux/test/except-test.cpp @@ -0,0 +1,75 @@ +#include "test_common.h" + +TEST(except, try1) { + /* init */ + pikaMemInfo.heapUsedMax = 0; + PikaObj* pikaMain = newRootObj("pikaMain", New_PikaMain); + __platform_printf("BEGIN\r\n"); + /* run */ + obj_run(pikaMain, + "try:\n" + " print('before raise')\n" + " raise \n" + " print('after raise')\n" + "except:\n" + " print('in except')\n" + "\n"); + /* collect */ + EXPECT_STREQ("BEGIN\r\n", log_buff[2]); + EXPECT_STREQ("before raise\r\n", log_buff[1]); + EXPECT_STREQ("in except\r\n", log_buff[0]); + /* assert */ + /* deinit */ + obj_deinit(pikaMain); + EXPECT_EQ(pikaMemNow(), 0); +} + +TEST(except, trycmodule1) { + /* init */ + pikaMemInfo.heapUsedMax = 0; + PikaObj* pikaMain = newRootObj("pikaMain", New_PikaMain); + __platform_printf("BEGIN\r\n"); + /* run */ + obj_run(pikaMain, + "import pika_cjson\n" + "try:\n" + " b = pika_cjson.Parse('')\n" + "except:\n" + " print('parse faild')\n" + "\n"); + /* collect */ + EXPECT_STREQ("BEGIN\r\n", log_buff[2]); + /* assert */ + /* deinit */ + obj_deinit(pikaMain); + EXPECT_EQ(pikaMemNow(), 0); +} + +TEST(except, trydef1) { + /* init */ + pikaMemInfo.heapUsedMax = 0; + PikaObj* pikaMain = newRootObj("pikaMain", New_PikaMain); + __platform_printf("BEGIN\r\n"); + /* run */ + obj_run(pikaMain, + "def tryfn(a):\n" + " if a == 1:\n" + " print('a:1')\n" + " raise\n" + " print('a:1,after raise')\n" + " return\n" + " if a == 0:\n" + " print('a:0')\n" + " return\n" + "try:\n" + " tryfn(1)\n" + " tryfn(0)\n" + "except:\n" + " print('in except')\n" + "\n"); + /* collect */ + /* assert */ + /* deinit */ + obj_deinit(pikaMain); + EXPECT_EQ(pikaMemNow(), 0); +} diff --git a/port/linux/test/parse-test.cpp b/port/linux/test/parse-test.cpp index eef82db20..0d99d26c4 100644 --- a/port/linux/test/parse-test.cpp +++ b/port/linux/test/parse-test.cpp @@ -3149,3 +3149,45 @@ TEST(parser, format2) { EXPECT_EQ(pikaMemNow(), 0); } #endif + +TEST(parser, try1) { + pikaMemInfo.heapUsedMax = 0; + Args* buffs = New_strBuff(); + char* lines = + "try:\n" + " a = 1\n" + " raise 0x25 + 256\n" + " raise\n" + "except:\n" + " print('in except')\n" + "\n"; + printf("%s\n", lines); + char* pikaAsm = Parser_multiLineToAsm(buffs, lines); + printf("%s", pikaAsm); + EXPECT_STREQ(pikaAsm, + "B0\n" + "0 TRY \n" + "B1\n" + "0 NUM 1\n" + "0 OUT a\n" + "B1\n" + "1 NUM 0x25\n" + "1 NUM 256\n" + "0 OPT +\n" + "0 RIS \n" + "B1\n" + "0 REF RuntimeError\n" + "0 RIS \n" + "B0\n" + "0 NTR \n" + "0 GER \n" + "0 JEZ 2\n" + "B0\n" + "B1\n" + "1 STR in except\n" + "0 RUN print\n" + "0 SER 0\n" + "B0\n"); + args_deinit(buffs); + EXPECT_EQ(pikaMemNow(), 0); +} diff --git a/src/PikaParser.c b/src/PikaParser.c index e32b279de..3c0b53610 100644 --- a/src/PikaParser.c +++ b/src/PikaParser.c @@ -1501,9 +1501,6 @@ AST* AST_parseLine(char* line, Stack* block_stack) { char* arg_in = strsPopToken(list_buffs, line_buff, ' '); obj_setStr(ast, "arg_in", arg_in); strsPopToken(list_buffs, line_buff, ' '); - if (strIsStartWith(line_buff, "range(")) { - obj_setInt(ast, "isRange", 1); - } char* list_in = strsPopToken(list_buffs, line_buff, ':'); list_in = strsAppend(list_buffs, "iter(", list_in); list_in = strsAppend(list_buffs, list_in, ")"); @@ -1529,6 +1526,31 @@ AST* AST_parseLine(char* line, Stack* block_stack) { } goto block_matched; } + + /* try */ + if (strIsStartWith(line_start, "try")) { + if ((line_start[3] == ' ') || (line_start[3] == ':')) { + stmt = ""; + obj_setStr(ast, "block", "try"); + if (NULL != block_stack) { + stack_pushStr(block_stack, "try"); + } + } + goto block_matched; + } + + /* except */ + if (strIsStartWith(line_start, "except")) { + if ((line_start[6] == ' ') || (line_start[6] == ':')) { + stmt = ""; + obj_setStr(ast, "block", "except"); + if (NULL != block_stack) { + stack_pushStr(block_stack, "except"); + } + } + goto block_matched; + } + if (strEqu(line_start, "return")) { obj_setStr(ast, "return", ""); stmt = ""; @@ -1541,6 +1563,21 @@ AST* AST_parseLine(char* line, Stack* block_stack) { obj_setStr(ast, "return", ""); goto block_matched; } + if (strEqu(line_start, "raise")) { + obj_setStr(ast, "raise", ""); + stmt = "RuntimeError"; + goto block_matched; + } + if (strIsStartWith(line_start, "raise ")) { + char* lineBuff = strsCopy(&buffs, line_start); + strsPopToken(&buffs, lineBuff, ' '); + stmt = lineBuff; + if (strEqu("", stmt)) { + stmt = "RuntimeError"; + } + obj_setStr(ast, "raise", ""); + goto block_matched; + } if (strIsStartWith(line_start, "global ")) { stmt = ""; char* global_list = line_start + 7; @@ -1995,6 +2032,19 @@ char* AST_toPikaASM(AST* ast, Args* outBuffs) { ASM_addBlockDeepth(ast, outBuffs, pikaAsm, block_type_num); pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 JMP -1\n"); } + /* goto the while start when exit while block */ + if (strEqu(block_type, "try")) { + pikaAsm = + ASM_addBlockDeepth(ast, outBuffs, pikaAsm, block_type_num); + pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 NTR \n"); + pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 GER \n"); + pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 JEZ 2\n"); + } + + if (strEqu(block_type, "except")) { + pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 SER 0\n"); + } + /* goto the while start when exit while block */ if (strEqu(block_type, "for")) { pikaAsm = @@ -2093,6 +2143,12 @@ char* AST_toPikaASM(AST* ast, Args* outBuffs) { pikaAsm = strsAppend(&buffs, pikaAsm, "0 NEL 1\n"); goto exit; } + + if (strEqu(obj_getStr(ast, "block"), "try")) { + pikaAsm = strsAppend(&buffs, pikaAsm, "0 TRY \n"); + goto exit; + } + if (strEqu(obj_getStr(ast, "block"), "elif")) { /* skip if __else is 0 */ pikaAsm = strsAppend(&buffs, pikaAsm, "0 NEL 1\n"); @@ -2158,6 +2214,15 @@ char* AST_toPikaASM(AST* ast, Args* outBuffs) { is_block_matched = 1; goto exit; } + + if (obj_isArgExist(ast, "raise")) { + /* parse stmt ast */ + pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm); + pikaAsm = strsAppend(&buffs, pikaAsm, "0 RIS \n"); + is_block_matched = 1; + goto exit; + } + if (obj_isArgExist(ast, "global")) { /* parse stmt ast */ pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm); diff --git a/src/PikaPlatform.h b/src/PikaPlatform.h index fbe953d7f..2221975e8 100644 --- a/src/PikaPlatform.h +++ b/src/PikaPlatform.h @@ -65,23 +65,22 @@ #define __platform_printf(...) rt_kprintf(__VA_ARGS__) #endif -/* clang-format off */ typedef enum { - PIKA_RES_ERR_ARG_NO_FOUND = -12, - PIKA_RES_ERR_UNKNOWN_INSTRUCTION = -11, - PIKA_RES_ERR_OUT_OF_RANGE = -10, - PIKA_RES_ERR_IO_ERROR = -9, - PIKA_RES_ERR_INSUFFICIENT_RESOURCE = -8, - PIKA_RES_ERR_INVALID_PARAM = -7, - PIKA_RES_ERR_INVALID_PTR = -6, - PIKA_RES_ERR_UNALIGNED_PTR = -5, - PIKA_RES_ERR_INVALID_VERSION_NUMBER = -4, - PIKA_RES_ERR_ILLEGAL_MAGIC_CODE = -3, - PIKA_RES_ERR_OPERATION_FAILED = -2, - PIKA_RES_ERR_UNKNOWN = -1, - PIKA_RES_OK = 0, + PIKA_RES_OK = 0, + PIKA_RES_ERR_RUNTIME_ERROR, + PIKA_RES_ERR_ARG_NO_FOUND, + PIKA_RES_ERR_UNKNOWN_INSTRUCTION, + PIKA_RES_ERR_OUT_OF_RANGE, + PIKA_RES_ERR_IO_ERROR, + PIKA_RES_ERR_INSUFFICIENT_RESOURCE, + PIKA_RES_ERR_INVALID_PARAM, + PIKA_RES_ERR_INVALID_PTR, + PIKA_RES_ERR_UNALIGNED_PTR, + PIKA_RES_ERR_INVALID_VERSION_NUMBER, + PIKA_RES_ERR_ILLEGAL_MAGIC_CODE, + PIKA_RES_ERR_OPERATION_FAILED, + PIKA_RES_ERR_UNKNOWN, } PIKA_RES; -/* clang-format on*/ /* clang-format off */ diff --git a/src/PikaVM.c b/src/PikaVM.c index b2b9ac7be..39012ec12 100644 --- a/src/PikaVM.c +++ b/src/PikaVM.c @@ -40,7 +40,8 @@ static VMParameters* __pikaVM_runByteCodeFrameWithState( VMParameters* locals, VMParameters* globals, ByteCodeFrame* bytecode_frame, - uint16_t pc); + uint16_t pc, + TRY_STATE is_in_try); /* head declear end */ @@ -71,7 +72,7 @@ static char* VMState_getConstWithInstructUnit(VMState* vs, instructUnit_getConstPoolIndex(ins_unit)); } -static int32_t VMState_getAddrOffsetOfJUM(VMState* vs) { +static int32_t VMState_getAddrOffsetOfJmpBack(VMState* vs) { int offset = 0; InstructUnit* ins_unit_now = VMState_getInstructNow(vs); while (1) { @@ -138,14 +139,29 @@ static int32_t VMState_getAddrOffsetFromJmp(VMState* vs) { } static int32_t VMState_getAddrOffsetOfBreak(VMState* vs) { - int32_t offset = VMState_getAddrOffsetOfJUM(vs); + int32_t offset = VMState_getAddrOffsetOfJmpBack(vs); /* byteCode */ offset += instructUnit_getSize(); return offset; } +static int32_t VMState_getAddrOffsetOfRaise(VMState* vs) { + int offset = 0; + InstructUnit* ins_unit_now = VMState_getInstructNow(vs); + while (1) { + offset += instructUnit_getSize(ins_unit_now); + ins_unit_now = VMState_getInstructWithOffset(vs, offset); + enum Instruct ins = instructUnit_getInstruct(ins_unit_now); + if ((NTR == ins)) { + return offset; + } + } + /* byteCode */ + return offset; +} + static int32_t VMState_getAddrOffsetOfContinue(VMState* vs) { - int32_t offset = VMState_getAddrOffsetOfJUM(vs); + int32_t offset = VMState_getAddrOffsetOfJmpBack(vs); /* byteCode */ return offset; } @@ -156,6 +172,16 @@ static Arg* VM_instruction_handler_NON(PikaObj* self, VMState* vs, char* data) { return NULL; } +static Arg* VM_instruction_handler_TRY(PikaObj* self, VMState* vs, char* data) { + vs->try_state = TRY_STATE_TOP; + return NULL; +} + +static Arg* VM_instruction_handler_NTR(PikaObj* self, VMState* vs, char* data) { + vs->try_state = TRY_STATE_NONE; + return NULL; +} + static Arg* VM_instruction_handler_NEW(PikaObj* self, VMState* vs, char* data) { Arg* origin_arg = obj_getArg(vs->locals, data); Arg* new_arg = arg_copy(origin_arg); @@ -174,6 +200,9 @@ static Arg* VM_instruction_handler_REF(PikaObj* self, VMState* vs, char* data) { if (strEqu(data, (char*)"None")) { return arg_setNull(NULL); } + if (strEqu(data, (char*)"RuntimeError")) { + return arg_setInt(NULL, "", PIKA_RES_ERR_RUNTIME_ERROR); + } /* find in local list first */ Arg* arg = arg_copy(obj_getArg(vs->locals, data)); if (NULL == arg) { @@ -181,12 +210,18 @@ static Arg* VM_instruction_handler_REF(PikaObj* self, VMState* vs, char* data) { arg = arg_copy(obj_getArg(vs->globals, data)); } if (NULL == arg) { - VMState_setErrorCode(vs, 1); + VMState_setErrorCode(vs, PIKA_RES_ERR_ARG_NO_FOUND); __platform_printf("NameError: name '%s' is not defined\r\n", data); } return arg; } +static Arg* VM_instruction_handler_GER(PikaObj* self, VMState* vs, char* data) { + PIKA_RES err = vs->try_error_code; + Arg* err_arg = arg_setInt(NULL, "", err); + return err_arg; +} + static int32_t __foreach_handler_deinitTuple(Arg* argEach, Args* context) { if (arg_getType(argEach) == ARG_TYPE_TUPLE) { PikaTuple* tuple = arg_getPtr(argEach); @@ -195,9 +230,10 @@ static int32_t __foreach_handler_deinitTuple(Arg* argEach, Args* context) { return PIKA_RES_OK; } -Arg* obj_runMethodArg(PikaObj* self, - PikaObj* method_args_obj, - Arg* method_arg) { +Arg* __obj_runMethodArgWithState(PikaObj* self, + PikaObj* method_args_obj, + Arg* method_arg, + TRY_STATE try_state) { Arg* return_arg = NULL; /* get method Ptr */ Method method_ptr = methodArg_getPtr(method_arg); @@ -213,7 +249,7 @@ Arg* obj_runMethodArg(PikaObj* self, if (NULL != method_context) { self = method_context; } - obj_setErrorCode(self, 0); + obj_setErrorCode(self, PIKA_RES_OK); /* run method */ if (method_type == ARG_TYPE_METHOD_NATIVE) { @@ -235,7 +271,7 @@ Arg* obj_runMethodArg(PikaObj* self, &(method_bytecodeFrame->instruct_array), 0); uint16_t pc = (uintptr_t)method_ptr - insturctArray_start; method_args_obj = __pikaVM_runByteCodeFrameWithState( - self, method_args_obj, self, method_bytecodeFrame, pc); + self, method_args_obj, self, method_bytecodeFrame, pc, try_state); /* get method return */ return_arg = @@ -245,6 +281,13 @@ Arg* obj_runMethodArg(PikaObj* self, return return_arg; } +Arg* obj_runMethodArg(PikaObj* self, + PikaObj* method_args_obj, + Arg* method_arg) { + return __obj_runMethodArgWithState(self, method_args_obj, method_arg, + TRY_STATE_NONE); +} + static int VMState_loadArgsFromMethodArg(VMState* vs, PikaObj* method_host_obj, Args* args, @@ -290,7 +333,7 @@ static int VMState_loadArgsFromMethodArg(VMState* vs, } else { /* check arg num decleard and input */ if (arg_num_dec != arg_num_input - arg_num_used) { - VMState_setErrorCode(vs, 3); + VMState_setErrorCode(vs, PIKA_RES_ERR_INVALID_PARAM); __platform_printf( "TypeError: %s() takes %d positional argument but %d were " "given\r\n", @@ -419,6 +462,11 @@ static Arg* VM_instruction_handler_RUN(PikaObj* self, VMState* vs, char* data) { Arg* method_arg = NULL; char* sys_out; int arg_num_used = 0; + TRY_STATE sub_try_state = TRY_STATE_NONE; + if (vs->try_state == TRY_STATE_TOP || + vs->try_error_code == TRY_STATE_INNER) { + sub_try_state = TRY_STATE_INNER; + } /* return arg directly */ if (strEqu(data, "")) { return_arg = stack_popArg(&(vs->stack)); @@ -438,7 +486,7 @@ static Arg* VM_instruction_handler_RUN(PikaObj* self, VMState* vs, char* data) { } if (NULL == method_host_obj) { /* error, not found object */ - VMState_setErrorCode(vs, 1); + VMState_setErrorCode(vs, PIKA_RES_ERR_ARG_NO_FOUND); __platform_printf("Error: method '%s' no found.\r\n", data); goto exit; } @@ -451,7 +499,7 @@ static Arg* VM_instruction_handler_RUN(PikaObj* self, VMState* vs, char* data) { /* assert method*/ if (NULL == method_arg || ARG_TYPE_NONE == arg_getType(method_arg)) { /* error, method no found */ - VMState_setErrorCode(vs, 2); + VMState_setErrorCode(vs, PIKA_RES_ERR_ARG_NO_FOUND); __platform_printf("NameError: name '%s' is not defined\r\n", data); goto exit; } @@ -467,7 +515,8 @@ static Arg* VM_instruction_handler_RUN(PikaObj* self, VMState* vs, char* data) { } /* run method arg */ - return_arg = obj_runMethodArg(method_host_obj, sub_locals, method_arg); + return_arg = __obj_runMethodArgWithState(method_host_obj, sub_locals, + method_arg, sub_try_state); /* __init__() */ if (ARG_TYPE_OBJECT_NEW == arg_getType(return_arg)) { @@ -486,7 +535,8 @@ static Arg* VM_instruction_handler_RUN(PikaObj* self, VMState* vs, char* data) { if (vs->error_code != 0) { goto init_exit; } - return_arg_init = obj_runMethodArg(new_obj, sub_locals, method_arg); + return_arg_init = __obj_runMethodArgWithState( + new_obj, sub_locals, method_arg, sub_try_state); init_exit: if (NULL != return_arg_init) { arg_deinit(return_arg_init); @@ -503,7 +553,7 @@ static Arg* VM_instruction_handler_RUN(PikaObj* self, VMState* vs, char* data) { /* transfer errCode */ if (0 != obj_getErrorCode(method_host_obj)) { /* method error */ - VMState_setErrorCode(vs, 6); + VMState_setErrorCode(vs, PIKA_RES_ERR_RUNTIME_ERROR); } goto exit; @@ -643,6 +693,11 @@ static Arg* VM_instruction_handler_JMP(PikaObj* self, VMState* vs, char* data) { return NULL; } +static Arg* VM_instruction_handler_SER(PikaObj* self, VMState* vs, char* data) { + vs->try_error_code = fast_atoi(data); + return NULL; +} + static Arg* VM_instruction_handler_JEZ(PikaObj* self, VMState* vs, char* data) { int thisBlockDeepth; thisBlockDeepth = VMState_getBlockDeepthNow(vs); @@ -768,7 +823,7 @@ static Arg* VM_instruction_handler_OPT(PikaObj* self, VMState* vs, char* data) { } if (strEqu("/", data)) { if (0 == num2_f) { - VMState_setErrorCode(vs, 1); + VMState_setErrorCode(vs, PIKA_RES_ERR_OPERATION_FAILED); args_setSysOut(vs->locals->list, "ZeroDivisionError: division by zero"); outArg = NULL; @@ -962,12 +1017,26 @@ static Arg* VM_instruction_handler_CLS(PikaObj* self, VMState* vs, char* data) { static Arg* VM_instruction_handler_RET(PikaObj* self, VMState* vs, char* data) { /* exit jmp signal */ - vs->jmp = -999; + vs->jmp = VM_JMP_EXIT; Arg* return_arg = stack_popArg(&(vs->stack)); method_returnArg(vs->locals->list, return_arg); return NULL; } +static Arg* VM_instruction_handler_RIS(PikaObj* self, VMState* vs, char* data) { + Arg* err_arg = stack_popArg(&(vs->stack)); + PIKA_RES err = arg_getInt(err_arg); + VMState_setErrorCode(vs, err); + arg_deinit(err_arg); + /* raise jmp */ + if (vs->try_state == TRY_STATE_TOP) { + vs->jmp = VM_JMP_RAISE; + } else if (vs->try_state == TRY_STATE_INNER) { + return VM_instruction_handler_RET(self, vs, data); + } + return NULL; +} + static Arg* VM_instruction_handler_NEL(PikaObj* self, VMState* vs, char* data) { int thisBlockDeepth = VMState_getBlockDeepthNow(vs); char __else[] = "__else0"; @@ -997,13 +1066,13 @@ static Arg* VM_instruction_handler_EST(PikaObj* self, VMState* vs, char* data) { static Arg* VM_instruction_handler_BRK(PikaObj* self, VMState* vs, char* data) { /* break jmp signal */ - vs->jmp = -998; + vs->jmp = VM_JMP_BREAK; return NULL; } static Arg* VM_instruction_handler_CTN(PikaObj* self, VMState* vs, char* data) { /* continue jmp signal */ - vs->jmp = -997; + vs->jmp = VM_JMP_CONTINUE; return NULL; } @@ -1043,7 +1112,7 @@ static Arg* VM_instruction_handler_IMP(PikaObj* self, VMState* vs, char* data) { if (0 == obj_importModule(self, data)) { return NULL; } - VMState_setErrorCode(vs, 3); + VMState_setErrorCode(vs, PIKA_RES_ERR_ARG_NO_FOUND); __platform_printf("ModuleNotFoundError: No module named '%s'\r\n", data); return NULL; } @@ -1075,20 +1144,25 @@ static int pikaVM_runInstructUnit(PikaObj* self, goto nextLine; nextLine: /* exit */ - if (-999 == vs->jmp) { + if (VM_JMP_EXIT == vs->jmp) { pc_next = -99999; goto exit; } /* break */ - if (-998 == vs->jmp) { + if (VM_JMP_BREAK == vs->jmp) { pc_next = vs->pc + VMState_getAddrOffsetOfBreak(vs); goto exit; } /* continue */ - if (-997 == vs->jmp) { + if (VM_JMP_CONTINUE == vs->jmp) { pc_next = vs->pc + VMState_getAddrOffsetOfContinue(vs); goto exit; } + /* raise */ + if (VM_JMP_RAISE == vs->jmp) { + pc_next = vs->pc + VMState_getAddrOffsetOfRaise(vs); + goto exit; + } /* static jmp */ if (vs->jmp != 0) { pc_next = vs->pc + VMState_getAddrOffsetFromJmp(vs); @@ -1520,7 +1594,8 @@ static VMParameters* __pikaVM_runByteCodeFrameWithState( VMParameters* locals, VMParameters* globals, ByteCodeFrame* bytecode_frame, - uint16_t pc) { + uint16_t pc, + TRY_STATE try_state) { int size = bytecode_frame->instruct_array.size; /* locals is the local scope */ VMState vs = { @@ -1529,8 +1604,10 @@ static VMParameters* __pikaVM_runByteCodeFrameWithState( .globals = globals, .jmp = 0, .pc = pc, - .error_code = 0, - .line_error_code = 0, + .error_code = PIKA_RES_OK, + .line_error_code = PIKA_RES_OK, + .try_error_code = PIKA_RES_OK, + .try_state = try_state, }; stack_init(&(vs.stack)); while (vs.pc < size) { @@ -1555,18 +1632,23 @@ static VMParameters* __pikaVM_runByteCodeFrameWithState( } head_ins_unit--; } + if (vs.try_state) { + vs.try_error_code = vs.error_code; + } /* print inses of a line */ - while (1) { - if (head_ins_unit != this_ins_unit) { - __platform_printf(" "); - } else { - __platform_printf(" -> "); - } - instructUnit_printWithConst(head_ins_unit, - &(bytecode_frame->const_pool)); - head_ins_unit++; - if (head_ins_unit > this_ins_unit) { - break; + if (!vs.try_state) { + while (1) { + if (head_ins_unit != this_ins_unit) { + __platform_printf(" "); + } else { + __platform_printf(" -> "); + } + instructUnit_printWithConst(head_ins_unit, + &(bytecode_frame->const_pool)); + head_ins_unit++; + if (head_ins_unit > this_ins_unit) { + break; + } } } __platform_error_handle(); @@ -1581,7 +1663,7 @@ static VMParameters* __pikaVM_runByteCodeFrameWithState( VMParameters* pikaVM_runByteCodeFrame(PikaObj* self, ByteCodeFrame* byteCode_frame) { return __pikaVM_runByteCodeFrameWithState(self, self, self, byteCode_frame, - 0); + 0, TRY_STATE_NONE); } char* constPool_getByOffset(ConstPool* self, uint16_t offset) { diff --git a/src/PikaVM.h b/src/PikaVM.h index 505557587..6b1aadeb3 100644 --- a/src/PikaVM.h +++ b/src/PikaVM.h @@ -38,6 +38,19 @@ enum Instruct { __INSTRCUTION_CNT, }; +typedef enum { + VM_JMP_EXIT = -999, + VM_JMP_CONTINUE = -997, + VM_JMP_BREAK = -998, + VM_JMP_RAISE = -996, +} VM_JMP; + +typedef enum { + TRY_STATE_NONE = 0, + TRY_STATE_TOP, + TRY_STATE_INNER, +} TRY_STATE; + typedef struct VMState VMState; struct VMState { VMParameters* locals; @@ -48,6 +61,8 @@ struct VMState { ByteCodeFrame* bytecode_frame; uint8_t error_code; uint8_t line_error_code; + uint8_t try_error_code; + TRY_STATE try_state; }; VMParameters* pikaVM_run(PikaObj* self, char* pyLine); diff --git a/src/__instruction_table.cfg b/src/__instruction_table.cfg index c72d64563..fb46098e3 100644 --- a/src/__instruction_table.cfg +++ b/src/__instruction_table.cfg @@ -30,26 +30,59 @@ //! just append ins to the end, insert ins would brake the pre-compiled //! bytecode. +/* none */ def_ins(NON) +/* get referance */ def_ins(REF) +/* run function */ def_ins(RUN) +/* string */ def_ins(STR) +/* output */ def_ins(OUT) +/* number */ def_ins(NUM) +/* jump */ def_ins(JMP) +/* jump qual zero */ def_ins(JEZ) +/* operator */ def_ins(OPT) +/* define */ def_ins(DEF) +/* return */ def_ins(RET) +/* not equal */ def_ins(NEL) +/* delete */ def_ins(DEL) +/* exist */ def_ins(EST) +/* break */ def_ins(BRK) +/* continue */ def_ins(CTN) +/* global */ def_ins(GLB) +/* run as */ def_ins(RAS) +/* new */ def_ins(NEW) +/* class */ def_ins(CLS) +/* bytes */ def_ins(BYT) +/* list */ def_ins(LST) +/* import */ def_ins(IMP) +/* try */ +def_ins(TRY) +/* not try */ +def_ins(NTR) +/* raise */ +def_ins(RIS) +/* get error code */ +def_ins(GER) +/* set error code */ +def_ins(SER)