add debugger framework
with function:backtrace,run,help,show global/local/upvalue,exit
This commit is contained in:
parent
6a543f2aa7
commit
189d49fa4a
|
@ -49,7 +49,7 @@ Also remember to use g++ or clang++.(mingw-w64 in Windows)
|
|||
|
||||
Or use this in linux/macOS/Unix
|
||||
|
||||
> [cpp compiler] -std=c++11 -O3 main.cpp -o nasal -fno-exceptions
|
||||
> [cpp compiler] -std=c++11 -O3 main.cpp -o nasal -fno-exceptions -ldl
|
||||
|
||||
## How to Use?
|
||||
|
||||
|
|
25
main.cpp
25
main.cpp
|
@ -1,4 +1,5 @@
|
|||
#include "nasal.h"
|
||||
|
||||
constexpr uint32_t VM_LEXINFO =1;
|
||||
constexpr uint32_t VM_ASTINFO =2;
|
||||
constexpr uint32_t VM_CODEINFO =4;
|
||||
|
@ -6,6 +7,8 @@ constexpr uint32_t VM_EXECTIME =8;
|
|||
constexpr uint32_t VM_OPCALLNUM=16;
|
||||
constexpr uint32_t VM_EXEC =32;
|
||||
constexpr uint32_t VM_DBGINFO =64;
|
||||
constexpr uint32_t VM_DEBUG =128;
|
||||
|
||||
void help()
|
||||
{
|
||||
std::cout
|
||||
|
@ -21,12 +24,13 @@ void help()
|
|||
<<" input file name to execute script file.\n\n"
|
||||
<<"nasal [options...] <file>\n"
|
||||
<<"option:\n"
|
||||
<<" -l, --lex | view token info.\n"
|
||||
<<" -a, --ast | view abstract syntax tree.\n"
|
||||
<<" -c, --code | view bytecode.\n"
|
||||
<<" -t, --time | execute and get the running time.\n"
|
||||
<<" -o, --opcnt | count operands while running.\n"
|
||||
<<" -d, --detail | get detail crash info.\n"
|
||||
<<" -l, --lex | view token info.\n"
|
||||
<<" -a, --ast | view abstract syntax tree.\n"
|
||||
<<" -c, --code | view bytecode.\n"
|
||||
<<" -t, --time | execute and get the running time.\n"
|
||||
<<" -o, --opcnt | execute and count used operands.\n"
|
||||
<<" -d, --detail| execute and get detail crash info.\n"
|
||||
<<" -dbg, --debug | debug mode (this will ignore -t -o -d).\n"
|
||||
<<"file:\n"
|
||||
<<" input file name to execute script file.\n";
|
||||
}
|
||||
|
@ -95,7 +99,12 @@ void execute(const std::string& file,const uint32_t cmd)
|
|||
parse.print();
|
||||
if(cmd&VM_CODEINFO)
|
||||
gen.print();
|
||||
if(cmd&VM_EXECTIME)
|
||||
if(cmd&VM_DEBUG)
|
||||
{
|
||||
nasal_dbg dbg;
|
||||
dbg.run(gen,linker);
|
||||
}
|
||||
else if(cmd&VM_EXECTIME)
|
||||
{
|
||||
clock_t t=clock();
|
||||
vm.run(gen,linker,cmd&VM_OPCALLNUM,cmd&VM_DBGINFO);
|
||||
|
@ -141,6 +150,8 @@ int main(int argc,const char* argv[])
|
|||
cmd|=VM_EXECTIME;
|
||||
else if(s=="--detail" || s=="-d")
|
||||
cmd|=VM_DBGINFO|VM_EXEC;
|
||||
else if(s=="--debug" || s=="-dbg")
|
||||
cmd|=VM_DEBUG;
|
||||
else
|
||||
err();
|
||||
}
|
||||
|
|
2
makefile
2
makefile
|
@ -1,5 +1,5 @@
|
|||
.PHONY=test
|
||||
nasal:main.cpp nasal_ast.h nasal_builtin.h nasal_codegen.h nasal_gc.h nasal_import.h nasal_lexer.h nasal_parse.h nasal_vm.h nasal.h
|
||||
nasal:main.cpp nasal_ast.h nasal_builtin.h nasal_codegen.h nasal_gc.h nasal_import.h nasal_lexer.h nasal_parse.h nasal_vm.h nasal_dbg.h nasal.h
|
||||
clang++ -std=c++11 -O3 main.cpp -o nasal -fno-exceptions -ldl -Wshadow -Wall
|
||||
test:nasal
|
||||
./nasal test/ascii-art.nas
|
||||
|
|
1
nasal.h
1
nasal.h
|
@ -135,5 +135,6 @@ std::string rawstr(const std::string& str)
|
|||
#include "nasal_builtin.h"
|
||||
#include "nasal_codegen.h"
|
||||
#include "nasal_vm.h"
|
||||
#include "nasal_dbg.h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1059,7 +1059,6 @@ nasal_ref builtin_platform(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
#elif defined __APPLE__
|
||||
*ret.str()="macOS";
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
|
@ -430,7 +430,7 @@ void nasal_codegen::func_gen(const nasal_ast& ast)
|
|||
|
||||
code[newfunc_label].num=code.size()+1;
|
||||
int jmp_ptr=code.size();
|
||||
gen(op_jmp,0,0);
|
||||
gen(op_jmp,0,ast.line());
|
||||
|
||||
const nasal_ast& block=ast[1];
|
||||
// search symbols first, must use after loading parameters
|
||||
|
@ -722,13 +722,13 @@ void nasal_codegen::conditional_gen(const nasal_ast& ast)
|
|||
{
|
||||
calc_gen(tmp[0]);
|
||||
int ptr=code.size();
|
||||
gen(op_jf,0,0);
|
||||
gen(op_jf,0,tmp.line());
|
||||
block_gen(tmp[1]);
|
||||
// without 'else' the last condition doesn't need to jmp
|
||||
if(&tmp!=&ast.child().back())
|
||||
{
|
||||
jmp_label.push_back(code.size());
|
||||
gen(op_jmp,0,0);
|
||||
gen(op_jmp,0,tmp.line());
|
||||
}
|
||||
code[ptr].num=code.size();
|
||||
}
|
||||
|
@ -770,10 +770,10 @@ void nasal_codegen::while_gen(const nasal_ast& ast)
|
|||
int loop_ptr=code.size();
|
||||
calc_gen(ast[0]);
|
||||
int condition_ptr=code.size();
|
||||
gen(op_jf,0,0);
|
||||
gen(op_jf,0,ast[0].line());
|
||||
|
||||
block_gen(ast[1]);
|
||||
gen(op_jmp,loop_ptr,0);
|
||||
gen(op_jmp,loop_ptr,ast[1].line());
|
||||
code[condition_ptr].num=code.size();
|
||||
load_continue_break(code.size()-1,code.size());
|
||||
}
|
||||
|
@ -813,7 +813,7 @@ void nasal_codegen::for_gen(const nasal_ast& ast)
|
|||
case ast_grt:
|
||||
case ast_trino:
|
||||
calc_gen(ast[0]);
|
||||
gen(op_pop,0,0);
|
||||
gen(op_pop,0,ast[0].line());
|
||||
break;
|
||||
}
|
||||
int jmp_place=code.size();
|
||||
|
@ -822,7 +822,7 @@ void nasal_codegen::for_gen(const nasal_ast& ast)
|
|||
else
|
||||
calc_gen(ast[1]);
|
||||
int label_exit=code.size();
|
||||
gen(op_jf,0,0);
|
||||
gen(op_jf,0,ast[1].line());
|
||||
|
||||
block_gen(ast[3]);
|
||||
int continue_place=code.size();
|
||||
|
@ -844,10 +844,10 @@ void nasal_codegen::for_gen(const nasal_ast& ast)
|
|||
case ast_less:case ast_geq:case ast_grt:
|
||||
case ast_trino:
|
||||
calc_gen(ast[2]);
|
||||
gen(op_pop,0,0);
|
||||
gen(op_pop,0,ast[2].line());
|
||||
break;
|
||||
}
|
||||
gen(op_jmp,jmp_place,0);
|
||||
gen(op_jmp,jmp_place,ast[2].line());
|
||||
code[label_exit].num=code.size();
|
||||
|
||||
load_continue_break(continue_place,code.size());
|
||||
|
@ -869,16 +869,16 @@ void nasal_codegen::forindex_gen(const nasal_ast& ast)
|
|||
{
|
||||
mcall(ast[0]);
|
||||
gen(op_meq,0,ast[0].line());
|
||||
gen(op_pop,0,0);
|
||||
gen(op_pop,0,ast[0].line());
|
||||
}
|
||||
++in_iterloop.top();
|
||||
block_gen(ast[2]);
|
||||
--in_iterloop.top();
|
||||
gen(op_jmp,ptr,0);
|
||||
gen(op_jmp,ptr,ast.line());
|
||||
code[ptr].num=code.size();
|
||||
load_continue_break(code.size()-1,code.size());
|
||||
gen(op_pop,0,0);// pop vector
|
||||
gen(op_pop,0,0);// pop iterator
|
||||
gen(op_pop,0,ast[1].line());// pop vector
|
||||
gen(op_pop,0,ast.line());// pop iterator
|
||||
}
|
||||
void nasal_codegen::foreach_gen(const nasal_ast& ast)
|
||||
{
|
||||
|
@ -897,31 +897,31 @@ void nasal_codegen::foreach_gen(const nasal_ast& ast)
|
|||
{
|
||||
mcall(ast[0]);
|
||||
gen(op_meq,0,ast[0].line());
|
||||
gen(op_pop,0,0);
|
||||
gen(op_pop,0,ast[0].line());
|
||||
}
|
||||
++in_iterloop.top();
|
||||
block_gen(ast[2]);
|
||||
--in_iterloop.top();
|
||||
gen(op_jmp,ptr,0);
|
||||
gen(op_jmp,ptr,ast.line());
|
||||
code[ptr].num=code.size();
|
||||
load_continue_break(code.size()-1,code.size());
|
||||
gen(op_pop,0,0);// pop vector
|
||||
gen(op_pop,0,0);// pop iterator
|
||||
gen(op_pop,0,ast[1].line());// pop vector
|
||||
gen(op_pop,0,ast.line());// pop iterator
|
||||
}
|
||||
|
||||
void nasal_codegen::or_gen(const nasal_ast& ast)
|
||||
{
|
||||
calc_gen(ast[0]);
|
||||
int l1=code.size();
|
||||
gen(op_jt,0,0);
|
||||
gen(op_jt,0,ast[0].line());
|
||||
|
||||
gen(op_pop,0,0);
|
||||
gen(op_pop,0,ast[0].line());
|
||||
calc_gen(ast[1]);
|
||||
int l2=code.size();
|
||||
gen(op_jt,0,0);
|
||||
gen(op_jt,0,ast[1].line());
|
||||
|
||||
gen(op_pop,0,0);
|
||||
gen(op_pnil,0,0);
|
||||
gen(op_pop,0,ast[1].line());
|
||||
gen(op_pnil,0,ast[1].line());
|
||||
|
||||
code[l1].num=code[l2].num=code.size();
|
||||
}
|
||||
|
@ -929,18 +929,18 @@ void nasal_codegen::or_gen(const nasal_ast& ast)
|
|||
void nasal_codegen::and_gen(const nasal_ast& ast)
|
||||
{
|
||||
calc_gen(ast[0]);
|
||||
gen(op_jt,code.size()+2,0);
|
||||
gen(op_jt,code.size()+2,ast[0].line());
|
||||
|
||||
int lfalse=code.size();
|
||||
gen(op_jmp,0,0);
|
||||
gen(op_pop,0,0);// jt jumps here
|
||||
gen(op_jmp,0,ast[0].line());
|
||||
gen(op_pop,0,ast[1].line());// jt jumps here
|
||||
|
||||
calc_gen(ast[1]);
|
||||
gen(op_jt,code.size()+3,0);
|
||||
gen(op_jt,code.size()+3,ast[1].line());
|
||||
|
||||
code[lfalse].num=code.size();
|
||||
gen(op_pop,0,0);
|
||||
gen(op_pnil,0,0);
|
||||
gen(op_pop,0,ast[1].line());
|
||||
gen(op_pnil,0,ast[1].line());
|
||||
//jt jumps here
|
||||
}
|
||||
|
||||
|
@ -948,10 +948,10 @@ void nasal_codegen::trino_gen(const nasal_ast& ast)
|
|||
{
|
||||
calc_gen(ast[0]);
|
||||
int lfalse=code.size();
|
||||
gen(op_jf,0,0);
|
||||
gen(op_jf,0,ast[0].line());
|
||||
calc_gen(ast[1]);
|
||||
int lexit=code.size();
|
||||
gen(op_jmp,0,0);
|
||||
gen(op_jmp,0,ast[1].line());
|
||||
code[lfalse].num=code.size();
|
||||
calc_gen(ast[2]);
|
||||
code[lexit].num=code.size();
|
||||
|
@ -1073,11 +1073,11 @@ void nasal_codegen::block_gen(const nasal_ast& ast)
|
|||
case ast_conditional:conditional_gen(tmp);break;
|
||||
case ast_continue:
|
||||
continue_ptr.front().push_back(code.size());
|
||||
gen(op_jmp,0,0);
|
||||
gen(op_jmp,0,tmp.line());
|
||||
break;
|
||||
case ast_break:
|
||||
break_ptr.front().push_back(code.size());
|
||||
gen(op_jmp,0,0);
|
||||
gen(op_jmp,0,tmp.line());
|
||||
break;
|
||||
case ast_while:
|
||||
case ast_for:
|
||||
|
@ -1126,7 +1126,7 @@ void nasal_codegen::block_gen(const nasal_ast& ast)
|
|||
case ast_grt:
|
||||
case ast_or:
|
||||
case ast_and:
|
||||
case ast_trino:calc_gen(tmp);gen(op_pop,0,0);break;
|
||||
case ast_trino:calc_gen(tmp);gen(op_pop,0,tmp.line());break;
|
||||
case ast_ret:ret_gen(tmp);break;
|
||||
}
|
||||
}
|
||||
|
@ -1135,8 +1135,8 @@ void nasal_codegen::ret_gen(const nasal_ast& ast)
|
|||
{
|
||||
for(uint32_t i=0;i<in_iterloop.top();++i)
|
||||
{
|
||||
gen(op_pop,0,0);
|
||||
gen(op_pop,0,0);
|
||||
gen(op_pop,0,ast.line());
|
||||
gen(op_pop,0,ast.line());
|
||||
}
|
||||
if(ast.size())
|
||||
calc_gen(ast[0]);
|
||||
|
@ -1231,25 +1231,26 @@ void nasal_codegen::print_op(uint32_t index)
|
|||
case op_addeqc:case op_subeqc: case op_muleqc:case op_diveqc:
|
||||
case op_lessc: case op_leqc: case op_grtc: case op_geqc:
|
||||
case op_pnum:
|
||||
printf("0x%x (",c.num);std::cout<<num_res[c.num]<<")\n";break;
|
||||
printf("0x%x (",c.num);std::cout<<num_res[c.num]<<")";break;
|
||||
case op_callvi:case op_newv: case op_callfv:
|
||||
case op_intg: case op_intl:
|
||||
case op_newf: case op_jmp: case op_jt: case op_jf:
|
||||
printf("0x%x\n",c.num);break;
|
||||
printf("0x%x",c.num);break;
|
||||
case op_callb:
|
||||
printf("0x%x <%s@0x%lx>\n",c.num,builtin[c.num].name,(uint64_t)builtin[c.num].func);break;
|
||||
printf("0x%x <%s@0x%lx>",c.num,builtin[c.num].name,(uint64_t)builtin[c.num].func);break;
|
||||
case op_callg: case op_mcallg: case op_loadg:
|
||||
case op_calll: case op_mcalll: case op_loadl:
|
||||
printf("0x%x\n",c.num);break;
|
||||
printf("0x%x",c.num);break;
|
||||
case op_upval:case op_mupval: case op_loadu:
|
||||
printf("0x%x[0x%x]\n",(c.num>>16)&0xffff,c.num&0xffff);break;
|
||||
printf("0x%x[0x%x]",(c.num>>16)&0xffff,c.num&0xffff);break;
|
||||
case op_happ: case op_pstr:
|
||||
case op_lnkc: case op_lnkeqc:
|
||||
case op_callh: case op_mcallh:
|
||||
case op_para: case op_defpara:case op_dynpara:
|
||||
printf("0x%x (\"%s\")\n",c.num,rawstr(str_res[c.num]).c_str());break;
|
||||
default:printf("\n");break;
|
||||
printf("0x%x (\"%s\")",c.num,rawstr(str_res[c.num]).c_str());break;
|
||||
default:break;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void nasal_codegen::print()
|
||||
|
|
|
@ -0,0 +1,258 @@
|
|||
#ifndef __NASAL_DBG_H__
|
||||
#define __NASAL_DBG_H__
|
||||
|
||||
#include "nasal_vm.h"
|
||||
|
||||
class nasal_dbg:public nasal_vm
|
||||
{
|
||||
private:
|
||||
std::vector<std::string> 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<std::string> nasal_dbg::parse(std::string& cmd)
|
||||
{
|
||||
std::vector<std::string> res;
|
||||
std::string tmp="";
|
||||
for(uint32_t i=0;i<cmd.length();++i)
|
||||
{
|
||||
if(cmd[i]==' ' && tmp.length())
|
||||
{
|
||||
res.push_back(tmp);
|
||||
tmp="";
|
||||
continue;
|
||||
}
|
||||
tmp+=cmd[i];
|
||||
}
|
||||
if(tmp.length())
|
||||
res.push_back(tmp);
|
||||
return res;
|
||||
}
|
||||
|
||||
uint16_t nasal_dbg::get_fileindex(std::string filename)
|
||||
{
|
||||
for(uint16_t i=0;i<files_size;++i)
|
||||
if(filename==files[i])
|
||||
return i;
|
||||
return 65535;
|
||||
}
|
||||
|
||||
void nasal_dbg::err()
|
||||
{
|
||||
std::cout
|
||||
<<"incorrect command\n"
|
||||
<<"input \'h\' to get help\n";
|
||||
}
|
||||
|
||||
void nasal_dbg::help()
|
||||
{
|
||||
std::cout
|
||||
<<"<option>\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<const void*> 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<canary)goto *code[++pc];goto vmexit;}
|
||||
|
||||
nop: dbg(opr_nop );
|
||||
intg: dbg(opr_intg );
|
||||
intl: dbg(opr_intl );
|
||||
loadg: dbg(opr_loadg );
|
||||
loadl: dbg(opr_loadl );
|
||||
loadu: dbg(opr_loadu );
|
||||
pnum: dbg(opr_pnum );
|
||||
pone: dbg(opr_pone );
|
||||
pzero: dbg(opr_pzero );
|
||||
pnil: dbg(opr_pnil );
|
||||
pstr: dbg(opr_pstr );
|
||||
newv: dbg(opr_newv );
|
||||
newh: dbg(opr_newh );
|
||||
newf: dbg(opr_newf );
|
||||
happ: dbg(opr_happ );
|
||||
para: dbg(opr_para );
|
||||
defpara: dbg(opr_defpara );
|
||||
dynpara: dbg(opr_dynpara );
|
||||
unot: dbg(opr_unot );
|
||||
usub: dbg(opr_usub );
|
||||
add: dbg(opr_add );
|
||||
sub: dbg(opr_sub );
|
||||
mul: dbg(opr_mul );
|
||||
div: dbg(opr_div );
|
||||
lnk: dbg(opr_lnk );
|
||||
addc: dbg(opr_addc );
|
||||
subc: dbg(opr_subc );
|
||||
mulc: dbg(opr_mulc );
|
||||
divc: dbg(opr_divc );
|
||||
lnkc: dbg(opr_lnkc );
|
||||
addeq: dbg(opr_addeq );
|
||||
subeq: dbg(opr_subeq );
|
||||
muleq: dbg(opr_muleq );
|
||||
diveq: dbg(opr_diveq );
|
||||
lnkeq: dbg(opr_lnkeq );
|
||||
addeqc: dbg(opr_addeqc );
|
||||
subeqc: dbg(opr_subeqc );
|
||||
muleqc: dbg(opr_muleqc );
|
||||
diveqc: dbg(opr_diveqc );
|
||||
lnkeqc: dbg(opr_lnkeqc );
|
||||
meq: dbg(opr_meq );
|
||||
eq: dbg(opr_eq );
|
||||
neq: dbg(opr_neq );
|
||||
less: dbg(opr_less );
|
||||
leq: dbg(opr_leq );
|
||||
grt: dbg(opr_grt );
|
||||
geq: dbg(opr_geq );
|
||||
lessc: dbg(opr_lessc );
|
||||
leqc: dbg(opr_leqc );
|
||||
grtc: dbg(opr_grtc );
|
||||
geqc: dbg(opr_geqc );
|
||||
pop: dbg(opr_pop );
|
||||
jmp: dbg(opr_jmp );
|
||||
jt: dbg(opr_jt );
|
||||
jf: dbg(opr_jf );
|
||||
counter: dbg(opr_counter );
|
||||
findex: dbg(opr_findex );
|
||||
feach: dbg(opr_feach );
|
||||
callg: dbg(opr_callg );
|
||||
calll: dbg(opr_calll );
|
||||
upval: dbg(opr_upval );
|
||||
callv: dbg(opr_callv );
|
||||
callvi: dbg(opr_callvi );
|
||||
callh: dbg(opr_callh );
|
||||
callfv: dbg(opr_callfv );
|
||||
callfh: dbg(opr_callfh );
|
||||
callb: dbg(opr_callb );
|
||||
slcbegin:dbg(opr_slcbegin);
|
||||
slcend: dbg(opr_slcend );
|
||||
slc: dbg(opr_slc );
|
||||
slc2: dbg(opr_slc2 );
|
||||
mcallg: dbg(opr_mcallg );
|
||||
mcalll: dbg(opr_mcalll );
|
||||
mupval: dbg(opr_mupval );
|
||||
mcallv: dbg(opr_mcallv );
|
||||
mcallh: dbg(opr_mcallh );
|
||||
ret: dbg(opr_ret );
|
||||
}
|
||||
|
||||
#endif
|
153
nasal_vm.h
153
nasal_vm.h
|
@ -3,7 +3,7 @@
|
|||
|
||||
class nasal_vm
|
||||
{
|
||||
private:
|
||||
protected:
|
||||
/* values of nasal_vm */
|
||||
uint32_t pc; // program counter
|
||||
uint32_t offset; // used to load default parameters to a new function
|
||||
|
@ -15,8 +15,9 @@ private:
|
|||
/* garbage collector */
|
||||
nasal_gc gc;
|
||||
/* values used for debug */
|
||||
const opcode* bytecode; // ref from nasal_codegen
|
||||
size_t files_size;
|
||||
const std::string* files; // ref from nasal_import
|
||||
const opcode* bytecode; // ref from nasal_codegen
|
||||
|
||||
void init(
|
||||
const std::vector<std::string>&,
|
||||
|
@ -25,9 +26,12 @@ private:
|
|||
/* debug functions */
|
||||
bool detail_info;
|
||||
void valinfo(nasal_ref&);
|
||||
void bytecodeinfo(const uint32_t);
|
||||
void bytecodeinfo(const char*,const uint32_t);
|
||||
void traceback();
|
||||
void stackinfo(const uint32_t);
|
||||
void global_state();
|
||||
void local_state();
|
||||
void upval_state();
|
||||
void detail();
|
||||
void opcallsort(const uint64_t*);
|
||||
void die(std::string);
|
||||
|
@ -116,6 +120,7 @@ public:
|
|||
const nasal_import&,
|
||||
const bool,
|
||||
const bool);
|
||||
|
||||
};
|
||||
|
||||
void nasal_vm::init(
|
||||
|
@ -127,32 +132,50 @@ void nasal_vm::init(
|
|||
num_table=nums.data();
|
||||
str_table=strs.data();
|
||||
files=filenames.data();
|
||||
files_size=filenames.size();
|
||||
}
|
||||
void nasal_vm::valinfo(nasal_ref& val)
|
||||
{
|
||||
const nasal_val* p=val.value.gcobj;
|
||||
printf("\t");
|
||||
switch(val.type)
|
||||
{
|
||||
case vm_none: printf("\t| null |\n");break;
|
||||
case vm_ret: printf("\t| addr | pc=0x%x\n",val.ret());break;
|
||||
case vm_cnt: printf("\t| cnt | %ld\n",val.cnt());break;
|
||||
case vm_nil: printf("\t| nil |\n");break;
|
||||
case vm_num: printf("\t| num | %lf\n",val.num());break;
|
||||
case vm_str: printf("\t| str | <0x%lx> %s\n",(uint64_t)p,rawstr(*val.str()).c_str());break;
|
||||
case vm_func: printf("\t| func | <0x%lx> entry=0x%x\n",(uint64_t)p,val.func()->entry);break;
|
||||
case vm_vec: printf("\t| vec | <0x%lx> [%lu val]\n",(uint64_t)p,val.vec()->elems.size());break;
|
||||
case vm_hash: printf("\t| hash | <0x%lx> {%lu member}\n",(uint64_t)p,val.hash()->elems.size());break;
|
||||
case vm_obj: printf("\t| obj | <0x%lx> object=0x%lx\n",(uint64_t)p,(uint64_t)val.obj()->ptr);break;
|
||||
default: printf("\t| ??? | <0x%lx>\n",(uint64_t)p);break;
|
||||
case vm_none: printf("| null |\n");break;
|
||||
case vm_ret: printf("| addr | pc=0x%x\n",val.ret());break;
|
||||
case vm_cnt: printf("| cnt | %ld\n",val.cnt());break;
|
||||
case vm_nil: printf("| nil |\n");break;
|
||||
case vm_num: printf("| num | ");std::cout<<val.num()<<'\n';break;
|
||||
case vm_str: printf("| str | <0x%lx> %s\n",(uint64_t)p,rawstr(*val.str()).c_str());break;
|
||||
case vm_func: printf("| func | <0x%lx> entry=0x%x\n",(uint64_t)p,val.func()->entry);break;
|
||||
case vm_vec: printf("| vec | <0x%lx> [%lu val]\n",(uint64_t)p,val.vec()->elems.size());break;
|
||||
case vm_hash: printf("| hash | <0x%lx> {%lu member}\n",(uint64_t)p,val.hash()->elems.size());break;
|
||||
case vm_obj: printf("| obj | <0x%lx> object=0x%lx\n",(uint64_t)p,(uint64_t)val.obj()->ptr);break;
|
||||
default: printf("| ??? | <0x%lx>\n",(uint64_t)p);break;
|
||||
}
|
||||
}
|
||||
void nasal_vm::bytecodeinfo(const uint32_t p)
|
||||
void nasal_vm::bytecodeinfo(const char* header,const uint32_t p)
|
||||
{
|
||||
const opcode& code=bytecode[p];
|
||||
printf("\t0x%.8x: %s 0x%x",p,code_table[code.op].name,code.num);
|
||||
if(code.op==op_callb)
|
||||
printf(" <%s@0x%lx>",builtin[code.num].name,(uint64_t)builtin[code.num].func);
|
||||
printf(" (<%s> line %d)\n",files[code.fidx].c_str(),code.line);
|
||||
const opcode& c=bytecode[p];
|
||||
printf("%s0x%.8x: %s 0x%x",header,p,code_table[c.op].name,c.num);
|
||||
switch(c.op)
|
||||
{
|
||||
case op_addc: case op_subc: case op_mulc: case op_divc:
|
||||
case op_addeqc:case op_subeqc: case op_muleqc:case op_diveqc:
|
||||
case op_lessc: case op_leqc: case op_grtc: case op_geqc:
|
||||
case op_pnum:
|
||||
std::cout<<" ("<<num_table[c.num]<<")";break;
|
||||
case op_callb:
|
||||
printf(" <%s@0x%lx>",builtin[c.num].name,(uint64_t)builtin[c.num].func);break;
|
||||
case op_happ: case op_pstr:
|
||||
case op_lnkc: case op_lnkeqc:
|
||||
case op_callh: case op_mcallh:
|
||||
case op_para: case op_defpara:case op_dynpara:
|
||||
printf(" (\"%s\")",rawstr(str_table[c.num]).c_str());break;
|
||||
case op_upval:case op_mupval: case op_loadu:
|
||||
printf(" (0x%x[0x%x])",(c.num>>16)&0xffff,c.num&0xffff);break;
|
||||
default:break;
|
||||
}
|
||||
printf(" (<%s> line %d)\n",files[c.fidx].c_str(),c.line);
|
||||
}
|
||||
void nasal_vm::traceback()
|
||||
{
|
||||
|
@ -177,7 +200,7 @@ void nasal_vm::traceback()
|
|||
if(same)
|
||||
printf("\t0x%.8x: %d same call(s)\n",last,same);
|
||||
same=0;
|
||||
bytecodeinfo(point);
|
||||
bytecodeinfo("\t",point);
|
||||
}
|
||||
if(same)
|
||||
printf("\t0x%.8x: %d same call(s)\n",last,same);
|
||||
|
@ -191,42 +214,60 @@ void nasal_vm::stackinfo(const uint32_t limit=10)
|
|||
for(uint32_t i=0;i<limit && top>=bottom;++i,--top)
|
||||
valinfo(top[0]);
|
||||
}
|
||||
void nasal_vm::global_state()
|
||||
{
|
||||
if(!bytecode[0].num) // bytecode[0].op is op_intg
|
||||
{
|
||||
printf("no global value exists\n");
|
||||
return;
|
||||
}
|
||||
printf("global:\n");
|
||||
for(uint32_t i=0;i<bytecode[0].num;++i)
|
||||
{
|
||||
printf("[0x%.8x]",i);
|
||||
valinfo(gc.stack[i]);
|
||||
}
|
||||
}
|
||||
void nasal_vm::local_state()
|
||||
{
|
||||
if(gc.local.empty() || !gc.local.back().vec()->elems.size())
|
||||
{
|
||||
printf("no local value exists\n");
|
||||
return;
|
||||
}
|
||||
printf("local:\n");
|
||||
auto& vec=gc.local.back().vec()->elems;
|
||||
for(uint32_t i=0;i<vec.size();++i)
|
||||
{
|
||||
printf("[0x%.8x]",i);
|
||||
valinfo(vec[i]);
|
||||
}
|
||||
}
|
||||
void nasal_vm::upval_state()
|
||||
{
|
||||
if(func_stk.empty() || func_stk.top()->upvalue.empty())
|
||||
{
|
||||
printf("no upvalue exists\n");
|
||||
return;
|
||||
}
|
||||
printf("upvalue:\n");
|
||||
auto& upval=func_stk.top()->upvalue;
|
||||
for(uint32_t i=0;i<upval.size();++i)
|
||||
{
|
||||
auto& vec=upval[i].vec()->elems;
|
||||
for(uint32_t j=0;j<vec.size();++j)
|
||||
{
|
||||
printf("[%.4x][%.4x]",i,j);
|
||||
valinfo(vec[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
void nasal_vm::detail()
|
||||
{
|
||||
printf("mcall address: 0x%lx\n",(uint64_t)mem_addr);
|
||||
if(bytecode[0].num) // bytecode[0] is op_intg
|
||||
{
|
||||
printf("global:\n");
|
||||
for(uint32_t i=0;i<bytecode[0].num;++i)
|
||||
{
|
||||
printf("[0x%.8x]",i);
|
||||
valinfo(gc.stack[i]);
|
||||
}
|
||||
}
|
||||
if(!gc.local.empty())
|
||||
{
|
||||
printf("local:\n");
|
||||
auto& vec=gc.local.back().vec()->elems;
|
||||
for(uint32_t i=0;i<vec.size();++i)
|
||||
{
|
||||
printf("[0x%.8x]",i);
|
||||
valinfo(vec[i]);
|
||||
}
|
||||
}
|
||||
if(!func_stk.empty() && !func_stk.top()->upvalue.empty())
|
||||
{
|
||||
printf("upvalue:\n");
|
||||
auto& upval=func_stk.top()->upvalue;
|
||||
for(uint32_t i=0;i<upval.size();++i)
|
||||
{
|
||||
auto& vec=upval[i].vec()->elems;
|
||||
for(uint32_t j=0;j<vec.size();++j)
|
||||
{
|
||||
printf("[%.4x][%.4x]",i,j);
|
||||
valinfo(vec[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
global_state();
|
||||
local_state();
|
||||
upval_state();
|
||||
}
|
||||
void nasal_vm::opcallsort(const uint64_t* arr)
|
||||
{
|
||||
|
@ -804,9 +845,9 @@ void nasal_vm::run(
|
|||
const nasal_codegen& gen,
|
||||
const nasal_import& linker,
|
||||
const bool opcnt,
|
||||
const bool debug)
|
||||
const bool detail)
|
||||
{
|
||||
detail_info=debug;
|
||||
detail_info=detail;
|
||||
init(gen.get_strs(),gen.get_nums(),linker.get_file());
|
||||
uint64_t count[op_exit+1]={0};
|
||||
const void* opr_table[]=
|
||||
|
|
|
@ -94,6 +94,7 @@ var math=
|
|||
atan2: func(x,y){return __builtin_atan2(x,y);},
|
||||
isnan: func(x) {return __builtin_isnan(x); }
|
||||
};
|
||||
|
||||
var D2R=math.pi/180;
|
||||
var FPS2KT=0.5925;
|
||||
var FT2M=0.3048;
|
||||
|
@ -137,4 +138,9 @@ var dylib=
|
|||
dlsym: func(lib,sym){return __builtin_dlsym; },
|
||||
dlclose: func(lib){return __builtin_dlclose; },
|
||||
dlcall: func(funcptr,args...){return __builtin_dlcall}
|
||||
};
|
||||
|
||||
var os=
|
||||
{
|
||||
platform: func(){return __builtin_platform;}
|
||||
};
|
20
test/bfs.nas
20
test/bfs.nas
|
@ -8,20 +8,25 @@ var map=[];
|
|||
for(var i=0;i<10;i+=1)
|
||||
{
|
||||
append(map,[]);
|
||||
for(var j=0;j<10;j+=1)
|
||||
for(var j=0;j<20;j+=1)
|
||||
append(map[i],(rand()>0.7));
|
||||
}
|
||||
|
||||
var prt=func()
|
||||
{
|
||||
var s="";
|
||||
if(os.platform()=="windows")
|
||||
system("cls");
|
||||
else
|
||||
system("clear");
|
||||
var s="+--------------------+\n";
|
||||
for(var i=0;i<10;i+=1)
|
||||
{
|
||||
for(var j=0;j<10;j+=1)
|
||||
s~="|";
|
||||
for(var j=0;j<20;j+=1)
|
||||
s~=pixel[map[i][j]];
|
||||
s~='\n';
|
||||
s~='|\n';
|
||||
}
|
||||
s~='----------\n';
|
||||
s~='+--------------------+\n';
|
||||
print(s);
|
||||
}
|
||||
|
||||
|
@ -31,6 +36,7 @@ var bfs=func(begin,end)
|
|||
var que=queue();
|
||||
que.push(begin);
|
||||
map[begin[0]][begin[1]]=2;
|
||||
map[end[0]][end[1]]=0;
|
||||
while(!que.empty())
|
||||
{
|
||||
var vertex=que.front();
|
||||
|
@ -45,7 +51,7 @@ var bfs=func(begin,end)
|
|||
prt();
|
||||
return;
|
||||
}
|
||||
if(0<=x and x<10 and 0<=y and y<10 and map[x][y]==0)
|
||||
if(0<=x and x<10 and 0<=y and y<20 and map[x][y]==0)
|
||||
{
|
||||
que.push([x,y]);
|
||||
map[x][y]=2;
|
||||
|
@ -57,4 +63,4 @@ var bfs=func(begin,end)
|
|||
return;
|
||||
}
|
||||
|
||||
bfs([0,0],[9,9]);
|
||||
bfs([0,0],[9,19]);
|
|
@ -1,6 +1,6 @@
|
|||
import("lib.nas");
|
||||
var filename=["main.cpp","nasal_ast.h","nasal_builtin.h","nasal_codegen.h","nasal_gc.h","nasal_import.h","nasal_lexer.h","nasal_parse.h","nasal_vm.h","nasal.h"];
|
||||
var space=[" "," ","",""," "," "," "," "," "," "];
|
||||
var filename=["main.cpp","nasal_ast.h","nasal_builtin.h","nasal_codegen.h","nasal_gc.h","nasal_import.h","nasal_lexer.h","nasal_parse.h","nasal_vm.h","nasal_dbg.h","nasal.h"];
|
||||
var space=[" "," ","",""," "," "," "," "," "," "," "];
|
||||
var enter_cnt=func(s)
|
||||
{
|
||||
var (cnt,len,enter)=(0,size(s),'\n'[0]);
|
||||
|
|
Loading…
Reference in New Issue