codeobject.h 2.7 KB

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