🚀 import information output of dbg, vm and codegen

This commit is contained in:
ValKmjolnir 2022-09-11 17:22:00 +08:00
parent 6a6eab8db5
commit aa5b1d3d66
7 changed files with 177 additions and 171 deletions

View File

@ -1,6 +1,9 @@
#ifndef __NASAL_AST_H__
#define __NASAL_AST_H__
#include <vector>
#include <cstring>
enum ast_node:u32
{
ast_null=0, // null node
@ -128,14 +131,15 @@ const char* ast_name[]=
class nasal_ast
{
private:
u32 _line;
u32 _column;
u32 _type;
f64 _num;
string _str;
std::vector<nasal_ast> _child;
u32 node_line;
u32 node_col;
u32 node_type;
f64 node_num;
string node_str;
std::vector<nasal_ast> node_child;
public:
nasal_ast(const u32 l,const u32 c,const u32 t):_line(l),_column(c),_type(t),_num(0){}
nasal_ast(const u32 l,const u32 c,const u32 t):
node_line(l),node_col(c),node_type(t),node_num(0){}
nasal_ast(const nasal_ast&);
nasal_ast(nasal_ast&&);
void tree();
@ -144,74 +148,74 @@ public:
nasal_ast& operator=(const nasal_ast&);
nasal_ast& operator=(nasal_ast&&);
nasal_ast& operator[](usize n){return _child[n];}
const nasal_ast& operator[](usize n) const {return _child[n];}
usize size() const {return _child.size();}
nasal_ast& operator[](usize n){return node_child[n];}
const nasal_ast& operator[](usize n) const {return node_child[n];}
usize size() const {return node_child.size();}
void add(nasal_ast&& ast){_child.push_back(std::move(ast));}
void add(const nasal_ast& ast){_child.push_back(ast);}
void set_line(const u32 l){_line=l;}
void set_type(const u32 t){_type=t;}
void set_str(const string& s){_str=s;}
void set_num(const f64 n){_num=n;}
void add(nasal_ast&& ast){node_child.push_back(std::move(ast));}
void add(const nasal_ast& ast){node_child.push_back(ast);}
void set_line(const u32 l){node_line=l;}
void set_type(const u32 t){node_type=t;}
void set_str(const string& s){node_str=s;}
void set_num(const f64 n){node_num=n;}
inline u32 line() const {return _line;}
inline u32 col() const {return _column;}
inline u32 type() const {return _type;}
inline f64 num() const {return _num;}
inline const string& str() const {return _str;}
inline const std::vector<nasal_ast>& child() const {return _child;}
inline std::vector<nasal_ast>& child(){return _child;}
inline u32 line() const {return node_line;}
inline u32 col() const {return node_col;}
inline u32 type() const {return node_type;}
inline f64 num() const {return node_num;}
inline const string& str() const {return node_str;}
inline const std::vector<nasal_ast>& child() const {return node_child;}
inline std::vector<nasal_ast>& child(){return node_child;}
};
nasal_ast::nasal_ast(const nasal_ast& tmp):
_str(tmp._str),_child(tmp._child)
node_str(tmp.node_str),node_child(tmp.node_child)
{
_line=tmp._line;
_column=tmp._column;
_type=tmp._type;
_num =tmp._num;
node_line=tmp.node_line;
node_col=tmp.node_col;
node_type=tmp.node_type;
node_num =tmp.node_num;
}
nasal_ast::nasal_ast(nasal_ast&& tmp)
{
_line=tmp._line;
_column=tmp._column;
_type=tmp._type;
_num =tmp._num;
_str.swap(tmp._str);
_child.swap(tmp._child);
node_line=tmp.node_line;
node_col=tmp.node_col;
node_type=tmp.node_type;
node_num =tmp.node_num;
node_str.swap(tmp.node_str);
node_child.swap(tmp.node_child);
}
nasal_ast& nasal_ast::operator=(const nasal_ast& tmp)
{
_line=tmp._line;
_column=tmp._column;
_type=tmp._type;
_num=tmp._num;
_str=tmp._str;
_child=tmp._child;
node_line=tmp.node_line;
node_col=tmp.node_col;
node_type=tmp.node_type;
node_num=tmp.node_num;
node_str=tmp.node_str;
node_child=tmp.node_child;
return *this;
}
nasal_ast& nasal_ast::operator=(nasal_ast&& tmp)
{
_line=tmp._line;
_column=tmp._column;
_type=tmp._type;
_num=tmp._num;
_str.swap(tmp._str);
_child.swap(tmp._child);
node_line=tmp.node_line;
node_col=tmp.node_col;
node_type=tmp.node_type;
node_num=tmp.node_num;
node_str.swap(tmp.node_str);
node_child.swap(tmp.node_child);
return *this;
}
void nasal_ast::clear()
{
_line=_column=0;
_num=0;
_str="";
_type=ast_null;
_child.clear();
node_line=node_col=0;
node_num=0;
node_str.clear();
node_type=ast_null;
node_child.clear();
}
void nasal_ast::tree()
@ -224,14 +228,16 @@ void nasal_ast::print(u32 depth,bool last,std::vector<string>& indent)
{
for(auto& i:indent)
std::cout<<i;
std::cout<<ast_name[_type];
if(_type==ast_str || _type==ast_id ||
_type==ast_default || _type==ast_dynamic ||
_type==ast_callh)
std::cout<<":"<<rawstr(_str);
else if(_type==ast_num || _type==ast_file)
std::cout<<":"<<_num;
std::cout<<'\n';
std::cout<<ast_name[node_type];
if(node_type==ast_str ||
node_type==ast_id ||
node_type==ast_default ||
node_type==ast_dynamic ||
node_type==ast_callh)
std::cout<<":"<<rawstr(node_str);
else if(node_type==ast_num || node_type==ast_file)
std::cout<<":"<<node_num;
std::cout<<"\n";
if(last && depth)
indent.back()=" ";
else if(!last && depth)
@ -240,14 +246,14 @@ void nasal_ast::print(u32 depth,bool last,std::vector<string>& indent)
#else
indent.back()="";
#endif
for(u32 i=0;i<_child.size();++i)
for(u32 i=0;i<node_child.size();++i)
{
#ifdef _WIN32
indent.push_back(i==_child.size()-1?"+-":"|-");
indent.push_back(i==node_child.size()-1?"+-":"|-");
#else
indent.push_back(i==_child.size()-1?"└─":"├─");
indent.push_back(i==node_child.size()-1?"└─":"├─");
#endif
_child[i].print(depth+1,i==_child.size()-1,indent);
node_child[i].print(depth+1,i==node_child.size()-1,indent);
indent.pop_back();
}
}

View File

@ -386,13 +386,7 @@ nas_ref builtin_keys(nas_ref* local,nasal_gc& gc)
}
nas_ref builtin_die(nas_ref* local,nasal_gc& gc)
{
nas_ref str=local[1];
if(str.type!=vm_str)
return nas_err("die","\"str\" must be string");
std::cerr<<bold_red<<"[vm] error: "
<<bold_white<<str.str()<<'\n'
<<reset;
return {vm_none};
return nas_err("error",local[1].tostr());
}
nas_ref builtin_find(nas_ref* local,nasal_gc& gc)
{

View File

@ -125,66 +125,78 @@ struct opcode
line=tmp.line;
return *this;
}
void print(const char*,
const f64*,
const string*,
const u32,bool) const;
};
void opcode::print(const char* header,
const f64* constnum,
const string* conststr,
const u32 index,
bool deftnum=false) const
class codestream
{
std::cout<<bold_cyan<<header<<reset<<std::hex<<"0x"
<<std::setw(8)<<std::setfill('0')<<index<<": "
<<std::setw(2)<<std::setfill('0')<<(u32)op<<" "
<<std::setw(2)<<std::setfill('0')<<((num>>24)&0xff)<<" "
<<std::setw(2)<<std::setfill('0')<<((num>>16)&0xff)<<" "
<<std::setw(2)<<std::setfill('0')<<((num>>8)&0xff)<<" "
<<std::setw(2)<<std::setfill('0')<<(num&0xff)
<<" "<<code_table[op]<<" "<<std::dec;
switch(op)
private:
opcode code;
const u32 index;
const f64* nums;
const string* strs;
const string* files;
public:
codestream(const opcode& c,const u32 i,const f64* n,const string* s,const string* f=nullptr):
code(c.op,c.fidx,c.num,c.line),index(i),nums(n),strs(s),files(f){}
friend std::ostream& operator<<(std::ostream& out,const codestream& ins)
{
case op_addeq: case op_subeq: case op_muleq: case op_diveq:
case op_lnkeq: case op_meq:
std::cout<<std::hex<<"0x"<<num<<std::dec
<<" sp-"<<num;break;
case op_addeqc:case op_subeqc: case op_muleqc:case op_diveqc:
std::cout<<std::hex<<"0x"<<(num&0x7fffffff)<<std::dec
<<" ("<<constnum[num&0x7fffffff]<<") sp-"
<<(num>>31);break;
case op_lnkeqc:
std::cout<<std::hex<<"0x"<<(num&0x7fffffff)<<std::dec<<" (\""
<<rawstr(conststr[num&0x7fffffff],16)<<"\") sp-"
<<(num>>31);break;
case op_addc: case op_subc: case op_mulc: case op_divc:
case op_lessc: case op_leqc: case op_grtc: case op_geqc:
case op_pnum:
std::cout<<std::hex<<"0x"<<num<<std::dec<<" ("
<<constnum[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:
case op_callg: case op_mcallg: case op_loadg:
case op_calll: case op_mcalll: case op_loadl:
std::cout<<std::hex<<"0x"<<num<<std::dec;break;
case op_callb:
std::cout<<std::hex<<"0x"<<num<<" <"<<builtin[num].name
<<"@0x"<<(u64)builtin[num].func<<std::dec<<">";break;
case op_upval: case op_mupval: case op_loadu:
std::cout<<std::hex<<"0x"<<((num>>16)&0xffff)
<<"[0x"<<(num&0xffff)<<"]"<<std::dec;break;
case op_happ: case op_pstr:
case op_lnkc:
case op_callh: case op_mcallh:
case op_para: case op_deft: case op_dyn:
std::cout<<std::hex<<"0x"<<num<<std::dec
<<" (\""<<rawstr(conststr[num],16)<<"\")";break;
default:if(deftnum)std::cout<<std::hex<<"0x"<<num<<std::dec;break;
u8 op=ins.code.op;
u32 num=ins.code.num;
out<<std::hex<<"0x"
<<std::setw(8)<<std::setfill('0')<<ins.index<<" "
<<std::setw(2)<<std::setfill('0')<<(u32)op<<" "
<<std::setw(2)<<std::setfill('0')<<((num>>24)&0xff)<<" "
<<std::setw(2)<<std::setfill('0')<<((num>>16)&0xff)<<" "
<<std::setw(2)<<std::setfill('0')<<((num>>8)&0xff)<<" "
<<std::setw(2)<<std::setfill('0')<<(num&0xff)<<" "
<<code_table[op]<<" "<<std::dec;
switch(op)
{
case op_addeq: case op_subeq: case op_muleq: case op_diveq:
case op_lnkeq: case op_meq:
out<<std::hex<<"0x"<<num<<std::dec
<<" sp-"<<num;break;
case op_addeqc:case op_subeqc: case op_muleqc:case op_diveqc:
out<<std::hex<<"0x"<<(num&0x7fffffff)<<std::dec
<<" ("<<ins.nums[num&0x7fffffff]<<") sp-"
<<(num>>31);break;
case op_lnkeqc:
out<<std::hex<<"0x"<<(num&0x7fffffff)<<std::dec<<" (\""
<<rawstr(ins.strs[num&0x7fffffff],16)<<"\") sp-"
<<(num>>31);break;
case op_addc: case op_subc: case op_mulc: case op_divc:
case op_lessc: case op_leqc: case op_grtc: case op_geqc:
case op_pnum:
out<<std::hex<<"0x"<<num<<std::dec<<" ("
<<ins.nums[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:
case op_callg: case op_mcallg: case op_loadg:
case op_calll: case op_mcalll: case op_loadl:
out<<std::hex<<"0x"<<num<<std::dec;break;
case op_callb:
out<<std::hex<<"0x"<<num<<" <"<<builtin[num].name
<<"@0x"<<(u64)builtin[num].func<<std::dec<<">";break;
case op_upval: case op_mupval: case op_loadu:
out<<std::hex<<"0x"<<((num>>16)&0xffff)
<<"[0x"<<(num&0xffff)<<"]"<<std::dec;break;
case op_happ: case op_pstr:
case op_lnkc:
case op_callh: case op_mcallh:
case op_para: case op_deft: case op_dyn:
out<<std::hex<<"0x"<<num<<std::dec
<<" (\""<<rawstr(ins.strs[num],16)<<"\")";break;
default:
if(ins.files)
out<<std::hex<<"0x"<<num<<std::dec;
break;
}
if(ins.files)
out<<" ("<<ins.files[ins.code.fidx]<<":"<<ins.code.line<<")";
return out;
}
}
};
class nasal_codegen
{
@ -1265,8 +1277,7 @@ void nasal_codegen::singleop(const u32 index)
break;
}
}
c.print(" ",num_res.data(),str_res.data(),index);
std::cout<<"\n";
std::cout<<" "<<codestream(c,index,num_res.data(),str_res.data())<<"\n";
}
void nasal_codegen::print()

View File

@ -113,19 +113,21 @@ void nasal_dbg::callsort(const u64* arr)
void nasal_dbg::stepinfo()
{
u32 begin,end;
u32 line=bytecode[pc].line==0?0:bytecode[pc].line-1;
u32 begin=(line>>3)==0?0:((line>>3)<<3);
u32 end=(1+(line>>3))<<3;
src.load(files[bytecode[pc].fidx]);
std::cout<<"\nsource code:\n";
begin=(line>>3)==0?0:((line>>3)<<3);
end=(1+(line>>3))<<3;
for(u32 i=begin;i<end && i<src.size();++i)
std::cout<<bold_cyan<<(i==line?"--> ":" ")<<reset<<src[i]<<"\n";
std::cout<<(i==line?back_white:reset)<<(i==line?"--> ":" ")<<src[i]<<reset<<"\n";
std::cout<<"next bytecode:\n";
begin=(pc>>3)==0?0:((pc>>3)<<3);
end=(1+(pc>>3))<<3;
for(u32 i=begin;i<end && bytecode[i].op!=op_exit;++i)
bytecodeinfo(i==pc?"--> ":" ",i);
std::cout
<<(i==pc?back_white:reset)<<(i==pc?"--> ":" ")
<<codestream(bytecode[i],i,num_table,str_table,files)
<<reset<<"\n";
stackinfo(10);
}

