#ifndef __NASAL_DBG_H__ #define __NASAL_DBG_H__ #include "nasal_vm.h" class nasal_dbg:public nasal_vm { private: std::vector parse(std::string&); uint16_t get_fileindex(std::string); void err(); void help(); void interact(); public: void run( const nasal_codegen&, const nasal_import& ); }; std::vector nasal_dbg::parse(std::string& cmd) { std::vector res; std::string tmp=""; for(uint32_t i=0;i\n" <<"\th, help | get help\n" <<"\tbt, backtrace | get function call trace\n" <<"\tr, run | run program until break point or exit\n" <<"\tg, global | see global values\n" <<"\tl, local | see local values\n" <<"\tu, upval | see upvalue\n" <<"\tquit, exit | exit debugger\n"; } void nasal_dbg::interact() { static uint16_t last_fidx=0; static uint32_t last_line=0; if(bytecode[pc].op==op_intg) { std::cout <<"nasal debug mode\n" <<"input \'h\' to get help\n"; } else if(bytecode[pc].op==op_exit) { std::cout<<"debugger exited successfully\n"; return; } else if(bytecode[pc].op==op_nop) return; if(bytecode[pc].fidx!=last_fidx || bytecode[pc].line!=last_line) return; last_fidx=0; last_line=0; std::string cmd; bytecodeinfo("->\t",pc); for(uint32_t i=1;i<5 && bytecode[pc+i].op!=op_exit;++i) bytecodeinfo(" \t",pc+i); while(1) { printf(">> "); std::getline(std::cin,cmd); auto res=parse(cmd); switch(res.size()) { case 1: if(res[0]=="h" || res[0]=="help") help(); else if(res[0]=="bt" || res[0]=="backtrace") traceback(); else if(res[0]=="r" || res[0]=="run") return; else if(res[0]=="g" || res[0]=="global") global_state(); else if(res[0]=="l" || res[0]=="local") local_state(); else if(res[0]=="u" || res[0]=="upval") upval_state(); else if(res[0]=="quit" || res[0]=="exit") std::exit(0); else err(); break; case 3: std::cout<<"unfinished\n"; break; default:err();break; } } } void nasal_dbg::run( const nasal_codegen& gen, const nasal_import& linker) { detail_info=true; init(gen.get_strs(),gen.get_nums(),linker.get_file()); const void* opr_table[]= { &&nop, &&intg, &&intl, &&loadg, &&loadl, &&loadu, &&pnum, &&pone, &&pzero, &&pnil, &&pstr, &&newv, &&newh, &&newf, &&happ, &¶, &&defpara, &&dynpara, &&unot, &&usub, &&add, &&sub, &&mul, &&div, &&lnk, &&addc, &&subc, &&mulc, &&divc, &&lnkc, &&addeq, &&subeq, &&muleq, &&diveq, &&lnkeq, &&addeqc, &&subeqc, &&muleqc, &&diveqc, &&lnkeqc, &&meq, &&eq, &&neq, &&less, &&leq, &&grt, &&geq, &&lessc, &&leqc, &&grtc, &&geqc, &&pop, &&jmp, &&jt, &&jf, &&counter, &&findex, &&feach, &&callg, &&calll, &&upval, &&callv, &&callvi, &&callh, &&callfv, &&callfh, &&callb, &&slcbegin, &&slcend, &&slc, &&slc2, &&mcallg, &&mcalll, &&mupval, &&mcallv, &&mcallh, &&ret, &&vmexit }; bytecode=gen.get_code().data(); std::vector code; for(auto& i:gen.get_code()) { code.push_back(opr_table[i.op]); imm.push_back(i.num); } // set canary and program counter auto canary=gc.stack+STACK_MAX_DEPTH-1; pc=0; // goto the first operand goto *code[pc]; vmexit: if(gc.top>=canary) die("stack overflow"); gc.clear(); imm.clear(); return; #define dbg(op) {interact();op();if(gc.top