#ifndef __NASAL_CODEGEN_H__ #define __NASAL_CODEGEN_H__ enum op_code { op_nop, op_load,// load value in value_stack to identifier op_loadg, op_loadl, op_pnum, op_pone, op_pzero, op_pnil, op_pstr, op_newv, op_newh, op_newf, op_vapp, op_happ, op_para, op_defpara, op_dynpara, op_unot, op_usub, op_add, op_sub, op_mul, op_div, op_lnk, op_addeq, op_subeq, op_muleq, op_diveq, op_lnkeq, op_meq, op_eq, op_neq, op_less, op_leq, op_grt, op_geq, op_pop, op_jmp, // jump with no condition op_jt, // used in operator and/or,jmp when condition is true and DO NOT POP op_jf, // used in conditional/loop,jmp when condition is false and POP STACK op_counter, // add counter for forindex/foreach op_cntpop, // pop counter op_findex, // index counter on the top of forindex_stack plus 1 op_feach, // index counter on the top of forindex_stack plus 1 and get the value in vector op_call, // call identifier op_callv, // call vec[index] op_callvi, // call vec[immediate] (used in multi-assign/multi-define) op_callh, // call hash.label op_callf, // call function(parameters) op_callb, // call builtin-function op_slcbegin, // begin of slice like: vec[1,2,3:6,0,-1] op_slcend, // end of slice op_slc, // slice like vec[1] op_slc2, // slice like vec[nil:10] op_mcall, // get memory of identifier op_mcallv, // get memory of vec[index] op_mcallh, // get memory of hash.label op_ret // return }; struct { int type; const char* name; }code_table[]= { {op_nop, "nop "}, {op_load, "load "}, {op_loadg, "loadg "}, {op_loadl, "loadl "}, {op_pnum, "pnum "}, {op_pone, "pone "}, {op_pzero, "pzero "}, {op_pnil, "pnil "}, {op_pstr, "pstr "}, {op_newv, "newv "}, {op_newh, "newh "}, {op_newf, "newf "}, {op_vapp, "vapp "}, {op_happ, "happ "}, {op_para, "para "}, {op_defpara, "def "}, {op_dynpara, "dyn "}, {op_unot, "not "}, {op_usub, "usub "}, {op_add, "add "}, {op_sub, "sub "}, {op_mul, "mult "}, {op_div, "div "}, {op_lnk, "link "}, {op_addeq, "addeq "}, {op_subeq, "subeq "}, {op_muleq, "muleq "}, {op_diveq, "diveq "}, {op_lnkeq, "linkeq"}, {op_meq, "meq "}, {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_counter, "cnt "}, {op_cntpop, "cntpop"}, {op_findex, "findx "}, {op_feach, "feach "}, {op_call, "call "}, {op_callv, "callv "}, {op_callvi, "callvi"}, {op_callh, "callh "}, {op_callf, "callf "}, {op_callb, "callb "}, {op_slcbegin, "slcbeg"}, {op_slcend, "slcend"}, {op_slc, "slc "}, {op_slc2, "slc2 "}, {op_mcall, "mcall "}, {op_mcallv, "mcallv"}, {op_mcallh, "mcallh"}, {op_ret, "ret "}, {-1, NULL }, }; struct opcode { unsigned char op; unsigned int num; opcode(unsigned char _op=op_nop,unsigned int _num=0) { op=_op; num=_num; return; } opcode& operator=(const opcode& tmp) { op=tmp.op; num=tmp.num; return *this; } }; class nasal_codegen { private: int error; int in_forindex; int in_foreach; std::unordered_map number_table; std::unordered_map string_table; std::vector num_res_table; std::vector str_res_table; std::vector exec_code; std::list > continue_ptr; std::list > break_ptr; void regist_number(double); void regist_string(std::string); void gen(unsigned char,unsigned int); void pop_gen(); void nil_gen(); void num_gen(nasal_ast&); void str_gen(nasal_ast&); void vec_gen(nasal_ast&); void hash_gen(nasal_ast&); void func_gen(nasal_ast&); void call_gen(nasal_ast&); void call_id(nasal_ast&); void call_hash(nasal_ast&); void call_vec(nasal_ast&); void call_func(nasal_ast&); void mcall(nasal_ast&); void mcall_id(nasal_ast&); void mcall_vec(nasal_ast&); void mcall_hash(nasal_ast&); void multi_def(nasal_ast&); void single_def(nasal_ast&); void def_gen(nasal_ast&); void multi_assign_gen(nasal_ast&); void conditional_gen(nasal_ast&); void loop_gen(nasal_ast&); void load_continue_break(int,int); void while_gen(nasal_ast&); void for_gen(nasal_ast&); void forindex_gen(nasal_ast&); void foreach_gen(nasal_ast&); void or_gen(nasal_ast&); void and_gen(nasal_ast&); void trino_gen(nasal_ast&); void calc_gen(nasal_ast&); void block_gen(nasal_ast&); void ret_gen(nasal_ast&); public: nasal_codegen(); void main_progress(nasal_ast&); void print_op(int); void print_byte_code(); std::vector& get_str_table(); std::vector& get_num_table(); std::vector& get_exec_code(); }; nasal_codegen::nasal_codegen() { error=0; in_foreach=0; in_forindex=0; return; } void nasal_codegen::regist_number(double num) { int size=number_table.size(); if(number_table.find(num)==number_table.end()) number_table[num]=size; return; } void nasal_codegen::regist_string(std::string str) { int size=string_table.size(); if(string_table.find(str)==string_table.end()) string_table[str]=size; return; } void nasal_codegen::gen(unsigned char op,unsigned int index) { opcode opr(op,index); exec_code.push_back(opr); return; } void nasal_codegen::pop_gen() { opcode op(op_pop,0); exec_code.push_back(op); return; } void nasal_codegen::nil_gen() { opcode op(op_pnil,0); exec_code.push_back(op); return; } void nasal_codegen::num_gen(nasal_ast& ast) { double num=ast.get_num(); if(num==1) gen(op_pone,0); else if(num==0) gen(op_pzero,0); else { regist_number(num); gen(op_pnum,number_table[num]); } return; } void nasal_codegen::str_gen(nasal_ast& ast) { std::string str=ast.get_str(); regist_string(str); gen(op_pstr,string_table[str]); return; } void nasal_codegen::vec_gen(nasal_ast& ast) { int size=ast.get_children().size(); gen(op_newv,0); for(int i=0;i=0;--i) calc_gen(ast.get_children()[1].get_children()[i]); for(int i=0;i jmp_label; for(int i=0;i::iterator i=jmp_label.begin();i!=jmp_label.end();++i) exec_code[*i].num=exec_code.size(); return; } void nasal_codegen::loop_gen(nasal_ast& ast) { std::vector new_level; continue_ptr.push_front(new_level); break_ptr.push_front(new_level); switch(ast.get_type()) { case ast_while: while_gen(ast); break; case ast_for: for_gen(ast); break; case ast_forindex: ++in_forindex;forindex_gen(ast);--in_forindex; break; case ast_foreach: ++in_foreach; foreach_gen(ast); --in_foreach; break; } return; } void nasal_codegen::load_continue_break(int continue_place,int break_place) { for(int i=0;isecond]=i->first; for(auto i=string_table.begin();i!=string_table.end();++i) str_res_table[i->second]=i->first; return; } void nasal_codegen::print_op(int index) { // print opcode ptr printf("0x%.8x: ",index); // print opcode name for(int i=0;code_table[i].name;++i) if(exec_code[index].op==code_table[i].type) { std::cout<& nasal_codegen::get_str_table() { return str_res_table; } std::vector& nasal_codegen::get_num_table() { return num_res_table; } std::vector& nasal_codegen::get_exec_code() { return exec_code; } #endif