From 99a131c55280b839b2f80d76e505530dded8ee44 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Sat, 23 Jul 2022 17:00:25 +0800 Subject: [PATCH] :rocket: change `std::string` to `string`, change identifiers' name, `-o` is now a function available in debug mode. --- README.md | 132 ++++---- doc/README_zh.md | 132 ++++---- main.cpp | 19 +- makefile | 10 +- module/fib.cpp | 8 +- module/keyboard.cpp | 6 +- module/nasocket.cpp | 30 +- nasal.h | 13 +- nasal_ast.h | 10 +- nasal_builtin.h | 496 ++++++++++++++-------------- nasal_codegen.h | 64 ++-- nasal_dbg.h | 325 +++++++++++-------- nasal_err.h | 22 +- nasal_gc.h | 468 +++++++++++++-------------- nasal_import.h | 34 +- nasal_lexer.h | 66 ++-- nasal_parse.h | 12 +- nasal_vm.h | 766 +++++++++++++++++++++----------------------- 18 files changed, 1310 insertions(+), 1303 deletions(-) diff --git a/README.md b/README.md index 0eb750b..04a803c 100644 --- a/README.md +++ b/README.md @@ -559,7 +559,7 @@ If you really want to change source code, check built-in functions in `lib.nas` Definition: ```C++ -nasal_ref builtin_print(nasal_ref*,nasal_gc&); +nas_ref builtin_print(nas_ref*,nasal_gc&); // you could also use a macro to define one. nas_native(builtin_print); ``` @@ -567,11 +567,11 @@ nas_native(builtin_print); Then complete this function using C++: ```C++ -nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_print(nas_ref* local,nasal_gc& gc) { // find value with index begin from 1 // because local[0] is reserved for value 'me' - nasal_ref vec=local[1]; + nas_ref vec=local[1]; // main process // also check number of arguments and type here // if get an error,use builtin_err @@ -601,7 +601,7 @@ After that, register the built-in function's name(in nasal) and the function's p struct func { const char* name; - nasal_ref (*func)(nasal_ref*,nasal_gc&); + nas_ref (*func)(nas_ref*,nasal_gc&); } builtin[]= { {"__print",builtin_print}, @@ -644,13 +644,13 @@ The value got before will be collected, but stil in use in this builtin function So use `gc::temp` in builtin functions to temprorarily store the gc-managed value that you want to return later. Like this: ```C++ -nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_keys(nas_ref* local,nasal_gc& gc) { - nasal_ref hash=local[1]; + nas_ref hash=local[1]; if(hash.type!=vm_hash) return builtin_err("keys","\"hash\" must be hash"); // avoid being sweeped - nasal_ref res=gc.temp=gc.alloc(vm_vec); + nas_ref res=gc.temp=gc.alloc(vm_vec); auto& vec=res.vec().elems; for(auto& iter:hash.hash().elems) vec.push_back(gc.newstr(iter.first)); @@ -693,10 +693,10 @@ double fibonaci(double x){ } // remember to use extern "C", // so you could search the symbol quickly -extern "C" nasal_ref fib(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref fib(std::vector& args,nasal_gc& gc){ // the arguments are generated into a vm_vec: args // get values from the vector that must be used here - nasal_ref num=args[0]; + nas_ref num=args[0]; // if you want your function safer, try this // builtin_err will print the error info on screen // and return vm_null for runtime to interrupt @@ -1330,37 +1330,37 @@ __We will explain how resume and yield work here:__ When `op_callb` is called, the stack frame is like this: ```C++ -+----------------------------+(main stack) -| old pc(vm_ret) | <- top[0] -+----------------------------+ -| old localr(vm_addr) | <- top[-1] -+----------------------------+ -| old upvalr(vm_upval) | <- top[-2] -+----------------------------+ -| local scope(nasal_ref) | -| ... | -+----------------------------+ <- local pointer stored in localr -| old funcr(vm_func) | <- old function stored in funcr -+----------------------------+ ++--------------------------+(main stack) +| old pc(vm_ret) | <- top[0] ++--------------------------+ +| old localr(vm_addr) | <- top[-1] ++--------------------------+ +| old upvalr(vm_upval) | <- top[-2] ++--------------------------+ +| local scope(nas_ref) | +| ... | ++--------------------------+ <- local pointer stored in localr +| old funcr(vm_func) | <- old function stored in funcr ++--------------------------+ ``` In `op_callb`'s progress, next step the stack frame is: ```C++ -+----------------------------+(main stack) -| nil(vm_nil) | <- push nil -+----------------------------+ -| old pc(vm_ret) | -+----------------------------+ -| old localr(vm_addr) | -+----------------------------+ -| old upvalr(vm_upval) | -+----------------------------+ -| local scope(nasal_ref) | -| ... | -+----------------------------+ <- local pointer stored in localr -| old funcr(vm_func) | <- old function stored in funcr -+----------------------------+ ++--------------------------+(main stack) +| nil(vm_nil) | <- push nil ++--------------------------+ +| old pc(vm_ret) | ++--------------------------+ +| old localr(vm_addr) | ++--------------------------+ +| old upvalr(vm_upval) | ++--------------------------+ +| local scope(nas_ref) | +| ... | ++--------------------------+ <- local pointer stored in localr +| old funcr(vm_func) | <- old function stored in funcr ++--------------------------+ ``` Then we call `resume`, this function will change stack. @@ -1371,9 +1371,9 @@ So for safe running, `resume` will return `gc.top[0]`. `op_callb` will do `top[0]=resume()`, so the value does not change. ```C++ -+----------------------------+(coroutine stack) -| pc:0(vm_ret) | <- now gc.top[0] -+----------------------------+ ++--------------------------+(coroutine stack) +| pc:0(vm_ret) | <- now gc.top[0] ++--------------------------+ ``` When we call `yield`, the function will do like this. @@ -1381,40 +1381,40 @@ And we find that `op_callb` has put the `nil` at the top. but where is the returned `local[1]` sent? ```C++ -+----------------------------+(coroutine stack) -| nil(vm_nil) | <- push nil -+----------------------------+ -| old pc(vm_ret) | -+----------------------------+ -| old localr(vm_addr) | -+----------------------------+ -| old upvalr(vm_upval) | -+----------------------------+ -| local scope(nasal_ref) | -| ... | -+----------------------------+ <- local pointer stored in localr -| old funcr(vm_func) | <- old function stored in funcr -+----------------------------+ ++--------------------------+(coroutine stack) +| nil(vm_nil) | <- push nil ++--------------------------+ +| old pc(vm_ret) | ++--------------------------+ +| old localr(vm_addr) | ++--------------------------+ +| old upvalr(vm_upval) | ++--------------------------+ +| local scope(nas_ref) | +| ... | ++--------------------------+ <- local pointer stored in localr +| old funcr(vm_func) | <- old function stored in funcr ++--------------------------+ ``` When `builtin_coyield` is finished, the stack is set to main stack, and the returned `local[1]` in fact is set to the top of the main stack by `op_callb`: ```C++ -+----------------------------+(main stack) -| return_value(nasal_ref) | -+----------------------------+ -| old pc(vm_ret) | -+----------------------------+ -| old localr(vm_addr) | -+----------------------------+ -| old upvalr(vm_upval) | -+----------------------------+ -| local scope(nasal_ref) | -| ... | -+----------------------------+ <- local pointer stored in localr -| old funcr(vm_func) | <- old function stored in funcr -+----------------------------+ ++--------------------------+(main stack) +| return_value(nas_ref) | ++--------------------------+ +| old pc(vm_ret) | ++--------------------------+ +| old localr(vm_addr) | ++--------------------------+ +| old upvalr(vm_upval) | ++--------------------------+ +| local scope(nas_ref) | +| ... | ++--------------------------+ <- local pointer stored in localr +| old funcr(vm_func) | <- old function stored in funcr ++--------------------------+ ``` so the main progress feels the value on the top is the returned value of `resume`. diff --git a/doc/README_zh.md b/doc/README_zh.md index 7f2553d..4e65797 100644 --- a/doc/README_zh.md +++ b/doc/README_zh.md @@ -525,7 +525,7 @@ __警告:__ 如果你 __不想__ 通过直接修改解释器源码来添加你 定义新的内置函数: ```C++ -nasal_ref builtin_print(nasal_ref*,nasal_gc&); +nas_ref builtin_print(nas_ref*,nasal_gc&); // 你可以使用这个宏来直接定义一个新的内置函数 nas_native(builtin_print); ``` @@ -533,11 +533,11 @@ nas_native(builtin_print); 然后用C++完成这个函数的函数体: ```C++ -nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_print(nas_ref* local,nasal_gc& gc) { // 局部变量的下标其实是从1开始的 // 因为local[0]是保留给'me'的空间 - nasal_ref vec=local[1]; + nas_ref vec=local[1]; // 主要部分 // 一些必要的类型检查和输入合法性检测也要在这里写出 // 如果检测到问题,用builtin_err函数来返回vm_null @@ -568,7 +568,7 @@ nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc) struct func { const char* name; - nasal_ref (*func)(nasal_ref*,nasal_gc&); + nas_ref (*func)(nas_ref*,nasal_gc&); } builtin[]= { {"__print",builtin_print}, @@ -608,13 +608,13 @@ import("./dirname/dirname/filename.nas"); 所以请使用`gc::temp`来暂时存储一个会被返回的需要gc管理的变量,这样可以防止内部所有的申请错误触发垃圾回收。如下所示: ```C++ -nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_keys(nas_ref* local,nasal_gc& gc) { - nasal_ref hash=local[1]; + nas_ref hash=local[1]; if(hash.type!=vm_hash) return builtin_err("keys","\"hash\" must be hash"); // 使用gc.temp来存储gc管理的变量,防止错误的回收 - nasal_ref res=gc.temp=gc.alloc(vm_vec); + nas_ref res=gc.temp=gc.alloc(vm_vec); auto& vec=res.vec().elems; for(auto& iter:hash.hash().elems) vec.push_back(gc.newstr(iter.first)); @@ -653,9 +653,9 @@ double fibonaci(double x){ } // 记得用extern "C" // 这样找符号会更加快速便捷,不要在意编译时的warning -extern "C" nasal_ref fib(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref fib(std::vector& args,nasal_gc& gc){ // 传参会被送到一个vm_vec类型中送过来,而不是上文中那种指针直接指向局部作用域 - nasal_ref num=args[0]; + nas_ref num=args[0]; // 如果你想让这个函数有更强的稳定性,那么一定要进行合法性检查 // builtin_err会输出错误信息并返回错误类型让虚拟机终止执行 if(num.type!=vm_num) @@ -1228,37 +1228,37 @@ __接下来我们解释这个协程的运行原理:__ 当`op_callb`被执行时,栈帧如下所示: ```C++ -+----------------------------+(主操作数栈) -| old pc(vm_ret) | <- top[0] -+----------------------------+ -| old localr(vm_addr) | <- top[-1] -+----------------------------+ -| old upvalr(vm_upval) | <- top[-2] -+----------------------------+ -| local scope(nasal_ref) | -| ... | -+----------------------------+ <- local pointer stored in localr -| old funcr(vm_func) | <- old function stored in funcr -+----------------------------+ ++--------------------------+(主操作数栈) +| old pc(vm_ret) | <- top[0] ++--------------------------+ +| old localr(vm_addr) | <- top[-1] ++--------------------------+ +| old upvalr(vm_upval) | <- top[-2] ++--------------------------+ +| local scope(nas_ref) | +| ... | ++--------------------------+ <- local pointer stored in localr +| old funcr(vm_func) | <- old function stored in funcr ++--------------------------+ ``` 在`op_callb`执行过程中,下一步的栈帧如下: ```C++ -+----------------------------+(主操作数栈) -| nil(vm_nil) | <- push nil -+----------------------------+ -| old pc(vm_ret) | -+----------------------------+ -| old localr(vm_addr) | -+----------------------------+ -| old upvalr(vm_upval) | -+----------------------------+ -| local scope(nasal_ref) | -| ... | -+----------------------------+ <- local pointer stored in localr -| old funcr(vm_func) | <- old function stored in funcr -+----------------------------+ ++--------------------------+(主操作数栈) +| nil(vm_nil) | <- push nil ++--------------------------+ +| old pc(vm_ret) | ++--------------------------+ +| old localr(vm_addr) | ++--------------------------+ +| old upvalr(vm_upval) | ++--------------------------+ +| local scope(nas_ref) | +| ... | ++--------------------------+ <- local pointer stored in localr +| old funcr(vm_func) | <- old function stored in funcr ++--------------------------+ ``` 接着我们调用`resume`,这个函数会替换操作数栈。我们会看到,协程的操作数栈上已经保存了一些数据,但是我们首次进入协程执行时,这个操作数栈的栈顶将会是`vm_ret`,并且返回的`pc`值是`0`。 @@ -1266,47 +1266,47 @@ __接下来我们解释这个协程的运行原理:__ 为了保证栈顶的数据不会被破坏,`resume`会返回`gc.top[0]`。`op_callb`将会执行`top[0]=resume()`,所以栈顶的数据虽然被覆盖了一次,但是实际上还是原来的数据。 ```C++ -+----------------------------+(协程操作数栈) -| pc:0(vm_ret) | <- now gc.top[0] -+----------------------------+ ++--------------------------+(协程操作数栈) +| pc:0(vm_ret) | <- now gc.top[0] ++--------------------------+ ``` 当我们调用`yield`的时候,该函数会执行出这个情况,我们发现`op_callb` 已经把`nil`放在的栈顶。但是应该返回的`local[1]`到底发送到哪里去了? ```C++ -+----------------------------+(协程操作数栈) -| nil(vm_nil) | <- push nil -+----------------------------+ -| old pc(vm_ret) | -+----------------------------+ -| old localr(vm_addr) | -+----------------------------+ -| old upvalr(vm_upval) | -+----------------------------+ -| local scope(nasal_ref) | -| ... | -+----------------------------+ <- local pointer stored in localr -| old funcr(vm_func) | <- old function stored in funcr -+----------------------------+ ++--------------------------+(协程操作数栈) +| nil(vm_nil) | <- push nil ++--------------------------+ +| old pc(vm_ret) | ++--------------------------+ +| old localr(vm_addr) | ++--------------------------+ +| old upvalr(vm_upval) | ++--------------------------+ +| local scope(nas_ref) | +| ... | ++--------------------------+ <- local pointer stored in localr +| old funcr(vm_func) | <- old function stored in funcr ++--------------------------+ ``` 当`builtin_coyield`执行完毕之后,栈又切换到了主操作数栈上,这时可以看到返回的`local[1]`实际上被`op_callb`放在了这里的栈顶: ```C++ -+----------------------------+(主操作数栈) -| return_value(nasal_ref) | -+----------------------------+ -| old pc(vm_ret) | -+----------------------------+ -| old localr(vm_addr) | -+----------------------------+ -| old upvalr(vm_upval) | -+----------------------------+ -| local scope(nasal_ref) | -| ... | -+----------------------------+ <- local pointer stored in localr -| old funcr(vm_func) | <- old function stored in funcr -+----------------------------+ ++--------------------------+(主操作数栈) +| return_value(nas_ref) | ++--------------------------+ +| old pc(vm_ret) | ++--------------------------+ +| old localr(vm_addr) | ++--------------------------+ +| old upvalr(vm_upval) | ++--------------------------+ +| local scope(nas_ref) | +| ... | ++--------------------------+ <- local pointer stored in localr +| old funcr(vm_func) | <- old function stored in funcr ++--------------------------+ ``` 所以主程序会认为顶部这个返回值好像是`resume`返回的。而实际上`resume`的返回值在协程的操作数栈顶。综上所述: diff --git a/main.cpp b/main.cpp index 8dcc0c2..7a8b49a 100644 --- a/main.cpp +++ b/main.cpp @@ -34,6 +34,7 @@ void help() <<" -e, --exec | execute.\n" <<" -t, --time | execute and get the running time.\n" <<" -o, --opcnt | execute and count used operands.\n" + <<" | this options is available in debug mode.\n" <<" -d, --detail | execute and get detail crash info.\n" <<" | get garbage collector info if didn't crash.\n" <<" -op, --optimize| use optimizer(beta).\n" @@ -70,7 +71,7 @@ void err() std::exit(1); } -void execute(const std::string& file,const std::vector& argv,const u32 cmd) +void execute(const string& file,const std::vector& argv,const u32 cmd) { // front end use the same error module nasal_err nerr; @@ -104,18 +105,18 @@ void execute(const std::string& file,const std::vector& argv,const // run bytecode if(cmd&VM_DEBUG) { - nasal_dbg debugger; - debugger.run(gen,linker,argv); + nasal_dbg debugger(nerr); + debugger.run(gen,linker,argv,cmd&VM_OPCALLNUM); } else if(cmd&VM_EXECTIME) { auto start=std::chrono::high_resolution_clock::now(); - vm.run(gen,linker,argv,cmd&VM_OPCALLNUM,cmd&VM_DBGINFO); + vm.run(gen,linker,argv,cmd&VM_DBGINFO); auto end=std::chrono::high_resolution_clock::now(); std::clog<<"process exited after "<<(end-start).count()*1.0/std::chrono::high_resolution_clock::duration::period::den<<"s.\n"; } else if(cmd&VM_EXEC) - vm.run(gen,linker,argv,cmd&VM_OPCALLNUM,cmd&VM_DBGINFO); + vm.run(gen,linker,argv,cmd&VM_DBGINFO); } int main(int argc,const char* argv[]) @@ -127,7 +128,7 @@ int main(int argc,const char* argv[]) } if(argc==2) { - std::string s(argv[1]); + string s(argv[1]); if(s=="-v" || s=="--version") logo(); else if(s=="-h" || s=="--help") @@ -138,7 +139,7 @@ int main(int argc,const char* argv[]) err(); return 0; } - std::unordered_map cmdlst={ + std::unordered_map cmdlst={ {"--lex",VM_LEXINFO},{"-l",VM_LEXINFO}, {"--ast",VM_ASTINFO},{"-a",VM_ASTINFO}, {"--code",VM_CODEINFO},{"-c",VM_CODEINFO}, @@ -150,8 +151,8 @@ int main(int argc,const char* argv[]) {"--debug",VM_DEBUG},{"-dbg",VM_DEBUG} }; u32 cmd=0; - std::string filename; - std::vector vm_argv; + string filename; + std::vector vm_argv; for(int i=1;i& args,nasal_gc& gc){ +extern "C" nas_ref fib(std::vector& args,nasal_gc& gc){ std::cout<<"[mod] this is the first test module of nasal\n"; if(!args.size()) return builtin_err("fib","lack arguments"); - nasal_ref num=args[0]; + nas_ref num=args[0]; if(num.type!=vm_num) return builtin_err("extern_fib","\"num\" must be number"); return {vm_num,fibonaci(num.tonum())}; } -extern "C" nasal_ref quick_fib(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref quick_fib(std::vector& args,nasal_gc& gc){ std::cout<<"[mod] this is the first test module of nasal\n"; if(!args.size()) return builtin_err("fib","lack arguments"); - nasal_ref num=args[0]; + nas_ref num=args[0]; if(num.type!=vm_num) return builtin_err("extern_quick_fib","\"num\" must be number"); if(num.num()<2) diff --git a/module/keyboard.cpp b/module/keyboard.cpp index 34ddaac..1731b9a 100644 --- a/module/keyboard.cpp +++ b/module/keyboard.cpp @@ -70,13 +70,13 @@ public: }; noecho_input this_window; -extern "C" nasal_ref nas_getch(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref nas_getch(std::vector& args,nasal_gc& gc){ return {vm_num,(double)this_window.noecho_getch()}; } -extern "C" nasal_ref nas_kbhit(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref nas_kbhit(std::vector& args,nasal_gc& gc){ return {vm_num,(double)this_window.noecho_kbhit()}; } -extern "C" nasal_ref nas_noblock(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref nas_noblock(std::vector& args,nasal_gc& gc){ if(this_window.noecho_kbhit()) return {vm_num,(double)this_window.noecho_getch()}; return nil; diff --git a/module/nasocket.cpp b/module/nasocket.cpp index b79d0d2..9b2c039 100644 --- a/module/nasocket.cpp +++ b/module/nasocket.cpp @@ -24,14 +24,14 @@ static WSAmanager win; #include #endif -extern "C" nasal_ref nas_socket(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref nas_socket(std::vector& args,nasal_gc& gc){ if(args[0].type!=vm_num || args[1].type!=vm_num || args[2].type!=vm_num) return builtin_err("socket","\"af\", \"type\", \"protocol\" should be number"); int sd=socket(args[0].num(),args[1].num(),args[2].num()); return {vm_num,(double)sd}; } -extern "C" nasal_ref nas_closesocket(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref nas_closesocket(std::vector& args,nasal_gc& gc){ if(args[0].type!=vm_num) return builtin_err("closesocket","\"\" should be number"); #ifdef _WIN32 @@ -41,7 +41,7 @@ extern "C" nasal_ref nas_closesocket(std::vector& args,nasal_gc& gc){ #endif } -extern "C" nasal_ref nas_shutdown(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref nas_shutdown(std::vector& args,nasal_gc& gc){ if(args[0].type!=vm_num) return builtin_err("shutdown","\"sd\" must be a number"); if(args[1].type!=vm_num) @@ -49,7 +49,7 @@ extern "C" nasal_ref nas_shutdown(std::vector& args,nasal_gc& gc){ return {vm_num,(double)shutdown(args[0].num(),args[1].num())}; } -extern "C" nasal_ref nas_bind(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref nas_bind(std::vector& args,nasal_gc& gc){ if(args[0].type!=vm_num) return builtin_err("bind","\"sd\" muse be a number"); if(args[1].type!=vm_str) @@ -64,7 +64,7 @@ extern "C" nasal_ref nas_bind(std::vector& args,nasal_gc& gc){ return {vm_num,(double)bind(args[0].num(),(sockaddr*)&server,sizeof(server))}; } -extern "C" nasal_ref nas_listen(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref nas_listen(std::vector& args,nasal_gc& gc){ if(args[0].type!=vm_num) return builtin_err("listen","\"sd\" must be a number"); if(args[1].type!=vm_num) @@ -72,7 +72,7 @@ extern "C" nasal_ref nas_listen(std::vector& args,nasal_gc& gc){ return{vm_num,(double)listen(args[0].num(),args[1].num())}; } -extern "C" nasal_ref nas_connect(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref nas_connect(std::vector& args,nasal_gc& gc){ if(args[0].type!=vm_num) return builtin_err("connect","\"sd\" must be a number"); if(args[1].type!=vm_str) @@ -88,7 +88,7 @@ extern "C" nasal_ref nas_connect(std::vector& args,nasal_gc& gc){ return {vm_num,(double)connect(args[0].num(),(sockaddr*)&addr,sizeof(sockaddr_in))}; } -extern "C" nasal_ref nas_accept(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref nas_accept(std::vector& args,nasal_gc& gc){ if(args[0].type!=vm_num) return builtin_err("accept","\"sd\" must be a number"); sockaddr_in client; @@ -98,7 +98,7 @@ extern "C" nasal_ref nas_accept(std::vector& args,nasal_gc& gc){ #else int client_sd=accept(args[0].num(),(sockaddr*)&client,(socklen_t*)&socklen); #endif - nasal_ref res=gc.temp=gc.alloc(vm_hash); + nas_ref res=gc.temp=gc.alloc(vm_hash); auto& hash=res.hash().elems; hash["sd"]={vm_num,(double)client_sd}; hash["ip"]=gc.newstr(inet_ntoa(client.sin_addr)); @@ -106,7 +106,7 @@ extern "C" nasal_ref nas_accept(std::vector& args,nasal_gc& gc){ return res; } -extern "C" nasal_ref nas_send(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref nas_send(std::vector& args,nasal_gc& gc){ if(args[0].type!=vm_num) return builtin_err("send","\"sd\" must be a number"); if(args[1].type!=vm_str) @@ -116,7 +116,7 @@ extern "C" nasal_ref nas_send(std::vector& args,nasal_gc& gc){ return {vm_num,(double)send(args[0].num(),args[1].str().c_str(),args[1].str().length(),args[2].num())}; } -extern "C" nasal_ref nas_sendto(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref nas_sendto(std::vector& args,nasal_gc& gc){ if(args[0].type!=vm_num) return builtin_err("sendto","\"sd\" must be a number"); if(args[1].type!=vm_str) @@ -136,7 +136,7 @@ extern "C" nasal_ref nas_sendto(std::vector& args,nasal_gc& gc){ return {vm_num,(double)sendto(args[0].num(),args[3].str().c_str(),args[3].str().length(),args[4].num(),(sockaddr*)&addr,sizeof(sockaddr_in))}; } -extern "C" nasal_ref nas_recv(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref nas_recv(std::vector& args,nasal_gc& gc){ if(args[0].type!=vm_num) return builtin_err("recv","\"sd\" must be a number"); if(args[1].type!=vm_num) @@ -145,7 +145,7 @@ extern "C" nasal_ref nas_recv(std::vector& args,nasal_gc& gc){ return builtin_err("recv","\"len\" out of range"); if(args[2].type!=vm_num) return builtin_err("recv","\"flags\" muse be a number"); - nasal_ref res=gc.temp=gc.alloc(vm_hash); + nas_ref res=gc.temp=gc.alloc(vm_hash); auto& hash=res.hash().elems; char* buf=new char[(int)args[1].num()]; hash["size"]={vm_num,(double)recv(args[0].num(),buf,args[1].num(),args[2].num())}; @@ -155,7 +155,7 @@ extern "C" nasal_ref nas_recv(std::vector& args,nasal_gc& gc){ return res; } -extern "C" nasal_ref nas_recvfrom(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref nas_recvfrom(std::vector& args,nasal_gc& gc){ if(args[0].type!=vm_num) return builtin_err("recvfrom","\"sd\" must be a number"); if(args[1].type!=vm_num) @@ -166,7 +166,7 @@ extern "C" nasal_ref nas_recvfrom(std::vector& args,nasal_gc& gc){ return builtin_err("recvfrom","\"flags\" muse be a number"); sockaddr_in addr; int socklen=sizeof(sockaddr_in); - nasal_ref res=gc.temp=gc.alloc(vm_hash); + nas_ref res=gc.temp=gc.alloc(vm_hash); auto& hash=res.hash().elems; char* buf=new char[(int)args[1].num()+1]; #ifdef _WIN32 @@ -182,6 +182,6 @@ extern "C" nasal_ref nas_recvfrom(std::vector& args,nasal_gc& gc){ return res; } -extern "C" nasal_ref nas_errno(std::vector& args,nasal_gc& gc){ +extern "C" nas_ref nas_errno(std::vector& args,nasal_gc& gc){ return gc.newstr(strerror(errno)); } \ No newline at end of file diff --git a/nasal.h b/nasal.h index be3c57a..30ac547 100644 --- a/nasal.h +++ b/nasal.h @@ -42,13 +42,13 @@ using i32=std::int32_t; using i64=std::int64_t; -using u8 =std::uint8_t; +using u8=std::uint8_t; using u16=std::uint16_t; using u32=std::uint32_t; using u64=std::uint64_t; using usize=std::size_t; using f64=double; - +using std::string; const u32 STACK_DEPTH=2048; @@ -145,14 +145,15 @@ int utf8_hdchk(const char head) return 0; } -std::string chrhex(const char c) +string chrhex(const char c) { - return {"0123456789abcdef"[(c&0xf0)>>4],"0123456789abcdef"[c&0x0f]}; + const char hextbl[]="0123456789abcdef"; + return {hextbl[(c&0xf0)>>4],hextbl[c&0x0f]}; } -std::string rawstr(const std::string& str,const usize maxlen=0) +string rawstr(const string& str,const usize maxlen=0) { - std::string ret(""); + string ret(""); for(auto i:str) { #ifdef _WIN32 diff --git a/nasal_ast.h b/nasal_ast.h index f71dadf..3529a4c 100644 --- a/nasal_ast.h +++ b/nasal_ast.h @@ -1,7 +1,7 @@ #ifndef __NASAL_AST_H__ #define __NASAL_AST_H__ -enum ast_node +enum ast_node:u32 { ast_null=0, // null node ast_root, // mark the root node of ast @@ -132,7 +132,7 @@ private: u32 _line; u32 _type; f64 _num; - std::string _str; + string _str; std::vector _child; public: nasal_ast(const u32 l=0,const u32 t=ast_null):_line(l),_type(t),_num(0){} @@ -151,13 +151,13 @@ public: void add(const nasal_ast& ast){_child.push_back(ast);} void set_line(const u32 l){_line=l;} void set_type(const u32 t){_type=t;} - void set_str(const std::string& s){_str=s;} + void set_str(const string& s){_str=s;} void set_num(const f64 n){_num=n;} inline u32 line() const {return _line;} inline u32 type() const {return _type;} inline f64 num() const {return _num;} - inline const std::string& str() const {return _str;} + inline const string& str() const {return _str;} inline const std::vector& child() const {return _child;} inline std::vector& child(){return _child;} }; @@ -210,7 +210,7 @@ void nasal_ast::clear() void nasal_ast::print(int depth,bool last=false) { - static std::vector intentation={}; + static std::vector intentation={}; for(auto& i:intentation) std::cout<& elems) +inline void print_core(std::vector& elems) { for(auto& i:elems) switch(i.type) @@ -224,7 +224,7 @@ inline void print_core(std::vector& elems) case vm_co: std::cout<<""; break; } } -nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_print(nas_ref* local,nasal_gc& gc) { // get arguments,local[0] is reserved for 'me' print_core(local[1].vec().elems); @@ -232,21 +232,21 @@ nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc) // generate return value return nil; } -nasal_ref builtin_println(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_println(nas_ref* local,nasal_gc& gc) { print_core(local[1].vec().elems); std::cout<>ret.str(); return ret; } -nasal_ref builtin_fin(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_fin(nas_ref* local,nasal_gc& gc) { - nasal_ref val=local[1]; + nas_ref val=local[1]; if(val.type!=vm_str) return builtin_err("io.fin","\"filename\" must be string"); std::ifstream fin(val.str()); @@ -295,10 +295,10 @@ nasal_ref builtin_fin(nasal_ref* local,nasal_gc& gc) } return builtin_err("io.fin","cannot open <"+val.str()+">"); } -nasal_ref builtin_fout(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_fout(nas_ref* local,nasal_gc& gc) { - nasal_ref val=local[1]; - nasal_ref str=local[2]; + nas_ref val=local[1]; + nas_ref str=local[2]; if(val.type!=vm_str) return builtin_err("io.fout","\"filename\" must be string"); if(str.type!=vm_str) @@ -309,20 +309,20 @@ nasal_ref builtin_fout(nasal_ref* local,nasal_gc& gc) fout<& vec=res.vec().elems; + nas_ref res=gc.temp=gc.alloc(vm_vec); + std::vector& vec=res.vec().elems; if(!deli.length()) { @@ -333,7 +333,7 @@ nasal_ref builtin_split(nasal_ref* local,nasal_gc& gc) } usize last=0; usize pos=s.find(deli,last); - while(pos!=std::string::npos) + while(pos!=string::npos) { if(pos>last) vec.push_back(gc.newstr(s.substr(last,pos-last))); @@ -345,9 +345,9 @@ nasal_ref builtin_split(nasal_ref* local,nasal_gc& gc) gc.temp=nil; return res; } -nasal_ref builtin_rand(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_rand(nas_ref* local,nasal_gc& gc) { - nasal_ref val=local[1]; + nas_ref val=local[1]; if(val.type!=vm_num && val.type!=vm_nil) return builtin_err("rand","\"seed\" must be nil or number"); if(val.type==vm_num) @@ -360,9 +360,9 @@ nasal_ref builtin_rand(nasal_ref* local,nasal_gc& gc) num=(num+rand())*(1.0/(RAND_MAX+1.0)); return {vm_num,num}; } -nasal_ref builtin_id(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_id(nas_ref* local,nasal_gc& gc) { - nasal_ref val=local[1]; + nas_ref val=local[1]; std::stringstream ss; if(val.type>vm_num) ss<<"0x"<"); - nasal_ref ret=gc.alloc(vm_obj); - ret.obj().set(nasal_obj::file,res,obj_file_dtor); + nas_ref ret=gc.alloc(vm_obj); + ret.obj().set(nas_obj::file,res,obj_file_dtor); return ret; } -nasal_ref builtin_close(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_close(nas_ref* local,nasal_gc& gc) { - nasal_ref fd=local[1]; - if(!fd.objchk(nasal_obj::file)) + nas_ref fd=local[1]; + if(!fd.objchk(nas_obj::file)) return builtin_err("close","not a valid filehandle"); fclose((FILE*)fd.obj().ptr); fd.obj().ptr=nullptr; return nil; } -nasal_ref builtin_read(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_read(nas_ref* local,nasal_gc& gc) { - nasal_ref fd=local[1]; - nasal_ref buf=local[2]; - nasal_ref len=local[3]; - if(!fd.objchk(nasal_obj::file)) + nas_ref fd=local[1]; + nas_ref buf=local[2]; + nas_ref len=local[3]; + if(!fd.objchk(nas_obj::file)) return builtin_err("read","not a valid filehandle"); if(buf.type!=vm_str) return builtin_err("read","\"buf\" must be string"); @@ -800,23 +800,23 @@ nasal_ref builtin_read(nasal_ref* local,nasal_gc& gc) delete []buff; return {vm_num,res}; } -nasal_ref builtin_write(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_write(nas_ref* local,nasal_gc& gc) { - nasal_ref fd=local[1]; - nasal_ref str=local[2]; - if(!fd.objchk(nasal_obj::file)) + nas_ref fd=local[1]; + nas_ref str=local[2]; + if(!fd.objchk(nas_obj::file)) return builtin_err("write","not a valid filehandle"); if(str.type!=vm_str) return builtin_err("write","\"str\" must be string"); f64 res=(f64)fwrite(str.str().c_str(),1,str.str().length(),(FILE*)fd.obj().ptr); return {vm_num,res}; } -nasal_ref builtin_seek(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_seek(nas_ref* local,nasal_gc& gc) { - nasal_ref fd=local[1]; - nasal_ref pos=local[2]; - nasal_ref whence=local[3]; - if(!fd.objchk(nasal_obj::file)) + nas_ref fd=local[1]; + nas_ref pos=local[2]; + nas_ref whence=local[3]; + if(!fd.objchk(nas_obj::file)) return builtin_err("seek","not a valid filehandle"); if(pos.type!=vm_num) return builtin_err("seek","\"pos\" must be number"); @@ -825,20 +825,20 @@ nasal_ref builtin_seek(nasal_ref* local,nasal_gc& gc) f64 res=fseek((FILE*)fd.obj().ptr,pos.num(),whence.num()); return {vm_num,res}; } -nasal_ref builtin_tell(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_tell(nas_ref* local,nasal_gc& gc) { - nasal_ref fd=local[1]; - if(!fd.objchk(nasal_obj::file)) + nas_ref fd=local[1]; + if(!fd.objchk(nas_obj::file)) return builtin_err("tell","not a valid filehandle"); f64 res=ftell((FILE*)fd.obj().ptr); return {vm_num,res}; } -nasal_ref builtin_readln(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_readln(nas_ref* local,nasal_gc& gc) { - nasal_ref fd=local[1]; - if(!fd.objchk(nasal_obj::file)) + nas_ref fd=local[1]; + if(!fd.objchk(nas_obj::file)) return builtin_err("readln","not a valid filehandle"); - nasal_ref str=gc.alloc(vm_str); + nas_ref str=gc.alloc(vm_str); auto& s=str.str(); char c; while((c=fgetc((FILE*)fd.obj().ptr))!=EOF) @@ -853,15 +853,15 @@ nasal_ref builtin_readln(nasal_ref* local,nasal_gc& gc) return str; return nil; } -nasal_ref builtin_stat(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_stat(nas_ref* local,nasal_gc& gc) { - nasal_ref name=local[1]; + nas_ref name=local[1]; if(name.type!=vm_str) return builtin_err("stat","\"filename\" must be string"); struct stat buf; if(stat(name.str().c_str(),&buf)<0) return builtin_err("stat","failed to open file <"+name.str()+">"); - nasal_ref ret=gc.alloc(vm_vec); + nas_ref ret=gc.alloc(vm_vec); ret.vec().elems={ {vm_num,(f64)buf.st_dev}, {vm_num,(f64)buf.st_ino}, @@ -877,21 +877,21 @@ nasal_ref builtin_stat(nasal_ref* local,nasal_gc& gc) }; return ret; } -nasal_ref builtin_eof(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_eof(nas_ref* local,nasal_gc& gc) { - nasal_ref fd=local[1]; - if(!fd.objchk(nasal_obj::file)) + nas_ref fd=local[1]; + if(!fd.objchk(nas_obj::file)) return builtin_err("readln","not a valid filehandle"); return {vm_num,(f64)feof((FILE*)fd.obj().ptr)}; } -nasal_ref builtin_fld(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_fld(nas_ref* local,nasal_gc& gc) { // bits.fld(s,0,3); // if s stores 10100010(162) // will get 101(5) - nasal_ref str=local[1]; - nasal_ref startbit=local[2]; - nasal_ref length=local[3]; + nas_ref str=local[1]; + nas_ref startbit=local[2]; + nas_ref length=local[3]; if(str.type!=vm_str || str.val.gcobj->unmut) return builtin_err("fld","\"str\" must be mutable string"); if(startbit.type!=vm_num || length.type!=vm_num) @@ -907,15 +907,15 @@ nasal_ref builtin_fld(nasal_ref* local,nasal_gc& gc) res|=1<<(bit+len-i-1); return {vm_num,(f64)res}; } -nasal_ref builtin_sfld(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_sfld(nas_ref* local,nasal_gc& gc) { // bits.sfld(s,0,3); // if s stores 10100010(162) // will get 101(5) then this will be signed extended to // 11111101(-3) - nasal_ref str=local[1]; - nasal_ref startbit=local[2]; - nasal_ref length=local[3]; + nas_ref str=local[1]; + nas_ref startbit=local[2]; + nas_ref length=local[3]; if(str.type!=vm_str || str.val.gcobj->unmut) return builtin_err("sfld","\"str\" must be mutable string"); if(startbit.type!=vm_num || length.type!=vm_num) @@ -933,16 +933,16 @@ nasal_ref builtin_sfld(nasal_ref* local,nasal_gc& gc) res|=~((1<unmut) return builtin_err("setfld","\"str\" must be mutable string"); if(startbit.type!=vm_num || length.type!=vm_num || value.type!=vm_num) @@ -962,29 +962,29 @@ nasal_ref builtin_setfld(nasal_ref* local,nasal_gc& gc) } return nil; } -nasal_ref builtin_buf(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_buf(nas_ref* local,nasal_gc& gc) { - nasal_ref length=local[1]; + nas_ref length=local[1]; if(length.type!=vm_num || length.num()<=0) return builtin_err("buf","\"len\" must be a number greater than 0"); - nasal_ref str=gc.alloc(vm_str); + nas_ref str=gc.alloc(vm_str); auto& s=str.str(); s.resize(length.num(),'\0'); return str; } -nasal_ref builtin_sleep(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_sleep(nas_ref* local,nasal_gc& gc) { - nasal_ref val=local[1]; + nas_ref val=local[1]; if(val.type!=vm_num) return builtin_err("sleep","\"duration\" must be number"); std::this_thread::sleep_for(std::chrono::microseconds(i64(val.num()*1e6))); return nil; } -nasal_ref builtin_pipe(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_pipe(nas_ref* local,nasal_gc& gc) { #ifndef _WIN32 int fd[2]; - nasal_ref res=gc.alloc(vm_vec); + nas_ref res=gc.alloc(vm_vec); if(pipe(fd)==-1) return builtin_err("pipe","failed to create pipe"); res.vec().elems.push_back({vm_num,(f64)fd[0]}); @@ -993,7 +993,7 @@ nasal_ref builtin_pipe(nasal_ref* local,nasal_gc& gc) #endif return builtin_err("pipe","not supported for windows"); } -nasal_ref builtin_fork(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_fork(nas_ref* local,nasal_gc& gc) { #ifndef _WIN32 f64 res=fork(); @@ -1003,17 +1003,17 @@ nasal_ref builtin_fork(nasal_ref* local,nasal_gc& gc) #endif return builtin_err("fork","not supported for windows"); } -nasal_ref builtin_waitpid(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_waitpid(nas_ref* local,nasal_gc& gc) { - nasal_ref pid=local[1]; - nasal_ref nohang=local[2]; + nas_ref pid=local[1]; + nas_ref nohang=local[2]; if(pid.type!=vm_num || nohang.type!=vm_num) return builtin_err("waitpid","pid and nohang must be number"); #ifndef _WIN32 int ret_pid; int status; ret_pid=waitpid(pid.num(),&status,nohang.num()==0?0:WNOHANG); - nasal_ref vec=gc.alloc(vm_vec); + nas_ref vec=gc.alloc(vm_vec); vec.vec().elems.push_back({vm_num,(f64)ret_pid}); vec.vec().elems.push_back({vm_num,(f64)status}); return vec; @@ -1028,9 +1028,9 @@ void obj_dir_dtor(void* ptr) FindClose(ptr); #endif } -nasal_ref builtin_opendir(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_opendir(nas_ref* local,nasal_gc& gc) { - nasal_ref path=local[1]; + nas_ref path=local[1]; if(path.type!=vm_str) return builtin_err("opendir","\"path\" must be string"); #ifdef _MSC_VER @@ -1044,14 +1044,14 @@ nasal_ref builtin_opendir(nasal_ref* local,nasal_gc& gc) if(!p) return builtin_err("opendir","cannot open dir <"+path.str()+">"); #endif - nasal_ref ret=gc.alloc(vm_obj); - ret.obj().set(nasal_obj::dir,p,obj_dir_dtor); + nas_ref ret=gc.alloc(vm_obj); + ret.obj().set(nas_obj::dir,p,obj_dir_dtor); return ret; } -nasal_ref builtin_readdir(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_readdir(nas_ref* local,nasal_gc& gc) { - nasal_ref handle=local[1]; - if(!handle.objchk(nasal_obj::dir)) + nas_ref handle=local[1]; + if(!handle.objchk(nas_obj::dir)) return builtin_err("readdir","not a valid dir handle"); #ifdef _MSC_VER WIN32_FIND_DATA data; @@ -1065,10 +1065,10 @@ nasal_ref builtin_readdir(nasal_ref* local,nasal_gc& gc) return gc.newstr(p->d_name); #endif } -nasal_ref builtin_closedir(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_closedir(nas_ref* local,nasal_gc& gc) { - nasal_ref handle=local[1]; - if(!handle.objchk(nasal_obj::dir)) + nas_ref handle=local[1]; + if(!handle.objchk(nas_obj::dir)) return builtin_err("closedir","not a valid dir handle"); #ifndef _MSC_VER closedir((DIR*)handle.obj().ptr); @@ -1078,19 +1078,19 @@ nasal_ref builtin_closedir(nasal_ref* local,nasal_gc& gc) handle.obj().ptr=nullptr; return nil; } -nasal_ref builtin_chdir(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_chdir(nas_ref* local,nasal_gc& gc) { - nasal_ref path=local[1]; + nas_ref path=local[1]; if(path.type!=vm_str) return builtin_err("chdir","\"path\" must be string"); if(chdir(path.str().c_str())<0) return builtin_err("chdir","failed to execute chdir"); return nil; } -nasal_ref builtin_environ(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_environ(nas_ref* local,nasal_gc& gc) { char** env=environ; - nasal_ref res=gc.temp=gc.alloc(vm_vec); + nas_ref res=gc.temp=gc.alloc(vm_vec); auto& vec=res.vec().elems; while(*env) { @@ -1100,16 +1100,16 @@ nasal_ref builtin_environ(nasal_ref* local,nasal_gc& gc) gc.temp=nil; return res; } -nasal_ref builtin_getcwd(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_getcwd(nas_ref* local,nasal_gc& gc) { char buf[1024]; if(!getcwd(buf,sizeof(buf))) return builtin_err("getcwd","failed to call getcwd"); return gc.newstr(buf); } -nasal_ref builtin_getenv(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_getenv(nas_ref* local,nasal_gc& gc) { - nasal_ref envvar=local[1]; + nas_ref envvar=local[1]; if(envvar.type!=vm_str) return builtin_err("getenv","\"envvar\" must be string"); char* res=getenv(envvar.str().c_str()); @@ -1125,9 +1125,9 @@ void obj_dylib_dtor(void* ptr) dlclose(ptr); #endif } -nasal_ref builtin_dlopen(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_dlopen(nas_ref* local,nasal_gc& gc) { - nasal_ref dlname=local[1]; + nas_ref dlname=local[1]; if(dlname.type!=vm_str) return builtin_err("dlopen","\"libname\" must be string"); #ifdef _WIN32 @@ -1141,15 +1141,15 @@ nasal_ref builtin_dlopen(nasal_ref* local,nasal_gc& gc) #endif if(!ptr) return builtin_err("dlopen","cannot open dynamic lib <"+dlname.str()+">"); - nasal_ref ret=gc.alloc(vm_obj); - ret.obj().set(nasal_obj::dylib,ptr,obj_dylib_dtor); + nas_ref ret=gc.alloc(vm_obj); + ret.obj().set(nas_obj::dylib,ptr,obj_dylib_dtor); return ret; } -nasal_ref builtin_dlsym(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_dlsym(nas_ref* local,nasal_gc& gc) { - nasal_ref lib=local[1]; - nasal_ref sym=local[2]; - if(!lib.objchk(nasal_obj::dylib)) + nas_ref lib=local[1]; + nas_ref sym=local[2]; + if(!lib.objchk(nas_obj::dylib)) return builtin_err("dlsym","\"lib\" is not a valid dynamic lib"); if(sym.type!=vm_str) return builtin_err("dlsym","\"sym\" must be string"); @@ -1160,14 +1160,14 @@ nasal_ref builtin_dlsym(nasal_ref* local,nasal_gc& gc) #endif if(!func) return builtin_err("dlsym","cannot find symbol \""+sym.str()+"\""); - nasal_ref ret=gc.alloc(vm_obj); - ret.obj().set(nasal_obj::faddr,func); + nas_ref ret=gc.alloc(vm_obj); + ret.obj().set(nas_obj::faddr,func); return ret; } -nasal_ref builtin_dlclose(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_dlclose(nas_ref* local,nasal_gc& gc) { - nasal_ref libptr=local[1]; - if(!libptr.objchk(nasal_obj::dylib)) + nas_ref libptr=local[1]; + if(!libptr.objchk(nas_obj::dylib)) return builtin_err("dlclose","\"lib\" is not a valid dynamic lib"); #ifdef _WIN32 FreeLibrary((HMODULE)libptr.obj().ptr); @@ -1177,17 +1177,17 @@ nasal_ref builtin_dlclose(nasal_ref* local,nasal_gc& gc) libptr.obj().ptr=nullptr; return nil; } -nasal_ref builtin_dlcall(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_dlcall(nas_ref* local,nasal_gc& gc) { - nasal_ref funcptr=local[1]; - nasal_ref args=local[2]; - if(!funcptr.objchk(nasal_obj::faddr)) + nas_ref funcptr=local[1]; + nas_ref args=local[2]; + if(!funcptr.objchk(nas_obj::faddr)) return builtin_err("dlcall","\"funcptr\" is not a valid function pointer"); - typedef nasal_ref (*externs)(std::vector&,nasal_gc&); + typedef nas_ref (*externs)(std::vector&,nasal_gc&); externs func=(externs)funcptr.obj().ptr; return func(args.vec().elems,gc); } -nasal_ref builtin_platform(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_platform(nas_ref* local,nasal_gc& gc) { #if defined _WIN32 || defined _WIN64 return gc.newstr("windows"); @@ -1198,7 +1198,7 @@ nasal_ref builtin_platform(nasal_ref* local,nasal_gc& gc) #endif return gc.newstr("unknown"); } -nasal_ref builtin_gc(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_gc(nas_ref* local,nasal_gc& gc) { gc.mark(); gc.sweep(); @@ -1206,20 +1206,20 @@ nasal_ref builtin_gc(nasal_ref* local,nasal_gc& gc) } // md5 related functions -std::string tohex(u32 num) +string tohex(u32 num) { const char str16[]="0123456789abcdef"; - std::string str=""; + string str=""; for(u32 i=0;i<4;i++,num>>=8) { - std::string tmp=""; + string tmp=""; for(u32 j=0,b=num&0xff;j<2;j++,b>>=4) tmp.insert(0,1,str16[b&0xf]); str+=tmp; } return str; } -std::string md5(const std::string& source) +string md5(const string& source) { std::vector buff; u32 num=((source.length()+8)>>6)+1; @@ -1289,15 +1289,15 @@ std::string md5(const std::string& source) } return tohex(atmp)+tohex(btmp)+tohex(ctmp)+tohex(dtmp); } -nasal_ref builtin_md5(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_md5(nas_ref* local,nasal_gc& gc) { - nasal_ref str=local[1]; + nas_ref str=local[1]; if(str.type!=vm_str) return builtin_err("md5","\"str\" must be a string"); return gc.newstr(md5(str.str())); } -nasal_ref builtin_cocreate(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_cocreate(nas_ref* local,nasal_gc& gc) { // +-----------------+ // | old pc | <- top[0] @@ -1311,13 +1311,13 @@ nasal_ref builtin_cocreate(nasal_ref* local,nasal_gc& gc) // +-----------------+ <- local pointer stored in localr // | old funcr | <- old function stored in funcr // +-----------------+ - nasal_ref func=local[1]; + nas_ref func=local[1]; if(func.type!=vm_func) return builtin_err("coroutine::create","must use a function to create coroutine"); - if(gc.coroutine) + if(gc.cort) return builtin_err("coroutine::create","cannot create another coroutine in a coroutine"); - nasal_ref co=gc.alloc(vm_co); - nasal_co& coroutine=co.co(); + nas_ref co=gc.alloc(vm_co); + nas_co& coroutine=co.co(); coroutine.pc=func.func().entry-1; coroutine.top[0]=nil; @@ -1326,69 +1326,69 @@ nasal_ref builtin_cocreate(nasal_ref* local,nasal_gc& gc) coroutine.localr[0]=func.func().local[0]; coroutine.top[0]=nil; // old upvalr coroutine.top++; - coroutine.top[0]={vm_addr,(nasal_ref*)nullptr}; // old localr + coroutine.top[0]={vm_addr,(nas_ref*)nullptr}; // old localr coroutine.top++; coroutine.top[0]={vm_ret,(u32)0}; // old pc, set to zero to make op_ret recognizing this as coroutine function coroutine.funcr=func; // make sure the coroutine function can use correct upvalues - coroutine.status=nasal_co::suspended; + coroutine.status=nas_co::suspended; return co; } -nasal_ref builtin_coresume(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_coresume(nas_ref* local,nasal_gc& gc) { - if(gc.coroutine) + if(gc.cort) return builtin_err("coroutine::resume","cannot start another coroutine when one is running"); - nasal_ref co=local[1]; + nas_ref co=local[1]; if(co.type!=vm_co) return builtin_err("coroutine::resume","must use a coroutine object"); - if(co.co().status==nasal_co::dead) + if(co.co().status==nas_co::dead) return nil; gc.ctxchg(co.co()); return gc.top[0]; } -nasal_ref builtin_coyield(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_coyield(nas_ref* local,nasal_gc& gc) { - if(!gc.coroutine) + if(!gc.cort) return builtin_err("coroutine::yield","no coroutine is running"); gc.ctxreserve(); // this will set to main stack top // then builtin_coresume will return it return local[1]; } -nasal_ref builtin_costatus(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_costatus(nas_ref* local,nasal_gc& gc) { - nasal_ref co=local[1]; + nas_ref co=local[1]; if(co.type!=vm_co) return builtin_err("coroutine::status","must use a coroutine object"); switch(co.co().status) { - case nasal_co::suspended: return gc.newstr("suspended");break; - case nasal_co::running: return gc.newstr("running"); break; - case nasal_co::dead: return gc.newstr("dead"); break; + case nas_co::suspended: return gc.newstr("suspended");break; + case nas_co::running: return gc.newstr("running"); break; + case nas_co::dead: return gc.newstr("dead"); break; } return nil; } -nasal_ref builtin_corun(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_corun(nas_ref* local,nasal_gc& gc) { - if(gc.coroutine) + if(gc.cort) return one; return zero; } -nasal_ref builtin_millisec(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_millisec(nas_ref* local,nasal_gc& gc) { f64 res=std::chrono::duration_cast (std::chrono::high_resolution_clock::now().time_since_epoch()) .count(); return {vm_num,res}; } -nasal_ref builtin_sysargv(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_sysargv(nas_ref* local,nasal_gc& gc) { - nasal_ref res=gc.alloc(vm_vec); + nas_ref res=gc.alloc(vm_vec); res.vec().elems=gc.env_argv; return res; } -nasal_ref builtin_logtime(nasal_ref* local,nasal_gc& gc) +nas_ref builtin_logtime(nas_ref* local,nasal_gc& gc) { time_t t=time(nullptr); tm* tm_t=localtime(&t); diff --git a/nasal_codegen.h b/nasal_codegen.h index ea03ac0..09c9480 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -182,13 +182,13 @@ struct opcode } void print(const char*, const f64*, - const std::string*, + const string*, const u32,bool) const; }; void opcode::print(const char* header, const f64* constnum, - const std::string* conststr, + const string* conststr, const u32 index, bool deftnum=false) const { @@ -227,7 +227,7 @@ void opcode::print(const char* header, std::cout<";break; + <<"@0x"<<(u64)builtin[num].func<";break; case op_upval: case op_mupval: case op_loadu: std::cout<>16)&0xffff) <<"[0x"<<(num&0xffff)<<"]"< in_iterloop; std::unordered_map num_table; - std::unordered_map str_table; + std::unordered_map str_table; std::vector num_res; - std::vector str_res; + std::vector str_res; std::vector code; std::list> continue_ptr; std::list> break_ptr; // global : max 4095 values - std::unordered_map global; + std::unordered_map global; // local : max 32768 upvalues 65536 values - std::list> local; + std::list> local; // func end stack, reserved for code print std::stack fbstk; std::stack festk; - void die(const std::string&,const u32); + void die(const string&,const u32); void regist_num(const f64); - void regist_str(const std::string&); + void regist_str(const string&); void find_symbol(const nasal_ast&); - void add_sym(const std::string&); - int local_find(const std::string&); - int global_find(const std::string&); - int upvalue_find(const std::string&); + void add_sym(const string&); + int local_find(const string&); + int global_find(const string&); + int upvalue_find(const string&); void gen(u8,u32,u32); void num_gen(const nasal_ast&); void str_gen(const nasal_ast&); @@ -310,12 +310,12 @@ public: nasal_codegen(nasal_err& e):fileindex(0),nerr(e),file(nullptr){} void compile(const nasal_parse&,const nasal_import&); void print(); - const std::vector& strs() const {return str_res;} - const std::vector& nums() const {return num_res;} - const std::vector& codes() const {return code;} + const std::vector& strs() const {return str_res;} + const std::vector& nums() const {return num_res;} + const std::vector& codes() const {return code;} }; -void nasal_codegen::die(const std::string& info,const u32 line) +void nasal_codegen::die(const string& info,const u32 line) { nerr.load(file[fileindex]); nerr.err("code",line,info); @@ -331,7 +331,7 @@ void nasal_codegen::regist_num(const f64 num) } } -void nasal_codegen::regist_str(const std::string& str) +void nasal_codegen::regist_str(const string& str) { if(!str_table.count(str)) { @@ -366,7 +366,7 @@ void nasal_codegen::find_symbol(const nasal_ast& node) find_symbol(i); } -void nasal_codegen::add_sym(const std::string& name) +void nasal_codegen::add_sym(const string& name) { if(local.empty()) { @@ -382,19 +382,19 @@ void nasal_codegen::add_sym(const std::string& name) local.back()[name]=index; } -int nasal_codegen::local_find(const std::string& name) +int nasal_codegen::local_find(const string& name) { if(local.empty()) return -1; return local.back().count(name)?local.back()[name]:-1; } -int nasal_codegen::global_find(const std::string& name) +int nasal_codegen::global_find(const string& name) { return global.count(name)?global[name]:-1; } -int nasal_codegen::upvalue_find(const std::string& name) +int nasal_codegen::upvalue_find(const string& name) { // 32768 level 65536 upvalues int index=-1; @@ -439,7 +439,7 @@ void nasal_codegen::hash_gen(const nasal_ast& ast) for(auto& node:ast.child()) { calc_gen(node[1]); - const std::string& str=node[0].str(); + const string& str=node[0].str(); regist_str(str); gen(op_happ,str_table[str],node.line()); } @@ -462,7 +462,7 @@ void nasal_codegen::func_gen(const nasal_ast& ast) // generate parameter list for(auto& tmp:ast[0].child()) { - const std::string& str=tmp.str(); + const string& str=tmp.str(); if(str=="me") die("\"me\" should not be a parameter",tmp.line()); regist_str(str); @@ -522,7 +522,7 @@ void nasal_codegen::call_gen(const nasal_ast& ast) void nasal_codegen::call_id(const nasal_ast& ast) { - const std::string& str=ast.str(); + const string& str=ast.str(); for(u32 i=0;builtin[i].name;++i) if(builtin[i].name==str) { @@ -640,7 +640,7 @@ void nasal_codegen::mcall(const nasal_ast& ast) void nasal_codegen::mcall_id(const nasal_ast& ast) { - const std::string& str=ast.str(); + const string& str=ast.str(); for(u32 i=0;builtin[i].name;++i) if(builtin[i].name==str) { @@ -680,7 +680,7 @@ void nasal_codegen::mcall_hash(const nasal_ast& ast) void nasal_codegen::single_def(const nasal_ast& ast) { - const std::string& str=ast[0].str(); + const string& str=ast[0].str(); calc_gen(ast[1]); local.empty()? gen(op_loadg,global_find(str),ast.line()): @@ -696,7 +696,7 @@ void nasal_codegen::multi_def(const nasal_ast& ast) for(int i=0;i parse(const std::string&); - u16 fileindex(const std::string&); + std::vector parse(const string&); + u16 fileindex(const string&); void err(); void help(); + void opcallsort(const u64*); void stepinfo(); void interact(); public: - nasal_dbg(): - next_step(false),fsize(0), - bk_fidx(0),bk_line(0){} + nasal_dbg(nasal_err& nerr): + next(false),fsize(0), + bk_fidx(0),bk_line(0), + src(nerr){} void run( const nasal_codegen&, const nasal_import&, - const std::vector& + const std::vector&, + bool ); }; -std::vector nasal_dbg::parse(const std::string& cmd) +std::vector nasal_dbg::parse(const string& cmd) { - std::vector res; + std::vector res; usize last=0,pos=cmd.find(" ",0); - while(pos!=std::string::npos) + while(pos!=string::npos) { if(pos>last) res.push_back(cmd.substr(last,pos-last)); @@ -45,7 +48,7 @@ std::vector nasal_dbg::parse(const std::string& cmd) return res; } -u16 nasal_dbg::fileindex(const std::string& filename) +u16 nasal_dbg::fileindex(const string& filename) { for(u16 i=0;i op; + std::vector opcall; + u64 total=0; + for(u32 i=0;ib.second;} + ); + std::clog<<"\noperands call info"; + for(auto& i:opcall) + { + u64 rate=i.second*100/total; + if(!rate) + { + std::clog<<"\n ..."; + break; + } + std::clog<<"\n "<& argv) + const std::vector& argv, + bool opcnt) { detail_info=true; fsize=linker.filelist().size(); init(gen.strs(),gen.nums(),gen.codes(),linker.filelist(),argv); + u64 count[op_ret+1]={0}; #ifndef _MSC_VER const void* oprs[]= { @@ -216,54 +248,55 @@ void nasal_dbg::run( typedef void (nasal_dbg::*nafunc)(); const nafunc oprs[]= { - nullptr, &nasal_dbg::opr_intg, - &nasal_dbg::opr_intl, &nasal_dbg::opr_loadg, - &nasal_dbg::opr_loadl, &nasal_dbg::opr_loadu, - &nasal_dbg::opr_pnum, &nasal_dbg::opr_pnil, - &nasal_dbg::opr_pstr, &nasal_dbg::opr_newv, - &nasal_dbg::opr_newh, &nasal_dbg::opr_newf, - &nasal_dbg::opr_happ, &nasal_dbg::opr_para, - &nasal_dbg::opr_deft, &nasal_dbg::opr_dyn, - &nasal_dbg::opr_unot, &nasal_dbg::opr_usub, - &nasal_dbg::opr_add, &nasal_dbg::opr_sub, - &nasal_dbg::opr_mul, &nasal_dbg::opr_div, - &nasal_dbg::opr_lnk, &nasal_dbg::opr_addc, - &nasal_dbg::opr_subc, &nasal_dbg::opr_mulc, - &nasal_dbg::opr_divc, &nasal_dbg::opr_lnkc, - &nasal_dbg::opr_addeq, &nasal_dbg::opr_subeq, - &nasal_dbg::opr_muleq, &nasal_dbg::opr_diveq, - &nasal_dbg::opr_lnkeq, &nasal_dbg::opr_addeqc, - &nasal_dbg::opr_subeqc, &nasal_dbg::opr_muleqc, - &nasal_dbg::opr_diveqc, &nasal_dbg::opr_lnkeqc, - &nasal_dbg::opr_meq, &nasal_dbg::opr_eq, - &nasal_dbg::opr_neq, &nasal_dbg::opr_less, - &nasal_dbg::opr_leq, &nasal_dbg::opr_grt, - &nasal_dbg::opr_geq, &nasal_dbg::opr_lessc, - &nasal_dbg::opr_leqc, &nasal_dbg::opr_grtc, - &nasal_dbg::opr_geqc, &nasal_dbg::opr_pop, - &nasal_dbg::opr_jmp, &nasal_dbg::opr_jt, - &nasal_dbg::opr_jf, &nasal_dbg::opr_cnt, - &nasal_dbg::opr_findex, &nasal_dbg::opr_feach, - &nasal_dbg::opr_callg, &nasal_dbg::opr_calll, - &nasal_dbg::opr_upval, &nasal_dbg::opr_callv, - &nasal_dbg::opr_callvi, &nasal_dbg::opr_callh, - &nasal_dbg::opr_callfv, &nasal_dbg::opr_callfh, - &nasal_dbg::opr_callb, &nasal_dbg::opr_slcbeg, - &nasal_dbg::opr_slcend, &nasal_dbg::opr_slc, - &nasal_dbg::opr_slc2, &nasal_dbg::opr_mcallg, - &nasal_dbg::opr_mcalll, &nasal_dbg::opr_mupval, - &nasal_dbg::opr_mcallv, &nasal_dbg::opr_mcallh, - &nasal_dbg::opr_ret + nullptr, &nasal_dbg::o_intg, + &nasal_dbg::o_intl, &nasal_dbg::o_loadg, + &nasal_dbg::o_loadl, &nasal_dbg::o_loadu, + &nasal_dbg::o_pnum, &nasal_dbg::o_pnil, + &nasal_dbg::o_pstr, &nasal_dbg::o_newv, + &nasal_dbg::o_newh, &nasal_dbg::o_newf, + &nasal_dbg::o_happ, &nasal_dbg::o_para, + &nasal_dbg::o_deft, &nasal_dbg::o_dyn, + &nasal_dbg::o_unot, &nasal_dbg::o_usub, + &nasal_dbg::o_add, &nasal_dbg::o_sub, + &nasal_dbg::o_mul, &nasal_dbg::o_div, + &nasal_dbg::o_lnk, &nasal_dbg::o_addc, + &nasal_dbg::o_subc, &nasal_dbg::o_mulc, + &nasal_dbg::o_divc, &nasal_dbg::o_lnkc, + &nasal_dbg::o_addeq, &nasal_dbg::o_subeq, + &nasal_dbg::o_muleq, &nasal_dbg::o_diveq, + &nasal_dbg::o_lnkeq, &nasal_dbg::o_addeqc, + &nasal_dbg::o_subeqc, &nasal_dbg::o_muleqc, + &nasal_dbg::o_diveqc, &nasal_dbg::o_lnkeqc, + &nasal_dbg::o_meq, &nasal_dbg::o_eq, + &nasal_dbg::o_neq, &nasal_dbg::o_less, + &nasal_dbg::o_leq, &nasal_dbg::o_grt, + &nasal_dbg::o_geq, &nasal_dbg::o_lessc, + &nasal_dbg::o_leqc, &nasal_dbg::o_grtc, + &nasal_dbg::o_geqc, &nasal_dbg::o_pop, + &nasal_dbg::o_jmp, &nasal_dbg::o_jt, + &nasal_dbg::o_jf, &nasal_dbg::o_cnt, + &nasal_dbg::o_findex, &nasal_dbg::o_feach, + &nasal_dbg::o_callg, &nasal_dbg::o_calll, + &nasal_dbg::o_upval, &nasal_dbg::o_callv, + &nasal_dbg::o_callvi, &nasal_dbg::o_callh, + &nasal_dbg::o_callfv, &nasal_dbg::o_callfh, + &nasal_dbg::o_callb, &nasal_dbg::o_slcbeg, + &nasal_dbg::o_slcend, &nasal_dbg::o_slc, + &nasal_dbg::o_slc2, &nasal_dbg::o_mcallg, + &nasal_dbg::o_mcalll, &nasal_dbg::o_mupval, + &nasal_dbg::o_mcallv, &nasal_dbg::o_mcallh, + &nasal_dbg::o_ret }; - std::vector code; + std::vector code; for(auto& i:gen.codes()) { - code.push_back(oprs[i.op]); + code.push_back(i.op); imm.push_back(i.num); } - while(code[pc]){ + while(oprs[code[pc]]){ interact(); - (this->*code[pc])(); + ++count[code[pc]]; + (this->*oprs[code[pc]])(); if(top>=canary) break; ++pc; @@ -273,87 +306,95 @@ void nasal_dbg::run( vmexit: if(top>=canary) die("stack overflow"); + if(opcnt) + opcallsort(count); gc.clear(); imm.clear(); std::cout<<"[debug] debugger exited\n"; return; #ifndef _MSC_VER -#define dbg(op) {interact();op();if(top res; + string file; + std::vector res; public: - void load(const std::string& f) + void load(const string& f) { if(file==f) // don't need to load a loaded file return; @@ -23,7 +23,7 @@ public: std::cerr<<"[src] cannot open file <"<\n"; std::exit(1); } - std::string line; + string line; while(!fin.eof()) { std::getline(fin,line); @@ -32,11 +32,11 @@ public: } void clear() { - std::vector tmp; + std::vector tmp; res.swap(tmp); } - const std::string& operator[](const u32 line){return res[line];} - const std::string& name(){return file;} + const string& operator[](const u32 line){return res[line];} + const string& name(){return file;} usize size(){return res.size();} }; @@ -46,21 +46,21 @@ private: u32 error; public: nasal_err():error(0){} - void err(const char* stage,const std::string& info) + void err(const char* stage,const string& info) { ++error; std::cerr<<"["< elems; + std::vector elems; - nasal_vec():printed(false){} - void print(); - usize size(){return elems.size();} - nasal_ref get_val(const int); - nasal_ref* get_mem(const int); + nas_vec():printed(false){} + void print(); + usize size(){return elems.size();} + nas_ref get_val(const int); + nas_ref* get_mem(const int); }; -struct nasal_hash +struct nas_hash { bool printed; - std::unordered_map elems; + std::unordered_map elems; - nasal_hash():printed(false){} - void print(); - usize size(){return elems.size();} - nasal_ref get_val(const std::string&); - nasal_ref* get_mem(const std::string&); + nas_hash():printed(false){} + void print(); + usize size(){return elems.size();} + nas_ref get_val(const string&); + nas_ref* get_mem(const string&); }; -struct nasal_func +struct nas_func { - i32 dynpara; // dynamic parameter name index in hash. - u32 entry; // pc will set to entry-1 to call this function - u32 psize; // used to load default parameters to a new function - u32 lsize; // used to expand memory space for local values on stack - std::vector local; // local scope with default value(nasal_ref) - std::vector upvalue; // closure - std::unordered_map keys; // parameter name table, u32 begins from 1 + i32 dpara; // dynamic parameter name index in hash. + u32 entry; // pc will set to entry-1 to call this function + u32 psize; // used to load default parameters to a new function + u32 lsize; // used to expand memory space for local values on stack + std::vector local; // local scope with default value(nas_ref) + std::vector upval; // closure + std::unordered_map keys; // parameter table, u32 begins from 1 - nasal_func():dynpara(-1),entry(0),psize(0),lsize(0){} + nas_func():dpara(-1),entry(0),psize(0),lsize(0){} void clear(); }; -struct nasal_upval +struct nas_upval { bool onstk; u32 size; - nasal_ref* stk; - std::vector elems; + nas_ref* stk; + std::vector elems; - nasal_upval(){onstk=true;stk=nullptr;size=0;} - nasal_ref& operator[](const int i){return onstk?stk[i]:elems[i];} + nas_upval(){onstk=true;stk=nullptr;size=0;} + nas_ref& operator[](const int i){return onstk?stk[i]:elems[i];} void clear(){onstk=true;elems.clear();size=0;} }; -struct nasal_obj +struct nas_obj { enum obj_t:u32 { @@ -165,8 +165,8 @@ struct nasal_obj typedef void (*dest)(void*); dest dtor; - nasal_obj():type(obj_t::null),ptr(nullptr),dtor(nullptr){} - ~nasal_obj(){clear();} + nas_obj():type(obj_t::null),ptr(nullptr),dtor(nullptr){} + ~nas_obj(){clear();} void set(u32 t=obj_t::null,void* p=nullptr,dest d=nullptr) { type=t; @@ -182,34 +182,33 @@ struct nasal_obj } }; -struct nasal_co +struct nas_co { - enum coroutine_stat + enum costat:u32 { suspended, running, dead }; - nasal_ref stack[STACK_DEPTH]; + nas_ref stack[STACK_DEPTH]; - u32 pc; - nasal_ref* top; - nasal_ref* canary; - nasal_ref* localr; - nasal_ref* memr; - nasal_ref funcr; - nasal_ref upvalr; + u32 pc; + nas_ref* top; + nas_ref* canary; + nas_ref* localr; + nas_ref* memr; + nas_ref funcr; + nas_ref upvalr; u32 status; - nasal_co(): - pc(0), - top(stack), + nas_co(): + pc(0),top(stack), canary(stack+STACK_DEPTH-1), localr(nullptr), memr(nullptr), funcr({vm_nil,(f64)0}), upvalr({vm_nil,(f64)0}), - status(nasal_co::suspended) + status(nas_co::suspended) { for(u32 i=0;i=size) return {vm_none}; return elems[index>=0?index:index+size]; } -nasal_ref* nasal_vec::get_mem(const int index) +nas_ref* nas_vec::get_mem(const int index) { int size=elems.size(); if(index<-size || index>=size) return nullptr; return &elems[index>=0?index:index+size]; } -void nasal_vec::print() +void nas_vec::print() { if(!elems.size() || printed) { @@ -283,14 +282,14 @@ void nasal_vec::print() printed=false; } -nasal_ref nasal_hash::get_val(const std::string& key) +nas_ref nas_hash::get_val(const string& key) { if(elems.count(key)) return elems[key]; else if(elems.count("parents")) { - nasal_ref ret(vm_none); - nasal_ref val=elems["parents"]; + nas_ref ret(vm_none); + nas_ref val=elems["parents"]; if(val.type==vm_vec) for(auto& i:val.vec().elems) { @@ -302,14 +301,14 @@ nasal_ref nasal_hash::get_val(const std::string& key) } return {vm_none}; } -nasal_ref* nasal_hash::get_mem(const std::string& key) +nas_ref* nas_hash::get_mem(const string& key) { if(elems.count(key)) return &elems[key]; else if(elems.count("parents")) { - nasal_ref* addr=nullptr; - nasal_ref val=elems["parents"]; + nas_ref* addr=nullptr; + nas_ref val=elems["parents"]; if(val.type==vm_vec) for(auto& i:val.vec().elems) { @@ -321,7 +320,7 @@ nasal_ref* nasal_hash::get_mem(const std::string& key) } return nullptr; } -void nasal_hash::print() +void nas_hash::print() { if(!elems.size() || printed) { @@ -341,31 +340,31 @@ void nasal_hash::print() printed=false; } -void nasal_func::clear() +void nas_func::clear() { - dynpara=-1; + dpara=-1; local.clear(); - upvalue.clear(); + upval.clear(); keys.clear(); } -nasal_val::nasal_val(u8 val_type) +nas_val::nas_val(u8 val_type) { mark=GC_COLLECTED; type=val_type; unmut=0; switch(val_type) { - case vm_str: ptr.str=new std::string; break; - case vm_vec: ptr.vec=new nasal_vec; break; - case vm_hash: ptr.hash=new nasal_hash; break; - case vm_func: ptr.func=new nasal_func; break; - case vm_upval:ptr.upval=new nasal_upval;break; - case vm_obj: ptr.obj=new nasal_obj; break; - case vm_co: ptr.co=new nasal_co; break; + case vm_str: ptr.str=new string; break; + case vm_vec: ptr.vec=new nas_vec; break; + case vm_hash: ptr.hash=new nas_hash; break; + case vm_func: ptr.func=new nas_func; break; + case vm_upval:ptr.upval=new nas_upval;break; + case vm_obj: ptr.obj=new nas_obj; break; + case vm_co: ptr.co=new nas_co; break; } } -nasal_val::~nasal_val() +nas_val::~nas_val() { switch(type) { @@ -379,24 +378,24 @@ nasal_val::~nasal_val() } type=vm_nil; } -f64 nasal_ref::tonum() +f64 nas_ref::tonum() { return type!=vm_str?val.num:str2num(str().c_str()); } -std::string nasal_ref::tostr() +string nas_ref::tostr() { if(type==vm_str) return str(); else if(type==vm_num) { - std::string tmp=std::to_string(num()); - tmp.erase(tmp.find_last_not_of('0')+1,std::string::npos); - tmp.erase(tmp.find_last_not_of('.')+1,std::string::npos); + string tmp=std::to_string(num()); + tmp.erase(tmp.find_last_not_of('0')+1,string::npos); + tmp.erase(tmp.find_last_not_of('.')+1,string::npos); return tmp; } return ""; } -void nasal_ref::print() +void nas_ref::print() { switch(type) { @@ -411,57 +410,58 @@ void nasal_ref::print() case vm_co: std::cout<<""; break; } } -bool nasal_ref::objchk(u32 objtype) +bool nas_ref::objchk(u32 objtype) { return type==vm_obj && obj().type==objtype && obj().ptr; } -inline nasal_ref* nasal_ref::addr (){return val.addr; } -inline u32 nasal_ref::ret (){return val.ret; } -inline i64& nasal_ref::cnt (){return val.cnt; } -inline f64 nasal_ref::num (){return val.num; } -inline std::string& nasal_ref::str (){return *val.gcobj->ptr.str; } -inline nasal_vec& nasal_ref::vec (){return *val.gcobj->ptr.vec; } -inline nasal_hash& nasal_ref::hash (){return *val.gcobj->ptr.hash; } -inline nasal_func& nasal_ref::func (){return *val.gcobj->ptr.func; } -inline nasal_upval& nasal_ref::upval(){return *val.gcobj->ptr.upval;} -inline nasal_obj& nasal_ref::obj (){return *val.gcobj->ptr.obj; } -inline nasal_co& nasal_ref::co (){return *val.gcobj->ptr.co; } +inline nas_ref* nas_ref::addr (){return val.addr; } +inline u32 nas_ref::ret (){return val.ret; } +inline i64& nas_ref::cnt (){return val.cnt; } +inline f64 nas_ref::num (){return val.num; } +inline string& nas_ref::str (){return *val.gcobj->ptr.str; } +inline nas_vec& nas_ref::vec (){return *val.gcobj->ptr.vec; } +inline nas_hash& nas_ref::hash (){return *val.gcobj->ptr.hash; } +inline nas_func& nas_ref::func (){return *val.gcobj->ptr.func; } +inline nas_upval& nas_ref::upval(){return *val.gcobj->ptr.upval;} +inline nas_obj& nas_ref::obj (){return *val.gcobj->ptr.obj; } +inline nas_co& nas_ref::co (){return *val.gcobj->ptr.co; } -const nasal_ref zero={vm_num,(f64)0}; -const nasal_ref one ={vm_num,(f64)1}; -const nasal_ref nil ={vm_nil,(f64)0}; +const nas_ref zero={vm_num,(f64)0}; +const nas_ref one ={vm_num,(f64)1}; +const nas_ref nil ={vm_nil,(f64)0}; struct nasal_gc { + /* main context */ struct { - u32 pc; - nasal_ref* top; - nasal_ref* localr; - nasal_ref* memr; - nasal_ref funcr; - nasal_ref upvalr; - nasal_ref* canary; - nasal_ref* stack; - } main_ctx; + u32 pc; + nas_ref* top; + nas_ref* localr; + nas_ref* memr; + nas_ref funcr; + nas_ref upvalr; + nas_ref* canary; + nas_ref* stack; + } mctx; /* runtime context */ - u32& pc; // program counter - nasal_ref*& localr; // local scope register - nasal_ref*& memr; // used for mem_call - nasal_ref& funcr; // function register - nasal_ref& upvalr; // upvalue register - nasal_ref*& canary; // avoid stackoverflow - nasal_ref*& top; // stack top - nasal_ref* stack; // stack pointer - nasal_co* coroutine; // running coroutine - nasal_ref temp; // temporary place used in builtin/module functions + u32& pc; // program counter + nas_ref*& localr;// local scope register + nas_ref*& memr; // used for mem_call + nas_ref& funcr; // function register + nas_ref& upvalr;// upvalue register + nas_ref*& canary;// avoid stackoverflow + nas_ref*& top; // stack top + nas_ref* stack; // stack pointer + nas_co* cort; // running coroutine + nas_ref temp; // temporary place used in builtin/module functions /* constants and memory pool */ - std::vector strs; // reserved address for const vm_str - std::vector env_argv; // command line arguments - std::vector memory; // gc memory - std::queue unused[gc_tsize]; // gc free list + std::vector strs; // reserved address for const vm_str + std::vector env_argv; // command line arguments + std::vector memory; // gc memory + std::queue unused[gc_tsize]; // gc free list /* values for analysis */ u64 size[gc_tsize]; @@ -469,52 +469,52 @@ struct nasal_gc u64 allocc[gc_tsize]; nasal_gc( u32& _pc, - nasal_ref*& _localr, - nasal_ref*& _memr, - nasal_ref& _funcr, - nasal_ref& _upvalr, - nasal_ref*& _canary, - nasal_ref*& _top, - nasal_ref* _stk): + nas_ref*& _localr, + nas_ref*& _memr, + nas_ref& _funcr, + nas_ref& _upvalr, + nas_ref*& _canary, + nas_ref*& _top, + nas_ref* _stk): pc(_pc),localr(_localr),memr(_memr),funcr(_funcr),upvalr(_upvalr), - canary(_canary),top(_top),stack(_stk),coroutine(nullptr),temp(nil){} - void mark(); - void sweep(); - void init(const std::vector&,const std::vector&); - void clear(); - void info(); - nasal_ref alloc(const u8); - nasal_ref newstr(char); - nasal_ref newstr(const char*); - nasal_ref newstr(const std::string&); - void ctxchg(nasal_co&); - void ctxreserve(); + canary(_canary),top(_top),stack(_stk),cort(nullptr),temp(nil){} + void mark(); + void sweep(); + void init(const std::vector&,const std::vector&); + void clear(); + void info(); + nas_ref alloc(const u8); + nas_ref newstr(char); + nas_ref newstr(const char*); + nas_ref newstr(const string&); + void ctxchg(nas_co&); + void ctxreserve(); }; /* gc functions */ void nasal_gc::mark() { - std::queue bfs; + std::queue bfs; // scan coroutine process stack when coroutine ptr is not null // scan main process stack when coroutine ptr is null // this scan process must execute because when running coroutine, // the nasal_co related to it will not update it's context(like `top`) until the coroutine suspends or exits. - for(nasal_ref* i=stack;i<=top;++i) + for(nas_ref* i=stack;i<=top;++i) bfs.push(*i); bfs.push(funcr); bfs.push(upvalr); bfs.push(temp); - if(coroutine) // scan main process stack + if(cort) // scan main process stack { - for(nasal_ref* i=main_ctx.stack;i<=main_ctx.top;++i) + for(nas_ref* i=mctx.stack;i<=mctx.top;++i) bfs.push(*i); - bfs.push(main_ctx.funcr); - bfs.push(main_ctx.upvalr); + bfs.push(mctx.funcr); + bfs.push(mctx.upvalr); } while(!bfs.empty()) { - nasal_ref tmp=bfs.front(); + nas_ref tmp=bfs.front(); bfs.pop(); if(tmp.type<=vm_num || tmp.val.gcobj->mark) continue; tmp.val.gcobj->mark=GC_FOUND; @@ -531,7 +531,7 @@ void nasal_gc::mark() case vm_func: for(auto& i:tmp.func().local) bfs.push(i); - for(auto& i:tmp.func().upvalue) + for(auto& i:tmp.func().upval) bfs.push(i); break; case vm_upval: @@ -541,7 +541,7 @@ void nasal_gc::mark() case vm_co: bfs.push(tmp.co().funcr); bfs.push(tmp.co().upvalr); - for(nasal_ref* i=tmp.co().stack;i<=tmp.co().top;++i) + for(nas_ref* i=tmp.co().stack;i<=tmp.co().top;++i) bfs.push(*i); break; } @@ -570,7 +570,7 @@ void nasal_gc::sweep() i->mark=GC_UNCOLLECTED; } } -void nasal_gc::init(const std::vector& s,const std::vector& argv) +void nasal_gc::init(const std::vector& s,const std::vector& argv) { // initiaize function register funcr=nil; @@ -580,16 +580,16 @@ void nasal_gc::init(const std::vector& s,const std::vectorunmut=1; strs[i].str()=s[i]; } @@ -597,7 +597,7 @@ void nasal_gc::init(const std::vector& s,const std::vectorunmut=1; env_argv[i].str()=argv[i]; } @@ -626,7 +626,7 @@ void nasal_gc::info() for(u8 i=0;imark=GC_UNCOLLECTED; unused[index].pop(); return ret; } -nasal_ref nasal_gc::newstr(char c) +nas_ref nasal_gc::newstr(char c) { - nasal_ref s=alloc(vm_str); + nas_ref s=alloc(vm_str); s.str()=c; return s; } -nasal_ref nasal_gc::newstr(const char* buff) +nas_ref nasal_gc::newstr(const char* buff) { - nasal_ref s=alloc(vm_str); + nas_ref s=alloc(vm_str); s.str()=buff; return s; } -nasal_ref nasal_gc::newstr(const std::string& buff) +nas_ref nasal_gc::newstr(const string& buff) { - nasal_ref s=alloc(vm_str); + nas_ref s=alloc(vm_str); s.str()=buff; return s; } -void nasal_gc::ctxchg(nasal_co& context) +void nasal_gc::ctxchg(nas_co& ctx) { - main_ctx.pc=pc; - main_ctx.top=top; - main_ctx.localr=localr; - main_ctx.memr=memr; - main_ctx.funcr=funcr; - main_ctx.upvalr=upvalr; - main_ctx.canary=canary; - main_ctx.stack=stack; + mctx.pc=pc; + mctx.top=top; + mctx.localr=localr; + mctx.memr=memr; + mctx.funcr=funcr; + mctx.upvalr=upvalr; + mctx.canary=canary; + mctx.stack=stack; - pc=context.pc; - top=context.top; - localr=context.localr; - memr=context.memr; - funcr=context.funcr; - upvalr=context.upvalr; - canary=context.canary; - stack=context.stack; - coroutine=&context; + pc=ctx.pc; + top=ctx.top; + localr=ctx.localr; + memr=ctx.memr; + funcr=ctx.funcr; + upvalr=ctx.upvalr; + canary=ctx.canary; + stack=ctx.stack; + cort=&ctx; - coroutine->status=nasal_co::running; + cort->status=nas_co::running; } void nasal_gc::ctxreserve() { // pc=0 means this coroutine is finished - coroutine->status=pc?nasal_co::suspended:nasal_co::dead; - coroutine->pc=pc; - coroutine->localr=localr; - coroutine->memr=memr; - coroutine->funcr=funcr; - coroutine->upvalr=upvalr; - coroutine->canary=canary; - coroutine->top=top; + cort->status=pc?nas_co::suspended:nas_co::dead; + cort->pc=pc; + cort->localr=localr; + cort->memr=memr; + cort->funcr=funcr; + cort->upvalr=upvalr; + cort->canary=canary; + cort->top=top; - pc=main_ctx.pc; - localr=main_ctx.localr; - memr=main_ctx.memr; - funcr=main_ctx.funcr; - upvalr=main_ctx.upvalr; - canary=main_ctx.canary; - top=main_ctx.top; - stack=main_ctx.stack; - coroutine=nullptr; + pc=mctx.pc; + localr=mctx.localr; + memr=mctx.memr; + funcr=mctx.funcr; + upvalr=mctx.upvalr; + canary=mctx.canary; + top=mctx.top; + stack=mctx.stack; + cort=nullptr; } #endif \ No newline at end of file diff --git a/nasal_import.h b/nasal_import.h index 0bcf67a..931ee66 100644 --- a/nasal_import.h +++ b/nasal_import.h @@ -10,19 +10,19 @@ class nasal_import private: bool lib_loaded; nasal_err& nerr; - std::vector files; - std::vector envpath; + std::vector files; + std::vector envpath; bool imptchk(const nasal_ast&); - bool exist(const std::string&); + bool exist(const string&); void linker(nasal_ast&,nasal_ast&&); - std::string path(const nasal_ast&); + string path(const nasal_ast&); nasal_ast fimpt(nasal_ast&); nasal_ast libimpt(); nasal_ast load(nasal_ast&,u16); public: nasal_import(nasal_err&); - void link(nasal_parse&,const std::string&); - const std::vector& filelist() const {return files;} + void link(nasal_parse&,const string&); + const std::vector& filelist() const {return files;} }; nasal_import::nasal_import(nasal_err& e):lib_loaded(false),nerr(e){ @@ -31,12 +31,12 @@ nasal_import::nasal_import(nasal_err& e):lib_loaded(false),nerr(e){ #else char sep=':'; #endif - std::string PATH=getenv("PATH"); + string PATH=getenv("PATH"); usize last=0; usize pos=PATH.find(sep,last); - while(pos!=std::string::npos) + while(pos!=string::npos) { - std::string dirpath=PATH.substr(last,pos-last); + string dirpath=PATH.substr(last,pos-last); if(dirpath.length()) envpath.push_back(dirpath); last=pos+1; @@ -46,11 +46,11 @@ nasal_import::nasal_import(nasal_err& e):lib_loaded(false),nerr(e){ envpath.push_back(PATH.substr(last)); } -std::string nasal_import::path(const nasal_ast& node) +string nasal_import::path(const nasal_ast& node) { if(node[1].type()==ast_callf) return node[1][0].str(); - std::string fpath="."; + string fpath="."; for(usize i=1;i libpath={nalib,nastllib}; + std::vector libpath={nalib,nastllib}; for(auto& p:envpath) { libpath.push_back(p+path_nalib); @@ -156,7 +156,7 @@ nasal_ast nasal_import::libimpt() nasal_lexer lex(nerr); nasal_parse par(nerr); - std::string filename=""; + string filename=""; for(auto& i:libpath) if(access(i.c_str(),F_OK)!=-1) { @@ -165,7 +165,7 @@ nasal_ast nasal_import::libimpt() } if(!filename.length()) { - std::string paths=""; + string paths=""; for(auto& i:libpath) paths+=" "+i+"\n"; nerr.err("link","cannot find lib file in these paths:\n"+paths); @@ -204,7 +204,7 @@ nasal_ast nasal_import::load(nasal_ast& root,u16 fileindex) return new_root; } -void nasal_import::link(nasal_parse& parse,const std::string& self) +void nasal_import::link(nasal_parse& parse,const string& self) { // initializing files={self}; diff --git a/nasal_lexer.h b/nasal_lexer.h index 4e2a5b3..2db0e8e 100644 --- a/nasal_lexer.h +++ b/nasal_lexer.h @@ -96,8 +96,8 @@ struct token u32 line; u32 col; u32 type; - std::string str; - token(u32 l=0,u32 c=0,u32 t=tok_null,const std::string& s=""):str(s) + string str; + token(u32 l=0,u32 c=0,u32 t=tok_null,const string& s=""):str(s) { line=l; col=c; @@ -108,33 +108,33 @@ struct token class nasal_lexer { private: - u32 line; - u32 column; - usize ptr; - nasal_err& nerr; - std::string res; + u32 line; + u32 column; + usize ptr; + string res; + nasal_err& nerr; std::vector tokens; - u32 get_type(const std::string&); - void die(const std::string& info){nerr.err("lexer",line,column,info);} - void open(const std::string&); - std::string utf8_gen(); - std::string id_gen(); - std::string num_gen(); - std::string str_gen(); + u32 get_type(const string&); + void die(const string& info){nerr.err("lexer",line,column,info);} + void open(const string&); + string utf8_gen(); + string id_gen(); + string num_gen(); + string str_gen(); public: nasal_lexer(nasal_err& e): line(1), column(0), ptr(0), - nerr(e), - res(""){} - void scan(const std::string&); + res(""), + nerr(e){} + void scan(const string&); void print(); const std::vector& result() const {return tokens;} }; -void nasal_lexer::open(const std::string& file) +void nasal_lexer::open(const string& file) { struct stat buffer; if(stat(file.c_str(),&buffer)==0 && !S_ISREG(buffer.st_mode)) @@ -152,7 +152,7 @@ void nasal_lexer::open(const std::string& file) res=ss.str(); } -u32 nasal_lexer::get_type(const std::string& str) +u32 nasal_lexer::get_type(const string& str) { for(u32 i=0;tok_table[i].str;++i) if(str==tok_table[i].str) @@ -160,12 +160,12 @@ u32 nasal_lexer::get_type(const std::string& str) return tok_null; } -std::string nasal_lexer::utf8_gen() +string nasal_lexer::utf8_gen() { - std::string str=""; + string str=""; while(ptr [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*) - std::string str=""; + string str=""; while(ptr argname; + std::unordered_map argname; for(auto& tmp:node.child()) { - std::string name; + string name; switch(tmp.type()) { case ast_dynamic: diff --git a/nasal_vm.h b/nasal_vm.h index 0428610..8c339da 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -5,122 +5,121 @@ class nasal_vm { protected: /* registers and constants of nasal_vm */ - u32 pc; // program counter - nasal_ref* localr; // local scope register - nasal_ref* memr; // used for mem_call - nasal_ref funcr; // function register - nasal_ref upvalr; // upvalue register - nasal_ref* canary; // avoid stackoverflow - nasal_ref* top; // stack top - const f64* num_table;// const numbers, ref from nasal_codegen - const std::string* str_table;// const symbols, ref from nasal_codegen - std::vector imm; // immediate number + u32 pc; // program counter + nas_ref* localr; // local scope register + nas_ref* memr; // used for mem_call + nas_ref funcr; // function register + nas_ref upvalr; // upvalue register + nas_ref* canary; // avoid stackoverflow + nas_ref* top; // stack top + const f64* num_table;// const numbers, ref from nasal_codegen + const string* str_table;// const symbols, ref from nasal_codegen + std::vector imm; // immediate number /* garbage collector */ - nasal_gc gc; + nasal_gc gc; /* main stack */ - nasal_ref stack[STACK_DEPTH]; + nas_ref stack[STACK_DEPTH]; /* values used for debugger */ - const std::string* files; // ref from nasal_import - const opcode* bytecode; // ref from nasal_codegen + const string* files; // ref from nasal_import + const opcode* bytecode; // ref from nasal_codegen void init( - const std::vector&, + const std::vector&, const std::vector&, const std::vector&, - const std::vector&, - const std::vector&); + const std::vector&, + const std::vector&); /* debug functions */ bool detail_info; - void valinfo(nasal_ref&); + void valinfo(nas_ref&); void bytecodeinfo(const char*,const u32); void traceback(); void stackinfo(const u32); - void register_info(); - void global_state(); - void local_state(); - void upval_state(); + void reginfo(); + void gstate(); + void lstate(); + void ustate(); void detail(); - void opcallsort(const u64*); - void die(const std::string&); + void die(const string&); /* vm calculation functions*/ - bool condition(nasal_ref); + bool condition(nas_ref); /* vm operands */ - void opr_intg(); - void opr_intl(); - void opr_loadg(); - void opr_loadl(); - void opr_loadu(); - void opr_pnum(); - void opr_pnil(); - void opr_pstr(); - void opr_newv(); - void opr_newh(); - void opr_newf(); - void opr_happ(); - void opr_para(); - void opr_deft(); - void opr_dyn(); - void opr_unot(); - void opr_usub(); - void opr_add(); - void opr_sub(); - void opr_mul(); - void opr_div(); - void opr_lnk(); - void opr_addc(); - void opr_subc(); - void opr_mulc(); - void opr_divc(); - void opr_lnkc(); - void opr_addeq(); - void opr_subeq(); - void opr_muleq(); - void opr_diveq(); - void opr_lnkeq(); - void opr_addeqc(); - void opr_subeqc(); - void opr_muleqc(); - void opr_diveqc(); - void opr_lnkeqc(); - void opr_meq(); - void opr_eq(); - void opr_neq(); - void opr_less(); - void opr_leq(); - void opr_grt(); - void opr_geq(); - void opr_lessc(); - void opr_leqc(); - void opr_grtc(); - void opr_geqc(); - void opr_pop(); - void opr_jmp(); - void opr_jt(); - void opr_jf(); - void opr_cnt(); - void opr_findex(); - void opr_feach(); - void opr_callg(); - void opr_calll(); - void opr_upval(); - void opr_callv(); - void opr_callvi(); - void opr_callh(); - void opr_callfv(); - void opr_callfh(); - void opr_callb(); - void opr_slcbeg(); - void opr_slcend(); - void opr_slc(); - void opr_slc2(); - void opr_mcallg(); - void opr_mcalll(); - void opr_mupval(); - void opr_mcallv(); - void opr_mcallh(); - void opr_ret(); + void o_intg(); + void o_intl(); + void o_loadg(); + void o_loadl(); + void o_loadu(); + void o_pnum(); + void o_pnil(); + void o_pstr(); + void o_newv(); + void o_newh(); + void o_newf(); + void o_happ(); + void o_para(); + void o_deft(); + void o_dyn(); + void o_unot(); + void o_usub(); + void o_add(); + void o_sub(); + void o_mul(); + void o_div(); + void o_lnk(); + void o_addc(); + void o_subc(); + void o_mulc(); + void o_divc(); + void o_lnkc(); + void o_addeq(); + void o_subeq(); + void o_muleq(); + void o_diveq(); + void o_lnkeq(); + void o_addeqc(); + void o_subeqc(); + void o_muleqc(); + void o_diveqc(); + void o_lnkeqc(); + void o_meq(); + void o_eq(); + void o_neq(); + void o_less(); + void o_leq(); + void o_grt(); + void o_geq(); + void o_lessc(); + void o_leqc(); + void o_grtc(); + void o_geqc(); + void o_pop(); + void o_jmp(); + void o_jt(); + void o_jf(); + void o_cnt(); + void o_findex(); + void o_feach(); + void o_callg(); + void o_calll(); + void o_upval(); + void o_callv(); + void o_callvi(); + void o_callh(); + void o_callfv(); + void o_callfh(); + void o_callb(); + void o_slcbeg(); + void o_slcend(); + void o_slc(); + void o_slc2(); + void o_mcallg(); + void o_mcalll(); + void o_mupval(); + void o_mcallv(); + void o_mcallh(); + void o_ret(); public: nasal_vm():pc(0),localr(nullptr),memr(nullptr),funcr(nil), upvalr(nil),canary(nullptr),top(stack), @@ -130,17 +129,16 @@ public: void run( const nasal_codegen&, const nasal_import&, - const std::vector&, - const bool, + const std::vector&, const bool); }; void nasal_vm::init( - const std::vector& strs, + const std::vector& strs, const std::vector& nums, const std::vector& code, - const std::vector& filenames, - const std::vector& argv) + const std::vector& filenames, + const std::vector& argv) { gc.init(strs,argv); num_table=nums.data(); @@ -159,9 +157,9 @@ void nasal_vm::init( for(u32 i=0;i ret; - for(nasal_ref* i=bottom;i<=t;++i) + for(nas_ref* i=bottom;i<=t;++i) if(i->type==vm_ret) ret.push(i->ret()); // push pc to ret stack to store the position program crashed @@ -236,9 +234,9 @@ void nasal_vm::traceback() void nasal_vm::stackinfo(const u32 limit=10) { /* bytecode[0] is op_intg, the .num is the global size */ - u32 gsize=gc.stack==stack?bytecode[0].num:0; - nasal_ref* t=top; - nasal_ref* bottom=gc.stack+gsize; + u32 gsize=gc.stack==stack?bytecode[0].num:0; + nas_ref* t=top; + nas_ref* bottom=gc.stack+gsize; std::cout<<"vm stack(0x"<, limit "< upval["< op; - std::vector opcall; - u64 total=0; - for(u32 i=0;ib.second;} - ); - std::clog<<"\noperands call info"; - for(auto& i:opcall) - { - u64 rate=i.second*100/total; - if(rate) - std::clog<<"\n "<>16)&0xffff] + funcr.func().upval[(imm[pc]>>16)&0xffff] .upval()[imm[pc]&0xffff]=(top--)[0]; } -inline void nasal_vm::opr_pnum() +inline void nasal_vm::o_pnum() { (++top)[0]={vm_num,num_table[imm[pc]]}; } -inline void nasal_vm::opr_pnil() +inline void nasal_vm::o_pnil() { (++top)[0]=nil; } -inline void nasal_vm::opr_pstr() +inline void nasal_vm::o_pstr() { (++top)[0]=gc.strs[imm[pc]]; } -inline void nasal_vm::opr_newv() +inline void nasal_vm::o_newv() { - nasal_ref newv=gc.alloc(vm_vec); + nas_ref newv=gc.alloc(vm_vec); auto& vec=newv.vec().elems; vec.resize(imm[pc]); // use top-=imm[pc]-1 here will cause error if imm[pc] is 0 @@ -409,55 +379,55 @@ inline void nasal_vm::opr_newv() vec[i]=top[i]; top[0]=newv; } -inline void nasal_vm::opr_newh() +inline void nasal_vm::o_newh() { (++top)[0]=gc.alloc(vm_hash); } -inline void nasal_vm::opr_newf() +inline void nasal_vm::o_newf() { (++top)[0]=gc.alloc(vm_func); - nasal_func& func=top[0].func(); + nas_func& func=top[0].func(); func.entry=imm[pc]; func.psize=1; /* this means you create a new function in local scope */ if(localr) { - func.upvalue=funcr.func().upvalue; - nasal_ref upval=(upvalr.type==vm_nil)?gc.alloc(vm_upval):upvalr; + func.upval=funcr.func().upval; + nas_ref upval=(upvalr.type==vm_nil)?gc.alloc(vm_upval):upvalr; upval.upval().size=funcr.func().lsize; upval.upval().stk=localr; - func.upvalue.push_back(upval); + func.upval.push_back(upval); upvalr=upval; } } -inline void nasal_vm::opr_happ() +inline void nasal_vm::o_happ() { top[-1].hash().elems[str_table[imm[pc]]]=top[0]; --top; } -inline void nasal_vm::opr_para() +inline void nasal_vm::o_para() { - nasal_func& func=top[0].func(); + nas_func& func=top[0].func(); // func->size has 1 place reserved for "me" func.keys[imm[pc]]=func.psize; func.local[func.psize++]={vm_none}; } -inline void nasal_vm::opr_deft() +inline void nasal_vm::o_deft() { - nasal_ref val=top[0]; - nasal_func& func=(--top)[0].func(); + nas_ref val=top[0]; + nas_func& func=(--top)[0].func(); // func->size has 1 place reserved for "me" func.keys[imm[pc]]=func.psize; func.local[func.psize++]=val; } -inline void nasal_vm::opr_dyn() +inline void nasal_vm::o_dyn() { - top[0].func().dynpara=imm[pc]; + top[0].func().dpara=imm[pc]; } -inline void nasal_vm::opr_unot() +inline void nasal_vm::o_unot() { - nasal_ref val=top[0]; + nas_ref val=top[0]; switch(val.type) { case vm_nil:top[0]=one;break; @@ -473,7 +443,7 @@ inline void nasal_vm::opr_unot() default:die("unot: incorrect value type");break; } } -inline void nasal_vm::opr_usub() +inline void nasal_vm::o_usub() { top[0]={vm_num,-top[0].tonum()}; } @@ -482,11 +452,11 @@ inline void nasal_vm::opr_usub() top[-1]={vm_num,top[-1].tonum() type top[0].tonum()};\ --top; -inline void nasal_vm::opr_add(){op_calc(+);} -inline void nasal_vm::opr_sub(){op_calc(-);} -inline void nasal_vm::opr_mul(){op_calc(*);} -inline void nasal_vm::opr_div(){op_calc(/);} -inline void nasal_vm::opr_lnk() +inline void nasal_vm::o_add(){op_calc(+);} +inline void nasal_vm::o_sub(){op_calc(-);} +inline void nasal_vm::o_mul(){op_calc(*);} +inline void nasal_vm::o_div(){op_calc(/);} +inline void nasal_vm::o_lnk() { top[-1]=gc.newstr(top[-1].tostr()+top[0].tostr()); --top; @@ -495,11 +465,11 @@ inline void nasal_vm::opr_lnk() #define op_calc_const(type)\ top[0]={vm_num,top[0].tonum() type num_table[imm[pc]]}; -inline void nasal_vm::opr_addc(){op_calc_const(+);} -inline void nasal_vm::opr_subc(){op_calc_const(-);} -inline void nasal_vm::opr_mulc(){op_calc_const(*);} -inline void nasal_vm::opr_divc(){op_calc_const(/);} -inline void nasal_vm::opr_lnkc() +inline void nasal_vm::o_addc(){op_calc_const(+);} +inline void nasal_vm::o_subc(){op_calc_const(-);} +inline void nasal_vm::o_mulc(){op_calc_const(*);} +inline void nasal_vm::o_divc(){op_calc_const(/);} +inline void nasal_vm::o_lnkc() { top[0]=gc.newstr(top[0].tostr()+str_table[imm[pc]]); } @@ -509,11 +479,11 @@ inline void nasal_vm::opr_lnkc() memr=nullptr;\ top-=imm[pc]+1; -inline void nasal_vm::opr_addeq(){op_calc_eq(+);} -inline void nasal_vm::opr_subeq(){op_calc_eq(-);} -inline void nasal_vm::opr_muleq(){op_calc_eq(*);} -inline void nasal_vm::opr_diveq(){op_calc_eq(/);} -inline void nasal_vm::opr_lnkeq() +inline void nasal_vm::o_addeq(){op_calc_eq(+);} +inline void nasal_vm::o_subeq(){op_calc_eq(-);} +inline void nasal_vm::o_muleq(){op_calc_eq(*);} +inline void nasal_vm::o_diveq(){op_calc_eq(/);} +inline void nasal_vm::o_lnkeq() { top[-1]=memr[0]=gc.newstr(memr[0].tostr()+top[-1].tostr()); memr=nullptr; @@ -525,18 +495,18 @@ inline void nasal_vm::opr_lnkeq() memr=nullptr;\ top-=(imm[pc]>>31); -inline void nasal_vm::opr_addeqc(){op_calc_eq_const(+);} -inline void nasal_vm::opr_subeqc(){op_calc_eq_const(-);} -inline void nasal_vm::opr_muleqc(){op_calc_eq_const(*);} -inline void nasal_vm::opr_diveqc(){op_calc_eq_const(/);} -inline void nasal_vm::opr_lnkeqc() +inline void nasal_vm::o_addeqc(){op_calc_eq_const(+);} +inline void nasal_vm::o_subeqc(){op_calc_eq_const(-);} +inline void nasal_vm::o_muleqc(){op_calc_eq_const(*);} +inline void nasal_vm::o_diveqc(){op_calc_eq_const(/);} +inline void nasal_vm::o_lnkeqc() { top[0]=memr[0]=gc.newstr(memr[0].tostr()+str_table[imm[pc]&0x7fffffff]); memr=nullptr; top-=(imm[pc]>>31); } -inline void nasal_vm::opr_meq() +inline void nasal_vm::o_meq() { // pop old memr[0] and replace it // the reason why we should get memr and push the old value on stack @@ -547,10 +517,10 @@ inline void nasal_vm::opr_meq() memr=nullptr; top-=imm[pc]+1; } -inline void nasal_vm::opr_eq() +inline void nasal_vm::o_eq() { - nasal_ref val2=top[0]; - nasal_ref val1=(--top)[0]; + nas_ref val2=top[0]; + nas_ref val1=(--top)[0]; if(val1.type==vm_nil && val2.type==vm_nil) top[0]=one; else if(val1.type==vm_str && val2.type==vm_str) @@ -561,10 +531,10 @@ inline void nasal_vm::opr_eq() else top[0]=(val1==val2)?one:zero; } -inline void nasal_vm::opr_neq() +inline void nasal_vm::o_neq() { - nasal_ref val2=top[0]; - nasal_ref val1=(--top)[0]; + nas_ref val2=top[0]; + nas_ref val1=(--top)[0]; if(val1.type==vm_nil && val2.type==vm_nil) top[0]=zero; else if(val1.type==vm_str && val2.type==vm_str) @@ -580,45 +550,45 @@ inline void nasal_vm::opr_neq() --top;\ top[0]=(top[0].tonum() type top[1].tonum())?one:zero; -inline void nasal_vm::opr_less(){op_cmp(<);} -inline void nasal_vm::opr_leq(){op_cmp(<=);} -inline void nasal_vm::opr_grt(){op_cmp(>);} -inline void nasal_vm::opr_geq(){op_cmp(>=);} +inline void nasal_vm::o_less(){op_cmp(<);} +inline void nasal_vm::o_leq(){op_cmp(<=);} +inline void nasal_vm::o_grt(){op_cmp(>);} +inline void nasal_vm::o_geq(){op_cmp(>=);} #define op_cmp_const(type)\ top[0]=(top[0].tonum() type num_table[imm[pc]])?one:zero; -inline void nasal_vm::opr_lessc(){op_cmp_const(<);} -inline void nasal_vm::opr_leqc(){op_cmp_const(<=);} -inline void nasal_vm::opr_grtc(){op_cmp_const(>);} -inline void nasal_vm::opr_geqc(){op_cmp_const(>=);} +inline void nasal_vm::o_lessc(){op_cmp_const(<);} +inline void nasal_vm::o_leqc(){op_cmp_const(<=);} +inline void nasal_vm::o_grtc(){op_cmp_const(>);} +inline void nasal_vm::o_geqc(){op_cmp_const(>=);} -inline void nasal_vm::opr_pop() +inline void nasal_vm::o_pop() { --top; } -inline void nasal_vm::opr_jmp() +inline void nasal_vm::o_jmp() { pc=imm[pc]-1; } -inline void nasal_vm::opr_jt() +inline void nasal_vm::o_jt() { if(condition(top[0])) pc=imm[pc]-1; } -inline void nasal_vm::opr_jf() +inline void nasal_vm::o_jf() { if(!condition(top[0])) pc=imm[pc]-1; --top; } -inline void nasal_vm::opr_cnt() +inline void nasal_vm::o_cnt() { if(top[0].type!=vm_vec) die("cnt: must use vector in forindex/foreach"); (++top)[0]={vm_cnt,(i64)-1}; } -inline void nasal_vm::opr_findex() +inline void nasal_vm::o_findex() { if((usize)(++top[0].cnt())>=top[-1].vec().size()) { @@ -628,9 +598,9 @@ inline void nasal_vm::opr_findex() top[1]={vm_num,(f64)top[0].cnt()}; ++top; } -inline void nasal_vm::opr_feach() +inline void nasal_vm::o_feach() { - std::vector& ref=top[-1].vec().elems; + std::vector& ref=top[-1].vec().elems; if((usize)(++top[0].cnt())>=ref.size()) { pc=imm[pc]-1; @@ -639,23 +609,23 @@ inline void nasal_vm::opr_feach() top[1]=ref[top[0].cnt()]; ++top; } -inline void nasal_vm::opr_callg() +inline void nasal_vm::o_callg() { (++top)[0]=stack[imm[pc]]; } -inline void nasal_vm::opr_calll() +inline void nasal_vm::o_calll() { (++top)[0]=localr[imm[pc]]; } -inline void nasal_vm::opr_upval() +inline void nasal_vm::o_upval() { - (++top)[0]=funcr.func().upvalue[(imm[pc]>>16)&0xffff] + (++top)[0]=funcr.func().upval[(imm[pc]>>16)&0xffff] .upval()[imm[pc]&0xffff]; } -inline void nasal_vm::opr_callv() +inline void nasal_vm::o_callv() { - nasal_ref val=top[0]; - nasal_ref vec=(--top)[0]; + nas_ref val=top[0]; + nas_ref vec=(--top)[0]; if(vec.type==vm_vec) { top[0]=vec.vec().get_val(val.tonum()); @@ -674,7 +644,7 @@ inline void nasal_vm::opr_callv() } else if(vec.type==vm_str) { - std::string& str=vec.str(); + string& str=vec.str(); int num=val.tonum(); int len=str.length(); if(num<-len || num>=len) @@ -684,9 +654,9 @@ inline void nasal_vm::opr_callv() else die("callv: must call a vector/hash/string"); } -inline void nasal_vm::opr_callvi() +inline void nasal_vm::o_callvi() { - nasal_ref val=top[0]; + nas_ref val=top[0]; if(val.type!=vm_vec) die("callvi: must use a vector"); @@ -695,9 +665,9 @@ inline void nasal_vm::opr_callvi() if(top[0].type==vm_none) die("callvi: index out of range:"+std::to_string(imm[pc])); } -inline void nasal_vm::opr_callh() +inline void nasal_vm::o_callh() { - nasal_ref val=top[0]; + nas_ref val=top[0]; if(val.type!=vm_hash) die("callh: must call a hash"); @@ -708,15 +678,15 @@ inline void nasal_vm::opr_callh() if(top[0].type==vm_func) top[0].func().local[0]=val;// 'me' } -inline void nasal_vm::opr_callfv() +inline void nasal_vm::o_callfv() { u32 argc=imm[pc]; // arguments counter - nasal_ref* local=top-argc+1; // arguments begin address + nas_ref* local=top-argc+1; // arguments begin address if(local[-1].type!=vm_func) die("callfv: must call a function"); auto& func=local[-1].func(); - nasal_ref tmp=local[-1]; + nas_ref tmp=local[-1]; local[-1]=funcr; funcr=tmp; // top-argc+lsize(local) +1(old pc) +1(old localr) +1(old upvalr) @@ -727,9 +697,9 @@ inline void nasal_vm::opr_callfv() if(argc=0)// load dynamic arguments + if(func.dpara>=0)// load dynamic arguments { dynamic=gc.alloc(vm_vec); for(u32 i=psize;i=0) + if(func.dpara>=0) local[psize+1]=dynamic; top[0]=upvalr; @@ -756,30 +726,30 @@ inline void nasal_vm::opr_callfv() localr=local; upvalr=nil; } -inline void nasal_vm::opr_callfh() +inline void nasal_vm::o_callfh() { auto& hash=top[0].hash().elems; if(top[-1].type!=vm_func) die("callfh: must call a function"); auto& func=top[-1].func(); - nasal_ref tmp=top[-1]; + nas_ref tmp=top[-1]; top[-1]=funcr; funcr=tmp; // 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) + if(func.dpara>=0) die("callfh: special call cannot use dynamic argument"); - nasal_ref* local=top; + nas_ref* local=top; top+=func.lsize; for(u32 i=0;i& ref=top[-1].vec().elems; - std::vector& aim=top[0].vec().elems; + nas_ref val2=(top--)[0]; + nas_ref val1=(top--)[0]; + std::vector& ref=top[-1].vec().elems; + std::vector& aim=top[0].vec().elems; u8 type1=val1.type,type2=val2.type; int num1=val1.tonum(); @@ -860,31 +830,31 @@ inline void nasal_vm::opr_slc2() for(int i=num1;i<=num2;++i) aim.push_back(i>=0?ref[i]:ref[i+size]); } -inline void nasal_vm::opr_mcallg() +inline void nasal_vm::o_mcallg() { memr=stack+imm[pc]; (++top)[0]=memr[0]; // push value in this memory space on stack // to avoid being garbage collected } -inline void nasal_vm::opr_mcalll() +inline void nasal_vm::o_mcalll() { memr=localr+imm[pc]; (++top)[0]=memr[0]; // push value in this memory space on stack // to avoid being garbage collected } -inline void nasal_vm::opr_mupval() +inline void nasal_vm::o_mupval() { - memr=&(funcr.func().upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]); + memr=&(funcr.func().upval[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]); (++top)[0]=memr[0]; // push value in this memory space on stack // to avoid being garbage collected } -inline void nasal_vm::opr_mcallv() +inline void nasal_vm::o_mcallv() { - nasal_ref val=top[0]; // index - nasal_ref vec=(--top)[0]; // mcall vector, reserved on stack to avoid gc + nas_ref val=top[0]; // index + nas_ref vec=(--top)[0]; // mcall vector, reserved on stack to avoid gc if(vec.type==vm_vec) { memr=vec.vec().get_mem(val.tonum()); @@ -895,8 +865,8 @@ inline void nasal_vm::opr_mcallv() { if(val.type!=vm_str) die("mcallv: must use string as the key"); - nasal_hash& ref=vec.hash(); - std::string& str=val.str(); + nas_hash& ref=vec.hash(); + string& str=val.str(); memr=ref.get_mem(str); if(!memr) { @@ -907,13 +877,13 @@ inline void nasal_vm::opr_mcallv() else die("mcallv: cannot get memory space in other types"); } -inline void nasal_vm::opr_mcallh() +inline void nasal_vm::o_mcallh() { - nasal_ref hash=top[0]; // mcall hash, reserved on stack to avoid gc + nas_ref hash=top[0]; // mcall hash, reserved on stack to avoid gc if(hash.type!=vm_hash) die("mcallh: must call a hash"); - nasal_hash& ref=hash.hash(); - const std::string& str=str_table[imm[pc]]; + nas_hash& ref=hash.hash(); + const string& str=str_table[imm[pc]]; memr=ref.get_mem(str); if(!memr) // create a new key { @@ -921,7 +891,7 @@ inline void nasal_vm::opr_mcallh() memr=ref.get_mem(str); } } -inline void nasal_vm::opr_ret() +inline void nasal_vm::o_ret() { /* +-----------------+ * | return value | <- top[0] @@ -938,10 +908,10 @@ inline void nasal_vm::opr_ret() * | old funcr | <- old function stored in funcr * +-----------------+ */ - nasal_ref ret =top[0]; - nasal_ref* local=localr; - nasal_ref func =funcr; - nasal_ref up =upvalr; + nas_ref ret =top[0]; + nas_ref* local=localr; + nas_ref func =funcr; + nas_ref up =upvalr; pc =top[-1].ret(); localr=top[-2].addr(); @@ -968,13 +938,11 @@ inline void nasal_vm::opr_ret() void nasal_vm::run( const nasal_codegen& gen, const nasal_import& linker, - const std::vector& argv, - const bool opcnt, + const std::vector& argv, const bool detail) { detail_info=detail; init(gen.strs(),gen.nums(),gen.codes(),linker.filelist(),argv); - u64 count[op_ret+1]={0}; #ifndef _MSC_VER const void* oprs[]= { @@ -1010,54 +978,53 @@ void nasal_vm::run( typedef void (nasal_vm::*nafunc)(); const nafunc oprs[]= { - nullptr, &nasal_vm::opr_intg, - &nasal_vm::opr_intl, &nasal_vm::opr_loadg, - &nasal_vm::opr_loadl, &nasal_vm::opr_loadu, - &nasal_vm::opr_pnum, &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_deft, &nasal_vm::opr_dyn, - &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_addc, - &nasal_vm::opr_subc, &nasal_vm::opr_mulc, - &nasal_vm::opr_divc, &nasal_vm::opr_lnkc, - &nasal_vm::opr_addeq, &nasal_vm::opr_subeq, - &nasal_vm::opr_muleq, &nasal_vm::opr_diveq, - &nasal_vm::opr_lnkeq, &nasal_vm::opr_addeqc, - &nasal_vm::opr_subeqc, &nasal_vm::opr_muleqc, - &nasal_vm::opr_diveqc, &nasal_vm::opr_lnkeqc, - &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_lessc, - &nasal_vm::opr_leqc, &nasal_vm::opr_grtc, - &nasal_vm::opr_geqc, &nasal_vm::opr_pop, - &nasal_vm::opr_jmp, &nasal_vm::opr_jt, - &nasal_vm::opr_jf, &nasal_vm::opr_cnt, - &nasal_vm::opr_findex, &nasal_vm::opr_feach, - &nasal_vm::opr_callg, &nasal_vm::opr_calll, - &nasal_vm::opr_upval, &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_slcbeg, - &nasal_vm::opr_slcend, &nasal_vm::opr_slc, - &nasal_vm::opr_slc2, &nasal_vm::opr_mcallg, - &nasal_vm::opr_mcalll, &nasal_vm::opr_mupval, - &nasal_vm::opr_mcallv, &nasal_vm::opr_mcallh, - &nasal_vm::opr_ret + nullptr, &nasal_vm::o_intg, + &nasal_vm::o_intl, &nasal_vm::o_loadg, + &nasal_vm::o_loadl, &nasal_vm::o_loadu, + &nasal_vm::o_pnum, &nasal_vm::o_pnil, + &nasal_vm::o_pstr, &nasal_vm::o_newv, + &nasal_vm::o_newh, &nasal_vm::o_newf, + &nasal_vm::o_happ, &nasal_vm::o_para, + &nasal_vm::o_deft, &nasal_vm::o_dyn, + &nasal_vm::o_unot, &nasal_vm::o_usub, + &nasal_vm::o_add, &nasal_vm::o_sub, + &nasal_vm::o_mul, &nasal_vm::o_div, + &nasal_vm::o_lnk, &nasal_vm::o_addc, + &nasal_vm::o_subc, &nasal_vm::o_mulc, + &nasal_vm::o_divc, &nasal_vm::o_lnkc, + &nasal_vm::o_addeq, &nasal_vm::o_subeq, + &nasal_vm::o_muleq, &nasal_vm::o_diveq, + &nasal_vm::o_lnkeq, &nasal_vm::o_addeqc, + &nasal_vm::o_subeqc, &nasal_vm::o_muleqc, + &nasal_vm::o_diveqc, &nasal_vm::o_lnkeqc, + &nasal_vm::o_meq, &nasal_vm::o_eq, + &nasal_vm::o_neq, &nasal_vm::o_less, + &nasal_vm::o_leq, &nasal_vm::o_grt, + &nasal_vm::o_geq, &nasal_vm::o_lessc, + &nasal_vm::o_leqc, &nasal_vm::o_grtc, + &nasal_vm::o_geqc, &nasal_vm::o_pop, + &nasal_vm::o_jmp, &nasal_vm::o_jt, + &nasal_vm::o_jf, &nasal_vm::o_cnt, + &nasal_vm::o_findex, &nasal_vm::o_feach, + &nasal_vm::o_callg, &nasal_vm::o_calll, + &nasal_vm::o_upval, &nasal_vm::o_callv, + &nasal_vm::o_callvi, &nasal_vm::o_callh, + &nasal_vm::o_callfv, &nasal_vm::o_callfh, + &nasal_vm::o_callb, &nasal_vm::o_slcbeg, + &nasal_vm::o_slcend, &nasal_vm::o_slc, + &nasal_vm::o_slc2, &nasal_vm::o_mcallg, + &nasal_vm::o_mcalll, &nasal_vm::o_mupval, + &nasal_vm::o_mcallv, &nasal_vm::o_mcallh, + &nasal_vm::o_ret }; - std::vector code; + std::vector code; for(auto& i:gen.codes()) { - code.push_back(i.op); + code.push_back(oprs[i.op]); imm.push_back(i.num); } - while(oprs[code[pc]]){ - ++count[code[pc]]; - (this->*oprs[code[pc]])(); + while(code[pc]){ + (this->*code[pc])(); if(top>=canary) break; ++pc; @@ -1067,8 +1034,6 @@ void nasal_vm::run( vmexit: if(top>=canary) die("stack overflow"); - if(opcnt) - opcallsort(count); if(detail) gc.info(); gc.clear(); @@ -1077,90 +1042,89 @@ vmexit: #ifndef _MSC_VER // may cause stackoverflow -#define exec_operand(op,num) {\ +#define exec_check(op) {\ op();\ - ++count[num];\ if(top