mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
add support for try..finally
This commit is contained in:
parent
2e8448577d
commit
1eb3ba3077
@ -127,7 +127,7 @@ for a quick overview of the supported features.
|
|||||||
| F-String | `f'value is {x}'` | ✅ |
|
| F-String | `f'value is {x}'` | ✅ |
|
||||||
| Unpacking | `a, b = 1, 2` | ✅ |
|
| Unpacking | `a, b = 1, 2` | ✅ |
|
||||||
| Star Unpacking | `a, *b = [1, 2, 3]` | ✅ |
|
| Star Unpacking | `a, *b = [1, 2, 3]` | ✅ |
|
||||||
| Exception | `raise/try..catch` | ✅ |
|
| Exception | `raise/try..catch..finally` | ✅ |
|
||||||
| Dynamic Code | `eval()/exec()` | ✅ |
|
| Dynamic Code | `eval()/exec()` | ✅ |
|
||||||
| Reflection | `hasattr()/getattr()/setattr()` | ✅ |
|
| Reflection | `hasattr()/getattr()/setattr()` | ✅ |
|
||||||
| Import | `import/from..import` | ✅ |
|
| Import | `import/from..import` | ✅ |
|
||||||
|
@ -24,7 +24,7 @@ The features marked with `YES` are supported, and the features marked with `NO`
|
|||||||
| F-String | `f'value is {x}'` | YES |
|
| F-String | `f'value is {x}'` | YES |
|
||||||
| Unpacking | `a, b = 1, 2` | YES |
|
| Unpacking | `a, b = 1, 2` | YES |
|
||||||
| Star Unpacking | `a, *b = [1, 2, 3]` | YES |
|
| Star Unpacking | `a, *b = [1, 2, 3]` | YES |
|
||||||
| Exception | `raise/try..catch` | YES |
|
| Exception | `raise/try..catch..finally` | YES |
|
||||||
| Dynamic Code | `eval()/exec()` | YES |
|
| Dynamic Code | `eval()/exec()` | YES |
|
||||||
| Reflection | `hasattr()/getattr()/setattr()` | YES |
|
| Reflection | `hasattr()/getattr()/setattr()` | YES |
|
||||||
| Import | `import/from..import` | YES |
|
| Import | `import/from..import` | YES |
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
#define PK_VERSION "1.3.6"
|
#define PK_VERSION "1.3.7"
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "export.h"
|
#include "export.h"
|
||||||
|
@ -82,6 +82,7 @@ OPCODE(IS_OP)
|
|||||||
OPCODE(CONTAINS_OP)
|
OPCODE(CONTAINS_OP)
|
||||||
/**************************/
|
/**************************/
|
||||||
OPCODE(JUMP_ABSOLUTE)
|
OPCODE(JUMP_ABSOLUTE)
|
||||||
|
OPCODE(JUMP_ABSOLUTE_TOP)
|
||||||
OPCODE(POP_JUMP_IF_FALSE)
|
OPCODE(POP_JUMP_IF_FALSE)
|
||||||
OPCODE(POP_JUMP_IF_TRUE)
|
OPCODE(POP_JUMP_IF_TRUE)
|
||||||
OPCODE(JUMP_IF_TRUE_OR_POP)
|
OPCODE(JUMP_IF_TRUE_OR_POP)
|
||||||
|
@ -533,6 +533,9 @@ __NEXT_STEP:;
|
|||||||
TARGET(JUMP_ABSOLUTE)
|
TARGET(JUMP_ABSOLUTE)
|
||||||
frame->jump_abs(byte.arg);
|
frame->jump_abs(byte.arg);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
TARGET(JUMP_ABSOLUTE_TOP)
|
||||||
|
frame->jump_abs(_CAST(uint16_t, POPX()));
|
||||||
|
DISPATCH();
|
||||||
TARGET(POP_JUMP_IF_FALSE){
|
TARGET(POP_JUMP_IF_FALSE){
|
||||||
PyObject* _0 = POPX();
|
PyObject* _0 = POPX();
|
||||||
if(_0==False || !py_bool(_0)) frame->jump_abs(byte.arg);
|
if(_0==False || !py_bool(_0)) frame->jump_abs(byte.arg);
|
||||||
@ -843,8 +846,8 @@ __NEXT_STEP:;
|
|||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
|
|
||||||
#if !PK_ENABLE_COMPUTED_GOTO
|
#if !PK_ENABLE_COMPUTED_GOTO
|
||||||
static_assert(OP_DEC_GLOBAL == 111);
|
static_assert(OP_DEC_GLOBAL == 112);
|
||||||
case 112: case 113: case 114: case 115: case 116: case 117: case 118: case 119: case 120: case 121: case 122: case 123: case 124: case 125: case 126: case 127: case 128: case 129: case 130: case 131: case 132: case 133: case 134: case 135: case 136: case 137: case 138: case 139: case 140: case 141: case 142: case 143: case 144: case 145: case 146: case 147: case 148: case 149: case 150: case 151: case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159: case 160: case 161: case 162: case 163: case 164: case 165: case 166: case 167: case 168: case 169: case 170: case 171: case 172: case 173: case 174: case 175: case 176: case 177: case 178: case 179: case 180: case 181: case 182: case 183: case 184: case 185: case 186: case 187: case 188: case 189: case 190: case 191: case 192: case 193: case 194: case 195: case 196: case 197: case 198: case 199: case 200: case 201: case 202: case 203: case 204: case 205: case 206: case 207: case 208: case 209: case 210: case 211: case 212: case 213: case 214: case 215: case 216: case 217: case 218: case 219: case 220: case 221: case 222: case 223: case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: case 255: PK_UNREACHABLE() break;
|
case 113: case 114: case 115: case 116: case 117: case 118: case 119: case 120: case 121: case 122: case 123: case 124: case 125: case 126: case 127: case 128: case 129: case 130: case 131: case 132: case 133: case 134: case 135: case 136: case 137: case 138: case 139: case 140: case 141: case 142: case 143: case 144: case 145: case 146: case 147: case 148: case 149: case 150: case 151: case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159: case 160: case 161: case 162: case 163: case 164: case 165: case 166: case 167: case 168: case 169: case 170: case 171: case 172: case 173: case 174: case 175: case 176: case 177: case 178: case 179: case 180: case 181: case 182: case 183: case 184: case 185: case 186: case 187: case 188: case 189: case 190: case 191: case 192: case 193: case 194: case 195: case 196: case 197: case 198: case 199: case 200: case 201: case 202: case 203: case 204: case 205: case 206: case 207: case 208: case 209: case 210: case 211: case 212: case 213: case 214: case 215: case 216: case 217: case 218: case 219: case 220: case 221: case 222: case 223: case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: case 255: PK_UNREACHABLE() break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -673,34 +673,56 @@ __EAT_DOTS_END:
|
|||||||
ctx()->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE)
|
ctx()->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE)
|
||||||
};
|
};
|
||||||
ctx()->exit_block();
|
ctx()->exit_block();
|
||||||
do {
|
|
||||||
StrName as_name;
|
int finally_entry = -1;
|
||||||
consume(TK("except"));
|
if(curr().type != TK("finally")){
|
||||||
if(is_expression()){
|
do {
|
||||||
EXPR(false); // push assumed type on to the stack
|
StrName as_name;
|
||||||
ctx()->emit_(OP_EXCEPTION_MATCH, BC_NOARG, prev().line);
|
consume(TK("except"));
|
||||||
if(match(TK("as"))){
|
if(is_expression()){
|
||||||
consume(TK("@id"));
|
EXPR(false); // push assumed type on to the stack
|
||||||
as_name = StrName(prev().sv());
|
ctx()->emit_(OP_EXCEPTION_MATCH, BC_NOARG, prev().line);
|
||||||
|
if(match(TK("as"))){
|
||||||
|
consume(TK("@id"));
|
||||||
|
as_name = StrName(prev().sv());
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
ctx()->emit_(OP_LOAD_TRUE, BC_NOARG, BC_KEEPLINE);
|
||||||
}
|
}
|
||||||
}else{
|
int patch = ctx()->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
|
||||||
ctx()->emit_(OP_LOAD_TRUE, BC_NOARG, BC_KEEPLINE);
|
// on match
|
||||||
}
|
if(!as_name.empty()){
|
||||||
int patch = ctx()->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit_(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
|
||||||
// on match
|
ctx()->emit_store_name(name_scope(), as_name, BC_KEEPLINE);
|
||||||
if(!as_name.empty()){
|
}
|
||||||
ctx()->emit_(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
|
// pop the exception
|
||||||
ctx()->emit_store_name(name_scope(), as_name, BC_KEEPLINE);
|
ctx()->emit_(OP_POP_EXCEPTION, BC_NOARG, BC_KEEPLINE);
|
||||||
}
|
compile_block_body();
|
||||||
// pop the exception
|
patches.push_back(ctx()->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE));
|
||||||
ctx()->emit_(OP_POP_EXCEPTION, BC_NOARG, BC_KEEPLINE);
|
ctx()->patch_jump(patch);
|
||||||
|
}while(curr().type == TK("except"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(match(TK("finally"))){
|
||||||
|
int patch = ctx()->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE);
|
||||||
|
finally_entry = ctx()->co->codes.size();
|
||||||
compile_block_body();
|
compile_block_body();
|
||||||
patches.push_back(ctx()->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE));
|
ctx()->emit_(OP_JUMP_ABSOLUTE_TOP, BC_NOARG, BC_KEEPLINE);
|
||||||
ctx()->patch_jump(patch);
|
ctx()->patch_jump(patch);
|
||||||
}while(curr().type == TK("except"));
|
}
|
||||||
// no match, re-raise
|
// no match, re-raise
|
||||||
|
if(finally_entry != -1){
|
||||||
|
ctx()->emit_(OP_LOAD_INTEGER, (uint16_t)ctx()->co->codes.size()+2, BC_KEEPLINE);
|
||||||
|
ctx()->emit_(OP_JUMP_ABSOLUTE, finally_entry, BC_KEEPLINE);
|
||||||
|
}
|
||||||
ctx()->emit_(OP_RE_RAISE, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit_(OP_RE_RAISE, BC_NOARG, BC_KEEPLINE);
|
||||||
|
|
||||||
|
// no exception or no match, jump to the end
|
||||||
for (int patch : patches) ctx()->patch_jump(patch);
|
for (int patch : patches) ctx()->patch_jump(patch);
|
||||||
|
if(finally_entry != -1){
|
||||||
|
ctx()->emit_(OP_LOAD_INTEGER, (uint16_t)ctx()->co->codes.size()+2, BC_KEEPLINE);
|
||||||
|
ctx()->emit_(OP_JUMP_ABSOLUTE, finally_entry, BC_KEEPLINE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::compile_decorated(){
|
void Compiler::compile_decorated(){
|
||||||
|
@ -584,7 +584,7 @@ static std::string _opcode_argstr(VM* vm, Bytecode byte, const CodeObject* co){
|
|||||||
break;
|
break;
|
||||||
case OP_LOAD_NAME: case OP_LOAD_GLOBAL: case OP_LOAD_NONLOCAL: case OP_STORE_GLOBAL:
|
case OP_LOAD_NAME: case OP_LOAD_GLOBAL: case OP_LOAD_NONLOCAL: case OP_STORE_GLOBAL:
|
||||||
case OP_LOAD_ATTR: case OP_LOAD_METHOD: case OP_STORE_ATTR: case OP_DELETE_ATTR:
|
case OP_LOAD_ATTR: case OP_LOAD_METHOD: case OP_STORE_ATTR: case OP_DELETE_ATTR:
|
||||||
case OP_BEGIN_CLASS: case OP_RAISE: case OP_GOTO:
|
case OP_BEGIN_CLASS: case OP_GOTO:
|
||||||
case OP_DELETE_GLOBAL: case OP_INC_GLOBAL: case OP_DEC_GLOBAL: case OP_STORE_CLASS_ATTR:
|
case OP_DELETE_GLOBAL: case OP_INC_GLOBAL: case OP_DEC_GLOBAL: case OP_STORE_CLASS_ATTR:
|
||||||
argStr += fmt(" (", StrName(byte.arg).sv(), ")").sv();
|
argStr += fmt(" (", StrName(byte.arg).sv(), ")").sv();
|
||||||
break;
|
break;
|
||||||
|
@ -122,3 +122,65 @@ except SyntaxError as e:
|
|||||||
assert type(e) is SyntaxError
|
assert type(e) is SyntaxError
|
||||||
ok = True
|
ok = True
|
||||||
assert ok
|
assert ok
|
||||||
|
|
||||||
|
# finally, only
|
||||||
|
def finally_only():
|
||||||
|
try:
|
||||||
|
raise KeyError
|
||||||
|
finally:
|
||||||
|
return True
|
||||||
|
|
||||||
|
assert finally_only() is True
|
||||||
|
|
||||||
|
def finally_only_2():
|
||||||
|
try:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
return True
|
||||||
|
|
||||||
|
assert finally_only_2() is True
|
||||||
|
|
||||||
|
# finally, no exception
|
||||||
|
def finally_no_exception():
|
||||||
|
ok = False
|
||||||
|
try:
|
||||||
|
pass
|
||||||
|
except KeyError:
|
||||||
|
exit(1)
|
||||||
|
finally:
|
||||||
|
ok = True
|
||||||
|
return ok
|
||||||
|
|
||||||
|
assert finally_no_exception()
|
||||||
|
|
||||||
|
# finally, match
|
||||||
|
def finally_match():
|
||||||
|
ok = False
|
||||||
|
try:
|
||||||
|
raise KeyError
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
ok = True
|
||||||
|
return ok
|
||||||
|
|
||||||
|
assert finally_match()
|
||||||
|
|
||||||
|
# finally, no match
|
||||||
|
ok = False
|
||||||
|
def finally_no_match():
|
||||||
|
global ok
|
||||||
|
try:
|
||||||
|
raise KeyError
|
||||||
|
except IndexError:
|
||||||
|
exit(1)
|
||||||
|
finally:
|
||||||
|
ok = True
|
||||||
|
|
||||||
|
try:
|
||||||
|
finally_no_match()
|
||||||
|
except KeyError:
|
||||||
|
assert ok
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
exit(1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user