internal.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. #include "pocketpy/interpreter/typeinfo.h"
  2. #include "pocketpy/objects/codeobject.h"
  3. #include "pocketpy/pocketpy.h"
  4. #include "pocketpy/common/utils.h"
  5. #include "pocketpy/interpreter/vm.h"
  6. VM* pk_current_vm;
  7. static VM pk_default_vm;
  8. static VM* pk_all_vm[16];
  9. static py_TValue _True, _False, _None, _NIL;
  10. void py_initialize() {
  11. if(pk_current_vm) {
  12. // c11__abort("py_initialize() can only be called once!");
  13. return;
  14. }
  15. MemoryPools__initialize();
  16. py_Name__initialize();
  17. pk_current_vm = pk_all_vm[0] = &pk_default_vm;
  18. // initialize some convenient references
  19. py_newbool(&_True, true);
  20. py_newbool(&_False, false);
  21. py_newnone(&_None);
  22. py_newnil(&_NIL);
  23. VM__ctor(&pk_default_vm);
  24. }
  25. py_GlobalRef py_True() { return &_True; }
  26. py_GlobalRef py_False() { return &_False; }
  27. py_GlobalRef py_None() { return &_None; }
  28. py_GlobalRef py_NIL() { return &_NIL; }
  29. void py_finalize() {
  30. for(int i = 1; i < 16; i++) {
  31. VM* vm = pk_all_vm[i];
  32. if(vm) {
  33. // temp fix https://github.com/pocketpy/pocketpy/issues/315
  34. // TODO: refactor VM__ctor and VM__dtor
  35. pk_current_vm = vm;
  36. VM__dtor(vm);
  37. free(vm);
  38. }
  39. }
  40. pk_current_vm = &pk_default_vm;
  41. VM__dtor(&pk_default_vm);
  42. pk_current_vm = NULL;
  43. py_Name__finalize();
  44. MemoryPools__finalize();
  45. }
  46. void py_switchvm(int index) {
  47. if(index < 0 || index >= 16) c11__abort("invalid vm index");
  48. if(!pk_all_vm[index]) {
  49. pk_current_vm = pk_all_vm[index] = malloc(sizeof(VM));
  50. memset(pk_current_vm, 0, sizeof(VM));
  51. VM__ctor(pk_all_vm[index]);
  52. } else {
  53. pk_current_vm = pk_all_vm[index];
  54. }
  55. }
  56. void py_resetvm() {
  57. VM* vm = pk_current_vm;
  58. VM__dtor(vm);
  59. memset(vm, 0, sizeof(VM));
  60. VM__ctor(vm);
  61. }
  62. int py_currentvm() {
  63. for(int i = 0; i < 16; i++) {
  64. if(pk_all_vm[i] == pk_current_vm) return i;
  65. }
  66. return -1;
  67. }
  68. void* py_getvmctx() { return pk_current_vm->ctx; }
  69. void py_setvmctx(void* ctx) { pk_current_vm->ctx = ctx; }
  70. void py_sys_setargv(int argc, char** argv) {
  71. py_GlobalRef sys = py_getmodule("sys");
  72. py_Ref argv_list = py_getdict(sys, py_name("argv"));
  73. py_list_clear(argv_list);
  74. for(int i = 0; i < argc; i++) {
  75. py_newstr(py_list_emplace(argv_list), argv[i]);
  76. }
  77. }
  78. py_Callbacks* py_callbacks() { return &pk_current_vm->callbacks; }
  79. const char* pk_opname(Opcode op) {
  80. const static char* OP_NAMES[] = {
  81. #define OPCODE(name) #name,
  82. #include "pocketpy/xmacros/opcodes.h"
  83. #undef OPCODE
  84. };
  85. return OP_NAMES[op];
  86. }
  87. bool py_call(py_Ref f, int argc, py_Ref argv) {
  88. if(f->type == tp_nativefunc) {
  89. return py_callcfunc(f->_cfunc, argc, argv);
  90. } else {
  91. py_StackRef p0 = py_peek(0);
  92. py_push(f);
  93. py_pushnil();
  94. for(int i = 0; i < argc; i++)
  95. py_push(py_offset(argv, i));
  96. bool ok = py_vectorcall(argc, 0);
  97. pk_current_vm->stack.sp = p0;
  98. return ok;
  99. }
  100. }
  101. #ifndef NDEBUG
  102. bool py_callcfunc(py_CFunction f, int argc, py_Ref argv) {
  103. py_StackRef p0 = py_peek(0);
  104. py_newnil(py_retval());
  105. bool ok = f(argc, argv);
  106. if(!ok) {
  107. if(!py_checkexc(true)) {
  108. c11__abort("py_CFunction returns `false` but no exception is set!");
  109. }
  110. return false;
  111. }
  112. if(py_peek(0) != p0) {
  113. c11__abort("py_CFunction corrupts the stack! Did you forget to call `py_pop()`?");
  114. }
  115. if(py_isnil(py_retval())) {
  116. c11__abort(
  117. "py_CFunction returns nothing! Did you forget to call `py_newnone(py_retval())`?");
  118. }
  119. if(py_checkexc(true)) {
  120. const char* name = py_tpname(pk_current_vm->curr_exception.type);
  121. c11__abort("py_CFunction returns `true`, but `%s` is set!", name);
  122. }
  123. return true;
  124. }
  125. #endif
  126. bool py_vectorcall(uint16_t argc, uint16_t kwargc) {
  127. return VM__vectorcall(pk_current_vm, argc, kwargc, false) != RES_ERROR;
  128. }
  129. py_Ref py_retval() { return &pk_current_vm->last_retval; }
  130. bool py_pushmethod(py_Name name) {
  131. bool ok = pk_loadmethod(py_peek(-1), name);
  132. if(ok) pk_current_vm->stack.sp++;
  133. return ok;
  134. }
  135. bool pk_loadmethod(py_StackRef self, py_Name name) {
  136. // NOTE: `out` and `out_self` may overlap with `self`
  137. py_Type type;
  138. if(name == __new__) {
  139. // __new__ acts like a @staticmethod
  140. if(py_istype(self, tp_type)) {
  141. // T.__new__(...)
  142. type = py_totype(self);
  143. } else if(py_istype(self, tp_super)) {
  144. // super().__new__(...)
  145. type = *(py_Type*)py_touserdata(self);
  146. } else {
  147. // invalid usage of `__new__`
  148. return false;
  149. }
  150. py_Ref cls_var = py_tpfindmagic(type, name);
  151. if(cls_var) {
  152. self[0] = *cls_var;
  153. self[1] = *py_NIL();
  154. return true;
  155. }
  156. return false;
  157. }
  158. // handle super() proxy
  159. if(py_istype(self, tp_super)) {
  160. type = *(py_Type*)py_touserdata(self);
  161. *self = *py_getslot(self, 0);
  162. } else {
  163. type = self->type;
  164. }
  165. py_Ref cls_var = py_tpfindname(type, name);
  166. if(cls_var != NULL) {
  167. switch(cls_var->type) {
  168. case tp_function:
  169. case tp_nativefunc: {
  170. py_TValue self_bak = *self;
  171. // `out` may overlap with `self`. If we assign `out`, `self` may be corrupted.
  172. self[0] = *cls_var;
  173. self[1] = self_bak;
  174. break;
  175. }
  176. case tp_staticmethod:
  177. self[0] = *py_getslot(cls_var, 0);
  178. self[1] = *py_NIL();
  179. break;
  180. case tp_classmethod:
  181. self[0] = *py_getslot(cls_var, 0);
  182. self[1] = pk__type_info(type)->self;
  183. break;
  184. default: c11__unreachedable();
  185. }
  186. return true;
  187. }
  188. return false;
  189. }
  190. py_Ref py_tpfindmagic(py_Type t, py_Name name) {
  191. assert(py_ismagicname(name));
  192. py_TypeInfo* ti = pk__type_info(t);
  193. do {
  194. py_Ref f = &ti->magic[name];
  195. if(!py_isnil(f)) return f;
  196. ti = ti->base_ti;
  197. } while(ti);
  198. return NULL;
  199. }
  200. py_Ref py_tpfindname(py_Type t, py_Name name) {
  201. py_TypeInfo* ti = pk__type_info(t);
  202. do {
  203. py_Ref res = py_getdict(&ti->self, name);
  204. if(res) return res;
  205. ti = ti->base_ti;
  206. } while(ti);
  207. return NULL;
  208. }
  209. py_Ref py_tpgetmagic(py_Type type, py_Name name) {
  210. assert(py_ismagicname(name));
  211. return pk__type_info(type)->magic + name;
  212. }
  213. py_Ref py_tpobject(py_Type type) {
  214. assert(type);
  215. return &pk__type_info(type)->self;
  216. }
  217. const char* py_tpname(py_Type type) {
  218. if(!type) return "nil";
  219. py_Name name = pk__type_info(type)->name;
  220. return py_name2str(name);
  221. }
  222. bool py_tpcall(py_Type type, int argc, py_Ref argv) {
  223. return py_call(py_tpobject(type), argc, argv);
  224. }
  225. bool pk_callmagic(py_Name name, int argc, py_Ref argv) {
  226. assert(argc >= 1);
  227. assert(py_ismagicname(name));
  228. py_Ref tmp = py_tpfindmagic(argv->type, name);
  229. if(!tmp) return AttributeError(argv, name);
  230. return py_call(tmp, argc, argv);
  231. }
  232. bool StopIteration() {
  233. bool ok = py_tpcall(tp_StopIteration, 0, NULL);
  234. if(!ok) return false;
  235. return py_raise(py_retval());
  236. }