support find ins unit by bytecode frame

This commit is contained in:
lyon 2023-05-20 17:40:51 +08:00
parent 0ff4ecd028
commit e81fbcc0f7
3 changed files with 138 additions and 25 deletions

View File

@ -1733,32 +1733,57 @@ static Arg* VM_instruction_handler_RET(PikaObj* self,
return NULL; return NULL;
} }
static InstructUnit* _find_ins_unit_up(ByteCodeFrame* bcframe,
int32_t pc_start,
enum InstructIndex index,
int32_t* p_offset) {
/* find super class */
int instructArray_size = instructArray_getSize(&(bcframe->instruct_array));
while (1) {
*p_offset -= instructUnit_getSize();
if (pc_start + *p_offset >= instructArray_size) {
return 0;
}
InstructUnit* unit = instructArray_getByOffset(
&(bcframe->instruct_array), pc_start + *p_offset);
if (CLS == instructUnit_getInstructIndex(unit)) {
return unit;
}
}
return NULL;
}
static InstructUnit* _find_ins_unit_down(ByteCodeFrame* bcframe,
int32_t pc_start,
enum InstructIndex index,
int32_t* p_offset) {
/* find super class */
int instructArray_size = instructArray_getSize(&(bcframe->instruct_array));
while (1) {
*p_offset += instructUnit_getSize();
if (pc_start + *p_offset >= instructArray_size) {
return 0;
}
InstructUnit* unit = instructArray_getByOffset(
&(bcframe->instruct_array), pc_start + *p_offset);
if (index == instructUnit_getInstructIndex(unit)) {
return unit;
}
}
return NULL;
}
#if !PIKA_NANO_ENABLE #if !PIKA_NANO_ENABLE
static char* _find_super_class_name(VMState* vm) { static char* _find_super_class_name(ByteCodeFrame* bcframe, int32_t pc_start) {
/* find super class */ /* find super class */
int offset = 0; int offset = 0;
char* super_class_name = NULL; char* super_class_name = NULL;
while (1) { _find_ins_unit_up(bcframe, pc_start, CLS, &offset);
offset -= instructUnit_getSize(); InstructUnit* unit_run =
if (vm->pc + offset >= (int)VMState_getInstructArraySize(vm)) { _find_ins_unit_down(bcframe, pc_start, RUN, &offset);
return 0; super_class_name = constPool_getByOffset(
} &(bcframe->const_pool), instructUnit_getConstPoolIndex(unit_run));
if ((CLS == VMstate_getInstructWithOffset(vm, offset))) { return super_class_name;
break;
}
}
while (1) {
offset += instructUnit_getSize();
if (vm->pc + offset >= (int)VMState_getInstructArraySize(vm)) {
return 0;
}
if ((RUN == instructUnit_getInstructIndex(
VMState_getInstructUnitWithOffset(vm, offset)))) {
super_class_name = VMState_getConstWithOffset(vm, offset);
return super_class_name;
}
}
} }
#endif #endif
@ -1841,7 +1866,7 @@ static Arg* VM_instruction_handler_RUN(PikaObj* self,
#if !PIKA_NANO_ENABLE #if !PIKA_NANO_ENABLE
/* support for super() */ /* support for super() */
if (strEqu(sRunPath, "super")) { if (strEqu(sRunPath, "super")) {
sRunPath = _find_super_class_name(vm); sRunPath = _find_super_class_name(vm->bytecode_frame, vm->pc);
sArgName = strPointToLastToken(sRunPath, '.'); sArgName = strPointToLastToken(sRunPath, '.');
vm->in_super = PIKA_TRUE; vm->in_super = PIKA_TRUE;
vm->super_invoke_deepth = VMState_getInvokeDeepthNow(vm); vm->super_invoke_deepth = VMState_getInvokeDeepthNow(vm);

View File

@ -177,8 +177,7 @@ TEST(except, except_break) {
" print('in excepton')\n" " print('in excepton')\n"
" break\n" " break\n"
"print(sum)\n" "print(sum)\n"
"\n" "\n");
);
/* collect */ /* collect */
/* assert */ /* assert */
EXPECT_EQ(obj_getInt(pikaMain, "sum"), 6); EXPECT_EQ(obj_getInt(pikaMain, "sum"), 6);
@ -204,6 +203,10 @@ TEST(except, while_try_while) {
EXPECT_EQ(pikaMemNow(), 0); EXPECT_EQ(pikaMemNow(), 0);
} }
TEST_RUN_SINGLE_FILE(except,
try_while_return,
"test/python/except/try_while_return.py");
#endif #endif
TEST_END TEST_END

View File

@ -0,0 +1,85 @@
def try_while_return():
try:
i = 0
while i < 5:
i += 1
if i == 3:
return i
except Exception as e:
return "Error occurred: %s" % str(e)
def try_finally_while_return():
try:
i = 0
while i < 5:
i += 1
if i == 3:
return i
finally:
pass
def while_try_return():
i = 0
while i < 5:
try:
if i == 3:
return i
i += 1
except Exception as e:
return "Error occurred: %s" % str(e)
def while_try_finally_return():
i = 0
while i < 5:
try:
if i == 3:
return i
i += 1
finally:
pass
def try_except_return():
try:
raise ValueError("An error occurred")
except ValueError as e:
return "Caught an error: %s" % str(e)
def try_except_return_sinple():
try:
raise
except:
return "Caught an error"
def while_try_except_return():
i = 0
while i < 5:
try:
if i == 3:
raise ValueError("An error occurred at 3")
i += 1
except ValueError as e:
return "Caught an error: %s" % str(e)
def while_try_except_return_simple():
i = 0
while i < 5:
try:
if i == 3:
raise
i += 1
except:
return "Caught an error"
assert try_while_return() == 3
assert while_try_return() == 3
assert try_except_return_sinple() == "Caught an error"
assert while_try_except_return_simple() == "Caught an error"
# assert while_try_except_return() == "Caught an error: An error occurred at 3"
# assert try_except_return() == "Caught an error: An error occurred"
# assert try_finally_while_return() == 3
# assert while_try_finally_return() == 3