codeobject.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #pragma once
  2. #include "obj.h"
  3. #include "error.h"
  4. #include "any.h"
  5. namespace pkpy{
  6. enum NameScope { NAME_LOCAL, NAME_GLOBAL, NAME_GLOBAL_UNKNOWN };
  7. enum Opcode: uint8_t {
  8. #define OPCODE(name) OP_##name,
  9. #include "opcodes.h"
  10. #undef OPCODE
  11. };
  12. struct Bytecode{
  13. uint8_t op;
  14. uint16_t arg;
  15. };
  16. enum class CodeBlockType {
  17. NO_BLOCK,
  18. FOR_LOOP,
  19. WHILE_LOOP,
  20. CONTEXT_MANAGER,
  21. TRY_EXCEPT,
  22. };
  23. inline const uint8_t BC_NOARG = 0;
  24. inline const int BC_KEEPLINE = -1;
  25. struct CodeBlock {
  26. CodeBlockType type;
  27. int parent; // parent index in blocks
  28. int base_stack_size; // this is used for exception handling
  29. int start; // start index of this block in codes, inclusive
  30. int end; // end index of this block in codes, exclusive
  31. int end2; // ...
  32. CodeBlock(CodeBlockType type, int parent, int base_stack_size, int start):
  33. type(type), parent(parent), base_stack_size(base_stack_size), start(start), end(-1), end2(-1) {}
  34. int get_break_end() const{
  35. if(end2 != -1) return end2;
  36. return end;
  37. }
  38. };
  39. struct CodeObject;
  40. struct FuncDecl;
  41. using CodeObject_ = std::shared_ptr<CodeObject>;
  42. using FuncDecl_ = std::shared_ptr<FuncDecl>;
  43. struct CodeObject {
  44. struct LineInfo{
  45. int lineno; // line number for each bytecode
  46. bool is_virtual; // whether this bytecode is virtual (not in source code)
  47. };
  48. std::shared_ptr<SourceData> src;
  49. Str name;
  50. std::vector<Bytecode> codes;
  51. std::vector<int> iblocks; // block index for each bytecode
  52. std::vector<LineInfo> lines;
  53. small_vector_no_copy_and_move<PyObject*, 8> consts; // constants
  54. small_vector_no_copy_and_move<StrName, 8> varnames; // local variables
  55. NameDictInt varnames_inv;
  56. std::vector<CodeBlock> blocks;
  57. NameDictInt labels;
  58. std::vector<FuncDecl_> func_decls;
  59. int start_line;
  60. int end_line;
  61. const CodeBlock& _get_block_codei(int codei) const{
  62. return blocks[iblocks[codei]];
  63. }
  64. CodeObject(std::shared_ptr<SourceData> src, const Str& name);
  65. void _gc_mark() const;
  66. };
  67. enum class FuncType{
  68. UNSET,
  69. NORMAL,
  70. SIMPLE,
  71. EMPTY,
  72. GENERATOR,
  73. };
  74. struct FuncDecl {
  75. struct KwArg {
  76. int index; // index in co->varnames
  77. StrName key; // name of this argument
  78. PyObject* value; // default value
  79. };
  80. CodeObject_ code; // code object of this function
  81. small_vector_no_copy_and_move<int, 6> args; // indices in co->varnames
  82. small_vector_no_copy_and_move<KwArg, 6> kwargs; // indices in co->varnames
  83. int starred_arg = -1; // index in co->varnames, -1 if no *arg
  84. int starred_kwarg = -1; // index in co->varnames, -1 if no **kwarg
  85. bool nested = false; // whether this function is nested
  86. const char* docstring; // docstring of this function (weak ref)
  87. FuncType type = FuncType::UNSET;
  88. NameDictInt kw_to_index;
  89. void add_kwarg(int index, StrName key, PyObject* value){
  90. kw_to_index.set(key, index);
  91. kwargs.push_back(KwArg{index, key, value});
  92. }
  93. void _gc_mark() const;
  94. };
  95. struct NativeFunc {
  96. NativeFuncC f;
  97. // old style argc-based call
  98. int argc;
  99. // new style decl-based call
  100. FuncDecl_ decl;
  101. any _userdata;
  102. void set_userdata(any&& data) {
  103. if(_userdata){
  104. throw std::runtime_error("NativeFunc userdata already set");
  105. }
  106. _userdata = std::move(data);
  107. }
  108. NativeFunc(NativeFuncC f, int argc): f(f), argc(argc) {}
  109. NativeFunc(NativeFuncC f, FuncDecl_ decl): f(f), argc(-1), decl(decl) {}
  110. void check_size(VM* vm, ArgsView args) const;
  111. PyObject* call(VM* vm, ArgsView args) const { return f(vm, args); }
  112. };
  113. struct Function{
  114. FuncDecl_ decl;
  115. PyObject* _module; // weak ref
  116. PyObject* _class; // weak ref
  117. NameDict_ _closure;
  118. explicit Function(FuncDecl_ decl, PyObject* _module, PyObject* _class, NameDict_ _closure):
  119. decl(decl), _module(_module), _class(_class), _closure(_closure) {}
  120. };
  121. template<>
  122. struct Py_<Function> final: PyObject {
  123. Function _value;
  124. template<typename... Args>
  125. Py_(Type type, Args&&... args): PyObject(type), _value(std::forward<Args>(args)...) {
  126. // _enable_instance_dict();
  127. }
  128. void _obj_gc_mark() override {
  129. _value.decl->_gc_mark();
  130. if(_value._closure != nullptr) _gc_mark_namedict(_value._closure.get());
  131. }
  132. };
  133. template<>
  134. struct Py_<NativeFunc> final: PyObject {
  135. NativeFunc _value;
  136. template<typename... Args>
  137. Py_(Type type, Args&&... args): PyObject(type), _value(std::forward<Args>(args)...) {
  138. // _enable_instance_dict();
  139. }
  140. void _obj_gc_mark() override {
  141. if(_value.decl != nullptr){
  142. _value.decl->_gc_mark();
  143. }
  144. }
  145. };
  146. template<typename T>
  147. T& lambda_get_userdata(PyObject** p){
  148. static_assert(std::is_same_v<T, std::decay_t<T>>);
  149. any* ud;
  150. if(p[-1] != PY_NULL) ud = &PK_OBJ_GET(NativeFunc, p[-1])._userdata;
  151. else ud = &PK_OBJ_GET(NativeFunc, p[-2])._userdata;
  152. T* out;
  153. if(!any_cast(*ud, &out)) throw std::runtime_error("lambda_get_userdata: any_cast failed");
  154. return *out;
  155. }
  156. } // namespace pkpy