enum.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. #include "pocketpy/pocketpy.h"
  2. #include "pocketpy/interpreter/vm.h"
  3. #include "pocketpy/common/sstream.h"
  4. static bool Enum__wrapper_field(py_Name name, py_Ref value, void* ctx) {
  5. c11_sv name_sv = py_name2sv(name);
  6. if(name_sv.size == 0 || name_sv.data[0] == '_') return true;
  7. py_push(ctx);
  8. py_pushnil();
  9. py_assign(py_pushtmp(), py_name2ref(name));
  10. py_push(value);
  11. bool ok = py_vectorcall(2, 0);
  12. if(!ok) return false;
  13. py_assign(value, py_retval());
  14. return true;
  15. }
  16. static void Enum__on_end_subclass(py_TypeInfo* derived_ti) {
  17. derived_ti->is_final = true;
  18. py_applydict(&derived_ti->self, Enum__wrapper_field, &derived_ti->self);
  19. }
  20. static bool Enum__new__(int argc, py_Ref argv) {
  21. py_newobject(py_retval(), py_totype(argv), 2, 0);
  22. return true;
  23. }
  24. static bool Enum__init__(int argc, py_Ref argv) {
  25. PY_CHECK_ARGC(3);
  26. PY_CHECK_ARG_TYPE(1, tp_str);
  27. py_setslot(argv, 0, py_arg(1));
  28. py_setslot(argv, 1, py_arg(2));
  29. py_newnone(py_retval());
  30. return true;
  31. }
  32. static bool Enum__str__(int argc, py_Ref argv) {
  33. PY_CHECK_ARGC(1);
  34. // f'{type(self).__name__}.{self.name}'
  35. c11_sbuf buf;
  36. c11_sbuf__ctor(&buf);
  37. c11_sbuf__write_cstr(&buf, py_tpname(argv->type));
  38. c11_sbuf__write_char(&buf, '.');
  39. c11_sbuf__write_cstr(&buf, py_tostr(py_getslot(argv, 0)));
  40. c11_sbuf__py_submit(&buf, py_retval());
  41. return true;
  42. }
  43. static bool Enum__repr__(int argc, py_Ref argv) {
  44. PY_CHECK_ARGC(1);
  45. // f'<{str(self)}: {self.value!r}>'
  46. if(!py_str(argv)) return false;
  47. py_push(py_retval()); // str(self)
  48. if(!py_repr(py_getslot(argv, 1))) return false;
  49. py_push(py_retval()); // repr(self.value)
  50. c11_sbuf buf;
  51. c11_sbuf__ctor(&buf);
  52. c11_sbuf__write_cstr(&buf, "<");
  53. c11_sbuf__write_cstr(&buf, py_tostr(py_peek(-2)));
  54. c11_sbuf__write_cstr(&buf, ": ");
  55. c11_sbuf__write_cstr(&buf, py_tostr(py_peek(-1)));
  56. c11_sbuf__write_cstr(&buf, ">");
  57. c11_sbuf__py_submit(&buf, py_retval());
  58. py_shrink(2);
  59. return true;
  60. }
  61. static bool Enum__name(int argc, py_Ref argv) {
  62. py_assign(py_retval(), py_getslot(argv, 0));
  63. return true;
  64. }
  65. static bool Enum__value(int argc, py_Ref argv) {
  66. py_assign(py_retval(), py_getslot(argv, 1));
  67. return true;
  68. }
  69. void pk__add_module_enum() {
  70. py_Ref mod = py_newmodule("enum");
  71. py_Type type = py_newtype("Enum", tp_object, mod, NULL);
  72. py_bindmagic(type, __new__, Enum__new__);
  73. py_bindmagic(type, __init__, Enum__init__);
  74. py_bindmagic(type, __str__, Enum__str__);
  75. py_bindmagic(type, __repr__, Enum__repr__);
  76. py_bindproperty(type, "name", Enum__name, NULL);
  77. py_bindproperty(type, "value", Enum__value, NULL);
  78. pk_typeinfo(type)->on_end_subclass = Enum__on_end_subclass;
  79. }