diff --git a/makefile b/makefile index 48c29ea..0975f38 100644 --- a/makefile +++ b/makefile @@ -5,6 +5,7 @@ SRC=\ nasal_ast.h\ nasal_err.h\ nasal_builtin.h\ + nasal_opcode.h\ nasal_opt.h\ nasal_codegen.h\ nasal_gc.h\ @@ -65,9 +66,7 @@ test:nasal @ ./nasal -e test/qrcode.nas @ ./nasal -t -d test/quick_sort.nas @ ./nasal -e test/scalar.nas hello world - @ ./nasal -t test/snake.nas --skip @ ./nasal -e test/trait.nas - @ ./nasal -t test/tetris.nas --skip @ ./nasal -t -d test/turingmachine.nas @ ./nasal -d test/wavecollapse.nas @ ./nasal test/word_collector.nas test/md5compare.nas diff --git a/nasal_codegen.h b/nasal_codegen.h index a7aa2e7..371527f 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -2,212 +2,13 @@ #include "nasal_err.h" #include "nasal_builtin.h" +#include "nasal_opcode.h" #include #include #include #include -enum op_code_type:u8 { - op_exit, // stop the virtual machine - op_intg, // global scope size, set stack top - op_intl, // local scope size - op_loadg, // load global value - op_loadl, // load local value - op_loadu, // load upvalue - op_pnum, // push constant number to the stack - op_pnil, // push constant nil to the stack - op_pstr, // push constant string to the stack - op_newv, // push new vector with initial values from stack - op_newh, // push new hash to the stack - op_newf, // push new function to the stack - op_happ, // hash append - op_para, // normal parameter - op_deft, // default parameter - op_dyn, // dynamic parameter - op_lnot, // ! logical negation - op_usub, // - negation - op_bnot, // ~ bitwise not static_cast - op_btor, // | bitwise or - op_btxor, // ^ bitwise xor - op_btand, // & bitwise and - op_add, // + - op_sub, // - - op_mul, // * - op_div, // / - op_lnk, // ~ - op_addc, // + const - op_subc, // - const - op_mulc, // * const - op_divc, // / const - op_lnkc, // ~ const - op_addeq, // += maybe pop stack top - op_subeq, // -= maybe pop stack top - op_muleq, // *= maybe pop stack top - op_diveq, // /= maybe pop stack top - op_lnkeq, // ~= maybe pop stack top - op_btandeq,// &= maybe pop stack top - op_btoreq, // |= maybe pop stack top - op_btxoreq,// ^= maybe pop stack top - op_addeqc, // += const don't pop stack top - op_subeqc, // -= const don't pop stack top - op_muleqc, // *= const don't pop stack top - op_diveqc, // /= const don't pop stack top - op_lnkeqc, // ~= const don't pop stack top - op_addecp, // += const and pop stack top - op_subecp, // -= const and pop stack top - op_mulecp, // *= const and pop stack top - op_divecp, // /= const and pop stack top - op_lnkecp, // ~= concat const string and pop stack top - op_meq, // = maybe pop stack top - op_eq, // == - op_neq, // != - op_less, // < - op_leq, // <= - op_grt, // > - op_geq, // >= - op_lessc, // < const - op_leqc, // <= const - op_grtc, // > const - op_geqc, // >= const - op_pop, // pop a value out of stack top - op_jmp, // jump absolute address 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_cnt, // add counter for forindex/foreach - 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_callg, // get value in global scope - op_calll, // get value in local scope - op_upval, // get upvalue in closure, high 16 as the index of upval, low 16 as the index of local - op_callv, // call vec[index] - op_callvi, // call vec[immediate] (used in multi-assign/multi-define) - op_callh, // call hash.label - op_callfv, // call function(vector as parameters) - op_callfh, // call function(hash as parameters) - op_callb, // call builtin-function - op_slcbeg, // 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_mcallg, // get memory space of value in global scope - op_mcalll, // get memory space of value in local scope - op_mupval, // get memory space of value in closure - op_mcallv, // get memory space of vec[index] - op_mcallh, // get memory space of hash.label - op_ret // return -}; - -const char* opname[]={ - "exit ","intg ","intl ","loadg ", - "loadl ","loadu ","pnum ","pnil ", - "pstr ","newv ","newh ","newf ", - "happ ","para ","def ","dyn ", - "lnot ","usub ","bnot ","btor ", - "btxor ","btand ","add ","sub ", - "mult ","div ","lnk ","addc ", - "subc ","multc ","divc ","lnkc ", - "addeq ","subeq ","muleq ","diveq ", - "lnkeq ","bandeq","boreq ","bxoreq", - "addeqc","subeqc","muleqc","diveqc", - "lnkeqc","addecp","subecp","mulecp", - "divecp","lnkecp","meq ","eq ", - "neq ","less ","leq ","grt ", - "geq ","lessc ","leqc ","grtc ", - "geqc ","pop ","jmp ","jt ", - "jf ","cnt ","findx ","feach ", - "callg ","calll ","upval ","callv ", - "callvi","callh ","callfv","callfh", - "callb ","slcbeg","slcend","slc ", - "slc2 ","mcallg","mcalll","mupval", - "mcallv","mcallh","ret " -}; - -struct opcode { - u8 op; // opcode - u16 fidx; // source code file index - u32 num; // immediate num - u32 line; // location line of source code - opcode(u8 o=op_exit,u16 f=0,u32 n=0,u32 l=0): - op(o),fidx(f),num(n),line(l) {} - opcode& operator=(const opcode& tmp) = default; -}; - -class codestream { -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) { - u8 op=ins.code.op; - u32 num=ins.code.num; - out<>16)&0xff)<<" " - <>8)&0xff)<<" " - <";break; - case op_upval: case op_mupval: case op_loadu: - out<>16)&0xffff) - <<"[0x"<<(num&0xffff)<<"]"< @@ -115,10 +116,11 @@ void debugger::stepinfo() { std::cout<<"next bytecode:\n"; begin=(pc>>3)==0?0:((pc>>3)<<3); end=(1+(pc>>3))<<3; + codestream::set(cnum,cstr,files); for(u32 i=begin;i ":" ") - < + +enum op_code_type:u8 { + op_exit, // stop the virtual machine + op_intg, // global scope size, set stack top + op_intl, // local scope size + op_loadg, // load global value + op_loadl, // load local value + op_loadu, // load upvalue + op_pnum, // push constant number to the stack + op_pnil, // push constant nil to the stack + op_pstr, // push constant string to the stack + op_newv, // push new vector with initial values from stack + op_newh, // push new hash to the stack + op_newf, // push new function to the stack + op_happ, // hash append + op_para, // normal parameter + op_deft, // default parameter + op_dyn, // dynamic parameter + op_lnot, // ! logical negation + op_usub, // - negation + op_bnot, // ~ bitwise not static_cast + op_btor, // | bitwise or + op_btxor, // ^ bitwise xor + op_btand, // & bitwise and + op_add, // + + op_sub, // - + op_mul, // * + op_div, // / + op_lnk, // ~ + op_addc, // + const + op_subc, // - const + op_mulc, // * const + op_divc, // / const + op_lnkc, // ~ const + op_addeq, // += maybe pop stack top + op_subeq, // -= maybe pop stack top + op_muleq, // *= maybe pop stack top + op_diveq, // /= maybe pop stack top + op_lnkeq, // ~= maybe pop stack top + op_btandeq,// &= maybe pop stack top + op_btoreq, // |= maybe pop stack top + op_btxoreq,// ^= maybe pop stack top + op_addeqc, // += const don't pop stack top + op_subeqc, // -= const don't pop stack top + op_muleqc, // *= const don't pop stack top + op_diveqc, // /= const don't pop stack top + op_lnkeqc, // ~= const don't pop stack top + op_addecp, // += const and pop stack top + op_subecp, // -= const and pop stack top + op_mulecp, // *= const and pop stack top + op_divecp, // /= const and pop stack top + op_lnkecp, // ~= concat const string and pop stack top + op_meq, // = maybe pop stack top + op_eq, // == + op_neq, // != + op_less, // < + op_leq, // <= + op_grt, // > + op_geq, // >= + op_lessc, // < const + op_leqc, // <= const + op_grtc, // > const + op_geqc, // >= const + op_pop, // pop a value out of stack top + op_jmp, // jump absolute address 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_cnt, // add counter for forindex/foreach + 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_callg, // get value in global scope + op_calll, // get value in local scope + op_upval, // get upvalue in closure, high 16 as the index of upval, low 16 as the index of local + op_callv, // call vec[index] + op_callvi, // call vec[immediate] (used in multi-assign/multi-define) + op_callh, // call hash.label + op_callfv, // call function(vector as parameters) + op_callfh, // call function(hash as parameters) + op_callb, // call builtin-function + op_slcbeg, // 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_mcallg, // get memory space of value in global scope + op_mcalll, // get memory space of value in local scope + op_mupval, // get memory space of value in closure + op_mcallv, // get memory space of vec[index] + op_mcallh, // get memory space of hash.label + op_ret // return +}; + +const char* opname[]={ + "exit ","intg ","intl ","loadg ", + "loadl ","loadu ","pnum ","pnil ", + "pstr ","newv ","newh ","newf ", + "happ ","para ","def ","dyn ", + "lnot ","usub ","bnot ","btor ", + "btxor ","btand ","add ","sub ", + "mult ","div ","lnk ","addc ", + "subc ","multc ","divc ","lnkc ", + "addeq ","subeq ","muleq ","diveq ", + "lnkeq ","bandeq","boreq ","bxoreq", + "addeqc","subeqc","muleqc","diveqc", + "lnkeqc","addecp","subecp","mulecp", + "divecp","lnkecp","meq ","eq ", + "neq ","less ","leq ","grt ", + "geq ","lessc ","leqc ","grtc ", + "geqc ","pop ","jmp ","jt ", + "jf ","cnt ","findx ","feach ", + "callg ","calll ","upval ","callv ", + "callvi","callh ","callfv","callfh", + "callb ","slcbeg","slcend","slc ", + "slc2 ","mcallg","mcalll","mupval", + "mcallv","mcallh","ret " +}; + +struct opcode { + u8 op; // opcode + u16 fidx; // source code file index + u32 num; // immediate num + u32 line; // location line of source code + opcode() = default; + opcode(const opcode&) = default; + opcode& operator=(const opcode&) = default; +}; + +class codestream { +private: + opcode code; + const u32 index; + static const f64* nums; + static const string* strs; + static const string* files; +public: + codestream(const opcode& c,const u32 i):code(c),index(i) {} + static void set(const f64*,const string*,const string*); + void dump(std::ostream&) const; + + friend std::ostream& operator<<(std::ostream& out,const codestream& ins) { + ins.dump(out); + return out; + } +}; + +const f64* codestream::nums=nullptr; +const string* codestream::strs=nullptr; +const string* codestream::files=nullptr; + +void codestream::set(const f64* numbuff,const string* strbuff,const string* filelist=nullptr) { + nums=numbuff; + strs=strbuff; + files=filelist; +} + +void codestream::dump(std::ostream& out) const { + auto op=code.op; + auto num=code.num; + out<>16)&0xff)<<" " + <>8)&0xff)<<" " + <";break; + case op_upval: case op_mupval: case op_loadu: + out<>16)&0xffff) + <<"[0x"<<(num&0xffff)<<"]"<