!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 <try:> parse
This commit is contained in:
李昂 2022-06-24 05:44:50 +00:00
parent 46fc722b47
commit 442e51e314
8 changed files with 369 additions and 58 deletions

View File

@ -11,7 +11,7 @@
"program": "${workspaceFolder}/build/test/pikascript_test", "program": "${workspaceFolder}/build/test/pikascript_test",
// "program": "${workspaceFolder}/build/boot/demo06-pikamain/pikascript_demo06-pikamain", // "program": "${workspaceFolder}/build/boot/demo06-pikamain/pikascript_demo06-pikamain",
"args": [ "args": [
// "--gtest_filter=class.class_par" "--gtest_filter=except.trydef1"
], ],
"stopAtEntry": false, "stopAtEntry": false,
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",

View File

@ -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);
}

View File

@ -3149,3 +3149,45 @@ TEST(parser, format2) {
EXPECT_EQ(pikaMemNow(), 0); EXPECT_EQ(pikaMemNow(), 0);
} }
#endif #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);
}

View File

@ -1501,9 +1501,6 @@ AST* AST_parseLine(char* line, Stack* block_stack) {
char* arg_in = strsPopToken(list_buffs, line_buff, ' '); char* arg_in = strsPopToken(list_buffs, line_buff, ' ');
obj_setStr(ast, "arg_in", arg_in); obj_setStr(ast, "arg_in", arg_in);
strsPopToken(list_buffs, line_buff, ' '); strsPopToken(list_buffs, line_buff, ' ');
if (strIsStartWith(line_buff, "range(")) {
obj_setInt(ast, "isRange", 1);
}
char* list_in = strsPopToken(list_buffs, line_buff, ':'); char* list_in = strsPopToken(list_buffs, line_buff, ':');
list_in = strsAppend(list_buffs, "iter(", list_in); list_in = strsAppend(list_buffs, "iter(", list_in);
list_in = strsAppend(list_buffs, list_in, ")"); list_in = strsAppend(list_buffs, list_in, ")");
@ -1529,6 +1526,31 @@ AST* AST_parseLine(char* line, Stack* block_stack) {
} }
goto block_matched; 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")) { if (strEqu(line_start, "return")) {
obj_setStr(ast, "return", ""); obj_setStr(ast, "return", "");
stmt = ""; stmt = "";
@ -1541,6 +1563,21 @@ AST* AST_parseLine(char* line, Stack* block_stack) {
obj_setStr(ast, "return", ""); obj_setStr(ast, "return", "");
goto block_matched; 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 ")) { if (strIsStartWith(line_start, "global ")) {
stmt = ""; stmt = "";
char* global_list = line_start + 7; 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); ASM_addBlockDeepth(ast, outBuffs, pikaAsm, block_type_num);
pikaAsm = strsAppend(outBuffs, pikaAsm, (char*)"0 JMP -1\n"); 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 */ /* goto the while start when exit while block */
if (strEqu(block_type, "for")) { if (strEqu(block_type, "for")) {
pikaAsm = pikaAsm =
@ -2093,6 +2143,12 @@ char* AST_toPikaASM(AST* ast, Args* outBuffs) {
pikaAsm = strsAppend(&buffs, pikaAsm, "0 NEL 1\n"); pikaAsm = strsAppend(&buffs, pikaAsm, "0 NEL 1\n");
goto exit; 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")) { if (strEqu(obj_getStr(ast, "block"), "elif")) {
/* skip if __else is 0 */ /* skip if __else is 0 */
pikaAsm = strsAppend(&buffs, pikaAsm, "0 NEL 1\n"); pikaAsm = strsAppend(&buffs, pikaAsm, "0 NEL 1\n");
@ -2158,6 +2214,15 @@ char* AST_toPikaASM(AST* ast, Args* outBuffs) {
is_block_matched = 1; is_block_matched = 1;
goto exit; 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")) { if (obj_isArgExist(ast, "global")) {
/* parse stmt ast */ /* parse stmt ast */
pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm); pikaAsm = AST_appandPikaASM(ast, ast, &buffs, pikaAsm);

View File

@ -65,23 +65,22 @@
#define __platform_printf(...) rt_kprintf(__VA_ARGS__) #define __platform_printf(...) rt_kprintf(__VA_ARGS__)
#endif #endif
/* clang-format off */
typedef enum { typedef enum {
PIKA_RES_ERR_ARG_NO_FOUND = -12, PIKA_RES_OK = 0,
PIKA_RES_ERR_UNKNOWN_INSTRUCTION = -11, PIKA_RES_ERR_RUNTIME_ERROR,
PIKA_RES_ERR_OUT_OF_RANGE = -10, PIKA_RES_ERR_ARG_NO_FOUND,
PIKA_RES_ERR_IO_ERROR = -9, PIKA_RES_ERR_UNKNOWN_INSTRUCTION,
PIKA_RES_ERR_INSUFFICIENT_RESOURCE = -8, PIKA_RES_ERR_OUT_OF_RANGE,
PIKA_RES_ERR_INVALID_PARAM = -7, PIKA_RES_ERR_IO_ERROR,
PIKA_RES_ERR_INVALID_PTR = -6, PIKA_RES_ERR_INSUFFICIENT_RESOURCE,
PIKA_RES_ERR_UNALIGNED_PTR = -5, PIKA_RES_ERR_INVALID_PARAM,
PIKA_RES_ERR_INVALID_VERSION_NUMBER = -4, PIKA_RES_ERR_INVALID_PTR,
PIKA_RES_ERR_ILLEGAL_MAGIC_CODE = -3, PIKA_RES_ERR_UNALIGNED_PTR,
PIKA_RES_ERR_OPERATION_FAILED = -2, PIKA_RES_ERR_INVALID_VERSION_NUMBER,
PIKA_RES_ERR_UNKNOWN = -1, PIKA_RES_ERR_ILLEGAL_MAGIC_CODE,
PIKA_RES_OK = 0, PIKA_RES_ERR_OPERATION_FAILED,
PIKA_RES_ERR_UNKNOWN,
} PIKA_RES; } PIKA_RES;
/* clang-format on*/
/* clang-format off */ /* clang-format off */

View File

@ -40,7 +40,8 @@ static VMParameters* __pikaVM_runByteCodeFrameWithState(
VMParameters* locals, VMParameters* locals,
VMParameters* globals, VMParameters* globals,
ByteCodeFrame* bytecode_frame, ByteCodeFrame* bytecode_frame,
uint16_t pc); uint16_t pc,
TRY_STATE is_in_try);
/* head declear end */ /* head declear end */
@ -71,7 +72,7 @@ static char* VMState_getConstWithInstructUnit(VMState* vs,
instructUnit_getConstPoolIndex(ins_unit)); instructUnit_getConstPoolIndex(ins_unit));
} }
static int32_t VMState_getAddrOffsetOfJUM(VMState* vs) { static int32_t VMState_getAddrOffsetOfJmpBack(VMState* vs) {
int offset = 0; int offset = 0;
InstructUnit* ins_unit_now = VMState_getInstructNow(vs); InstructUnit* ins_unit_now = VMState_getInstructNow(vs);
while (1) { while (1) {
@ -138,14 +139,29 @@ static int32_t VMState_getAddrOffsetFromJmp(VMState* vs) {
} }
static int32_t VMState_getAddrOffsetOfBreak(VMState* vs) { static int32_t VMState_getAddrOffsetOfBreak(VMState* vs) {
int32_t offset = VMState_getAddrOffsetOfJUM(vs); int32_t offset = VMState_getAddrOffsetOfJmpBack(vs);
/* byteCode */ /* byteCode */
offset += instructUnit_getSize(); offset += instructUnit_getSize();
return offset; 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) { static int32_t VMState_getAddrOffsetOfContinue(VMState* vs) {
int32_t offset = VMState_getAddrOffsetOfJUM(vs); int32_t offset = VMState_getAddrOffsetOfJmpBack(vs);
/* byteCode */ /* byteCode */
return offset; return offset;
} }
@ -156,6 +172,16 @@ static Arg* VM_instruction_handler_NON(PikaObj* self, VMState* vs, char* data) {
return NULL; 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) { static Arg* VM_instruction_handler_NEW(PikaObj* self, VMState* vs, char* data) {
Arg* origin_arg = obj_getArg(vs->locals, data); Arg* origin_arg = obj_getArg(vs->locals, data);
Arg* new_arg = arg_copy(origin_arg); 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")) { if (strEqu(data, (char*)"None")) {
return arg_setNull(NULL); return arg_setNull(NULL);
} }
if (strEqu(data, (char*)"RuntimeError")) {
return arg_setInt(NULL, "", PIKA_RES_ERR_RUNTIME_ERROR);
}
/* find in local list first */ /* find in local list first */
Arg* arg = arg_copy(obj_getArg(vs->locals, data)); Arg* arg = arg_copy(obj_getArg(vs->locals, data));
if (NULL == arg) { 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)); arg = arg_copy(obj_getArg(vs->globals, data));
} }
if (NULL == arg) { 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); __platform_printf("NameError: name '%s' is not defined\r\n", data);
} }
return arg; 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) { static int32_t __foreach_handler_deinitTuple(Arg* argEach, Args* context) {
if (arg_getType(argEach) == ARG_TYPE_TUPLE) { if (arg_getType(argEach) == ARG_TYPE_TUPLE) {
PikaTuple* tuple = arg_getPtr(argEach); PikaTuple* tuple = arg_getPtr(argEach);
@ -195,9 +230,10 @@ static int32_t __foreach_handler_deinitTuple(Arg* argEach, Args* context) {
return PIKA_RES_OK; return PIKA_RES_OK;
} }
Arg* obj_runMethodArg(PikaObj* self, Arg* __obj_runMethodArgWithState(PikaObj* self,
PikaObj* method_args_obj, PikaObj* method_args_obj,
Arg* method_arg) { Arg* method_arg,
TRY_STATE try_state) {
Arg* return_arg = NULL; Arg* return_arg = NULL;
/* get method Ptr */ /* get method Ptr */
Method method_ptr = methodArg_getPtr(method_arg); Method method_ptr = methodArg_getPtr(method_arg);
@ -213,7 +249,7 @@ Arg* obj_runMethodArg(PikaObj* self,
if (NULL != method_context) { if (NULL != method_context) {
self = method_context; self = method_context;
} }
obj_setErrorCode(self, 0); obj_setErrorCode(self, PIKA_RES_OK);
/* run method */ /* run method */
if (method_type == ARG_TYPE_METHOD_NATIVE) { if (method_type == ARG_TYPE_METHOD_NATIVE) {
@ -235,7 +271,7 @@ Arg* obj_runMethodArg(PikaObj* self,
&(method_bytecodeFrame->instruct_array), 0); &(method_bytecodeFrame->instruct_array), 0);
uint16_t pc = (uintptr_t)method_ptr - insturctArray_start; uint16_t pc = (uintptr_t)method_ptr - insturctArray_start;
method_args_obj = __pikaVM_runByteCodeFrameWithState( 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 */ /* get method return */
return_arg = return_arg =
@ -245,6 +281,13 @@ Arg* obj_runMethodArg(PikaObj* self,
return return_arg; 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, static int VMState_loadArgsFromMethodArg(VMState* vs,
PikaObj* method_host_obj, PikaObj* method_host_obj,
Args* args, Args* args,
@ -290,7 +333,7 @@ static int VMState_loadArgsFromMethodArg(VMState* vs,
} else { } else {
/* check arg num decleard and input */ /* check arg num decleard and input */
if (arg_num_dec != arg_num_input - arg_num_used) { if (arg_num_dec != arg_num_input - arg_num_used) {
VMState_setErrorCode(vs, 3); VMState_setErrorCode(vs, PIKA_RES_ERR_INVALID_PARAM);
__platform_printf( __platform_printf(
"TypeError: %s() takes %d positional argument but %d were " "TypeError: %s() takes %d positional argument but %d were "
"given\r\n", "given\r\n",
@ -419,6 +462,11 @@ static Arg* VM_instruction_handler_RUN(PikaObj* self, VMState* vs, char* data) {
Arg* method_arg = NULL; Arg* method_arg = NULL;
char* sys_out; char* sys_out;
int arg_num_used = 0; 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 */ /* return arg directly */
if (strEqu(data, "")) { if (strEqu(data, "")) {
return_arg = stack_popArg(&(vs->stack)); 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) { if (NULL == method_host_obj) {
/* error, not found object */ /* 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); __platform_printf("Error: method '%s' no found.\r\n", data);
goto exit; goto exit;
} }
@ -451,7 +499,7 @@ static Arg* VM_instruction_handler_RUN(PikaObj* self, VMState* vs, char* data) {
/* assert method*/ /* assert method*/
if (NULL == method_arg || ARG_TYPE_NONE == arg_getType(method_arg)) { if (NULL == method_arg || ARG_TYPE_NONE == arg_getType(method_arg)) {
/* error, method no found */ /* 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); __platform_printf("NameError: name '%s' is not defined\r\n", data);
goto exit; goto exit;
} }
@ -467,7 +515,8 @@ static Arg* VM_instruction_handler_RUN(PikaObj* self, VMState* vs, char* data) {
} }
/* run method arg */ /* 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__() */ /* __init__() */
if (ARG_TYPE_OBJECT_NEW == arg_getType(return_arg)) { 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) { if (vs->error_code != 0) {
goto init_exit; 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: init_exit:
if (NULL != return_arg_init) { if (NULL != return_arg_init) {
arg_deinit(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 */ /* transfer errCode */
if (0 != obj_getErrorCode(method_host_obj)) { if (0 != obj_getErrorCode(method_host_obj)) {
/* method error */ /* method error */
VMState_setErrorCode(vs, 6); VMState_setErrorCode(vs, PIKA_RES_ERR_RUNTIME_ERROR);
} }
goto exit; goto exit;
@ -643,6 +693,11 @@ static Arg* VM_instruction_handler_JMP(PikaObj* self, VMState* vs, char* data) {
return NULL; 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) { static Arg* VM_instruction_handler_JEZ(PikaObj* self, VMState* vs, char* data) {
int thisBlockDeepth; int thisBlockDeepth;
thisBlockDeepth = VMState_getBlockDeepthNow(vs); thisBlockDeepth = VMState_getBlockDeepthNow(vs);
@ -768,7 +823,7 @@ static Arg* VM_instruction_handler_OPT(PikaObj* self, VMState* vs, char* data) {
} }
if (strEqu("/", data)) { if (strEqu("/", data)) {
if (0 == num2_f) { if (0 == num2_f) {
VMState_setErrorCode(vs, 1); VMState_setErrorCode(vs, PIKA_RES_ERR_OPERATION_FAILED);
args_setSysOut(vs->locals->list, args_setSysOut(vs->locals->list,
"ZeroDivisionError: division by zero"); "ZeroDivisionError: division by zero");
outArg = NULL; 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) { static Arg* VM_instruction_handler_RET(PikaObj* self, VMState* vs, char* data) {
/* exit jmp signal */ /* exit jmp signal */
vs->jmp = -999; vs->jmp = VM_JMP_EXIT;
Arg* return_arg = stack_popArg(&(vs->stack)); Arg* return_arg = stack_popArg(&(vs->stack));
method_returnArg(vs->locals->list, return_arg); method_returnArg(vs->locals->list, return_arg);
return NULL; 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) { static Arg* VM_instruction_handler_NEL(PikaObj* self, VMState* vs, char* data) {
int thisBlockDeepth = VMState_getBlockDeepthNow(vs); int thisBlockDeepth = VMState_getBlockDeepthNow(vs);
char __else[] = "__else0"; 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) { static Arg* VM_instruction_handler_BRK(PikaObj* self, VMState* vs, char* data) {
/* break jmp signal */ /* break jmp signal */
vs->jmp = -998; vs->jmp = VM_JMP_BREAK;
return NULL; return NULL;
} }
static Arg* VM_instruction_handler_CTN(PikaObj* self, VMState* vs, char* data) { static Arg* VM_instruction_handler_CTN(PikaObj* self, VMState* vs, char* data) {
/* continue jmp signal */ /* continue jmp signal */
vs->jmp = -997; vs->jmp = VM_JMP_CONTINUE;
return NULL; return NULL;
} }
@ -1043,7 +1112,7 @@ static Arg* VM_instruction_handler_IMP(PikaObj* self, VMState* vs, char* data) {
if (0 == obj_importModule(self, data)) { if (0 == obj_importModule(self, data)) {
return NULL; 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); __platform_printf("ModuleNotFoundError: No module named '%s'\r\n", data);
return NULL; return NULL;
} }
@ -1075,20 +1144,25 @@ static int pikaVM_runInstructUnit(PikaObj* self,
goto nextLine; goto nextLine;
nextLine: nextLine:
/* exit */ /* exit */
if (-999 == vs->jmp) { if (VM_JMP_EXIT == vs->jmp) {
pc_next = -99999; pc_next = -99999;
goto exit; goto exit;
} }
/* break */ /* break */
if (-998 == vs->jmp) { if (VM_JMP_BREAK == vs->jmp) {
pc_next = vs->pc + VMState_getAddrOffsetOfBreak(vs); pc_next = vs->pc + VMState_getAddrOffsetOfBreak(vs);
goto exit; goto exit;
} }
/* continue */ /* continue */
if (-997 == vs->jmp) { if (VM_JMP_CONTINUE == vs->jmp) {
pc_next = vs->pc + VMState_getAddrOffsetOfContinue(vs); pc_next = vs->pc + VMState_getAddrOffsetOfContinue(vs);
goto exit; goto exit;
} }
/* raise */
if (VM_JMP_RAISE == vs->jmp) {
pc_next = vs->pc + VMState_getAddrOffsetOfRaise(vs);
goto exit;
}
/* static jmp */ /* static jmp */
if (vs->jmp != 0) { if (vs->jmp != 0) {
pc_next = vs->pc + VMState_getAddrOffsetFromJmp(vs); pc_next = vs->pc + VMState_getAddrOffsetFromJmp(vs);
@ -1520,7 +1594,8 @@ static VMParameters* __pikaVM_runByteCodeFrameWithState(
VMParameters* locals, VMParameters* locals,
VMParameters* globals, VMParameters* globals,
ByteCodeFrame* bytecode_frame, ByteCodeFrame* bytecode_frame,
uint16_t pc) { uint16_t pc,
TRY_STATE try_state) {
int size = bytecode_frame->instruct_array.size; int size = bytecode_frame->instruct_array.size;
/* locals is the local scope */ /* locals is the local scope */
VMState vs = { VMState vs = {
@ -1529,8 +1604,10 @@ static VMParameters* __pikaVM_runByteCodeFrameWithState(
.globals = globals, .globals = globals,
.jmp = 0, .jmp = 0,
.pc = pc, .pc = pc,
.error_code = 0, .error_code = PIKA_RES_OK,
.line_error_code = 0, .line_error_code = PIKA_RES_OK,
.try_error_code = PIKA_RES_OK,
.try_state = try_state,
}; };
stack_init(&(vs.stack)); stack_init(&(vs.stack));
while (vs.pc < size) { while (vs.pc < size) {
@ -1555,18 +1632,23 @@ static VMParameters* __pikaVM_runByteCodeFrameWithState(
} }
head_ins_unit--; head_ins_unit--;
} }
if (vs.try_state) {
vs.try_error_code = vs.error_code;
}
/* print inses of a line */ /* print inses of a line */
while (1) { if (!vs.try_state) {
if (head_ins_unit != this_ins_unit) { while (1) {
__platform_printf(" "); if (head_ins_unit != this_ins_unit) {
} else { __platform_printf(" ");
__platform_printf(" -> "); } else {
} __platform_printf(" -> ");
instructUnit_printWithConst(head_ins_unit, }
&(bytecode_frame->const_pool)); instructUnit_printWithConst(head_ins_unit,
head_ins_unit++; &(bytecode_frame->const_pool));
if (head_ins_unit > this_ins_unit) { head_ins_unit++;
break; if (head_ins_unit > this_ins_unit) {
break;
}
} }
} }
__platform_error_handle(); __platform_error_handle();
@ -1581,7 +1663,7 @@ static VMParameters* __pikaVM_runByteCodeFrameWithState(
VMParameters* pikaVM_runByteCodeFrame(PikaObj* self, VMParameters* pikaVM_runByteCodeFrame(PikaObj* self,
ByteCodeFrame* byteCode_frame) { ByteCodeFrame* byteCode_frame) {
return __pikaVM_runByteCodeFrameWithState(self, self, self, byteCode_frame, return __pikaVM_runByteCodeFrameWithState(self, self, self, byteCode_frame,
0); 0, TRY_STATE_NONE);
} }
char* constPool_getByOffset(ConstPool* self, uint16_t offset) { char* constPool_getByOffset(ConstPool* self, uint16_t offset) {

View File

@ -38,6 +38,19 @@ enum Instruct {
__INSTRCUTION_CNT, __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; typedef struct VMState VMState;
struct VMState { struct VMState {
VMParameters* locals; VMParameters* locals;
@ -48,6 +61,8 @@ struct VMState {
ByteCodeFrame* bytecode_frame; ByteCodeFrame* bytecode_frame;
uint8_t error_code; uint8_t error_code;
uint8_t line_error_code; uint8_t line_error_code;
uint8_t try_error_code;
TRY_STATE try_state;
}; };
VMParameters* pikaVM_run(PikaObj* self, char* pyLine); VMParameters* pikaVM_run(PikaObj* self, char* pyLine);

View File

@ -30,26 +30,59 @@
//! just append ins to the end, insert ins would brake the pre-compiled //! just append ins to the end, insert ins would brake the pre-compiled
//! bytecode. //! bytecode.
/* none */
def_ins(NON) def_ins(NON)
/* get referance */
def_ins(REF) def_ins(REF)
/* run function */
def_ins(RUN) def_ins(RUN)
/* string */
def_ins(STR) def_ins(STR)
/* output */
def_ins(OUT) def_ins(OUT)
/* number */
def_ins(NUM) def_ins(NUM)
/* jump */
def_ins(JMP) def_ins(JMP)
/* jump qual zero */
def_ins(JEZ) def_ins(JEZ)
/* operator */
def_ins(OPT) def_ins(OPT)
/* define */
def_ins(DEF) def_ins(DEF)
/* return */
def_ins(RET) def_ins(RET)
/* not equal */
def_ins(NEL) def_ins(NEL)
/* delete */
def_ins(DEL) def_ins(DEL)
/* exist */
def_ins(EST) def_ins(EST)
/* break */
def_ins(BRK) def_ins(BRK)
/* continue */
def_ins(CTN) def_ins(CTN)
/* global */
def_ins(GLB) def_ins(GLB)
/* run as */
def_ins(RAS) def_ins(RAS)
/* new */
def_ins(NEW) def_ins(NEW)
/* class */
def_ins(CLS) def_ins(CLS)
/* bytes */
def_ins(BYT) def_ins(BYT)
/* list */
def_ins(LST) def_ins(LST)
/* import */
def_ins(IMP) 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)