From 0871b627ed166913ac7905b35733c4d91922547f Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Tue, 25 Jun 2024 19:32:15 +0800 Subject: [PATCH] up --- include/pocketpy/interpreter/vm.h | 1 + include/pocketpy/pocketpy.h | 77 ++++++++++++++++++++-------- src/interpreter/vm.c | 85 +++++++++++++++---------------- src/pocketpy.c | 76 +++++++++++++++++++++++++++ 4 files changed, 173 insertions(+), 66 deletions(-) diff --git a/include/pocketpy/interpreter/vm.h b/include/pocketpy/interpreter/vm.h index 6b00cbb4..8ad1679e 100644 --- a/include/pocketpy/interpreter/vm.h +++ b/include/pocketpy/interpreter/vm.h @@ -64,6 +64,7 @@ typedef struct pk_VM { PyVar last_retval; // registers PyVar reg[8]; + PyVar sysreg[8]; PyObject* __curr_class; PyObject* __cached_object_new; diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index 19ee69c3..cf23be68 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -48,27 +48,28 @@ int py_le(const py_Ref, const py_Ref); int py_hash(const py_Ref, int64_t* out); /* py_var */ -void py_new_int(py_Ref, int64_t); -void py_new_float(py_Ref, double); -void py_new_bool(py_Ref, bool); -void py_new_str(py_Ref, const char*); -void py_new_strn(py_Ref, const char*, int); -void py_new_fstr(py_Ref, const char*, ...); -void py_new_bytes(py_Ref, const uint8_t*, int); -void py_new_none(py_Ref); -void py_new_null(py_Ref); +void py_newint(py_Ref, int64_t); +void py_newfloat(py_Ref, double); +void py_newbool(py_Ref, bool); +void py_newstr(py_Ref, const char*); +void py_newstrn(py_Ref, const char*, int); +// void py_newfstr(py_Ref, const char*, ...); +void py_newbytes(py_Ref, const uint8_t*, int); +void py_newnone(py_Ref); +void py_newnull(py_Ref); -void py_new_tuple(PyVar, int); +void py_newtuple(py_Ref, int); // new style decl-based function -void py_new_function(py_Ref, py_CFunction, const char* sig, BindType bt); -void py_new_function2(py_Ref, py_CFunction, const char* sig, BindType bt, const char* docstring, const py_Ref userdata); +void py_newfunction(py_Ref, py_CFunction, const char* sig, BindType bt); +void py_newfunction2(py_Ref, py_CFunction, const char* sig, BindType bt, const char* docstring, const py_Ref userdata); // old style argc-based function -void py_new_nativefunc(py_Ref, py_CFunction, int argc, BindType bt); -void py_new_nativefunc2(py_Ref, py_CFunction, int argc, BindType bt, const char* docstring, const py_Ref userdata); +void py_newnativefunc(py_Ref, py_CFunction, int argc, BindType bt); +void py_newnativefunc2(py_Ref, py_CFunction, int argc, BindType bt, const char* docstring, const py_Ref userdata); -py_Ref py_new_module(const char* name); +py_Ref py_newmodule(const char* name, const char* package); +py_Ref py_getmodule(const char* name); const py_Ref py_import(const char* name); #define py_isnull(self) ((self)->type == 0) @@ -84,19 +85,25 @@ void py_setslot(py_Ref self, int i, const py_Ref val); /// Returns a reference to the i-th slot of the object. py_Ref py_getslot(const py_Ref self, int i); -/// Sets the attribute of the object to the given value. -/// This is equivalent to `self.name = val`. +/// Equivalent to `self.name = val`. /// Returns 0 | err int py_setattr(py_Ref self, py_Name name, const py_Ref val); -/// Gets the attribute of the object. -/// This is equivalent to `self.name`. +/// Equivalent to `self.name`. /// Returns 0 | err int py_getattr(const py_Ref self, py_Name name, py_Ref out); -/// Returns a reference to the i-th object in the stack. -/// For example, `py_stackref(-1)` refers to the top of the stack. -py_Ref py_stackref(int i); +/// Returns a reference to the i-th object from the top of the stack. +/// i should be negative, e.g. (-1) means TOS. +py_Ref py_stack(int i); +/// Returns a reference to the i-th register. +py_Ref py_reg(int i); +/// Returns a reference to the i-th system register. +py_Ref py_sysreg(int i); +/// Prepares a push and returns an uninitialized reference. +py_Ref py_push(); + + /// Pushes the object to the stack. void py_pushref(const py_Ref src); /// Pops the object from the stack. @@ -109,13 +116,39 @@ void py_copyref(const py_Ref src, py_Ref dst); py_Ref py_tuple__getitem(const py_Ref self, int i); void py_tuple__setitem(py_Ref self, int i, const py_Ref val); int py_tuple__len(const py_Ref self); +bool py_tuple__contains(const py_Ref self, const py_Ref val); + +// unchecked functions, if self is not a list, the behavior is undefined +py_Ref py_list__getitem(const py_Ref self, int i); +void py_list__setitem(py_Ref self, int i, const py_Ref val); +void py_list__delitem(py_Ref self, int i); +int py_list__len(const py_Ref self); +bool py_list__contains(const py_Ref self, const py_Ref val); +void py_list__append(py_Ref self, const py_Ref val); +void py_list__extend(py_Ref self, const py_Ref begin, const py_Ref end); +void py_list__clear(py_Ref self); +void py_list__insert(py_Ref self, int i, const py_Ref val); + +// unchecked functions, if self is not a dict, the behavior is undefined +int py_dict__len(const py_Ref self); +bool py_dict__contains(const py_Ref self, const py_Ref key); +py_Ref py_dict__getitem(const py_Ref self, const py_Ref key); +void py_dict__setitem(py_Ref self, const py_Ref key, const py_Ref val); +void py_dict__delitem(py_Ref self, const py_Ref key); +void py_dict__clear(py_Ref self); int py_str(const py_Ref, py_Str* out); int py_repr(const py_Ref, py_Str* out); +int py_toint(py_Ref, int64_t* out); +int py_tofloat(py_Ref, double* out); int py_tostr(py_Ref, py_Str** out); int py_tobool(py_Ref, bool* out); +bool py_istype(const py_Ref, Type); +bool py_isinstance(const py_Ref obj, Type type); +bool py_issubclass(Type derived, Type base); + #ifdef __cplusplus } #endif diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index 62bc150b..0bfedb2d 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -34,53 +34,50 @@ void pk_TypeInfo__dtor(pk_TypeInfo *self){ c11_vector__dtor(&self->annotated_fields); } -static int _hello(const py_Ref args, int argc){ - return 0; -} +// static int _py_print(const py_Ref args, int argc){ +// int length = py_tuple__len(args+0); +// py_Str* sep; +// py_Str* end; -// print(*args, sep=' ', end='\n') -static int _py_print(const py_Ref args, int argc){ - int length = py_tuple__len(args+0); - py_Str* sep; - py_Str* end; +// int err; +// err = py_tostr(args+1, &sep); +// if(err) return err; +// err = py_tostr(args+2, &end); +// if(err) return err; - int err; - err = py_tostr(args+1, &sep); - if(err) return err; - err = py_tostr(args+2, &end); - if(err) return err; +// pk_SStream ss; +// pk_SStream__ctor(&ss); - pk_SStream ss; - pk_SStream__ctor(&ss); - - for(int i=0; i_stdout(py_Str__data(&out)); - py_Str__dtor(&out); - return 0; -} +// for(int i=0; i_stdout(py_Str__data(&out)); +// py_Str__dtor(&out); +// return 0; +// } static void do_builtin_bindings(){ - pk_VM* vm = pk_current_vm; - - py_new_nativefunc(&vm->reg[0], _hello, 2, BindType_FUNCTION); - py_setdict(&vm->builtins, py_name("hello"), &vm->reg[0]); + // py_Ref builtins = py_getmodule("builtins"); + // py_newfunction(py_reg(0), _py_print, + // "print(*args, sep=' ', end='\\n')", + // BindType_FUNCTION + // ); + // py_setdict(builtins, py_name("hello"), py_reg(0)); } void pk_VM__ctor(pk_VM* self){ @@ -172,7 +169,7 @@ void pk_VM__ctor(pk_VM* self){ #undef validate self->StopIteration = c11__at(pk_TypeInfo, &self->types, tp_stop_iteration)->self; - self->builtins = *py_new_module("builtins"); + self->builtins = *py_newmodule("builtins", NULL); /* Setup Public Builtin Types */ Type public_types[] = { @@ -193,7 +190,7 @@ void pk_VM__ctor(pk_VM* self){ /* Do Buildin Bindings*/ do_builtin_bindings(); - self->main = *py_new_module("__main__"); + self->main = *py_newmodule("__main__", NULL); } void pk_VM__dtor(pk_VM* self){ diff --git a/src/pocketpy.c b/src/pocketpy.c index 4803df38..6a801ac1 100644 --- a/src/pocketpy.c +++ b/src/pocketpy.c @@ -1,4 +1,5 @@ #include "pocketpy/pocketpy.h" +#include "pocketpy/common/utils.h" #include "pocketpy/objects/object.h" #include "pocketpy/interpreter/vm.h" #include @@ -32,6 +33,47 @@ int py_exec_simple(const char* source){ assert(0); // unreachable } +py_Ref py_getmodule(const char *name){ + pk_VM* vm = pk_current_vm; + return pk_NameDict__try_get(&vm->modules, py_name(name)); +} + +py_Ref py_newmodule(const char *name, const char *package){ + pk_ManagedHeap* heap = &pk_current_vm->heap; + PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_module, -1, 0); + + py_Ref r0 = py_sysreg(0); + py_Ref r1 = py_sysreg(1); + + *r0 = PyVar__fromobj(obj); + + py_newstr(r1, name); + py_setdict(r0, __name__, r1); + + package = package ? package : ""; + + py_newstr(r1, package); + py_setdict(r0, __package__, r1); + + // convert to fullname + if(package[0] != '\0'){ + // package.name + char buf[256]; + snprintf(buf, sizeof(buf), "%s.%s", package, name); + name = buf; + } + + py_newstr(r1, name); + py_setdict(r0, __path__, r1); + + // we do not allow override in order to avoid memory leak + // it is because Module objects are not garbage collected + bool exists = pk_NameDict__contains(&pk_current_vm->modules, py_name(name)); + if(exists) abort(); + pk_NameDict__set(&pk_current_vm->modules, py_name(name), *r0); + return py_getmodule(name); +} + py_Error* py_getlasterror(){ return pk_current_vm->last_error; } @@ -40,6 +82,21 @@ void py_Error__print(py_Error* self){ abort(); } +py_Ref py_reg(int i){ + assert(i >= 0 && i < 8); + return &pk_current_vm->reg[i]; +} + +py_Ref py_sysreg(int i){ + assert(i >= 0 && i < 8); + return &pk_current_vm->sysreg[i]; +} + +py_Ref py_stack(int i){ + assert(i < 0); + return &pk_current_vm->stack.sp[i]; +} + void py_finalize(){ pk_VM__dtor(&pk_default_vm); pk_current_vm = NULL; @@ -61,3 +118,22 @@ void py_newint(py_Ref self, int64_t val){ self->_i64 = val; } +void py_newfloat(py_Ref self, double val){ + self->type = tp_float; + self->is_ptr = false; + self->_f64 = val; +} + +void py_newbool(py_Ref self, bool val){ + pk_VM* vm = pk_current_vm; + *self = val ? vm->True : vm->False; +} + +void py_newstr(py_Ref self, const char* val){ + pk_VM* vm = pk_current_vm; + PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_str, 0, sizeof(py_Str)); + py_Str__ctor((py_Str*)PyObject__value(obj), val); + self->type = tp_str; + self->is_ptr = true; + self->_obj = obj; +}