| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- #pragma once
- #include "obj.h"
- #include "error.h"
- namespace pkpy{
- enum NameScope {
- NAME_LOCAL = 0,
- NAME_GLOBAL,
- NAME_ATTR,
- NAME_SPECIAL,
- };
- enum Opcode {
- #define OPCODE(name) OP_##name,
- #include "opcodes.h"
- #undef OPCODE
- };
- inline const char* OP_NAMES[] = {
- #define OPCODE(name) #name,
- #include "opcodes.h"
- #undef OPCODE
- };
- struct Bytecode{
- uint8_t op;
- uint16_t block;
- int arg;
- int line;
- };
- enum CodeBlockType {
- NO_BLOCK,
- FOR_LOOP,
- WHILE_LOOP,
- CONTEXT_MANAGER,
- TRY_EXCEPT,
- };
- struct CodeBlock {
- CodeBlockType type;
- int parent; // parent index in blocks
- int start; // start index of this block in codes, inclusive
- int end; // end index of this block in codes, exclusive
- };
- struct CodeObject {
- shared_ptr<SourceData> src;
- Str name;
- bool is_generator = false;
- CodeObject(shared_ptr<SourceData> src, Str name) {
- this->src = src;
- this->name = name;
- }
- std::vector<Bytecode> codes;
- List consts;
- std::vector<std::pair<StrName, NameScope>> names;
- std::map<StrName, int> global_names;
- std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} };
- std::map<StrName, int> labels;
- uint32_t perfect_locals_capacity = 2;
- uint32_t perfect_hash_seed = 0;
- void optimize(VM* vm);
- bool add_label(StrName label){
- if(labels.count(label)) return false;
- labels[label] = codes.size();
- return true;
- }
- int add_name(StrName name, NameScope scope){
- if(scope == NAME_LOCAL && global_names.count(name)) scope = NAME_GLOBAL;
- auto p = std::make_pair(name, scope);
- for(int i=0; i<names.size(); i++){
- if(names[i] == p) return i;
- }
- names.push_back(p);
- return names.size() - 1;
- }
- int add_const(PyObject* v){
- consts.push_back(v);
- return consts.size() - 1;
- }
- /************************************************/
- int _curr_block_i = 0;
- int _rvalue = 0;
- bool _is_compiling_class = false;
- bool _is_curr_block_loop() const {
- return blocks[_curr_block_i].type == FOR_LOOP || blocks[_curr_block_i].type == WHILE_LOOP;
- }
- void _enter_block(CodeBlockType type){
- blocks.push_back(CodeBlock{type, _curr_block_i, (int)codes.size()});
- _curr_block_i = blocks.size()-1;
- }
- void _exit_block(){
- blocks[_curr_block_i].end = codes.size();
- _curr_block_i = blocks[_curr_block_i].parent;
- if(_curr_block_i < 0) UNREACHABLE();
- }
- /************************************************/
- };
- } // namespace pkpy
|