update docs & fix bug in nasal_builtin.h

This commit is contained in:
ValKmjolnir 2022-03-16 15:30:34 +08:00
parent 9bcad59e45
commit c4d52a88cd
6 changed files with 37 additions and 35 deletions

View File

@ -518,11 +518,11 @@ println(a.get());
### __native functions__ ### __native functions__
You could add builtin functions of your own This part shows how we add native functions in this nasal interpreter.
(written in C/C++) to help you calculate things more quickly. If you are interested in this part, this may help you.
But you should add your own code into the source code of this interpreter and re-compile it. And...
If you want to add your own functions __without__ changing the source code of the interpreter, see the __`module`__ after this part. __CAUTION:__ If you want to add your own functions __without__ changing the source code of the interpreter, see the __`module`__ after this part.
If you really want to change source code, check built-in functions in lib.nas and see the example below. If you really want to change source code, check built-in functions in lib.nas and see the example below.
@ -530,6 +530,8 @@ Definition:
```C++ ```C++
nasal_ref builtin_print(nasal_ref*,nasal_gc&); nasal_ref builtin_print(nasal_ref*,nasal_gc&);
// you could also use a macro to define one.
nas_native(builtin_print);
``` ```
Then complete this function using C++: Then complete this function using C++:
@ -538,12 +540,12 @@ Then complete this function using C++:
nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc)
{ {
// find value with index begin from 1 // find value with index begin from 1
// because local_scope[0] is reserved for value 'me' // because local[0] is reserved for value 'me'
nasal_ref vec=local[1]; nasal_ref vec=local[1];
// main process // main process
// also check number of arguments and type here // also check number of arguments and type here
// if get an error,use builtin_err // if get an error,use builtin_err
for(auto i:vec.vec().elems) for(auto& i:vec.vec().elems)
switch(i.type) switch(i.type)
{ {
case vm_none: std::cout<<"undefined"; break; case vm_none: std::cout<<"undefined"; break;
@ -556,7 +558,8 @@ nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc)
case vm_obj: std::cout<<"<object>"; break; case vm_obj: std::cout<<"<object>"; break;
} }
std::cout<<std::flush; std::cout<<std::flush;
// generate return value,use gc::alloc(type) to make a new value // generate return value,
// use gc::alloc(type) to make a new value
// or use reserved reference nil/one/zero // or use reserved reference nil/one/zero
return nil; return nil;
} }
@ -569,7 +572,7 @@ struct func
{ {
const char* name; const char* name;
nasal_ref (*func)(nasal_ref*,nasal_gc&); nasal_ref (*func)(nasal_ref*,nasal_gc&);
} builtin_func[]= } builtin[]=
{ {
{"__builtin_print",builtin_print}, {"__builtin_print",builtin_print},
{nullptr, nullptr } {nullptr, nullptr }
@ -584,7 +587,7 @@ var print=func(elems...){
}; };
``` ```
In fact the arguments that `__builtin_print` uses is not necessary. In fact the arguments that `__builtin_print` uses are not necessary.
So writting it like this is also right: So writting it like this is also right:
```javascript ```javascript
@ -610,7 +613,9 @@ this may cause mark-sweep in `gc::alloc`.
The value got before will be collected,but stil in use in this builtin function, The value got before will be collected,but stil in use in this builtin function,
this is a fatal error. this is a fatal error.
So use `builtin_alloc` in builtin functions like this: So use `gc::builtin_alloc` in builtin functions to allocate a new object.
Or use `gc::alloc` like this to avoid sweeping objects incorrectly:
```C++ ```C++
nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc)
@ -620,7 +625,7 @@ nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc)
return builtin_err("keys","\"hash\" must be hash"); return builtin_err("keys","\"hash\" must be hash");
// push vector into local scope to avoid being sweeped // push vector into local scope to avoid being sweeped
if(gc.top+1>=gc.stack+STACK_MAX_DEPTH-1) if(gc.top+1>=gc.stack+STACK_MAX_DEPTH-1)
builtin_err("keys","expand temporary space error:stackoverflow"); return builtin_err("keys","expand temporary space error:stackoverflow");
(++gc.top)[0]=gc.alloc(vm_vec); (++gc.top)[0]=gc.alloc(vm_vec);
auto& vec=gc.top[0].vec().elems; auto& vec=gc.top[0].vec().elems;
for(auto& iter:hash.hash().elems) for(auto& iter:hash.hash().elems)
@ -767,7 +772,15 @@ please change it to:
`canary=gc.stack+STACK_MAX_DEPTH-1;` `canary=gc.stack+STACK_MAX_DEPTH-1;`
If do not change this line, only the debugger runs abnormally. this bug is fixed in `v9.0` If do not change this line, only the debugger runs abnormally. this bug is fixed in `v9.0`.
Another bug is that in `nasal_err.h:class nasal_err`, we should add a constructor for this class:
```C++
nasal_err():error(0){}
```
This bug is fixed in `v9.0`.
## __Parser__ ## __Parser__

View File

@ -6,14 +6,6 @@
#define environ (*_NSGetEnviron()) #define environ (*_NSGetEnviron())
#endif #endif
/*
builtin functions must be called inside a function like this:
var print=func(elems...){
return __builtin_print(elems);
}
builtin function __builtin_print is wrapped up by print
*/
// declaration of builtin functions // declaration of builtin functions
// to add new builtin function, declare it here and write the definition below // to add new builtin function, declare it here and write the definition below
#define nas_native(name) nasal_ref name(nasal_ref*,nasal_gc&) #define nas_native(name) nasal_ref name(nasal_ref*,nasal_gc&)
@ -283,7 +275,7 @@ nasal_ref builtin_split(nasal_ref* local,nasal_gc& gc)
// push it to local scope to avoid being sweeped // push it to local scope to avoid being sweeped
if(gc.top+1>=gc.stack+STACK_MAX_DEPTH-1) if(gc.top+1>=gc.stack+STACK_MAX_DEPTH-1)
builtin_err("split","expand temporary space error:stackoverflow"); return builtin_err("split","expand temporary space error:stackoverflow");
(++gc.top)[0]=gc.alloc(vm_vec); (++gc.top)[0]=gc.alloc(vm_vec);
std::vector<nasal_ref>& vec=gc.top[0].vec().elems; std::vector<nasal_ref>& vec=gc.top[0].vec().elems;
@ -575,7 +567,7 @@ nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc)
return builtin_err("keys","\"hash\" must be hash"); return builtin_err("keys","\"hash\" must be hash");
// push vector into local scope to avoid being sweeped // push vector into local scope to avoid being sweeped
if(gc.top+1>=gc.stack+STACK_MAX_DEPTH-1) if(gc.top+1>=gc.stack+STACK_MAX_DEPTH-1)
builtin_err("keys","expand temporary space error:stackoverflow"); return builtin_err("keys","expand temporary space error:stackoverflow");
(++gc.top)[0]=gc.alloc(vm_vec); (++gc.top)[0]=gc.alloc(vm_vec);
auto& vec=gc.top[0].vec().elems; auto& vec=gc.top[0].vec().elems;
for(auto& iter:hash.hash().elems) for(auto& iter:hash.hash().elems)
@ -1032,7 +1024,7 @@ nasal_ref builtin_environ(nasal_ref* local,nasal_gc& gc)
{ {
char** env=environ; char** env=environ;
if(gc.top+1>=gc.stack+STACK_MAX_DEPTH-1) if(gc.top+1>=gc.stack+STACK_MAX_DEPTH-1)
builtin_err("environ","expand temporary space error:stackoverflow"); return builtin_err("environ","expand temporary space error:stackoverflow");
(++gc.top)[0]=gc.alloc(vm_vec); (++gc.top)[0]=gc.alloc(vm_vec);
auto& vec=gc.top[0].vec().elems; auto& vec=gc.top[0].vec().elems;
while(*env) while(*env)

View File

@ -171,7 +171,7 @@ struct nasal_obj
void clear() void clear()
{ {
if(destructor && ptr) if(destructor && ptr)
{destructor(ptr);} destructor(ptr);
ptr=nullptr; ptr=nullptr;
destructor=nullptr; destructor=nullptr;
} }

View File

@ -14,11 +14,7 @@ for(var i=0;i<10;i+=1)
var prt=func() var prt=func()
{ {
if(os.platform()=="windows") var s="\e[0;0H+--------------------+\n";
system("cls");
else
system("clear");
var s="+--------------------+\n";
for(var i=0;i<10;i+=1) for(var i=0;i<10;i+=1)
{ {
s~="|"; s~="|";
@ -28,6 +24,7 @@ var prt=func()
} }
s~='+--------------------+\n'; s~='+--------------------+\n';
print(s); print(s);
unix.sleep(1/144);
} }
var bfs=func(begin,end) var bfs=func(begin,end)
@ -49,6 +46,7 @@ var bfs=func(begin,end)
{ {
map[x][y]=3; map[x][y]=3;
prt(); prt();
print("reached.\n");
return; return;
} }
if(0<=x and x<10 and 0<=y and y<20 and map[x][y]==0) if(0<=x and x<10 and 0<=y and y<20 and map[x][y]==0)
@ -63,4 +61,5 @@ var bfs=func(begin,end)
return; return;
} }
print("\ec");
bfs([0,0],[9,19]); bfs([0,0],[9,19]);

View File

@ -23,22 +23,20 @@ var new_map=func()
var prt=func() var prt=func()
{ {
var s=''; var s='\e[0;0H';
foreach(var line;map) foreach(var line;map)
{ {
foreach(var elem;line) foreach(var elem;line)
s~=elem~' '; s~=elem~' ';
s~='\n'; s~='\n';
} }
if(os.platform()=="windows")
system("cls");
else
system("clear");
print(s); print(s);
unix.sleep(1/144);
} }
func() func()
{ {
print("\ec");
rand(time(0)); rand(time(0));
map=new_map(); map=new_map();
forindex(var i;map) forindex(var i;map)