codeobject.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #pragma once
  2. #include "obj.h"
  3. #include "pointer.h"
  4. #include "error.h"
  5. enum Opcode {
  6. #define OPCODE(name) OP_##name,
  7. #include "opcodes.h"
  8. #undef OPCODE
  9. };
  10. static const char* OP_NAMES[] = {
  11. #define OPCODE(name) #name,
  12. #include "opcodes.h"
  13. #undef OPCODE
  14. };
  15. struct ByteCode{
  16. uint8_t op;
  17. int arg;
  18. uint16_t line;
  19. };
  20. _Str pad(const _Str& s, const int n){
  21. return s + std::string(n - s.size(), ' ');
  22. }
  23. struct CodeObject {
  24. _Source src;
  25. _Str name;
  26. CodeObject(_Source src, _Str name) {
  27. this->src = src;
  28. this->name = name;
  29. }
  30. CompileMode mode() const {
  31. return src->mode;
  32. }
  33. std::vector<ByteCode> co_code;
  34. PyVarList co_consts;
  35. std::vector<NamePointer> co_names;
  36. std::vector<_Str> co_global_names;
  37. // for goto use
  38. // note: some opcodes moves the bytecode, such as listcomp
  39. // goto/label should be put at toplevel statements
  40. emhash8::HashMap<_Str, int> co_labels;
  41. void addLabel(const _Str& label){
  42. if(co_labels.find(label) != co_labels.end()){
  43. _Str msg = "label '" + label + "' already exists";
  44. throw std::runtime_error(msg.c_str());
  45. }
  46. co_labels[label] = co_code.size();
  47. }
  48. int addName(_Str name, NameScope scope){
  49. name.intern();
  50. if(scope == NAME_LOCAL && std::find(co_global_names.begin(), co_global_names.end(), name) != co_global_names.end()){
  51. scope = NAME_GLOBAL;
  52. }
  53. auto p = NamePointer(name, scope);
  54. for(int i=0; i<co_names.size(); i++){
  55. if(co_names[i] == p) return i;
  56. }
  57. co_names.push_back(p);
  58. return co_names.size() - 1;
  59. }
  60. int addConst(PyVar v){
  61. co_consts.push_back(v);
  62. return co_consts.size() - 1;
  63. }
  64. void __moveToEnd(int start, int end){
  65. auto _start = co_code.begin() + start;
  66. auto _end = co_code.begin() + end;
  67. co_code.insert(co_code.end(), _start, _end);
  68. for(int i=start; i<end; i++) co_code[i].op = OP_DELETED_OP;
  69. }
  70. _Str toString(){
  71. _StrStream ss;
  72. int prev_line = -1;
  73. for(int i=0; i<co_code.size(); i++){
  74. const ByteCode& byte = co_code[i];
  75. if(byte.op == OP_NO_OP) continue;
  76. _Str line = std::to_string(byte.line);
  77. if(byte.line == prev_line) line = "";
  78. else{
  79. if(prev_line != -1) ss << "\n";
  80. prev_line = byte.line;
  81. }
  82. ss << pad(line, 12) << " " << pad(std::to_string(i), 3);
  83. ss << " " << pad(OP_NAMES[byte.op], 20) << " ";
  84. ss << (byte.arg == -1 ? "" : std::to_string(byte.arg));
  85. if(i != co_code.size() - 1) ss << '\n';
  86. }
  87. _StrStream consts;
  88. consts << "co_consts: ";
  89. for(int i=0; i<co_consts.size(); i++){
  90. consts << co_consts[i]->getTypeName();
  91. if(i != co_consts.size() - 1) consts << ", ";
  92. }
  93. _StrStream names;
  94. names << "co_names: ";
  95. for(int i=0; i<co_names.size(); i++){
  96. names << co_names[i].name;
  97. if(i != co_names.size() - 1) names << ", ";
  98. }
  99. ss << '\n' << consts.str() << '\n' << names.str() << '\n';
  100. for(int i=0; i<co_consts.size(); i++){
  101. auto fn = std::get_if<_Func>(&co_consts[i]->_native);
  102. if(fn) ss << '\n' << (*fn)->code->name << ":\n" << (*fn)->code->toString();
  103. }
  104. return _Str(ss.str());
  105. }
  106. };
  107. class Frame {
  108. private:
  109. std::vector<PyVar> s_data;
  110. int ip = 0;
  111. std::stack<int> forLoops; // record the FOR_ITER bytecode index
  112. public:
  113. PyVar _module;
  114. PyVarDict f_locals;
  115. uint64_t id;
  116. inline PyVarDict& f_globals(){
  117. return _module->attribs;
  118. }
  119. const CodeObject* code;
  120. Frame(const CodeObject* code, PyVar _module, const PyVarDict& locals)
  121. : code(code), _module(_module), f_locals(locals) {
  122. static uint64_t frame_id = 1;
  123. id = frame_id++;
  124. }
  125. inline const ByteCode& readCode() {
  126. return code->co_code[ip++];
  127. }
  128. _Str errorSnapshot(){
  129. int line = code->co_code[ip-1].line;
  130. return code->src->snapshot(line);
  131. }
  132. inline int stackSize() const {
  133. return s_data.size();
  134. }
  135. inline bool isCodeEnd() const {
  136. return ip >= code->co_code.size();
  137. }
  138. inline PyVar __pop(){
  139. if(s_data.empty()) throw std::runtime_error("s_data.empty() is true");
  140. PyVar v = std::move(s_data.back());
  141. s_data.pop_back();
  142. return v;
  143. }
  144. inline PyVar __deref_pointer(VM*, PyVar);
  145. inline PyVar popValue(VM* vm){
  146. return __deref_pointer(vm, __pop());
  147. }
  148. inline PyVar topValue(VM* vm){
  149. if(s_data.empty()) throw std::runtime_error("s_data.empty() is true");
  150. return __deref_pointer(vm, s_data.back());
  151. }
  152. inline PyVar& __top(){
  153. if(s_data.empty()) throw std::runtime_error("s_data.empty() is true");
  154. return s_data.back();
  155. }
  156. inline PyVar __topValueN(VM* vm, int n=-1){
  157. return __deref_pointer(vm, s_data[s_data.size() + n]);
  158. }
  159. inline void push(const PyVar& v){
  160. s_data.push_back(v);
  161. }
  162. inline void push(PyVar&& v){
  163. s_data.emplace_back(std::move(v));
  164. }
  165. void __reportForIter(){
  166. int lastIp = ip - 1;
  167. if(forLoops.empty()) forLoops.push(lastIp);
  168. else{
  169. if(forLoops.top() == lastIp) return;
  170. if(forLoops.top() < lastIp) forLoops.push(lastIp);
  171. else UNREACHABLE();
  172. }
  173. }
  174. inline void jump(int i){
  175. this->ip = i;
  176. }
  177. void safeJump(int i){
  178. this->ip = i;
  179. while(!forLoops.empty()){
  180. int start = forLoops.top();
  181. int end = code->co_code[start].arg;
  182. if(i < start || i >= end){
  183. //printf("%d <- [%d, %d)\n", i, start, end);
  184. __pop(); // pop the iterator
  185. forLoops.pop();
  186. }else{
  187. break;
  188. }
  189. }
  190. }
  191. pkpy::ArgList popNValuesReversed(VM* vm, int n){
  192. pkpy::ArgList v(n);
  193. for(int i=n-1; i>=0; i--) v._index(i) = std::move(popValue(vm));
  194. return v;
  195. }
  196. pkpy::ArgList __popNReversed(int n){
  197. pkpy::ArgList v(n);
  198. for(int i=n-1; i>=0; i--) v._index(i) = std::move(__pop());
  199. return v;
  200. }
  201. };