diff --git a/nasal_codegen.h b/nasal_codegen.h index 9a227ca..25d189d 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -10,7 +10,7 @@ enum op_code_type:u8 { op_exit, // stop the virtual machine - op_intg, // global scope size + op_intg, // global scope size, set stack top op_intl, // local scope size op_loadg, // load global value op_loadl, // load local value @@ -26,7 +26,7 @@ enum op_code_type:u8 { op_deft, // default parameter op_dyn, // dynamic parameter op_lnot, // ! logical negation - op_usub, // - + op_usub, // - negation op_bnot, // ~ bitwise not static_cast op_btor, // | bitwise or op_btxor, // ^ bitwise xor @@ -41,20 +41,25 @@ enum op_code_type:u8 { op_mulc, // * const op_divc, // / const op_lnkc, // ~ const - op_addeq, // += - op_subeq, // -= - op_muleq, // *= - op_diveq, // /= - op_lnkeq, // ~= - op_btandeq,// &= - op_btoreq, // |= - op_btxoreq,// ^= - op_addeqc, // += const - op_subeqc, // -= const - op_muleqc, // *= const - op_diveqc, // /= const - op_lnkeqc, // ~= const - op_meq, // = + 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, // < @@ -65,8 +70,8 @@ enum op_code_type:u8 { op_leqc, // <= const op_grtc, // > const op_geqc, // >= const - op_pop, // pop a value from stack - op_jmp, // jump with no condition + 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 @@ -74,7 +79,7 @@ enum op_code_type:u8 { 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 + 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 @@ -105,23 +110,24 @@ const char* opname[]={ "addeq ","subeq ","muleq ","diveq ", "lnkeq ","bandeq","boreq ","bxoreq", "addeqc","subeqc","muleqc","diveqc", - "lnkeqc","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 " + "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; // imm num - u32 line;// line of source code + 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; @@ -141,7 +147,7 @@ public: u8 op=ins.code.op; u32 num=ins.code.num; out<>24)&0xff)<<" " <>16)&0xff)<<" " @@ -155,13 +161,17 @@ public: out<>31);break; + out<>31);break; + out< code; std::list> continue_ptr; std::list> break_ptr; - // global : max 1023 values + + // symbol table + // global : max STACK_DEPTH-1 values std::unordered_map global; // local : max 32768 upvalues 65536 values + // but in fact local scope also has less than STACK_DEPTH value std::list> local; bool check_memory_reachable(const ast&); @@ -858,7 +871,7 @@ void codegen::expr_gen(const ast& node) { if (op_addeq<=code.back().op && code.back().op<=op_btxoreq) { code.back().num=1; } else if (op_addeqc<=code.back().op && code.back().op<=op_lnkeqc) { - code.back().num|=0x80000000; + code.back().op=code.back().op-op_addeqc+op_addecp; } else { gen(op_pop,0,node.line()); } @@ -1195,11 +1208,21 @@ const error& codegen::compile(const parse& parse,const linker& import) { gen(op_intg,global.size(),0); block_gen(parse.tree()); // generate main block gen(op_exit,0,0); + + // size out of bound check + if (num_res.size()>0xffffff) { + err.load(file[0]); // load main execute file + err.err("code","too many constant numbers: "+std::to_string(num_res.size())); + } + if (str_res.size()>0xffffff) { + err.load(file[0]); // load main execute file + err.err("code","too many constant strings: "+std::to_string(str_res.size())); + } if (global.size()>=STACK_DEPTH) { err.load(file[0]); // load main execute file err.err("code","too many global variants: "+std::to_string(global.size())); } - if (code.size()>0x00ffffff) { + if (code.size()>0xffffff) { err.load(file[0]); // load main execute file err.err("code","bytecode size overflow: "+std::to_string(code.size())); } diff --git a/nasal_dbg.h b/nasal_dbg.h index f7741a0..2cb9c29 100644 --- a/nasal_dbg.h +++ b/nasal_dbg.h @@ -213,16 +213,17 @@ void debugger::run( &&addeq, &&subeq, &&muleq, &&diveq, &&lnkeq, &&bandeq, &&boreq, &&bxoreq, &&addeqc, &&subeqc, &&muleqc, &&diveqc, - &&lnkeqc, &&meq, &&eq, &&neq, - &&less, &&leq, &&grt, &&geq, - &&lessc, &&leqc, &&grtc, &&geqc, - &&pop, &&jmp, &&jt, &&jf, - &&cnt, &&findex, &&feach, &&callg, - &&calll, &&upval, &&callv, &&callvi, - &&callh, &&callfv, &&callfh, &&callb, - &&slcbeg, &&slcend, &&slc, &&slc2, - &&mcallg, &&mcalll, &&mupval, &&mcallv, - &&mcallh, &&ret + &&lnkeqc, &&addecp, &&subecp, &&mulecp, + &&divecp, &&lnkecp, &&meq, &&eq, + &&neq, &&less, &&leq, &&grt, + &&geq, &&lessc, &&leqc, &&grtc, + &&geqc, &&pop, &&jmp, &&jt, + &&jf, &&cnt, &&findex, &&feach, + &&callg, &&calll, &&upval, &&callv, + &&callvi, &&callh, &&callfv, &&callfh, + &&callb, &&slcbeg, &&slcend, &&slc, + &&slc2, &&mcallg, &&mcalll, &&mupval, + &&mcallv, &&mcallh, &&ret }; std::vector code; for(auto& i:gen.codes()) { @@ -254,9 +255,11 @@ void debugger::run( &debugger::o_muleq, &debugger::o_diveq, &debugger::o_lnkeq, &debugger::o_bandeq, &debugger::o_boreq, &debugger::o_bxoreq, - &debugger::o_addeqc, - &debugger::o_subeqc, &debugger::o_muleqc, - &debugger::o_diveqc, &debugger::o_lnkeqc, + &debugger::o_addeqc, &debugger::o_subeqc, + &debugger::o_muleqc, &debugger::o_diveqc, + &debugger::o_lnkeqc, &debugger::o_addecp, + &debugger::o_subecp, &debugger::o_mulecp, + &debugger::o_divecp, &debugger::o_lnkecp, &debugger::o_meq, &debugger::o_eq, &debugger::o_neq, &debugger::o_less, &debugger::o_leq, &debugger::o_grt, @@ -355,6 +358,11 @@ subeqc: dbg(o_subeqc,op_subeqc); muleqc: dbg(o_muleqc,op_muleqc); diveqc: dbg(o_diveqc,op_diveqc); lnkeqc: dbg(o_lnkeqc,op_lnkeqc); +addecp: dbg(o_addecp,op_addecp); +subecp: dbg(o_subecp,op_subecp); +mulecp: dbg(o_mulecp,op_mulecp); +divecp: dbg(o_divecp,op_divecp); +lnkecp: dbg(o_lnkecp,op_lnkecp); meq: dbg(o_meq ,op_meq ); eq: dbg(o_eq ,op_eq ); neq: dbg(o_neq ,op_neq ); diff --git a/nasal_vm.h b/nasal_vm.h index 12f671a..028fbcd 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -96,6 +96,11 @@ protected: void o_muleqc(); void o_diveqc(); void o_lnkeqc(); + void o_addecp(); + void o_subecp(); + void o_mulecp(); + void o_divecp(); + void o_lnkecp(); void o_meq(); void o_eq(); void o_neq(); @@ -554,18 +559,31 @@ void vm::o_bxoreq() { // like this: func{a+=1;}(); the result of 'a+1' will no be used later, imm[pc]>>31=1 // but if b+=a+=1; the result of 'a+1' will be used later, imm[pc]>>31=0 #define op_calc_eq_const(type)\ - top[0]=memr[0]=var::num(memr[0].tonum() type cnum[imm[pc]&0x7fffffff]);\ - memr=nullptr;\ - top-=(imm[pc]>>31); + top[0]=memr[0]=var::num(memr[0].tonum() type cnum[imm[pc]]);\ + memr=nullptr; void vm::o_addeqc() {op_calc_eq_const(+);} void vm::o_subeqc() {op_calc_eq_const(-);} void vm::o_muleqc() {op_calc_eq_const(*);} void vm::o_diveqc() {op_calc_eq_const(/);} void vm::o_lnkeqc() { - top[0]=memr[0]=ngc.newstr(memr[0].tostr()+cstr[imm[pc]&0x7fffffff]); + top[0]=memr[0]=ngc.newstr(memr[0].tostr()+cstr[imm[pc]]); memr=nullptr; - top-=(imm[pc]>>31); +} + +#define op_calc_eq_const_and_pop(type)\ + top[0]=memr[0]=var::num(memr[0].tonum() type cnum[imm[pc]]);\ + memr=nullptr;\ + --top; + +void vm::o_addecp() {op_calc_eq_const_and_pop(+);} +void vm::o_subecp() {op_calc_eq_const_and_pop(-);} +void vm::o_mulecp() {op_calc_eq_const_and_pop(*);} +void vm::o_divecp() {op_calc_eq_const_and_pop(/);} +void vm::o_lnkecp() { + top[0]=memr[0]=ngc.newstr(memr[0].tostr()+cstr[imm[pc]]); + memr=nullptr; + --top; } void vm::o_meq() { @@ -1062,16 +1080,17 @@ void vm::run( &&addeq, &&subeq, &&muleq, &&diveq, &&lnkeq, &&bandeq, &&boreq, &&bxoreq, &&addeqc, &&subeqc, &&muleqc, &&diveqc, - &&lnkeqc, &&meq, &&eq, &&neq, - &&less, &&leq, &&grt, &&geq, - &&lessc, &&leqc, &&grtc, &&geqc, - &&pop, &&jmp, &&jt, &&jf, - &&cnt, &&findex, &&feach, &&callg, - &&calll, &&upval, &&callv, &&callvi, - &&callh, &&callfv, &&callfh, &&callb, - &&slcbeg, &&slcend, &&slc, &&slc2, - &&mcallg, &&mcalll, &&mupval, &&mcallv, - &&mcallh, &&ret + &&lnkeqc, &&addecp, &&subecp, &&mulecp, + &&divecp, &&lnkecp, &&meq, &&eq, + &&neq, &&less, &&leq, &&grt, + &&geq, &&lessc, &&leqc, &&grtc, + &&geqc, &&pop, &&jmp, &&jt, + &&jf, &&cnt, &&findex, &&feach, + &&callg, &&calll, &&upval, &&callv, + &&callvi, &&callh, &&callfv, &&callfh, + &&callb, &&slcbeg, &&slcend, &&slc, + &&slc2, &&mcallg, &&mcalll, &&mupval, + &&mcallv, &&mcallh, &&ret }; std::vector code; for(auto& i:gen.codes()) { @@ -1103,9 +1122,11 @@ void vm::run( &vm::o_muleq, &vm::o_diveq, &vm::o_lnkeq, &vm::o_bandeq, &vm::o_boreq, &vm::o_bxoreq, - &vm::o_addeqc, - &vm::o_subeqc, &vm::o_muleqc, - &vm::o_diveqc, &vm::o_lnkeqc, + &vm::o_addeqc, &vm::o_subeqc, + &vm::o_muleqc, &vm::o_diveqc, + &vm::o_lnkeqc, &vm::o_addecp, + &vm::o_subecp, &vm::o_mulecp, + &vm::o_divecp, &vm::o_lnkecp, &vm::o_meq, &vm::o_eq, &vm::o_neq, &vm::o_less, &vm::o_leq, &vm::o_grt, @@ -1204,6 +1225,11 @@ subeqc: exec_nodie(o_subeqc); // -0 muleqc: exec_nodie(o_muleqc); // -0 diveqc: exec_nodie(o_diveqc); // -0 lnkeqc: exec_nodie(o_lnkeqc); // -0 +addecp: exec_nodie(o_addecp); // -1 +subecp: exec_nodie(o_subecp); // -1 +mulecp: exec_nodie(o_mulecp); // -1 +divecp: exec_nodie(o_divecp); // -1 +lnkecp: exec_nodie(o_lnkecp); // -1 meq: exec_nodie(o_meq ); // -1 eq: exec_nodie(o_eq ); // -1 neq: exec_nodie(o_neq ); // -1 diff --git a/stl/mat.nas b/stl/mat.nas index 29abb98..3c52e9a 100644 --- a/stl/mat.nas +++ b/stl/mat.nas @@ -219,7 +219,7 @@ var bp_example=func() { var epoch=0; var total=1e6; - while(total>0.01) { + while(total>0.001) { epoch+=1; if(epoch>1e4) { println("Training failed after ",epoch," epoch."); diff --git a/test/ascii-art.nas b/test/ascii-art.nas index 8ee723e..e1cf805 100644 --- a/test/ascii-art.nas +++ b/test/ascii-art.nas @@ -55,7 +55,7 @@ var curve1=func(line=4){ rand(100); var s=""; for(var i=0;i0.0005){ backward(i); } cnt+=1; - if(cnt>=3e5) + if(cnt>=1e4) break; } if(cnt>=3e5){ diff --git a/test/life.nas b/test/life.nas index e2cfa0e..676fe62 100644 --- a/test/life.nas +++ b/test/life.nas @@ -41,7 +41,7 @@ var run=func(width,height){ forindex(var j;map[i]) map[i][j]=rand()<0.45?'O':'.'; - for(var r=0;r<400;r+=1){ + for(var r=0;r<200;r+=1){ prt(map); for(var i=0;i