diff --git a/README.md b/README.md index b8c2ccc..6ab0840 100644 --- a/README.md +++ b/README.md @@ -199,7 +199,7 @@ for(var i=0;i<4000000;i+=1); 0x0000000c: nop 0x00000000 ``` -### Version 6.5(latest) +### Version 6.5(last update 2021/6/24) 2021/5/31 update: Now gc can collect garbage correctly without re-collecting,which will cause fatal error. @@ -329,6 +329,16 @@ As you could see from the bytecode above,mcall/mcallv/mcallh operands' using fre And because of the new structure of mcall, addr_stack, a stack used to store the memory address, is deleted from nasal_vm, and now nasal_vm use nasal_val** mem_addr to store the memory address. This will not cause fatal errors because the memory address is used __immediately__ after getting it. +### version 7.0(latest) + +2021/6/26 update: + +Instruction dispatch is changed from call-threading to computed-goto(with inline function).After changing the way of instruction dispatch,there is a great improvement in nasal_vm.Now vm can run test/bigloop and test/pi in 0.2s!And vm runs test/fib in 0.8s on linux.You could see the time use data below,in Test data section. + +This version uses gcc extension "labels as values", which is also supported by clang.(But i don't know if MSVC supports this) + +There is also a change in nasal_gc: std::vector global is deleted,now the global values are all stored on stack(from val_stack+0 to val_stack+intg-1). + ## Test data ### version 6.5(i5-8250U windows10 2021/6/19) @@ -378,6 +388,23 @@ operands calling total times: |quick_sort.nas|16226|5561|4144|3524|2833| |bfs.nas|24707|16297|14606|14269|8672| +### version 7.0(i5-8250U ubuntu-WSL on windows10 2021/6/26) + +running time: + +|file|total time|info| +|:----|:----|:----| +|pi.nas|0.17s|great improvement| +|fib.nas|0.75s|great improvement| +|bp.nas|0.32s(5467 epoch)|good improvement| +|bigloop.nas|0.11s|great improvement| +|mandelbrot.nas|0.04s|great improvment| +|life.nas|8.80s(windows) 1.34(ubuntu WSL)|little improvement| +|ascii-art.nas|0.015s|little improvement| +|calc.nas|0.0625s|little improvement| +|quick_sort.nas|0s|great improvement| +|bfs.nas|0.0156s|great improvement| + ## How to Use Nasal to Program ### basic value type @@ -660,7 +687,7 @@ Use import("") to get the nasal file including your built-in functions,then you version 6.5 update: -Use nasal_gc::builtin_alloc in builtin function if this function uses alloc more then one time. +Use nasal_gc::builtin_alloc in builtin function if this function uses alloc more than one time. When running a builtin function,alloc will run more than one time,this may cause mark-sweep in gc_alloc. diff --git a/main.cpp b/main.cpp index 105796c..8260488 100644 --- a/main.cpp +++ b/main.cpp @@ -29,7 +29,6 @@ void help_cmd() void info() { std::cout - <<">> Nasal interpreter ver 6.5.\n" <<">> Thanks to https://github.com/andyross/nasal\n" <<">> Code: https://github.com/ValKmjolnir/Nasal-Interpreter\n" <<">> Code: https://gitee.com/valkmjolnir/Nasal-Interpreter\n" @@ -44,7 +43,8 @@ void logo() <<" /\\ \\ \\__ _ ___ __ _| | \n" <<" / \\/ / _` / __|/ _` | | \n" <<" / /\\ / (_| \\__ \\ (_| | | \n" - <<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n"; + <<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n" + <<">> Nasal interpreter ver 7.0 \n"; return; } void die(const char* stage,std::string& filename) @@ -104,10 +104,9 @@ void execute(std::string& file,std::string& command) } vm.init( codegen.get_str_table(), - codegen.get_num_table(), - codegen.get_exec_code() + codegen.get_num_table() ); - vm.run(); + vm.run(codegen.get_exec_code()); vm.clear(); return; } @@ -150,10 +149,7 @@ int main(int argc,const char* argv[]) if(argc==1) interact(); else if(argc==2 && (!strcmp(argv[1],"-v") || !strcmp(argv[1],"-version"))) - { logo(); - std::cout<<"Nasal interpreter ver 6.5\n"; - } else if(argc==2 && (!strcmp(argv[1],"-h") || !strcmp(argv[1],"-help"))) help_cmd(); else if(argc==2 && argv[1][0]!='-') diff --git a/nasal_builtin.h b/nasal_builtin.h index 4f79632..0d02e80 100644 --- a/nasal_builtin.h +++ b/nasal_builtin.h @@ -722,7 +722,7 @@ nasal_val* builtin_substr(std::vector& local_scope,nasal_gc& gc) std::string& str=*str_addr->ptr.str; int beg=(int)beg_addr->ptr.num; int len=(int)len_addr->ptr.num; - if(beg>=str.length() || beg+len>=str.length()) + if(beg>=str.length() || beg+len-1>=str.length()) { builtin_err("susbtr","index out of range"); return nullptr; diff --git a/nasal_gc.h b/nasal_gc.h index 870483c..36e33d7 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -245,7 +245,6 @@ struct nasal_gc std::vector slice_stack; // slice stack for vec[val,val,val:val] std::vector memory; // gc memory std::queue free_list[vm_type_size]; // gc free list - std::vector global; std::list> local; void mark(); void sweep(); @@ -259,8 +258,6 @@ struct nasal_gc void nasal_gc::mark() { std::queue bfs; - for(auto i:global) - bfs.push(i); for(auto& i:local) for(auto j:i) bfs.push(j); @@ -332,7 +329,6 @@ void nasal_gc::gc_init(std::vector& nums,std::vector& strs) nil_addr=new nasal_val(vm_nil); // init nil - *val_stack=nil_addr; // the first space will not store any values,but gc checks // init constant numbers num_addrs.resize(nums.size()); for(int i=0;i ret; // ptr stack stores address for function to return std::stack counter; // iterator stack for forindex/foreach std::vector str_table;// symbols used in process - std::vector - exec_code;//function pointer std::vector imm; // immediate number nasal_val** mem_addr; // used for mem_call nasal_gc gc; // garbage collector void die(std::string); bool condition(nasal_val*); - void opr_nop(); void opr_intg(); void opr_intl(); void opr_offset(); @@ -86,91 +82,18 @@ public: nasal_vm():stack_top(gc.stack_top){}; void init( std::vector&, - std::vector&, - std::vector&); + std::vector&); void clear(); - void run(); + void run(std::vector&); }; void nasal_vm::init( std::vector& strs, - std::vector& nums, - std::vector& exec) + std::vector& nums) { gc.gc_init(nums,strs); gc.val_stack[STACK_MAX_DEPTH-1]=nullptr; str_table=strs; // get constant strings & symbols - void (nasal_vm::*opr_table[])()= - { - &nasal_vm::opr_nop, - &nasal_vm::opr_intg, - &nasal_vm::opr_intl, - &nasal_vm::opr_offset, - &nasal_vm::opr_loadg, - &nasal_vm::opr_loadl, - &nasal_vm::opr_pnum, - &nasal_vm::opr_pone, - &nasal_vm::opr_pzero, - &nasal_vm::opr_pnil, - &nasal_vm::opr_pstr, - &nasal_vm::opr_newv, - &nasal_vm::opr_newh, - &nasal_vm::opr_newf, - &nasal_vm::opr_happ, - &nasal_vm::opr_para, - &nasal_vm::opr_defpara, - &nasal_vm::opr_dynpara, - &nasal_vm::opr_unot, - &nasal_vm::opr_usub, - &nasal_vm::opr_add, - &nasal_vm::opr_sub, - &nasal_vm::opr_mul, - &nasal_vm::opr_div, - &nasal_vm::opr_lnk, - &nasal_vm::opr_addeq, - &nasal_vm::opr_subeq, - &nasal_vm::opr_muleq, - &nasal_vm::opr_diveq, - &nasal_vm::opr_lnkeq, - &nasal_vm::opr_meq, - &nasal_vm::opr_eq, - &nasal_vm::opr_neq, - &nasal_vm::opr_less, - &nasal_vm::opr_leq, - &nasal_vm::opr_grt, - &nasal_vm::opr_geq, - &nasal_vm::opr_pop, - &nasal_vm::opr_jmp, - &nasal_vm::opr_jt, - &nasal_vm::opr_jf, - &nasal_vm::opr_counter, - &nasal_vm::opr_cntpop, - &nasal_vm::opr_findex, - &nasal_vm::opr_feach, - &nasal_vm::opr_callg, - &nasal_vm::opr_calll, - &nasal_vm::opr_callv, - &nasal_vm::opr_callvi, - &nasal_vm::opr_callh, - &nasal_vm::opr_callfv, - &nasal_vm::opr_callfh, - &nasal_vm::opr_callb, - &nasal_vm::opr_slcbegin, - &nasal_vm::opr_slcend, - &nasal_vm::opr_slc, - &nasal_vm::opr_slc2, - &nasal_vm::opr_mcallg, - &nasal_vm::opr_mcalll, - &nasal_vm::opr_mcallv, - &nasal_vm::opr_mcallh, - &nasal_vm::opr_ret - }; - for(auto& i:exec) - { - exec_code.push_back(opr_table[i.op]); - imm.push_back(i.num); - } - loop_mark=true; // set loop mark to true return; } void nasal_vm::clear() @@ -181,13 +104,13 @@ void nasal_vm::clear() while(!counter.empty()) counter.pop(); str_table.clear(); - exec_code.clear(); + imm.clear(); return; } void nasal_vm::die(std::string str) { printf(">> [vm] 0x%.8x: %s\n",pc,str.c_str()); - loop_mark=false; + gc.val_stack[STACK_MAX_DEPTH-1]=(nasal_val*)0xffff; return; } bool nasal_vm::condition(nasal_val* val_addr) @@ -204,62 +127,60 @@ bool nasal_vm::condition(nasal_val* val_addr) } return false; } -void nasal_vm::opr_nop() +inline void nasal_vm::opr_intg() { - loop_mark=false; + // global values store on stack + for(int i=0;iptr.func->closure.resize(imm[pc],gc.nil_addr); return; } -void nasal_vm::opr_offset() +inline void nasal_vm::opr_offset() { stack_top[0]->ptr.func->offset=imm[pc]; return; } -void nasal_vm::opr_loadg() +inline void nasal_vm::opr_loadg() { - gc.global[imm[pc]]=(stack_top--)[0]; + gc.val_stack[imm[pc]]=(stack_top--)[0]; return; } -void nasal_vm::opr_loadl() +inline void nasal_vm::opr_loadl() { gc.local.back()[imm[pc]]=(stack_top--)[0]; return; } -void nasal_vm::opr_pnum() +inline void nasal_vm::opr_pnum() { (++stack_top)[0]=gc.num_addrs[imm[pc]]; return; } -void nasal_vm::opr_pone() +inline void nasal_vm::opr_pone() { (++stack_top)[0]=gc.one_addr; return; } -void nasal_vm::opr_pzero() +inline void nasal_vm::opr_pzero() { (++stack_top)[0]=gc.zero_addr; return; } -void nasal_vm::opr_pnil() +inline void nasal_vm::opr_pnil() { (++stack_top)[0]=gc.nil_addr; return; } -void nasal_vm::opr_pstr() +inline void nasal_vm::opr_pstr() { (++stack_top)[0]=gc.str_addrs[imm[pc]]; return; } -void nasal_vm::opr_newv() +inline void nasal_vm::opr_newv() { nasal_val* vec_addr=gc.gc_alloc(vm_vec); nasal_val** begin=stack_top-imm[pc]+1; @@ -271,12 +192,12 @@ void nasal_vm::opr_newv() stack_top=begin; return; } -void nasal_vm::opr_newh() +inline void nasal_vm::opr_newh() { (++stack_top)[0]=gc.gc_alloc(vm_hash); return; } -void nasal_vm::opr_newf() +inline void nasal_vm::opr_newf() { nasal_val* val=gc.gc_alloc(vm_func); val->ptr.func->entry=imm[pc]; @@ -287,13 +208,13 @@ void nasal_vm::opr_newf() (++stack_top)[0]=val; return; } -void nasal_vm::opr_happ() +inline void nasal_vm::opr_happ() { nasal_val* val=stack_top[0]; (--stack_top)[0]->ptr.hash->elems[str_table[imm[pc]]]=val; return; } -void nasal_vm::opr_para() +inline void nasal_vm::opr_para() { nasal_func* func=stack_top[0]->ptr.func; int size=func->key_table.size(); @@ -301,7 +222,7 @@ void nasal_vm::opr_para() func->default_para.push_back(nullptr); return; } -void nasal_vm::opr_defpara() +inline void nasal_vm::opr_defpara() { nasal_val* def_val=stack_top[0]; nasal_func* func=(--stack_top)[0]->ptr.func; @@ -310,12 +231,12 @@ void nasal_vm::opr_defpara() func->default_para.push_back(def_val); return; } -void nasal_vm::opr_dynpara() +inline void nasal_vm::opr_dynpara() { stack_top[0]->ptr.func->dynpara=imm[pc]; return; } -void nasal_vm::opr_unot() +inline void nasal_vm::opr_unot() { nasal_val* val=stack_top[0]; int type=val->type; @@ -335,89 +256,89 @@ void nasal_vm::opr_unot() die("unot: incorrect value type"); return; } -void nasal_vm::opr_usub() +inline void nasal_vm::opr_usub() { nasal_val* new_val=gc.gc_alloc(vm_num); new_val->ptr.num=-stack_top[0]->to_number(); stack_top[0]=new_val; return; } -void nasal_vm::opr_add() +inline void nasal_vm::opr_add() { nasal_val* new_val=gc.gc_alloc(vm_num); new_val->ptr.num=stack_top[-1]->to_number()+stack_top[0]->to_number(); (--stack_top)[0]=new_val; return; } -void nasal_vm::opr_sub() +inline void nasal_vm::opr_sub() { nasal_val* new_val=gc.gc_alloc(vm_num); new_val->ptr.num=stack_top[-1]->to_number()-stack_top[0]->to_number(); (--stack_top)[0]=new_val; return; } -void nasal_vm::opr_mul() +inline void nasal_vm::opr_mul() { nasal_val* new_val=gc.gc_alloc(vm_num); new_val->ptr.num=stack_top[-1]->to_number()*stack_top[0]->to_number(); (--stack_top)[0]=new_val; return; } -void nasal_vm::opr_div() +inline void nasal_vm::opr_div() { nasal_val* new_val=gc.gc_alloc(vm_num); new_val->ptr.num=stack_top[-1]->to_number()/stack_top[0]->to_number(); (--stack_top)[0]=new_val; return; } -void nasal_vm::opr_lnk() +inline void nasal_vm::opr_lnk() { nasal_val* new_val=gc.gc_alloc(vm_str); *new_val->ptr.str=stack_top[-1]->to_string()+stack_top[0]->to_string(); (--stack_top)[0]=new_val; return; } -void nasal_vm::opr_addeq() +inline void nasal_vm::opr_addeq() { nasal_val* new_val=gc.gc_alloc(vm_num); new_val->ptr.num=mem_addr[0]->to_number()+stack_top[-1]->to_number(); (--stack_top)[0]=mem_addr[0]=new_val; return; } -void nasal_vm::opr_subeq() +inline void nasal_vm::opr_subeq() { nasal_val* new_val=gc.gc_alloc(vm_num); new_val->ptr.num=mem_addr[0]->to_number()-stack_top[-1]->to_number(); (--stack_top)[0]=mem_addr[0]=new_val; return; } -void nasal_vm::opr_muleq() +inline void nasal_vm::opr_muleq() { nasal_val* new_val=gc.gc_alloc(vm_num); new_val->ptr.num=mem_addr[0]->to_number()*stack_top[-1]->to_number(); (--stack_top)[0]=mem_addr[0]=new_val; return; } -void nasal_vm::opr_diveq() +inline void nasal_vm::opr_diveq() { nasal_val* new_val=gc.gc_alloc(vm_num); new_val->ptr.num=mem_addr[0]->to_number()/stack_top[-1]->to_number(); (--stack_top)[0]=mem_addr[0]=new_val; return; } -void nasal_vm::opr_lnkeq() +inline void nasal_vm::opr_lnkeq() { nasal_val* new_val=gc.gc_alloc(vm_str); *new_val->ptr.str=mem_addr[0]->to_string()+stack_top[-1]->to_string(); (--stack_top)[0]=mem_addr[0]=new_val; return; } -void nasal_vm::opr_meq() +inline void nasal_vm::opr_meq() { mem_addr[0]=(--stack_top)[0]; return; } -void nasal_vm::opr_eq() +inline void nasal_vm::opr_eq() { nasal_val* val2=stack_top[0]; nasal_val* val1=(--stack_top)[0]; @@ -433,7 +354,7 @@ void nasal_vm::opr_eq() stack_top[0]=(val1==val2)?gc.one_addr:gc.zero_addr; return; } -void nasal_vm::opr_neq() +inline void nasal_vm::opr_neq() { nasal_val* val2=stack_top[0]; nasal_val* val1=(--stack_top)[0]; @@ -449,66 +370,66 @@ void nasal_vm::opr_neq() stack_top[0]=(val1!=val2)?gc.one_addr:gc.zero_addr; return; } -void nasal_vm::opr_less() +inline void nasal_vm::opr_less() { --stack_top; stack_top[0]=(stack_top[0]->to_number()to_number())?gc.one_addr:gc.zero_addr; return; } -void nasal_vm::opr_leq() +inline void nasal_vm::opr_leq() { --stack_top; stack_top[0]=(stack_top[0]->to_number()<=stack_top[1]->to_number())?gc.one_addr:gc.zero_addr; return; } -void nasal_vm::opr_grt() +inline void nasal_vm::opr_grt() { --stack_top; stack_top[0]=(stack_top[0]->to_number()>stack_top[1]->to_number())?gc.one_addr:gc.zero_addr; return; } -void nasal_vm::opr_geq() +inline void nasal_vm::opr_geq() { --stack_top; stack_top[0]=(stack_top[0]->to_number()>=stack_top[1]->to_number())?gc.one_addr:gc.zero_addr; return; } -void nasal_vm::opr_pop() +inline void nasal_vm::opr_pop() { --stack_top; return; } -void nasal_vm::opr_jmp() +inline void nasal_vm::opr_jmp() { pc=imm[pc]-1; return; } -void nasal_vm::opr_jt() +inline void nasal_vm::opr_jt() { if(condition(stack_top[0])) pc=imm[pc]-1; return; } -void nasal_vm::opr_jf() +inline void nasal_vm::opr_jf() { if(!condition(stack_top[0])) pc=imm[pc]-1; --stack_top; return; } -void nasal_vm::opr_counter() +inline void nasal_vm::opr_counter() { counter.push(-1); if(stack_top[0]->type!=vm_vec) die("cnt: must use vector in forindex/foreach"); return; } -void nasal_vm::opr_cntpop() +inline void nasal_vm::opr_cntpop() { counter.pop(); return; } -void nasal_vm::opr_findex() +inline void nasal_vm::opr_findex() { if(++counter.top()>=stack_top[0]->ptr.vec->elems.size()) { @@ -519,7 +440,7 @@ void nasal_vm::opr_findex() stack_top[0]->ptr.num=counter.top(); return; } -void nasal_vm::opr_feach() +inline void nasal_vm::opr_feach() { std::vector& ref=stack_top[0]->ptr.vec->elems; if(++counter.top()>=ref.size()) @@ -530,17 +451,17 @@ void nasal_vm::opr_feach() (++stack_top)[0]=ref[counter.top()]; return; } -void nasal_vm::opr_callg() +inline void nasal_vm::opr_callg() { - (++stack_top)[0]=gc.global[imm[pc]]; + (++stack_top)[0]=gc.val_stack[imm[pc]]; return; } -void nasal_vm::opr_calll() +inline void nasal_vm::opr_calll() { (++stack_top)[0]=gc.local.back()[imm[pc]]; return; } -void nasal_vm::opr_callv() +inline void nasal_vm::opr_callv() { nasal_val* val=stack_top[0]; nasal_val* vec_addr=(--stack_top)[0]; @@ -584,7 +505,7 @@ void nasal_vm::opr_callv() die("callv: must call a vector/hash/string"); return; } -void nasal_vm::opr_callvi() +inline void nasal_vm::opr_callvi() { nasal_val* val=stack_top[0]; if(val->type!=vm_vec) @@ -598,7 +519,7 @@ void nasal_vm::opr_callvi() die("callvi: index out of range:"+num2str(imm[pc])); return; } -void nasal_vm::opr_callh() +inline void nasal_vm::opr_callh() { nasal_val* val=stack_top[0]; if(val->type!=vm_hash) @@ -616,7 +537,7 @@ void nasal_vm::opr_callh() stack_top[0]->ptr.func->closure[0]=val;// me return; } -void nasal_vm::opr_callfv() +inline void nasal_vm::opr_callfv() { // get parameter list and function value int args_size=imm[pc]; @@ -660,7 +581,7 @@ void nasal_vm::opr_callfv() pc=ref_func.entry-1; return; } -void nasal_vm::opr_callfh() +inline void nasal_vm::opr_callfh() { // get parameter list and function value auto& ref_hash=stack_top[0]->ptr.hash->elems; @@ -701,25 +622,26 @@ void nasal_vm::opr_callfh() pc=ref_func.entry-1; return; } -void nasal_vm::opr_callb() +inline void nasal_vm::opr_callb() { - loop_mark=(++stack_top)[0]=(*builtin_func[imm[pc]].func)(gc.local.back(),gc); + (++stack_top)[0]=(*builtin_func[imm[pc]].func)(gc.local.back(),gc); + gc.val_stack[STACK_MAX_DEPTH-1]=(stack_top[0]?nullptr:(nasal_val*)0xffff); return; } -void nasal_vm::opr_slcbegin() +inline void nasal_vm::opr_slcbegin() { gc.slice_stack.push_back(gc.gc_alloc(vm_vec)); if(stack_top[0]->type!=vm_vec) die("slcbegin: must slice a vector"); return; } -void nasal_vm::opr_slcend() +inline void nasal_vm::opr_slcend() { stack_top[0]=gc.slice_stack.back(); gc.slice_stack.pop_back(); return; } -void nasal_vm::opr_slc() +inline void nasal_vm::opr_slc() { nasal_val* val=(stack_top--)[0]; nasal_val* res=stack_top[0]->ptr.vec->get_val(val->to_number()); @@ -728,7 +650,7 @@ void nasal_vm::opr_slc() gc.slice_stack.back()->ptr.vec->elems.push_back(res); return; } -void nasal_vm::opr_slc2() +inline void nasal_vm::opr_slc2() { nasal_val* val2=(stack_top--)[0]; nasal_val* val1=(stack_top--)[0]; @@ -768,19 +690,19 @@ void nasal_vm::opr_slc2() aim.push_back(i>=0?ref[i]:ref[i+ref_size]); return; } -void nasal_vm::opr_mcallg() +inline void nasal_vm::opr_mcallg() { - mem_addr=&gc.global[imm[pc]]; + mem_addr=gc.val_stack+imm[pc]; (++stack_top)[0]=mem_addr[0]; return; } -void nasal_vm::opr_mcalll() +inline void nasal_vm::opr_mcalll() { mem_addr=&gc.local.back()[imm[pc]]; (++stack_top)[0]=mem_addr[0]; return; } -void nasal_vm::opr_mcallv() +inline void nasal_vm::opr_mcallv() { nasal_val* val=stack_top[0]; nasal_val* vec_addr=(--stack_top)[0]; @@ -811,7 +733,7 @@ void nasal_vm::opr_mcallv() die("mcallv: cannot get memory space in other types"); return; } -void nasal_vm::opr_mcallh() +inline void nasal_vm::opr_mcallh() { nasal_val* hash_addr=stack_top[0]; if(hash_addr->type!=vm_hash) @@ -829,7 +751,7 @@ void nasal_vm::opr_mcallh() } return; } -void nasal_vm::opr_ret() +inline void nasal_vm::opr_ret() { gc.local.pop_back();// delete local scope pc=ret.top();ret.pop();// fetch pc @@ -837,14 +759,104 @@ void nasal_vm::opr_ret() stack_top[0]=stack_top[1];// rewrite nasal_func with returned value return; } -void nasal_vm::run() +void nasal_vm::run(std::vector& exec) { - clock_t begin_time=clock(); - for(pc=0;loop_mark&&!gc.val_stack[STACK_MAX_DEPTH-1];++pc) - (this->*exec_code[pc])(); - if(gc.val_stack[STACK_MAX_DEPTH-1]) - die("stack overflow"); - std::cout<<">> [vm] process exited after "<<((double)(clock()-begin_time))/CLOCKS_PER_SEC<<"s.\n"; + void* opr_table[]= + { + &&nop, &&intg, &&intl, &&offset, + &&loadg, &&loadl, &&pnum, &&pone, + &&pzero, &&pnil, &&pstr, &&newv, + &&newh, &&newf, &&happ, &¶, + &&defpara, &&dynpara, &&unot, &&usub, + &&add, &&sub, &&mul, &&div, + &&lnk, &&addeq, &&subeq, &&muleq, + &&diveq, &&lnkeq, &&meq, &&eq, + &&neq, &&less, &&leq, &&grt, + &&geq, &&pop, &&jmp, &&jt, + &&jf, &&counter, &&cntpop, &&findex, + &&feach, &&callg, &&calll, &&callv, + &&callvi, &&callh, &&callfv, &&callfh, + &&callb, &&slcbegin, &&slcend, &&slc, + &&slc2, &&mcallg, &&mcalll, &&mcallv, + &&mcallh, &&ret + }; + std::vector code; + for(auto& i:exec) + { + code.push_back(opr_table[i.op]); + imm.push_back(i.num); + } + + clock_t begin=clock(); + pc=0; + goto *code[pc]; + +nop: + if(gc.val_stack[STACK_MAX_DEPTH-1]&&gc.val_stack[STACK_MAX_DEPTH-1]!=(nasal_val*)0xffff) + std::cout<<">> [vm] stack overflow.\n"; + std::cout<<">> [vm] process exited after "<<((double)(clock()-begin))/CLOCKS_PER_SEC<<"s.\n"; return; +#define exec_operand(op) {op();if(!gc.val_stack[STACK_MAX_DEPTH-1])goto *code[++pc];goto nop;} +intg: exec_operand(opr_intg ); +intl: exec_operand(opr_intl ); +offset: exec_operand(opr_offset ); +loadg: exec_operand(opr_loadg ); +loadl: exec_operand(opr_loadl ); +pnum: exec_operand(opr_pnum ); +pone: exec_operand(opr_pone ); +pzero: exec_operand(opr_pzero ); +pnil: exec_operand(opr_pnil ); +pstr: exec_operand(opr_pstr ); +newv: exec_operand(opr_newv ); +newh: exec_operand(opr_newh ); +newf: exec_operand(opr_newf ); +happ: exec_operand(opr_happ ); +para: exec_operand(opr_para ); +defpara: exec_operand(opr_defpara ); +dynpara: exec_operand(opr_dynpara ); +unot: exec_operand(opr_unot ); +usub: exec_operand(opr_usub ); +add: exec_operand(opr_add ); +sub: exec_operand(opr_sub ); +mul: exec_operand(opr_mul ); +div: exec_operand(opr_div ); +lnk: exec_operand(opr_lnk ); +addeq: exec_operand(opr_addeq ); +subeq: exec_operand(opr_subeq ); +muleq: exec_operand(opr_muleq ); +diveq: exec_operand(opr_diveq ); +lnkeq: exec_operand(opr_lnkeq ); +meq: exec_operand(opr_meq ); +eq: exec_operand(opr_eq ); +neq: exec_operand(opr_neq ); +less: exec_operand(opr_less ); +leq: exec_operand(opr_leq ); +grt: exec_operand(opr_grt ); +geq: exec_operand(opr_geq ); +pop: exec_operand(opr_pop ); +jmp: exec_operand(opr_jmp ); +jt: exec_operand(opr_jt ); +jf: exec_operand(opr_jf ); +counter: exec_operand(opr_counter ); +cntpop: exec_operand(opr_cntpop ); +findex: exec_operand(opr_findex ); +feach: exec_operand(opr_feach ); +callg: exec_operand(opr_callg ); +calll: exec_operand(opr_calll ); +callv: exec_operand(opr_callv ); +callvi: exec_operand(opr_callvi ); +callh: exec_operand(opr_callh ); +callfv: exec_operand(opr_callfv ); +callfh: exec_operand(opr_callfh ); +callb: exec_operand(opr_callb ); +slcbegin:exec_operand(opr_slcbegin); +slcend: exec_operand(opr_slcend ); +slc: exec_operand(opr_slc ); +slc2: exec_operand(opr_slc2 ); +mcallg: exec_operand(opr_mcallg ); +mcalll: exec_operand(opr_mcalll ); +mcallv: exec_operand(opr_mcallv ); +mcallh: exec_operand(opr_mcallh ); +ret: exec_operand(opr_ret ); } #endif \ No newline at end of file diff --git a/stl/list.nas b/stl/list.nas index 98109f6..54dfde1 100644 --- a/stl/list.nas +++ b/stl/list.nas @@ -15,10 +15,7 @@ var list=func() _.end=tmp; } else - { - _.begin=tmp; - _.end=tmp; - } + _.begin=_.end=tmp; return; }, push_front:func(elem) @@ -31,10 +28,7 @@ var list=func() _.begin=tmp; } else - { - _.begin=tmp; - _.end=tmp; - } + _.begin=_.end=tmp; return; }, pop_back:func() diff --git a/stl/sort.nas b/stl/sort.nas index 0e5c3a1..9162671 100644 --- a/stl/sort.nas +++ b/stl/sort.nas @@ -3,9 +3,7 @@ var sort=func(vec,left,right,cmp=func(a,b){return a<=b;}) { if(left>=right) return nil; - var L=left; - var R=right; - var tmp=vec[L]; + var (L,R,tmp)=(left,right,vec[left]); while(left