diff --git a/main.cpp b/main.cpp index 48a7128..860058e 100644 --- a/main.cpp +++ b/main.cpp @@ -89,7 +89,7 @@ void execute(std::string& file,std::string& command) codegen.main_progress(import.get_root(),import.get_file()); if(codegen.get_error()) { - die("codegen",file); + die("code",file); return; } if(command=="--code" || command=="-c") diff --git a/nasal_codegen.h b/nasal_codegen.h index 0911725..ed2451f 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -268,7 +268,10 @@ void nasal_codegen::regist_number(double num) { int size=number_table.size(); if(!number_table.count(num)) + { number_table[num]=size; + num_res_table.push_back(num); + } return; } @@ -276,7 +279,10 @@ void nasal_codegen::regist_string(std::string& str) { int size=string_table.size(); if(!string_table.count(str)) + { string_table[str]=size; + str_res_table.push_back(str); + } return; } @@ -1170,6 +1176,8 @@ void nasal_codegen::main_progress(nasal_ast& ast,std::vector& files number_table.clear(); string_table.clear(); + num_res_table.clear(); + str_res_table.clear(); file_name=files; exec_code.clear(); @@ -1237,13 +1245,9 @@ void nasal_codegen::main_progress(nasal_ast& ast,std::vector& files } } gen(op_nop,0,0); + if(global.size()>=STACK_MAX_DEPTH) + die("too many global variants: "+std::to_string(global.size())+".",0); exec_code[0].num=global.size(); - num_res_table.resize(number_table.size()); - str_res_table.resize(string_table.size()); - for(auto& i:number_table) - num_res_table[i.second]=i.first; - for(auto& i:string_table) - str_res_table[i.second]=i.first; return; } diff --git a/nasal_gc.h b/nasal_gc.h index 48559da..9b99d1b 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -264,11 +264,11 @@ std::string nasal_val::to_string() struct nasal_gc { -#define STACK_MAX_DEPTH (4080) +#define STACK_MAX_DEPTH (4095) nasal_ref zero_addr; // reserved address of nasal_val,type vm_num, 0 nasal_ref one_addr; // reserved address of nasal_val,type vm_num, 1 nasal_ref nil_addr; // reserved address of nasal_val,type vm_nil - nasal_ref val_stack[STACK_MAX_DEPTH+16];// 16 reserved to avoid stack overflow + nasal_ref val_stack[STACK_MAX_DEPTH+1];// 1 reserved to avoid stack overflow, stack grows 1 each time nasal_ref* stack_top; // stack top std::vector num_addrs; // reserved address for const vm_num std::vector str_addrs; // reserved address for const vm_str diff --git a/nasal_vm.h b/nasal_vm.h index 7f2a484..8de0f2c 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -149,7 +149,7 @@ void nasal_vm::bytecodeinfo(uint32_t p) void nasal_vm::traceback() { printf("trace back:\n"); - uint32_t same_cnt=0,last_point=0; + uint32_t same_cnt=0,last_point=0xffffffff; for(uint32_t point=0;!ret.empty();last_point=point,ret.pop()) { point=ret.top(); @@ -214,7 +214,7 @@ void nasal_vm::die(std::string str) ret.push(pc); traceback(); stackinfo(10); - gc.val_stack[STACK_MAX_DEPTH-1]=(nasal_ref)0xffff; + exit(1); return; } void nasal_vm::stackoverflow() @@ -222,6 +222,7 @@ void nasal_vm::stackoverflow() printf("[vm] stack overflow\n"); traceback(); stackinfo(10); + exit(1); return; } inline bool nasal_vm::condition(nasal_ref val_addr) @@ -931,7 +932,7 @@ void nasal_vm::run(std::vector& exec,bool op_cnt) goto *code[pc]; nop: - if(canary && canary!=(nasal_ref)0xffff) + if(canary) stackoverflow(); if(op_cnt) { @@ -950,83 +951,85 @@ nop: } } return; +// may cause stackoverflow #define exec_operand(op,num) {op();++count[num];if(!canary)goto *code[++pc];goto nop;} +// do not cause stackoverflow #define exec_opnodie(op,num) {op();++count[num];goto *code[++pc];} -intg: exec_opnodie(opr_intg ,op_intg ); -intl: exec_opnodie(opr_intl ,op_intl ); -offset: exec_opnodie(opr_offset ,op_offset ); -loadg: exec_opnodie(opr_loadg ,op_loadg ); -loadl: exec_opnodie(opr_loadl ,op_loadl ); -pnum: exec_operand(opr_pnum ,op_pnum ); -pone: exec_operand(opr_pone ,op_pone ); -pzero: exec_operand(opr_pzero ,op_pzero ); -pnil: exec_operand(opr_pnil ,op_pnil ); -pstr: exec_operand(opr_pstr ,op_pstr ); -newv: exec_operand(opr_newv ,op_newv ); -newh: exec_operand(opr_newh ,op_newh ); -newf: exec_operand(opr_newf ,op_newf ); -happ: exec_opnodie(opr_happ ,op_happ ); -para: exec_opnodie(opr_para ,op_para ); -defpara: exec_opnodie(opr_defpara ,op_defpara ); -dynpara: exec_opnodie(opr_dynpara ,op_dynpara ); -unot: exec_operand(opr_unot ,op_unot ); -usub: exec_opnodie(opr_usub ,op_usub ); -add: exec_opnodie(opr_add ,op_add ); -sub: exec_opnodie(opr_sub ,op_sub ); -mul: exec_opnodie(opr_mul ,op_mul ); -div: exec_opnodie(opr_div ,op_div ); -lnk: exec_opnodie(opr_lnk ,op_lnk ); -addc: exec_opnodie(opr_addc ,op_addc ); -subc: exec_opnodie(opr_subc ,op_subc ); -mulc: exec_opnodie(opr_mulc ,op_mulc ); -divc: exec_opnodie(opr_divc ,op_divc ); -lnkc: exec_opnodie(opr_lnkc ,op_lnkc ); -addeq: exec_opnodie(opr_addeq ,op_addeq ); -subeq: exec_opnodie(opr_subeq ,op_subeq ); -muleq: exec_opnodie(opr_muleq ,op_muleq ); -diveq: exec_opnodie(opr_diveq ,op_diveq ); -lnkeq: exec_opnodie(opr_lnkeq ,op_lnkeq ); -addeqc: exec_opnodie(opr_addeqc ,op_addeqc ); -subeqc: exec_opnodie(opr_subeqc ,op_subeqc ); -muleqc: exec_opnodie(opr_muleqc ,op_muleqc ); -diveqc: exec_opnodie(opr_diveqc ,op_diveqc ); -lnkeqc: exec_opnodie(opr_lnkeqc ,op_lnkeqc ); -meq: exec_opnodie(opr_meq ,op_meq ); -eq: exec_opnodie(opr_eq ,op_eq ); -neq: exec_opnodie(opr_neq ,op_neq ); -less: exec_opnodie(opr_less ,op_less ); -leq: exec_opnodie(opr_leq ,op_leq ); -grt: exec_opnodie(opr_grt ,op_grt ); -geq: exec_opnodie(opr_geq ,op_geq ); -lessc: exec_opnodie(opr_lessc ,op_lessc ); -leqc: exec_opnodie(opr_leqc ,op_leqc ); -grtc: exec_opnodie(opr_grtc ,op_grtc ); -geqc: exec_opnodie(opr_geqc ,op_geqc ); -pop: exec_opnodie(opr_pop ,op_pop ); -jmp: exec_opnodie(opr_jmp ,op_jmp ); -jt: exec_opnodie(opr_jt ,op_jt ); -jf: exec_opnodie(opr_jf ,op_jf ); -counter: exec_operand(opr_counter ,op_cnt ); -cntpop: exec_opnodie(opr_cntpop ,op_cntpop ); -findex: exec_opnodie(opr_findex ,op_findex ); -feach: exec_opnodie(opr_feach ,op_feach ); -callg: exec_opnodie(opr_callg ,op_callg ); -calll: exec_opnodie(opr_calll ,op_calll ); -callv: exec_operand(opr_callv ,op_callv ); -callvi: exec_operand(opr_callvi ,op_callvi ); -callh: exec_operand(opr_callh ,op_callh ); -callfv: exec_operand(opr_callfv ,op_callfv ); -callfh: exec_operand(opr_callfh ,op_callfh ); -callb: exec_operand(opr_callb ,op_callb ); -slcbegin:exec_operand(opr_slcbegin,op_slcbegin); -slcend: exec_opnodie(opr_slcend ,op_slcend ); -slc: exec_operand(opr_slc ,op_slc ); -slc2: exec_operand(opr_slc2 ,op_slc2 ); -mcallg: exec_opnodie(opr_mcallg ,op_mcallg ); -mcalll: exec_opnodie(opr_mcalll ,op_mcalll ); -mcallv: exec_operand(opr_mcallv ,op_mcallv ); -mcallh: exec_operand(opr_mcallh ,op_mcallh ); -ret: exec_opnodie(opr_ret ,op_ret ); +intg: exec_opnodie(opr_intg ,op_intg ); // stack+=imm[pc] (detected at codegen) +intl: exec_opnodie(opr_intl ,op_intl ); // stack-=0 +offset: exec_opnodie(opr_offset ,op_offset ); // stack-=0 +loadg: exec_opnodie(opr_loadg ,op_loadg ); // stack-=1 +loadl: exec_opnodie(opr_loadl ,op_loadl ); // stack-=1 +pnum: exec_operand(opr_pnum ,op_pnum ); // stack+=1 +pone: exec_operand(opr_pone ,op_pone ); // stack+=1 +pzero: exec_operand(opr_pzero ,op_pzero ); // stack+=1 +pnil: exec_operand(opr_pnil ,op_pnil ); // stack+=1 +pstr: exec_operand(opr_pstr ,op_pstr ); // stack+=1 +newv: exec_operand(opr_newv ,op_newv ); // stack+=1-imm[pc] +newh: exec_operand(opr_newh ,op_newh ); // stack+=1 +newf: exec_operand(opr_newf ,op_newf ); // stack+=1 +happ: exec_opnodie(opr_happ ,op_happ ); // stack-=1 +para: exec_opnodie(opr_para ,op_para ); // stack-=0 +defpara: exec_opnodie(opr_defpara ,op_defpara ); // stack-=1 +dynpara: exec_opnodie(opr_dynpara ,op_dynpara ); // stack-=0 +unot: exec_opnodie(opr_unot ,op_unot ); // stack-=0 +usub: exec_opnodie(opr_usub ,op_usub ); // stack-=0 +add: exec_opnodie(opr_add ,op_add ); // stack-=1 +sub: exec_opnodie(opr_sub ,op_sub ); // stack-=1 +mul: exec_opnodie(opr_mul ,op_mul ); // stack-=1 +div: exec_opnodie(opr_div ,op_div ); // stack-=1 +lnk: exec_opnodie(opr_lnk ,op_lnk ); // stack-=1 +addc: exec_opnodie(opr_addc ,op_addc ); // stack-=0 +subc: exec_opnodie(opr_subc ,op_subc ); // stack-=0 +mulc: exec_opnodie(opr_mulc ,op_mulc ); // stack-=0 +divc: exec_opnodie(opr_divc ,op_divc ); // stack-=0 +lnkc: exec_opnodie(opr_lnkc ,op_lnkc ); // stack-=0 +addeq: exec_opnodie(opr_addeq ,op_addeq ); // stack-=1 +subeq: exec_opnodie(opr_subeq ,op_subeq ); // stack-=1 +muleq: exec_opnodie(opr_muleq ,op_muleq ); // stack-=1 +diveq: exec_opnodie(opr_diveq ,op_diveq ); // stack-=1 +lnkeq: exec_opnodie(opr_lnkeq ,op_lnkeq ); // stack-=1 +addeqc: exec_opnodie(opr_addeqc ,op_addeqc ); // stack-=0 +subeqc: exec_opnodie(opr_subeqc ,op_subeqc ); // stack-=0 +muleqc: exec_opnodie(opr_muleqc ,op_muleqc ); // stack-=0 +diveqc: exec_opnodie(opr_diveqc ,op_diveqc ); // stack-=0 +lnkeqc: exec_opnodie(opr_lnkeqc ,op_lnkeqc ); // stack-=0 +meq: exec_opnodie(opr_meq ,op_meq ); // stack-=1 +eq: exec_opnodie(opr_eq ,op_eq ); // stack-=1 +neq: exec_opnodie(opr_neq ,op_neq ); // stack-=1 +less: exec_opnodie(opr_less ,op_less ); // stack-=1 +leq: exec_opnodie(opr_leq ,op_leq ); // stack-=1 +grt: exec_opnodie(opr_grt ,op_grt ); // stack-=1 +geq: exec_opnodie(opr_geq ,op_geq ); // stack-=1 +lessc: exec_opnodie(opr_lessc ,op_lessc ); // stack-=0 +leqc: exec_opnodie(opr_leqc ,op_leqc ); // stack-=0 +grtc: exec_opnodie(opr_grtc ,op_grtc ); // stack-=0 +geqc: exec_opnodie(opr_geqc ,op_geqc ); // stack-=0 +pop: exec_opnodie(opr_pop ,op_pop ); // stack-=1 +jmp: exec_opnodie(opr_jmp ,op_jmp ); // stack-=0 +jt: exec_opnodie(opr_jt ,op_jt ); // stack-=0 +jf: exec_opnodie(opr_jf ,op_jf ); // stack-=1 +counter: exec_opnodie(opr_counter ,op_cnt ); // stack-=0 +cntpop: exec_opnodie(opr_cntpop ,op_cntpop ); // stack-=0 +findex: exec_operand(opr_findex ,op_findex ); // stack+=1 +feach: exec_operand(opr_feach ,op_feach ); // stack+=1 +callg: exec_operand(opr_callg ,op_callg ); // stack+=1 +calll: exec_operand(opr_calll ,op_calll ); // stack+=1 +callv: exec_opnodie(opr_callv ,op_callv ); // stack-=0 +callvi: exec_opnodie(opr_callvi ,op_callvi ); // stack-=0 +callh: exec_opnodie(opr_callh ,op_callh ); // stack-=0 +callfv: exec_opnodie(opr_callfv ,op_callfv ); // stack-=0 +callfh: exec_opnodie(opr_callfh ,op_callfh ); // stack-=0 +callb: exec_opnodie(opr_callb ,op_callb ); // stack-=0 +slcbegin:exec_operand(opr_slcbegin,op_slcbegin); // stack+=1 +slcend: exec_opnodie(opr_slcend ,op_slcend ); // stack-=1 +slc: exec_opnodie(opr_slc ,op_slc ); // stack-=1 +slc2: exec_opnodie(opr_slc2 ,op_slc2 ); // stack-=2 +mcallg: exec_operand(opr_mcallg ,op_mcallg ); // stack+=1 +mcalll: exec_operand(opr_mcalll ,op_mcalll ); // stack+=1 +mcallv: exec_opnodie(opr_mcallv ,op_mcallv ); // stack-=0 +mcallh: exec_opnodie(opr_mcallh ,op_mcallh ); // stack-=0 +ret: exec_opnodie(opr_ret ,op_ret ); // stack-=1 } #endif \ No newline at end of file diff --git a/test/hexdump.nas b/test/hexdump.nas index 8ed5aa0..3115dcb 100644 --- a/test/hexdump.nas +++ b/test/hexdump.nas @@ -85,7 +85,7 @@ func() } for(var l=cnt;l<16;l+=1) print(' '); - if(cnt<8) + if(cnt<=8) print(' '); textprint(i); }(); \ No newline at end of file diff --git a/test/ycombinator.nas b/test/ycombinator.nas index 698263e..858647f 100644 --- a/test/ycombinator.nas +++ b/test/ycombinator.nas @@ -1,13 +1,12 @@ # Y combinator by ValKmjolnir import("lib.nas"); -var count=0; + var fib=func(f){ return f(f); }( func(f){ return func(x){ - count+=1; if(x<2) return x; return f(f)(x-1)+f(f)(x-2); }