diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index db02f484..c9c7e87e 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -209,15 +209,16 @@ py_GlobalRef py_tpfindmagic(py_Type, py_Name name); /// Search the name from the given type to the base type. /// Return `NULL` if not found. py_GlobalRef py_tpfindname(py_Type, py_Name name); +/// Get the magic method from the given type only. +/// The returned reference is always valid. However, its value may be `nil`. +py_GlobalRef py_tpgetmagic(py_Type type, py_Name name); + /// Get the type object of the given type. py_GlobalRef py_tpobject(py_Type type); /// Get the type name. const char* py_tpname(py_Type type); /// Call a type to create a new instance. bool py_tpcall(py_Type type, int argc, py_Ref argv) PY_RAISE; -/// Get the magic method from the given type only. -/// The returned reference is always valid. However, its value may be `nil`. -py_GlobalRef py_tpmagic(py_Type type, py_Name name); /// Check if the object is an instance of the given type. /// Raise `TypeError` if the check fails. @@ -287,7 +288,7 @@ void py_bindfunc(py_Ref obj, const char* name, py_CFunction f); /// @param setter setter function. Use `NULL` if not needed. void py_bindproperty(py_Type type, const char* name, py_CFunction getter, py_CFunction setter); -#define py_bindmagic(type, __magic__, f) py_newnativefunc(py_tpmagic((type), __magic__), (f)) +#define py_bindmagic(type, __magic__, f) py_newnativefunc(py_tpgetmagic((type), __magic__), (f)) #define PY_CHECK_ARGC(n) \ if(argc != n) return TypeError("expected %d arguments, got %d", n, argc) diff --git a/src/public/exec.c b/src/public/exec.c new file mode 100644 index 00000000..fc272c2d --- /dev/null +++ b/src/public/exec.c @@ -0,0 +1,74 @@ +#include "pocketpy/objects/codeobject.h" +#include "pocketpy/objects/sourcedata.h" +#include "pocketpy/pocketpy.h" + +#include "pocketpy/common/utils.h" +#include "pocketpy/common/sstream.h" +#include "pocketpy/objects/object.h" +#include "pocketpy/interpreter/vm.h" +#include "pocketpy/compiler/compiler.h" + +typedef struct { + const char* source; + const char* filename; + int mode; + int is_dynamic; +} py_ExecKey; + +static int py_ExecKey__cmp(const py_ExecKey* a, const py_ExecKey* b) { + return memcmp(a, b, sizeof(py_ExecKey)); +} + +static void py_ExecKey__ctor(py_ExecKey* key, const char* source, const char* filename, + enum py_CompileMode mode, bool is_dynamic) { + key->source = source; + key->filename = filename; + key->mode = mode; + key->is_dynamic = is_dynamic; +} + +static bool _py_exec(const char* source, + const char* filename, + enum py_CompileMode mode, + py_Ref module, + bool is_dynamic) { + VM* vm = pk_current_vm; + // py_ExecKey cache_key; + // py_ExecKey__ctor(&cache_key, source, filename, mode, is_dynamic); + CodeObject co; + SourceData_ src = SourceData__rcnew(source, filename, mode, is_dynamic); + Error* err = pk_compile(src, &co); + if(err) { + py_exception(tp_SyntaxError, err->msg); + py_BaseException__stpush(&vm->curr_exception, src, err->lineno, NULL); + + PK_DECREF(src); + free(err); + return false; + } + + if(!module) module = &vm->main; + + py_StackRef sp = vm->stack.sp; + if(is_dynamic) { + // [globals, locals] + sp -= 2; + } + + Frame* frame = Frame__new(&co, module, sp, sp, false, is_dynamic); + VM__push_frame(vm, frame); + FrameResult res = VM__run_top_frame(vm); + CodeObject__dtor(&co); + PK_DECREF(src); + if(res == RES_ERROR) return false; + if(res == RES_RETURN) return true; + c11__unreachedable(); +} + +bool py_exec(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) { + return _py_exec(source, filename, mode, module, false); +} + +bool py_execdyn(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) { + return _py_exec(source, filename, mode, module, true); +} \ No newline at end of file diff --git a/src/public/internal.c b/src/public/internal.c index 7883b270..a416ea44 100644 --- a/src/public/internal.c +++ b/src/public/internal.c @@ -7,8 +7,6 @@ #include "pocketpy/objects/object.h" #include "pocketpy/interpreter/vm.h" #include "pocketpy/compiler/compiler.h" -#include -#include VM* pk_current_vm; @@ -78,50 +76,6 @@ const char* pk_opname(Opcode op) { return OP_NAMES[op]; } -static bool _py_exec(const char* source, - const char* filename, - enum py_CompileMode mode, - py_Ref module, - bool is_dynamic) { - VM* vm = pk_current_vm; - CodeObject co; - SourceData_ src = SourceData__rcnew(source, filename, mode, is_dynamic); - Error* err = pk_compile(src, &co); - if(err) { - py_exception(tp_SyntaxError, err->msg); - py_BaseException__stpush(&vm->curr_exception, src, err->lineno, NULL); - - PK_DECREF(src); - free(err); - return false; - } - - if(!module) module = &vm->main; - - py_StackRef sp = vm->stack.sp; - if(is_dynamic) { - // [globals, locals] - sp -= 2; - } - - Frame* frame = Frame__new(&co, module, sp, sp, false, is_dynamic); - VM__push_frame(vm, frame); - FrameResult res = VM__run_top_frame(vm); - CodeObject__dtor(&co); - PK_DECREF(src); - if(res == RES_ERROR) return false; - if(res == RES_RETURN) return true; - c11__unreachedable(); -} - -bool py_exec(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) { - return _py_exec(source, filename, mode, module, false); -} - -bool py_execdyn(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) { - return _py_exec(source, filename, mode, module, true); -} - bool py_call(py_Ref f, int argc, py_Ref argv) { if(f->type == tp_nativefunc) { return py_callcfunc(f->_cfunc, argc, argv); @@ -220,7 +174,7 @@ py_Ref py_tpfindname(py_Type t, py_Name name) { return NULL; } -py_Ref py_tpmagic(py_Type type, py_Name name) { +py_Ref py_tpgetmagic(py_Type type, py_Name name) { assert(py_ismagicname(name)); VM* vm = pk_current_vm; return &c11__at(py_TypeInfo, &vm->types, type)->magic[name]; diff --git a/src/public/stack_ops.c b/src/public/stack_ops.c index f68be579..c598fbde 100644 --- a/src/public/stack_ops.c +++ b/src/public/stack_ops.c @@ -14,7 +14,7 @@ py_Ref py_getdict(py_Ref self, py_Name name) { return NameDict__try_get(PyObject__dict(self->_obj), name); } else { py_Type* ud = py_touserdata(self); - py_Ref slot = py_tpmagic(*ud, name); + py_Ref slot = py_tpgetmagic(*ud, name); return py_isnil(slot) ? NULL : slot; } } @@ -25,7 +25,7 @@ void py_setdict(py_Ref self, py_Name name, py_Ref val) { NameDict__set(PyObject__dict(self->_obj), name, *val); } else { py_Type* ud = py_touserdata(self); - *py_tpmagic(*ud, name) = *val; + *py_tpgetmagic(*ud, name) = *val; } } @@ -41,7 +41,7 @@ bool py_deldict(py_Ref self, py_Name name) { } else { py_Type* ud = py_touserdata(self); - py_newnil(py_tpmagic(*ud, name)); + py_newnil(py_tpgetmagic(*ud, name)); return true; } }