mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
up
This commit is contained in:
parent
ef36a1d3a0
commit
981fcbc8e5
@ -201,7 +201,7 @@ class dict:
|
||||
def __getitem__(self, key):
|
||||
ok, i = self.__probe(key)
|
||||
if not ok:
|
||||
raise KeyError(key)
|
||||
raise KeyError(repr(key))
|
||||
return self._a[i][1]
|
||||
|
||||
def __contains__(self, key):
|
||||
@ -222,7 +222,7 @@ class dict:
|
||||
def __delitem__(self, key):
|
||||
ok, i = self.__probe(key)
|
||||
if not ok:
|
||||
raise KeyError(key)
|
||||
raise KeyError(repr(key))
|
||||
self._a[i] = None
|
||||
self._len -= 1
|
||||
|
||||
|
@ -204,6 +204,17 @@ public:
|
||||
}
|
||||
|
||||
inline int stack_size() const{ return s_data.size(); }
|
||||
_Str stack_info(){
|
||||
_StrStream ss;
|
||||
ss << "[";
|
||||
for(int i=0; i<s_data.size(); i++){
|
||||
ss << UNION_TP_NAME(s_data[i]);
|
||||
if(i != s_data.size()-1) ss << ", ";
|
||||
}
|
||||
ss << "]";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
inline bool has_next_bytecode() const{ return next_ip < code->co_code.size(); }
|
||||
|
||||
inline PyVar pop(){
|
||||
@ -247,7 +258,7 @@ public:
|
||||
inline void push(T&& obj){ s_data.push_back(std::forward<T>(obj)); }
|
||||
|
||||
inline void jump_abs(int i){ next_ip = i; }
|
||||
inline void jump_rel(int i){ next_ip = ip + i; }
|
||||
inline void jump_rel(int i){ next_ip += i; }
|
||||
|
||||
std::stack<std::pair<int, std::vector<PyVar>>> s_try_block;
|
||||
|
||||
@ -259,10 +270,14 @@ public:
|
||||
s_try_block.pop();
|
||||
}
|
||||
|
||||
inline int get_ip() const{ return ip; }
|
||||
|
||||
bool jump_to_exception_handler(){
|
||||
if(s_try_block.empty()) return false;
|
||||
PyVar obj = pop();
|
||||
auto& p = s_try_block.top();
|
||||
s_data = std::move(p.second);
|
||||
s_data.push_back(obj);
|
||||
next_ip = code->co_blocks[p.first].end;
|
||||
on_try_block_exit();
|
||||
return true;
|
||||
|
@ -910,8 +910,8 @@ __LISTCOMP:
|
||||
// If last op is not an assignment, pop the result.
|
||||
uint8_t lastOp = co()->co_code.back().op;
|
||||
if( lastOp!=OP_STORE_NAME && lastOp!=OP_STORE_REF){
|
||||
if(mode()==SINGLE_MODE && parser->indents.top()==0) emit(OP_PRINT_EXPR);
|
||||
emit(OP_POP_TOP);
|
||||
if(mode()==SINGLE_MODE && parser->indents.top()==0) emit(OP_PRINT_EXPR, -1, true);
|
||||
emit(OP_POP_TOP, -1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
26
src/error.h
26
src/error.h
@ -8,11 +8,7 @@ struct NeedMoreLines {
|
||||
};
|
||||
|
||||
struct HandledException {};
|
||||
|
||||
struct UnhandledException {
|
||||
PyVar obj;
|
||||
UnhandledException(PyVar obj) : obj(obj) {}
|
||||
};
|
||||
struct UnhandledException {};
|
||||
|
||||
enum CompileMode {
|
||||
EXEC_MODE,
|
||||
@ -73,32 +69,26 @@ struct SourceMetadata {
|
||||
|
||||
typedef pkpy::shared_ptr<SourceMetadata> _Source;
|
||||
|
||||
class _Exception : public std::exception {
|
||||
class _Exception {
|
||||
_Str type;
|
||||
_Str msg;
|
||||
bool is_runtime_error;
|
||||
bool is_re;
|
||||
std::stack<_Str> stacktrace;
|
||||
|
||||
mutable _Str _what_cached;
|
||||
public:
|
||||
_Exception(_Str type, _Str msg, bool is_runtime_error): type(type), msg(msg), is_runtime_error(is_runtime_error) {}
|
||||
|
||||
bool match_type(const _Str& type) const {
|
||||
return this->type == type;
|
||||
}
|
||||
_Exception(_Str type, _Str msg, bool is_re): type(type), msg(msg), is_re(is_re) {}
|
||||
bool match_type(const _Str& type) const { return this->type == type;}
|
||||
|
||||
void st_push(_Str snapshot){
|
||||
if(stacktrace.size() >= 8) return;
|
||||
stacktrace.push(snapshot);
|
||||
}
|
||||
|
||||
const char* what() const noexcept override {
|
||||
_Str summary() const {
|
||||
std::stack<_Str> st(stacktrace);
|
||||
_StrStream ss;
|
||||
if(is_runtime_error) ss << "Traceback (most recent call last):\n";
|
||||
if(is_re) ss << "Traceback (most recent call last):\n";
|
||||
while(!st.empty()) { ss << st.top() << '\n'; st.pop(); }
|
||||
ss << type << ": " << msg;
|
||||
_what_cached = ss.str();
|
||||
return _what_cached.c_str();
|
||||
return ss.str();
|
||||
}
|
||||
};
|
@ -6,14 +6,7 @@
|
||||
|
||||
_Code VM::compile(_Str source, _Str filename, CompileMode mode) {
|
||||
Compiler compiler(this, source.c_str(), filename, mode);
|
||||
try{
|
||||
return compiler.__fillCode();
|
||||
}catch(_Exception& e){
|
||||
throw e;
|
||||
}catch(std::exception& e){
|
||||
compiler.__throw_e("UnexpectedError", e.what());
|
||||
return nullptr;
|
||||
}
|
||||
return compiler.__fillCode();
|
||||
}
|
||||
|
||||
#define BIND_NUM_ARITH_OPT(name, op) \
|
||||
@ -136,6 +129,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
|
||||
_vm->bindMethod<1>("object", "__eq__", CPP_LAMBDA(vm->PyBool(args[0] == args[1])));
|
||||
_vm->bindMethod<1>("object", "__ne__", CPP_LAMBDA(vm->PyBool(args[0] != args[1])));
|
||||
|
||||
_vm->bindStaticMethod<1>("type", "__new__", CPP_LAMBDA(args[0]->_type));
|
||||
|
||||
_vm->bindStaticMethod<-1>("range", "__new__", [](VM* vm, const pkpy::Args& args) {
|
||||
|
56
src/vm.h
56
src/vm.h
@ -29,8 +29,9 @@ protected:
|
||||
PyVar run_frame(Frame* frame){
|
||||
while(frame->has_next_bytecode()){
|
||||
const Bytecode& byte = frame->next_bytecode();
|
||||
//printf("[%d] %s (%d)\n", frame->stack_size(), OP_NAMES[byte.op], byte.arg);
|
||||
//printf("%s\n", frame->code->src->getLine(byte.line).c_str());
|
||||
// if(frame->_module != builtins){
|
||||
// printf("%d: %s (%d) %s\n", frame->get_ip(), OP_NAMES[byte.op], byte.arg, frame->stack_info().c_str());
|
||||
// }
|
||||
switch (byte.op)
|
||||
{
|
||||
case OP_NO_OP: break; // do nothing
|
||||
@ -530,16 +531,13 @@ public:
|
||||
_Code code = compile(source, filename, mode);
|
||||
return _exec(code, _module, pkpy::make_shared<PyVarDict>());
|
||||
}catch (const _Exception& e){
|
||||
*_stderr << e.what() << '\n';
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
auto re = _Exception("UnexpectedError", e.what(), false);
|
||||
while (!callstack.empty()){
|
||||
re.st_push(callstack.back()->curr_snapshot());
|
||||
callstack.pop_back();
|
||||
}
|
||||
*_stderr << re.what() << '\n';
|
||||
*_stderr << e.summary() << '\n';
|
||||
}
|
||||
// catch (const std::exception& e) {
|
||||
// *_stderr << "A std::exception occurred! It may be a bug, please report it!!\n";
|
||||
// *_stderr << e.what() << '\n';
|
||||
// }
|
||||
callstack.clear();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -564,34 +562,35 @@ public:
|
||||
try{
|
||||
if(need_raise){ need_raise = false; _raise(); }
|
||||
ret = run_frame(frame);
|
||||
|
||||
if(ret != __py2py_call_signal){
|
||||
if(frame->id() == base_id){ // [ frameBase<- ]
|
||||
break;
|
||||
}else{
|
||||
callstack.pop_back();
|
||||
frame = callstack.back().get();
|
||||
frame->push(ret);
|
||||
}
|
||||
}else{
|
||||
frame = callstack.back().get(); // [ frameBase, newFrame<- ]
|
||||
}
|
||||
}catch(HandledException& e){
|
||||
continue;
|
||||
}catch(UnhandledException& e){
|
||||
_Exception& _e = UNION_GET(_Exception, e.obj);
|
||||
PyVar obj = frame->pop();
|
||||
_Exception& _e = PyException_AS_C(obj);
|
||||
_e.st_push(frame->curr_snapshot());
|
||||
callstack.pop_back();
|
||||
|
||||
if(!callstack.empty()){
|
||||
frame = callstack.back().get();
|
||||
if(frame->id() < base_id) throw e;
|
||||
frame->push(ret);
|
||||
frame->push(obj);
|
||||
need_raise = true;
|
||||
continue;
|
||||
}
|
||||
throw _e;
|
||||
}
|
||||
|
||||
if(ret != __py2py_call_signal){
|
||||
if(frame->id() == base_id){ // [ frameBase<- ]
|
||||
break;
|
||||
}else{
|
||||
callstack.pop_back();
|
||||
frame = callstack.back().get();
|
||||
frame->push(ret);
|
||||
}
|
||||
}else{
|
||||
frame = callstack.back().get(); // [ frameBase, newFrame<- ]
|
||||
}
|
||||
}
|
||||
|
||||
callstack.pop_back();
|
||||
@ -778,7 +777,7 @@ public:
|
||||
if(byte.op == OP_LOAD_CONST){
|
||||
argStr += " (" + PyStr_AS_C(asRepr(code->co_consts[byte.arg])) + ")";
|
||||
}
|
||||
if(byte.op == OP_LOAD_NAME_REF || byte.op == OP_LOAD_NAME){
|
||||
if(byte.op == OP_LOAD_NAME_REF || byte.op == OP_LOAD_NAME || byte.op == OP_RAISE){
|
||||
argStr += " (" + code->co_names[byte.arg].first.__escape(true) + ")";
|
||||
}
|
||||
ss << pad(argStr, 20); // may overflow
|
||||
@ -879,6 +878,7 @@ public:
|
||||
this->False = new_object(_tp_bool, false);
|
||||
this->builtins = new_module("builtins");
|
||||
this->_main = new_module("__main__");
|
||||
this->__py2py_call_signal = new_object(new_type_object("_signal"), DUMMY_VAL);
|
||||
|
||||
setattr(_tp_type, __base__, _tp_object);
|
||||
_tp_type->_type = _tp_type;
|
||||
@ -889,8 +889,6 @@ public:
|
||||
setattr(type, __name__, PyStr(name));
|
||||
}
|
||||
|
||||
this->__py2py_call_signal = new_object(_tp_object, DUMMY_VAL);
|
||||
|
||||
std::vector<_Str> publicTypes = {"type", "object", "bool", "int", "float", "str", "list", "tuple", "range"};
|
||||
for (auto& name : publicTypes) {
|
||||
setattr(builtins, name, _types[name]);
|
||||
@ -929,7 +927,7 @@ private:
|
||||
void _raise(){
|
||||
bool ok = top_frame()->jump_to_exception_handler();
|
||||
if(ok) throw HandledException();
|
||||
throw UnhandledException(top_frame()->top());
|
||||
else throw UnhandledException();
|
||||
}
|
||||
|
||||
public:
|
||||
|
14
tests/_exception.py
Normal file
14
tests/_exception.py
Normal file
@ -0,0 +1,14 @@
|
||||
try:
|
||||
raise KeyError
|
||||
except:
|
||||
print("exception caught")
|
||||
print(123)
|
||||
|
||||
def f():
|
||||
try:
|
||||
raise KeyError('foo')
|
||||
except A: # will fail to catch
|
||||
print("exception caught")
|
||||
print(123)
|
||||
|
||||
f()
|
Loading…
x
Reference in New Issue
Block a user