typeinfo.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #include "pocketpy/interpreter/vm.h"
  2. #include <assert.h>
  3. py_ItemRef pk_tpfindname(py_TypeInfo* ti, py_Name name) {
  4. assert(ti != NULL);
  5. do {
  6. py_Ref res = py_getdict(&ti->self, name);
  7. if(res) return res;
  8. ti = ti->base_ti;
  9. } while(ti);
  10. return NULL;
  11. }
  12. PK_INLINE py_ItemRef py_tpfindname(py_Type type, py_Name name) {
  13. py_TypeInfo* ti = pk_typeinfo(type);
  14. return pk_tpfindname(ti, name);
  15. }
  16. PK_INLINE py_Ref py_tpfindmagic(py_Type t, py_Name name) {
  17. // assert(py_ismagicname(name));
  18. return py_tpfindname(t, name);
  19. }
  20. PK_INLINE py_Type py_tpbase(py_Type t) {
  21. assert(t);
  22. py_TypeInfo* ti = pk_typeinfo(t);
  23. return ti->base;
  24. }
  25. PK_DEPRECATED py_Ref py_tpgetmagic(py_Type type, py_Name name) {
  26. // assert(py_ismagicname(name));
  27. py_TypeInfo* ti = pk_typeinfo(type);
  28. py_Ref retval = py_getdict(&ti->self, name);
  29. return retval != NULL ? retval : py_NIL();
  30. }
  31. py_Ref py_tpobject(py_Type type) {
  32. assert(type);
  33. return &pk_typeinfo(type)->self;
  34. }
  35. const char* py_tpname(py_Type type) {
  36. if(!type) return "nil";
  37. py_Name name = pk_typeinfo(type)->name;
  38. return py_name2str(name);
  39. }
  40. PK_INLINE py_TypeInfo* pk_typeinfo(py_Type type) {
  41. #ifndef NDEBUG
  42. int length = pk_current_vm->types.length;
  43. if(type < 0 || type >= length) {
  44. c11__abort("type index %d is out of bounds [0, %d)", type, length);
  45. }
  46. #endif
  47. return c11__getitem(TypePointer, &pk_current_vm->types, type).ti;
  48. }
  49. static void py_TypeInfo__common_init(py_Name name,
  50. py_Type base,
  51. py_Type index,
  52. const py_GlobalRef module,
  53. void (*dtor)(void*),
  54. bool is_python,
  55. bool is_final,
  56. py_TypeInfo* self,
  57. py_TValue* typeobject) {
  58. py_TypeInfo* base_ti = base ? pk_typeinfo(base) : NULL;
  59. if(base_ti && base_ti->is_final) {
  60. c11__abort("type '%s' is not an acceptable base type", py_name2str(base_ti->name));
  61. }
  62. self->name = name;
  63. self->index = index;
  64. self->base = base;
  65. self->base_ti = base_ti;
  66. py_assign(&self->self, typeobject);
  67. self->module = module ? module : py_NIL();
  68. if(!dtor && base) dtor = base_ti->dtor;
  69. self->is_python = is_python;
  70. self->is_final = is_final;
  71. self->getattribute = NULL;
  72. self->setattribute = NULL;
  73. self->delattribute = NULL;
  74. self->getunboundmethod = NULL;
  75. self->annotations = *py_NIL();
  76. self->dtor = dtor;
  77. self->on_end_subclass = NULL;
  78. }
  79. py_Type pk_newtype(const char* name,
  80. py_Type base,
  81. const py_GlobalRef module,
  82. void (*dtor)(void*),
  83. bool is_python,
  84. bool is_final) {
  85. py_Type index = pk_current_vm->types.length;
  86. py_TypeInfo* self = py_newobject(py_retval(), tp_type, -1, sizeof(py_TypeInfo));
  87. py_TypeInfo__common_init(py_name(name),
  88. base,
  89. index,
  90. module,
  91. dtor,
  92. is_python,
  93. is_final,
  94. self,
  95. py_retval());
  96. TypePointer* pointer = c11_vector__emplace(&pk_current_vm->types);
  97. pointer->ti = self;
  98. pointer->dtor = self->dtor;
  99. return index;
  100. }
  101. py_Type pk_newtypewithmode(py_Name name,
  102. py_Type base,
  103. const py_GlobalRef module,
  104. void (*dtor)(void*),
  105. bool is_python,
  106. bool is_final,
  107. enum py_CompileMode mode) {
  108. if(mode == RELOAD_MODE && module != NULL) {
  109. py_ItemRef old_class = py_getdict(module, name);
  110. if(old_class != NULL && py_istype(old_class, tp_type)) {
  111. #ifndef NDEBUG
  112. const char* name_cstr = py_name2str(name);
  113. (void)name_cstr; // avoid unused warning
  114. #endif
  115. py_cleardict(old_class);
  116. py_TypeInfo* self = py_touserdata(old_class);
  117. py_Type index = self->index;
  118. py_TypeInfo__common_init(name,
  119. base,
  120. index,
  121. module,
  122. dtor,
  123. is_python,
  124. is_final,
  125. self,
  126. &self->self);
  127. TypePointer* pointer = c11__at(TypePointer, &pk_current_vm->types, index);
  128. pointer->ti = self;
  129. pointer->dtor = self->dtor;
  130. return index;
  131. }
  132. }
  133. return pk_newtype(py_name2str(name), base, module, dtor, is_python, is_final);
  134. }
  135. py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, void (*dtor)(void*)) {
  136. if(strlen(name) == 0) c11__abort("type name cannot be empty");
  137. py_Type type = pk_newtype(name, base, module, dtor, false, false);
  138. if(module) py_setdict(module, py_name(name), py_tpobject(type));
  139. return type;
  140. }
  141. void py_tpsetfinal(py_Type type) {
  142. assert(type);
  143. py_TypeInfo* ti = pk_typeinfo(type);
  144. ti->is_final = true;
  145. }
  146. void py_tphookattributes(py_Type type,
  147. bool (*getattribute)(py_Ref self, py_Name name),
  148. bool (*setattribute)(py_Ref self, py_Name name, py_Ref val),
  149. bool (*delattribute)(py_Ref self, py_Name name),
  150. bool (*getunboundmethod)(py_Ref self, py_Name name)) {
  151. assert(type);
  152. py_TypeInfo* ti = pk_typeinfo(type);
  153. ti->getattribute = getattribute;
  154. ti->setattribute = setattribute;
  155. ti->delattribute = delattribute;
  156. ti->getunboundmethod = getunboundmethod;
  157. }