diff --git a/lib.nas b/lib.nas index d517ad7..57105c7 100644 --- a/lib.nas +++ b/lib.nas @@ -1,7 +1,7 @@ # lib.nas # print is used to print all things in nasal, try and see how it works. -# this function uses std::cout/printf to output logs. +# this function uses std::cout to output logs. var print=func(elems...){ return __print(elems); } diff --git a/module/makefile b/module/makefile index 7983ecb..86bba57 100644 --- a/module/makefile +++ b/module/makefile @@ -6,6 +6,7 @@ libfib.so: fib.cpp libfib.dll: fib.cpp g++ -c -O3 fib.cpp -fPIC -o fib.o g++ -shared -o libfib.dll fib.o + del fib.o libkey.so: keyboard.cpp clang++ -c -O3 keyboard.cpp -fPIC -o keyboard.o @@ -14,6 +15,7 @@ libkey.so: keyboard.cpp libkey.dll: keyboard.cpp g++ -c -O3 keyboard.cpp -fPIC -o keyboard.o -static g++ -shared -o libkey.dll keyboard.o -static + del keyboard.o libnasock.so: nasocket.cpp clang++ -c -O3 nasocket.cpp -fPIC -o nasocket.o @@ -22,9 +24,10 @@ libnasock.so: nasocket.cpp libnasock.dll: nasocket.cpp g++ -c -O3 nasocket.cpp -fPIC -o nasocket.o -lwsock32 -static g++ -shared -o libnasock.dll nasocket.o -lwsock32 -static + del nasocket.o clean: - rm *.o *.so *.dll *.dylib + rm *.so *.dll *.dylib all: libfib.so libkey.so libnasock.so @ echo "build done" mingw-all: libfib.dll libkey.dll libnasock.dll diff --git a/nasal.h b/nasal.h index bd5efaa..d4e2870 100644 --- a/nasal.h +++ b/nasal.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -35,16 +36,6 @@ #include #endif -#ifdef __linux__ -#define PRTHEX64 "%lx" -#define PRTHEX64_8 "%.8lx" -#define PRTINT64 "%ld" -#else -#define PRTHEX64 "%llx" -#define PRTHEX64_8 "%.8llx" -#define PRTINT64 "%lld" -#endif - const uint32_t STACK_DEPTH=2048; inline double hex_to_double(const char* str) diff --git a/nasal_codegen.h b/nasal_codegen.h index c6ec46b..f336d5f 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -180,8 +180,67 @@ struct opcode line=tmp.line; return *this; } + void print(const char*, + const double*, + const std::string*, + const uint32_t,bool) const; }; +void opcode::print(const char* header, + const double* constnum, + const std::string* conststr, + const uint32_t index, + bool deftnum=false) const +{ + std::cout<>24)&0xff)<<" " + <>16)&0xff)<<" " + <>8)&0xff)<<" " + <>31);break; + case op_lnkeqc: + std::cout<>31);break; + case op_addc: case op_subc: case op_mulc: case op_divc: + case op_lessc: case op_leqc: case op_grtc: case op_geqc: + case op_pnum: + std::cout<";break; + case op_upval: case op_mupval: case op_loadu: + std::cout<>16)&0xffff) + <<"[0x"<<(num&0xffff)<<"]"<& get_strs() const {return str_res;} const std::vector& get_nums() const {return num_res;} @@ -1237,21 +1297,21 @@ void nasal_codegen::compile(const nasal_parse& parse,const nasal_import& import) nerr.chkerr(); } -void nasal_codegen::print_op(const uint32_t index) +void nasal_codegen::singleop(const uint32_t index) { // print opcode index,opcode name,opcode immediate number const opcode& c=code[index]; if(!festk.empty() && index==festk.top()) { - printf("<0x%x>;\n",fbstk.top()); + std::cout<;\n"; if(code[index].op!=op_newf) // avoid two empty lines - printf("\n"); + std::cout<<"\n"; fbstk.pop(); festk.pop(); } if(c.op==op_newf) { - printf("\nfunc <0x%x>:\n",index); + std::cout<:\n"; for(uint32_t i=index;i>24)&0xff),uint8_t((c.num>>16)&0xff), - uint8_t((c.num>>8)&0xff),uint8_t(c.num&0xff), - code_table[c.op].name - ); - // print detail info - switch(c.op) - { - case op_addeq: case op_subeq: case op_muleq: case op_diveq: - case op_lnkeq: case op_meq: - printf("0x%x sp-%u\n",c.num,c.num);break; - case op_addeqc:case op_subeqc: case op_muleqc:case op_diveqc: - printf("0x%x (",c.num&0x7fffffff); - std::cout<>31)<<"\n"; - break; - case op_lnkeqc: - printf("0x%x (\"%s\") sp-%u\n",c.num&0x7fffffff,rawstr(str_res[c.num&0x7fffffff],16).c_str(),c.num>>31); - break; - case op_addc: case op_subc: case op_mulc: case op_divc: - case op_lessc: case op_leqc: case op_grtc: case op_geqc: - case op_pnum: - printf("0x%x (",c.num);std::cout<\n",c.num,builtin[c.num].name,(uint64_t)builtin[c.num].func);break; - case op_upval:case op_mupval: case op_loadu: - printf("0x%x[0x%x]\n",(c.num>>16)&0xffff,c.num&0xffff);break; - case op_happ: case op_pstr: - case op_lnkc: - case op_callh: case op_mcallh: - case op_para: case op_deft: case op_dyn: - printf("0x%x (\"%s\")\n",c.num,rawstr(str_res[c.num],16).c_str());break; - default:printf("\n");break; - } + c.print(" ",num_res.data(),str_res.data(),index); + std::cout<<"\n"; } void nasal_codegen::print() @@ -1310,7 +1332,7 @@ void nasal_codegen::print() std::cout<<" .symbol \""<>3)==0?0:((line>>3)<<3); end=(1+(line>>3))<<3; for(uint32_t i=begin;i":" ",src[i].c_str()); - printf("next bytecode:\n"); + std::cout<<(i==line?"--> ":" ")<>3)==0?0:((pc>>3)<<3); end=(1+(pc>>3))<<3; for(uint32_t i=begin;i\t":" \t",i); + bytecodeinfo(i==pc?"--> ":" ",i); stackinfo(10); } @@ -119,7 +119,7 @@ void nasal_dbg::interact() stepinfo(); while(1) { - printf(">> "); + std::cout<<">> "; std::getline(std::cin,cmd); auto res=parse(cmd); if(res.size()==1) @@ -132,7 +132,7 @@ void nasal_dbg::interact() return; else if(res[0]=="f" || res[0]=="file") for(size_t i=0;i %s\n",(uint64_t)p,rawstr(val.str(),16).c_str());break; - case vm_func: printf("| func | <0x" PRTHEX64 "> entry:0x%x\n",(uint64_t)p,val.func().entry);break; - case vm_upval:printf("| upval| <0x" PRTHEX64 "> [%u val]\n",(uint64_t)p,val.upval().size);break; - case vm_vec: printf("| vec | <0x" PRTHEX64 "> [%zu val]\n",(uint64_t)p,val.vec().size());break; - case vm_hash: printf("| hash | <0x" PRTHEX64 "> {%zu val}\n",(uint64_t)p,val.hash().size());break; - case vm_obj: printf("| obj | <0x" PRTHEX64 "> obj:0x" PRTHEX64 "\n",(uint64_t)p,(uint64_t)val.obj().ptr);break; - case vm_co: printf("| co | <0x" PRTHEX64 "> coroutine\n",(uint64_t)p);break; - default: printf("| err | <0x" PRTHEX64 "> unknown object\n",(uint64_t)p);break; + case vm_none: std::cout<<"| null |";break; + case vm_ret: std::cout<<"| pc | 0x"< " + < entry:0x" + < [" + < [" + < {" + < obj:0x" + <<(uint64_t)val.obj().ptr< coroutine";break; + default: std::cout<<"| err | <"< unknown object";break; } + std::cout<<"\n"; } void nasal_vm::bytecodeinfo(const char* header,const uint32_t p) { const opcode& c=bytecode[p]; - printf("%s0x%.8x: %.2x %.2x %.2x %.2x %.2x %s ", - header,p,c.op, - uint8_t((c.num>>24)&0xff),uint8_t((c.num>>16)&0xff), - uint8_t((c.num>>8)&0xff),uint8_t(c.num&0xff), - code_table[c.op].name - ); - switch(c.op) - { - case op_addeq: case op_subeq: case op_muleq: case op_diveq: - case op_lnkeq: case op_meq: - printf("0x%x sp-%u",c.num,c.num);break; - case op_addeqc:case op_subeqc: case op_muleqc:case op_diveqc: - printf("0x%x (",c.num&0x7fffffff); - std::cout<>31); - break; - case op_lnkeqc: - printf("0x%x (\"%s\") sp-%u",c.num&0x7fffffff,rawstr(str_table[c.num&0x7fffffff],16).c_str(),c.num>>31); - break; - case op_addc: case op_subc: case op_mulc: case op_divc: - case op_lessc: case op_leqc: case op_grtc: case op_geqc: - case op_pnum: - printf("0x%x (",c.num);std::cout<",c.num,builtin[c.num].name,(uint64_t)builtin[c.num].func);break; - case op_upval: case op_mupval: case op_loadu: - printf("0x%x[0x%x]",(c.num>>16)&0xffff,c.num&0xffff);break; - case op_happ: case op_pstr: - case op_lnkc: - case op_callh: case op_mcallh: - case op_para: case op_deft: case op_dyn: - printf("0x%x (\"%s\")",c.num,rawstr(str_table[c.num],16).c_str()); - break; - default:printf("0x%x",c.num);break; - } - printf(" (%s:%u)\n",files[c.fidx].c_str(),c.line); + c.print(header,num_table,str_table,p,true); + std::cout<<" ("<ret()); // push pc to ret stack to store the position program crashed ret.push(pc); - printf("trace back:\n"); + std::cout<<"trace back:\n"; uint32_t same=0,last=0xffffffff; for(uint32_t point=0;!ret.empty();last=point,ret.pop()) { @@ -239,12 +211,14 @@ void nasal_vm::traceback() continue; } if(same) - printf("\t0x%.8x: %u same call(s)\n",last,same); + std::cout<<" 0x"<, limit %u, total ",(uint64_t)bottom,gsize,limit); + std::cout<<"vm stack(0x"<, limit "<=bottom;++i,--t) { - printf(" 0x" PRTHEX64_8 "",(uint64_t)(t-gc.stack)); + std::cout<<" 0x"< entry:0x%x\n", - (uint64_t)funcr.value.gcobj, - funcr.func().entry); - if(upvalr.type==vm_nil) - printf(" [ upvalr ] | nil |\n"); - else - printf(" [ upvalr ] | upval| <0x" PRTHEX64 "> [%u val]\n", - (uint64_t)upvalr.value.gcobj, - upvalr.upval().size); - printf(" [ canary ] | addr | 0x" PRTHEX64 "\n",(uint64_t)canary); - printf(" [ top ] | addr | 0x" PRTHEX64 "\n",(uint64_t)top); + std::cout<<"registers("<<(gc.coroutine?"coroutine":"main")<<")\n"<):\n",(uint64_t)stack); + std::cout<<"global(0x"<)\n"<):\n",(uint64_t)localr,(int64_t)(localr-gc.stack)); + std::cout<<"local(0x"<)\n"< upval[%u]:\n",i); + std::cout<<" -> upval["<>16)&0xffff].upval()[imm[pc]&0xffff]=(top--)[0]; + funcr.func().upvalue[(imm[pc]>>16)&0xffff] + .upval()[imm[pc]&0xffff]=(top--)[0]; } inline void nasal_vm::opr_pnum() { @@ -461,14 +432,16 @@ inline void nasal_vm::opr_happ() inline void nasal_vm::opr_para() { nasal_func& func=top[0].func(); - func.keys[str_table[imm[pc]]]=func.psize;// func->size has 1 place reserved for "me" + // func->size has 1 place reserved for "me" + func.keys[str_table[imm[pc]]]=func.psize; func.local[func.psize++]={vm_none}; } inline void nasal_vm::opr_deft() { nasal_ref val=top[0]; nasal_func& func=(--top)[0].func(); - func.keys[str_table[imm[pc]]]=func.psize;// func->size has 1 place reserved for "me" + // func->size has 1 place reserved for "me" + func.keys[str_table[imm[pc]]]=func.psize; func.local[func.psize++]=val; } inline void nasal_vm::opr_dyn() @@ -669,7 +642,8 @@ inline void nasal_vm::opr_calll() } inline void nasal_vm::opr_upval() { - (++top)[0]=funcr.func().upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]; + (++top)[0]=funcr.func().upvalue[(imm[pc]>>16)&0xffff] + .upval()[imm[pc]&0xffff]; } inline void nasal_vm::opr_callv() { @@ -738,10 +712,11 @@ inline void nasal_vm::opr_callfv() nasal_ref tmp=local[-1]; local[-1]=funcr; funcr=tmp; - if(top-argc+func.lsize+3>=canary) // top-argc+lsize(local) +1(old pc) +1(old localr) +1(old upvalr) + // top-argc+lsize(local) +1(old pc) +1(old localr) +1(old upvalr) + if(top-argc+func.lsize+3>=canary) die("stack overflow"); - - uint32_t psize=func.psize-1; // parameter size is func->psize-1, 1 is reserved for "me" + // parameter size is func->psize-1, 1 is reserved for "me" + uint32_t psize=func.psize-1; if(argc=canary) // top -1(hash) +lsize(local) +1(old pc) +1(old localr) +1(old upvalr) + // top -1(hash) +lsize(local) +1(old pc) +1(old localr) +1(old upvalr) + if(top+func.lsize+2>=canary) die("stack overflow"); if(func.dynpara>=0) die("callfh: special call cannot use dynamic argument"); @@ -901,7 +877,7 @@ inline void nasal_vm::opr_mcallv() if(!memr) die("mcallv: index out of range:"+std::to_string(val.tonum())); } - else if(vec.type==vm_hash) // special call of hash, this do mcallh but use the mcallv way + else if(vec.type==vm_hash) // do mcallh but use the mcallv way { if(val.type!=vm_str) die("mcallv: must use string as the key"); @@ -1027,7 +1003,13 @@ vmexit: imm.clear(); return; // may cause stackoverflow -#define exec_operand(op,num) {op();++count[num];if(top