add debugger framework

with function:backtrace,run,help,show global/local/upvalue,exit
This commit is contained in:
ValKmjolnir 2021-12-20 21:33:22 +08:00
parent 6a543f2aa7
commit 189d49fa4a
11 changed files with 440 additions and 117 deletions

View File

@ -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?

View File

@ -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();
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()

258
nasal_dbg.h Normal file
View File

@ -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, &&para,
&&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

View File

@ -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[]=

View File

@ -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;}
};

View File

@ -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]);

View File

@ -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]);