mirror of
				https://github.com/pocketpy/pocketpy
				synced 2025-11-04 02:30:17 +00:00 
			
		
		
		
	Compare commits
	
		
			No commits in common. "3e7ca3cddd32503225c2a968f6ed5cd4b846a80b" and "8de566f875733618be67b67c63975163b80f84e4" have entirely different histories.
		
	
	
		
			3e7ca3cddd
			...
			8de566f875
		
	
		
@ -44,7 +44,7 @@ typedef struct pk_VM {
 | 
				
			|||||||
    void (*_stderr)(const char*, ...);
 | 
					    void (*_stderr)(const char*, ...);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    py_TValue last_retval;
 | 
					    py_TValue last_retval;
 | 
				
			||||||
    py_TValue curr_exception;
 | 
					    py_TValue last_exception;
 | 
				
			||||||
    bool is_stopiteration;
 | 
					    bool is_stopiteration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    py_TValue reg[8];  // users' registers
 | 
					    py_TValue reg[8];  // users' registers
 | 
				
			||||||
 | 
				
			|||||||
@ -2,15 +2,38 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "pocketpy/common/str.h"
 | 
					#include "pocketpy/common/str.h"
 | 
				
			||||||
#include "pocketpy/common/strname.h"
 | 
					#include "pocketpy/common/strname.h"
 | 
				
			||||||
#include "pocketpy/objects/codeobject.h"
 | 
					 | 
				
			||||||
#include "pocketpy/objects/sourcedata.h"
 | 
					#include "pocketpy/objects/sourcedata.h"
 | 
				
			||||||
#include "pocketpy/objects/object.h"
 | 
					#include "pocketpy/objects/object.h"
 | 
				
			||||||
#include "pocketpy/pocketpy.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// typedef struct pkpy_ExceptionFrame {
 | 
				
			||||||
 | 
					//     pk_SourceData_ src;
 | 
				
			||||||
 | 
					//     int lineno;
 | 
				
			||||||
 | 
					//     const char* cursor;
 | 
				
			||||||
 | 
					//     c11_string* name;
 | 
				
			||||||
 | 
					// } pkpy_ExceptionFrame;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// typedef struct pkpy_Exception {
 | 
				
			||||||
 | 
					//     py_Name type;
 | 
				
			||||||
 | 
					//     c11_string* msg;
 | 
				
			||||||
 | 
					//     bool is_re;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//     int _ip_on_error;
 | 
				
			||||||
 | 
					//     void* _code_on_error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//     PyObject* self;  // weak reference
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//     c11_vector/*T=pkpy_ExceptionFrame*/ stacktrace;
 | 
				
			||||||
 | 
					// } pkpy_Exception;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// void pkpy_Exception__ctor(pkpy_Exception* self, py_Name type);
 | 
				
			||||||
 | 
					// void pkpy_Exception__dtor(pkpy_Exception* self);
 | 
				
			||||||
 | 
					// void pkpy_Exception__stpush(pkpy_Exception* self, pk_SourceData_ src, int lineno, const char* cursor, const char* name);
 | 
				
			||||||
 | 
					// py_Str pkpy_Exception__summary(pkpy_Exception* self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Error{
 | 
					struct Error{
 | 
				
			||||||
    const char* type;
 | 
					    const char* type;
 | 
				
			||||||
    pk_SourceData_ src;
 | 
					    pk_SourceData_ src;
 | 
				
			||||||
@ -20,10 +43,6 @@ struct Error{
 | 
				
			|||||||
    int64_t userdata;
 | 
					    int64_t userdata;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void py_BaseException__set_lineno(py_Ref, int lineno, const CodeObject* code);
 | 
					 | 
				
			||||||
int py_BaseException__get_lineno(py_Ref, const CodeObject* code);
 | 
					 | 
				
			||||||
void py_BaseException__stpush(py_Ref, pk_SourceData_ src, int lineno, const char* func_name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@ -241,15 +241,12 @@ py_TmpRef py_getmodule(const char* name);
 | 
				
			|||||||
bool py_import(const char* name);
 | 
					bool py_import(const char* name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/************* Errors *************/
 | 
					/************* Errors *************/
 | 
				
			||||||
/// Raise an exception by name and message. Always returns false.
 | 
					 | 
				
			||||||
bool py_exception(const char* name, const char* fmt, ...);
 | 
					bool py_exception(const char* name, const char* fmt, ...);
 | 
				
			||||||
/// Raise an expection object. Always returns false.
 | 
					 | 
				
			||||||
bool py_raise(py_Ref);
 | 
					 | 
				
			||||||
/// Print the last error to the console.
 | 
					/// Print the last error to the console.
 | 
				
			||||||
void py_printexc();
 | 
					void py_printexc();
 | 
				
			||||||
/// Format the last error to a string.
 | 
					/// Format the last error to a string.
 | 
				
			||||||
char* py_formatexc();
 | 
					void py_formatexc(char* out);
 | 
				
			||||||
/// Check if an exception is raised.
 | 
					/// Check if an error is set.
 | 
				
			||||||
bool py_checkexc();
 | 
					bool py_checkexc();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define NameError(n) py_exception("NameError", "name '%n' is not defined", (n))
 | 
					#define NameError(n) py_exception("NameError", "name '%n' is not defined", (n))
 | 
				
			||||||
 | 
				
			|||||||
@ -105,7 +105,6 @@ OPCODE(EXCEPTION_MATCH)
 | 
				
			|||||||
OPCODE(RAISE)
 | 
					OPCODE(RAISE)
 | 
				
			||||||
OPCODE(RAISE_ASSERT)
 | 
					OPCODE(RAISE_ASSERT)
 | 
				
			||||||
OPCODE(RE_RAISE)
 | 
					OPCODE(RE_RAISE)
 | 
				
			||||||
OPCODE(PUSH_EXCEPTION)
 | 
					 | 
				
			||||||
OPCODE(POP_EXCEPTION)
 | 
					OPCODE(POP_EXCEPTION)
 | 
				
			||||||
/**************************/
 | 
					/**************************/
 | 
				
			||||||
OPCODE(FSTRING_EVAL)
 | 
					OPCODE(FSTRING_EVAL)
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,6 @@
 | 
				
			|||||||
#include "pocketpy/common/config.h"
 | 
					#include "pocketpy/common/config.h"
 | 
				
			||||||
#include "pocketpy/common/memorypool.h"
 | 
					#include "pocketpy/common/memorypool.h"
 | 
				
			||||||
#include <ctype.h>
 | 
					#include <ctype.h>
 | 
				
			||||||
#include <stdbool.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* expr.h */
 | 
					/* expr.h */
 | 
				
			||||||
typedef struct Expr Expr;
 | 
					typedef struct Expr Expr;
 | 
				
			||||||
@ -2493,53 +2492,7 @@ __EAT_DOTS_END:
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static Error* compile_try_except(Compiler* self) {
 | 
					static Error* compile_try_except(Compiler* self) {
 | 
				
			||||||
    Error* err;
 | 
					    assert(false);
 | 
				
			||||||
    Ctx__enter_block(ctx(), CodeBlockType_TRY_EXCEPT);
 | 
					 | 
				
			||||||
    Ctx__emit_(ctx(), OP_TRY_ENTER, BC_NOARG, prev()->line);
 | 
					 | 
				
			||||||
    check(compile_block_body(self, compile_stmt));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    int patches[8];
 | 
					 | 
				
			||||||
    int patches_length = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    patches[patches_length++] = Ctx__emit_(ctx(), OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE);
 | 
					 | 
				
			||||||
    Ctx__exit_block(ctx());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(curr()->type == TK_FINALLY) { return SyntaxError("finally clause is not supported yet"); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    do {
 | 
					 | 
				
			||||||
        if(patches_length == 8) { return SyntaxError("maximum number of except clauses reached"); }
 | 
					 | 
				
			||||||
        py_Name as_name = 0;
 | 
					 | 
				
			||||||
        consume(TK_EXCEPT);
 | 
					 | 
				
			||||||
        if(is_expression(self, false)) {
 | 
					 | 
				
			||||||
            check(EXPR(self));  // push assumed type on to the stack
 | 
					 | 
				
			||||||
            Ctx__s_emit_top(ctx());
 | 
					 | 
				
			||||||
            Ctx__emit_(ctx(), OP_EXCEPTION_MATCH, BC_NOARG, prev()->line);
 | 
					 | 
				
			||||||
            if(match(TK_AS)) {
 | 
					 | 
				
			||||||
                consume(TK_ID);
 | 
					 | 
				
			||||||
                as_name = py_namev(Token__sv(prev()));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            Ctx__emit_(ctx(), OP_LOAD_TRUE, BC_NOARG, BC_KEEPLINE);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        int patch = Ctx__emit_(ctx(), OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
 | 
					 | 
				
			||||||
        // on match
 | 
					 | 
				
			||||||
        if(as_name) {
 | 
					 | 
				
			||||||
            Ctx__emit_(ctx(), OP_PUSH_EXCEPTION, BC_NOARG, BC_KEEPLINE);
 | 
					 | 
				
			||||||
            Ctx__emit_store_name(ctx(), name_scope(self), as_name, BC_KEEPLINE);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // pop the exception
 | 
					 | 
				
			||||||
        Ctx__emit_(ctx(), OP_POP_EXCEPTION, BC_NOARG, BC_KEEPLINE);
 | 
					 | 
				
			||||||
        check(compile_block_body(self, compile_stmt));
 | 
					 | 
				
			||||||
        patches[patches_length++] = Ctx__emit_(ctx(), OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE);
 | 
					 | 
				
			||||||
        Ctx__patch_jump(ctx(), patch);
 | 
					 | 
				
			||||||
    } while(curr()->type == TK_EXCEPT);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // no match, re-raise
 | 
					 | 
				
			||||||
    Ctx__emit_(ctx(), OP_RE_RAISE, BC_NOARG, BC_KEEPLINE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // no exception or no match, jump to the end
 | 
					 | 
				
			||||||
    for(int i = 0; i < patches_length; i++)
 | 
					 | 
				
			||||||
        Ctx__patch_jump(ctx(), patches[i]);
 | 
					 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,9 @@
 | 
				
			|||||||
#include "pocketpy/common/config.h"
 | 
					#include "pocketpy/common/config.h"
 | 
				
			||||||
#include "pocketpy/common/utils.h"
 | 
					 | 
				
			||||||
#include "pocketpy/interpreter/frame.h"
 | 
					 | 
				
			||||||
#include "pocketpy/interpreter/vm.h"
 | 
					#include "pocketpy/interpreter/vm.h"
 | 
				
			||||||
#include "pocketpy/common/memorypool.h"
 | 
					#include "pocketpy/common/memorypool.h"
 | 
				
			||||||
#include "pocketpy/common/sstream.h"
 | 
					#include "pocketpy/common/sstream.h"
 | 
				
			||||||
#include "pocketpy/objects/codeobject.h"
 | 
					#include "pocketpy/objects/codeobject.h"
 | 
				
			||||||
#include "pocketpy/pocketpy.h"
 | 
					#include "pocketpy/pocketpy.h"
 | 
				
			||||||
#include "pocketpy/objects/error.h"
 | 
					 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool stack_unpack_sequence(pk_VM* self, uint16_t arg);
 | 
					static bool stack_unpack_sequence(pk_VM* self, uint16_t arg);
 | 
				
			||||||
@ -853,30 +850,6 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
 | 
				
			|||||||
                DISPATCH();
 | 
					                DISPATCH();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ///////////
 | 
					            ///////////
 | 
				
			||||||
            case OP_TRY_ENTER: {
 | 
					 | 
				
			||||||
                Frame__set_unwind_target(frame, SP());
 | 
					 | 
				
			||||||
                DISPATCH();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            case OP_EXCEPTION_MATCH: {
 | 
					 | 
				
			||||||
                if(!py_checktype(TOP(), tp_type)) goto __ERROR;
 | 
					 | 
				
			||||||
                bool ok = py_isinstance(TOP(), py_totype(&self->curr_exception));
 | 
					 | 
				
			||||||
                POP();
 | 
					 | 
				
			||||||
                py_newbool(TOP(), ok);
 | 
					 | 
				
			||||||
                DISPATCH();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            case OP_RAISE: {
 | 
					 | 
				
			||||||
                // [exception]
 | 
					 | 
				
			||||||
                if(py_istype(TOP(), tp_type)) {
 | 
					 | 
				
			||||||
                    if(!py_tpcall(py_totype(TOP()), 0, NULL)) goto __ERROR;
 | 
					 | 
				
			||||||
                    py_assign(TOP(), py_retval());
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                if(!py_isinstance(TOP(), tp_BaseException)) {
 | 
					 | 
				
			||||||
                    TypeError("exceptions must derive from BaseException");
 | 
					 | 
				
			||||||
                    goto __ERROR;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                py_raise(TOP());
 | 
					 | 
				
			||||||
                goto __ERROR;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            case OP_RAISE_ASSERT: {
 | 
					            case OP_RAISE_ASSERT: {
 | 
				
			||||||
                if(byte.arg) {
 | 
					                if(byte.arg) {
 | 
				
			||||||
                    if(!py_str(TOP())) goto __ERROR;
 | 
					                    if(!py_str(TOP())) goto __ERROR;
 | 
				
			||||||
@ -887,20 +860,6 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                goto __ERROR;
 | 
					                goto __ERROR;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            case OP_RE_RAISE: {
 | 
					 | 
				
			||||||
                py_raise(&self->curr_exception);
 | 
					 | 
				
			||||||
                goto __ERROR_RE_RAISE;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            case OP_PUSH_EXCEPTION: {
 | 
					 | 
				
			||||||
                assert(self->curr_exception.type);
 | 
					 | 
				
			||||||
                PUSH(&self->curr_exception);
 | 
					 | 
				
			||||||
                DISPATCH();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            case OP_POP_EXCEPTION: {
 | 
					 | 
				
			||||||
                assert(self->curr_exception.type);
 | 
					 | 
				
			||||||
                self->curr_exception = *py_NIL;
 | 
					 | 
				
			||||||
                DISPATCH();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            //////////////////
 | 
					            //////////////////
 | 
				
			||||||
            case OP_FSTRING_EVAL: {
 | 
					            case OP_FSTRING_EVAL: {
 | 
				
			||||||
                py_TValue* tmp = c11__at(py_TValue, &frame->co->consts, byte.arg);
 | 
					                py_TValue* tmp = c11__at(py_TValue, &frame->co->consts, byte.arg);
 | 
				
			||||||
@ -920,29 +879,14 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
 | 
				
			|||||||
            default: c11__unreachedable();
 | 
					            default: c11__unreachedable();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        c11__unreachedable();
 | 
					        assert(false);  // should never reach here
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    __ERROR:
 | 
					    __ERROR:
 | 
				
			||||||
        pk_print_stack(self, frame, (Bytecode){OP_NO_OP, 0});
 | 
					 | 
				
			||||||
        py_BaseException__set_lineno(&self->curr_exception, Frame__lineno(frame), frame->co);
 | 
					 | 
				
			||||||
    __ERROR_RE_RAISE:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        printf("error.op: %s, line: %d\n", pk_opname(byte.op), Frame__lineno(frame));
 | 
					 | 
				
			||||||
        int lineno = py_BaseException__get_lineno(&self->curr_exception, frame->co);
 | 
					 | 
				
			||||||
        py_BaseException__stpush(&self->curr_exception,
 | 
					 | 
				
			||||||
                                 frame->co->src,
 | 
					 | 
				
			||||||
                                 lineno < 0 ? Frame__lineno(frame) : lineno,
 | 
					 | 
				
			||||||
                                 frame->function ? frame->co->name->data : NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        int target = Frame__prepare_jump_exception_handler(frame, &self->stack);
 | 
					 | 
				
			||||||
        if(target >= 0) {
 | 
					 | 
				
			||||||
        // 1. Exception can be handled inside the current frame
 | 
					        // 1. Exception can be handled inside the current frame
 | 
				
			||||||
            DISPATCH_JUMP_ABSOLUTE(target);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
        // 2. Exception need to be propagated to the upper frame
 | 
					        // 2. Exception need to be propagated to the upper frame
 | 
				
			||||||
 | 
					        printf("error.op: %s, line: %d\n", pk_opname(byte.op), Frame__lineno(frame));
 | 
				
			||||||
        return RES_ERROR;
 | 
					        return RES_ERROR;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return RES_RETURN;
 | 
					    return RES_RETURN;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -71,8 +71,10 @@ int Frame__prepare_jump_exception_handler(Frame* self, ValueStack* _s) {
 | 
				
			|||||||
        iblock = block->parent;
 | 
					        iblock = block->parent;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if(iblock < 0) return -1;
 | 
					    if(iblock < 0) return -1;
 | 
				
			||||||
 | 
					    py_TValue obj = *--_s->sp;  // pop exception object
 | 
				
			||||||
    UnwindTarget* uw = Frame__find_unwind_target(self, iblock);
 | 
					    UnwindTarget* uw = Frame__find_unwind_target(self, iblock);
 | 
				
			||||||
    _s->sp = (self->locals + uw->offset);  // unwind the stack
 | 
					    _s->sp = (self->locals + uw->offset);  // unwind the stack
 | 
				
			||||||
 | 
					    *(_s->sp++) = obj;                     // push it back
 | 
				
			||||||
    return c11__at(CodeBlock, &self->co->blocks, iblock)->end;
 | 
					    return c11__at(CodeBlock, &self->co->blocks, iblock)->end;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,7 @@ static void pk_TypeInfo__ctor(pk_TypeInfo* self,
 | 
				
			|||||||
                              py_Name name,
 | 
					                              py_Name name,
 | 
				
			||||||
                              py_Type index,
 | 
					                              py_Type index,
 | 
				
			||||||
                              py_Type base,
 | 
					                              py_Type base,
 | 
				
			||||||
                              py_TValue module) {
 | 
					                              const py_TValue* module) {
 | 
				
			||||||
    memset(self, 0, sizeof(pk_TypeInfo));
 | 
					    memset(self, 0, sizeof(pk_TypeInfo));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    self->name = name;
 | 
					    self->name = name;
 | 
				
			||||||
@ -47,7 +47,7 @@ static void pk_TypeInfo__ctor(pk_TypeInfo* self,
 | 
				
			|||||||
        ._obj = typeobj,
 | 
					        ._obj = typeobj,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    self->module = module;
 | 
					    self->module = module ? *module : *py_NIL;
 | 
				
			||||||
    c11_vector__ctor(&self->annotated_fields, sizeof(py_Name));
 | 
					    c11_vector__ctor(&self->annotated_fields, sizeof(py_Name));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -68,7 +68,7 @@ void pk_VM__ctor(pk_VM* self) {
 | 
				
			|||||||
    self->_stderr = pk_default_stderr;
 | 
					    self->_stderr = pk_default_stderr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    self->last_retval = *py_NIL;
 | 
					    self->last_retval = *py_NIL;
 | 
				
			||||||
    self->curr_exception = *py_NIL;
 | 
					    self->last_exception = *py_NIL;
 | 
				
			||||||
    self->is_stopiteration = false;
 | 
					    self->is_stopiteration = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    self->__curr_class = NULL;
 | 
					    self->__curr_class = NULL;
 | 
				
			||||||
@ -161,30 +161,6 @@ void pk_VM__ctor(pk_VM* self) {
 | 
				
			|||||||
        py_setdict(&self->builtins, ti->name, py_tpobject(t));
 | 
					        py_setdict(&self->builtins, ti->name, py_tpobject(t));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // inject some builtin expections
 | 
					 | 
				
			||||||
    const char** builtin_exceptions = (const char*[]){
 | 
					 | 
				
			||||||
        "StackOverflowError",
 | 
					 | 
				
			||||||
        "IOError",
 | 
					 | 
				
			||||||
        "NotImplementedError",
 | 
					 | 
				
			||||||
        "TypeError",
 | 
					 | 
				
			||||||
        "IndexError",
 | 
					 | 
				
			||||||
        "ValueError",
 | 
					 | 
				
			||||||
        "RuntimeError",
 | 
					 | 
				
			||||||
        "ZeroDivisionError",
 | 
					 | 
				
			||||||
        "NameError",
 | 
					 | 
				
			||||||
        "UnboundLocalError",
 | 
					 | 
				
			||||||
        "AttributeError",
 | 
					 | 
				
			||||||
        "ImportError",
 | 
					 | 
				
			||||||
        "AssertionError",
 | 
					 | 
				
			||||||
        // "KeyError",
 | 
					 | 
				
			||||||
        NULL,   // sentinel
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    const char** it = builtin_exceptions;
 | 
					 | 
				
			||||||
    while(*it){
 | 
					 | 
				
			||||||
        py_Type type = pk_newtype(*it, tp_Exception, &self->builtins, NULL, false, true);
 | 
					 | 
				
			||||||
        py_setdict(&self->builtins, py_name(*it), py_tpobject(type));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    py_TValue tmp;
 | 
					    py_TValue tmp;
 | 
				
			||||||
    py_newnotimplemented(&tmp);
 | 
					    py_newnotimplemented(&tmp);
 | 
				
			||||||
    py_setdict(&self->builtins, py_name("NotImplemented"), &tmp);
 | 
					    py_setdict(&self->builtins, py_name("NotImplemented"), &tmp);
 | 
				
			||||||
@ -290,7 +266,7 @@ py_Type pk_newtype(const char* name,
 | 
				
			|||||||
    c11_vector* types = &pk_current_vm->types;
 | 
					    c11_vector* types = &pk_current_vm->types;
 | 
				
			||||||
    py_Type index = types->count;
 | 
					    py_Type index = types->count;
 | 
				
			||||||
    pk_TypeInfo* ti = c11_vector__emplace(types);
 | 
					    pk_TypeInfo* ti = c11_vector__emplace(types);
 | 
				
			||||||
    pk_TypeInfo__ctor(ti, py_name(name), index, base, module ? *module : *py_NIL);
 | 
					    pk_TypeInfo__ctor(ti, py_name(name), index, base, module);
 | 
				
			||||||
    ti->dtor = dtor;
 | 
					    ti->dtor = dtor;
 | 
				
			||||||
    ti->is_python = is_python;
 | 
					    ti->is_python = is_python;
 | 
				
			||||||
    ti->is_sealed = is_sealed;
 | 
					    ti->is_sealed = is_sealed;
 | 
				
			||||||
@ -564,14 +540,14 @@ void pk_ManagedHeap__mark(pk_ManagedHeap* self) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    // mark vm's registers
 | 
					    // mark vm's registers
 | 
				
			||||||
    mark_value(&vm->last_retval);
 | 
					    mark_value(&vm->last_retval);
 | 
				
			||||||
    mark_value(&vm->curr_exception);
 | 
					    mark_value(&vm->last_exception);
 | 
				
			||||||
    for(int i = 0; i < c11__count_array(vm->reg); i++) {
 | 
					    for(int i = 0; i < c11__count_array(vm->reg); i++) {
 | 
				
			||||||
        mark_value(&vm->reg[i]);
 | 
					        mark_value(&vm->reg[i]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pk_print_stack(pk_VM* self, Frame* frame, Bytecode byte) {
 | 
					void pk_print_stack(pk_VM* self, Frame* frame, Bytecode byte) {
 | 
				
			||||||
    // return;
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    py_TValue* sp = self->stack.sp;
 | 
					    py_TValue* sp = self->stack.sp;
 | 
				
			||||||
    c11_sbuf buf;
 | 
					    c11_sbuf buf;
 | 
				
			||||||
 | 
				
			|||||||
@ -46,17 +46,4 @@ bool py_checktype(py_Ref self, py_Type type) {
 | 
				
			|||||||
    return TypeError("expected %t, got %t", type, self->type);
 | 
					    return TypeError("expected %t, got %t", type, self->type);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool py_isinstance(py_Ref obj, py_Type type){
 | 
					 | 
				
			||||||
    return py_issubclass(obj->type, type);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool py_issubclass(py_Type derived, py_Type base){
 | 
					 | 
				
			||||||
    pk_TypeInfo* types = pk_current_vm->types.data;
 | 
					 | 
				
			||||||
    do {
 | 
					 | 
				
			||||||
        if(derived == base) return true;
 | 
					 | 
				
			||||||
        derived = types[derived].base;
 | 
					 | 
				
			||||||
    } while(derived);
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
py_Type py_typeof(py_Ref self) { return self->type; }
 | 
					py_Type py_typeof(py_Ref self) { return self->type; }
 | 
				
			||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
#include "pocketpy/objects/base.h"
 | 
					 | 
				
			||||||
#include "pocketpy/pocketpy.h"
 | 
					#include "pocketpy/pocketpy.h"
 | 
				
			||||||
#include "pocketpy/common/sstream.h"
 | 
					#include "pocketpy/common/sstream.h"
 | 
				
			||||||
#include "pocketpy/interpreter/vm.h"
 | 
					#include "pocketpy/interpreter/vm.h"
 | 
				
			||||||
@ -7,31 +6,29 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
bool py_checkexc() {
 | 
					bool py_checkexc() {
 | 
				
			||||||
    pk_VM* vm = pk_current_vm;
 | 
					    pk_VM* vm = pk_current_vm;
 | 
				
			||||||
    return !py_isnil(&vm->curr_exception);
 | 
					    return !py_isnil(&vm->last_exception);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void py_printexc() {
 | 
					void py_printexc() {
 | 
				
			||||||
    pk_VM* vm = pk_current_vm;
 | 
					    pk_VM* vm = pk_current_vm;
 | 
				
			||||||
    if(py_isnil(&vm->curr_exception)) {
 | 
					    if(py_isnil(&vm->last_exception)) {
 | 
				
			||||||
        vm->_stdout("NoneType: None\n");
 | 
					        vm->_stdout("NoneType: None\n");
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        const char* name = py_tpname(vm->curr_exception.type);
 | 
					        const char* name = py_tpname(vm->last_exception.type);
 | 
				
			||||||
        bool ok = py_str(&vm->curr_exception);
 | 
					        bool ok = py_str(&vm->last_exception);
 | 
				
			||||||
        if(!ok) abort();
 | 
					        if(!ok) abort();
 | 
				
			||||||
        const char* message = py_tostr(py_retval());
 | 
					        const char* message = py_tostr(py_retval());
 | 
				
			||||||
        vm->_stdout("%s: %s\n", name, message);
 | 
					        vm->_stdout("%s: %s\n", name, message);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char* py_formatexc() {
 | 
					void py_formatexc(char* out) {}
 | 
				
			||||||
    pk_VM* vm = pk_current_vm;
 | 
					 | 
				
			||||||
    if(py_isnil(&vm->curr_exception)) {
 | 
					 | 
				
			||||||
        return NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    assert(false);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool py_exception(const char* name, const char* fmt, ...) {
 | 
					bool py_exception(const char* name, const char* fmt, ...) {
 | 
				
			||||||
 | 
					    pk_VM* vm = pk_current_vm;
 | 
				
			||||||
 | 
					    // an error is already set
 | 
				
			||||||
 | 
					    assert(py_isnil(&vm->last_exception));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    c11_sbuf buf;
 | 
					    c11_sbuf buf;
 | 
				
			||||||
    c11_sbuf__ctor(&buf);
 | 
					    c11_sbuf__ctor(&buf);
 | 
				
			||||||
    va_list args;
 | 
					    va_list args;
 | 
				
			||||||
@ -44,16 +41,11 @@ bool py_exception(const char* name, const char* fmt, ...) {
 | 
				
			|||||||
    py_newstrn(message, res->data, res->size);
 | 
					    py_newstrn(message, res->data, res->size);
 | 
				
			||||||
    c11_string__delete(res);
 | 
					    c11_string__delete(res);
 | 
				
			||||||
    bool ok = py_tpcall(tp_Exception, 1, message);
 | 
					    bool ok = py_tpcall(tp_Exception, 1, message);
 | 
				
			||||||
    if(!ok) abort();
 | 
					 | 
				
			||||||
    py_pop();
 | 
					    py_pop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return py_raise(py_retval());
 | 
					    if(!ok) abort();
 | 
				
			||||||
}
 | 
					    vm->last_exception = *py_retval();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool py_raise(py_Ref exc) {
 | 
					 | 
				
			||||||
    assert(py_isinstance(exc, tp_BaseException));
 | 
					 | 
				
			||||||
    pk_VM* vm = pk_current_vm;
 | 
					 | 
				
			||||||
    vm->curr_exception = *exc;
 | 
					 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,3 @@
 | 
				
			|||||||
#include "pocketpy/objects/codeobject.h"
 | 
					 | 
				
			||||||
#include "pocketpy/objects/error.h"
 | 
					 | 
				
			||||||
#include "pocketpy/pocketpy.h"
 | 
					#include "pocketpy/pocketpy.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "pocketpy/common/utils.h"
 | 
					#include "pocketpy/common/utils.h"
 | 
				
			||||||
@ -14,47 +12,20 @@ typedef struct BaseExceptionFrame {
 | 
				
			|||||||
} BaseExceptionFrame;
 | 
					} BaseExceptionFrame;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct BaseException {
 | 
					typedef struct BaseException {
 | 
				
			||||||
    int lineno_backup;
 | 
					    int ip_backup;
 | 
				
			||||||
    const CodeObject* code_backup;
 | 
					    CodeObject* code_backup;
 | 
				
			||||||
    c11_vector /*T=BaseExceptionFrame*/ stacktrace;
 | 
					    c11_vector /*T=BaseExceptionFrame*/ stacktrace;
 | 
				
			||||||
} BaseException;
 | 
					} BaseException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void py_BaseException__set_lineno(py_Ref self, int lineno, const CodeObject* code){
 | 
					 | 
				
			||||||
    BaseException* ud = py_touserdata(self);
 | 
					 | 
				
			||||||
    ud->lineno_backup = lineno;
 | 
					 | 
				
			||||||
    ud->code_backup = code;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int py_BaseException__get_lineno(py_Ref self, const CodeObject* code){
 | 
					 | 
				
			||||||
    BaseException* ud = py_touserdata(self);
 | 
					 | 
				
			||||||
    if(code != ud->code_backup) return -1;
 | 
					 | 
				
			||||||
    return ud->lineno_backup;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void py_BaseException__stpush(py_Ref self, pk_SourceData_ src, int lineno, const char *func_name){
 | 
					 | 
				
			||||||
    BaseException* ud = py_touserdata(self);
 | 
					 | 
				
			||||||
    if(ud->stacktrace.count >= 7) return;
 | 
					 | 
				
			||||||
    BaseExceptionFrame* frame = c11_vector__emplace(&ud->stacktrace);
 | 
					 | 
				
			||||||
    PK_INCREF(src);
 | 
					 | 
				
			||||||
    frame->src = src;
 | 
					 | 
				
			||||||
    frame->lineno = lineno;
 | 
					 | 
				
			||||||
    frame->name = func_name ? c11_string__new(func_name) : NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void BaseException__dtor(void* ud) {
 | 
					static void BaseException__dtor(void* ud) {
 | 
				
			||||||
    BaseException* self = (BaseException*)ud;
 | 
					    BaseException* self = (BaseException*)ud;
 | 
				
			||||||
    c11__foreach(BaseExceptionFrame, &self->stacktrace, it) {
 | 
					 | 
				
			||||||
        PK_DECREF(it->src);
 | 
					 | 
				
			||||||
        if(it->name) c11_string__delete(it->name);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    c11_vector__dtor(&self->stacktrace);
 | 
					    c11_vector__dtor(&self->stacktrace);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool _py_BaseException__new__(int argc, py_Ref argv) {
 | 
					static bool _py_BaseException__new__(int argc, py_Ref argv) {
 | 
				
			||||||
    py_Type cls = py_totype(argv);
 | 
					    py_Type cls = py_totype(argv);
 | 
				
			||||||
    BaseException* ud = py_newobject(py_retval(), cls, 1, sizeof(BaseException));
 | 
					    BaseException* ud = py_newobject(py_retval(), cls, 1, sizeof(BaseException));
 | 
				
			||||||
    c11_vector__ctor(&ud->stacktrace, sizeof(BaseExceptionFrame));
 | 
					    ud->ip_backup = -1;
 | 
				
			||||||
    ud->lineno_backup = -1;
 | 
					 | 
				
			||||||
    ud->code_backup = NULL;
 | 
					    ud->code_backup = NULL;
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,14 +1,14 @@
 | 
				
			|||||||
 | 
					try:
 | 
				
			||||||
 | 
					    raise 1
 | 
				
			||||||
 | 
					except TypeError:
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
try:
 | 
					try:
 | 
				
			||||||
    assert False
 | 
					    assert False
 | 
				
			||||||
    exit(1)
 | 
					    exit(1)
 | 
				
			||||||
except AssertionError:
 | 
					except AssertionError:
 | 
				
			||||||
    pass
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
try:
 | 
					 | 
				
			||||||
    raise 1
 | 
					 | 
				
			||||||
except TypeError:
 | 
					 | 
				
			||||||
    pass
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
try:
 | 
					try:
 | 
				
			||||||
    for i in range(5):
 | 
					    for i in range(5):
 | 
				
			||||||
        raise KeyError(i)
 | 
					        raise KeyError(i)
 | 
				
			||||||
@ -134,7 +134,6 @@ except SyntaxError as e:
 | 
				
			|||||||
    ok = True
 | 
					    ok = True
 | 
				
			||||||
assert ok
 | 
					assert ok
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
# finally, only
 | 
					# finally, only
 | 
				
			||||||
def finally_only():
 | 
					def finally_only():
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
@ -196,4 +195,3 @@ except KeyError:
 | 
				
			|||||||
    exit(0)
 | 
					    exit(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
exit(1)
 | 
					exit(1)
 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user