🚀 change `std::string` to `string`, change identifiers' name, `-o` is now a function available in debug mode.
This commit is contained in:
parent
46516485b5
commit
99a131c552
132
README.md
132
README.md
|
@ -559,7 +559,7 @@ If you really want to change source code, check built-in functions in `lib.nas`
|
|||
Definition:
|
||||
|
||||
```C++
|
||||
nasal_ref builtin_print(nasal_ref*,nasal_gc&);
|
||||
nas_ref builtin_print(nas_ref*,nasal_gc&);
|
||||
// you could also use a macro to define one.
|
||||
nas_native(builtin_print);
|
||||
```
|
||||
|
@ -567,11 +567,11 @@ nas_native(builtin_print);
|
|||
Then complete this function using C++:
|
||||
|
||||
```C++
|
||||
nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc)
|
||||
nas_ref builtin_print(nas_ref* local,nasal_gc& gc)
|
||||
{
|
||||
// find value with index begin from 1
|
||||
// because local[0] is reserved for value 'me'
|
||||
nasal_ref vec=local[1];
|
||||
nas_ref vec=local[1];
|
||||
// main process
|
||||
// also check number of arguments and type here
|
||||
// if get an error,use builtin_err
|
||||
|
@ -601,7 +601,7 @@ After that, register the built-in function's name(in nasal) and the function's p
|
|||
struct func
|
||||
{
|
||||
const char* name;
|
||||
nasal_ref (*func)(nasal_ref*,nasal_gc&);
|
||||
nas_ref (*func)(nas_ref*,nasal_gc&);
|
||||
} builtin[]=
|
||||
{
|
||||
{"__print",builtin_print},
|
||||
|
@ -644,13 +644,13 @@ The value got before will be collected, but stil in use in this builtin function
|
|||
So use `gc::temp` in builtin functions to temprorarily store the gc-managed value that you want to return later. Like this:
|
||||
|
||||
```C++
|
||||
nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc)
|
||||
nas_ref builtin_keys(nas_ref* local,nasal_gc& gc)
|
||||
{
|
||||
nasal_ref hash=local[1];
|
||||
nas_ref hash=local[1];
|
||||
if(hash.type!=vm_hash)
|
||||
return builtin_err("keys","\"hash\" must be hash");
|
||||
// avoid being sweeped
|
||||
nasal_ref res=gc.temp=gc.alloc(vm_vec);
|
||||
nas_ref res=gc.temp=gc.alloc(vm_vec);
|
||||
auto& vec=res.vec().elems;
|
||||
for(auto& iter:hash.hash().elems)
|
||||
vec.push_back(gc.newstr(iter.first));
|
||||
|
@ -693,10 +693,10 @@ double fibonaci(double x){
|
|||
}
|
||||
// remember to use extern "C",
|
||||
// so you could search the symbol quickly
|
||||
extern "C" nasal_ref fib(std::vector<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`.
|
||||
|
|
132
doc/README_zh.md
132
doc/README_zh.md
|
@ -525,7 +525,7 @@ __警告:__ 如果你 __不想__ 通过直接修改解释器源码来添加你
|
|||
定义新的内置函数:
|
||||
|
||||
```C++
|
||||
nasal_ref builtin_print(nasal_ref*,nasal_gc&);
|
||||
nas_ref builtin_print(nas_ref*,nasal_gc&);
|
||||
// 你可以使用这个宏来直接定义一个新的内置函数
|
||||
nas_native(builtin_print);
|
||||
```
|
||||
|
@ -533,11 +533,11 @@ nas_native(builtin_print);
|
|||
然后用C++完成这个函数的函数体:
|
||||
|
||||
```C++
|
||||
nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc)
|
||||
nas_ref builtin_print(nas_ref* local,nasal_gc& gc)
|
||||
{
|
||||
// 局部变量的下标其实是从1开始的
|
||||
// 因为local[0]是保留给'me'的空间
|
||||
nasal_ref vec=local[1];
|
||||
nas_ref vec=local[1];
|
||||
// 主要部分
|
||||
// 一些必要的类型检查和输入合法性检测也要在这里写出
|
||||
// 如果检测到问题,用builtin_err函数来返回vm_null
|
||||
|
@ -568,7 +568,7 @@ nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc)
|
|||
struct func
|
||||
{
|
||||
const char* name;
|
||||
nasal_ref (*func)(nasal_ref*,nasal_gc&);
|
||||
nas_ref (*func)(nas_ref*,nasal_gc&);
|
||||
} builtin[]=
|
||||
{
|
||||
{"__print",builtin_print},
|
||||
|
@ -608,13 +608,13 @@ import("./dirname/dirname/filename.nas");
|
|||
所以请使用`gc::temp`来暂时存储一个会被返回的需要gc管理的变量,这样可以防止内部所有的申请错误触发垃圾回收。如下所示:
|
||||
|
||||
```C++
|
||||
nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc)
|
||||
nas_ref builtin_keys(nas_ref* local,nasal_gc& gc)
|
||||
{
|
||||
nasal_ref hash=local[1];
|
||||
nas_ref hash=local[1];
|
||||
if(hash.type!=vm_hash)
|
||||
return builtin_err("keys","\"hash\" must be hash");
|
||||
// 使用gc.temp来存储gc管理的变量,防止错误的回收
|
||||
nasal_ref res=gc.temp=gc.alloc(vm_vec);
|
||||
nas_ref res=gc.temp=gc.alloc(vm_vec);
|
||||
auto& vec=res.vec().elems;
|
||||
for(auto& iter:hash.hash().elems)
|
||||
vec.push_back(gc.newstr(iter.first));
|
||||
|
@ -653,9 +653,9 @@ double fibonaci(double x){
|
|||
}
|
||||
// 记得用extern "C"
|
||||
// 这样找符号会更加快速便捷,不要在意编译时的warning
|
||||
extern "C" nasal_ref fib(std::vector<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`的返回值在协程的操作数栈顶。综上所述:
|
||||
|
|
19
main.cpp
19
main.cpp
|
@ -34,6 +34,7 @@ void help()
|
|||
<<" -e, --exec | execute.\n"
|
||||
<<" -t, --time | execute and get the running time.\n"
|
||||
<<" -o, --opcnt | execute and count used operands.\n"
|
||||
<<" | this options is available in debug mode.\n"
|
||||
<<" -d, --detail | execute and get detail crash info.\n"
|
||||
<<" | get garbage collector info if didn't crash.\n"
|
||||
<<" -op, --optimize| use optimizer(beta).\n"
|
||||
|
@ -70,7 +71,7 @@ void err()
|
|||
std::exit(1);
|
||||
}
|
||||
|
||||
void execute(const std::string& file,const std::vector<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]))
|
||||
|
|
10
makefile
10
makefile
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
13
nasal.h
|
@ -42,13 +42,13 @@
|
|||
|
||||
using i32=std::int32_t;
|
||||
using i64=std::int64_t;
|
||||
using u8 =std::uint8_t;
|
||||
using u8=std::uint8_t;
|
||||
using u16=std::uint16_t;
|
||||
using u32=std::uint32_t;
|
||||
using u64=std::uint64_t;
|
||||
using usize=std::size_t;
|
||||
using f64=double;
|
||||
|
||||
using std::string;
|
||||
|
||||
const u32 STACK_DEPTH=2048;
|
||||
|
||||
|
@ -145,14 +145,15 @@ int utf8_hdchk(const char head)
|
|||
return 0;
|
||||
}
|
||||
|
||||
std::string chrhex(const char c)
|
||||
string chrhex(const char c)
|
||||
{
|
||||
return {"0123456789abcdef"[(c&0xf0)>>4],"0123456789abcdef"[c&0x0f]};
|
||||
const char hextbl[]="0123456789abcdef";
|
||||
return {hextbl[(c&0xf0)>>4],hextbl[c&0x0f]};
|
||||
}
|
||||
|
||||
std::string rawstr(const std::string& str,const usize maxlen=0)
|
||||
string rawstr(const string& str,const usize maxlen=0)
|
||||
{
|
||||
std::string ret("");
|
||||
string ret("");
|
||||
for(auto i:str)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
|
10
nasal_ast.h
10
nasal_ast.h
|
@ -1,7 +1,7 @@
|
|||
#ifndef __NASAL_AST_H__
|
||||
#define __NASAL_AST_H__
|
||||
|
||||
enum ast_node
|
||||
enum ast_node:u32
|
||||
{
|
||||
ast_null=0, // null node
|
||||
ast_root, // mark the root node of ast
|
||||
|
@ -132,7 +132,7 @@ private:
|
|||
u32 _line;
|
||||
u32 _type;
|
||||
f64 _num;
|
||||
std::string _str;
|
||||
string _str;
|
||||
std::vector<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];
|
||||
|
|
496
nasal_builtin.h
496
nasal_builtin.h
File diff suppressed because it is too large
Load Diff
|
@ -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());
|
||||
|
|
325
nasal_dbg.h
325
nasal_dbg.h
|
@ -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
|
||||
}
|
||||
|
||||
|
|
22
nasal_err.h
22
nasal_err.h
|
@ -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';
|
||||
|
|
468
nasal_gc.h
468
nasal_gc.h
|
@ -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
|
|
@ -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};
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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:
|
||||
|
|
766
nasal_vm.h
766
nasal_vm.h
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue