加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
nas_code.h 17.78 KB
一键复制 编辑 原始数据 按行查看 历史
Valk Richard Li 提交于 2021-04-14 17:11 . change scope from map to vector
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
#ifndef __NAS_CODE_H__
#define __NAS_CODE_H__
enum opcode_type
{
// loop end mark
op_nop=0,
// push value
op_nil,
op_pushn,
op_pushs,
op_pushv,
op_pushh,
op_pushf,
op_vapp,
op_happ,
op_para,
op_dynpara,
// space size
op_intg,
op_intl,
// load
op_loadg,
op_loadl,
// call
op_callg,
op_calll,
op_callv,
op_callh,
op_callf,
// mem_call
op_mcallg,
op_mcalll,
op_mcallv,
op_mcallh,
// operator
op_neg,
op_not,
op_plus,
op_minus,
op_mult,
op_div,
op_lnk,
// assignment
op_meq,
op_pluseq,
op_minuseq,
op_lnkeq,
op_multeq,
op_diveq,
// compare operator
op_eq,
op_neq,
op_less,
op_leq,
op_grt,
op_geq,
// stack operator
op_pop,
// branch
op_jmp,
op_jt,
op_jf,
// function return
op_ret
};
struct
{
char type;
const char* content;
}code_table[]=
{
{op_nop, "nop "},
{op_nil, "nil "},
{op_pushn, "pushn "},
{op_pushs, "pushs "},
{op_pushv, "pushv "},
{op_pushh, "pushh "},
{op_pushf, "pushf "},
{op_vapp, "vapp "},
{op_happ, "happ "},
{op_para, "para "},
{op_dynpara, "dynp "},
{op_intg, "intg "},
{op_intl, "intl "},
{op_loadg, "loadg "},
{op_loadl, "loadl "},
{op_callg, "callg "},
{op_calll, "calll "},
{op_callv, "callv "},
{op_callh, "callh "},
{op_callf, "callf "},
{op_mcallg, "mcallg"},
{op_mcalll, "mcalll"},
{op_mcallv, "mcallv"},
{op_mcallh, "mcallh"},
{op_neg, "neg "},
{op_not, "not "},
{op_plus, "plus "},
{op_minus, "minus "},
{op_mult, "mult "},
{op_div, "div "},
{op_lnk, "lnk "},
{op_meq, "meq "},
{op_pluseq, "pluseq"},
{op_minuseq, "subeq "},
{op_multeq, "multeq"},
{op_diveq, "diveq "},
{op_lnkeq, "lnkeq "},
{op_eq, "eq "},
{op_neq, "neq "},
{op_less, "less "},
{op_leq, "leq "},
{op_grt, "grt "},
{op_geq, "geq "},
{op_pop, "pop "},
{op_jmp, "jmp "},
{op_jt, "jt "},
{op_jf, "jf "},
{op_ret, "ret "},
{-1, NULL }
};
struct bytecode
{
unsigned char op;
unsigned int num;
};
std::vector<bytecode>
exec_code;
std::unordered_map<std::string,unsigned int>
string_table;
std::unordered_map<double,unsigned int>
number_table;
std::list<std::vector<int> >
continue_ptr;
std::list<std::vector<int> >
break_ptr;
std::vector<std::string>
global_symbol;
std::list<std::vector<std::string> >
local_symbol;
void code_print()
{
int size=exec_code.size();
for(int i=0;i<size;++i)
{
printf("0x%.8x ",i);
for(int j=0;code_table[j].content;++j)
if(exec_code[i].op==code_table[j].type)
{
printf("%s ",code_table[j].content);
break;
}
printf("0x%.8x\n",exec_code[i].num);
}
return;
}
void regist_str(std::string);
void regist_num(double);
void global_addsym(std::string);
void local_addsym(std::string);
int in_global(std::string);
int in_local(std::string);
void emit(unsigned char,unsigned int);
void regist_builtin();
void proc_gen(nas_ast&);
void blk_gen(nas_ast&);
void expr_gen(nas_ast&);
void calc_gen(nas_ast&);
void num_gen(nas_ast&);
void str_gen(nas_ast&);
void vec_gen(nas_ast&);
void hash_gen(nas_ast&);
void func_gen(nas_ast&);
void call_gen(nas_ast&);
void mcall_gen(nas_ast&);
void def_gen(nas_ast&);
void if_gen(nas_ast&);
void while_gen(nas_ast&);
void for_gen(nas_ast&);
void ret_gen(nas_ast&);
void and_gen(nas_ast&);
void or_gen(nas_ast&);
void regist_str(std::string str)
{
if(string_table.find(str)==string_table.end())
{
int size=string_table.size();
string_table[str]=size;
}
return;
}
void regist_num(double num)
{
if(number_table.find(num)==number_table.end())
{
int size=number_table.size();
number_table[num]=size;
}
return;
}
void global_addsym(std::string sym)
{
for(int i=0;i<global_symbol.size();++i)
if(global_symbol[i]==sym)
return;
global_symbol.push_back(sym);
return;
}
void local_addsym(std::string sym)
{
for(int i=0;i<local_symbol.front().size();++i)
if(local_symbol.front()[i]==sym)
return;
local_symbol.front().push_back(sym);
return;
}
int in_global(std::string sym)
{
for(int i=0;i<global_symbol.size();++i)
if(global_symbol[i]==sym)
return i;
return -1;
}
int in_local(std::string sym)
{
int index=-1;
int cnt=0;
for(auto i=local_symbol.begin();i!=local_symbol.end();++i)
{
for(int j=0;j<i->size();++j)
if((*i)[j]==sym)
index=cnt+j;
cnt+=i->size();
}
return index;
}
void emit(unsigned char op,unsigned int num=0)
{
bytecode tmp;
tmp.op=op;
tmp.num=num;
exec_code.push_back(tmp);
return;
}
void regist_builtin()
{
for(int i=0;builtin_func[i].func_name;++i)
global_addsym(builtin_func[i].func_name);
return;
}
void proc_gen(nas_ast& root)
{
global_symbol.clear();
local_symbol.clear();
regist_builtin();
exec_code.clear();
emit(op_intg,0);
std::vector<nas_ast>& exprs=root.get_children();
int size=exprs.size();
for(int i=0;i<size;++i)
expr_gen(exprs[i]);
emit(op_nop);
exec_code[0].num=global_symbol.size();
return;
}
void blk_gen(nas_ast& node)
{
std::vector<nas_ast>& exprs=node.get_children();
int size=exprs.size();
for(int i=0;i<size;++i)
expr_gen(exprs[i]);
return;
}
void expr_gen(nas_ast& node)
{
switch(node.get_type())
{
case ast_definition:
def_gen(node);
break;
case ast_nil:
case ast_num:
case ast_str:
case ast_func:break;
case ast_list:
case ast_hash:
case ast_call:
case ast_plus:
case ast_minus:
case ast_mult:
case ast_div:
case ast_link:
case ast_and:
case ast_or:
case ast_not:
case ast_cmpeq:
case ast_neq:
case ast_less:
case ast_leq:
case ast_grt:
case ast_geq:
case ast_eq:
case ast_pluseq:
case ast_minuseq:
case ast_linkeq:
case ast_multeq:
case ast_diveq:
calc_gen(node);
emit(op_pop);
break;
case ast_conditional:
if_gen(node);
break;
case ast_while:
while_gen(node);
break;
case ast_for:
for_gen(node);
break;
case ast_continue:
continue_ptr.front().push_back(exec_code.size());
emit(op_jmp);
break;
case ast_break:
break_ptr.front().push_back(exec_code.size());
emit(op_jmp);
break;
case ast_ret:
ret_gen(node);
break;
}
return;
}
void calc_gen(nas_ast& node)
{
switch(node.get_type())
{
case ast_nil: emit(op_nil); break;
case ast_id:
case ast_call: call_gen(node); break;
case ast_num: num_gen(node); break;
case ast_str: str_gen(node); break;
case ast_list: vec_gen(node); break;
case ast_hash: hash_gen(node); break;
case ast_func: func_gen(node); break;
case ast_trino:
{
calc_gen(node.get_children()[0]);
int jf_label=exec_code.size();
emit(op_jf,0);
calc_gen(node.get_children()[1]);
int jmp_label=exec_code.size();
emit(op_jmp,0);
exec_code[jf_label].num=exec_code.size();
calc_gen(node.get_children()[2]);
exec_code[jmp_label].num=exec_code.size();
}
break;
case ast_eq:
case ast_pluseq:
case ast_minuseq:
case ast_linkeq:
case ast_multeq:
case ast_diveq:
mcall_gen(node.get_children()[0]);
calc_gen(node.get_children()[1]);
emit(node.get_type()-ast_eq+op_meq);
break;
case ast_not:
calc_gen(node.get_children()[0]);
emit(op_not);
break;
case ast_minus:
if(node.get_children().size()==1)
{
calc_gen(node.get_children()[0]);
emit(op_neg);
}
else
{
calc_gen(node.get_children()[0]);
calc_gen(node.get_children()[1]);
emit(op_minus);
}
break;
case ast_plus:
case ast_mult:
case ast_div:
calc_gen(node.get_children()[0]);
calc_gen(node.get_children()[1]);
switch(node.get_type())
{
case ast_plus:emit(op_plus);break;
case ast_mult:emit(op_mult);break;
case ast_div: emit(op_div); break;
}
break;
case ast_link:
calc_gen(node.get_children()[0]);
calc_gen(node.get_children()[1]);
emit(op_lnk);
break;
case ast_cmpeq:
case ast_neq:
case ast_less:
case ast_leq:
case ast_grt:
case ast_geq:
calc_gen(node.get_children()[0]);
calc_gen(node.get_children()[1]);
emit(node.get_type()-ast_cmpeq+op_eq);
break;
case ast_and: and_gen(node); break;
case ast_or: or_gen(node); break;
}
return;
}
void num_gen(nas_ast& node)
{
regist_num(node.get_num());
emit(op_pushn,number_table[node.get_num()]);
return;
}
void str_gen(nas_ast& node)
{
regist_str(node.get_str());
emit(op_pushs,string_table[node.get_str()]);
return;
}
void vec_gen(nas_ast& node)
{
emit(op_pushv,0);
std::vector<nas_ast>& members=node.get_children();
for(int i=0;i<members.size();++i)
calc_gen(members[i]);
emit(op_vapp,members.size());
return;
}
void hash_gen(nas_ast& node)
{
emit(op_pushh,0);
std::vector<nas_ast>& members=node.get_children();
for(int i=0;i<members.size();++i)
{
std::string name=members[i].get_str();
regist_str(name);
calc_gen(members[i].get_children()[0]);
emit(op_happ,string_table[name]);
}
return;
}
void func_gen(nas_ast& node)
{
int pushf_label=exec_code.size();
emit(op_pushf,0);
int intl_label=exec_code.size();
emit(op_intl,0);
std::vector<nas_ast>& parameter=node.get_children()[0].get_children();
std::vector<std::string> new_local;
local_symbol.push_back(new_local);
for(int i=0;i<parameter.size();++i)
{
local_addsym(parameter[i].get_str());
emit(
parameter[i].get_type()==ast_para?op_para:op_dynpara,
in_local(parameter[i].get_str())
);
}
exec_code[pushf_label].num=exec_code.size()+1;
emit(op_jmp);
int jmp_label=exec_code.size()-1;
blk_gen(node.get_children()[1]);
if(exec_code.back().op!=op_ret)
{
emit(op_nil);
emit(op_ret);
}
exec_code[intl_label].num=0;
for(auto i=local_symbol.begin();i!=local_symbol.end();++i)
exec_code[intl_label].num+=i->size();
local_symbol.pop_back();
exec_code[jmp_label].num=exec_code.size();
return;
}
void call_gen(nas_ast& node)
{
if(node.get_type()==ast_id)
{
int index=-1;
index=in_local(node.get_str());
if(index>-1)
{
emit(op_calll,index);
return;
}
index=in_global(node.get_str());
if(index>-1)
{
emit(op_callg,index);
return;
}
die("cannot find symbol named \""+node.get_str()+"\".",node.get_line());
return;
}
std::vector<nas_ast>& calls=node.get_children();
switch(calls[0].get_type())
{
case ast_id: call_gen(calls[0]);break;
case ast_str: str_gen(calls[0]); break;
case ast_list:vec_gen(calls[0]); break;
case ast_hash:hash_gen(calls[0]);break;
case ast_func:func_gen(calls[0]);break;
}
for(int i=1;i<calls.size();++i)
{
switch(calls[i].get_type())
{
case ast_callv:
calc_gen(calls[i].get_children()[0]);
emit(op_callv);
break;
case ast_callh:
regist_str(calls[i].get_str());
emit(op_callh,string_table[calls[i].get_str()]);
break;
case ast_callf:
vec_gen(calls[i]);
emit(op_callf);
break;
}
}
return;
}
void mcall_gen(nas_ast& node)
{
if(node.get_type()==ast_id)
{
int index=-1;
index=in_local(node.get_str());
if(index>-1)
{
emit(op_mcalll,index);
return;
}
index=in_global(node.get_str());
if(index>-1)
{
emit(op_mcallg,index);
return;
}
die("cannot find symbol named \""+node.get_str()+"\".",node.get_line());
return;
}
std::vector<nas_ast>& calls=node.get_children();
mcall_gen(calls[0]);
for(int i=1;i<calls.size();++i)
{
switch(calls[i].get_type())
{
case ast_callv:
calc_gen(calls[i].get_children()[0]);
emit(op_mcallv);
break;
case ast_callh:
regist_str(calls[i].get_str());
emit(op_mcallh,string_table[calls[i].get_str()]);
break;
}
}
return;
}
void def_gen(nas_ast& node)
{
if(local_symbol.empty())
global_addsym(node.get_str());
else
local_addsym(node.get_str());
calc_gen(node.get_children()[0]);
if(local_symbol.empty())
emit(op_loadg,in_global(node.get_str()));
else
emit(op_loadl,in_local(node.get_str()));
return;
}
void if_gen(nas_ast& node)
{
nas_ast& if_node=node.get_children()[0];
calc_gen(if_node.get_children()[0]);
emit(op_jf);
int condition_jmplabel=exec_code.size()-1;
blk_gen(if_node.get_children()[1]);
exec_code[condition_jmplabel].num=exec_code.size();
if(node.get_children().size()==2)
{
emit(op_jmp);
exec_code[condition_jmplabel].num=exec_code.size();
int jmp_out_label=exec_code.size()-1;
nas_ast& else_node=node.get_children()[1];
blk_gen(else_node.get_children()[0]);
exec_code[jmp_out_label].num=exec_code.size();
}
return;
}
void while_gen(nas_ast& node)
{
if(node.get_children()[1].get_children()[0].get_type()==ast_null)
return;
std::vector<int> new_labels;
continue_ptr.push_front(new_labels);
break_ptr.push_front(new_labels);
int jmp_label=exec_code.size();
calc_gen(node.get_children()[0]);
int jf_label=exec_code.size();
emit(op_jf);
blk_gen(node.get_children()[1]);
emit(op_jmp,jmp_label);
exec_code[jf_label].num=exec_code.size();
for(int i=0;i<continue_ptr.front().size();++i)
exec_code[continue_ptr.front()[i]].num=jmp_label;
for(int i=0;i<break_ptr.front().size();++i)
exec_code[break_ptr.front()[i]].num=exec_code.size();
continue_ptr.pop_front();
break_ptr.pop_front();
return;
}
void for_gen(nas_ast& node)
{
nas_ast& before_loop=node.get_children()[0];
nas_ast& condition=node.get_children()[1];
nas_ast& after_loop=node.get_children()[2];
if(before_loop.get_type()==ast_definition)
def_gen(before_loop);
else if(before_loop.get_type()!=ast_null)
{
calc_gen(before_loop);
emit(op_pop);
}
if(node.get_children()[3].get_children()[0].get_type()==ast_null)
return;
std::vector<int> new_labels;
continue_ptr.push_front(new_labels);
break_ptr.push_front(new_labels);
int jmp_label=exec_code.size();
if(condition.get_type()==ast_null)
{
regist_num(1);
emit(op_pushn,number_table[1]);
}
else
calc_gen(condition);
int jmp_false=exec_code.size();
emit(op_jf);
blk_gen(node.get_children()[3]);
int continue_label=exec_code.size();
if(after_loop.get_type()!=ast_null)
{
calc_gen(after_loop);
emit(op_pop);
}
emit(op_jmp,jmp_label);
exec_code[jmp_false].num=exec_code.size();
for(int i=0;i<continue_ptr.front().size();++i)
exec_code[continue_ptr.front()[i]].num=continue_label;
for(int i=0;i<break_ptr.front().size();++i)
exec_code[break_ptr.front()[i]].num=exec_code.size();
continue_ptr.pop_front();
break_ptr.pop_front();
return;
}
void ret_gen(nas_ast& node)
{
if(!node.get_children().size())
emit(op_nil);
else
calc_gen(node.get_children()[0]);
emit(op_ret);
return;
}
void and_gen(nas_ast& node)
{
calc_gen(node.get_children()[0]);
int jf_label1=exec_code.size();
emit(op_jf);
calc_gen(node.get_children()[1]);
int jf_label2=exec_code.size();
emit(op_jf);
regist_num(1);
emit(op_pushn,number_table[1]);
int jmp_label=exec_code.size();
emit(op_jmp);
exec_code[jf_label1].num=exec_code[jf_label2].num=exec_code.size();
emit(op_nil);
exec_code[jmp_label].num=exec_code.size();
return;
}
void or_gen(nas_ast& node)
{
calc_gen(node.get_children()[0]);
int jt_label1=exec_code.size();
emit(op_jt);
calc_gen(node.get_children()[1]);
int jt_label2=exec_code.size();
emit(op_jt);
emit(op_nil);
int jmp_label=exec_code.size();
emit(op_jmp);
exec_code[jt_label1].num=exec_code[jt_label2].num=exec_code.size();
regist_num(1);
emit(op_pushn,number_table[1]);
exec_code[jmp_label].num=exec_code.size();
return;
}
#endif
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化