add tutorial of how to add built-in function

This commit is contained in:
Valk Richard Li 2021-02-23 23:33:01 +08:00
parent b1a5a5f6c0
commit 1c40cca673
1 changed files with 101 additions and 11 deletions

110
README.md
View File

@ -127,37 +127,46 @@ Function is also a value type in nasal.
var spc=nil; var spc=nil;
var a=1; var a=1;
a=0x7fffffff; var a=2.71828;
a=0o170001; var a=2.147e16;
var a=1e-10;
var a=0x7fffffff;
var a=0xAA55;
var a=0o170001;
var b='str'; var b='str';
b="another string"; var b="another string";
b=`c`; var b=`c`;
var c=[]; var c=[];
c=[0,nil,{},[],func(){return 0;}]; var c=[0,nil,{},[],func(){return 0;}];
append(c,0,1,2); append(c,0,1,2);
var d={ var d={
member1:nil, member1:nil,
member2:'str', member2:'str',
'member3':'member\'s name can also be a string constant', 'member3':'member\'s name can also be a string constant',
"member4":"also this" "member4":"also this",
function:func()
{
var a=me.member2~me.member3;
return a;
}
}; };
var e=func(x,y,z) var f=func(x,y,z)
{ {
return nil; return nil;
} }
e=func var f=func
{ {
return 1024; return 1024;
} }
e=func(x,y,z,default_parameter1=1,default_parameter2=2) var f=func(x,y,z,default_parameter1=1,default_parameter2=2)
{ {
return x+y+z+default_parameter1+default_parameter2; return x+y+z+default_parameter1+default_parameter2;
} }
e=func(x,y,z,dynamic_parameter...) var f=func(x,y,z,dynamic_parameter...)
{ {
var sum=0; var sum=0;
foreach(var i;dynamic_parameter) foreach(var i;dynamic_parameter)
@ -174,6 +183,7 @@ e=func(x,y,z,dynamic_parameter...)
1*2; 1*2;
1/2; 1/2;
'str1'~'str2'; 'str1'~'str2';
(1+2)*(3+4)
1+1 and 0; 1+1 and 0;
1+2*3 or 0; 1+2*3 or 0;
@ -251,8 +261,11 @@ foreach(var i;elem)
## subvec ## subvec
Use index to search one element in the string will get the ascii number of this character.If you want to get the character,use built-in function chr().
```javascript ```javascript
a[-1,1,0:2,0:,:3,:,nil:8,3:nil,nil:nil]; a[-1,1,0:2,0:,:3,:,nil:8,3:nil,nil:nil];
"hello world"[0];
``` ```
## special function call ## special function call
@ -263,6 +276,16 @@ This is of great use but is not very efficient.
a(x:0,y:1,z:2); a(x:0,y:1,z:2);
``` ```
## closure
```javascript
var f=func()
{
var a=1;
return func(){return a;};
}
print(f()());
```
## built-in functions ## built-in functions
Must import lib.nas or has these functions' definitions inside your code. Must import lib.nas or has these functions' definitions inside your code.
@ -270,3 +293,70 @@ Must import lib.nas or has these functions' definitions inside your code.
Also you could add builtin functions of your own(written in C/C++) to help you calculate things more quickly.(Advanced usage) Also you could add builtin functions of your own(written in C/C++) to help you calculate things more quickly.(Advanced usage)
Check built-in functions in lib.nas! Check built-in functions in lib.nas!
If you want to add your own built-in functions,define the function in nasal_builtin.h.
definition:
```C++
nasal_val* builtin_chr(nasal_val*,nasal_gc&);
```
Then complete this function using C++:
```C++
nasal_val* builtin_print(nasal_val* local_scope_addr,nasal_gc& gc)
{
// get arguments by using in_builtin_find
nasal_val* vector_value_addr=in_builtin_find("elements");
// main process
// also check type here,if get a type error,use builtin_error_occurred and return nullptr
nasal_vec& ref_vec=vector_value_addr->get_vector();
int size=ref_vec.size();
for(int i=0;i<size;++i)
{
nasal_val* tmp=ref_vec[i];
switch(tmp->get_type())
{
case vm_nil: std::cout<<"nil"; break;
case vm_num: std::cout<<tmp->get_number(); break;
case vm_str: std::cout<<tmp->get_string(); break;
case vm_vec: tmp->get_vector().print(); break;
case vm_hash: tmp->get_hash().print(); break;
case vm_func: std::cout<<"func(...){...}"; break;
}
}
// if a nasal value is not in use,use gc::del_reference to delete it
// if get a new reference of a nasal value,use gc::add_reference
// generate return value,use gc::gc_alloc(type) to make a new value
return gc.gc_alloc(vm_nil);
}
```
After that, write the built-in function's name(in nasal) and the function's pointer in this table:
```C++
struct FUNC_TABLE
{
std::string func_name;
nasal_val* (*func_pointer)(nasal_val* x,nasal_gc& gc);
} builtin_func_table[]=
{
{"nasal_call_builtin_std_cout",builtin_print},
{"",NULL}
};
```
At last,warp the 'nasal_call_builtin_std_cout' in a nasal file:
```javascript
var print=func(elements...)
{
nasal_call_builtin_std_cout(elements);
return nil;
};
```
In version 5.0,if you don't warp built-in function in a normal nasal function,this built-in function may cause a fault when searching arguments,which will cause SIGSEGV segmentation error(maybe).
Use import("") to get the nasal file including your biult-in functions,then you could use it.