codeobject.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #pragma once
  2. #include "obj.h"
  3. #include "error.h"
  4. namespace pkpy{
  5. enum NameScope {
  6. NAME_LOCAL = 0,
  7. NAME_GLOBAL,
  8. NAME_ATTR,
  9. NAME_SPECIAL,
  10. };
  11. enum Opcode {
  12. #define OPCODE(name) OP_##name,
  13. #include "opcodes.h"
  14. #undef OPCODE
  15. };
  16. static const char* OP_NAMES[] = {
  17. #define OPCODE(name) #name,
  18. #include "opcodes.h"
  19. #undef OPCODE
  20. };
  21. struct Bytecode{
  22. uint8_t op;
  23. int arg;
  24. int line;
  25. uint16_t block;
  26. };
  27. Str pad(const Str& s, const int n){
  28. if(s.size() >= n) return s.substr(0, n);
  29. return s + std::string(n - s.size(), ' ');
  30. }
  31. enum CodeBlockType {
  32. NO_BLOCK,
  33. FOR_LOOP,
  34. WHILE_LOOP,
  35. CONTEXT_MANAGER,
  36. TRY_EXCEPT,
  37. };
  38. struct CodeBlock {
  39. CodeBlockType type;
  40. int parent; // parent index in blocks
  41. int start; // start index of this block in codes, inclusive
  42. int end; // end index of this block in codes, exclusive
  43. std::string to_string() const {
  44. if(parent == -1) return "";
  45. return "[B:" + std::to_string(type) + "]";
  46. }
  47. };
  48. struct CodeObject {
  49. shared_ptr<SourceData> src;
  50. Str name;
  51. bool is_generator = false;
  52. CodeObject(shared_ptr<SourceData> src, Str name) {
  53. this->src = src;
  54. this->name = name;
  55. }
  56. std::vector<Bytecode> codes;
  57. List consts;
  58. std::vector<std::pair<StrName, NameScope>> names;
  59. std::map<StrName, int> global_names;
  60. std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} };
  61. std::map<StrName, int> labels;
  62. uint32_t perfect_locals_capacity = 2;
  63. uint32_t perfect_hash_seed = 0;
  64. void optimize(VM* vm);
  65. bool add_label(StrName label){
  66. if(labels.count(label)) return false;
  67. labels[label] = codes.size();
  68. return true;
  69. }
  70. int add_name(StrName name, NameScope scope){
  71. if(scope == NAME_LOCAL && global_names.count(name)) scope = NAME_GLOBAL;
  72. auto p = std::make_pair(name, scope);
  73. for(int i=0; i<names.size(); i++){
  74. if(names[i] == p) return i;
  75. }
  76. names.push_back(p);
  77. return names.size() - 1;
  78. }
  79. int add_const(PyVar v){
  80. consts.push_back(v);
  81. return consts.size() - 1;
  82. }
  83. /************************************************/
  84. int _curr_block_i = 0;
  85. int _rvalue = 0;
  86. bool _is_compiling_class = false;
  87. bool _is_curr_block_loop() const {
  88. return blocks[_curr_block_i].type == FOR_LOOP || blocks[_curr_block_i].type == WHILE_LOOP;
  89. }
  90. void _enter_block(CodeBlockType type){
  91. blocks.push_back(CodeBlock{type, _curr_block_i, (int)codes.size()});
  92. _curr_block_i = blocks.size()-1;
  93. }
  94. void _exit_block(){
  95. blocks[_curr_block_i].end = codes.size();
  96. _curr_block_i = blocks[_curr_block_i].parent;
  97. if(_curr_block_i < 0) UNREACHABLE();
  98. }
  99. /************************************************/
  100. };
  101. } // namespace pkpy