View File

@ -17,6 +17,15 @@ struct for_reset
}reset_ter_color;
#endif
std::ostream& back_white(std::ostream& s)
{
#ifdef _WIN32
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0xf0);
#else
s<<"\033[7m";
#endif
return s;
}
std::ostream& bold_red(std::ostream& s)
{
#ifdef _WIN32
@ -74,24 +83,19 @@ public:
if(file==f) return; // don't need to load a loaded file
file=f;
res.clear();
std::ifstream fin(f,std::ios::binary);
if(fin.fail())
std::ifstream in(f,std::ios::binary);
if(in.fail())
{
std::cerr<<bold_red<<"src: "<<reset<<"cannot open <"<<f<<">\n";
std::exit(1);
}
string line;
while(!fin.eof())
while(!in.eof())
{
std::getline(fin,line);
std::getline(in,line);
res.push_back(line);
}
}
void clear()
{
std::vector<string> tmp;
res.swap(tmp);
}
const string& operator[](usize n){return res[n];}
const string& name(){return file;}
usize size(){return res.size();}

View File

@ -723,9 +723,7 @@ void nasal_gc::ctxreserve()
// use to print error log and return error value
nas_ref nas_err(const string& err_f,const string& info)
{
std::cerr<<bold_red<<"[vm] "<<err_f<<": "
<<bold_white<<info<<"\n"
<<reset;
std::cerr<<"[vm] "<<err_f<<": "<<info<<"\n";
return {vm_none};
}
#endif

View File

@ -3,8 +3,7 @@
#include <iomanip>
#include <stack>
#include "nasal_err.h"
#include "nasal_codegen.h"
class nasal_vm
{
@ -39,7 +38,6 @@ protected:
/* debug functions */
bool detail_info;
void valinfo(nas_ref&);
void bytecodeinfo(const char*,const u32);
void traceback();
void stackinfo(const u32);
void reginfo();
@ -200,22 +198,17 @@ void nasal_vm::valinfo(nas_ref& val)
}
std::cout<<"\n";
}
void nasal_vm::bytecodeinfo(const char* header,const u32 p)
{
const opcode& c=bytecode[p];
c.print(header,num_table,str_table,p,true);
std::cout<<" ("<<files[c.fidx]<<":"<<c.line<<")\n";
}
void nasal_vm::traceback()
{
nas_ref* bottom=stack+bytecode[0].num; // bytecode[0] is op_intg
nas_ref* main_ctx_top=gc.stack==stack?top:gc.mctx.top; // if error occurs in coroutine, this works
/* bytecode[0].num is the global size */
nas_ref* bottom=gc.stack==stack?stack+bytecode[0].num:gc.stack;
nas_ref* ctx_top=gc.stack==stack?top:gc.top;
std::stack<u32> ret;
for(nas_ref* i=bottom;i<=main_ctx_top;++i)
if(i->type==vm_ret)
for(nas_ref* i=bottom;i<=ctx_top;++i)
if(i->type==vm_ret && i->ret()!=0)
ret.push(i->ret());
ret.push(pc); // store the position program crashed
std::cout<<"trace back:\n";
std::cout<<"trace back ("<<(gc.stack==stack?"main":"coroutine")<<")\n";
for(u32 p=0,same=0,prev=0xffffffff;!ret.empty();prev=p,ret.pop())
{
if((p=ret.top())==prev)
@ -228,18 +221,18 @@ void nasal_vm::traceback()
<<" 0x"<<std::hex<<std::setw(8)<<std::setfill('0')
<<prev<<std::dec<<": "<<same<<" same call(s)\n";
same=0;
bytecodeinfo(" ",p);
std::cout<<" "<<codestream(bytecode[p],p,num_table,str_table,files)<<"\n";
}
// the first called place has no same calls
}
void nasal_vm::stackinfo(const u32 limit=10)
{
/* bytecode[0].num is the global size */
u32 gsize=gc.stack==stack?bytecode[0].num:0;
nas_ref* t=top;
nas_ref* bottom=gc.stack+gsize;
std::cout<<"vm stack(0x"<<std::hex<<(u64)bottom<<std::dec
<<"<sp+"<<gsize<<">, limit "<<limit<<", total "
const u32 gsize=gc.stack==stack?bytecode[0].num:0;
nas_ref* t=top;
nas_ref* bottom=gc.stack+gsize;
std::cout<<"vm stack (0x"<<std::hex<<(u64)bottom<<std::dec
<<" <sp+"<<gsize<<">, limit "<<limit<<", total "
<<(t<bottom? 0:(i64)(t-bottom+1))<<")\n";
for(u32 i=0;i<limit && t>=bottom;++i,--t)
{
@ -251,7 +244,7 @@ void nasal_vm::stackinfo(const u32 limit=10)
}
void nasal_vm::reginfo()
{
std::cout<<"registers("<<(gc.cort?"coroutine":"main")<<")\n"<<std::hex
std::cout<<"registers ("<<(gc.cort?"coroutine":"main")<<")\n"<<std::hex
<<" [ pc ] | pc | 0x"<<pc<<"\n"
<<" [ global ] | addr | 0x"<<(u64)stack<<"\n"
<<" [ localr ] | addr | 0x"<<(u64)localr<<"\n"
@ -266,7 +259,7 @@ void nasal_vm::gstate()
{
if(!bytecode[0].num || stack[0].type==vm_none) // bytecode[0].op is op_intg
return;
std::cout<<"global(0x"<<std::hex<<(u64)stack<<"<sp+0>)\n"<<std::dec;
std::cout<<"global (0x"<<std::hex<<(u64)stack<<" <sp+0>)\n"<<std::dec;
for(u32 i=0;i<bytecode[0].num;++i)
{
std::cout<<" 0x"<<std::hex<<std::setw(8)
@ -279,8 +272,8 @@ void nasal_vm::lstate()
if(!localr || !funcr.func().lsize)
return;
const u32 lsize=funcr.func().lsize;
std::cout<<"local(0x"<<std::hex<<(u64)localr
<<"<sp+"<<(u64)(localr-gc.stack)<<">)\n"<<std::dec;
std::cout<<"local (0x"<<std::hex<<(u64)localr
<<" <sp+"<<(u64)(localr-gc.stack)<<">)\n"<<std::dec;
for(u32 i=0;i<lsize;++i)
{
std::cout<<" 0x"<<std::hex<<std::setw(8)
@ -317,9 +310,7 @@ void nasal_vm::detail()
[[noreturn]]
void nasal_vm::die(const string& str)
{
std::cout<<bold_red<<"[vm] error: "
<<bold_white<<str<<"\n"
<<reset;
std::cout<<"[vm] error: "<<str<<"\n";
traceback();
stackinfo();
if(detail_info)