🚀 change `std::string` to `string`, change identifiers' name, `-o` is now a function available in debug mode.

This commit is contained in:
ValKmjolnir 2022-07-23 17:00:25 +08:00
parent 46516485b5
commit 99a131c552
18 changed files with 1310 additions and 1303 deletions

132
README.md
View File

@ -559,7 +559,7 @@ If you really want to change source code, check built-in functions in `lib.nas`
Definition:
```C++
nasal_ref builtin_print(nasal_ref*,nasal_gc&);
nas_ref builtin_print(nas_ref*,nasal_gc&);
// you could also use a macro to define one.
nas_native(builtin_print);
```
@ -567,11 +567,11 @@ nas_native(builtin_print);
Then complete this function using C++:
```C++
nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc)
nas_ref builtin_print(nas_ref* local,nasal_gc& gc)
{
// find value with index begin from 1
// because local[0] is reserved for value 'me'
nasal_ref vec=local[1];
nas_ref vec=local[1];
// main process
// also check number of arguments and type here
// if get an error,use builtin_err
@ -601,7 +601,7 @@ After that, register the built-in function's name(in nasal) and the function's p
struct func
{
const char* name;
nasal_ref (*func)(nasal_ref*,nasal_gc&);
nas_ref (*func)(nas_ref*,nasal_gc&);
} builtin[]=
{
{"__print",builtin_print},
@ -644,13 +644,13 @@ The value got before will be collected, but stil in use in this builtin function
So use `gc::temp` in builtin functions to temprorarily store the gc-managed value that you want to return later. Like this:
```C++
nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc)
nas_ref builtin_keys(nas_ref* local,nasal_gc& gc)
{
nasal_ref hash=local[1];
nas_ref hash=local[1];
if(hash.type!=vm_hash)
return builtin_err("keys","\"hash\" must be hash");
// avoid being sweeped
nasal_ref res=gc.temp=gc.alloc(vm_vec);
nas_ref res=gc.temp=gc.alloc(vm_vec);
auto& vec=res.vec().elems;
for(auto& iter:hash.hash().elems)
vec.push_back(gc.newstr(iter.first));
@ -693,10 +693,10 @@ double fibonaci(double x){
}
// remember to use extern "C",
// so you could search the symbol quickly
extern "C" nasal_ref fib(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref fib(std::vector<nas_ref>& args,nasal_gc& gc){
// the arguments are generated into a vm_vec: args
// get values from the vector that must be used here
nasal_ref num=args[0];
nas_ref num=args[0];
// if you want your function safer, try this
// builtin_err will print the error info on screen
// and return vm_null for runtime to interrupt
@ -1330,37 +1330,37 @@ __We will explain how resume and yield work here:__
When `op_callb` is called, the stack frame is like this:
```C++
+----------------------------+(main stack)
| old pc(vm_ret) | <- top[0]
+----------------------------+
| old localr(vm_addr) | <- top[-1]
+----------------------------+
| old upvalr(vm_upval) | <- top[-2]
+----------------------------+
| local scope(nasal_ref) |
| ... |
+----------------------------+ <- local pointer stored in localr
| old funcr(vm_func) | <- old function stored in funcr
+----------------------------+
+--------------------------+(main stack)
| old pc(vm_ret) | <- top[0]
+--------------------------+
| old localr(vm_addr) | <- top[-1]
+--------------------------+
| old upvalr(vm_upval) | <- top[-2]
+--------------------------+
| local scope(nas_ref) |
| ... |
+--------------------------+ <- local pointer stored in localr
| old funcr(vm_func) | <- old function stored in funcr
+--------------------------+
```
In `op_callb`'s progress, next step the stack frame is:
```C++
+----------------------------+(main stack)
| nil(vm_nil) | <- push nil
+----------------------------+
| old pc(vm_ret) |
+----------------------------+
| old localr(vm_addr) |
+----------------------------+
| old upvalr(vm_upval) |
+----------------------------+
| local scope(nasal_ref) |
| ... |
+----------------------------+ <- local pointer stored in localr
| old funcr(vm_func) | <- old function stored in funcr
+----------------------------+
+--------------------------+(main stack)
| nil(vm_nil) | <- push nil
+--------------------------+
| old pc(vm_ret) |
+--------------------------+
| old localr(vm_addr) |
+--------------------------+
| old upvalr(vm_upval) |
+--------------------------+
| local scope(nas_ref) |
| ... |
+--------------------------+ <- local pointer stored in localr
| old funcr(vm_func) | <- old function stored in funcr
+--------------------------+
```
Then we call `resume`, this function will change stack.
@ -1371,9 +1371,9 @@ So for safe running, `resume` will return `gc.top[0]`.
`op_callb` will do `top[0]=resume()`, so the value does not change.
```C++
+----------------------------+(coroutine stack)
| pc:0(vm_ret) | <- now gc.top[0]
+----------------------------+
+--------------------------+(coroutine stack)
| pc:0(vm_ret) | <- now gc.top[0]
+--------------------------+
```
When we call `yield`, the function will do like this.
@ -1381,40 +1381,40 @@ And we find that `op_callb` has put the `nil` at the top.
but where is the returned `local[1]` sent?
```C++
+----------------------------+(coroutine stack)
| nil(vm_nil) | <- push nil
+----------------------------+
| old pc(vm_ret) |
+----------------------------+
| old localr(vm_addr) |
+----------------------------+
| old upvalr(vm_upval) |
+----------------------------+
| local scope(nasal_ref) |
| ... |
+----------------------------+ <- local pointer stored in localr
| old funcr(vm_func) | <- old function stored in funcr
+----------------------------+
+--------------------------+(coroutine stack)
| nil(vm_nil) | <- push nil
+--------------------------+
| old pc(vm_ret) |
+--------------------------+
| old localr(vm_addr) |
+--------------------------+
| old upvalr(vm_upval) |
+--------------------------+
| local scope(nas_ref) |
| ... |
+--------------------------+ <- local pointer stored in localr
| old funcr(vm_func) | <- old function stored in funcr
+--------------------------+
```
When `builtin_coyield` is finished, the stack is set to main stack,
and the returned `local[1]` in fact is set to the top of the main stack by `op_callb`:
```C++
+----------------------------+(main stack)
| return_value(nasal_ref) |
+----------------------------+
| old pc(vm_ret) |
+----------------------------+
| old localr(vm_addr) |
+----------------------------+
| old upvalr(vm_upval) |
+----------------------------+
| local scope(nasal_ref) |
| ... |
+----------------------------+ <- local pointer stored in localr
| old funcr(vm_func) | <- old function stored in funcr
+----------------------------+
+--------------------------+(main stack)
| return_value(nas_ref) |
+--------------------------+
| old pc(vm_ret) |
+--------------------------+
| old localr(vm_addr) |
+--------------------------+
| old upvalr(vm_upval) |
+--------------------------+
| local scope(nas_ref) |
| ... |
+--------------------------+ <- local pointer stored in localr
| old funcr(vm_func) | <- old function stored in funcr
+--------------------------+
```
so the main progress feels the value on the top is the returned value of `resume`.

View File

@ -525,7 +525,7 @@ __警告:__ 如果你 __不想__ 通过直接修改解释器源码来添加你
定义新的内置函数:
```C++
nasal_ref builtin_print(nasal_ref*,nasal_gc&);
nas_ref builtin_print(nas_ref*,nasal_gc&);
// 你可以使用这个宏来直接定义一个新的内置函数
nas_native(builtin_print);
```
@ -533,11 +533,11 @@ nas_native(builtin_print);
然后用C++完成这个函数的函数体:
```C++
nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc)
nas_ref builtin_print(nas_ref* local,nasal_gc& gc)
{
// 局部变量的下标其实是从1开始的
// 因为local[0]是保留给'me'的空间
nasal_ref vec=local[1];
nas_ref vec=local[1];
// 主要部分
// 一些必要的类型检查和输入合法性检测也要在这里写出
// 如果检测到问题用builtin_err函数来返回vm_null
@ -568,7 +568,7 @@ nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc)
struct func
{
const char* name;
nasal_ref (*func)(nasal_ref*,nasal_gc&);
nas_ref (*func)(nas_ref*,nasal_gc&);
} builtin[]=
{
{"__print",builtin_print},
@ -608,13 +608,13 @@ import("./dirname/dirname/filename.nas");
所以请使用`gc::temp`来暂时存储一个会被返回的需要gc管理的变量这样可以防止内部所有的申请错误触发垃圾回收。如下所示
```C++
nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc)
nas_ref builtin_keys(nas_ref* local,nasal_gc& gc)
{
nasal_ref hash=local[1];
nas_ref hash=local[1];
if(hash.type!=vm_hash)
return builtin_err("keys","\"hash\" must be hash");
// 使用gc.temp来存储gc管理的变量防止错误的回收
nasal_ref res=gc.temp=gc.alloc(vm_vec);
nas_ref res=gc.temp=gc.alloc(vm_vec);
auto& vec=res.vec().elems;
for(auto& iter:hash.hash().elems)
vec.push_back(gc.newstr(iter.first));
@ -653,9 +653,9 @@ double fibonaci(double x){
}
// 记得用extern "C"
// 这样找符号会更加快速便捷不要在意编译时的warning
extern "C" nasal_ref fib(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref fib(std::vector<nas_ref>& args,nasal_gc& gc){
// 传参会被送到一个vm_vec类型中送过来而不是上文中那种指针直接指向局部作用域
nasal_ref num=args[0];
nas_ref num=args[0];
// 如果你想让这个函数有更强的稳定性,那么一定要进行合法性检查
// builtin_err会输出错误信息并返回错误类型让虚拟机终止执行
if(num.type!=vm_num)
@ -1228,37 +1228,37 @@ __接下来我们解释这个协程的运行原理:__
当`op_callb`被执行时,栈帧如下所示:
```C++
+----------------------------+(主操作数栈)
| old pc(vm_ret) | <- top[0]
+----------------------------+
| old localr(vm_addr) | <- top[-1]
+----------------------------+
| old upvalr(vm_upval) | <- top[-2]
+----------------------------+
| local scope(nasal_ref) |
| ... |
+----------------------------+ <- local pointer stored in localr
| old funcr(vm_func) | <- old function stored in funcr
+----------------------------+
+--------------------------+(主操作数栈)
| old pc(vm_ret) | <- top[0]
+--------------------------+
| old localr(vm_addr) | <- top[-1]
+--------------------------+
| old upvalr(vm_upval) | <- top[-2]
+--------------------------+
| local scope(nas_ref) |
| ... |
+--------------------------+ <- local pointer stored in localr
| old funcr(vm_func) | <- old function stored in funcr
+--------------------------+
```
在`op_callb`执行过程中,下一步的栈帧如下:
```C++
+----------------------------+(主操作数栈)
| nil(vm_nil) | <- push nil
+----------------------------+
| old pc(vm_ret) |
+----------------------------+
| old localr(vm_addr) |
+----------------------------+
| old upvalr(vm_upval) |
+----------------------------+
| local scope(nasal_ref) |
| ... |
+----------------------------+ <- local pointer stored in localr
| old funcr(vm_func) | <- old function stored in funcr
+----------------------------+
+--------------------------+(主操作数栈)
| nil(vm_nil) | <- push nil
+--------------------------+
| old pc(vm_ret) |
+--------------------------+
| old localr(vm_addr) |
+--------------------------+
| old upvalr(vm_upval) |
+--------------------------+
| local scope(nas_ref) |
| ... |
+--------------------------+ <- local pointer stored in localr
| old funcr(vm_func) | <- old function stored in funcr
+--------------------------+
```
接着我们调用`resume`,这个函数会替换操作数栈。我们会看到,协程的操作数栈上已经保存了一些数据,但是我们首次进入协程执行时,这个操作数栈的栈顶将会是`vm_ret`,并且返回的`pc`值是`0`。
@ -1266,47 +1266,47 @@ __接下来我们解释这个协程的运行原理:__
为了保证栈顶的数据不会被破坏,`resume`会返回`gc.top[0]`。`op_callb`将会执行`top[0]=resume()`,所以栈顶的数据虽然被覆盖了一次,但是实际上还是原来的数据。
```C++
+----------------------------+(协程操作数栈)
| pc:0(vm_ret) | <- now gc.top[0]
+----------------------------+
+--------------------------+(协程操作数栈)
| pc:0(vm_ret) | <- now gc.top[0]
+--------------------------+
```
当我们调用`yield`的时候,该函数会执行出这个情况,我们发现`op_callb` 已经把`nil`放在的栈顶。但是应该返回的`local[1]`到底发送到哪里去了?
```C++
+----------------------------+(协程操作数栈)
| nil(vm_nil) | <- push nil
+----------------------------+
| old pc(vm_ret) |
+----------------------------+
| old localr(vm_addr) |
+----------------------------+
| old upvalr(vm_upval) |
+----------------------------+
| local scope(nasal_ref) |
| ... |
+----------------------------+ <- local pointer stored in localr
| old funcr(vm_func) | <- old function stored in funcr
+----------------------------+
+--------------------------+(协程操作数栈)
| nil(vm_nil) | <- push nil
+--------------------------+
| old pc(vm_ret) |
+--------------------------+
| old localr(vm_addr) |
+--------------------------+
| old upvalr(vm_upval) |
+--------------------------+
| local scope(nas_ref) |
| ... |
+--------------------------+ <- local pointer stored in localr
| old funcr(vm_func) | <- old function stored in funcr
+--------------------------+
```
当`builtin_coyield`执行完毕之后,栈又切换到了主操作数栈上,这时可以看到返回的`local[1]`实际上被`op_callb`放在了这里的栈顶:
```C++
+----------------------------+(主操作数栈)
| return_value(nasal_ref) |
+----------------------------+
| old pc(vm_ret) |
+----------------------------+
| old localr(vm_addr) |
+----------------------------+
| old upvalr(vm_upval) |
+----------------------------+
| local scope(nasal_ref) |
| ... |
+----------------------------+ <- local pointer stored in localr
| old funcr(vm_func) | <- old function stored in funcr
+----------------------------+
+--------------------------+(主操作数栈)
| return_value(nas_ref) |
+--------------------------+
| old pc(vm_ret) |
+--------------------------+
| old localr(vm_addr) |
+--------------------------+
| old upvalr(vm_upval) |
+--------------------------+
| local scope(nas_ref) |
| ... |
+--------------------------+ <- local pointer stored in localr
| old funcr(vm_func) | <- old function stored in funcr
+--------------------------+
```
所以主程序会认为顶部这个返回值好像是`resume`返回的。而实际上`resume`的返回值在协程的操作数栈顶。综上所述:

View File

@ -34,6 +34,7 @@ void help()
<<" -e, --exec | execute.\n"
<<" -t, --time | execute and get the running time.\n"
<<" -o, --opcnt | execute and count used operands.\n"
<<" | this options is available in debug mode.\n"
<<" -d, --detail | execute and get detail crash info.\n"
<<" | get garbage collector info if didn't crash.\n"
<<" -op, --optimize| use optimizer(beta).\n"
@ -70,7 +71,7 @@ void err()
std::exit(1);
}
void execute(const std::string& file,const std::vector<std::string>& argv,const u32 cmd)
void execute(const string& file,const std::vector<string>& argv,const u32 cmd)
{
// front end use the same error module
nasal_err nerr;
@ -104,18 +105,18 @@ void execute(const std::string& file,const std::vector<std::string>& argv,const
// run bytecode
if(cmd&VM_DEBUG)
{
nasal_dbg debugger;
debugger.run(gen,linker,argv);
nasal_dbg debugger(nerr);
debugger.run(gen,linker,argv,cmd&VM_OPCALLNUM);
}
else if(cmd&VM_EXECTIME)
{
auto start=std::chrono::high_resolution_clock::now();
vm.run(gen,linker,argv,cmd&VM_OPCALLNUM,cmd&VM_DBGINFO);
vm.run(gen,linker,argv,cmd&VM_DBGINFO);
auto end=std::chrono::high_resolution_clock::now();
std::clog<<"process exited after "<<(end-start).count()*1.0/std::chrono::high_resolution_clock::duration::period::den<<"s.\n";
}
else if(cmd&VM_EXEC)
vm.run(gen,linker,argv,cmd&VM_OPCALLNUM,cmd&VM_DBGINFO);
vm.run(gen,linker,argv,cmd&VM_DBGINFO);
}
int main(int argc,const char* argv[])
@ -127,7 +128,7 @@ int main(int argc,const char* argv[])
}
if(argc==2)
{
std::string s(argv[1]);
string s(argv[1]);
if(s=="-v" || s=="--version")
logo();
else if(s=="-h" || s=="--help")
@ -138,7 +139,7 @@ int main(int argc,const char* argv[])
err();
return 0;
}
std::unordered_map<std::string,u32> cmdlst={
std::unordered_map<string,u32> cmdlst={
{"--lex",VM_LEXINFO},{"-l",VM_LEXINFO},
{"--ast",VM_ASTINFO},{"-a",VM_ASTINFO},
{"--code",VM_CODEINFO},{"-c",VM_CODEINFO},
@ -150,8 +151,8 @@ int main(int argc,const char* argv[])
{"--debug",VM_DEBUG},{"-dbg",VM_DEBUG}
};
u32 cmd=0;
std::string filename;
std::vector<std::string> vm_argv;
string filename;
std::vector<string> vm_argv;
for(int i=1;i<argc;++i)
{
if(cmdlst.count(argv[i]))

View File

@ -37,7 +37,7 @@ test:nasal
@ ./nasal -op -e -d test/calc.nas
@ ./nasal -op -e test/choice.nas
@ ./nasal -op -e test/class.nas
@ ./nasal -op -d -o test/coroutine.nas
@ ./nasal -op -d test/coroutine.nas
@ ./nasal -op -e test/diff.nas
-@ ./nasal -op -d test/exception.nas
@ ./nasal -op -t -d test/fib.nas
@ -51,8 +51,8 @@ test:nasal
@ ./nasal -op -t test/loop.nas
@ ./nasal -op -t -d test/mandel.nas
@ ./nasal -op -t -d test/mandelbrot.nas
@ ./nasal -op -t -d -o test/md5.nas
-@ ./nasal -op -t -d -o test/md5compare.nas
@ ./nasal -op -t -d test/md5.nas
-@ ./nasal -op -t -d test/md5compare.nas
-@ ./nasal -op -d test/module_test.nas
@ ./nasal -op -e test/nasal_test.nas
@ ./nasal -op -c test/occupation.nas
@ -65,6 +65,6 @@ test:nasal
@ ./nasal -op -c -e test/trait.nas
-@ ./nasal -op -c -t test/tetris.nas
@ ./nasal -op -c -t -d test/turingmachine.nas
@ ./nasal -op -c -t -d -o test/ycombinator.nas
@ ./nasal -op -d -o test/wavecollapse.nas
@ ./nasal -op -c -t -d test/ycombinator.nas
@ ./nasal -op -d test/wavecollapse.nas

View File

@ -6,20 +6,20 @@ double fibonaci(double x){
return x;
return fibonaci(x-1)+fibonaci(x-2);
}
extern "C" nasal_ref fib(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref fib(std::vector<nas_ref>& args,nasal_gc& gc){
std::cout<<"[mod] this is the first test module of nasal\n";
if(!args.size())
return builtin_err("fib","lack arguments");
nasal_ref num=args[0];
nas_ref num=args[0];
if(num.type!=vm_num)
return builtin_err("extern_fib","\"num\" must be number");
return {vm_num,fibonaci(num.tonum())};
}
extern "C" nasal_ref quick_fib(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref quick_fib(std::vector<nas_ref>& args,nasal_gc& gc){
std::cout<<"[mod] this is the first test module of nasal\n";
if(!args.size())
return builtin_err("fib","lack arguments");
nasal_ref num=args[0];
nas_ref num=args[0];
if(num.type!=vm_num)
return builtin_err("extern_quick_fib","\"num\" must be number");
if(num.num()<2)

View File

@ -70,13 +70,13 @@ public:
};
noecho_input this_window;
extern "C" nasal_ref nas_getch(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref nas_getch(std::vector<nas_ref>& args,nasal_gc& gc){
return {vm_num,(double)this_window.noecho_getch()};
}
extern "C" nasal_ref nas_kbhit(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref nas_kbhit(std::vector<nas_ref>& args,nasal_gc& gc){
return {vm_num,(double)this_window.noecho_kbhit()};
}
extern "C" nasal_ref nas_noblock(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref nas_noblock(std::vector<nas_ref>& args,nasal_gc& gc){
if(this_window.noecho_kbhit())
return {vm_num,(double)this_window.noecho_getch()};
return nil;

View File

@ -24,14 +24,14 @@ static WSAmanager win;
#include <netinet/in.h>
#endif
extern "C" nasal_ref nas_socket(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref nas_socket(std::vector<nas_ref>& args,nasal_gc& gc){
if(args[0].type!=vm_num || args[1].type!=vm_num || args[2].type!=vm_num)
return builtin_err("socket","\"af\", \"type\", \"protocol\" should be number");
int sd=socket(args[0].num(),args[1].num(),args[2].num());
return {vm_num,(double)sd};
}
extern "C" nasal_ref nas_closesocket(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref nas_closesocket(std::vector<nas_ref>& args,nasal_gc& gc){
if(args[0].type!=vm_num)
return builtin_err("closesocket","\"\" should be number");
#ifdef _WIN32
@ -41,7 +41,7 @@ extern "C" nasal_ref nas_closesocket(std::vector<nasal_ref>& args,nasal_gc& gc){
#endif
}
extern "C" nasal_ref nas_shutdown(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref nas_shutdown(std::vector<nas_ref>& args,nasal_gc& gc){
if(args[0].type!=vm_num)
return builtin_err("shutdown","\"sd\" must be a number");
if(args[1].type!=vm_num)
@ -49,7 +49,7 @@ extern "C" nasal_ref nas_shutdown(std::vector<nasal_ref>& args,nasal_gc& gc){
return {vm_num,(double)shutdown(args[0].num(),args[1].num())};
}
extern "C" nasal_ref nas_bind(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref nas_bind(std::vector<nas_ref>& args,nasal_gc& gc){
if(args[0].type!=vm_num)
return builtin_err("bind","\"sd\" muse be a number");
if(args[1].type!=vm_str)
@ -64,7 +64,7 @@ extern "C" nasal_ref nas_bind(std::vector<nasal_ref>& args,nasal_gc& gc){
return {vm_num,(double)bind(args[0].num(),(sockaddr*)&server,sizeof(server))};
}
extern "C" nasal_ref nas_listen(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref nas_listen(std::vector<nas_ref>& args,nasal_gc& gc){
if(args[0].type!=vm_num)
return builtin_err("listen","\"sd\" must be a number");
if(args[1].type!=vm_num)
@ -72,7 +72,7 @@ extern "C" nasal_ref nas_listen(std::vector<nasal_ref>& args,nasal_gc& gc){
return{vm_num,(double)listen(args[0].num(),args[1].num())};
}
extern "C" nasal_ref nas_connect(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref nas_connect(std::vector<nas_ref>& args,nasal_gc& gc){
if(args[0].type!=vm_num)
return builtin_err("connect","\"sd\" must be a number");
if(args[1].type!=vm_str)
@ -88,7 +88,7 @@ extern "C" nasal_ref nas_connect(std::vector<nasal_ref>& args,nasal_gc& gc){
return {vm_num,(double)connect(args[0].num(),(sockaddr*)&addr,sizeof(sockaddr_in))};
}
extern "C" nasal_ref nas_accept(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref nas_accept(std::vector<nas_ref>& args,nasal_gc& gc){
if(args[0].type!=vm_num)
return builtin_err("accept","\"sd\" must be a number");
sockaddr_in client;
@ -98,7 +98,7 @@ extern "C" nasal_ref nas_accept(std::vector<nasal_ref>& args,nasal_gc& gc){
#else
int client_sd=accept(args[0].num(),(sockaddr*)&client,(socklen_t*)&socklen);
#endif
nasal_ref res=gc.temp=gc.alloc(vm_hash);
nas_ref res=gc.temp=gc.alloc(vm_hash);
auto& hash=res.hash().elems;
hash["sd"]={vm_num,(double)client_sd};
hash["ip"]=gc.newstr(inet_ntoa(client.sin_addr));
@ -106,7 +106,7 @@ extern "C" nasal_ref nas_accept(std::vector<nasal_ref>& args,nasal_gc& gc){
return res;
}
extern "C" nasal_ref nas_send(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref nas_send(std::vector<nas_ref>& args,nasal_gc& gc){
if(args[0].type!=vm_num)
return builtin_err("send","\"sd\" must be a number");
if(args[1].type!=vm_str)
@ -116,7 +116,7 @@ extern "C" nasal_ref nas_send(std::vector<nasal_ref>& args,nasal_gc& gc){
return {vm_num,(double)send(args[0].num(),args[1].str().c_str(),args[1].str().length(),args[2].num())};
}
extern "C" nasal_ref nas_sendto(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref nas_sendto(std::vector<nas_ref>& args,nasal_gc& gc){
if(args[0].type!=vm_num)
return builtin_err("sendto","\"sd\" must be a number");
if(args[1].type!=vm_str)
@ -136,7 +136,7 @@ extern "C" nasal_ref nas_sendto(std::vector<nasal_ref>& args,nasal_gc& gc){
return {vm_num,(double)sendto(args[0].num(),args[3].str().c_str(),args[3].str().length(),args[4].num(),(sockaddr*)&addr,sizeof(sockaddr_in))};
}
extern "C" nasal_ref nas_recv(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref nas_recv(std::vector<nas_ref>& args,nasal_gc& gc){
if(args[0].type!=vm_num)
return builtin_err("recv","\"sd\" must be a number");
if(args[1].type!=vm_num)
@ -145,7 +145,7 @@ extern "C" nasal_ref nas_recv(std::vector<nasal_ref>& args,nasal_gc& gc){
return builtin_err("recv","\"len\" out of range");
if(args[2].type!=vm_num)
return builtin_err("recv","\"flags\" muse be a number");
nasal_ref res=gc.temp=gc.alloc(vm_hash);
nas_ref res=gc.temp=gc.alloc(vm_hash);
auto& hash=res.hash().elems;
char* buf=new char[(int)args[1].num()];
hash["size"]={vm_num,(double)recv(args[0].num(),buf,args[1].num(),args[2].num())};
@ -155,7 +155,7 @@ extern "C" nasal_ref nas_recv(std::vector<nasal_ref>& args,nasal_gc& gc){
return res;
}
extern "C" nasal_ref nas_recvfrom(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref nas_recvfrom(std::vector<nas_ref>& args,nasal_gc& gc){
if(args[0].type!=vm_num)
return builtin_err("recvfrom","\"sd\" must be a number");
if(args[1].type!=vm_num)
@ -166,7 +166,7 @@ extern "C" nasal_ref nas_recvfrom(std::vector<nasal_ref>& args,nasal_gc& gc){
return builtin_err("recvfrom","\"flags\" muse be a number");
sockaddr_in addr;
int socklen=sizeof(sockaddr_in);
nasal_ref res=gc.temp=gc.alloc(vm_hash);
nas_ref res=gc.temp=gc.alloc(vm_hash);
auto& hash=res.hash().elems;
char* buf=new char[(int)args[1].num()+1];
#ifdef _WIN32
@ -182,6 +182,6 @@ extern "C" nasal_ref nas_recvfrom(std::vector<nasal_ref>& args,nasal_gc& gc){
return res;
}
extern "C" nasal_ref nas_errno(std::vector<nasal_ref>& args,nasal_gc& gc){
extern "C" nas_ref nas_errno(std::vector<nas_ref>& args,nasal_gc& gc){
return gc.newstr(strerror(errno));
}

13
nasal.h
View File

@ -42,13 +42,13 @@
using i32=std::int32_t;
using i64=std::int64_t;
using u8 =std::uint8_t;
using u8=std::uint8_t;
using u16=std::uint16_t;
using u32=std::uint32_t;
using u64=std::uint64_t;
using usize=std::size_t;
using f64=double;
using std::string;
const u32 STACK_DEPTH=2048;
@ -145,14 +145,15 @@ int utf8_hdchk(const char head)
return 0;
}
std::string chrhex(const char c)
string chrhex(const char c)
{
return {"0123456789abcdef"[(c&0xf0)>>4],"0123456789abcdef"[c&0x0f]};
const char hextbl[]="0123456789abcdef";
return {hextbl[(c&0xf0)>>4],hextbl[c&0x0f]};
}
std::string rawstr(const std::string& str,const usize maxlen=0)
string rawstr(const string& str,const usize maxlen=0)
{
std::string ret("");
string ret("");
for(auto i:str)
{
#ifdef _WIN32

View File

@ -1,7 +1,7 @@
#ifndef __NASAL_AST_H__
#define __NASAL_AST_H__
enum ast_node
enum ast_node:u32
{
ast_null=0, // null node
ast_root, // mark the root node of ast
@ -132,7 +132,7 @@ private:
u32 _line;
u32 _type;
f64 _num;
std::string _str;
string _str;
std::vector<nasal_ast> _child;
public:
nasal_ast(const u32 l=0,const u32 t=ast_null):_line(l),_type(t),_num(0){}
@ -151,13 +151,13 @@ public:
void add(const nasal_ast& ast){_child.push_back(ast);}
void set_line(const u32 l){_line=l;}
void set_type(const u32 t){_type=t;}
void set_str(const std::string& s){_str=s;}
void set_str(const string& s){_str=s;}
void set_num(const f64 n){_num=n;}
inline u32 line() const {return _line;}
inline u32 type() const {return _type;}
inline f64 num() const {return _num;}
inline const std::string& str() const {return _str;}
inline const string& str() const {return _str;}
inline const std::vector<nasal_ast>& child() const {return _child;}
inline std::vector<nasal_ast>& child(){return _child;}
};
@ -210,7 +210,7 @@ void nasal_ast::clear()
void nasal_ast::print(int depth,bool last=false)
{
static std::vector<std::string> intentation={};
static std::vector<string> intentation={};
for(auto& i:intentation)
std::cout<<i;
std::cout<<ast_name[_type];

File diff suppressed because it is too large Load Diff

View File

@ -182,13 +182,13 @@ struct opcode
}
void print(const char*,
const f64*,
const std::string*,
const string*,
const u32,bool) const;
};
void opcode::print(const char* header,
const f64* constnum,
const std::string* conststr,
const string* conststr,
const u32 index,
bool deftnum=false) const
{
@ -227,7 +227,7 @@ void opcode::print(const char* header,
std::cout<<std::hex<<"0x"<<num<<std::dec;break;
case op_callb:
std::cout<<std::hex<<"0x"<<num<<" <"<<builtin[num].name
<<"@"<<(void*)builtin[num].func<<std::dec<<">";break;
<<"@0x"<<(u64)builtin[num].func<<std::dec<<">";break;
case op_upval: case op_mupval: case op_loadu:
std::cout<<std::hex<<"0x"<<((num>>16)&0xffff)
<<"[0x"<<(num&0xffff)<<"]"<<std::dec;break;
@ -246,32 +246,32 @@ class nasal_codegen
private:
u16 fileindex;
nasal_err& nerr;
const std::string* file;
const string* file;
std::stack<u32> in_iterloop;
std::unordered_map<f64,u32> num_table;
std::unordered_map<std::string,u32> str_table;
std::unordered_map<string,u32> str_table;
std::vector<f64> num_res;
std::vector<std::string> str_res;
std::vector<string> str_res;
std::vector<opcode> code;
std::list<std::vector<int>> continue_ptr;
std::list<std::vector<int>> break_ptr;
// global : max 4095 values
std::unordered_map<std::string,int> global;
std::unordered_map<string,int> global;
// local : max 32768 upvalues 65536 values
std::list<std::unordered_map<std::string,int>> local;
std::list<std::unordered_map<string,int>> local;
// func end stack, reserved for code print
std::stack<u32> fbstk;
std::stack<u32> festk;
void die(const std::string&,const u32);
void die(const string&,const u32);
void regist_num(const f64);
void regist_str(const std::string&);
void regist_str(const string&);
void find_symbol(const nasal_ast&);
void add_sym(const std::string&);
int local_find(const std::string&);
int global_find(const std::string&);
int upvalue_find(const std::string&);
void add_sym(const string&);
int local_find(const string&);
int global_find(const string&);
int upvalue_find(const string&);
void gen(u8,u32,u32);
void num_gen(const nasal_ast&);
void str_gen(const nasal_ast&);
@ -310,12 +310,12 @@ public:
nasal_codegen(nasal_err& e):fileindex(0),nerr(e),file(nullptr){}
void compile(const nasal_parse&,const nasal_import&);
void print();
const std::vector<std::string>& strs() const {return str_res;}
const std::vector<f64>& nums() const {return num_res;}
const std::vector<opcode>& codes() const {return code;}
const std::vector<string>& strs() const {return str_res;}
const std::vector<f64>& nums() const {return num_res;}
const std::vector<opcode>& codes() const {return code;}
};
void nasal_codegen::die(const std::string& info,const u32 line)
void nasal_codegen::die(const string& info,const u32 line)
{
nerr.load(file[fileindex]);
nerr.err("code",line,info);
@ -331,7 +331,7 @@ void nasal_codegen::regist_num(const f64 num)
}
}
void nasal_codegen::regist_str(const std::string& str)
void nasal_codegen::regist_str(const string& str)
{
if(!str_table.count(str))
{
@ -366,7 +366,7 @@ void nasal_codegen::find_symbol(const nasal_ast& node)
find_symbol(i);
}
void nasal_codegen::add_sym(const std::string& name)
void nasal_codegen::add_sym(const string& name)
{
if(local.empty())
{
@ -382,19 +382,19 @@ void nasal_codegen::add_sym(const std::string& name)
local.back()[name]=index;
}
int nasal_codegen::local_find(const std::string& name)
int nasal_codegen::local_find(const string& name)
{
if(local.empty())
return -1;
return local.back().count(name)?local.back()[name]:-1;
}
int nasal_codegen::global_find(const std::string& name)
int nasal_codegen::global_find(const string& name)
{
return global.count(name)?global[name]:-1;
}
int nasal_codegen::upvalue_find(const std::string& name)
int nasal_codegen::upvalue_find(const string& name)
{
// 32768 level 65536 upvalues
int index=-1;
@ -439,7 +439,7 @@ void nasal_codegen::hash_gen(const nasal_ast& ast)
for(auto& node:ast.child())
{
calc_gen(node[1]);
const std::string& str=node[0].str();
const string& str=node[0].str();
regist_str(str);
gen(op_happ,str_table[str],node.line());
}
@ -462,7 +462,7 @@ void nasal_codegen::func_gen(const nasal_ast& ast)
// generate parameter list
for(auto& tmp:ast[0].child())
{
const std::string& str=tmp.str();
const string& str=tmp.str();
if(str=="me")
die("\"me\" should not be a parameter",tmp.line());
regist_str(str);
@ -522,7 +522,7 @@ void nasal_codegen::call_gen(const nasal_ast& ast)
void nasal_codegen::call_id(const nasal_ast& ast)
{
const std::string& str=ast.str();
const string& str=ast.str();
for(u32 i=0;builtin[i].name;++i)
if(builtin[i].name==str)
{
@ -640,7 +640,7 @@ void nasal_codegen::mcall(const nasal_ast& ast)
void nasal_codegen::mcall_id(const nasal_ast& ast)
{
const std::string& str=ast.str();
const string& str=ast.str();
for(u32 i=0;builtin[i].name;++i)
if(builtin[i].name==str)
{
@ -680,7 +680,7 @@ void nasal_codegen::mcall_hash(const nasal_ast& ast)
void nasal_codegen::single_def(const nasal_ast& ast)
{
const std::string& str=ast[0].str();
const string& str=ast[0].str();
calc_gen(ast[1]);
local.empty()?
gen(op_loadg,global_find(str),ast.line()):
@ -696,7 +696,7 @@ void nasal_codegen::multi_def(const nasal_ast& ast)
for(int i=0;i<size;++i)
{
calc_gen(vals[i]);
const std::string& str=ids[i].str();
const string& str=ids[i].str();
local.empty()?
gen(op_loadg,global_find(str),ids[i].line()):
gen(op_loadl,local_find(str),ids[i].line());
@ -708,7 +708,7 @@ void nasal_codegen::multi_def(const nasal_ast& ast)
for(int i=0;i<size;++i)
{
gen(op_callvi,i,ast[1].line());
const std::string& str=ids[i].str();
const string& str=ids[i].str();
local.empty()?
gen(op_loadg,global_find(str),ids[i].line()):
gen(op_loadl,local_find(str),ids[i].line());
@ -966,7 +966,7 @@ void nasal_codegen::forindex_gen(const nasal_ast& ast)
gen(op_findex,0,ast.line());
if(ast[0].type()==ast_iter) // define a new iterator
{
const std::string& str=ast[0][0].str();
const string& str=ast[0][0].str();
local.empty()?
gen(op_loadg,global_find(str),ast[0][0].line()):
gen(op_loadl,local_find(str),ast[0][0].line());
@ -1000,7 +1000,7 @@ void nasal_codegen::foreach_gen(const nasal_ast& ast)
gen(op_feach,0,ast.line());
if(ast[0].type()==ast_iter) // define a new iterator
{
const std::string& str=ast[0][0].str();
const string& str=ast[0][0].str();
local.empty()?
gen(op_loadg,global_find(str),ast[0][0].line()):
gen(op_loadl,local_find(str),ast[0][0].line());

View File

@ -6,34 +6,37 @@
class nasal_dbg:public nasal_vm
{
private:
bool next_step;
bool next;
usize fsize;
u16 bk_fidx;
u32 bk_line;
fstreamline src;
u16 bk_fidx;
u32 bk_line;
nasal_err& src;
std::vector<std::string> parse(const std::string&);
u16 fileindex(const std::string&);
std::vector<string> parse(const string&);
u16 fileindex(const string&);
void err();
void help();
void opcallsort(const u64*);
void stepinfo();
void interact();
public:
nasal_dbg():
next_step(false),fsize(0),
bk_fidx(0),bk_line(0){}
nasal_dbg(nasal_err& nerr):
next(false),fsize(0),
bk_fidx(0),bk_line(0),
src(nerr){}
void run(
const nasal_codegen&,
const nasal_import&,
const std::vector<std::string>&
const std::vector<string>&,
bool
);
};
std::vector<std::string> nasal_dbg::parse(const std::string& cmd)
std::vector<string> nasal_dbg::parse(const string& cmd)
{
std::vector<std::string> res;
std::vector<string> res;
usize last=0,pos=cmd.find(" ",0);
while(pos!=std::string::npos)
while(pos!=string::npos)
{
if(pos>last)
res.push_back(cmd.substr(last,pos-last));
@ -45,7 +48,7 @@ std::vector<std::string> nasal_dbg::parse(const std::string& cmd)
return res;
}
u16 nasal_dbg::fileindex(const std::string& filename)
u16 nasal_dbg::fileindex(const string& filename)
{
for(u16 i=0;i<fsize;++i)
if(filename==files[i])
@ -79,6 +82,34 @@ void nasal_dbg::help()
<<"\tbk, break | set break point\n";
}
void nasal_dbg::opcallsort(const u64* arr)
{
typedef std::pair<u32,u64> op;
std::vector<op> opcall;
u64 total=0;
for(u32 i=0;i<op_ret+1;++i)
{
total+=arr[i];
opcall.push_back({i,arr[i]});
}
std::sort(opcall.begin(),opcall.end(),
[](const op& a,const op& b){return a.second>b.second;}
);
std::clog<<"\noperands call info";
for(auto& i:opcall)
{
u64 rate=i.second*100/total;
if(!rate)
{
std::clog<<"\n ...";
break;
}
std::clog<<"\n "<<code_table[i.first].name
<<" : "<<i.second<<" ("<<rate<<"%)";
}
std::clog<<"\n total : "<<total<<'\n';
}
void nasal_dbg::stepinfo()
{
u32 begin,end;
@ -111,11 +142,11 @@ void nasal_dbg::interact()
if(
(bytecode[pc].fidx!=bk_fidx || bytecode[pc].line!=bk_line) && // break point
!next_step // next step
!next // next step
)return;
next_step=false;
std::string cmd;
next=false;
string cmd;
stepinfo();
while(1)
{
@ -134,19 +165,18 @@ void nasal_dbg::interact()
for(usize i=0;i<fsize;++i)
std::cout<<"["<<i<<"] "<<files[i]<<"\n";
else if(res[0]=="g" || res[0]=="global")
global_state();
else if(res[0]=="l" || res[0]=="local"){
local_state();
}
gstate();
else if(res[0]=="l" || res[0]=="local")
lstate();
else if(res[0]=="u" || res[0]=="upval")
upval_state();
ustate();
else if(res[0]=="r" || res[0]=="register")
register_info();
reginfo();
else if(res[0]=="a" || res[0]=="all")
detail();
else if(res[0]=="n" || res[0]=="next")
{
next_step=true;
next=true;
return;
}
else if(res[0]=="q" || res[0]=="exit")
@ -176,11 +206,13 @@ void nasal_dbg::interact()
void nasal_dbg::run(
const nasal_codegen& gen,
const nasal_import& linker,
const std::vector<std::string>& argv)
const std::vector<string>& argv,
bool opcnt)
{
detail_info=true;
fsize=linker.filelist().size();
init(gen.strs(),gen.nums(),gen.codes(),linker.filelist(),argv);
u64 count[op_ret+1]={0};
#ifndef _MSC_VER
const void* oprs[]=
{
@ -216,54 +248,55 @@ void nasal_dbg::run(
typedef void (nasal_dbg::*nafunc)();
const nafunc oprs[]=
{
nullptr, &nasal_dbg::opr_intg,
&nasal_dbg::opr_intl, &nasal_dbg::opr_loadg,
&nasal_dbg::opr_loadl, &nasal_dbg::opr_loadu,
&nasal_dbg::opr_pnum, &nasal_dbg::opr_pnil,
&nasal_dbg::opr_pstr, &nasal_dbg::opr_newv,
&nasal_dbg::opr_newh, &nasal_dbg::opr_newf,
&nasal_dbg::opr_happ, &nasal_dbg::opr_para,
&nasal_dbg::opr_deft, &nasal_dbg::opr_dyn,
&nasal_dbg::opr_unot, &nasal_dbg::opr_usub,
&nasal_dbg::opr_add, &nasal_dbg::opr_sub,
&nasal_dbg::opr_mul, &nasal_dbg::opr_div,
&nasal_dbg::opr_lnk, &nasal_dbg::opr_addc,
&nasal_dbg::opr_subc, &nasal_dbg::opr_mulc,
&nasal_dbg::opr_divc, &nasal_dbg::opr_lnkc,
&nasal_dbg::opr_addeq, &nasal_dbg::opr_subeq,
&nasal_dbg::opr_muleq, &nasal_dbg::opr_diveq,
&nasal_dbg::opr_lnkeq, &nasal_dbg::opr_addeqc,
&nasal_dbg::opr_subeqc, &nasal_dbg::opr_muleqc,
&nasal_dbg::opr_diveqc, &nasal_dbg::opr_lnkeqc,
&nasal_dbg::opr_meq, &nasal_dbg::opr_eq,
&nasal_dbg::opr_neq, &nasal_dbg::opr_less,
&nasal_dbg::opr_leq, &nasal_dbg::opr_grt,
&nasal_dbg::opr_geq, &nasal_dbg::opr_lessc,
&nasal_dbg::opr_leqc, &nasal_dbg::opr_grtc,
&nasal_dbg::opr_geqc, &nasal_dbg::opr_pop,
&nasal_dbg::opr_jmp, &nasal_dbg::opr_jt,
&nasal_dbg::opr_jf, &nasal_dbg::opr_cnt,
&nasal_dbg::opr_findex, &nasal_dbg::opr_feach,
&nasal_dbg::opr_callg, &nasal_dbg::opr_calll,
&nasal_dbg::opr_upval, &nasal_dbg::opr_callv,
&nasal_dbg::opr_callvi, &nasal_dbg::opr_callh,
&nasal_dbg::opr_callfv, &nasal_dbg::opr_callfh,
&nasal_dbg::opr_callb, &nasal_dbg::opr_slcbeg,
&nasal_dbg::opr_slcend, &nasal_dbg::opr_slc,
&nasal_dbg::opr_slc2, &nasal_dbg::opr_mcallg,
&nasal_dbg::opr_mcalll, &nasal_dbg::opr_mupval,
&nasal_dbg::opr_mcallv, &nasal_dbg::opr_mcallh,
&nasal_dbg::opr_ret
nullptr, &nasal_dbg::o_intg,
&nasal_dbg::o_intl, &nasal_dbg::o_loadg,
&nasal_dbg::o_loadl, &nasal_dbg::o_loadu,
&nasal_dbg::o_pnum, &nasal_dbg::o_pnil,
&nasal_dbg::o_pstr, &nasal_dbg::o_newv,
&nasal_dbg::o_newh, &nasal_dbg::o_newf,
&nasal_dbg::o_happ, &nasal_dbg::o_para,
&nasal_dbg::o_deft, &nasal_dbg::o_dyn,
&nasal_dbg::o_unot, &nasal_dbg::o_usub,
&nasal_dbg::o_add, &nasal_dbg::o_sub,
&nasal_dbg::o_mul, &nasal_dbg::o_div,
&nasal_dbg::o_lnk, &nasal_dbg::o_addc,
&nasal_dbg::o_subc, &nasal_dbg::o_mulc,
&nasal_dbg::o_divc, &nasal_dbg::o_lnkc,
&nasal_dbg::o_addeq, &nasal_dbg::o_subeq,
&nasal_dbg::o_muleq, &nasal_dbg::o_diveq,
&nasal_dbg::o_lnkeq, &nasal_dbg::o_addeqc,
&nasal_dbg::o_subeqc, &nasal_dbg::o_muleqc,
&nasal_dbg::o_diveqc, &nasal_dbg::o_lnkeqc,
&nasal_dbg::o_meq, &nasal_dbg::o_eq,
&nasal_dbg::o_neq, &nasal_dbg::o_less,
&nasal_dbg::o_leq, &nasal_dbg::o_grt,
&nasal_dbg::o_geq, &nasal_dbg::o_lessc,
&nasal_dbg::o_leqc, &nasal_dbg::o_grtc,
&nasal_dbg::o_geqc, &nasal_dbg::o_pop,
&nasal_dbg::o_jmp, &nasal_dbg::o_jt,
&nasal_dbg::o_jf, &nasal_dbg::o_cnt,
&nasal_dbg::o_findex, &nasal_dbg::o_feach,
&nasal_dbg::o_callg, &nasal_dbg::o_calll,
&nasal_dbg::o_upval, &nasal_dbg::o_callv,
&nasal_dbg::o_callvi, &nasal_dbg::o_callh,
&nasal_dbg::o_callfv, &nasal_dbg::o_callfh,
&nasal_dbg::o_callb, &nasal_dbg::o_slcbeg,
&nasal_dbg::o_slcend, &nasal_dbg::o_slc,
&nasal_dbg::o_slc2, &nasal_dbg::o_mcallg,
&nasal_dbg::o_mcalll, &nasal_dbg::o_mupval,
&nasal_dbg::o_mcallv, &nasal_dbg::o_mcallh,
&nasal_dbg::o_ret
};
std::vector<nafunc> code;
std::vector<u32> code;
for(auto& i:gen.codes())
{
code.push_back(oprs[i.op]);
code.push_back(i.op);
imm.push_back(i.num);
}
while(code[pc]){
while(oprs[code[pc]]){
interact();
(this->*code[pc])();
++count[code[pc]];
(this->*oprs[code[pc]])();
if(top>=canary)
break;
++pc;
@ -273,87 +306,95 @@ void nasal_dbg::run(
vmexit:
if(top>=canary)
die("stack overflow");
if(opcnt)
opcallsort(count);
gc.clear();
imm.clear();
std::cout<<"[debug] debugger exited\n";
return;
#ifndef _MSC_VER
#define dbg(op) {interact();op();if(top<canary)goto *code[++pc];goto vmexit;}
#define dbg(op,num) {\
interact();\
op();\
++count[num];\
if(top<canary)\
goto *code[++pc];\
goto vmexit;}
intg: dbg(opr_intg );
intl: dbg(opr_intl );
loadg: dbg(opr_loadg );
loadl: dbg(opr_loadl );
loadu: dbg(opr_loadu );
pnum: dbg(opr_pnum );
pnil: dbg(opr_pnil );
pstr: dbg(opr_pstr );
newv: dbg(opr_newv );
newh: dbg(opr_newh );
newf: dbg(opr_newf );
happ: dbg(opr_happ );
para: dbg(opr_para );
deft: dbg(opr_deft );
dyn: dbg(opr_dyn );
unot: dbg(opr_unot );
usub: dbg(opr_usub );
add: dbg(opr_add );
sub: dbg(opr_sub );
mul: dbg(opr_mul );
div: dbg(opr_div );
lnk: dbg(opr_lnk );
addc: dbg(opr_addc );
subc: dbg(opr_subc );
mulc: dbg(opr_mulc );
divc: dbg(opr_divc );
lnkc: dbg(opr_lnkc );
addeq: dbg(opr_addeq );
subeq: dbg(opr_subeq );
muleq: dbg(opr_muleq );
diveq: dbg(opr_diveq );
lnkeq: dbg(opr_lnkeq );
addeqc: dbg(opr_addeqc);
subeqc: dbg(opr_subeqc);
muleqc: dbg(opr_muleqc);
diveqc: dbg(opr_diveqc);
lnkeqc: dbg(opr_lnkeqc);
meq: dbg(opr_meq );
eq: dbg(opr_eq );
neq: dbg(opr_neq );
less: dbg(opr_less );
leq: dbg(opr_leq );
grt: dbg(opr_grt );
geq: dbg(opr_geq );
lessc: dbg(opr_lessc );
leqc: dbg(opr_leqc );
grtc: dbg(opr_grtc );
geqc: dbg(opr_geqc );
pop: dbg(opr_pop );
jmp: dbg(opr_jmp );
jt: dbg(opr_jt );
jf: dbg(opr_jf );
cnt: dbg(opr_cnt );
findex: dbg(opr_findex);
feach: dbg(opr_feach );
callg: dbg(opr_callg );
calll: dbg(opr_calll );
upval: dbg(opr_upval );
callv: dbg(opr_callv );
callvi: dbg(opr_callvi);
callh: dbg(opr_callh );
callfv: dbg(opr_callfv);
callfh: dbg(opr_callfh);
callb: dbg(opr_callb );
slcbeg: dbg(opr_slcbeg);
slcend: dbg(opr_slcend);
slc: dbg(opr_slc );
slc2: dbg(opr_slc2 );
mcallg: dbg(opr_mcallg);
mcalll: dbg(opr_mcalll);
mupval: dbg(opr_mupval);
mcallv: dbg(opr_mcallv);
mcallh: dbg(opr_mcallh);
ret: dbg(opr_ret );
intg: dbg(o_intg ,op_intg );
intl: dbg(o_intl ,op_intl );
loadg: dbg(o_loadg ,op_loadg );
loadl: dbg(o_loadl ,op_loadl );
loadu: dbg(o_loadu ,op_loadu );
pnum: dbg(o_pnum ,op_pnum );
pnil: dbg(o_pnil ,op_pnil );
pstr: dbg(o_pstr ,op_pstr );
newv: dbg(o_newv ,op_newv );
newh: dbg(o_newh ,op_newh );
newf: dbg(o_newf ,op_newf );
happ: dbg(o_happ ,op_happ );
para: dbg(o_para ,op_para );
deft: dbg(o_deft ,op_deft );
dyn: dbg(o_dyn ,op_dyn );
unot: dbg(o_unot ,op_unot );
usub: dbg(o_usub ,op_usub );
add: dbg(o_add ,op_add );
sub: dbg(o_sub ,op_sub );
mul: dbg(o_mul ,op_mul );
div: dbg(o_div ,op_div );
lnk: dbg(o_lnk ,op_lnk );
addc: dbg(o_addc ,op_addc );
subc: dbg(o_subc ,op_subc );
mulc: dbg(o_mulc ,op_mulc );
divc: dbg(o_divc ,op_divc );
lnkc: dbg(o_lnkc ,op_lnkc );
addeq: dbg(o_addeq ,op_addeq );
subeq: dbg(o_subeq ,op_subeq );
muleq: dbg(o_muleq ,op_muleq );
diveq: dbg(o_diveq ,op_diveq );
lnkeq: dbg(o_lnkeq ,op_lnkeq );
addeqc: dbg(o_addeqc,op_addeqc);
subeqc: dbg(o_subeqc,op_subeqc);
muleqc: dbg(o_muleqc,op_muleqc);
diveqc: dbg(o_diveqc,op_diveqc);
lnkeqc: dbg(o_lnkeqc,op_lnkeqc);
meq: dbg(o_meq ,op_meq );
eq: dbg(o_eq ,op_eq );
neq: dbg(o_neq ,op_neq );
less: dbg(o_less ,op_less );
leq: dbg(o_leq ,op_leq );
grt: dbg(o_grt ,op_grt );
geq: dbg(o_geq ,op_geq );
lessc: dbg(o_lessc ,op_lessc );
leqc: dbg(o_leqc ,op_leqc );
grtc: dbg(o_grtc ,op_grtc );
geqc: dbg(o_geqc ,op_geqc );
pop: dbg(o_pop ,op_pop );
jmp: dbg(o_jmp ,op_jmp );
jt: dbg(o_jt ,op_jt );
jf: dbg(o_jf ,op_jf );
cnt: dbg(o_cnt ,op_cnt );
findex: dbg(o_findex,op_findex);
feach: dbg(o_feach ,op_feach );
callg: dbg(o_callg ,op_callg );
calll: dbg(o_calll ,op_calll );
upval: dbg(o_upval ,op_upval );
callv: dbg(o_callv ,op_callv );
callvi: dbg(o_callvi,op_callvi);
callh: dbg(o_callh ,op_callh );
callfv: dbg(o_callfv,op_callfv);
callfh: dbg(o_callfh,op_callfh);
callb: dbg(o_callb ,op_callb );
slcbeg: dbg(o_slcbeg,op_slcbeg);
slcend: dbg(o_slcend,op_slcend);
slc: dbg(o_slc ,op_slc );
slc2: dbg(o_slc2 ,op_slc2 );
mcallg: dbg(o_mcallg,op_mcallg);
mcalll: dbg(o_mcalll,op_mcalll);
mupval: dbg(o_mupval,op_mupval);
mcallv: dbg(o_mcallv,op_mcallv);
mcallh: dbg(o_mcallh,op_mcallh);
ret: dbg(o_ret ,op_ret );
#endif
}

View File

@ -8,10 +8,10 @@
class fstreamline
{
protected:
std::string file;
std::vector<std::string> res;
string file;
std::vector<string> res;
public:
void load(const std::string& f)
void load(const string& f)
{
if(file==f) // don't need to load a loaded file
return;
@ -23,7 +23,7 @@ public:
std::cerr<<"[src] cannot open file <"<<f<<">\n";
std::exit(1);
}
std::string line;
string line;
while(!fin.eof())
{
std::getline(fin,line);
@ -32,11 +32,11 @@ public:
}
void clear()
{
std::vector<std::string> tmp;
std::vector<string> tmp;
res.swap(tmp);
}
const std::string& operator[](const u32 line){return res[line];}
const std::string& name(){return file;}
const string& operator[](const u32 line){return res[line];}
const string& name(){return file;}
usize size(){return res.size();}
};
@ -46,21 +46,21 @@ private:
u32 error;
public:
nasal_err():error(0){}
void err(const char* stage,const std::string& info)
void err(const char* stage,const string& info)
{
++error;
std::cerr<<"["<<stage<<"] "<<info<<"\n";
}
void err(const char* stage,u32 line,u32 column,const std::string& info)
void err(const char* stage,u32 line,u32 column,const string& info)
{
++error;
const std::string& code=res[line-1];
const string& code=res[line-1];
std::cerr<<"["<<stage<<"] "<<file<<":"<<line<<":"<<column<<" "<<info<<"\n"<<code<<"\n";
for(int i=0;i<(int)column-1;++i)
std::cerr<<char(" \t"[code[i]=='\t']);
std::cerr<<"^\n";
}
void err(const char* stage,u32 line,const std::string& info)
void err(const char* stage,u32 line,const string& info)
{
++error;
std::cerr<<"["<<stage<<"] "<<file<<":"<<line<<" "<<info<<"\n"<<res[line-1]<<'\n';

View File

@ -43,15 +43,15 @@ const u32 incr[gc_tsize]=
16 // vm_co
};
struct nasal_vec; // vector
struct nasal_hash; // hashmap(dict)
struct nasal_func; // function(lambda)
struct nasal_upval;// upvalue
struct nasal_obj; // special objects
struct nasal_co; // coroutine
struct nasal_val; // nasal_val includes gc-managed types
struct nas_vec; // vector
struct nas_hash; // hashmap(dict)
struct nas_func; // function(lambda)
struct nas_upval;// upvalue
struct nas_obj; // special objects
struct nas_co; // coroutine
struct nas_val; // nasal_val includes gc-managed types
struct nasal_ref
struct nas_ref
{
u8 type;
union
@ -59,94 +59,94 @@ struct nasal_ref
u32 ret;
i64 cnt;
f64 num;
nasal_ref* addr;
nasal_val* gcobj;
nas_ref* addr;
nas_val* gcobj;
} val;
// vm_none/vm_nil
nasal_ref(const u8 t=vm_none):type(t){}
nas_ref(const u8 t=vm_none):type(t){}
// vm_ret
nasal_ref(const u8 t,const u32 n):type(t){val.ret=n;}
nas_ref(const u8 t,const u32 n):type(t){val.ret=n;}
// vm_cnt
nasal_ref(const u8 t,const i64 n):type(t){val.cnt=n;}
nas_ref(const u8 t,const i64 n):type(t){val.cnt=n;}
// vm_num
nasal_ref(const u8 t,const f64 n):type(t){val.num=n;}
nas_ref(const u8 t,const f64 n):type(t){val.num=n;}
// vm_str/vm_func/vm_vec/vm_hash/vm_upval/vm_obj
nasal_ref(const u8 t,nasal_val* n):type(t){val.gcobj=n;}
nas_ref(const u8 t,nas_val* n):type(t){val.gcobj=n;}
// vm_addr
nasal_ref(const u8 t,nasal_ref* n):type(t){val.addr=n;}
nasal_ref(const nasal_ref& nr):type(nr.type),val(nr.val){}
bool operator==(const nasal_ref& nr){return type==nr.type && val.gcobj==nr.val.gcobj;}
bool operator!=(const nasal_ref& nr){return type!=nr.type || val.gcobj!=nr.val.gcobj;}
nas_ref(const u8 t,nas_ref* n):type(t){val.addr=n;}
nas_ref(const nas_ref& nr):type(nr.type),val(nr.val){}
bool operator==(const nas_ref& nr){return type==nr.type && val.gcobj==nr.val.gcobj;}
bool operator!=(const nas_ref& nr){return type!=nr.type || val.gcobj!=nr.val.gcobj;}
// number and string can be translated to each other
f64 tonum();
std::string tostr();
void print();
bool objchk(u32);
inline nasal_ref* addr();
inline u32 ret ();
inline i64& cnt ();
inline f64 num ();
inline std::string& str ();
inline nasal_vec& vec ();
inline nasal_hash& hash();
inline nasal_func& func();
inline nasal_upval& upval();
inline nasal_obj& obj ();
inline nasal_co& co ();
f64 tonum();
string tostr();
void print();
bool objchk(u32);
inline nas_ref* addr();
inline u32 ret ();
inline i64& cnt ();
inline f64 num ();
inline string& str ();
inline nas_vec& vec ();
inline nas_hash& hash();
inline nas_func& func();
inline nas_upval& upval();
inline nas_obj& obj ();
inline nas_co& co ();
};
struct nasal_vec
struct nas_vec
{
bool printed;
std::vector<nasal_ref> elems;
std::vector<nas_ref> elems;
nasal_vec():printed(false){}
void print();
usize size(){return elems.size();}
nasal_ref get_val(const int);
nasal_ref* get_mem(const int);
nas_vec():printed(false){}
void print();
usize size(){return elems.size();}
nas_ref get_val(const int);
nas_ref* get_mem(const int);
};
struct nasal_hash
struct nas_hash
{
bool printed;
std::unordered_map<std::string,nasal_ref> elems;
std::unordered_map<string,nas_ref> elems;
nasal_hash():printed(false){}
void print();
usize size(){return elems.size();}
nasal_ref get_val(const std::string&);
nasal_ref* get_mem(const std::string&);
nas_hash():printed(false){}
void print();
usize size(){return elems.size();}
nas_ref get_val(const string&);
nas_ref* get_mem(const string&);
};
struct nasal_func
struct nas_func
{
i32 dynpara; // dynamic parameter name index in hash.
u32 entry; // pc will set to entry-1 to call this function
u32 psize; // used to load default parameters to a new function
u32 lsize; // used to expand memory space for local values on stack
std::vector<nasal_ref> local; // local scope with default value(nasal_ref)
std::vector<nasal_ref> upvalue; // closure
std::unordered_map<u32,u32> keys; // parameter name table, u32 begins from 1
i32 dpara; // dynamic parameter name index in hash.
u32 entry; // pc will set to entry-1 to call this function
u32 psize; // used to load default parameters to a new function
u32 lsize; // used to expand memory space for local values on stack
std::vector<nas_ref> local; // local scope with default value(nas_ref)
std::vector<nas_ref> upval; // closure
std::unordered_map<u32,u32> keys; // parameter table, u32 begins from 1
nasal_func():dynpara(-1),entry(0),psize(0),lsize(0){}
nas_func():dpara(-1),entry(0),psize(0),lsize(0){}
void clear();
};
struct nasal_upval
struct nas_upval
{
bool onstk;
u32 size;
nasal_ref* stk;
std::vector<nasal_ref> elems;
nas_ref* stk;
std::vector<nas_ref> elems;
nasal_upval(){onstk=true;stk=nullptr;size=0;}
nasal_ref& operator[](const int i){return onstk?stk[i]:elems[i];}
nas_upval(){onstk=true;stk=nullptr;size=0;}
nas_ref& operator[](const int i){return onstk?stk[i]:elems[i];}
void clear(){onstk=true;elems.clear();size=0;}
};
struct nasal_obj
struct nas_obj
{
enum obj_t:u32
{
@ -165,8 +165,8 @@ struct nasal_obj
typedef void (*dest)(void*);
dest dtor;
nasal_obj():type(obj_t::null),ptr(nullptr),dtor(nullptr){}
~nasal_obj(){clear();}
nas_obj():type(obj_t::null),ptr(nullptr),dtor(nullptr){}
~nas_obj(){clear();}
void set(u32 t=obj_t::null,void* p=nullptr,dest d=nullptr)
{
type=t;
@ -182,34 +182,33 @@ struct nasal_obj
}
};
struct nasal_co
struct nas_co
{
enum coroutine_stat
enum costat:u32
{
suspended,
running,
dead
};
nasal_ref stack[STACK_DEPTH];
nas_ref stack[STACK_DEPTH];
u32 pc;
nasal_ref* top;
nasal_ref* canary;
nasal_ref* localr;
nasal_ref* memr;
nasal_ref funcr;
nasal_ref upvalr;
u32 pc;
nas_ref* top;
nas_ref* canary;
nas_ref* localr;
nas_ref* memr;
nas_ref funcr;
nas_ref upvalr;
u32 status;
nasal_co():
pc(0),
top(stack),
nas_co():
pc(0),top(stack),
canary(stack+STACK_DEPTH-1),
localr(nullptr),
memr(nullptr),
funcr({vm_nil,(f64)0}),
upvalr({vm_nil,(f64)0}),
status(nasal_co::suspended)
status(nas_co::suspended)
{
for(u32 i=0;i<STACK_DEPTH;++i)
stack[i]={vm_nil,(f64)0};
@ -222,7 +221,7 @@ struct nasal_co
localr=nullptr;
memr=nullptr;
top=stack;
status=nasal_co::suspended;
status=nas_co::suspended;
funcr={vm_nil,(f64)0};
}
};
@ -230,41 +229,41 @@ struct nasal_co
const u8 GC_UNCOLLECTED=0;
const u8 GC_COLLECTED =1;
const u8 GC_FOUND =2;
struct nasal_val
struct nas_val
{
u8 mark;
u8 type;
u8 unmut; // used to mark if a string is unmutable
union
{
std::string* str;
nasal_vec* vec;
nasal_hash* hash;
nasal_func* func;
nasal_upval* upval;
nasal_obj* obj;
nasal_co* co;
string* str;
nas_vec* vec;
nas_hash* hash;
nas_func* func;
nas_upval* upval;
nas_obj* obj;
nas_co* co;
}ptr;
nasal_val(u8);
~nasal_val();
nas_val(u8);
~nas_val();
};
nasal_ref nasal_vec::get_val(const int index)
nas_ref nas_vec::get_val(const int index)
{
int size=elems.size();
if(index<-size || index>=size)
return {vm_none};
return elems[index>=0?index:index+size];
}
nasal_ref* nasal_vec::get_mem(const int index)
nas_ref* nas_vec::get_mem(const int index)
{
int size=elems.size();
if(index<-size || index>=size)
return nullptr;
return &elems[index>=0?index:index+size];
}
void nasal_vec::print()
void nas_vec::print()
{
if(!elems.size() || printed)
{
@ -283,14 +282,14 @@ void nasal_vec::print()
printed=false;
}
nasal_ref nasal_hash::get_val(const std::string& key)
nas_ref nas_hash::get_val(const string& key)
{
if(elems.count(key))
return elems[key];
else if(elems.count("parents"))
{
nasal_ref ret(vm_none);
nasal_ref val=elems["parents"];
nas_ref ret(vm_none);
nas_ref val=elems["parents"];
if(val.type==vm_vec)
for(auto& i:val.vec().elems)
{
@ -302,14 +301,14 @@ nasal_ref nasal_hash::get_val(const std::string& key)
}
return {vm_none};
}
nasal_ref* nasal_hash::get_mem(const std::string& key)
nas_ref* nas_hash::get_mem(const string& key)
{
if(elems.count(key))
return &elems[key];
else if(elems.count("parents"))
{
nasal_ref* addr=nullptr;
nasal_ref val=elems["parents"];
nas_ref* addr=nullptr;
nas_ref val=elems["parents"];
if(val.type==vm_vec)
for(auto& i:val.vec().elems)
{
@ -321,7 +320,7 @@ nasal_ref* nasal_hash::get_mem(const std::string& key)
}
return nullptr;
}
void nasal_hash::print()
void nas_hash::print()
{
if(!elems.size() || printed)
{
@ -341,31 +340,31 @@ void nasal_hash::print()
printed=false;
}
void nasal_func::clear()
void nas_func::clear()
{
dynpara=-1;
dpara=-1;
local.clear();
upvalue.clear();
upval.clear();
keys.clear();
}
nasal_val::nasal_val(u8 val_type)
nas_val::nas_val(u8 val_type)
{
mark=GC_COLLECTED;
type=val_type;
unmut=0;
switch(val_type)
{
case vm_str: ptr.str=new std::string; break;
case vm_vec: ptr.vec=new nasal_vec; break;
case vm_hash: ptr.hash=new nasal_hash; break;
case vm_func: ptr.func=new nasal_func; break;
case vm_upval:ptr.upval=new nasal_upval;break;
case vm_obj: ptr.obj=new nasal_obj; break;
case vm_co: ptr.co=new nasal_co; break;
case vm_str: ptr.str=new string; break;
case vm_vec: ptr.vec=new nas_vec; break;
case vm_hash: ptr.hash=new nas_hash; break;
case vm_func: ptr.func=new nas_func; break;
case vm_upval:ptr.upval=new nas_upval;break;
case vm_obj: ptr.obj=new nas_obj; break;
case vm_co: ptr.co=new nas_co; break;
}
}
nasal_val::~nasal_val()
nas_val::~nas_val()
{
switch(type)
{
@ -379,24 +378,24 @@ nasal_val::~nasal_val()
}
type=vm_nil;
}
f64 nasal_ref::tonum()
f64 nas_ref::tonum()
{
return type!=vm_str?val.num:str2num(str().c_str());
}
std::string nasal_ref::tostr()
string nas_ref::tostr()
{
if(type==vm_str)
return str();
else if(type==vm_num)
{
std::string tmp=std::to_string(num());
tmp.erase(tmp.find_last_not_of('0')+1,std::string::npos);
tmp.erase(tmp.find_last_not_of('.')+1,std::string::npos);
string tmp=std::to_string(num());
tmp.erase(tmp.find_last_not_of('0')+1,string::npos);
tmp.erase(tmp.find_last_not_of('.')+1,string::npos);
return tmp;
}
return "";
}
void nasal_ref::print()
void nas_ref::print()
{
switch(type)
{
@ -411,57 +410,58 @@ void nasal_ref::print()
case vm_co: std::cout<<"<coroutine>"; break;
}
}
bool nasal_ref::objchk(u32 objtype)
bool nas_ref::objchk(u32 objtype)
{
return type==vm_obj && obj().type==objtype && obj().ptr;
}
inline nasal_ref* nasal_ref::addr (){return val.addr; }
inline u32 nasal_ref::ret (){return val.ret; }
inline i64& nasal_ref::cnt (){return val.cnt; }
inline f64 nasal_ref::num (){return val.num; }
inline std::string& nasal_ref::str (){return *val.gcobj->ptr.str; }
inline nasal_vec& nasal_ref::vec (){return *val.gcobj->ptr.vec; }
inline nasal_hash& nasal_ref::hash (){return *val.gcobj->ptr.hash; }
inline nasal_func& nasal_ref::func (){return *val.gcobj->ptr.func; }
inline nasal_upval& nasal_ref::upval(){return *val.gcobj->ptr.upval;}
inline nasal_obj& nasal_ref::obj (){return *val.gcobj->ptr.obj; }
inline nasal_co& nasal_ref::co (){return *val.gcobj->ptr.co; }
inline nas_ref* nas_ref::addr (){return val.addr; }
inline u32 nas_ref::ret (){return val.ret; }
inline i64& nas_ref::cnt (){return val.cnt; }
inline f64 nas_ref::num (){return val.num; }
inline string& nas_ref::str (){return *val.gcobj->ptr.str; }
inline nas_vec& nas_ref::vec (){return *val.gcobj->ptr.vec; }
inline nas_hash& nas_ref::hash (){return *val.gcobj->ptr.hash; }
inline nas_func& nas_ref::func (){return *val.gcobj->ptr.func; }
inline nas_upval& nas_ref::upval(){return *val.gcobj->ptr.upval;}
inline nas_obj& nas_ref::obj (){return *val.gcobj->ptr.obj; }
inline nas_co& nas_ref::co (){return *val.gcobj->ptr.co; }
const nasal_ref zero={vm_num,(f64)0};
const nasal_ref one ={vm_num,(f64)1};
const nasal_ref nil ={vm_nil,(f64)0};
const nas_ref zero={vm_num,(f64)0};
const nas_ref one ={vm_num,(f64)1};
const nas_ref nil ={vm_nil,(f64)0};
struct nasal_gc
{
/* main context */
struct
{
u32 pc;
nasal_ref* top;
nasal_ref* localr;
nasal_ref* memr;
nasal_ref funcr;
nasal_ref upvalr;
nasal_ref* canary;
nasal_ref* stack;
} main_ctx;
u32 pc;
nas_ref* top;
nas_ref* localr;
nas_ref* memr;
nas_ref funcr;
nas_ref upvalr;
nas_ref* canary;
nas_ref* stack;
} mctx;
/* runtime context */
u32& pc; // program counter
nasal_ref*& localr; // local scope register
nasal_ref*& memr; // used for mem_call
nasal_ref& funcr; // function register
nasal_ref& upvalr; // upvalue register
nasal_ref*& canary; // avoid stackoverflow
nasal_ref*& top; // stack top
nasal_ref* stack; // stack pointer
nasal_co* coroutine; // running coroutine
nasal_ref temp; // temporary place used in builtin/module functions
u32& pc; // program counter
nas_ref*& localr;// local scope register
nas_ref*& memr; // used for mem_call
nas_ref& funcr; // function register
nas_ref& upvalr;// upvalue register
nas_ref*& canary;// avoid stackoverflow
nas_ref*& top; // stack top
nas_ref* stack; // stack pointer
nas_co* cort; // running coroutine
nas_ref temp; // temporary place used in builtin/module functions
/* constants and memory pool */
std::vector<nasal_ref> strs; // reserved address for const vm_str
std::vector<nasal_ref> env_argv; // command line arguments
std::vector<nasal_val*> memory; // gc memory
std::queue<nasal_val*> unused[gc_tsize]; // gc free list
std::vector<nas_ref> strs; // reserved address for const vm_str
std::vector<nas_ref> env_argv; // command line arguments
std::vector<nas_val*> memory; // gc memory
std::queue<nas_val*> unused[gc_tsize]; // gc free list
/* values for analysis */
u64 size[gc_tsize];
@ -469,52 +469,52 @@ struct nasal_gc
u64 allocc[gc_tsize];
nasal_gc(
u32& _pc,
nasal_ref*& _localr,
nasal_ref*& _memr,
nasal_ref& _funcr,
nasal_ref& _upvalr,
nasal_ref*& _canary,
nasal_ref*& _top,
nasal_ref* _stk):
nas_ref*& _localr,
nas_ref*& _memr,
nas_ref& _funcr,
nas_ref& _upvalr,
nas_ref*& _canary,
nas_ref*& _top,
nas_ref* _stk):
pc(_pc),localr(_localr),memr(_memr),funcr(_funcr),upvalr(_upvalr),
canary(_canary),top(_top),stack(_stk),coroutine(nullptr),temp(nil){}
void mark();
void sweep();
void init(const std::vector<std::string>&,const std::vector<std::string>&);
void clear();
void info();
nasal_ref alloc(const u8);
nasal_ref newstr(char);
nasal_ref newstr(const char*);
nasal_ref newstr(const std::string&);
void ctxchg(nasal_co&);
void ctxreserve();
canary(_canary),top(_top),stack(_stk),cort(nullptr),temp(nil){}
void mark();
void sweep();
void init(const std::vector<string>&,const std::vector<string>&);
void clear();
void info();
nas_ref alloc(const u8);
nas_ref newstr(char);
nas_ref newstr(const char*);
nas_ref newstr(const string&);
void ctxchg(nas_co&);
void ctxreserve();
};
/* gc functions */
void nasal_gc::mark()
{
std::queue<nasal_ref> bfs;
std::queue<nas_ref> bfs;
// scan coroutine process stack when coroutine ptr is not null
// scan main process stack when coroutine ptr is null
// this scan process must execute because when running coroutine,
// the nasal_co related to it will not update it's context(like `top`) until the coroutine suspends or exits.
for(nasal_ref* i=stack;i<=top;++i)
for(nas_ref* i=stack;i<=top;++i)
bfs.push(*i);
bfs.push(funcr);
bfs.push(upvalr);
bfs.push(temp);
if(coroutine) // scan main process stack
if(cort) // scan main process stack
{
for(nasal_ref* i=main_ctx.stack;i<=main_ctx.top;++i)
for(nas_ref* i=mctx.stack;i<=mctx.top;++i)
bfs.push(*i);
bfs.push(main_ctx.funcr);
bfs.push(main_ctx.upvalr);
bfs.push(mctx.funcr);
bfs.push(mctx.upvalr);
}
while(!bfs.empty())
{
nasal_ref tmp=bfs.front();
nas_ref tmp=bfs.front();
bfs.pop();
if(tmp.type<=vm_num || tmp.val.gcobj->mark) continue;
tmp.val.gcobj->mark=GC_FOUND;
@ -531,7 +531,7 @@ void nasal_gc::mark()
case vm_func:
for(auto& i:tmp.func().local)
bfs.push(i);
for(auto& i:tmp.func().upvalue)
for(auto& i:tmp.func().upval)
bfs.push(i);
break;
case vm_upval:
@ -541,7 +541,7 @@ void nasal_gc::mark()
case vm_co:
bfs.push(tmp.co().funcr);
bfs.push(tmp.co().upvalr);
for(nasal_ref* i=tmp.co().stack;i<=tmp.co().top;++i)
for(nas_ref* i=tmp.co().stack;i<=tmp.co().top;++i)
bfs.push(*i);
break;
}
@ -570,7 +570,7 @@ void nasal_gc::sweep()
i->mark=GC_UNCOLLECTED;
}
}
void nasal_gc::init(const std::vector<std::string>& s,const std::vector<std::string>& argv)
void nasal_gc::init(const std::vector<string>& s,const std::vector<string>& argv)
{
// initiaize function register
funcr=nil;
@ -580,16 +580,16 @@ void nasal_gc::init(const std::vector<std::string>& s,const std::vector<std::str
for(u8 i=0;i<gc_tsize;++i)
for(u32 j=0;j<ini[i];++j)
{
nasal_val* tmp=new nasal_val(i+vm_str);
nas_val* tmp=new nas_val(i+vm_str);
memory.push_back(tmp);
unused[i].push(tmp);
}
coroutine=nullptr;
cort=nullptr;
// init constant strings
strs.resize(s.size());
for(u32 i=0;i<strs.size();++i)
{
strs[i]={vm_str,new nasal_val(vm_str)};
strs[i]={vm_str,new nas_val(vm_str)};
strs[i].val.gcobj->unmut=1;
strs[i].str()=s[i];
}
@ -597,7 +597,7 @@ void nasal_gc::init(const std::vector<std::string>& s,const std::vector<std::str
env_argv.resize(argv.size());
for(usize i=0;i<argv.size();++i)
{
env_argv[i]={vm_str,new nasal_val(vm_str)};
env_argv[i]={vm_str,new nas_val(vm_str)};
env_argv[i].val.gcobj->unmut=1;
env_argv[i].str()=argv[i];
}
@ -626,7 +626,7 @@ void nasal_gc::info()
for(u8 i=0;i<gc_tsize;++i)
std::cout<<" "<<name[i]<<" | "<<ini[i]+size[i]*incr[i]<<" (+"<<size[i]<<")\n";
}
nasal_ref nasal_gc::alloc(u8 type)
nas_ref nasal_gc::alloc(u8 type)
{
const u8 index=type-vm_str;
++allocc[index];
@ -641,77 +641,77 @@ nasal_ref nasal_gc::alloc(u8 type)
++size[index];
for(u32 i=0;i<incr[index];++i)
{
nasal_val* tmp=new nasal_val(type);
nas_val* tmp=new nas_val(type);
memory.push_back(tmp);
unused[index].push(tmp);
}
}
nasal_ref ret={type,unused[index].front()};
nas_ref ret={type,unused[index].front()};
ret.val.gcobj->mark=GC_UNCOLLECTED;
unused[index].pop();
return ret;
}
nasal_ref nasal_gc::newstr(char c)
nas_ref nasal_gc::newstr(char c)
{
nasal_ref s=alloc(vm_str);
nas_ref s=alloc(vm_str);
s.str()=c;
return s;
}
nasal_ref nasal_gc::newstr(const char* buff)
nas_ref nasal_gc::newstr(const char* buff)
{
nasal_ref s=alloc(vm_str);
nas_ref s=alloc(vm_str);
s.str()=buff;
return s;
}
nasal_ref nasal_gc::newstr(const std::string& buff)
nas_ref nasal_gc::newstr(const string& buff)
{
nasal_ref s=alloc(vm_str);
nas_ref s=alloc(vm_str);
s.str()=buff;
return s;
}
void nasal_gc::ctxchg(nasal_co& context)
void nasal_gc::ctxchg(nas_co& ctx)
{
main_ctx.pc=pc;
main_ctx.top=top;
main_ctx.localr=localr;
main_ctx.memr=memr;
main_ctx.funcr=funcr;
main_ctx.upvalr=upvalr;
main_ctx.canary=canary;
main_ctx.stack=stack;
mctx.pc=pc;
mctx.top=top;
mctx.localr=localr;
mctx.memr=memr;
mctx.funcr=funcr;
mctx.upvalr=upvalr;
mctx.canary=canary;
mctx.stack=stack;
pc=context.pc;
top=context.top;
localr=context.localr;
memr=context.memr;
funcr=context.funcr;
upvalr=context.upvalr;
canary=context.canary;
stack=context.stack;
coroutine=&context;
pc=ctx.pc;
top=ctx.top;
localr=ctx.localr;
memr=ctx.memr;
funcr=ctx.funcr;
upvalr=ctx.upvalr;
canary=ctx.canary;
stack=ctx.stack;
cort=&ctx;
coroutine->status=nasal_co::running;
cort->status=nas_co::running;
}
void nasal_gc::ctxreserve()
{
// pc=0 means this coroutine is finished
coroutine->status=pc?nasal_co::suspended:nasal_co::dead;
coroutine->pc=pc;
coroutine->localr=localr;
coroutine->memr=memr;
coroutine->funcr=funcr;
coroutine->upvalr=upvalr;
coroutine->canary=canary;
coroutine->top=top;
cort->status=pc?nas_co::suspended:nas_co::dead;
cort->pc=pc;
cort->localr=localr;
cort->memr=memr;
cort->funcr=funcr;
cort->upvalr=upvalr;
cort->canary=canary;
cort->top=top;
pc=main_ctx.pc;
localr=main_ctx.localr;
memr=main_ctx.memr;
funcr=main_ctx.funcr;
upvalr=main_ctx.upvalr;
canary=main_ctx.canary;
top=main_ctx.top;
stack=main_ctx.stack;
coroutine=nullptr;
pc=mctx.pc;
localr=mctx.localr;
memr=mctx.memr;
funcr=mctx.funcr;
upvalr=mctx.upvalr;
canary=mctx.canary;
top=mctx.top;
stack=mctx.stack;
cort=nullptr;
}
#endif

View File

@ -10,19 +10,19 @@ class nasal_import
private:
bool lib_loaded;
nasal_err& nerr;
std::vector<std::string> files;
std::vector<std::string> envpath;
std::vector<string> files;
std::vector<string> envpath;
bool imptchk(const nasal_ast&);
bool exist(const std::string&);
bool exist(const string&);
void linker(nasal_ast&,nasal_ast&&);
std::string path(const nasal_ast&);
string path(const nasal_ast&);
nasal_ast fimpt(nasal_ast&);
nasal_ast libimpt();
nasal_ast load(nasal_ast&,u16);
public:
nasal_import(nasal_err&);
void link(nasal_parse&,const std::string&);
const std::vector<std::string>& filelist() const {return files;}
void link(nasal_parse&,const string&);
const std::vector<string>& filelist() const {return files;}
};
nasal_import::nasal_import(nasal_err& e):lib_loaded(false),nerr(e){
@ -31,12 +31,12 @@ nasal_import::nasal_import(nasal_err& e):lib_loaded(false),nerr(e){
#else
char sep=':';
#endif
std::string PATH=getenv("PATH");
string PATH=getenv("PATH");
usize last=0;
usize pos=PATH.find(sep,last);
while(pos!=std::string::npos)
while(pos!=string::npos)
{
std::string dirpath=PATH.substr(last,pos-last);
string dirpath=PATH.substr(last,pos-last);
if(dirpath.length())
envpath.push_back(dirpath);
last=pos+1;
@ -46,11 +46,11 @@ nasal_import::nasal_import(nasal_err& e):lib_loaded(false),nerr(e){
envpath.push_back(PATH.substr(last));
}
std::string nasal_import::path(const nasal_ast& node)
string nasal_import::path(const nasal_ast& node)
{
if(node[1].type()==ast_callf)
return node[1][0].str();
std::string fpath=".";
string fpath=".";
for(usize i=1;i<node.size();++i)
#ifndef _WIN32
fpath+="/"+node[i].str();
@ -92,7 +92,7 @@ bool nasal_import::imptchk(const nasal_ast& node)
);
}
bool nasal_import::exist(const std::string& file)
bool nasal_import::exist(const string& file)
{
// avoid importing the same file
for(auto& fname:files)
@ -114,7 +114,7 @@ nasal_ast nasal_import::fimpt(nasal_ast& node)
nasal_lexer lex(nerr);
nasal_parse par(nerr);
// get filename and set node to ast_null
std::string filename=path(node);
string filename=path(node);
node.clear();
// avoid infinite loading loop
@ -147,7 +147,7 @@ nasal_ast nasal_import::libimpt()
#define path_nalib "/lib.nas"
#define path_stllib "/stl/lib.nas"
#endif
std::vector<std::string> libpath={nalib,nastllib};
std::vector<string> libpath={nalib,nastllib};
for(auto& p:envpath)
{
libpath.push_back(p+path_nalib);
@ -156,7 +156,7 @@ nasal_ast nasal_import::libimpt()
nasal_lexer lex(nerr);
nasal_parse par(nerr);
std::string filename="";
string filename="";
for(auto& i:libpath)
if(access(i.c_str(),F_OK)!=-1)
{
@ -165,7 +165,7 @@ nasal_ast nasal_import::libimpt()
}
if(!filename.length())
{
std::string paths="";
string paths="";
for(auto& i:libpath)
paths+=" "+i+"\n";
nerr.err("link","cannot find lib file in these paths:\n"+paths);
@ -204,7 +204,7 @@ nasal_ast nasal_import::load(nasal_ast& root,u16 fileindex)
return new_root;
}
void nasal_import::link(nasal_parse& parse,const std::string& self)
void nasal_import::link(nasal_parse& parse,const string& self)
{
// initializing
files={self};

View File

@ -96,8 +96,8 @@ struct token
u32 line;
u32 col;
u32 type;
std::string str;
token(u32 l=0,u32 c=0,u32 t=tok_null,const std::string& s=""):str(s)
string str;
token(u32 l=0,u32 c=0,u32 t=tok_null,const string& s=""):str(s)
{
line=l;
col=c;
@ -108,33 +108,33 @@ struct token
class nasal_lexer
{
private:
u32 line;
u32 column;
usize ptr;
nasal_err& nerr;
std::string res;
u32 line;
u32 column;
usize ptr;
string res;
nasal_err& nerr;
std::vector<token> tokens;
u32 get_type(const std::string&);
void die(const std::string& info){nerr.err("lexer",line,column,info);}
void open(const std::string&);
std::string utf8_gen();
std::string id_gen();
std::string num_gen();
std::string str_gen();
u32 get_type(const string&);
void die(const string& info){nerr.err("lexer",line,column,info);}
void open(const string&);
string utf8_gen();
string id_gen();
string num_gen();
string str_gen();
public:
nasal_lexer(nasal_err& e):
line(1),
column(0),
ptr(0),
nerr(e),
res(""){}
void scan(const std::string&);
res(""),
nerr(e){}
void scan(const string&);
void print();
const std::vector<token>& result() const {return tokens;}
};
void nasal_lexer::open(const std::string& file)
void nasal_lexer::open(const string& file)
{
struct stat buffer;
if(stat(file.c_str(),&buffer)==0 && !S_ISREG(buffer.st_mode))
@ -152,7 +152,7 @@ void nasal_lexer::open(const std::string& file)
res=ss.str();
}
u32 nasal_lexer::get_type(const std::string& str)
u32 nasal_lexer::get_type(const string& str)
{
for(u32 i=0;tok_table[i].str;++i)
if(str==tok_table[i].str)
@ -160,12 +160,12 @@ u32 nasal_lexer::get_type(const std::string& str)
return tok_null;
}
std::string nasal_lexer::utf8_gen()
string nasal_lexer::utf8_gen()
{
std::string str="";
string str="";
while(ptr<res.size() && res[ptr]<0)
{
std::string tmp="";
string tmp="";
u32 nbytes=utf8_hdchk(res[ptr]);
if(nbytes)
{
@ -176,7 +176,7 @@ std::string nasal_lexer::utf8_gen()
if(tmp.length()!=1+nbytes)
{
++column;
std::string utf_info="0x"+chrhex(tmp[0]);
string utf_info="0x"+chrhex(tmp[0]);
for(u32 i=1;i<tmp.size();++i)
utf_info+=" 0x"+chrhex(tmp[i]);
die("invalid utf-8 character `"+utf_info+"`, make sure it is utf8-text file.");
@ -194,9 +194,9 @@ std::string nasal_lexer::utf8_gen()
return str;
}
std::string nasal_lexer::id_gen()
string nasal_lexer::id_gen()
{
std::string str="";
string str="";
while(ptr<res.size() && (ID(res[ptr])||DIGIT(res[ptr])))
{
if(res[ptr]<0) // utf-8
@ -210,12 +210,12 @@ std::string nasal_lexer::id_gen()
return str;
}
std::string nasal_lexer::num_gen()
string nasal_lexer::num_gen()
{
// generate hex number
if(ptr+1<res.size() && res[ptr]=='0' && res[ptr+1]=='x')
{
std::string str="0x";
string str="0x";
ptr+=2;
while(ptr<res.size() && HEX(res[ptr]))
str+=res[ptr++];
@ -227,7 +227,7 @@ std::string nasal_lexer::num_gen()
// generate oct number
else if(ptr+1<res.size() && res[ptr]=='0' && res[ptr+1]=='o')
{
std::string str="0o";
string str="0o";
ptr+=2;
while(ptr<res.size() && OCT(res[ptr]))
str+=res[ptr++];
@ -238,7 +238,7 @@ std::string nasal_lexer::num_gen()
}
// generate dec number
// dec number -> [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*)
std::string str="";
string str="";
while(ptr<res.size() && DIGIT(res[ptr]))
str+=res[ptr++];
if(ptr<res.size() && res[ptr]=='.')
@ -273,9 +273,9 @@ std::string nasal_lexer::num_gen()
return str;
}
std::string nasal_lexer::str_gen()
string nasal_lexer::str_gen()
{
std::string str="";
string str="";
const char begin=res[ptr];
++column;
while(++ptr<res.size() && res[ptr]!=begin)
@ -327,14 +327,14 @@ std::string nasal_lexer::str_gen()
return str;
}
void nasal_lexer::scan(const std::string& file)
void nasal_lexer::scan(const string& file)
{
line=1;
column=0;
ptr=0;
open(file);
std::string str;
string str;
while(ptr<res.size())
{
while(ptr<res.size() && (res[ptr]==' ' || res[ptr]=='\n' || res[ptr]=='\t' || res[ptr]=='\r' || res[ptr]==0))

View File

@ -48,7 +48,7 @@ private:
nasal_ast root;
nasal_err& nerr;
void die(u32,std::string,bool);
void die(u32,string,bool);
void match(u32 type,const char* info=nullptr);
bool check_comma(const u32*);
bool check_multi_scalar();
@ -121,7 +121,7 @@ void nasal_parse::compile(const nasal_lexer& lexer)
}
nerr.chkerr();
}
void nasal_parse::die(u32 line,std::string info,bool report_prev=false)
void nasal_parse::die(u32 line,string info,bool report_prev=false)
{
int col=(int)tokens[ptr].col-(int)tokens[ptr].str.length();
if(tokens[ptr].type==tok_str)
@ -147,7 +147,7 @@ void nasal_parse::match(u32 type,const char* info)
case tok_num:die(error_line,"expected number"); break;
case tok_str:die(error_line,"expected string"); break;
case tok_id: die(error_line,"expected identifier");break;
default: die(error_line,"expected \'"+std::string(tok_table[type-tok_for].str)+"\'"); break;
default: die(error_line,"expected \'"+string(tok_table[type-tok_for].str)+"\'"); break;
}
return;
}
@ -387,7 +387,7 @@ nasal_ast nasal_parse::args()
}
match(tok_rcurve,"expected \')\' after parameter list");
std::string format="func(";
string format="func(";
for(auto& tmp:node.child())
{
format+=tmp.str();
@ -411,10 +411,10 @@ nasal_ast nasal_parse::args()
if(checked_dynamic && &tmp!=&node.child().back())
die(tmp.line(),"dynamic para must be the end: "+format);
}
std::unordered_map<std::string,bool> argname;
std::unordered_map<string,bool> argname;
for(auto& tmp:node.child())
{
std::string name;
string name;
switch(tmp.type())
{
case ast_dynamic:

File diff suppressed because it is too large Load Diff