codeobject.h 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. inline 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. uint16_t block;
  24. int arg;
  25. int line;
  26. };
  27. enum CodeBlockType {
  28. NO_BLOCK,
  29. FOR_LOOP,
  30. WHILE_LOOP,
  31. CONTEXT_MANAGER,
  32. TRY_EXCEPT,
  33. };
  34. struct CodeBlock {
  35. CodeBlockType type;
  36. int parent; // parent index in blocks
  37. int start; // start index of this block in codes, inclusive
  38. int end; // end index of this block in codes, exclusive
  39. };
  40. struct CodeObject {
  41. shared_ptr<SourceData> src;
  42. Str name;
  43. bool is_generator = false;
  44. CodeObject(shared_ptr<SourceData> src, Str name) {
  45. this->src = src;
  46. this->name = name;
  47. }
  48. std::vector<Bytecode> codes;
  49. List consts;
  50. std::vector<std::pair<StrName, NameScope>> names;
  51. std::map<StrName, int> global_names;
  52. std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} };
  53. std::map<StrName, int> labels;
  54. uint32_t perfect_locals_capacity = 2;
  55. uint32_t perfect_hash_seed = 0;
  56. void optimize(VM* vm);
  57. bool add_label(StrName label){
  58. if(labels.count(label)) return false;
  59. labels[label] = codes.size();
  60. return true;
  61. }
  62. int add_name(StrName name, NameScope scope){
  63. if(scope == NAME_LOCAL && global_names.count(name)) scope = NAME_GLOBAL;
  64. auto p = std::make_pair(name, scope);
  65. for(int i=0; i<names.size(); i++){
  66. if(names[i] == p) return i;
  67. }
  68. names.push_back(p);
  69. return names.size() - 1;
  70. }
  71. int add_const(PyObject* v){
  72. consts.push_back(v);
  73. return consts.size() - 1;
  74. }
  75. /************************************************/
  76. int _curr_block_i = 0;
  77. int _rvalue = 0;
  78. bool _is_compiling_class = false;
  79. bool _is_curr_block_loop() const {
  80. return blocks[_curr_block_i].type == FOR_LOOP || blocks[_curr_block_i].type == WHILE_LOOP;
  81. }
  82. void _enter_block(CodeBlockType type){
  83. blocks.push_back(CodeBlock{type, _curr_block_i, (int)codes.size()});
  84. _curr_block_i = blocks.size()-1;
  85. }
  86. void _exit_block(){
  87. blocks[_curr_block_i].end = codes.size();
  88. _curr_block_i = blocks[_curr_block_i].parent;
  89. if(_curr_block_i < 0) UNREACHABLE();
  90. }
  91. /************************************************/
  92. };
  93. } // namespace pkpy