codeobject.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. #pragma once
  2. #include "obj.h"
  3. #include "error.h"
  4. namespace pkpy{
  5. enum NameScope { NAME_LOCAL, NAME_GLOBAL, NAME_GLOBAL_UNKNOWN };
  6. enum Opcode {
  7. #define OPCODE(name) OP_##name,
  8. #include "opcodes.h"
  9. #undef OPCODE
  10. };
  11. inline const char* OP_NAMES[] = {
  12. #define OPCODE(name) #name,
  13. #include "opcodes.h"
  14. #undef OPCODE
  15. };
  16. struct Bytecode{
  17. uint16_t op;
  18. uint16_t block;
  19. int arg;
  20. };
  21. enum CodeBlockType {
  22. NO_BLOCK,
  23. FOR_LOOP,
  24. WHILE_LOOP,
  25. CONTEXT_MANAGER,
  26. TRY_EXCEPT,
  27. };
  28. inline const int BC_NOARG = -1;
  29. inline const int BC_KEEPLINE = -1;
  30. struct CodeBlock {
  31. CodeBlockType type;
  32. int parent; // parent index in blocks
  33. int for_loop_depth; // this is used for exception handling
  34. int start; // start index of this block in codes, inclusive
  35. int end; // end index of this block in codes, exclusive
  36. CodeBlock(CodeBlockType type, int parent, int for_loop_depth, int start):
  37. type(type), parent(parent), for_loop_depth(for_loop_depth), start(start), end(-1) {}
  38. };
  39. struct CodeObject;
  40. typedef shared_ptr<CodeObject> CodeObject_;
  41. struct FuncDecl;
  42. using FuncDecl_ = shared_ptr<FuncDecl>;
  43. struct CodeObjectSerializer{
  44. std::string buffer;
  45. int depth = 0;
  46. std::set<StrName> names;
  47. static const char END = '\n';
  48. CodeObjectSerializer();
  49. void write_int(i64 v);
  50. void write_float(f64 v);
  51. void write_str(const Str& v);
  52. void write_none();
  53. void write_ellipsis();
  54. void write_bool(bool v);
  55. void write_begin_mark();
  56. void write_name(StrName name);
  57. void write_end_mark();
  58. template<typename T>
  59. void write_bytes(T v){
  60. static_assert(std::is_trivially_copyable<T>::value);
  61. buffer += 'x';
  62. char* p = (char*)&v;
  63. for(int i=0; i<sizeof(T); i++){
  64. char c = p[i];
  65. buffer += "0123456789abcdef"[(c >> 4) & 0xf];
  66. buffer += "0123456789abcdef"[c & 0xf];
  67. }
  68. buffer += END;
  69. }
  70. void write_object(VM* vm, PyObject* obj);
  71. void write_code(VM* vm, const CodeObject* co);
  72. std::string str();
  73. };
  74. struct CodeObject {
  75. shared_ptr<SourceData> src;
  76. Str name;
  77. bool is_generator = false;
  78. std::vector<Bytecode> codes;
  79. std::vector<int> lines; // line number for each bytecode
  80. List consts;
  81. std::vector<StrName> varnames; // local variables
  82. NameDictInt varnames_inv;
  83. std::vector<CodeBlock> blocks = { CodeBlock(NO_BLOCK, -1, 0, 0) };
  84. NameDictInt labels;
  85. std::vector<FuncDecl_> func_decls;
  86. CodeObject(shared_ptr<SourceData> src, const Str& name);
  87. void _gc_mark() const;
  88. void write(VM* vm, CodeObjectSerializer& ss) const;
  89. Str serialize(VM* vm) const;
  90. };
  91. struct FuncDecl {
  92. struct KwArg {
  93. int key; // index in co->varnames
  94. PyObject* value; // default value
  95. };
  96. CodeObject_ code; // code object of this function
  97. pod_vector<int> args; // indices in co->varnames
  98. pod_vector<KwArg> kwargs; // indices in co->varnames
  99. int starred_arg = -1; // index in co->varnames, -1 if no *arg
  100. int starred_kwarg = -1; // index in co->varnames, -1 if no **kwarg
  101. bool nested = false; // whether this function is nested
  102. Str signature; // signature of this function
  103. Str docstring; // docstring of this function
  104. void _gc_mark() const;
  105. };
  106. struct UserData{
  107. char data[16];
  108. bool empty;
  109. UserData(): empty(true) {}
  110. template<typename T>
  111. UserData(T t): empty(false){
  112. static_assert(std::is_trivially_copyable_v<T>);
  113. static_assert(sizeof(T) <= sizeof(data));
  114. memcpy(data, &t, sizeof(T));
  115. }
  116. template <typename T>
  117. T get() const{
  118. static_assert(std::is_trivially_copyable_v<T>);
  119. static_assert(sizeof(T) <= sizeof(data));
  120. #if PK_DEBUG_EXTRA_CHECK
  121. PK_ASSERT(!empty);
  122. #endif
  123. return reinterpret_cast<const T&>(data);
  124. }
  125. };
  126. struct NativeFunc {
  127. NativeFuncC f;
  128. // old style argc-based call
  129. int argc;
  130. // new style decl-based call
  131. FuncDecl_ decl;
  132. UserData _userdata;
  133. void set_userdata(UserData data) {
  134. if(!_userdata.empty && !data.empty){
  135. // override is not supported
  136. throw std::runtime_error("userdata already set");
  137. }
  138. _userdata = data;
  139. }
  140. NativeFunc(NativeFuncC f, int argc, bool method);
  141. NativeFunc(NativeFuncC f, FuncDecl_ decl);
  142. void check_size(VM* vm, ArgsView args) const;
  143. PyObject* call(VM* vm, ArgsView args) const;
  144. };
  145. struct Function{
  146. FuncDecl_ decl;
  147. PyObject* _module;
  148. NameDict_ _closure;
  149. };
  150. template<>
  151. struct Py_<Function> final: PyObject {
  152. Function _value;
  153. Py_(Type type, Function val): PyObject(type), _value(val) {
  154. enable_instance_dict();
  155. }
  156. void _obj_gc_mark() override {
  157. _value.decl->_gc_mark();
  158. if(_value._module != nullptr) PK_OBJ_MARK(_value._module);
  159. if(_value._closure != nullptr) gc_mark_namedict(*_value._closure);
  160. }
  161. };
  162. template<>
  163. struct Py_<NativeFunc> final: PyObject {
  164. NativeFunc _value;
  165. Py_(Type type, NativeFunc val): PyObject(type), _value(val) {
  166. enable_instance_dict();
  167. }
  168. void _obj_gc_mark() override {
  169. if(_value.decl != nullptr){
  170. _value.decl->_gc_mark();
  171. }
  172. }
  173. };
  174. template<typename T>
  175. T lambda_get_userdata(PyObject** p){
  176. if(p[-1] != PY_NULL) return PK_OBJ_GET(NativeFunc, p[-1])._userdata.get<T>();
  177. else return PK_OBJ_GET(NativeFunc, p[-2])._userdata.get<T>();
  178. }
  179. } // namespace pkpy