From 3fd1b25f7990b5cb0d207ccff9594943f8ce1d6c Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Fri, 21 Oct 2022 01:29:29 +0800 Subject: [PATCH] :fire: change class name. nasal_lexer -> lexer nasal_parse -> parse nasal_codegen -> codegen nasal_vm -> vm nasal_gc -> gc nasal_dbg -> debugger nasal_import -> linker nas_ref -> var --- README.md | 18 +- doc/README_zh.md | 18 +- doc/dev.md | 120 +++++------ doc/dev_zh.md | 116 +++++----- main.cpp | 19 +- module/fib.cpp | 8 +- module/keyboard.cpp | 6 +- module/makefile | 3 +- module/nasocket.cpp | 46 ++-- nasal.h | 2 +- nasal_builtin.h | 514 ++++++++++++++++++++++---------------------- nasal_codegen.h | 104 ++++----- nasal_dbg.h | 112 +++++----- nasal_err.h | 14 +- nasal_gc.h | 248 +++++++++++---------- nasal_import.h | 50 ++--- nasal_lexer.h | 42 ++-- nasal_parse.h | 288 +++++++++++++------------ nasal_vm.h | 410 +++++++++++++++++------------------ 19 files changed, 1070 insertions(+), 1068 deletions(-) diff --git a/README.md b/README.md index 8d5b1da..66ad847 100644 --- a/README.md +++ b/README.md @@ -182,7 +182,7 @@ var f=func(args...){ } ``` -__`upval`__ is used to store upvalues, used in __`nasal_vm`__ to make sure closure runs correctly. +__`upval`__ is used to store upvalues, used in __`vm`__ to make sure closure runs correctly. __`obj`__ is used to store other complex `C/C++` data types. This type is created by native-function of nasal. If want to define a new data type, see how to add native-functions by editing code. @@ -490,11 +490,11 @@ nas_native(builtin_print); Then complete this function using C++: ```C++ -nas_ref builtin_print(nas_ref* local,nasal_gc& gc) +var builtin_print(var* local,nasal_gc& gc) { // find value with index begin from 1 // because local[0] is reserved for value 'me' - nas_ref vec=local[1]; + var vec=local[1]; // main process // also check number of arguments and type here // if get an error,use nas_err @@ -524,13 +524,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++ -nas_ref builtin_keys(nas_ref* local,nasal_gc& gc) +var builtin_keys(var* local,nasal_gc& gc) { - nas_ref hash=local[1]; + var hash=local[1]; if(hash.type!=vm_hash) return nas_err("keys","\"hash\" must be hash"); // use gc.temp to store the gc-managed-value, to avoid being sweeped - nas_ref res=gc.temp=gc.alloc(vm_vec); + var 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)); @@ -545,7 +545,7 @@ After that, register the built-in function's name(in nasal) and the function's p struct func { const char* name; - nas_ref (*func)(nas_ref*,nasal_gc&); + var (*func)(var*,nasal_gc&); } builtin[]= { {"__print",builtin_print}, @@ -617,10 +617,10 @@ double fibonaci(double x){ } // remember to use extern "C", // so you could search the symbol quickly -extern "C" nas_ref fib(std::vector& args,nasal_gc& gc){ +extern "C" var 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 - nas_ref num=args[0]; + var num=args[0]; // if you want your function safer, try this // nas_err will print the error info on screen // and return vm_null for runtime to interrupt diff --git a/doc/README_zh.md b/doc/README_zh.md index ef04c00..06dfd45 100644 --- a/doc/README_zh.md +++ b/doc/README_zh.md @@ -168,7 +168,7 @@ var f=func(args...){ } ``` -__`upval`__ 是存储闭包数据的特殊类型, 在 __`nasal_vm`__ 中使用,以确保闭包功能正常。 +__`upval`__ 是存储闭包数据的特殊类型, 在 __`vm`__ 中使用,以确保闭包功能正常。 __`obj`__ 是用来存储`C/C++`的一些复杂数据结构。这种类型的数据由内置函数生成。如果想为nasal添加新的数据结构, 可以看下文如何通过修改本项目来添加内置函数。 @@ -469,11 +469,11 @@ nas_native(builtin_print); 然后用C++完成这个函数的函数体: ```C++ -nas_ref builtin_print(nas_ref* local,nasal_gc& gc) +var builtin_print(var* local,nasal_gc& gc) { // 局部变量的下标其实是从1开始的 // 因为local[0]是保留给'me'的空间 - nas_ref vec=local[1]; + var vec=local[1]; // 主要部分 // 一些必要的类型检查和输入合法性检测也要在这里写出 // 如果检测到问题,用builtin_err函数来返回vm_null @@ -504,13 +504,13 @@ nas_ref builtin_print(nas_ref* local,nasal_gc& gc) 可以使用`gc::temp`来暂时存储一个会被返回的需要gc管理的变量,这样可以防止内部所有的申请错误触发垃圾回收。如下所示: ```C++ -nas_ref builtin_keys(nas_ref* local,nasal_gc& gc) +var builtin_keys(var* local,nasal_gc& gc) { - nas_ref hash=local[1]; + var hash=local[1]; if(hash.type!=vm_hash) return nas_err("keys","\"hash\" must be hash"); // 使用gc.temp来存储gc管理的变量,防止错误的回收 - nas_ref res=gc.temp=gc.alloc(vm_vec); + var 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)); @@ -525,7 +525,7 @@ nas_ref builtin_keys(nas_ref* local,nasal_gc& gc) struct func { const char* name; - nas_ref (*func)(nas_ref*,nasal_gc&); + var (*func)(var*,nasal_gc&); } builtin[]= { {"__print",builtin_print}, @@ -592,9 +592,9 @@ double fibonaci(double x){ } // 记得用extern "C" // 这样找符号会更加快速便捷,不要在意编译时的warning -extern "C" nas_ref fib(std::vector& args,nasal_gc& gc){ +extern "C" var fib(std::vector& args,nasal_gc& gc){ // 传参会被送到一个vm_vec类型中送过来,而不是上文中那种指针直接指向局部作用域 - nas_ref num=args[0]; + var num=args[0]; // 如果你想让这个函数有更强的稳定性,那么一定要进行合法性检查 // builtin_err会输出错误信息并返回错误类型让虚拟机终止执行 if(num.type!=vm_num) diff --git a/doc/dev.md b/doc/dev.md index 19fb01b..8acb0d9 100644 --- a/doc/dev.md +++ b/doc/dev.md @@ -337,8 +337,8 @@ As you could see from the bytecode above, And because of the new structure of `mcall`, `addr_stack`, a stack used to store the memory address, -is deleted from `nasal_vm`, -and now `nasal_vm` use `nas_val** mem_addr` to store the memory address. +is deleted from `vm`, +and now `vm` use `nas_val** mem_addr` to store the memory address. This will not cause fatal errors because the memory address is used __immediately__ after getting it. ### version 7.0 vm (last update 2021/10/8) @@ -347,7 +347,7 @@ This will not cause fatal errors because the memory address is used __immediatel Instruction dispatch is changed from call-threading to computed-goto(with inline function). After changing the way of instruction dispatch, -there is a great improvement in nasal_vm. +there is a great improvement in `vm`. Now vm can run test/bigloop and test/pi in 0.2s! And vm runs test/fib in 0.8s on linux. You could see the time use data below, @@ -550,37 +550,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(nas_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(var) | +| ... | ++----------------------+ <- 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(nas_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(var) | +| ... | ++----------------------+ <- local pointer stored in localr +| old funcr(vm_func) | <- old function stored in funcr ++----------------------+ ``` Then we call `resume`, this function will change stack. @@ -591,9 +591,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. @@ -601,40 +601,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(nas_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(var) | +| ... | ++----------------------+ <- 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(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 -+--------------------------+ ++----------------------+(main stack) +| return_value(var) | ++----------------------+ +| old pc(vm_ret) | ++----------------------+ +| old localr(vm_addr) | ++----------------------+ +| old upvalr(vm_upval) | ++----------------------+ +| local scope(var) | +| ... | ++----------------------+ <- 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/dev_zh.md b/doc/dev_zh.md index eb5b7ce..df00bad 100644 --- a/doc/dev_zh.md +++ b/doc/dev_zh.md @@ -305,7 +305,7 @@ m(0)._=m(1)._=10; 从上面这些字节码可以看出,`mcall`/`mcallv`/`mcallh`指令的使用频率比以前减小了一些,而`call`/`callv`/`callh`/`callfv`/`callfh`则相反。 -并且因为新的数据结构,`mcall`指令以及`addr_stack`,一个曾用来存储指针的栈,从`nasal_vm`中被移除。现在`nasal_vm`使用`nas_val** mem_addr`来暂存获取的内存地址。这不会导致严重的问题,因为内存空间是 __获取即使用__ 的。 +并且因为新的数据结构,`mcall`指令以及`addr_stack`,一个曾用来存储指针的栈,从`vm`中被移除。现在`vm`使用`nas_val** mem_addr`来暂存获取的内存地址。这不会导致严重的问题,因为内存空间是 __获取即使用__ 的。 ### version 7.0 vm (last update 2021/10/8) @@ -491,37 +491,37 @@ __接下来我们解释这个协程的运行原理:__ 当`op_callb`被执行时,栈帧如下所示: ```C++ -+--------------------------+(主操作数栈) -| 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 -+--------------------------+ ++----------------------+(主操作数栈) +| old pc(vm_ret) | <- top[0] ++----------------------+ +| old localr(vm_addr) | <- top[-1] ++----------------------+ +| old upvalr(vm_upval) | <- top[-2] ++----------------------+ +| local scope(var) | +| ... | ++----------------------+ <- 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(nas_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(var) | +| ... | ++----------------------+ <- local pointer stored in localr +| old funcr(vm_func) | <- old function stored in funcr ++----------------------+ ``` 接着我们调用`resume`,这个函数会替换操作数栈。我们会看到,协程的操作数栈上已经保存了一些数据,但是我们首次进入协程执行时,这个操作数栈的栈顶将会是`vm_ret`,并且返回的`pc`值是`0`。 @@ -529,47 +529,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(nas_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(var) | +| ... | ++----------------------+ <- local pointer stored in localr +| old funcr(vm_func) | <- old function stored in funcr ++----------------------+ ``` 当`builtin_coyield`执行完毕之后,栈又切换到了主操作数栈上,这时可以看到返回的`local[1]`实际上被`op_callb`放在了这里的栈顶: ```C++ -+--------------------------+(主操作数栈) -| 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 -+--------------------------+ ++----------------------+(主操作数栈) +| return_value(var) | ++----------------------+ +| old pc(vm_ret) | ++----------------------+ +| old localr(vm_addr) | ++----------------------+ +| old upvalr(vm_upval) | ++----------------------+ +| local scope(var) | +| ... | ++----------------------+ <- 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 a15eced..bea7ad7 100644 --- a/main.cpp +++ b/main.cpp @@ -10,6 +10,7 @@ #include "nasal_codegen.h" #include "nasal_vm.h" #include "nasal_dbg.h" + #include const u32 VM_TOKEN =0x01; @@ -82,13 +83,13 @@ void err() void execute(const string& file,const std::vector& argv,const u32 cmd) { // front end use the same error module - nasal_err nerr; - nasal_lexer lex(nerr); - nasal_parse parse(nerr); - nasal_import ld(nerr); - nasal_codegen gen(nerr); + error err; + lexer lex(err); + parse parse(err); + linker ld(err); + codegen gen(err); // back end - nasal_vm vm; + vm rt; // lexer scans file to get tokens lex.scan(file); @@ -112,16 +113,16 @@ void execute(const string& file,const std::vector& argv,const u32 cmd) // run if(cmd&VM_DEBUG) - nasal_dbg(nerr).run(gen,ld,argv); + debugger(err).run(gen,ld,argv); else if(cmd&VM_TIME) { auto start=std::chrono::high_resolution_clock::now(); - vm.run(gen,ld,argv,cmd&VM_DETAIL); + rt.run(gen,ld,argv,cmd&VM_DETAIL); 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,ld,argv,cmd&VM_DETAIL); + rt.run(gen,ld,argv,cmd&VM_DETAIL); } i32 main(i32 argc,const char* argv[]) diff --git a/module/fib.cpp b/module/fib.cpp index d9ffc30..bac813d 100644 --- a/module/fib.cpp +++ b/module/fib.cpp @@ -6,20 +6,20 @@ double fibonaci(double x){ return x; return fibonaci(x-1)+fibonaci(x-2); } -extern "C" nas_ref fib(std::vector& args,nasal_gc& gc){ +extern "C" var fib(std::vector& args,gc& ngc){ std::cout<<"[mod] this is the first test module of nasal\n"; if(!args.size()) return nas_err("fib","lack arguments"); - nas_ref num=args[0]; + var num=args[0]; if(num.type!=vm_num) return nas_err("extern_fib","\"num\" must be number"); return {vm_num,fibonaci(num.tonum())}; } -extern "C" nas_ref quick_fib(std::vector& args,nasal_gc& gc){ +extern "C" var quick_fib(std::vector& args,gc& ngc){ std::cout<<"[mod] this is the first test module of nasal\n"; if(!args.size()) return nas_err("fib","lack arguments"); - nas_ref num=args[0]; + var num=args[0]; if(num.type!=vm_num) return nas_err("extern_quick_fib","\"num\" must be number"); if(num.num()<2) diff --git a/module/keyboard.cpp b/module/keyboard.cpp index 669d1d3..dc70729 100644 --- a/module/keyboard.cpp +++ b/module/keyboard.cpp @@ -71,13 +71,13 @@ public: }; noecho_input this_window; -extern "C" nas_ref nas_getch(std::vector& args,nasal_gc& gc){ +extern "C" var nas_getch(std::vector& args,gc& ngc){ return {vm_num,(double)this_window.noecho_getch()}; } -extern "C" nas_ref nas_kbhit(std::vector& args,nasal_gc& gc){ +extern "C" var nas_kbhit(std::vector& args,gc& ngc){ return {vm_num,(double)this_window.noecho_kbhit()}; } -extern "C" nas_ref nas_noblock(std::vector& args,nasal_gc& gc){ +extern "C" var nas_noblock(std::vector& args,gc& ngc){ if(this_window.noecho_kbhit()) return {vm_num,(double)this_window.noecho_getch()}; return nil; diff --git a/module/makefile b/module/makefile index 234a28d..5a74b84 100644 --- a/module/makefile +++ b/module/makefile @@ -30,7 +30,8 @@ libnasock.dll: nasocket.cpp del nasocket.o clean: - rm *.so *.dll *.dylib + -@ rm *.so *.dll *.dylib + @ echo "done" all: libfib.so libkey.so libnasock.so @ echo "build done" mingw-all: libfib.dll libkey.dll libnasock.dll diff --git a/module/nasocket.cpp b/module/nasocket.cpp index 602b325..5b12768 100644 --- a/module/nasocket.cpp +++ b/module/nasocket.cpp @@ -25,14 +25,14 @@ static WSAmanager win; #include #endif -extern "C" nas_ref nas_socket(std::vector& args,nasal_gc& gc){ +extern "C" var nas_socket(std::vector& args,gc& ngc){ if(args[0].type!=vm_num || args[1].type!=vm_num || args[2].type!=vm_num) return nas_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" nas_ref nas_closesocket(std::vector& args,nasal_gc& gc){ +extern "C" var nas_closesocket(std::vector& args,gc& ngc){ if(args[0].type!=vm_num) return nas_err("closesocket","\"\" should be number"); #ifdef _WIN32 @@ -42,7 +42,7 @@ extern "C" nas_ref nas_closesocket(std::vector& args,nasal_gc& gc){ #endif } -extern "C" nas_ref nas_shutdown(std::vector& args,nasal_gc& gc){ +extern "C" var nas_shutdown(std::vector& args,gc& ngc){ if(args[0].type!=vm_num) return nas_err("shutdown","\"sd\" must be a number"); if(args[1].type!=vm_num) @@ -50,7 +50,7 @@ extern "C" nas_ref nas_shutdown(std::vector& args,nasal_gc& gc){ return {vm_num,(double)shutdown(args[0].num(),args[1].num())}; } -extern "C" nas_ref nas_bind(std::vector& args,nasal_gc& gc){ +extern "C" var nas_bind(std::vector& args,gc& ngc){ if(args[0].type!=vm_num) return nas_err("bind","\"sd\" muse be a number"); if(args[1].type!=vm_str) @@ -65,7 +65,7 @@ extern "C" nas_ref nas_bind(std::vector& args,nasal_gc& gc){ return {vm_num,(double)bind(args[0].num(),(sockaddr*)&server,sizeof(server))}; } -extern "C" nas_ref nas_listen(std::vector& args,nasal_gc& gc){ +extern "C" var nas_listen(std::vector& args,gc& ngc){ if(args[0].type!=vm_num) return nas_err("listen","\"sd\" must be a number"); if(args[1].type!=vm_num) @@ -73,7 +73,7 @@ extern "C" nas_ref nas_listen(std::vector& args,nasal_gc& gc){ return{vm_num,(double)listen(args[0].num(),args[1].num())}; } -extern "C" nas_ref nas_connect(std::vector& args,nasal_gc& gc){ +extern "C" var nas_connect(std::vector& args,gc& ngc){ if(args[0].type!=vm_num) return nas_err("connect","\"sd\" must be a number"); if(args[1].type!=vm_str) @@ -89,7 +89,7 @@ extern "C" nas_ref nas_connect(std::vector& args,nasal_gc& gc){ return {vm_num,(double)connect(args[0].num(),(sockaddr*)&addr,sizeof(sockaddr_in))}; } -extern "C" nas_ref nas_accept(std::vector& args,nasal_gc& gc){ +extern "C" var nas_accept(std::vector& args,gc& ngc){ if(args[0].type!=vm_num) return nas_err("accept","\"sd\" must be a number"); sockaddr_in client; @@ -99,15 +99,15 @@ extern "C" nas_ref nas_accept(std::vector& args,nasal_gc& gc){ #else int client_sd=accept(args[0].num(),(sockaddr*)&client,(socklen_t*)&socklen); #endif - nas_ref res=gc.temp=gc.alloc(vm_hash); + var res=ngc.temp=ngc.alloc(vm_hash); auto& hash=res.hash().elems; hash["sd"]={vm_num,(double)client_sd}; - hash["ip"]=gc.newstr(inet_ntoa(client.sin_addr)); - gc.temp=nil; + hash["ip"]=ngc.newstr(inet_ntoa(client.sin_addr)); + ngc.temp=nil; return res; } -extern "C" nas_ref nas_send(std::vector& args,nasal_gc& gc){ +extern "C" var nas_send(std::vector& args,gc& ngc){ if(args[0].type!=vm_num) return nas_err("send","\"sd\" must be a number"); if(args[1].type!=vm_str) @@ -117,7 +117,7 @@ extern "C" nas_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" nas_ref nas_sendto(std::vector& args,nasal_gc& gc){ +extern "C" var nas_sendto(std::vector& args,gc& ngc){ if(args[0].type!=vm_num) return nas_err("sendto","\"sd\" must be a number"); if(args[1].type!=vm_str) @@ -137,7 +137,7 @@ extern "C" nas_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" nas_ref nas_recv(std::vector& args,nasal_gc& gc){ +extern "C" var nas_recv(std::vector& args,gc& ngc){ if(args[0].type!=vm_num) return nas_err("recv","\"sd\" must be a number"); if(args[1].type!=vm_num) @@ -146,17 +146,17 @@ extern "C" nas_ref nas_recv(std::vector& args,nasal_gc& gc){ return nas_err("recv","\"len\" out of range"); if(args[2].type!=vm_num) return nas_err("recv","\"flags\" muse be a number"); - nas_ref res=gc.temp=gc.alloc(vm_hash); + var res=ngc.temp=ngc.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())}; - hash["str"]=gc.newstr(buf); + hash["str"]=ngc.newstr(buf); delete[] buf; - gc.temp=nil; + ngc.temp=nil; return res; } -extern "C" nas_ref nas_recvfrom(std::vector& args,nasal_gc& gc){ +extern "C" var nas_recvfrom(std::vector& args,gc& ngc){ if(args[0].type!=vm_num) return nas_err("recvfrom","\"sd\" must be a number"); if(args[1].type!=vm_num) @@ -167,7 +167,7 @@ extern "C" nas_ref nas_recvfrom(std::vector& args,nasal_gc& gc){ return nas_err("recvfrom","\"flags\" muse be a number"); sockaddr_in addr; int socklen=sizeof(sockaddr_in); - nas_ref res=gc.temp=gc.alloc(vm_hash); + var res=ngc.temp=ngc.alloc(vm_hash); auto& hash=res.hash().elems; char* buf=new char[(int)args[1].num()+1]; #ifdef _WIN32 @@ -176,13 +176,13 @@ extern "C" nas_ref nas_recvfrom(std::vector& args,nasal_gc& gc){ hash["size"]={vm_num,(double)recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,(socklen_t*)&socklen)}; #endif buf[(int)hash["size"].num()]=0; - hash["str"]=gc.newstr(buf); + hash["str"]=ngc.newstr(buf); delete[] buf; - hash["fromip"]=gc.newstr(inet_ntoa(addr.sin_addr)); - gc.temp=nil; + hash["fromip"]=ngc.newstr(inet_ntoa(addr.sin_addr)); + ngc.temp=nil; return res; } -extern "C" nas_ref nas_errno(std::vector& args,nasal_gc& gc){ - return gc.newstr(strerror(errno)); +extern "C" var nas_errno(std::vector& args,gc& ngc){ + return ngc.newstr(strerror(errno)); } \ No newline at end of file diff --git a/nasal.h b/nasal.h index 706731e..b4e800a 100644 --- a/nasal.h +++ b/nasal.h @@ -150,6 +150,6 @@ string rawstr(const string& str,const usize maxlen=0) return ret; } -#include "nasal_gc.h" // declarations of nas_ref and nasal_gc +#include "nasal_gc.h" // declarations of var and nasal_gc #endif diff --git a/nasal_builtin.h b/nasal_builtin.h index a0adae7..8bd4b43 100644 --- a/nasal_builtin.h +++ b/nasal_builtin.h @@ -31,34 +31,34 @@ #define environ (*_NSGetEnviron()) #endif -nas_ref builtin_print(nas_ref* local,nasal_gc& gc) +var builtin_print(var* local,gc& ngc) { for(auto& i:local[1].vec().elems) std::cout<1 || !end.str().length()) std::cin>>ret.str(); else std::getline(std::cin,ret.str(),end.str()[0]); return ret; } -nas_ref builtin_fin(nas_ref* local,nasal_gc& gc) +var builtin_fin(var* local,gc& ngc) { - nas_ref val=local[1]; + var val=local[1]; if(val.type!=vm_str) return nas_err("io::fin","\"filename\" must be string"); std::ifstream fin(val.str(),std::ios::binary); std::stringstream rd; if(!fin.fail()) rd<& vec=res.vec().elems; + var res=ngc.temp=ngc.alloc(vm_vec); + std::vector& vec=res.vec().elems; if(!deli.length()) { for(auto i:s) - vec.push_back(gc.newstr(i)); - gc.temp=nil; + vec.push_back(ngc.newstr(i)); + ngc.temp=nil; return res; } usize last=0,pos=s.find(deli,0); while(pos!=string::npos) { if(pos>last) - vec.push_back(gc.newstr(s.substr(last,pos-last))); + vec.push_back(ngc.newstr(s.substr(last,pos-last))); last=pos+deli.length(); pos=s.find(deli,last); } if(last!=s.length()) - vec.push_back(gc.newstr(s.substr(last))); - gc.temp=nil; + vec.push_back(ngc.newstr(s.substr(last))); + ngc.temp=nil; return res; } -nas_ref builtin_rand(nas_ref* local,nasal_gc& gc) +var builtin_rand(var* local,gc& ngc) { - nas_ref val=local[1]; + var val=local[1]; if(val.type!=vm_num && val.type!=vm_nil) return nas_err("rand","\"seed\" must be nil or number"); if(val.type==vm_num) @@ -167,30 +167,30 @@ nas_ref builtin_rand(nas_ref* local,nasal_gc& gc) num=(num+rand())*(1.0/(RAND_MAX+1.0)); return {vm_num,num}; } -nas_ref builtin_id(nas_ref* local,nasal_gc& gc) +var builtin_id(var* local,gc& ngc) { - nas_ref val=local[1]; + var val=local[1]; std::stringstream ss; ss<<"0"; if(val.type>vm_num) ss<<"x"<=str.str().length() || begin+length>str.str().length()) return nas_err("susbtr","index out of range"); - return gc.newstr(str.str().substr(begin,length)); + return ngc.newstr(str.str().substr(begin,length)); } -nas_ref builtin_streq(nas_ref* local,nasal_gc& gc) +var builtin_streq(var* local,gc& ngc) { - nas_ref a=local[1]; - nas_ref b=local[2]; + var a=local[1]; + var b=local[2]; return {vm_num,f64((a.type!=vm_str || b.type!=vm_str)?0:(a.str()==b.str()))}; } -nas_ref builtin_left(nas_ref* local,nasal_gc& gc) +var builtin_left(var* local,gc& ngc) { - nas_ref str=local[1]; - nas_ref len=local[2]; + var str=local[1]; + var len=local[2]; if(str.type!=vm_str) return nas_err("left","\"string\" must be string"); if(len.type!=vm_num) return nas_err("left","\"length\" must be number"); if(len.num()<0) - return gc.newstr(""); - return gc.newstr(str.str().substr(0,len.num())); + return ngc.newstr(""); + return ngc.newstr(str.str().substr(0,len.num())); } -nas_ref builtin_right(nas_ref* local,nasal_gc& gc) +var builtin_right(var* local,gc& ngc) { - nas_ref str=local[1]; - nas_ref len=local[2]; + var str=local[1]; + var len=local[2]; if(str.type!=vm_str) return nas_err("right","\"string\" must be string"); if(len.type!=vm_num) @@ -448,17 +448,17 @@ nas_ref builtin_right(nas_ref* local,nasal_gc& gc) length=srclen; if(length<0) length=0; - return gc.newstr(str.str().substr(srclen-length,srclen)); + return ngc.newstr(str.str().substr(srclen-length,srclen)); } -nas_ref builtin_cmp(nas_ref* local,nasal_gc& gc) +var builtin_cmp(var* local,gc& ngc) { - nas_ref a=local[1]; - nas_ref b=local[2]; + var a=local[1]; + var b=local[2]; if(a.type!=vm_str || b.type!=vm_str) return nas_err("cmp","\"a\" and \"b\" must be string"); return {vm_num,(f64)strcmp(a.str().c_str(),b.str().c_str())}; } -nas_ref builtin_chr(nas_ref* local,nasal_gc& gc) +var builtin_chr(var* local,gc& ngc) { const char* extend[]={ "€"," ","‚","ƒ","„","…","†","‡", @@ -480,23 +480,23 @@ nas_ref builtin_chr(nas_ref* local,nasal_gc& gc) }; i32 num=local[1].num(); if(0<=num && num<128) - return gc.newstr((char)num); + return ngc.newstr((char)num); else if(128<=num && num<256) - return gc.newstr(extend[num-128]); - return gc.newstr(" "); + return ngc.newstr(extend[num-128]); + return ngc.newstr(" "); } -nas_ref builtin_values(nas_ref* local,nasal_gc& gc) +var builtin_values(var* local,gc& ngc) { - nas_ref hash=local[1]; + var hash=local[1]; if(hash.type!=vm_hash) return nas_err("values","\"hash\" must be hash"); - nas_ref vec=gc.alloc(vm_vec); + var vec=ngc.alloc(vm_vec); auto& v=vec.vec().elems; for(auto& i:hash.hash().elems) v.push_back(i.second); return vec; } -nas_ref builtin_exists(nas_ref* local,nasal_gc& gc) +var builtin_exists(var* local,gc& ngc) { if(local[1].type!=vm_str) return zero; @@ -506,10 +506,10 @@ void obj_file_dtor(void* ptr) { fclose((FILE*)ptr); } -nas_ref builtin_open(nas_ref* local,nasal_gc& gc) +var builtin_open(var* local,gc& ngc) { - nas_ref name=local[1]; - nas_ref mode=local[2]; + var name=local[1]; + var mode=local[2]; if(name.type!=vm_str) return nas_err("open","\"filename\" must be string"); if(mode.type!=vm_str) @@ -517,24 +517,24 @@ nas_ref builtin_open(nas_ref* local,nasal_gc& gc) FILE* res=fopen(name.str().c_str(),mode.str().c_str()); if(!res) return nas_err("open","failed to open file <"+name.str()+">"); - nas_ref ret=gc.alloc(vm_obj); + var ret=ngc.alloc(vm_obj); ret.obj().set(nas_obj::file,res,obj_file_dtor); return ret; } -nas_ref builtin_close(nas_ref* local,nasal_gc& gc) +var builtin_close(var* local,gc& ngc) { - nas_ref fd=local[1]; + var fd=local[1]; if(!fd.objchk(nas_obj::file)) return nas_err("close","not a valid filehandle"); fclose((FILE*)fd.obj().ptr); fd.obj().ptr=nullptr; return nil; } -nas_ref builtin_read(nas_ref* local,nasal_gc& gc) +var builtin_read(var* local,gc& ngc) { - nas_ref fd=local[1]; - nas_ref buf=local[2]; - nas_ref len=local[3]; + var fd=local[1]; + var buf=local[2]; + var len=local[3]; if(!fd.objchk(nas_obj::file)) return nas_err("read","not a valid filehandle"); if(buf.type!=vm_str || buf.val.gcobj->unmut) @@ -552,38 +552,38 @@ nas_ref builtin_read(nas_ref* local,nasal_gc& gc) delete []buff; return {vm_num,res}; } -nas_ref builtin_write(nas_ref* local,nasal_gc& gc) +var builtin_write(var* local,gc& ngc) { - nas_ref fd=local[1]; - nas_ref str=local[2]; + var fd=local[1]; + var str=local[2]; if(!fd.objchk(nas_obj::file)) return nas_err("write","not a valid filehandle"); if(str.type!=vm_str) return nas_err("write","\"str\" must be string"); return {vm_num,(f64)fwrite(str.str().c_str(),1,str.str().length(),(FILE*)fd.obj().ptr)}; } -nas_ref builtin_seek(nas_ref* local,nasal_gc& gc) +var builtin_seek(var* local,gc& ngc) { - nas_ref fd=local[1]; - nas_ref pos=local[2]; - nas_ref whence=local[3]; + var fd=local[1]; + var pos=local[2]; + var whence=local[3]; if(!fd.objchk(nas_obj::file)) return nas_err("seek","not a valid filehandle"); return {vm_num,(f64)fseek((FILE*)fd.obj().ptr,pos.num(),whence.num())}; } -nas_ref builtin_tell(nas_ref* local,nasal_gc& gc) +var builtin_tell(var* local,gc& ngc) { - nas_ref fd=local[1]; + var fd=local[1]; if(!fd.objchk(nas_obj::file)) return nas_err("tell","not a valid filehandle"); return {vm_num,(f64)ftell((FILE*)fd.obj().ptr)}; } -nas_ref builtin_readln(nas_ref* local,nasal_gc& gc) +var builtin_readln(var* local,gc& ngc) { - nas_ref fd=local[1]; + var fd=local[1]; if(!fd.objchk(nas_obj::file)) return nas_err("readln","not a valid filehandle"); - nas_ref str=gc.alloc(vm_str); + var str=ngc.alloc(vm_str); char c; while((c=fgetc((FILE*)fd.obj().ptr))!=EOF) { @@ -597,15 +597,15 @@ nas_ref builtin_readln(nas_ref* local,nasal_gc& gc) return str; return nil; } -nas_ref builtin_stat(nas_ref* local,nasal_gc& gc) +var builtin_stat(var* local,gc& ngc) { - nas_ref name=local[1]; + var name=local[1]; if(name.type!=vm_str) return nas_err("stat","\"filename\" must be string"); struct stat buf; if(stat(name.str().c_str(),&buf)<0) return nas_err("stat","failed to open file <"+name.str()+">"); - nas_ref ret=gc.alloc(vm_vec); + var ret=ngc.alloc(vm_vec); ret.vec().elems={ {vm_num,(f64)buf.st_dev}, {vm_num,(f64)buf.st_ino}, @@ -621,21 +621,21 @@ nas_ref builtin_stat(nas_ref* local,nasal_gc& gc) }; return ret; } -nas_ref builtin_eof(nas_ref* local,nasal_gc& gc) +var builtin_eof(var* local,gc& ngc) { - nas_ref fd=local[1]; + var fd=local[1]; if(!fd.objchk(nas_obj::file)) return nas_err("readln","not a valid filehandle"); return {vm_num,(f64)feof((FILE*)fd.obj().ptr)}; } -nas_ref builtin_fld(nas_ref* local,nasal_gc& gc) +var builtin_fld(var* local,gc& ngc) { // bits.fld(s,0,3); // if s stores 10100010(162) // will get 101(5) - nas_ref str=local[1]; - nas_ref startbit=local[2]; - nas_ref length=local[3]; + var str=local[1]; + var startbit=local[2]; + var length=local[3]; if(str.type!=vm_str || str.val.gcobj->unmut) return nas_err("fld","\"str\" must be mutable string"); if(startbit.type!=vm_num || length.type!=vm_num) @@ -651,15 +651,15 @@ nas_ref builtin_fld(nas_ref* local,nasal_gc& gc) res|=1<<(bit+len-i-1); return {vm_num,(f64)res}; } -nas_ref builtin_sfld(nas_ref* local,nasal_gc& gc) +var builtin_sfld(var* local,gc& ngc) { // bits.sfld(s,0,3); // if s stores 10100010(162) // will get 101(5) then this will be signed extended to // 11111101(-3) - nas_ref str=local[1]; - nas_ref startbit=local[2]; - nas_ref length=local[3]; + var str=local[1]; + var startbit=local[2]; + var length=local[3]; if(str.type!=vm_str || str.val.gcobj->unmut) return nas_err("sfld","\"str\" must be mutable string"); if(startbit.type!=vm_num || length.type!=vm_num) @@ -677,16 +677,16 @@ nas_ref builtin_sfld(nas_ref* local,nasal_gc& gc) res|=~((1<unmut) return nas_err("setfld","\"str\" must be mutable string"); if(startbit.type!=vm_num || length.type!=vm_num || value.type!=vm_num) @@ -706,29 +706,29 @@ nas_ref builtin_setfld(nas_ref* local,nasal_gc& gc) } return nil; } -nas_ref builtin_buf(nas_ref* local,nasal_gc& gc) +var builtin_buf(var* local,gc& ngc) { - nas_ref length=local[1]; + var length=local[1]; if(length.type!=vm_num || length.num()<=0) return nas_err("buf","\"len\" must be number greater than 0"); - nas_ref str=gc.alloc(vm_str); + var str=ngc.alloc(vm_str); auto& s=str.str(); s.resize(length.num(),'\0'); return str; } -nas_ref builtin_sleep(nas_ref* local,nasal_gc& gc) +var builtin_sleep(var* local,gc& ngc) { - nas_ref val=local[1]; + var val=local[1]; if(val.type!=vm_num) return nas_err("sleep","\"duration\" must be number"); std::this_thread::sleep_for(std::chrono::microseconds(i64(val.num()*1e6))); return nil; } -nas_ref builtin_pipe(nas_ref* local,nasal_gc& gc) +var builtin_pipe(var* local,gc& ngc) { #ifndef _WIN32 i32 fd[2]; - nas_ref res=gc.alloc(vm_vec); + var res=ngc.alloc(vm_vec); if(pipe(fd)==-1) return nas_err("pipe","failed to create pipe"); res.vec().elems.push_back({vm_num,(f64)fd[0]}); @@ -737,7 +737,7 @@ nas_ref builtin_pipe(nas_ref* local,nasal_gc& gc) #endif return nas_err("pipe","not supported for windows"); } -nas_ref builtin_fork(nas_ref* local,nasal_gc& gc) +var builtin_fork(var* local,gc& ngc) { #ifndef _WIN32 f64 res=fork(); @@ -747,16 +747,16 @@ nas_ref builtin_fork(nas_ref* local,nasal_gc& gc) #endif return nas_err("fork","not supported for windows"); } -nas_ref builtin_waitpid(nas_ref* local,nasal_gc& gc) +var builtin_waitpid(var* local,gc& ngc) { - nas_ref pid=local[1]; - nas_ref nohang=local[2]; + var pid=local[1]; + var nohang=local[2]; if(pid.type!=vm_num || nohang.type!=vm_num) return nas_err("waitpid","pid and nohang must be number"); #ifndef _WIN32 i32 ret_pid,status; ret_pid=waitpid(pid.num(),&status,nohang.num()==0?0:WNOHANG); - nas_ref vec=gc.alloc(vm_vec); + var vec=ngc.alloc(vm_vec); vec.vec().elems.push_back({vm_num,(f64)ret_pid}); vec.vec().elems.push_back({vm_num,(f64)status}); return vec; @@ -771,9 +771,9 @@ void obj_dir_dtor(void* ptr) FindClose(ptr); #endif } -nas_ref builtin_opendir(nas_ref* local,nasal_gc& gc) +var builtin_opendir(var* local,gc& ngc) { - nas_ref path=local[1]; + var path=local[1]; if(path.type!=vm_str) return nas_err("opendir","\"path\" must be string"); #ifdef _MSC_VER @@ -787,28 +787,28 @@ nas_ref builtin_opendir(nas_ref* local,nasal_gc& gc) if(!p) return nas_err("opendir","cannot open dir <"+path.str()+">"); #endif - nas_ref ret=gc.alloc(vm_obj); + var ret=ngc.alloc(vm_obj); ret.obj().set(nas_obj::dir,p,obj_dir_dtor); return ret; } -nas_ref builtin_readdir(nas_ref* local,nasal_gc& gc) +var builtin_readdir(var* local,gc& ngc) { - nas_ref handle=local[1]; + var handle=local[1]; if(!handle.objchk(nas_obj::dir)) return nas_err("readdir","not a valid dir handle"); #ifdef _MSC_VER WIN32_FIND_DATAA data; if(!FindNextFileA(handle.obj().ptr,&data)) return nil; - return gc.newstr(data.cFileName); + return ngc.newstr(data.cFileName); #else dirent* p=readdir((DIR*)handle.obj().ptr); - return p?gc.newstr(p->d_name):nil; + return p?ngc.newstr(p->d_name):nil; #endif } -nas_ref builtin_closedir(nas_ref* local,nasal_gc& gc) +var builtin_closedir(var* local,gc& ngc) { - nas_ref handle=local[1]; + var handle=local[1]; if(!handle.objchk(nas_obj::dir)) return nas_err("closedir","not a valid dir handle"); #ifndef _MSC_VER @@ -819,36 +819,36 @@ nas_ref builtin_closedir(nas_ref* local,nasal_gc& gc) handle.obj().ptr=nullptr; return nil; } -nas_ref builtin_chdir(nas_ref* local,nasal_gc& gc) +var builtin_chdir(var* local,gc& ngc) { - nas_ref path=local[1]; + var path=local[1]; if(path.type!=vm_str) return {vm_num,(f64)-1}; return {vm_num,(f64)chdir(path.str().c_str())}; } -nas_ref builtin_environ(nas_ref* local,nasal_gc& gc) +var builtin_environ(var* local,gc& ngc) { - nas_ref res=gc.temp=gc.alloc(vm_vec); + var res=ngc.temp=ngc.alloc(vm_vec); auto& vec=res.vec().elems; for(char** env=environ;*env;++env) - vec.push_back(gc.newstr(*env)); - gc.temp=nil; + vec.push_back(ngc.newstr(*env)); + ngc.temp=nil; return res; } -nas_ref builtin_getcwd(nas_ref* local,nasal_gc& gc) +var builtin_getcwd(var* local,gc& ngc) { char buf[1024]; if(!getcwd(buf,sizeof(buf))) return nil; - return gc.newstr(buf); + return ngc.newstr(buf); } -nas_ref builtin_getenv(nas_ref* local,nasal_gc& gc) +var builtin_getenv(var* local,gc& ngc) { - nas_ref envvar=local[1]; + var envvar=local[1]; if(envvar.type!=vm_str) return nas_err("getenv","\"envvar\" must be string"); char* res=getenv(envvar.str().c_str()); - return res?gc.newstr(res):nil; + return res?ngc.newstr(res):nil; } void obj_dylib_dtor(void* ptr) { @@ -858,9 +858,9 @@ void obj_dylib_dtor(void* ptr) dlclose(ptr); #endif } -nas_ref builtin_dlopen(nas_ref* local,nasal_gc& gc) +var builtin_dlopen(var* local,gc& ngc) { - nas_ref dlname=local[1]; + var dlname=local[1]; if(dlname.type!=vm_str) return nas_err("dlopen","\"libname\" must be string"); #ifdef _WIN32 @@ -876,14 +876,14 @@ nas_ref builtin_dlopen(nas_ref* local,nasal_gc& gc) #endif if(!ptr) return nas_err("dlopen","cannot open dynamic lib <"+dlname.str()+">"); - nas_ref ret=gc.alloc(vm_obj); + var ret=ngc.alloc(vm_obj); ret.obj().set(nas_obj::dylib,ptr,obj_dylib_dtor); return ret; } -nas_ref builtin_dlsym(nas_ref* local,nasal_gc& gc) +var builtin_dlsym(var* local,gc& ngc) { - nas_ref lib=local[1]; - nas_ref sym=local[2]; + var lib=local[1]; + var sym=local[2]; if(!lib.objchk(nas_obj::dylib)) return nas_err("dlsym","\"lib\" is not a valid dynamic lib"); if(sym.type!=vm_str) @@ -895,13 +895,13 @@ nas_ref builtin_dlsym(nas_ref* local,nasal_gc& gc) #endif if(!func) return nas_err("dlsym","cannot find symbol \""+sym.str()+"\""); - nas_ref ret=gc.alloc(vm_obj); + var ret=ngc.alloc(vm_obj); ret.obj().set(nas_obj::faddr,func); return ret; } -nas_ref builtin_dlclose(nas_ref* local,nasal_gc& gc) +var builtin_dlclose(var* local,gc& ngc) { - nas_ref libptr=local[1]; + var libptr=local[1]; if(!libptr.objchk(nas_obj::dylib)) return nas_err("dlclose","\"lib\" is not a valid dynamic lib"); #ifdef _WIN32 @@ -912,27 +912,27 @@ nas_ref builtin_dlclose(nas_ref* local,nasal_gc& gc) libptr.obj().ptr=nullptr; return nil; } -nas_ref builtin_dlcall(nas_ref* local,nasal_gc& gc) +var builtin_dlcall(var* local,gc& ngc) { - nas_ref fp=local[1]; - nas_ref args=local[2]; + var fp=local[1]; + var args=local[2]; if(!fp.objchk(nas_obj::faddr)) return nas_err("dlcall","\"funcptr\" is not a valid function pointer"); - typedef nas_ref (*externs)(std::vector&,nasal_gc&); + typedef var (*externs)(std::vector&,gc&); externs func=(externs)fp.obj().ptr; - return func(args.vec().elems,gc); + return func(args.vec().elems,ngc); } -nas_ref builtin_platform(nas_ref* local,nasal_gc& gc) +var builtin_platform(var* local,gc& ngc) { #if defined _WIN32 || defined _WIN64 - return gc.newstr("windows"); + return ngc.newstr("windows"); #elif defined __linux__ - return gc.newstr("linux"); + return ngc.newstr("linux"); #elif defined __APPLE__ - return gc.newstr("macOS"); + return ngc.newstr("macOS"); #endif - return gc.newstr("unknown"); + return ngc.newstr("unknown"); } // md5 related functions @@ -1019,15 +1019,15 @@ string md5(const string& src) } return tohex(atmp)+tohex(btmp)+tohex(ctmp)+tohex(dtmp); } -nas_ref builtin_md5(nas_ref* local,nasal_gc& gc) +var builtin_md5(var* local,gc& ngc) { - nas_ref str=local[1]; + var str=local[1]; if(str.type!=vm_str) return nas_err("md5","\"str\" must be string"); - return gc.newstr(md5(str.str())); + return ngc.newstr(md5(str.str())); } -nas_ref builtin_cocreate(nas_ref* local,nasal_gc& gc) +var builtin_cocreate(var* local,gc& ngc) { // +-----------------+ // | old pc | <- top[0] @@ -1041,12 +1041,12 @@ nas_ref builtin_cocreate(nas_ref* local,nasal_gc& gc) // +-----------------+ <- local pointer stored in localr // | old funcr | <- old function stored in funcr // +-----------------+ - nas_ref func=local[1]; + var func=local[1]; if(func.type!=vm_func) return nas_err("coroutine::create","must use a function to create coroutine"); - if(gc.cort) + if(ngc.cort) return nas_err("coroutine::create","cannot create another coroutine in a coroutine"); - nas_ref co=gc.alloc(vm_co); + var co=ngc.alloc(vm_co); nas_co& cort=co.co(); cort.pc=func.func().entry-1; @@ -1056,7 +1056,7 @@ nas_ref builtin_cocreate(nas_ref* local,nasal_gc& gc) cort.localr[0]=func.func().local[0]; cort.top[0]=nil; // old upvalr cort.top++; - cort.top[0]={vm_addr,(nas_ref*)nullptr}; // old localr + cort.top[0]={vm_addr,(var*)nullptr}; // old localr cort.top++; cort.top[0]={vm_ret,(u32)0}; // old pc, set to zero to make op_ret recognizing this as coroutine function @@ -1065,64 +1065,64 @@ nas_ref builtin_cocreate(nas_ref* local,nasal_gc& gc) return co; } -nas_ref builtin_coresume(nas_ref* local,nasal_gc& gc) +var builtin_coresume(var* local,gc& ngc) { - if(gc.cort) + if(ngc.cort) return nas_err("coroutine::resume","cannot start another coroutine when one is running"); - nas_ref co=local[1]; + var co=local[1]; if(co.type!=vm_co) return nas_err("coroutine::resume","must use a coroutine object"); if(co.co().status==nas_co::dead) return nil; - gc.ctxchg(co.co()); - return gc.top[0]; + ngc.ctxchg(co.co()); + return ngc.top[0]; } -nas_ref builtin_coyield(nas_ref* local,nasal_gc& gc) +var builtin_coyield(var* local,gc& ngc) { - if(!gc.cort) + if(!ngc.cort) return nas_err("coroutine::yield","no coroutine is running"); - gc.ctxreserve(); + ngc.ctxreserve(); // this will set to main stack top // then builtin_coresume will return it return local[1]; } -nas_ref builtin_costatus(nas_ref* local,nasal_gc& gc) +var builtin_costatus(var* local,gc& ngc) { - nas_ref co=local[1]; + var co=local[1]; if(co.type!=vm_co) return nas_err("coroutine::status","must use a coroutine object"); switch(co.co().status) { - 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; + case nas_co::suspended: return ngc.newstr("suspended");break; + case nas_co::running: return ngc.newstr("running"); break; + case nas_co::dead: return ngc.newstr("dead"); break; } return nil; } -nas_ref builtin_corun(nas_ref* local,nasal_gc& gc) +var builtin_corun(var* local,gc& ngc) { - return gc.cort?one:zero; + return ngc.cort?one:zero; } -nas_ref builtin_millisec(nas_ref* local,nasal_gc& gc) +var builtin_millisec(var* local,gc& ngc) { f64 res=std::chrono::duration_cast (std::chrono::high_resolution_clock::now().time_since_epoch()) .count(); return {vm_num,res}; } -nas_ref builtin_sysargv(nas_ref* local,nasal_gc& gc) +var builtin_sysargv(var* local,gc& ngc) { - nas_ref res=gc.alloc(vm_vec); - res.vec().elems=gc.env_argv; + var res=ngc.alloc(vm_vec); + res.vec().elems=ngc.env_argv; return res; } -nas_ref builtin_logtime(nas_ref* local,nasal_gc& gc) +var builtin_logtime(var* local,gc& ngc) { time_t t=time(nullptr); tm* tm_t=localtime(&t); char s[32]; sprintf(s,"%d-%.2d-%.2d %.2d:%.2d:%.2d",tm_t->tm_year+1900,tm_t->tm_mon+1,tm_t->tm_mday,tm_t->tm_hour,tm_t->tm_min,tm_t->tm_sec); - return gc.newstr(s); + return ngc.newstr(s); } // register builtin function's name and it's address here in this table below @@ -1130,7 +1130,7 @@ nas_ref builtin_logtime(nas_ref* local,nasal_gc& gc) struct { const char* name; - nas_ref (*func)(nas_ref*,nasal_gc&); + var (*func)(var*,gc&); } builtin[]= { {"__print", builtin_print }, diff --git a/nasal_codegen.h b/nasal_codegen.h index f51434c..2519b56 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -198,11 +198,11 @@ public: } }; -class nasal_codegen +class codegen { private: u16 fileindex; - nasal_err& nerr; + error& err; const string* file; std::stack in_iterloop; std::unordered_map num_table; @@ -264,24 +264,24 @@ private: void singleop(const u32); public: - nasal_codegen(nasal_err& e):fileindex(0),nerr(e),file(nullptr){} - void compile(const nasal_parse&,const nasal_import&); + codegen(error& e):fileindex(0),err(e),file(nullptr){} + void compile(const parse&,const linker&); 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;} }; -void nasal_codegen::die(const string& info,const u32 line,const u32 col) +void codegen::die(const string& info,const u32 line,const u32 col) { - nerr.load(file[fileindex]); + err.load(file[fileindex]); if(col) - nerr.err("code",line,col,info); + err.err("code",line,col,info); else - nerr.err("code",line,info); + err.err("code",line,info); } -void nasal_codegen::regist_num(const f64 num) +void codegen::regist_num(const f64 num) { if(!num_table.count(num)) { @@ -291,7 +291,7 @@ void nasal_codegen::regist_num(const f64 num) } } -void nasal_codegen::regist_str(const string& str) +void codegen::regist_str(const string& str) { if(!str_table.count(str)) { @@ -301,7 +301,7 @@ void nasal_codegen::regist_str(const string& str) } } -void nasal_codegen::find_symbol(const ast& node) +void codegen::find_symbol(const ast& node) { // symbol definition checked here // if find a function, return @@ -326,7 +326,7 @@ void nasal_codegen::find_symbol(const ast& node) find_symbol(i); } -void nasal_codegen::add_sym(const string& name) +void codegen::add_sym(const string& name) { if(local.empty()) { @@ -342,19 +342,19 @@ void nasal_codegen::add_sym(const string& name) local.back()[name]=index; } -i32 nasal_codegen::local_find(const string& name) +i32 codegen::local_find(const string& name) { if(local.empty()) return -1; return local.back().count(name)?local.back()[name]:-1; } -i32 nasal_codegen::global_find(const string& name) +i32 codegen::global_find(const string& name) { return global.count(name)?global[name]:-1; } -i32 nasal_codegen::upvalue_find(const string& name) +i32 codegen::upvalue_find(const string& name) { // 32768 level 65536 upvalues i32 index=-1; @@ -368,32 +368,32 @@ i32 nasal_codegen::upvalue_find(const string& name) return index; } -void nasal_codegen::gen(u8 op,u32 num,u32 line) +void codegen::gen(u8 op,u32 num,u32 line) { code.push_back({op,fileindex,num,line}); } -void nasal_codegen::num_gen(const ast& node) +void codegen::num_gen(const ast& node) { f64 num=node.num(); regist_num(num); gen(op_pnum,num_table[num],node.line()); } -void nasal_codegen::str_gen(const ast& node) +void codegen::str_gen(const ast& node) { regist_str(node.str()); gen(op_pstr,str_table[node.str()],node.line()); } -void nasal_codegen::vec_gen(const ast& node) +void codegen::vec_gen(const ast& node) { for(auto& child:node.child()) calc_gen(child); gen(op_newv,node.size(),node.line()); } -void nasal_codegen::hash_gen(const ast& node) +void codegen::hash_gen(const ast& node) { gen(op_newh,0,node.line()); for(auto& child:node.child()) @@ -405,7 +405,7 @@ void nasal_codegen::hash_gen(const ast& node) } } -void nasal_codegen::func_gen(const ast& node) +void codegen::func_gen(const ast& node) { usize newf=code.size(); gen(op_newf,0,node.line()); @@ -462,7 +462,7 @@ void nasal_codegen::func_gen(const ast& node) code[jmp_ptr].num=code.size(); } -void nasal_codegen::call_gen(const ast& node) +void codegen::call_gen(const ast& node) { calc_gen(node[0]); if(code.back().op==op_callb) @@ -479,7 +479,7 @@ void nasal_codegen::call_gen(const ast& node) } } -void nasal_codegen::call_id(const ast& node) +void codegen::call_id(const ast& node) { const string& str=node.str(); for(u32 i=0;builtin[i].name;++i) @@ -509,13 +509,13 @@ void nasal_codegen::call_id(const ast& node) die("undefined symbol \""+str+"\"",node.line(),node.col()); } -void nasal_codegen::call_hash(const ast& node) +void codegen::call_hash(const ast& node) { regist_str(node.str()); gen(op_callh,str_table[node.str()],node.line()); } -void nasal_codegen::call_vec(const ast& node) +void codegen::call_vec(const ast& node) { // maybe this place can use callv-const if ast's first child is ast_num if(node.size()==1 && node[0].type()!=ast_subvec) @@ -542,7 +542,7 @@ void nasal_codegen::call_vec(const ast& node) gen(op_slcend,0,node.line()); } -void nasal_codegen::call_func(const ast& node) +void codegen::call_func(const ast& node) { if(!node.size()) gen(op_callfv,0,node.line()); @@ -565,9 +565,9 @@ void nasal_codegen::call_func(const ast& node) * at this time the value including the memory space can must be found alive. * BUT in fact this method does not make much safety. * so we use another way to avoid gc-caused SIGSEGV: reserve m-called value on stack. -* you could see the notes in `nasal_vm::opr_mcallv()`. +* you could see the notes in `vm::opr_mcallv()`. */ -void nasal_codegen::mcall(const ast& node) +void codegen::mcall(const ast& node) { if(node.type()==ast_id) { @@ -597,7 +597,7 @@ void nasal_codegen::mcall(const ast& node) mcall_vec(tmp); } -void nasal_codegen::mcall_id(const ast& node) +void codegen::mcall_id(const ast& node) { const string& str=node.str(); for(u32 i=0;builtin[i].name;++i) @@ -625,19 +625,19 @@ void nasal_codegen::mcall_id(const ast& node) die("undefined symbol \""+str+"\"",node.line(),node.col()); } -void nasal_codegen::mcall_vec(const ast& node) +void codegen::mcall_vec(const ast& node) { calc_gen(node[0]); gen(op_mcallv,0,node.line()); } -void nasal_codegen::mcall_hash(const ast& node) +void codegen::mcall_hash(const ast& node) { regist_str(node.str()); gen(op_mcallh,str_table[node.str()],node.line()); } -void nasal_codegen::single_def(const ast& node) +void codegen::single_def(const ast& node) { const string& str=node[0].str(); calc_gen(node[1]); @@ -645,7 +645,7 @@ void nasal_codegen::single_def(const ast& node) gen(op_loadg,global_find(str),node.line()): gen(op_loadl,local_find(str),node.line()); } -void nasal_codegen::multi_def(const ast& node) +void codegen::multi_def(const ast& node) { auto& ids=node[0].child(); usize size=ids.size(); @@ -676,12 +676,12 @@ void nasal_codegen::multi_def(const ast& node) } } -void nasal_codegen::def_gen(const ast& node) +void codegen::def_gen(const ast& node) { node[0].type()==ast_id?single_def(node):multi_def(node); } -void nasal_codegen::multi_assign_gen(const ast& node) +void codegen::multi_assign_gen(const ast& node) { i32 size=node[0].size(); if(node[1].type()==ast_multi_scalar) @@ -725,7 +725,7 @@ void nasal_codegen::multi_assign_gen(const ast& node) } } -void nasal_codegen::conditional_gen(const ast& node) +void codegen::conditional_gen(const ast& node) { std::vector jmp_label; for(auto& tmp:node.child()) @@ -754,7 +754,7 @@ void nasal_codegen::conditional_gen(const ast& node) code[i].num=code.size(); } -void nasal_codegen::loop_gen(const ast& node) +void codegen::loop_gen(const ast& node) { continue_ptr.push_front(std::vector()); break_ptr.push_front(std::vector()); @@ -767,7 +767,7 @@ void nasal_codegen::loop_gen(const ast& node) } } -void nasal_codegen::load_continue_break(i32 continue_place,i32 break_place) +void codegen::load_continue_break(i32 continue_place,i32 break_place) { for(auto i:continue_ptr.front()) code[i].num=continue_place; @@ -777,7 +777,7 @@ void nasal_codegen::load_continue_break(i32 continue_place,i32 break_place) break_ptr.pop_front(); } -void nasal_codegen::while_gen(const ast& node) +void codegen::while_gen(const ast& node) { usize loop_ptr=code.size(); calc_gen(node[0]); @@ -790,7 +790,7 @@ void nasal_codegen::while_gen(const ast& node) load_continue_break(code.size()-1,code.size()); } -void nasal_codegen::for_gen(const ast& node) +void codegen::for_gen(const ast& node) { switch(node[0].type()) { @@ -915,7 +915,7 @@ void nasal_codegen::for_gen(const ast& node) load_continue_break(continue_place,code.size()); } -void nasal_codegen::forindex_gen(const ast& node) +void codegen::forindex_gen(const ast& node) { calc_gen(node[1]); gen(op_cnt,0,node[1].line()); @@ -949,7 +949,7 @@ void nasal_codegen::forindex_gen(const ast& node) gen(op_pop,0,node[1].line());// pop vector gen(op_pop,0,node.line());// pop iterator } -void nasal_codegen::foreach_gen(const ast& node) +void codegen::foreach_gen(const ast& node) { calc_gen(node[1]); gen(op_cnt,0,node.line()); @@ -984,7 +984,7 @@ void nasal_codegen::foreach_gen(const ast& node) gen(op_pop,0,node.line());// pop iterator } -void nasal_codegen::or_gen(const ast& node) +void codegen::or_gen(const ast& node) { calc_gen(node[0]); usize l1=code.size(); @@ -1001,7 +1001,7 @@ void nasal_codegen::or_gen(const ast& node) code[l1].num=code[l2].num=code.size(); } -void nasal_codegen::and_gen(const ast& node) +void codegen::and_gen(const ast& node) { calc_gen(node[0]); gen(op_jt,code.size()+2,node[0].line()); @@ -1019,7 +1019,7 @@ void nasal_codegen::and_gen(const ast& node) //jt jumps here } -void nasal_codegen::trino_gen(const ast& node) +void codegen::trino_gen(const ast& node) { calc_gen(node[0]); usize lfalse=code.size(); @@ -1032,7 +1032,7 @@ void nasal_codegen::trino_gen(const ast& node) code[lexit].num=code.size(); } -void nasal_codegen::calc_gen(const ast& node) +void codegen::calc_gen(const ast& node) { switch(node.type()) { @@ -1137,7 +1137,7 @@ void nasal_codegen::calc_gen(const ast& node) } } -void nasal_codegen::block_gen(const ast& node) +void codegen::block_gen(const ast& node) { for(auto& tmp:node.child()) switch(tmp.type()) @@ -1222,7 +1222,7 @@ void nasal_codegen::block_gen(const ast& node) } } -void nasal_codegen::ret_gen(const ast& node) +void codegen::ret_gen(const ast& node) { for(u32 i=0;i0xffffffff) die("too large generated bytecode file: "+std::to_string(code.size()),0,0); - nerr.chkerr(); + err.chkerr(); } -void nasal_codegen::singleop(const u32 index) +void codegen::singleop(const u32 index) { // print opcode index,opcode name,opcode immediate number const opcode& c=code[index]; @@ -1278,7 +1278,7 @@ void nasal_codegen::singleop(const u32 index) std::cout<<" "< -class nasal_dbg:public nasal_vm +class debugger:public vm { private: bool next; usize fsize; u16 bk_fidx; u32 bk_line; - nasal_err& src; + error& src; std::vector parse(const string&); u16 fileindex(const string&); @@ -22,18 +22,18 @@ private: void stepinfo(); void interact(); public: - nasal_dbg(nasal_err& nerr): + debugger(error& err): next(false),fsize(0), bk_fidx(0),bk_line(0), - src(nerr){} + src(err){} void run( - const nasal_codegen&, - const nasal_import&, + const codegen&, + const linker&, const std::vector& ); }; -std::vector nasal_dbg::parse(const string& cmd) +std::vector debugger::parse(const string& cmd) { std::vector res; usize last=0,pos=cmd.find(" ",0); @@ -49,7 +49,7 @@ std::vector nasal_dbg::parse(const string& cmd) return res; } -u16 nasal_dbg::fileindex(const string& filename) +u16 debugger::fileindex(const string& filename) { for(u16 i=0;i\n" @@ -83,7 +83,7 @@ void nasal_dbg::help() <<"\tbk, break | set break point\n"; } -void nasal_dbg::callsort(const u64* arr) +void debugger::callsort(const u64* arr) { typedef std::pair op; std::vector opcall; @@ -111,7 +111,7 @@ void nasal_dbg::callsort(const u64* arr) std::clog<<"\n total : "<>3)==0?0:((line>>3)<<3); @@ -131,7 +131,7 @@ void nasal_dbg::stepinfo() stackinfo(10); } -void nasal_dbg::interact() +void debugger::interact() { // special operand if(bytecode[pc].op==op_intg) @@ -207,9 +207,9 @@ void nasal_dbg::interact() } } -void nasal_dbg::run( - const nasal_codegen& gen, - const nasal_import& linker, +void debugger::run( + const codegen& gen, + const linker& linker, const std::vector& argv) { detail_info=true; @@ -248,47 +248,47 @@ void nasal_dbg::run( // goto the first operand goto *code[pc]; #else - typedef void (nasal_dbg::*nafunc)(); + typedef void (debugger::*nafunc)(); const nafunc oprs[]= { - 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 + nullptr, &debugger::o_intg, + &debugger::o_intl, &debugger::o_loadg, + &debugger::o_loadl, &debugger::o_loadu, + &debugger::o_pnum, &debugger::o_pnil, + &debugger::o_pstr, &debugger::o_newv, + &debugger::o_newh, &debugger::o_newf, + &debugger::o_happ, &debugger::o_para, + &debugger::o_deft, &debugger::o_dyn, + &debugger::o_unot, &debugger::o_usub, + &debugger::o_add, &debugger::o_sub, + &debugger::o_mul, &debugger::o_div, + &debugger::o_lnk, &debugger::o_addc, + &debugger::o_subc, &debugger::o_mulc, + &debugger::o_divc, &debugger::o_lnkc, + &debugger::o_addeq, &debugger::o_subeq, + &debugger::o_muleq, &debugger::o_diveq, + &debugger::o_lnkeq, &debugger::o_addeqc, + &debugger::o_subeqc, &debugger::o_muleqc, + &debugger::o_diveqc, &debugger::o_lnkeqc, + &debugger::o_meq, &debugger::o_eq, + &debugger::o_neq, &debugger::o_less, + &debugger::o_leq, &debugger::o_grt, + &debugger::o_geq, &debugger::o_lessc, + &debugger::o_leqc, &debugger::o_grtc, + &debugger::o_geqc, &debugger::o_pop, + &debugger::o_jmp, &debugger::o_jt, + &debugger::o_jf, &debugger::o_cnt, + &debugger::o_findex, &debugger::o_feach, + &debugger::o_callg, &debugger::o_calll, + &debugger::o_upval, &debugger::o_callv, + &debugger::o_callvi, &debugger::o_callh, + &debugger::o_callfv, &debugger::o_callfh, + &debugger::o_callb, &debugger::o_slcbeg, + &debugger::o_slcend, &debugger::o_slc, + &debugger::o_slc2, &debugger::o_mcallg, + &debugger::o_mcalll, &debugger::o_mupval, + &debugger::o_mcallv, &debugger::o_mcallh, + &debugger::o_ret }; std::vector code; for(auto& i:gen.codes()) @@ -308,7 +308,7 @@ void nasal_dbg::run( vmexit: callsort(count); - gc.clear(); + ngc.clear(); imm.clear(); std::cout< elems; + std::vector elems; nas_vec():printed(false){} - friend std::ostream& operator<<(std::ostream&,nas_vec&); - usize size(){return elems.size();} - nas_ref get_val(const i32); - nas_ref* get_mem(const i32); + friend std::ostream& operator<<(std::ostream&,nas_vec&); + usize size(){return elems.size();} + var get_val(const i32); + var* get_mem(const i32); }; struct nas_hash { bool printed; - std::unordered_map elems; + std::unordered_map elems; nas_hash():printed(false){} - friend std::ostream& operator<<(std::ostream&,nas_hash&); - usize size(){return elems.size();} - nas_ref get_val(const string&); - nas_ref* get_mem(const string&); + friend std::ostream& operator<<(std::ostream&,nas_hash&); + usize size(){return elems.size();} + var get_val(const string&); + var* get_mem(const string&); }; struct nas_func @@ -131,8 +131,8 @@ struct nas_func 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::vector local; // local scope with default value(var) + std::vector upval; // closure std::unordered_map keys; // parameter table, u32 begins from 1 nas_func():dpara(-1),entry(0),psize(0),lsize(0){} @@ -142,12 +142,12 @@ struct nas_func struct nas_upval { bool onstk; - u32 size; - nas_ref* stk; - std::vector elems; + u32 size; + var* stk; + std::vector elems; nas_upval(){onstk=true;stk=nullptr;size=0;} - nas_ref& operator[](usize n){return onstk?stk[n]:elems[n];} + var& operator[](usize n){return onstk?stk[n]:elems[n];} void clear(){onstk=true;elems.clear();size=0;} }; @@ -195,15 +195,15 @@ struct nas_co running, dead }; - nas_ref stack[STACK_DEPTH]; + var stack[STACK_DEPTH]; - u32 pc; - nas_ref* top; - nas_ref* canary; - nas_ref* localr; - nas_ref* memr; - nas_ref funcr; - nas_ref upvalr; + u32 pc; + var* top; + var* canary; + var* localr; + var* memr; + var funcr; + var upvalr; u32 status; nas_co(): @@ -248,20 +248,20 @@ struct nas_val nas_upval* upval; nas_obj* obj; nas_co* co; - }ptr; + } ptr; nas_val(u8); ~nas_val(); }; -nas_ref nas_vec::get_val(const i32 n) +var nas_vec::get_val(const i32 n) { i32 size=elems.size(); if(n<-size || n>=size) return {vm_none}; return elems[n>=0?n:n+size]; } -nas_ref* nas_vec::get_mem(const i32 n) +var* nas_vec::get_mem(const i32 n) { i32 size=elems.size(); if(n<-size || n>=size) @@ -284,14 +284,14 @@ std::ostream& operator<<(std::ostream& out,nas_vec& vec) return out; } -nas_ref nas_hash::get_val(const string& key) +var nas_hash::get_val(const string& key) { if(elems.count(key)) return elems[key]; else if(elems.count("parents")) { - nas_ref ret(vm_none); - nas_ref val=elems["parents"]; + var ret(vm_none); + var val=elems["parents"]; if(val.type==vm_vec) for(auto& i:val.vec().elems) { @@ -303,14 +303,14 @@ nas_ref nas_hash::get_val(const string& key) } return {vm_none}; } -nas_ref* nas_hash::get_mem(const string& key) +var* nas_hash::get_mem(const string& key) { if(elems.count(key)) return &elems[key]; else if(elems.count("parents")) { - nas_ref* addr=nullptr; - nas_ref val=elems["parents"]; + var* addr=nullptr; + var val=elems["parents"]; if(val.type==vm_vec) for(auto& i:val.vec().elems) { @@ -376,11 +376,11 @@ nas_val::~nas_val() } type=vm_nil; } -f64 nas_ref::tonum() +f64 var::tonum() { return type!=vm_str?val.num:str2num(str().c_str()); } -string nas_ref::tostr() +string var::tostr() { if(type==vm_str) return str(); @@ -393,7 +393,7 @@ string nas_ref::tostr() } return ""; } -std::ostream& operator<<(std::ostream& out,nas_ref& ref) +std::ostream& operator<<(std::ostream& out,var& ref) { switch(ref.type) { @@ -409,56 +409,56 @@ std::ostream& operator<<(std::ostream& out,nas_ref& ref) } return out; } -bool nas_ref::objchk(u32 objtype) +bool var::objchk(u32 objtype) { return type==vm_obj && obj().type==objtype && obj().ptr; } -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; } +inline var* var::addr (){return val.addr; } +inline u32 var::ret (){return val.ret; } +inline i64& var::cnt (){return val.cnt; } +inline f64 var::num (){return val.num; } +inline string& var::str (){return *val.gcobj->ptr.str; } +inline nas_vec& var::vec (){return *val.gcobj->ptr.vec; } +inline nas_hash& var::hash (){return *val.gcobj->ptr.hash; } +inline nas_func& var::func (){return *val.gcobj->ptr.func; } +inline nas_upval& var::upval(){return *val.gcobj->ptr.upval;} +inline nas_obj& var::obj (){return *val.gcobj->ptr.obj; } +inline nas_co& var::co (){return *val.gcobj->ptr.co; } -const nas_ref zero={vm_num,(f64)0}; -const nas_ref one ={vm_num,(f64)1}; -const nas_ref nil ={vm_nil,(f64)0}; +const var zero={vm_num,(f64)0}; +const var one ={vm_num,(f64)1}; +const var nil ={vm_nil,(f64)0}; -struct nasal_gc +struct gc { /* main context */ struct { - u32 pc; - nas_ref* top; - nas_ref* localr; - nas_ref* memr; - nas_ref funcr; - nas_ref upvalr; - nas_ref* canary; - nas_ref* stack; + u32 pc; + var* top; + var* localr; + var* memr; + var funcr; + var upvalr; + var* canary; + var* stack; } mctx; /* runtime context */ - 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 + u32& pc; // program counter + var*& localr;// local scope register + var*& memr; // used for mem_call + var& funcr; // function register + var& upvalr;// upvalue register + var*& canary;// avoid stackoverflow + var*& top; // stack top + var* stack; // stack pointer + nas_co* cort;// running coroutine + var 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 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 @@ -466,46 +466,42 @@ struct nasal_gc u64 size[gc_tsize]; u64 count[gc_tsize]; u64 allocc[gc_tsize]; - nasal_gc( - u32& _pc, - nas_ref*& _localr, - nas_ref*& _memr, - nas_ref& _funcr, - nas_ref& _upvalr, - nas_ref*& _canary, - nas_ref*& _top, - nas_ref* _stk): + gc( + u32& _pc, var*& _localr, + var*& _memr, var& _funcr, + var& _upvalr, var*& _canary, + var*& _top, var* _stk): pc(_pc),localr(_localr),memr(_memr),funcr(_funcr),upvalr(_upvalr), 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(); + void mark(); + void sweep(); + void init(const std::vector&,const std::vector&); + void clear(); + void info(); + var alloc(const u8); + var newstr(char); + var newstr(const char*); + var newstr(const string&); + void ctxchg(nas_co&); + void ctxreserve(); }; /* gc functions */ -void nasal_gc::mark() +void 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 nas_co related to it will not update it's context(like `top`) until the coroutine suspends or exits. - for(nas_ref* i=stack;i<=top;++i) + for(var* i=stack;i<=top;++i) bfs.push(*i); bfs.push(funcr); bfs.push(upvalr); bfs.push(temp); if(cort) // scan main process stack { - for(nas_ref* i=mctx.stack;i<=mctx.top;++i) + for(var* i=mctx.stack;i<=mctx.top;++i) bfs.push(*i); bfs.push(mctx.funcr); bfs.push(mctx.upvalr); @@ -513,7 +509,7 @@ void nasal_gc::mark() while(!bfs.empty()) { - nas_ref tmp=bfs.front(); + var tmp=bfs.front(); bfs.pop(); if(tmp.type<=vm_num || tmp.val.gcobj->mark) continue; tmp.val.gcobj->mark=GC_FOUND; @@ -540,13 +536,13 @@ void nasal_gc::mark() case vm_co: bfs.push(tmp.co().funcr); bfs.push(tmp.co().upvalr); - for(nas_ref* i=tmp.co().stack;i<=tmp.co().top;++i) + for(var* i=tmp.co().stack;i<=tmp.co().top;++i) bfs.push(*i); break; } } } -void nasal_gc::sweep() +void gc::sweep() { for(auto i:memory) { @@ -569,7 +565,7 @@ void nasal_gc::sweep() i->mark=GC_UNCOLLECTED; } } -void nasal_gc::init(const std::vector& s,const std::vector& argv) +void gc::init(const std::vector& s,const std::vector& argv) { // initiaize function register funcr=nil; @@ -601,7 +597,7 @@ void nasal_gc::init(const std::vector& s,const std::vector& argv env_argv[i].str()=argv[i]; } } -void nasal_gc::clear() +void gc::clear() { for(auto i:memory) delete i; @@ -614,7 +610,7 @@ void nasal_gc::clear() strs.clear(); env_argv.clear(); } -void nasal_gc::info() +void gc::info() { const char* name[]={"str ","vec ","hash ","func ","upval","obj ","co "}; std::cout<<"\ngarbage collector info(gc/alloc)\n"; @@ -626,7 +622,7 @@ void nasal_gc::info() if(ini[i] || size[i]) std::cout<<" "<mark=GC_UNCOLLECTED; unused[index].pop(); return ret; } -nas_ref nasal_gc::newstr(char c) +var gc::newstr(char c) { - nas_ref s=alloc(vm_str); + var s=alloc(vm_str); s.str()=c; return s; } -nas_ref nasal_gc::newstr(const char* buff) +var gc::newstr(const char* buff) { - nas_ref s=alloc(vm_str); + var s=alloc(vm_str); s.str()=buff; return s; } -nas_ref nasal_gc::newstr(const string& buff) +var gc::newstr(const string& buff) { - nas_ref s=alloc(vm_str); + var s=alloc(vm_str); s.str()=buff; return s; } -void nasal_gc::ctxchg(nas_co& ctx) +void gc::ctxchg(nas_co& ctx) { mctx.pc=pc; mctx.top=top; @@ -692,7 +688,7 @@ void nasal_gc::ctxchg(nas_co& ctx) cort->status=nas_co::running; } -void nasal_gc::ctxreserve() +void gc::ctxreserve() { // pc=0 means this coroutine is finished cort->status=pc?nas_co::suspended:nas_co::dead; @@ -716,7 +712,7 @@ void nasal_gc::ctxreserve() } // use to print error log and return error value -nas_ref nas_err(const string& err_f,const string& info) +var nas_err(const string& err_f,const string& info) { std::cerr<<"[vm] "< files; std::vector envpath; bool imptchk(const ast&); bool exist(const string&); - void linker(ast&,ast&&); + void link(ast&,ast&&); string path(const ast&); string findf(const string&); ast fimpt(ast&); ast libimpt(); ast load(ast&,u16); public: - nasal_import(nasal_err&); - void link(nasal_parse&,const string&,bool); + linker(error&); + void link(parse&,const string&,bool); const std::vector& filelist() const {return files;} }; -nasal_import::nasal_import(nasal_err& e):lib_loaded(false),nerr(e){ +linker::linker(error& e):lib_loaded(false),err(e){ #ifdef _WIN32 char sep=';'; #else @@ -55,7 +55,7 @@ nasal_import::nasal_import(nasal_err& e):lib_loaded(false),nerr(e){ envpath.push_back(PATH.substr(last)); } -string nasal_import::path(const ast& node) +string linker::path(const ast& node) { if(node[1].type()==ast_callf) return node[1][0].str(); @@ -69,7 +69,7 @@ string nasal_import::path(const ast& node) return fpath+".nas"; } -string nasal_import::findf(const string& fname) +string linker::findf(const string& fname) { std::vector filepath={fname}; for(auto&p:envpath) @@ -91,17 +91,17 @@ string nasal_import::findf(const string& fname) #endif if(!show_path) { - nerr.err("link","cannot find file <"+fname+">"); + err.err("link","cannot find file <"+fname+">"); return ""; } string paths=""; for(auto& i:filepath) paths+=" "+i+"\n"; - nerr.err("link","cannot find file <"+fname+"> in these paths:\n"+paths); + err.err("link","cannot find file <"+fname+"> in these paths:\n"+paths); return ""; } -bool nasal_import::imptchk(const ast& node) +bool linker::imptchk(const ast& node) { // only these two kinds of node can be recognized as 'import': /* @@ -133,7 +133,7 @@ bool nasal_import::imptchk(const ast& node) ); } -bool nasal_import::exist(const string& file) +bool linker::exist(const string& file) { // avoid importing the same file for(auto& fname:files) @@ -143,17 +143,17 @@ bool nasal_import::exist(const string& file) return false; } -void nasal_import::linker(ast& root,ast&& add_root) +void linker::link(ast& root,ast&& add_root) { // add children of add_root to the back of root for(auto& i:add_root.child()) root.add(std::move(i)); } -ast nasal_import::fimpt(ast& node) +ast linker::fimpt(ast& node) { - nasal_lexer lex(nerr); - nasal_parse par(nerr); + lexer lex(err); + parse par(err); // get filename and set node to ast_null string filename=path(node); node.clear(); @@ -171,10 +171,10 @@ ast nasal_import::fimpt(ast& node) return load(tmp,files.size()-1); } -ast nasal_import::libimpt() +ast linker::libimpt() { - nasal_lexer lex(nerr); - nasal_parse par(nerr); + lexer lex(err); + parse par(err); string filename=findf("lib.nas"); if(!filename.length()) return {0,0,ast_root}; @@ -191,18 +191,18 @@ ast nasal_import::libimpt() return load(tmp,files.size()-1); } -ast nasal_import::load(ast& root,u16 fileindex) +ast linker::load(ast& root,u16 fileindex) { ast new_root(0,0,ast_root); if(!lib_loaded) { - linker(new_root,libimpt()); + link(new_root,libimpt()); lib_loaded=true; } for(auto& i:root.child()) { if(imptchk(i)) - linker(new_root,fimpt(i)); + link(new_root,fimpt(i)); else break; } @@ -210,11 +210,11 @@ ast nasal_import::load(ast& root,u16 fileindex) ast file_head(0,0,ast_file); file_head.set_num(fileindex); new_root.add(std::move(file_head)); - linker(new_root,std::move(root)); + link(new_root,std::move(root)); return new_root; } -void nasal_import::link(nasal_parse& parse,const string& self,bool spath=false) +void linker::link(parse& parse,const string& self,bool spath=false) { show_path=spath; // initializing @@ -222,7 +222,7 @@ void nasal_import::link(nasal_parse& parse,const string& self,bool spath=false) // scan root and import files,then generate a new ast and return to import_ast // the main file's index is 0 parse.tree()=load(parse.tree(),0); - nerr.chkerr(); + err.chkerr(); } #endif \ No newline at end of file diff --git a/nasal_lexer.h b/nasal_lexer.h index 970cae0..9ee3432 100644 --- a/nasal_lexer.h +++ b/nasal_lexer.h @@ -115,54 +115,52 @@ struct token } }; -class nasal_lexer +class lexer { private: u32 line; u32 column; usize ptr; string res; - nasal_err& nerr; + error& err; std::vector tokens; u32 get_type(const string&); - void die(const string& info){nerr.err("lexer",line,column,info);} + void die(const string& info){err.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), - res(""), - nerr(e){} + lexer(error& e): + line(1),column(0), + ptr(0),res(""), + err(e){} void scan(const string&); void print(); const std::vector& result() const {return tokens;} }; -void nasal_lexer::open(const string& file) +void lexer::open(const string& file) { struct stat buffer; if(stat(file.c_str(),&buffer)==0 && !S_ISREG(buffer.st_mode)) { - nerr.err("lexer","<"+file+"> is not a regular file"); - nerr.chkerr(); + err.err("lexer","<"+file+"> is not a regular file"); + err.chkerr(); } std::ifstream fin(file,std::ios::binary); if(fin.fail()) - nerr.err("lexer","failed to open <"+file+">"); + err.err("lexer","failed to open <"+file+">"); else - nerr.load(file); + err.load(file); std::stringstream ss; ss< #include "nasal_codegen.h" -class nasal_vm +class vm { protected: - /* registers and constants of nasal_vm */ - 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 + /* registers and constants of vm */ + u32 pc; // program counter + var* localr; // local scope register + var* memr; // used for mem_call + var funcr; // function register + var upvalr; // upvalue register + var* canary; // avoid stackoverflow + var* top; // stack top + const f64* num_table;// const numbers, ref from codegen + const string* str_table;// const symbols, ref from codegen std::vector imm; // immediate number /* garbage collector */ - nasal_gc gc; + gc ngc; /* main stack */ - nas_ref stack[STACK_DEPTH]; + var stack[STACK_DEPTH]; /* values used for debugger */ - const string* files; // ref from nasal_import - const opcode* bytecode; // ref from nasal_codegen + const string* files; // ref from linker + const opcode* bytecode; // ref from codegen void init( const std::vector&, @@ -37,7 +37,7 @@ protected: const std::vector&); /* debug functions */ bool detail_info; - void valinfo(nas_ref&); + void valinfo(var&); void traceback(); void stackinfo(const u32); void reginfo(); @@ -48,7 +48,7 @@ protected: void die(const string&); #define vm_error(info) {die(info);return;} /* vm calculation functions*/ - bool condition(nas_ref); + bool condition(var); /* vm operands */ void o_intg(); void o_intl(); @@ -125,26 +125,26 @@ protected: void o_mcallh(); void o_ret(); public: - nasal_vm():pc(0),localr(nullptr),memr(nullptr),funcr(nil), + vm():pc(0),localr(nullptr),memr(nullptr),funcr(nil), upvalr(nil),canary(nullptr),top(stack), num_table(nullptr),str_table(nullptr), - gc(pc,localr,memr,funcr,upvalr,canary,top,stack), + ngc(pc,localr,memr,funcr,upvalr,canary,top,stack), files(nullptr),bytecode(nullptr),detail_info(false){} void run( - const nasal_codegen&, - const nasal_import&, + const codegen&, + const linker&, const std::vector&, const bool); }; -void nasal_vm::init( +void vm::init( const std::vector& strs, const std::vector& nums, const std::vector& code, const std::vector& filenames, const std::vector& argv) { - gc.init(strs,argv); + ngc.init(strs,argv); num_table=nums.data(); str_table=strs.data(); bytecode=code.data(); @@ -161,7 +161,7 @@ void nasal_vm::init( for(u32 i=0;i ret; - for(nas_ref* i=bottom;i<=ctx_top;++i) + for(var* i=bottom;i<=ctx_top;++i) if(i->type==vm_ret && i->ret()!=0) ret.push(i->ret()); ret.push(pc); // store the position program crashed - std::cout<<"trace back ("<<(gc.stack==stack?"main":"coroutine")<<")\n"; + std::cout<<"trace back ("<<(ngc.stack==stack?"main":"coroutine")<<")\n"; for(u32 p=0,same=0,prev=0xffffffff;!ret.empty();prev=p,ret.pop()) { if((p=ret.top())==prev) @@ -226,12 +226,12 @@ void nasal_vm::traceback() } // the first called place has no same calls } -void nasal_vm::stackinfo(const u32 limit=10) +void vm::stackinfo(const u32 limit=10) { /* bytecode[0].num is the global size */ - const u32 gsize=gc.stack==stack?bytecode[0].num:0; - nas_ref* t=top; - nas_ref* bottom=gc.stack+gsize; + const u32 gsize=ngc.stack==stack?bytecode[0].num:0; + var* t=top; + var* bottom=ngc.stack+gsize; std::cout<<"vm stack (0x"<, limit "<)\n"<)\n"<>16)&0xffff] .upval()[imm[pc]&0xffff]=(top--)[0]; } -inline void nasal_vm::o_pnum() +inline void vm::o_pnum() { (++top)[0]={vm_num,num_table[imm[pc]]}; } -inline void nasal_vm::o_pnil() +inline void vm::o_pnil() { (++top)[0]=nil; } -inline void nasal_vm::o_pstr() +inline void vm::o_pstr() { - (++top)[0]=gc.strs[imm[pc]]; + (++top)[0]=ngc.strs[imm[pc]]; } -inline void nasal_vm::o_newv() +inline void vm::o_newv() { - nas_ref newv=gc.alloc(vm_vec); + var newv=ngc.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 @@ -380,13 +380,13 @@ inline void nasal_vm::o_newv() vec[i]=top[i]; top[0]=newv; } -inline void nasal_vm::o_newh() +inline void vm::o_newh() { - (++top)[0]=gc.alloc(vm_hash); + (++top)[0]=ngc.alloc(vm_hash); } -inline void nasal_vm::o_newf() +inline void vm::o_newf() { - (++top)[0]=gc.alloc(vm_func); + (++top)[0]=ngc.alloc(vm_func); nas_func& func=top[0].func(); func.entry=imm[pc]; func.psize=1; @@ -395,40 +395,40 @@ inline void nasal_vm::o_newf() if(localr) { func.upval=funcr.func().upval; - nas_ref upval=(upvalr.type==vm_nil)?gc.alloc(vm_upval):upvalr; + var upval=(upvalr.type==vm_nil)?ngc.alloc(vm_upval):upvalr; upval.upval().size=funcr.func().lsize; upval.upval().stk=localr; func.upval.push_back(upval); upvalr=upval; } } -inline void nasal_vm::o_happ() +inline void vm::o_happ() { top[-1].hash().elems[str_table[imm[pc]]]=top[0]; --top; } -inline void nasal_vm::o_para() +inline void vm::o_para() { 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::o_deft() +inline void vm::o_deft() { - nas_ref val=top[0]; + var 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::o_dyn() +inline void vm::o_dyn() { top[0].func().dpara=imm[pc]; } -inline void nasal_vm::o_unot() +inline void vm::o_unot() { - nas_ref val=top[0]; + var val=top[0]; switch(val.type) { case vm_nil:top[0]=one;break; @@ -444,7 +444,7 @@ inline void nasal_vm::o_unot() default:vm_error("incorrect value type");break; } } -inline void nasal_vm::o_usub() +inline void vm::o_usub() { top[0]={vm_num,-top[0].tonum()}; } @@ -453,26 +453,26 @@ inline void nasal_vm::o_usub() top[-1]={vm_num,top[-1].tonum() type top[0].tonum()};\ --top; -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() +inline void vm::o_add(){op_calc(+);} +inline void vm::o_sub(){op_calc(-);} +inline void vm::o_mul(){op_calc(*);} +inline void vm::o_div(){op_calc(/);} +inline void vm::o_lnk() { - top[-1]=gc.newstr(top[-1].tostr()+top[0].tostr()); + top[-1]=ngc.newstr(top[-1].tostr()+top[0].tostr()); --top; } #define op_calc_const(type)\ top[0]={vm_num,top[0].tonum() type num_table[imm[pc]]}; -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() +inline void vm::o_addc(){op_calc_const(+);} +inline void vm::o_subc(){op_calc_const(-);} +inline void vm::o_mulc(){op_calc_const(*);} +inline void vm::o_divc(){op_calc_const(/);} +inline void vm::o_lnkc() { - top[0]=gc.newstr(top[0].tostr()+str_table[imm[pc]]); + top[0]=ngc.newstr(top[0].tostr()+str_table[imm[pc]]); } #define op_calc_eq(type)\ @@ -480,13 +480,13 @@ inline void nasal_vm::o_lnkc() memr=nullptr;\ top-=imm[pc]+1; -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() +inline void vm::o_addeq(){op_calc_eq(+);} +inline void vm::o_subeq(){op_calc_eq(-);} +inline void vm::o_muleq(){op_calc_eq(*);} +inline void vm::o_diveq(){op_calc_eq(/);} +inline void vm::o_lnkeq() { - top[-1]=memr[0]=gc.newstr(memr[0].tostr()+top[-1].tostr()); + top[-1]=memr[0]=ngc.newstr(memr[0].tostr()+top[-1].tostr()); memr=nullptr; top-=imm[pc]+1; } @@ -496,18 +496,18 @@ inline void nasal_vm::o_lnkeq() memr=nullptr;\ top-=(imm[pc]>>31); -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() +inline void vm::o_addeqc(){op_calc_eq_const(+);} +inline void vm::o_subeqc(){op_calc_eq_const(-);} +inline void vm::o_muleqc(){op_calc_eq_const(*);} +inline void vm::o_diveqc(){op_calc_eq_const(/);} +inline void vm::o_lnkeqc() { - top[0]=memr[0]=gc.newstr(memr[0].tostr()+str_table[imm[pc]&0x7fffffff]); + top[0]=memr[0]=ngc.newstr(memr[0].tostr()+str_table[imm[pc]&0x7fffffff]); memr=nullptr; top-=(imm[pc]>>31); } -inline void nasal_vm::o_meq() +inline void vm::o_meq() { // pop old memr[0] and replace it // the reason why we should get memr and push the old value on stack @@ -518,10 +518,10 @@ inline void nasal_vm::o_meq() memr=nullptr; top-=imm[pc]+1; } -inline void nasal_vm::o_eq() +inline void vm::o_eq() { - nas_ref val2=top[0]; - nas_ref val1=(--top)[0]; + var val2=top[0]; + var 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) @@ -532,10 +532,10 @@ inline void nasal_vm::o_eq() else top[0]=(val1==val2)?one:zero; } -inline void nasal_vm::o_neq() +inline void vm::o_neq() { - nas_ref val2=top[0]; - nas_ref val1=(--top)[0]; + var val2=top[0]; + var 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) @@ -551,45 +551,45 @@ inline void nasal_vm::o_neq() --top;\ top[0]=(top[0].tonum() type top[1].tonum())?one:zero; -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(>=);} +inline void vm::o_less(){op_cmp(<);} +inline void vm::o_leq(){op_cmp(<=);} +inline void vm::o_grt(){op_cmp(>);} +inline void 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::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 vm::o_lessc(){op_cmp_const(<);} +inline void vm::o_leqc(){op_cmp_const(<=);} +inline void vm::o_grtc(){op_cmp_const(>);} +inline void vm::o_geqc(){op_cmp_const(>=);} -inline void nasal_vm::o_pop() +inline void vm::o_pop() { --top; } -inline void nasal_vm::o_jmp() +inline void vm::o_jmp() { pc=imm[pc]-1; } -inline void nasal_vm::o_jt() +inline void vm::o_jt() { if(condition(top[0])) pc=imm[pc]-1; } -inline void nasal_vm::o_jf() +inline void vm::o_jf() { if(!condition(top[0])) pc=imm[pc]-1; --top; } -inline void nasal_vm::o_cnt() +inline void vm::o_cnt() { if(top[0].type!=vm_vec) vm_error("must use vector in forindex/foreach"); (++top)[0]={vm_cnt,(i64)-1}; } -inline void nasal_vm::o_findex() +inline void vm::o_findex() { if((usize)(++top[0].cnt())>=top[-1].vec().size()) { @@ -599,9 +599,9 @@ inline void nasal_vm::o_findex() top[1]={vm_num,(f64)top[0].cnt()}; ++top; } -inline void nasal_vm::o_feach() +inline void 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; @@ -610,23 +610,23 @@ inline void nasal_vm::o_feach() top[1]=ref[top[0].cnt()]; ++top; } -inline void nasal_vm::o_callg() +inline void vm::o_callg() { (++top)[0]=stack[imm[pc]]; } -inline void nasal_vm::o_calll() +inline void vm::o_calll() { (++top)[0]=localr[imm[pc]]; } -inline void nasal_vm::o_upval() +inline void vm::o_upval() { (++top)[0]=funcr.func().upval[(imm[pc]>>16)&0xffff] .upval()[imm[pc]&0xffff]; } -inline void nasal_vm::o_callv() +inline void vm::o_callv() { - nas_ref val=top[0]; - nas_ref vec=(--top)[0]; + var val=top[0]; + var vec=(--top)[0]; if(vec.type==vm_vec) { top[0]=vec.vec().get_val(val.tonum()); @@ -655,9 +655,9 @@ inline void nasal_vm::o_callv() else vm_error("must call a vector/hash/string"); } -inline void nasal_vm::o_callvi() +inline void vm::o_callvi() { - nas_ref val=top[0]; + var val=top[0]; if(val.type!=vm_vec) vm_error("must use a vector"); // cannot use operator[],because this may cause overflow @@ -665,9 +665,9 @@ inline void nasal_vm::o_callvi() if(top[0].type==vm_none) vm_error("index out of range:"+std::to_string(imm[pc])); } -inline void nasal_vm::o_callh() +inline void vm::o_callh() { - nas_ref val=top[0]; + var val=top[0]; if(val.type!=vm_hash) vm_error("must call a hash"); top[0]=val.hash().get_val(str_table[imm[pc]]); @@ -676,14 +676,14 @@ inline void nasal_vm::o_callh() if(top[0].type==vm_func) top[0].func().local[0]=val;// 'me' } -inline void nasal_vm::o_callfv() +inline void vm::o_callfv() { u32 argc=imm[pc]; // arguments counter - nas_ref* local=top-argc+1; // arguments begin address + var* local=top-argc+1; // arguments begin address if(local[-1].type!=vm_func) vm_error("must call a function"); auto& func=local[-1].func(); - nas_ref tmp=local[-1]; + var tmp=local[-1]; local[-1]=funcr; funcr=tmp; // top-argc+lsize(local) +1(old pc) +1(old localr) +1(old upvalr) @@ -694,11 +694,11 @@ inline void nasal_vm::o_callfv() if(argc=0)// load dynamic arguments { - dynamic=gc.alloc(vm_vec); + dynamic=ngc.alloc(vm_vec); for(u32 i=psize;i=0) vm_error("special call cannot use dynamic argument"); - nas_ref* local=top; + var* local=top; top+=func.lsize; for(u32 i=0;i& ref=top[-1].vec().elems; - std::vector& aim=top[0].vec().elems; + var val2=(top--)[0]; + var val1=(top--)[0]; + std::vector& ref=top[-1].vec().elems; + std::vector& aim=top[0].vec().elems; u8 type1=val1.type,type2=val2.type; i32 num1=val1.tonum(); @@ -823,31 +823,31 @@ inline void nasal_vm::o_slc2() aim.push_back(i>=0?ref[i]:ref[i+size]); } } -inline void nasal_vm::o_mcallg() +inline void 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::o_mcalll() +inline void 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::o_mupval() +inline void vm::o_mupval() { 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::o_mcallv() +inline void vm::o_mcallv() { - nas_ref val=top[0]; // index - nas_ref vec=(--top)[0]; // mcall vector, reserved on stack to avoid gc + var val=top[0]; // index + var vec=(--top)[0]; // mcall vector, reserved on stack to avoid gc if(vec.type==vm_vec) { memr=vec.vec().get_mem(val.tonum()); @@ -868,9 +868,9 @@ inline void nasal_vm::o_mcallv() }else vm_error("cannot get memory space in this type"); } -inline void nasal_vm::o_mcallh() +inline void vm::o_mcallh() { - nas_ref hash=top[0]; // mcall hash, reserved on stack to avoid gc + var hash=top[0]; // mcall hash, reserved on stack to avoid gc if(hash.type!=vm_hash) vm_error("must call a hash"); nas_hash& ref=hash.hash(); @@ -882,7 +882,7 @@ inline void nasal_vm::o_mcallh() memr=ref.get_mem(str); } } -inline void nasal_vm::o_ret() +inline void vm::o_ret() { /* +-------------+ * | return value| <- top[0] @@ -899,10 +899,10 @@ inline void nasal_vm::o_ret() * | old funcr | <- old function stored in funcr * +-------------+ */ - nas_ref ret =top[0]; - nas_ref* local=localr; - nas_ref func =funcr; - nas_ref up =upvalr; + var ret =top[0]; + var* local=localr; + var func =funcr; + var up =upvalr; pc =top[-1].ret(); localr=top[-2].addr(); @@ -923,11 +923,11 @@ inline void nasal_vm::o_ret() // cannot use gc.cort to judge, // because there maybe another function call inside if(!pc) - gc.ctxreserve(); + ngc.ctxreserve(); } -void nasal_vm::run( - const nasal_codegen& gen, - const nasal_import& linker, +void vm::run( + const codegen& gen, + const linker& linker, const std::vector& argv, const bool detail) { @@ -965,47 +965,47 @@ void nasal_vm::run( // goto the first operand goto *code[pc]; #else - typedef void (nasal_vm::*nafunc)(); + typedef void (vm::*nafunc)(); const nafunc oprs[]= { - 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 + nullptr, &vm::o_intg, + &vm::o_intl, &vm::o_loadg, + &vm::o_loadl, &vm::o_loadu, + &vm::o_pnum, &vm::o_pnil, + &vm::o_pstr, &vm::o_newv, + &vm::o_newh, &vm::o_newf, + &vm::o_happ, &vm::o_para, + &vm::o_deft, &vm::o_dyn, + &vm::o_unot, &vm::o_usub, + &vm::o_add, &vm::o_sub, + &vm::o_mul, &vm::o_div, + &vm::o_lnk, &vm::o_addc, + &vm::o_subc, &vm::o_mulc, + &vm::o_divc, &vm::o_lnkc, + &vm::o_addeq, &vm::o_subeq, + &vm::o_muleq, &vm::o_diveq, + &vm::o_lnkeq, &vm::o_addeqc, + &vm::o_subeqc, &vm::o_muleqc, + &vm::o_diveqc, &vm::o_lnkeqc, + &vm::o_meq, &vm::o_eq, + &vm::o_neq, &vm::o_less, + &vm::o_leq, &vm::o_grt, + &vm::o_geq, &vm::o_lessc, + &vm::o_leqc, &vm::o_grtc, + &vm::o_geqc, &vm::o_pop, + &vm::o_jmp, &vm::o_jt, + &vm::o_jf, &vm::o_cnt, + &vm::o_findex, &vm::o_feach, + &vm::o_callg, &vm::o_calll, + &vm::o_upval, &vm::o_callv, + &vm::o_callvi, &vm::o_callh, + &vm::o_callfv, &vm::o_callfh, + &vm::o_callb, &vm::o_slcbeg, + &vm::o_slcend, &vm::o_slc, + &vm::o_slc2, &vm::o_mcallg, + &vm::o_mcalll, &vm::o_mupval, + &vm::o_mcallv, &vm::o_mcallh, + &vm::o_ret }; std::vector code; for(auto& i:gen.codes()) @@ -1023,8 +1023,8 @@ void nasal_vm::run( vmexit: if(detail) - gc.info(); - gc.clear(); + ngc.info(); + ngc.clear(); imm.clear(); return;