📝 update documents
This commit is contained in:
parent
2f58a7c223
commit
c946e9debd
515
README.md
515
README.md
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
__Contact us if having great ideas to share!__
|
__Contact us if having great ideas to share!__
|
||||||
|
|
||||||
* __E-mail__: __lhk101lhk101@qq.com__
|
* __E-mail__: __lhk101lhk101@qq.com__(ValKmjolnir) __1467329765@qq.com__(Sidi762)
|
||||||
|
|
||||||
## __Introduction__
|
## __Introduction__
|
||||||
|
|
||||||
|
@ -97,8 +97,9 @@ You could choose which compiler you want to use:
|
||||||
If your system is `Windows` and you want to output unicode, you could write this in nasal code:
|
If your system is `Windows` and you want to output unicode, you could write this in nasal code:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
if(os.platform()=="windows")
|
if (os.platform()=="windows") {
|
||||||
system("chcp 65001");
|
system("chcp 65001");
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## __Tutorial__
|
## __Tutorial__
|
||||||
|
@ -116,30 +117,30 @@ This type is not created by user program.
|
||||||
__`nil`__ is a null type. Just like `null`.
|
__`nil`__ is a null type. Just like `null`.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var spc=nil;
|
var spc = nil;
|
||||||
```
|
```
|
||||||
|
|
||||||
__`num`__ has 3 formats: `dec`, `hex` and `oct`. Using IEEE754 `double` to store.
|
__`num`__ has 3 formats: `dec`, `hex` and `oct`. Using IEEE754 `double` to store.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
# this language use '#' to write notes
|
# this language use '#' to write notes
|
||||||
var n=2.71828; # dec
|
var n = 2.71828; # dec
|
||||||
var n=2.147e16; # dec
|
var n = 2.147e16; # dec
|
||||||
var n=1e-10; # dec
|
var n = 1e-10; # dec
|
||||||
var n=0xAA55; # hex
|
var n = 0xAA55; # hex
|
||||||
var n=0o170001; # oct
|
var n = 0o170001; # oct
|
||||||
|
|
||||||
# caution: true and false also useful in nasal now
|
# caution: true and false also useful in nasal now
|
||||||
var n=true; # in fact n is now 1.0
|
var n = true; # in fact n is now 1.0
|
||||||
var n=false; # in face n is now 0.0
|
var n = false; # in face n is now 0.0
|
||||||
```
|
```
|
||||||
|
|
||||||
__`str`__ has 3 formats. The third one is used to declare a character.
|
__`str`__ has 3 formats. The third one is used to declare a character.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var s='str';
|
var s = 'str';
|
||||||
var s="another string";
|
var s = "another string";
|
||||||
var s=`c`;
|
var s = `c`;
|
||||||
# some special characters is allowed in this language:
|
# some special characters is allowed in this language:
|
||||||
'\a'; '\b'; '\e'; '\f';
|
'\a'; '\b'; '\e'; '\f';
|
||||||
'\n'; '\r'; '\t'; '\v';
|
'\n'; '\r'; '\t'; '\v';
|
||||||
|
@ -150,19 +151,19 @@ var s=`c`;
|
||||||
__`vec`__ has unlimited length and can store all types of values.
|
__`vec`__ has unlimited length and can store all types of values.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var vec=[];
|
var vec = [];
|
||||||
var vec=[0,nil,{},[],func(){return 0}];
|
var vec = [0, nil, {}, [], func(){return 0}];
|
||||||
append(vec,0,1,2);
|
append(vec, 0, 1, 2);
|
||||||
```
|
```
|
||||||
|
|
||||||
__`hash`__ is a hashmap (or like a `dict` in `python`) that stores values with strings/identifiers as the key.
|
__`hash`__ is a hashmap (or like a `dict` in `python`) that stores values with strings/identifiers as the key.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var hash={
|
var hash = {
|
||||||
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",
|
||||||
funct:func(){
|
funct: func() {
|
||||||
return me.member2~me.member3;
|
return me.member2~me.member3;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -171,27 +172,28 @@ var hash={
|
||||||
__`func`__ is a function type (in fact it is `lambda`).
|
__`func`__ is a function type (in fact it is `lambda`).
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var f=func(x,y,z){
|
var f = func(x, y, z) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
# function could be declared without parameters and `(`, `)`
|
# function could be declared without parameters and `(`, `)`
|
||||||
var f=func{
|
var f = func {
|
||||||
return 114514;
|
return 114514;
|
||||||
}
|
}
|
||||||
var f=func(x,y,z,deft=1){
|
var f = func(x, y, z, deft = 1) {
|
||||||
return x+y+z+deft;
|
return x+y+z+deft;
|
||||||
}
|
}
|
||||||
var f=func(args...){
|
var f = func(args...) {
|
||||||
var sum=0;
|
var sum = 0;
|
||||||
foreach(var i;args)
|
foreach(var i; args) {
|
||||||
sum+=i;
|
sum += i;
|
||||||
|
}
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
__`upval`__ is used to store upvalues, used in __`vm`__ to make sure closure runs correctly.
|
__`upval`__ is used to store upvalues, used in __`vm`__ to make sure closure runs correctly.
|
||||||
|
|
||||||
__`obj`__ is used to store other complex `C/C++` data types.
|
__`ghost`__ is used to store other complex `C/C++` data types.
|
||||||
This type is created by native-function of nasal. If want to define a new data type, see how to add native-functions by editing code.
|
This type is created by native-function of nasal. If want to define a new data type, see how to add native-functions by editing code.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
@ -237,16 +239,16 @@ Bitwise operators `~` `|` `&` `^` have the same function as C/C++.
|
||||||
Operators `=` `+=` `-=` `*=` `/=` `~=` `^=` `&=` `|=` are used in assignment expressions.
|
Operators `=` `+=` `-=` `*=` `/=` `~=` `^=` `&=` `|=` are used in assignment expressions.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
a=b=c=d=1;
|
a = b = c = d = 1;
|
||||||
a+=1;
|
a += 1;
|
||||||
a-=1;
|
a -= 1;
|
||||||
a*=1;
|
a *= 1;
|
||||||
a/=1;
|
a /= 1;
|
||||||
a~="string";
|
a ~= "string";
|
||||||
|
|
||||||
a^=0xff;
|
a ^= 0xff;
|
||||||
a&=0xca;
|
a &= 0xca;
|
||||||
a|=0xba;
|
a |= 0xba;
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
@ -256,9 +258,9 @@ a|=0xba;
|
||||||
As follows.
|
As follows.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var a=1; # define single variable
|
var a = 1; # define single variable
|
||||||
var (a,b,c)=[0,1,2]; # define multiple variables from a vector
|
var (a, b, c) = [0, 1, 2]; # define multiple variables from a vector
|
||||||
var (a,b,c)=(0,1,2); # define multiple variables from a tuple
|
var (a, b, c) = (0, 1, 2); # define multiple variables from a tuple
|
||||||
```
|
```
|
||||||
|
|
||||||
Nasal has many special global symbols:
|
Nasal has many special global symbols:
|
||||||
|
@ -292,9 +294,9 @@ func() {
|
||||||
The last one is often used to swap two variables.
|
The last one is often used to swap two variables.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
(a,b[0],c.d)=[0,1,2];
|
(a, b[0], c.d) = [0, 1, 2];
|
||||||
(a,b[1],c.e)=(0,1,2);
|
(a, b[1], c.e) = (0, 1, 2);
|
||||||
(a,b)=(b,a);
|
(a, b) = (b, a);
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
@ -305,13 +307,13 @@ In nasal there's a new key word `elsif`.
|
||||||
It has the same functions as `else if`.
|
It has the same functions as `else if`.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
if(1){
|
if (1) {
|
||||||
;
|
;
|
||||||
}elsif(2){
|
} elsif (2) {
|
||||||
;
|
;
|
||||||
}else if(3){
|
} else if (3) {
|
||||||
;
|
;
|
||||||
}else{
|
} else {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -323,10 +325,12 @@ if(1){
|
||||||
While loop and for loop is simalar to C/C++.
|
While loop and for loop is simalar to C/C++.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
while(condition)
|
while(condition) {
|
||||||
continue;
|
continue;
|
||||||
for(var i=0;i<10;i+=1)
|
}
|
||||||
|
for(var i = 0; i<10; i += 1) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Nasal has another two kinds of loops that iterates through a vector:
|
Nasal has another two kinds of loops that iterates through a vector:
|
||||||
|
@ -334,15 +338,17 @@ Nasal has another two kinds of loops that iterates through a vector:
|
||||||
`forindex` will get the index of a vector. Index will be `0` to `size(elem)-1`.
|
`forindex` will get the index of a vector. Index will be `0` to `size(elem)-1`.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
forindex(var i;elem)
|
forindex(var i; elem) {
|
||||||
print(elem[i]);
|
print(elem[i]);
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`foreach` will get the element of a vector. Element will be `elem[0]` to `elem[size(elem)-1]`.
|
`foreach` will get the element of a vector. Element will be `elem[0]` to `elem[size(elem)-1]`.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
foreach(var i;elem)
|
foreach(var i; elem) {
|
||||||
print(i);
|
print(i);
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
@ -356,7 +362,7 @@ If you want to get the character, use built-in function `chr()`.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
a[0];
|
a[0];
|
||||||
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];
|
"hello world"[0];
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -370,7 +376,7 @@ because hashmap use string as the key to compare.
|
||||||
But if it really useful, the efficientcy may not be so important...
|
But if it really useful, the efficientcy may not be so important...
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
f(x:0,y:nil,z:[]);
|
f(x:0, y:nil, z:[]);
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
@ -380,10 +386,10 @@ f(x:0,y:nil,z:[]);
|
||||||
Also functions have this kind of use:
|
Also functions have this kind of use:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
func(x,y){
|
func(x, y) {
|
||||||
return x+y
|
return x+y
|
||||||
}(0,1);
|
}(0, 1);
|
||||||
func(x){
|
func(x) {
|
||||||
return 1/(1+math.exp(-x));
|
return 1/(1+math.exp(-x));
|
||||||
}(0.5);
|
}(0.5);
|
||||||
```
|
```
|
||||||
|
@ -392,11 +398,11 @@ There's an interesting test file `y-combinator.nas`,
|
||||||
try it for fun:
|
try it for fun:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var fib=func(f){
|
var fib = func(f) {
|
||||||
return f(f);
|
return f(f);
|
||||||
}(
|
}(
|
||||||
func(f){
|
func(f) {
|
||||||
return func(x){
|
return func(x) {
|
||||||
if(x<2) return x;
|
if(x<2) return x;
|
||||||
return f(f)(x-1)+f(f)(x-2);
|
return f(f)(x-1)+f(f)(x-2);
|
||||||
}
|
}
|
||||||
|
@ -412,9 +418,9 @@ Closure means you could get the variable that is not in the local scope of a fun
|
||||||
Here is an example, result is `1`:
|
Here is an example, result is `1`:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var f=func(){
|
var f = func() {
|
||||||
var a=1;
|
var a = 1;
|
||||||
return func(){return a;};
|
return func() {return a;};
|
||||||
}
|
}
|
||||||
print(f()());
|
print(f()());
|
||||||
```
|
```
|
||||||
|
@ -422,14 +428,14 @@ print(f()());
|
||||||
Using closure makes it easier to OOP.
|
Using closure makes it easier to OOP.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var student=func(n,a){
|
var student = func(n, a) {
|
||||||
var (name,age)=(n,a);
|
var (name, age) = (n, a);
|
||||||
return {
|
return {
|
||||||
print_info:func() {println(name,' ',age);},
|
print_info: func() {println(name, ' ', age);},
|
||||||
set_age: func(a){age=a;},
|
set_age: func(a) {age = a;},
|
||||||
get_age: func() {return age;},
|
get_age: func() {return age;},
|
||||||
set_name: func(n){name=n;},
|
set_name: func(n) {name = n;},
|
||||||
get_name: func() {return name;}
|
get_name: func() {return name;}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -448,20 +454,20 @@ If there is a hash that has the member, you will get the member's value.
|
||||||
Using this mechanism, we could OOP like this, the result is `114514`:
|
Using this mechanism, we could OOP like this, the result is `114514`:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var trait={
|
var trait = {
|
||||||
get:func{return me.val;},
|
get: func {return me.val;},
|
||||||
set:func(x){me.val=x;}
|
set: func(x) {me.val = x;}
|
||||||
};
|
};
|
||||||
|
|
||||||
var class={
|
var class = {
|
||||||
new:func(){
|
new: func() {
|
||||||
return {
|
return {
|
||||||
val:nil,
|
val: nil,
|
||||||
parents:[trait]
|
parents: [trait]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var a=class.new();
|
var a = class.new();
|
||||||
a.set(114514);
|
a.set(114514);
|
||||||
println(a.get());
|
println(a.get());
|
||||||
```
|
```
|
||||||
|
@ -473,28 +479,28 @@ And `get` has the same process.
|
||||||
And we must remind you that if you do this:
|
And we must remind you that if you do this:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var trait={
|
var trait = {
|
||||||
get:func{return me.val;},
|
get: func {return me.val;},
|
||||||
set:func(x){me.val=x;}
|
set: func(x) {me.val = x;}
|
||||||
};
|
};
|
||||||
|
|
||||||
var class={
|
var class = {
|
||||||
new:func(){
|
new: func() {
|
||||||
return {
|
return {
|
||||||
val:nil,
|
val: nil,
|
||||||
parents:[trait]
|
parents: [trait]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var a=class.new();
|
var a = class.new();
|
||||||
var b=class.new();
|
var b = class.new();
|
||||||
a.set(114);
|
a.set(114);
|
||||||
b.set(514);
|
b.set(514);
|
||||||
println(a.get());
|
println(a.get());
|
||||||
println(b.get());
|
println(b.get());
|
||||||
|
|
||||||
var c=a.get;
|
var c = a.get;
|
||||||
var d=b.get;
|
var d = b.get;
|
||||||
|
|
||||||
println(c());
|
println(c());
|
||||||
println(c());
|
println(c());
|
||||||
|
@ -532,33 +538,19 @@ Definition:
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
// you could also use a macro to define one.
|
// you could also use a macro to define one.
|
||||||
nas_native(builtin_print);
|
var builtin_print(context*, gc*);
|
||||||
```
|
```
|
||||||
|
|
||||||
Then complete this function using C++:
|
Then complete this function using C++:
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
var builtin_print(var* local,gc& ngc)
|
var builtin_print(context* ctx, gc* ngc) {
|
||||||
{
|
|
||||||
// find value with index begin from 1
|
// find value with index begin from 1
|
||||||
// because local[0] is reserved for value 'me'
|
// because local[0] is reserved for value 'me'
|
||||||
var vec=local[1];
|
for(auto& i : ctx->localr[1].vec().elems) {
|
||||||
// main process
|
std::cout << i;
|
||||||
// also check number of arguments and type here
|
}
|
||||||
// if get an error,use nas_err
|
std::cout << std::flush;
|
||||||
for(auto& i:vec.vec().elems)
|
|
||||||
switch(i.type)
|
|
||||||
{
|
|
||||||
case vm_none: std::cout<<"undefined"; break;
|
|
||||||
case vm_nil: std::cout<<"nil"; break;
|
|
||||||
case vm_num: std::cout<<i.num(); break;
|
|
||||||
case vm_str: std::cout<<i.str(); break;
|
|
||||||
case vm_vec: std::cout<<i.vec(); break;
|
|
||||||
case vm_hash: std::cout<<i.hash(); break;
|
|
||||||
case vm_func: std::cout<<"func(..){..}";break;
|
|
||||||
case vm_obj: std::cout<<"<object>"; break;
|
|
||||||
}
|
|
||||||
std::cout<<std::flush;
|
|
||||||
// generate return value,
|
// generate return value,
|
||||||
// use ngc::alloc(type) to make a new value
|
// use ngc::alloc(type) to make a new value
|
||||||
// or use reserved reference nil/one/zero
|
// or use reserved reference nil/one/zero
|
||||||
|
@ -572,17 +564,24 @@ 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:
|
So use `gc::temp` in builtin functions to temprorarily store the gc-managed value that you want to return later. Like this:
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
var builtin_keys(var* local,gc& ngc)
|
var builtin_keys(context* ctx, gc* ngc) {
|
||||||
{
|
auto hash = ctx->localr[1];
|
||||||
var hash=local[1];
|
if (hash.type!=vm_hash && hash.type!=vm_map) {
|
||||||
if(hash.type!=vm_hash)
|
return nas_err("keys", "\"hash\" must be hash");
|
||||||
return nas_err("keys","\"hash\" must be hash");
|
}
|
||||||
// use gc.temp to store the gc-managed-value, to avoid being sweeped
|
// use gc.temp to store the gc-managed-value, to avoid being sweeped
|
||||||
var res=ngc.temp=ngc.alloc(vm_vec);
|
auto res = ngc->temp = ngc->alloc(vm_vec);
|
||||||
auto& vec=res.vec().elems;
|
auto& vec = res.vec().elems;
|
||||||
for(auto& iter:hash.hash().elems)
|
if (hash.type==vm_hash) {
|
||||||
vec.push_back(ngc.newstr(iter.first));
|
for(const auto& iter : hash.hash().elems) {
|
||||||
ngc.temp=nil;
|
vec.push_back(ngc->newstr(iter.first));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(const auto& iter : hash.map().mapper) {
|
||||||
|
vec.push_back(ngc->newstr(iter.first));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ngc->temp = nil;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -590,21 +589,16 @@ var builtin_keys(var* local,gc& ngc)
|
||||||
After that, register the built-in function's name(in nasal) and the function's pointer in this table:
|
After that, register the built-in function's name(in nasal) and the function's pointer in this table:
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
struct func
|
nasal_builtin_table builtin[] = {
|
||||||
{
|
{"__print", builtin_print},
|
||||||
const char* name;
|
{nullptr, nullptr}
|
||||||
var (*func)(var*,gc&);
|
|
||||||
} builtin[]=
|
|
||||||
{
|
|
||||||
{"__print",builtin_print},
|
|
||||||
{nullptr, nullptr }
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
At last,warp the `__print` in a nasal file:
|
At last,warp the `__print` in a nasal file:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var print=func(elems...){
|
var print = func(elems...) {
|
||||||
return __print(elems);
|
return __print(elems);
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
@ -613,7 +607,7 @@ In fact the arguments that `__print` uses are not necessary.
|
||||||
So writting it like this is also right:
|
So writting it like this is also right:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var print=func(elems...){
|
var print = func(elems...) {
|
||||||
return __print;
|
return __print;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
@ -631,7 +625,7 @@ import("./dirname/dirname/filename.nas");
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details><summary> Modules(for lib developers) </summary>
|
<details><summary> Modules (for lib developers) </summary>
|
||||||
|
|
||||||
If there is only one way to add your own functions into nasal,
|
If there is only one way to add your own functions into nasal,
|
||||||
that is really inconvenient.
|
that is really inconvenient.
|
||||||
|
@ -731,7 +725,7 @@ Then we write a test nasal file to run this fib function, using `os.platform()`
|
||||||
use std.dylib;
|
use std.dylib;
|
||||||
var dlhandle = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
var dlhandle = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
||||||
var fib = dlhandle.fib;
|
var fib = dlhandle.fib;
|
||||||
for(var i = 1; i<30; i+=1)
|
for(var i = 1; i<30; i += 1)
|
||||||
println(dylib.dlcall(fib, i));
|
println(dylib.dlcall(fib, i));
|
||||||
dylib.dlclose(dlhandle.lib);
|
dylib.dlclose(dlhandle.lib);
|
||||||
```
|
```
|
||||||
|
@ -749,7 +743,7 @@ use std.dylib;
|
||||||
var dlhandle = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
var dlhandle = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
||||||
var fib = dlhandle.fib;
|
var fib = dlhandle.fib;
|
||||||
var invoke = dylib.limitcall(1); # this means the called function has only one parameter
|
var invoke = dylib.limitcall(1); # this means the called function has only one parameter
|
||||||
for(var i = 1; i<30; i+=1)
|
for(var i = 1; i<30; i += 1)
|
||||||
println(invoke(fib, i));
|
println(invoke(fib, i));
|
||||||
dylib.dlclose(dlhandle.lib);
|
dylib.dlclose(dlhandle.lib);
|
||||||
```
|
```
|
||||||
|
@ -791,7 +785,7 @@ If get this, Congratulations!
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details><summary> Ghost Type(for lib developers) </summary>
|
<details><summary> Ghost Type (for lib developers) </summary>
|
||||||
|
|
||||||
It's quite easy to create a new ghost by yourself now.
|
It's quite easy to create a new ghost by yourself now.
|
||||||
Look at the example below:
|
Look at the example below:
|
||||||
|
@ -812,19 +806,31 @@ void ghost_for_test_destructor(void* ptr) {
|
||||||
var create_new_ghost(var* args, usize size, gc* ngc) {
|
var create_new_ghost(var* args, usize size, gc* ngc) {
|
||||||
var res = ngc->alloc(vm_obj);
|
var res = ngc->alloc(vm_obj);
|
||||||
// create ghost type
|
// create ghost type
|
||||||
res.obj().set(ghost_for_test, ghost_for_test_destructor, new u32);
|
res.ghost().set(ghost_for_test, ghost_for_test_destructor, new u32);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var set_new_ghost(var* args, usize size, gc* ngc) {
|
||||||
|
var res = args[0];
|
||||||
|
if (!res.object_check(ghost_for_test)) {
|
||||||
|
std::cout << "set_new_ghost: not ghost for test type.\n";
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
f64 num = args[1].num();
|
||||||
|
*(reinterpret_cast<u32*>(res.ghost().pointer)) = static_cast<u32>(num);
|
||||||
|
std::cout << "set_new_ghost: successfully set ghost = " << num << "\n";
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
var print_new_ghost(var* args, usize size, gc* ngc) {
|
var print_new_ghost(var* args, usize size, gc* ngc) {
|
||||||
var res = args[0];
|
var res = args[0];
|
||||||
// check ghost type by the type name
|
// check ghost type by the type name
|
||||||
if (!res.objchk(ghost_for_test)) {
|
if (!res.object_check(ghost_for_test)) {
|
||||||
std::cout << "print_new_ghost: not ghost for test type.\n";
|
std::cout << "print_new_ghost: not ghost for test type.\n";
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
std::cout << "print_new_ghost: " << res.obj() << " result = "
|
std::cout << "print_new_ghost: " << res.ghost() << " result = "
|
||||||
<< *((u32*)res.obj().ptr) << "\n";
|
<< *((u32*)res.ghost().pointer) << "\n";
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -841,7 +847,7 @@ We use this function to create a new ghost type:
|
||||||
|
|
||||||
And we use this function to check if value is the correct ghost type:
|
And we use this function to check if value is the correct ghost type:
|
||||||
|
|
||||||
`bool var::objchk(const std::string&);`
|
`bool var::object_check(const std::string&);`
|
||||||
|
|
||||||
The parameter is the name of the ghost type.
|
The parameter is the name of the ghost type.
|
||||||
|
|
||||||
|
@ -860,7 +866,7 @@ So do not use variable without using `var` to declare it.
|
||||||
In Andy's interpreter:
|
In Andy's interpreter:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
foreach(i;[0,1,2,3])
|
foreach(i; [0, 1, 2, 3])
|
||||||
print(i)
|
print(i)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -877,7 +883,7 @@ If you forget to add the keyword `var`, you will get this:
|
||||||
code: undefined symbol "i"
|
code: undefined symbol "i"
|
||||||
--> test.nas:1:9
|
--> test.nas:1:9
|
||||||
|
|
|
|
||||||
1 | foreach(i;[0,1,2,3])
|
1 | foreach(i; [0, 1, 2, 3])
|
||||||
| ^ undefined symbol "i"
|
| ^ undefined symbol "i"
|
||||||
|
|
||||||
code: undefined symbol "i"
|
code: undefined symbol "i"
|
||||||
|
@ -901,8 +907,7 @@ it will print trace back information:
|
||||||
Function `die` is used to throw error and crash immediately.
|
Function `die` is used to throw error and crash immediately.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
func()
|
func() {
|
||||||
{
|
|
||||||
println("hello");
|
println("hello");
|
||||||
die("error occurred this line");
|
die("error occurred this line");
|
||||||
return;
|
return;
|
||||||
|
@ -912,17 +917,27 @@ func()
|
||||||
```javascript
|
```javascript
|
||||||
hello
|
hello
|
||||||
[vm] error: error occurred this line
|
[vm] error: error occurred this line
|
||||||
[vm] native function error.
|
[vm] error: error occurred in native function
|
||||||
trace back:
|
|
||||||
0x000000ac 40 00 00 00 25 callb 0x25 <__die@0x41afc0> (lib.nas:131)
|
call trace (main)
|
||||||
0x000004f6 3e 00 00 00 01 callfv 0x1 (a.nas:4)
|
call func@0x557513935710() {entry: 0x850}
|
||||||
0x000004fa 3e 00 00 00 00 callfv 0x0 (a.nas:6)
|
|
||||||
vm stack (0x7fffcd21bc68 <sp+80>, limit 10, total 12):
|
trace back (main)
|
||||||
0x0000005b | null |
|
0x000547 4c 00 00 16 callb 0x16 <__die@0x557512441780>(std/lib.nas:150)
|
||||||
...
|
0x000856 4a 00 00 01 callfv 0x1(a.nas:3)
|
||||||
0x00000057 | str | <0x138ff60> error occurred t...
|
0x00085a 4a 00 00 00 callfv 0x0(a.nas:5)
|
||||||
...
|
|
||||||
0x00000052 | nil |
|
stack (0x5575138e8c40, limit 10, total 14)
|
||||||
|
0x00000d | null |
|
||||||
|
0x00000c | pc | 0x856
|
||||||
|
0x00000b | addr | 0x5575138e8c50
|
||||||
|
0x00000a | nil |
|
||||||
|
0x000009 | nil |
|
||||||
|
0x000008 | str | <0x5575138d9190> error occurred t...
|
||||||
|
0x000007 | nil |
|
||||||
|
0x000006 | func | <0x5575139356f0> entry:0x850
|
||||||
|
0x000005 | pc | 0x85a
|
||||||
|
0x000004 | addr | 0x0
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
@ -932,28 +947,41 @@ vm stack (0x7fffcd21bc68 <sp+80>, limit 10, total 12):
|
||||||
Here is an example of stack overflow:
|
Here is an example of stack overflow:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
func(f){
|
func(f) {
|
||||||
return f(f);
|
return f(f);
|
||||||
}(
|
}(
|
||||||
func(f){
|
func(f) {
|
||||||
f(f);
|
f(f);
|
||||||
}
|
}
|
||||||
)();
|
)();
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
[vm] stack overflow
|
[vm] error: stack overflow
|
||||||
trace back:
|
|
||||||
0x000004fb 3e 00 00 00 01 callfv 0x1 (a.nas:5)
|
call trace (main)
|
||||||
0x000004fb 1349 same call(s)
|
call func@0x564106058620(f) {entry: 0x859}
|
||||||
0x000004f3 3e 00 00 00 01 callfv 0x1 (a.nas:2)
|
--> 583 same call(s)
|
||||||
0x000004ff 3e 00 00 00 01 callfv 0x1 (a.nas:3)
|
call func@0x5641060586c0(f) {entry: 0x851}
|
||||||
vm stack (0x7fffd3781d58 <sp+80>, limit 10, total 8108):
|
|
||||||
0x00001ffb | func | <0x15f8d90> entry:0x4f9
|
trace back (main)
|
||||||
0x00001ffa | func | <0x15f8d90> entry:0x4f9
|
0x000859 45 00 00 01 calll 0x1(a.nas:5)
|
||||||
0x00001ff9 | pc | 0x4fb
|
0x00085b 4a 00 00 01 callfv 0x1(a.nas:5)
|
||||||
...
|
0x00085b 582 same call(s)
|
||||||
0x00001ff2 | addr | 0x7fffd37a16e8
|
0x000853 4a 00 00 01 callfv 0x1(a.nas:2)
|
||||||
|
0x00085f 4a 00 00 01 callfv 0x1(a.nas:3)
|
||||||
|
|
||||||
|
stack (0x56410600be00, limit 10, total 4096)
|
||||||
|
0x000fff | func | <0x564106058600> entry:0x859
|
||||||
|
0x000ffe | pc | 0x85b
|
||||||
|
0x000ffd | addr | 0x56410601bd20
|
||||||
|
0x000ffc | nil |
|
||||||
|
0x000ffb | nil |
|
||||||
|
0x000ffa | func | <0x564106058600> entry:0x859
|
||||||
|
0x000ff9 | nil |
|
||||||
|
0x000ff8 | func | <0x564106058600> entry:0x859
|
||||||
|
0x000ff7 | pc | 0x85b
|
||||||
|
0x000ff6 | addr | 0x56410601bcb0
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
@ -963,17 +991,19 @@ vm stack (0x7fffd3781d58 <sp+80>, limit 10, total 8108):
|
||||||
Error will be thrown if there's a fatal error when executing:
|
Error will be thrown if there's a fatal error when executing:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
func(){
|
func() {
|
||||||
return 0;
|
return 0;
|
||||||
}()[1];
|
}()[1];
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
[vm] callv: must call a vector/hash/string
|
[vm] error: must call a vector/hash/string but get number
|
||||||
trace back:
|
|
||||||
0x000004f4 3b 00 00 00 00 callv 0x0 (a.nas:3)
|
trace back (main)
|
||||||
vm stack (0x7fffff539c28 <sp+80>, limit 10, total 1):
|
0x000854 47 00 00 00 callv 0x0(a.nas:3)
|
||||||
0x00000050 | num | 0
|
|
||||||
|
stack (0x564993f462b0, limit 10, total 1)
|
||||||
|
0x000000 | num | 0
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
@ -985,35 +1015,48 @@ Use command __`-d`__ or __`--detail`__ the trace back info will show more detail
|
||||||
```javascript
|
```javascript
|
||||||
hello
|
hello
|
||||||
[vm] error: error occurred this line
|
[vm] error: error occurred this line
|
||||||
[vm] error: native function error
|
[vm] error: error occurred in native function
|
||||||
|
|
||||||
|
call trace (main)
|
||||||
|
call func@0x55dcb5b8fbf0() {entry: 0x850}
|
||||||
|
|
||||||
trace back (main)
|
trace back (main)
|
||||||
0x000000b0 40 00 00 00 2b callb 0x2b <__die@0x41c380> (lib.nas:131)
|
0x000547 4c 00 00 16 callb 0x16 <__die@0x55dcb3c41780>(std/lib.nas:150)
|
||||||
0x00000553 3e 00 00 00 01 callfv 0x1 (test.nas:4)
|
0x000856 4a 00 00 01 callfv 0x1(a.nas:3)
|
||||||
0x00000557 3e 00 00 00 00 callfv 0x0 (test.nas:6)
|
0x00085a 4a 00 00 00 callfv 0x0(a.nas:5)
|
||||||
vm stack (0x7fffe0ffed90 <sp+63>, limit 10, total 12)
|
|
||||||
0x0000004a | null |
|
stack (0x55dcb5b43120, limit 10, total 14)
|
||||||
0x00000049 | pc | 0x553
|
0x00000d | null |
|
||||||
0x00000048 | addr | 0x7fffe0ffeda0
|
0x00000c | pc | 0x856
|
||||||
...
|
0x00000b | addr | 0x55dcb5b43130
|
||||||
0x00000041 | nil |
|
0x00000a | nil |
|
||||||
|
0x000009 | nil |
|
||||||
|
0x000008 | str | <0x55dcb5b33670> error occurred t...
|
||||||
|
0x000007 | nil |
|
||||||
|
0x000006 | func | <0x55dcb5b8fbd0> entry:0x850
|
||||||
|
0x000005 | pc | 0x85a
|
||||||
|
0x000004 | addr | 0x0
|
||||||
|
|
||||||
registers (main)
|
registers (main)
|
||||||
[ pc ] | pc | 0xb0
|
[pc ] | pc | 0x547
|
||||||
[ global ] | addr | 0x7fffe0ffe9a0
|
[global] | addr | 0x55dcb5b53130
|
||||||
[ localr ] | addr | 0x7fffe0ffedf0
|
[local ] | addr | 0x55dcb5b43190
|
||||||
[ memr ] | addr | 0x0
|
[memr ] | addr | 0x0
|
||||||
[ canary ] | addr | 0x7fffe1002990
|
[canary] | addr | 0x55dcb5b53110
|
||||||
[ top ] | addr | 0x7fffe0ffee40
|
[top ] | addr | 0x55dcb5b431f0
|
||||||
[ funcr ] | func | <0x677cd0> entry:0xb0
|
[funcr ] | func | <0x55dcb5b65620> entry:0x547
|
||||||
[ upvalr ] | nil |
|
[upval ] | nil |
|
||||||
global (0x7fffe0ffe9a0 <sp+0>)
|
|
||||||
0x00000000 | func | <0x65fb00> entry:0x5
|
global (0x55dcb5b53130)
|
||||||
0x00000001 | func | <0x65fb20> entry:0xd
|
0x000000 | nmspc| <0x55dcb5b33780> namespace [95 val]
|
||||||
|
0x000001 | vec | <0x55dcb5b64c20> [0 val]
|
||||||
...
|
...
|
||||||
0x0000003d | func | <0x66bf00> entry:0x51f
|
0x00005e | func | <0x55dcb5b8fc70> entry:0x846
|
||||||
0x0000003e | hash | <0x65ffa0> {5 val}
|
|
||||||
local (0x7fffe0ffedf0 <sp+45>)
|
local (0x55dcb5b43190 <+7>)
|
||||||
0x00000000 | nil |
|
0x000000 | nil |
|
||||||
0x00000001 | str | <0x6cb630> error occurred t...
|
0x000001 | str | <0x55dcb5b33670> error occurred t...
|
||||||
|
0x000002 | nil |
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
@ -1038,16 +1081,18 @@ source code:
|
||||||
for(var i=0;i<31;i+=1)
|
for(var i=0;i<31;i+=1)
|
||||||
print(fib(i),'\n');
|
print(fib(i),'\n');
|
||||||
|
|
||||||
|
|
||||||
next bytecode:
|
next bytecode:
|
||||||
--> 0x00000000 01 00 00 00 41 intg 0x41 (test/fib.nas:0)
|
0x000848 4a 00 00 01 callfv 0x1(std/lib.nas:427)
|
||||||
0x00000001 0b 00 00 00 05 newf 0x5 (lib.nas:6)
|
0x000849 3d 00 00 00 pop 0x0(std/lib.nas:427)
|
||||||
0x00000002 02 00 00 00 02 intl 0x2 (lib.nas:6)
|
0x00084a 07 00 00 00 pnil 0x0(std/lib.nas:423)
|
||||||
0x00000003 0f 00 00 00 00 dyn 0x0 ("elems") (lib.nas:6)
|
0x00084b 56 00 00 00 ret 0x0(std/lib.nas:423)
|
||||||
0x00000004 32 00 00 00 07 jmp 0x7 (lib.nas:6)
|
0x00084c 03 00 00 5e loadg 0x5e(std/lib.nas:423)
|
||||||
0x00000005 40 00 00 00 00 callb 0x0 <__print@0x419c80> (lib.nas:7)
|
--> 0x00084d 0b 00 08 51 newf 0x851(test/fib.nas:1)
|
||||||
0x00000006 4a 00 00 00 00 ret 0x0 (lib.nas:7)
|
0x00084e 02 00 00 03 intl 0x3(test/fib.nas:1)
|
||||||
0x00000007 03 00 00 00 00 loadg 0x0 (lib.nas:6)
|
0x00084f 0d 00 00 08 para 0x8 (x)(test/fib.nas:1)
|
||||||
vm stack (0x7fffd0259138 <sp+65>, limit 10, total 0)
|
|
||||||
|
stack (0x55ccd0a1b9d0, limit 10, total 0)
|
||||||
>>
|
>>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1070,23 +1115,26 @@ source code:
|
||||||
for(var i=0;i<31;i+=1)
|
for(var i=0;i<31;i+=1)
|
||||||
print(fib(i),'\n');
|
print(fib(i),'\n');
|
||||||
|
|
||||||
|
|
||||||
next bytecode:
|
next bytecode:
|
||||||
0x00000548 0c 00 00 00 aa happ 0xaa ("running") (lib.nas:503)
|
0x000850 3e 00 08 60 jmp 0x860(test/fib.nas:1)
|
||||||
0x00000549 03 00 00 00 3e loadg 0x3e (lib.nas:498)
|
--> 0x000851 45 00 00 01 calll 0x1(test/fib.nas:3)
|
||||||
0x0000054a 0b 00 00 05 4e newf 0x54e (test/fib.nas:1)
|
0x000852 39 00 00 07 lessc 0x7 (2)(test/fib.nas:3)
|
||||||
0x0000054b 02 00 00 00 02 intl 0x2 (test/fib.nas:1)
|
0x000853 40 00 08 56 jf 0x856(test/fib.nas:3)
|
||||||
0x0000054c 0d 00 00 00 1b para 0x1b ("x") (test/fib.nas:1)
|
0x000854 45 00 00 01 calll 0x1(test/fib.nas:3)
|
||||||
0x0000054d 32 00 00 05 5d jmp 0x55d (test/fib.nas:1)
|
0x000855 56 00 00 00 ret 0x0(test/fib.nas:3)
|
||||||
--> 0x0000054e 39 00 00 00 01 calll 0x1 (test/fib.nas:3)
|
0x000856 44 00 00 5f callg 0x5f(test/fib.nas:4)
|
||||||
0x0000054f 2d 00 00 00 03 lessc 0x3 (2) (test/fib.nas:3)
|
0x000857 45 00 00 01 calll 0x1(test/fib.nas:4)
|
||||||
vm stack (0x7fffd0259138 <sp+65>, limit 10, total 7)
|
|
||||||
0x00000047 | pc | 0x566
|
stack (0x55ccd0a1b9d0, limit 10, total 8)
|
||||||
0x00000046 | addr | 0x0
|
0x000007 | pc | 0x869
|
||||||
0x00000045 | nil |
|
0x000006 | addr | 0x0
|
||||||
0x00000044 | num | 0
|
0x000005 | nil |
|
||||||
0x00000043 | nil |
|
0x000004 | nil |
|
||||||
0x00000042 | nil |
|
0x000003 | num | 0
|
||||||
0x00000041 | func | <0x88d2f0> entry:0x5
|
0x000002 | nil |
|
||||||
|
0x000001 | nil |
|
||||||
|
0x000000 | func | <0x55ccd0a58fa0> entry:0x487
|
||||||
>>
|
>>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1114,3 +1162,22 @@ Nasal REPL interpreter version 11.0 (Oct 7 2023 17:28:31)
|
||||||
|
|
||||||
>>>
|
>>>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Try import `std/json.nas`~
|
||||||
|
|
||||||
|
```bash
|
||||||
|
[nasal-repl] Initializating enviroment...
|
||||||
|
[nasal-repl] Initialization complete.
|
||||||
|
|
||||||
|
Nasal REPL interpreter version 11.1 (Nov 1 2023 23:37:30)
|
||||||
|
.h, .help | show help
|
||||||
|
.e, .exit | quit the REPL
|
||||||
|
.q, .quit | quit the REPL
|
||||||
|
.c, .clear | clear the screen
|
||||||
|
.s, .source | show source code
|
||||||
|
|
||||||
|
>>> use std.json;
|
||||||
|
{stringify:func(..) {..},parse:func(..) {..}}
|
||||||
|
|
||||||
|
>>>
|
||||||
|
```
|
||||||
|
|
524
doc/README_zh.md
524
doc/README_zh.md
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
__如果有好的意见或建议,欢迎联系我们!__
|
__如果有好的意见或建议,欢迎联系我们!__
|
||||||
|
|
||||||
* __E-mail__: __lhk101lhk101@qq.com__
|
* __E-mail__: __lhk101lhk101@qq.com__(ValKmjolnir) __1467329765@qq.com__(Sidi762)
|
||||||
|
|
||||||
## __简介__
|
## __简介__
|
||||||
|
|
||||||
|
@ -88,8 +88,9 @@ __注意__: 如果你想直接下载发行版提供的zip/tar.gz压缩包来构
|
||||||
如果你是 `Windows` 用户且想正常输出unicode,在nasal代码里写这个来开启unicode代码页:
|
如果你是 `Windows` 用户且想正常输出unicode,在nasal代码里写这个来开启unicode代码页:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
if(os.platform()=="windows")
|
if (os.platform()=="windows") {
|
||||||
system("chcp 65001");
|
system("chcp 65001");
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## __教程__
|
## __教程__
|
||||||
|
@ -104,30 +105,30 @@ __`none`__ 是特殊的错误类型。这个类型用于终止虚拟机的执行
|
||||||
__`nil`__ 是空类型。类似于null。
|
__`nil`__ 是空类型。类似于null。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var spc=nil;
|
var spc = nil;
|
||||||
```
|
```
|
||||||
|
|
||||||
__`num`__ 有三种形式:十进制,十六进制以及八进制。并且该类型使用IEEE754标准的浮点数`double`格式来存储。
|
__`num`__ 有三种形式:十进制,十六进制以及八进制。并且该类型使用IEEE754标准的浮点数`double`格式来存储。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
# 该语言用 '#' 来作为注释的开头
|
# 该语言用 '#' 来作为注释的开头
|
||||||
var n=2.71828; # dec 十进制
|
var n = 2.71828; # dec 十进制
|
||||||
var n=2.147e16; # dec 十进制
|
var n = 2.147e16; # dec 十进制
|
||||||
var n=1e-10; # dec 十进制
|
var n = 1e-10; # dec 十进制
|
||||||
var n=0xAA55; # hex 十六进制
|
var n = 0xAA55; # hex 十六进制
|
||||||
var n=0o170001; # oct 八进制
|
var n = 0o170001; # oct 八进制
|
||||||
|
|
||||||
# 注意: true 和 false 关键字在现在的 nasal 里也是可用的
|
# 注意: true 和 false 关键字在现在的 nasal 里也是可用的
|
||||||
var n=true; # n 实际上是数字 1.0
|
var n = true; # n 实际上是数字 1.0
|
||||||
var n=false; # n 实际上是数字 0.0
|
var n = false; # n 实际上是数字 0.0
|
||||||
```
|
```
|
||||||
|
|
||||||
__`str`__ 也有三种不同的格式。第三种只允许包含一个的字符。
|
__`str`__ 也有三种不同的格式。第三种只允许包含一个的字符。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var s='str';
|
var s = 'str';
|
||||||
var s="another string";
|
var s = "another string";
|
||||||
var s=`c`;
|
var s = `c`;
|
||||||
# 该语言也支持一些特别的转义字符:
|
# 该语言也支持一些特别的转义字符:
|
||||||
'\a'; '\b'; '\e'; '\f';
|
'\a'; '\b'; '\e'; '\f';
|
||||||
'\n'; '\r'; '\t'; '\v';
|
'\n'; '\r'; '\t'; '\v';
|
||||||
|
@ -138,19 +139,19 @@ var s=`c`;
|
||||||
__`vec`__ 有不受限制的长度并且可以存储所有类型的数据。(当然不能超过可分配内存空间的长度)
|
__`vec`__ 有不受限制的长度并且可以存储所有类型的数据。(当然不能超过可分配内存空间的长度)
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var vec=[];
|
var vec = [];
|
||||||
var vec=[0,nil,{},[],func(){return 0}];
|
var vec = [0, nil, {}, [], func(){return 0}];
|
||||||
append(vec,0,1,2);
|
append(vec, 0, 1, 2);
|
||||||
```
|
```
|
||||||
|
|
||||||
__`hash`__ 使用哈希表 (类似于`python`中的`dict`),通过键值对来存储数据。key可以是一个字符串,也可以是一个标识符。
|
__`hash`__ 使用哈希表 (类似于`python`中的`dict`),通过键值对来存储数据。key可以是一个字符串,也可以是一个标识符。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var hash={
|
var hash = {
|
||||||
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",
|
||||||
funct:func(){
|
funct: func() {
|
||||||
return me.member2~me.member3;
|
return me.member2~me.member3;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -159,27 +160,28 @@ var hash={
|
||||||
__`func`__ 函数类型。(实际上在这个语言里函数是一种`lambda`表达式)
|
__`func`__ 函数类型。(实际上在这个语言里函数是一种`lambda`表达式)
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var f=func(x,y,z){
|
var f = func(x, y, z) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
# 函数声明可以没有参数列表以及 `(`, `)`
|
# 函数声明可以没有参数列表以及 `(`, `)`
|
||||||
var f=func{
|
var f = func {
|
||||||
return 114514;
|
return 114514;
|
||||||
}
|
}
|
||||||
var f=func(x,y,z,deft=1){
|
var f = func(x, y, z, deft = 1) {
|
||||||
return x+y+z+deft;
|
return x+y+z+deft;
|
||||||
}
|
}
|
||||||
var f=func(args...){
|
var f = func(args...) {
|
||||||
var sum=0;
|
var sum = 0;
|
||||||
foreach(var i;args)
|
foreach(var i; args) {
|
||||||
sum+=i;
|
sum += i;
|
||||||
|
}
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
__`upval`__ 是存储闭包数据的特殊类型, 在 __`vm`__ 中使用,以确保闭包功能正常。
|
__`upval`__ 是存储闭包数据的特殊类型, 在 __`vm`__ 中使用,以确保闭包功能正常。
|
||||||
|
|
||||||
__`obj`__ 是用来存储`C/C++`的一些复杂数据结构。这种类型的数据由内置函数生成。如果想为nasal添加新的数据结构, 可以看下文如何通过修改本项目来添加内置函数。
|
__`ghost`__ 是用来存储`C/C++`的一些复杂数据结构。这种类型的数据由内置函数生成。如果想为nasal添加新的数据结构, 可以看下文如何通过修改本项目来添加内置函数。
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
@ -223,16 +225,16 @@ Nasal拥有基本的四种数学运算符 `+` `-` `*` `/`以及一个特别的
|
||||||
赋值运算符`=` `+=` `-=` `*=` `/=` `~=` `^=` `&=` `|=`正如其名,用于进行赋值。
|
赋值运算符`=` `+=` `-=` `*=` `/=` `~=` `^=` `&=` `|=`正如其名,用于进行赋值。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
a=b=c=d=1;
|
a = b = c = d = 1;
|
||||||
a+=1;
|
a += 1;
|
||||||
a-=1;
|
a -= 1;
|
||||||
a*=1;
|
a *= 1;
|
||||||
a/=1;
|
a /= 1;
|
||||||
a~="string";
|
a ~= "string";
|
||||||
|
|
||||||
a^=0xff;
|
a ^= 0xff;
|
||||||
a&=0xca;
|
a &= 0xca;
|
||||||
a|=0xba;
|
a |= 0xba;
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
@ -242,9 +244,9 @@ a|=0xba;
|
||||||
如下所示。
|
如下所示。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var a=1; # 定义单个变量
|
var a = 1; # 定义单个变量
|
||||||
var (a,b,c)=[0,1,2]; # 从数组中初始化多个变量
|
var (a, b, c) = [0, 1, 2]; # 从数组中初始化多个变量
|
||||||
var (a,b,c)=(0,1,2); # 从元组中初始化多个变量
|
var (a, b, c) = (0, 1, 2); # 从元组中初始化多个变量
|
||||||
```
|
```
|
||||||
|
|
||||||
Nasal 有很多特别的全局变量:
|
Nasal 有很多特别的全局变量:
|
||||||
|
@ -278,9 +280,9 @@ func() {
|
||||||
最后这个语句通常用于交换两个变量的数据,类似于Python中的操作。
|
最后这个语句通常用于交换两个变量的数据,类似于Python中的操作。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
(a,b[0],c.d)=[0,1,2];
|
(a, b[0], c.d) = [0, 1, 2];
|
||||||
(a,b[1],c.e)=(0,1,2);
|
(a, b[1], c.e) = (0, 1, 2);
|
||||||
(a,b)=(b,a);
|
(a, b) = (b, a);
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
@ -290,13 +292,13 @@ func() {
|
||||||
nasal在提供`else if`的同时还有另外一个关键字`elsif`。该关键字与`else if`有相同的功能。
|
nasal在提供`else if`的同时还有另外一个关键字`elsif`。该关键字与`else if`有相同的功能。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
if(1){
|
if (1) {
|
||||||
;
|
;
|
||||||
}elsif(2){
|
} elsif (2) {
|
||||||
;
|
;
|
||||||
}else if(3){
|
} else if (3) {
|
||||||
;
|
;
|
||||||
}else{
|
} else {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -308,10 +310,12 @@ if(1){
|
||||||
while循环和for循环大体上与C/C++是一致的。
|
while循环和for循环大体上与C/C++是一致的。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
while(condition)
|
while(condition) {
|
||||||
continue;
|
continue;
|
||||||
for(var i=0;i<10;i+=1)
|
}
|
||||||
|
for(var i = 0; i<10; i += 1) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
同时,nasal还有另外两种直接遍历列表的循环方式:
|
同时,nasal还有另外两种直接遍历列表的循环方式:
|
||||||
|
@ -319,15 +323,17 @@ for(var i=0;i<10;i+=1)
|
||||||
`forindex` 会获取列表的下标,依次递增. 下标会从`0`递增到`size(elem)-1`结束。
|
`forindex` 会获取列表的下标,依次递增. 下标会从`0`递增到`size(elem)-1`结束。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
forindex(var i;elem)
|
forindex(var i; elem) {
|
||||||
print(elem[i]);
|
print(elem[i]);
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`foreach`会依次直接获取列表中的数据. 这些数据会从`elem[0]`依次获取到`elem[size(elem)-1]`.
|
`foreach`会依次直接获取列表中的数据. 这些数据会从`elem[0]`依次获取到`elem[size(elem)-1]`.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
foreach(var i;elem)
|
foreach(var i; elem) {
|
||||||
print(i);
|
print(i);
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
@ -338,7 +344,7 @@ nasal提供了下面第一句的类似语法来从列表中随机或者按照一
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
a[0];
|
a[0];
|
||||||
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];
|
"hello world"[0];
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -351,7 +357,7 @@ a[-1,1,0:2,0:,:3,:,nil:8,3:nil,nil:nil];
|
||||||
然而如果它用起来非常舒适,那效率也显得不是非常重要了……
|
然而如果它用起来非常舒适,那效率也显得不是非常重要了……
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
f(x:0,y:nil,z:[]);
|
f(x:0, y:nil, z:[]);
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
@ -361,10 +367,10 @@ f(x:0,y:nil,z:[]);
|
||||||
函数有这样一种直接编写函数体并且立即调用的方式:
|
函数有这样一种直接编写函数体并且立即调用的方式:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
func(x,y){
|
func(x, y) {
|
||||||
return x+y;
|
return x+y;
|
||||||
}(0,1);
|
}(0, 1);
|
||||||
func(x){
|
func(x) {
|
||||||
return 1/(1+math.exp(-x));
|
return 1/(1+math.exp(-x));
|
||||||
}(0.5);
|
}(0.5);
|
||||||
```
|
```
|
||||||
|
@ -372,11 +378,11 @@ func(x){
|
||||||
测试文件中有一个非常有趣的文件`y-combinator.nas`,可以试一试:
|
测试文件中有一个非常有趣的文件`y-combinator.nas`,可以试一试:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var fib=func(f){
|
var fib = func(f) {
|
||||||
return f(f);
|
return f(f);
|
||||||
}(
|
}(
|
||||||
func(f){
|
func(f) {
|
||||||
return func(x){
|
return func(x) {
|
||||||
if(x<2) return x;
|
if(x<2) return x;
|
||||||
return f(f)(x-1)+f(f)(x-2);
|
return f(f)(x-1)+f(f)(x-2);
|
||||||
}
|
}
|
||||||
|
@ -393,9 +399,9 @@ var fib=func(f){
|
||||||
下面这个例子里,结果是`1`:
|
下面这个例子里,结果是`1`:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var f=func(){
|
var f = func() {
|
||||||
var a=1;
|
var a = 1;
|
||||||
return func(){return a;};
|
return func() {return a;};
|
||||||
}
|
}
|
||||||
print(f()());
|
print(f()());
|
||||||
```
|
```
|
||||||
|
@ -403,14 +409,14 @@ print(f()());
|
||||||
如果善用闭包,你可以使用它来进行面向对象编程。
|
如果善用闭包,你可以使用它来进行面向对象编程。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var student=func(n,a){
|
var student = func(n, a) {
|
||||||
var (name,age)=(n,a);
|
var (name, age) = (n, a);
|
||||||
return {
|
return {
|
||||||
print_info:func() {println(name,' ',age);},
|
print_info: func() {println(name, ' ', age);},
|
||||||
set_age: func(a){age=a;},
|
set_age: func(a) {age = a;},
|
||||||
get_age: func() {return age;},
|
get_age: func() {return age;},
|
||||||
set_name: func(n){name=n;},
|
set_name: func(n) {name = n;},
|
||||||
get_name: func() {return name;}
|
get_name: func() {return name;}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -429,20 +435,20 @@ var student=func(n,a){
|
||||||
使用这个机制,我们可以进行面向对象编程,下面样例的结果是`114514`:
|
使用这个机制,我们可以进行面向对象编程,下面样例的结果是`114514`:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var trait={
|
var trait = {
|
||||||
get:func{return me.val;},
|
get: func {return me.val;},
|
||||||
set:func(x){me.val=x;}
|
set: func(x) {me.val = x;}
|
||||||
};
|
};
|
||||||
|
|
||||||
var class={
|
var class = {
|
||||||
new:func(){
|
new: func() {
|
||||||
return {
|
return {
|
||||||
val:nil,
|
val: nil,
|
||||||
parents:[trait]
|
parents: [trait]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var a=class.new();
|
var a = class.new();
|
||||||
a.set(114514);
|
a.set(114514);
|
||||||
println(a.get());
|
println(a.get());
|
||||||
```
|
```
|
||||||
|
@ -453,28 +459,28 @@ println(a.get());
|
||||||
不过我们必须提醒你一点,如果你在这个地方使用该优化来减少hash的搜索开销:
|
不过我们必须提醒你一点,如果你在这个地方使用该优化来减少hash的搜索开销:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var trait={
|
var trait = {
|
||||||
get:func{return me.val;},
|
get: func {return me.val;},
|
||||||
set:func(x){me.val=x;}
|
set: func(x) {me.val = x;}
|
||||||
};
|
};
|
||||||
|
|
||||||
var class={
|
var class = {
|
||||||
new:func(){
|
new: func() {
|
||||||
return {
|
return {
|
||||||
val:nil,
|
val: nil,
|
||||||
parents:[trait]
|
parents: [trait]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var a=class.new();
|
var a = class.new();
|
||||||
var b=class.new();
|
var b = class.new();
|
||||||
a.set(114);
|
a.set(114);
|
||||||
b.set(514);
|
b.set(514);
|
||||||
println(a.get());
|
println(a.get());
|
||||||
println(b.get());
|
println(b.get());
|
||||||
|
|
||||||
var c=a.get;
|
var c = a.get;
|
||||||
var d=b.get;
|
var d = b.get;
|
||||||
|
|
||||||
println(c());
|
println(c());
|
||||||
println(c());
|
println(c());
|
||||||
|
@ -506,42 +512,27 @@ println(d());
|
||||||
|
|
||||||
__警告:__ 如果你 __不想__ 通过直接修改解释器源码来添加你自定义的函数,那么你应该看下一个节 __`模块`__ 的内容。
|
__警告:__ 如果你 __不想__ 通过直接修改解释器源码来添加你自定义的函数,那么你应该看下一个节 __`模块`__ 的内容。
|
||||||
|
|
||||||
如果你确实是想修改源码来搞一个自己私人订制的解释器,那么你可以说:“我他妈就是想自己私人订制,你们他妈的管得着吗”,
|
如果你确实是想修改源码来搞一个自己私人订制的解释器 ———— “我他妈就是想自己私人订制,你们他妈的管得着吗?”,
|
||||||
然后看看源码中关于内置函数的部分,以及`lib.nas`中是如何包装这些函数的,还有下面的样例:
|
参考源码中关于内置函数的部分,以及`lib.nas`中是如何包装这些函数的,下面是其中一个样例:
|
||||||
|
|
||||||
定义新的内置函数:
|
定义新的内置函数:
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
// 你可以使用这个宏来直接定义一个新的内置函数
|
// 你可以使用这个宏来直接定义一个新的内置函数
|
||||||
nas_native(builtin_print);
|
var builtin_print(context*, gc*);
|
||||||
```
|
```
|
||||||
|
|
||||||
然后用C++完成这个函数的函数体:
|
然后用C++完成这个函数的函数体:
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
var builtin_print(var* local,gc& ngc)
|
var builtin_print(context* ctx, gc* ngc) {
|
||||||
{
|
// 局部变量的下标其实是从 1 开始的
|
||||||
// 局部变量的下标其实是从1开始的
|
// 因为 local[0] 是保留给 'me' 的空间
|
||||||
// 因为local[0]是保留给'me'的空间
|
for(auto& i : ctx->localr[1].vec().elems) {
|
||||||
var vec=local[1];
|
std::cout << i;
|
||||||
// 主要部分
|
}
|
||||||
// 一些必要的类型检查和输入合法性检测也要在这里写出
|
std::cout << std::flush;
|
||||||
// 如果检测到问题,用builtin_err函数来返回vm_null
|
// 最后生成返回值,返回值必须是一个内置的类型,
|
||||||
// 并且狠狠地骂那些不好好写代码的混蛋(玩笑)
|
|
||||||
for(auto& i:vec.vec().elems)
|
|
||||||
switch(i.type)
|
|
||||||
{
|
|
||||||
case vm_none: std::cout<<"undefined"; break;
|
|
||||||
case vm_nil: std::cout<<"nil"; break;
|
|
||||||
case vm_num: std::cout<<i.num(); break;
|
|
||||||
case vm_str: std::cout<<i.str(); break;
|
|
||||||
case vm_vec: std::cout<<i.vec(); break;
|
|
||||||
case vm_hash: std::cout<<i.hash(); break;
|
|
||||||
case vm_func: std::cout<<"func(..){..}";break;
|
|
||||||
case vm_obj: std::cout<<"<object>"; break;
|
|
||||||
}
|
|
||||||
std::cout<<std::flush;
|
|
||||||
// 最后一定要记得生成返回值,返回值必须是一个内置的类型,
|
|
||||||
// 可以使用ngc::alloc(type)来申请一个需要内存管理的复杂数据结构
|
// 可以使用ngc::alloc(type)来申请一个需要内存管理的复杂数据结构
|
||||||
// 或者用我们已经定义好的nil/one/zero,这些可以直接使用
|
// 或者用我们已经定义好的nil/one/zero,这些可以直接使用
|
||||||
return nil;
|
return nil;
|
||||||
|
@ -554,17 +545,24 @@ var builtin_print(var* local,gc& ngc)
|
||||||
可以使用`gc::temp`来暂时存储一个会被返回的需要gc管理的变量,这样可以防止内部所有的申请错误触发垃圾回收。如下所示:
|
可以使用`gc::temp`来暂时存储一个会被返回的需要gc管理的变量,这样可以防止内部所有的申请错误触发垃圾回收。如下所示:
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
var builtin_keys(var* local,gc& ngc)
|
var builtin_keys(context* ctx, gc* ngc) {
|
||||||
{
|
auto hash = ctx->localr[1];
|
||||||
var hash=local[1];
|
if (hash.type!=vm_hash && hash.type!=vm_map) {
|
||||||
if(hash.type!=vm_hash)
|
return nas_err("keys", "\"hash\" must be hash");
|
||||||
return nas_err("keys","\"hash\" must be hash");
|
}
|
||||||
// 使用gc.temp来存储gc管理的变量,防止错误的回收
|
// 使用gc.temp来存储gc管理的变量,防止错误的回收
|
||||||
var res=ngc.temp=ngc.alloc(vm_vec);
|
auto res = ngc->temp = ngc->alloc(vm_vec);
|
||||||
auto& vec=res.vec().elems;
|
auto& vec = res.vec().elems;
|
||||||
for(auto& iter:hash.hash().elems)
|
if (hash.type==vm_hash) {
|
||||||
vec.push_back(ngc.newstr(iter.first));
|
for(const auto& iter : hash.hash().elems) {
|
||||||
ngc.temp=nil;
|
vec.push_back(ngc->newstr(iter.first));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(const auto& iter : hash.map().mapper) {
|
||||||
|
vec.push_back(ngc->newstr(iter.first));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ngc->temp = nil;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -572,21 +570,16 @@ var builtin_keys(var* local,gc& ngc)
|
||||||
这些工作都完成之后,在内置函数注册表中填写它在nasal中的别名,并且在表中填对这个函数的函数指针:
|
这些工作都完成之后,在内置函数注册表中填写它在nasal中的别名,并且在表中填对这个函数的函数指针:
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
struct func
|
nasal_builtin_table builtin[] = {
|
||||||
{
|
{"__print", builtin_print},
|
||||||
const char* name;
|
{nullptr, nullptr}
|
||||||
var (*func)(var*,gc&);
|
|
||||||
} builtin[]=
|
|
||||||
{
|
|
||||||
{"__print",builtin_print},
|
|
||||||
{nullptr, nullptr }
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
最后,将其包装到nasal文件中:
|
最后,将其包装到nasal文件中:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var print=func(elems...){
|
var print = func(elems...) {
|
||||||
return __print(elems);
|
return __print(elems);
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
@ -594,7 +587,7 @@ var print=func(elems...){
|
||||||
事实上`__print`后面跟着的传参列表不是必须要写的。所以这样写也对:
|
事实上`__print`后面跟着的传参列表不是必须要写的。所以这样写也对:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var print=func(elems...){
|
var print = func(elems...) {
|
||||||
return __print;
|
return __print;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
@ -705,7 +698,7 @@ Windows(`.dll`):
|
||||||
use std.dylib;
|
use std.dylib;
|
||||||
var dlhandle = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
var dlhandle = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
||||||
var fib = dlhandle.fib;
|
var fib = dlhandle.fib;
|
||||||
for(var i = 1; i<30; i+=1)
|
for(var i = 1; i<30; i += 1)
|
||||||
println(dylib.dlcall(fib, i));
|
println(dylib.dlcall(fib, i));
|
||||||
dylib.dlclose(dlhandle.lib);
|
dylib.dlclose(dlhandle.lib);
|
||||||
```
|
```
|
||||||
|
@ -723,7 +716,7 @@ use std.dylib;
|
||||||
var dlhandle = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
var dlhandle = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
||||||
var fib = dlhandle.fib;
|
var fib = dlhandle.fib;
|
||||||
var invoke = dylib.limitcall(1); # this means the called function has only one parameter
|
var invoke = dylib.limitcall(1); # this means the called function has only one parameter
|
||||||
for(var i = 1; i<30; i+=1)
|
for(var i = 1; i<30; i += 1)
|
||||||
println(invoke(fib, i));
|
println(invoke(fib, i));
|
||||||
dylib.dlclose(dlhandle.lib);
|
dylib.dlclose(dlhandle.lib);
|
||||||
```
|
```
|
||||||
|
@ -767,7 +760,7 @@ dylib.dlclose(dlhandle.lib);
|
||||||
|
|
||||||
<details><summary> 自定义类型(开发者教程) </summary>
|
<details><summary> 自定义类型(开发者教程) </summary>
|
||||||
|
|
||||||
创建一个自定义类型现在不是很困难。下面是使用示例:
|
创建一个自定义类型很容易。下面是使用示例:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
const auto ghost_for_test = "ghost_for_test";
|
const auto ghost_for_test = "ghost_for_test";
|
||||||
|
@ -785,19 +778,31 @@ void ghost_for_test_destructor(void* ptr) {
|
||||||
var create_new_ghost(var* args, usize size, gc* ngc) {
|
var create_new_ghost(var* args, usize size, gc* ngc) {
|
||||||
var res = ngc->alloc(vm_obj);
|
var res = ngc->alloc(vm_obj);
|
||||||
// 创建自定义类型
|
// 创建自定义类型
|
||||||
res.obj().set(ghost_for_test, ghost_for_test_destructor, new u32);
|
res.ghost().set(ghost_for_test, ghost_for_test_destructor, new u32);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var set_new_ghost(var* args, usize size, gc* ngc) {
|
||||||
|
var res = args[0];
|
||||||
|
if (!res.object_check(ghost_for_test)) {
|
||||||
|
std::cout << "set_new_ghost: not ghost for test type.\n";
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
f64 num = args[1].num();
|
||||||
|
*(reinterpret_cast<u32*>(res.ghost().pointer)) = static_cast<u32>(num);
|
||||||
|
std::cout << "set_new_ghost: successfully set ghost = " << num << "\n";
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
var print_new_ghost(var* args, usize size, gc* ngc) {
|
var print_new_ghost(var* args, usize size, gc* ngc) {
|
||||||
var res = args[0];
|
var res = args[0];
|
||||||
// 用自定义类型的名字来检查是否是正确的自定义类型
|
// 用自定义类型的名字来检查是否是正确的自定义类型
|
||||||
if (!res.objchk(ghost_for_test)) {
|
if (!res.object_check(ghost_for_test)) {
|
||||||
std::cout << "print_new_ghost: not ghost for test type.\n";
|
std::cout << "print_new_ghost: not ghost for test type.\n";
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
std::cout << "print_new_ghost: " << res.obj() << " result = "
|
std::cout << "print_new_ghost: " << res.ghost() << " result = "
|
||||||
<< *((u32*)res.obj().ptr) << "\n";
|
<< *((u32*)res.ghost().pointer) << "\n";
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -814,7 +819,7 @@ var print_new_ghost(var* args, usize size, gc* ngc) {
|
||||||
|
|
||||||
我们使用下面的这个函数检测是否是正确的自定义类型:
|
我们使用下面的这个函数检测是否是正确的自定义类型:
|
||||||
|
|
||||||
`bool var::objchk(const std::string&);`
|
`bool var::object_check(const std::string&);`
|
||||||
|
|
||||||
参数是自定义类型的类型名。
|
参数是自定义类型的类型名。
|
||||||
|
|
||||||
|
@ -832,7 +837,7 @@ var print_new_ghost(var* args, usize size, gc* ngc) {
|
||||||
在Andy的解释器中:
|
在Andy的解释器中:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
foreach(i;[0,1,2,3])
|
foreach(i; [0, 1, 2, 3])
|
||||||
print(i)
|
print(i)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -844,7 +849,7 @@ foreach(i;[0,1,2,3])
|
||||||
code: undefined symbol "i"
|
code: undefined symbol "i"
|
||||||
--> test.nas:1:9
|
--> test.nas:1:9
|
||||||
|
|
|
|
||||||
1 | foreach(i;[0,1,2,3])
|
1 | foreach(i; [0, 1, 2, 3])
|
||||||
| ^ undefined symbol "i"
|
| ^ undefined symbol "i"
|
||||||
|
|
||||||
code: undefined symbol "i"
|
code: undefined symbol "i"
|
||||||
|
@ -866,8 +871,7 @@ code: undefined symbol "i"
|
||||||
`die`函数用于直接抛出错误并终止执行。
|
`die`函数用于直接抛出错误并终止执行。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
func()
|
func() {
|
||||||
{
|
|
||||||
println("hello");
|
println("hello");
|
||||||
die("error occurred this line");
|
die("error occurred this line");
|
||||||
return;
|
return;
|
||||||
|
@ -877,17 +881,27 @@ func()
|
||||||
```javascript
|
```javascript
|
||||||
hello
|
hello
|
||||||
[vm] error: error occurred this line
|
[vm] error: error occurred this line
|
||||||
[vm] native function error.
|
[vm] error: error occurred in native function
|
||||||
trace back:
|
|
||||||
0x000000ac 40 00 00 00 25 callb 0x25 <__die@0x41afc0> (lib.nas:131)
|
call trace (main)
|
||||||
0x000004f6 3e 00 00 00 01 callfv 0x1 (a.nas:4)
|
call func@0x557513935710() {entry: 0x850}
|
||||||
0x000004fa 3e 00 00 00 00 callfv 0x0 (a.nas:6)
|
|
||||||
vm stack (0x7fffcd21bc68 <sp+80>, limit 10, total 12):
|
trace back (main)
|
||||||
0x0000005b | null |
|
0x000547 4c 00 00 16 callb 0x16 <__die@0x557512441780>(std/lib.nas:150)
|
||||||
...
|
0x000856 4a 00 00 01 callfv 0x1(a.nas:3)
|
||||||
0x00000057 | str | <0x138ff60> error occurred t...
|
0x00085a 4a 00 00 00 callfv 0x0(a.nas:5)
|
||||||
...
|
|
||||||
0x00000052 | nil |
|
stack (0x5575138e8c40, limit 10, total 14)
|
||||||
|
0x00000d | null |
|
||||||
|
0x00000c | pc | 0x856
|
||||||
|
0x00000b | addr | 0x5575138e8c50
|
||||||
|
0x00000a | nil |
|
||||||
|
0x000009 | nil |
|
||||||
|
0x000008 | str | <0x5575138d9190> error occurred t...
|
||||||
|
0x000007 | nil |
|
||||||
|
0x000006 | func | <0x5575139356f0> entry:0x850
|
||||||
|
0x000005 | pc | 0x85a
|
||||||
|
0x000004 | addr | 0x0
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
@ -897,28 +911,41 @@ vm stack (0x7fffcd21bc68 <sp+80>, limit 10, total 12):
|
||||||
这是一个会导致栈溢出的例子:
|
这是一个会导致栈溢出的例子:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
func(f){
|
func(f) {
|
||||||
return f(f);
|
return f(f);
|
||||||
}(
|
}(
|
||||||
func(f){
|
func(f) {
|
||||||
f(f);
|
f(f);
|
||||||
}
|
}
|
||||||
)();
|
)();
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
[vm] stack overflow
|
[vm] error: stack overflow
|
||||||
trace back:
|
|
||||||
0x000004fb 3e 00 00 00 01 callfv 0x1 (a.nas:5)
|
call trace (main)
|
||||||
0x000004fb 1349 same call(s)
|
call func@0x564106058620(f) {entry: 0x859}
|
||||||
0x000004f3 3e 00 00 00 01 callfv 0x1 (a.nas:2)
|
--> 583 same call(s)
|
||||||
0x000004ff 3e 00 00 00 01 callfv 0x1 (a.nas:3)
|
call func@0x5641060586c0(f) {entry: 0x851}
|
||||||
vm stack (0x7fffd3781d58 <sp+80>, limit 10, total 8108):
|
|
||||||
0x00001ffb | func | <0x15f8d90> entry:0x4f9
|
trace back (main)
|
||||||
0x00001ffa | func | <0x15f8d90> entry:0x4f9
|
0x000859 45 00 00 01 calll 0x1(a.nas:5)
|
||||||
0x00001ff9 | pc | 0x4fb
|
0x00085b 4a 00 00 01 callfv 0x1(a.nas:5)
|
||||||
...
|
0x00085b 582 same call(s)
|
||||||
0x00001ff2 | addr | 0x7fffd37a16e8
|
0x000853 4a 00 00 01 callfv 0x1(a.nas:2)
|
||||||
|
0x00085f 4a 00 00 01 callfv 0x1(a.nas:3)
|
||||||
|
|
||||||
|
stack (0x56410600be00, limit 10, total 4096)
|
||||||
|
0x000fff | func | <0x564106058600> entry:0x859
|
||||||
|
0x000ffe | pc | 0x85b
|
||||||
|
0x000ffd | addr | 0x56410601bd20
|
||||||
|
0x000ffc | nil |
|
||||||
|
0x000ffb | nil |
|
||||||
|
0x000ffa | func | <0x564106058600> entry:0x859
|
||||||
|
0x000ff9 | nil |
|
||||||
|
0x000ff8 | func | <0x564106058600> entry:0x859
|
||||||
|
0x000ff7 | pc | 0x85b
|
||||||
|
0x000ff6 | addr | 0x56410601bcb0
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
@ -928,17 +955,19 @@ vm stack (0x7fffd3781d58 <sp+80>, limit 10, total 8108):
|
||||||
如果在执行的时候出现错误,程序会直接终止执行:
|
如果在执行的时候出现错误,程序会直接终止执行:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
func(){
|
func() {
|
||||||
return 0;
|
return 0;
|
||||||
}()[1];
|
}()[1];
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
[vm] callv: must call a vector/hash/string
|
[vm] error: must call a vector/hash/string but get number
|
||||||
trace back:
|
|
||||||
0x000004f4 3b 00 00 00 00 callv 0x0 (a.nas:3)
|
trace back (main)
|
||||||
vm stack (0x7fffff539c28 <sp+80>, limit 10, total 1):
|
0x000854 47 00 00 00 callv 0x0(a.nas:3)
|
||||||
0x00000050 | num | 0
|
|
||||||
|
stack (0x564993f462b0, limit 10, total 1)
|
||||||
|
0x000000 | num | 0
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
@ -950,35 +979,48 @@ vm stack (0x7fffff539c28 <sp+80>, limit 10, total 1):
|
||||||
```javascript
|
```javascript
|
||||||
hello
|
hello
|
||||||
[vm] error: error occurred this line
|
[vm] error: error occurred this line
|
||||||
[vm] error: native function error
|
[vm] error: error occurred in native function
|
||||||
|
|
||||||
|
call trace (main)
|
||||||
|
call func@0x55dcb5b8fbf0() {entry: 0x850}
|
||||||
|
|
||||||
trace back (main)
|
trace back (main)
|
||||||
0x000000b0 40 00 00 00 2b callb 0x2b <__die@0x41c380> (lib.nas:131)
|
0x000547 4c 00 00 16 callb 0x16 <__die@0x55dcb3c41780>(std/lib.nas:150)
|
||||||
0x00000553 3e 00 00 00 01 callfv 0x1 (test.nas:4)
|
0x000856 4a 00 00 01 callfv 0x1(a.nas:3)
|
||||||
0x00000557 3e 00 00 00 00 callfv 0x0 (test.nas:6)
|
0x00085a 4a 00 00 00 callfv 0x0(a.nas:5)
|
||||||
vm stack (0x7fffe0ffed90 <sp+63>, limit 10, total 12)
|
|
||||||
0x0000004a | null |
|
stack (0x55dcb5b43120, limit 10, total 14)
|
||||||
0x00000049 | pc | 0x553
|
0x00000d | null |
|
||||||
0x00000048 | addr | 0x7fffe0ffeda0
|
0x00000c | pc | 0x856
|
||||||
...
|
0x00000b | addr | 0x55dcb5b43130
|
||||||
0x00000041 | nil |
|
0x00000a | nil |
|
||||||
|
0x000009 | nil |
|
||||||
|
0x000008 | str | <0x55dcb5b33670> error occurred t...
|
||||||
|
0x000007 | nil |
|
||||||
|
0x000006 | func | <0x55dcb5b8fbd0> entry:0x850
|
||||||
|
0x000005 | pc | 0x85a
|
||||||
|
0x000004 | addr | 0x0
|
||||||
|
|
||||||
registers (main)
|
registers (main)
|
||||||
[ pc ] | pc | 0xb0
|
[pc ] | pc | 0x547
|
||||||
[ global ] | addr | 0x7fffe0ffe9a0
|
[global] | addr | 0x55dcb5b53130
|
||||||
[ localr ] | addr | 0x7fffe0ffedf0
|
[local ] | addr | 0x55dcb5b43190
|
||||||
[ memr ] | addr | 0x0
|
[memr ] | addr | 0x0
|
||||||
[ canary ] | addr | 0x7fffe1002990
|
[canary] | addr | 0x55dcb5b53110
|
||||||
[ top ] | addr | 0x7fffe0ffee40
|
[top ] | addr | 0x55dcb5b431f0
|
||||||
[ funcr ] | func | <0x677cd0> entry:0xb0
|
[funcr ] | func | <0x55dcb5b65620> entry:0x547
|
||||||
[ upvalr ] | nil |
|
[upval ] | nil |
|
||||||
global (0x7fffe0ffe9a0 <sp+0>)
|
|
||||||
0x00000000 | func | <0x65fb00> entry:0x5
|
global (0x55dcb5b53130)
|
||||||
0x00000001 | func | <0x65fb20> entry:0xd
|
0x000000 | nmspc| <0x55dcb5b33780> namespace [95 val]
|
||||||
|
0x000001 | vec | <0x55dcb5b64c20> [0 val]
|
||||||
...
|
...
|
||||||
0x0000003d | func | <0x66bf00> entry:0x51f
|
0x00005e | func | <0x55dcb5b8fc70> entry:0x846
|
||||||
0x0000003e | hash | <0x65ffa0> {5 val}
|
|
||||||
local (0x7fffe0ffedf0 <sp+45>)
|
local (0x55dcb5b43190 <+7>)
|
||||||
0x00000000 | nil |
|
0x000000 | nil |
|
||||||
0x00000001 | str | <0x6cb630> error occurred t...
|
0x000001 | str | <0x55dcb5b33670> error occurred t...
|
||||||
|
0x000002 | nil |
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
@ -1002,16 +1044,18 @@ source code:
|
||||||
for(var i=0;i<31;i+=1)
|
for(var i=0;i<31;i+=1)
|
||||||
print(fib(i),'\n');
|
print(fib(i),'\n');
|
||||||
|
|
||||||
|
|
||||||
next bytecode:
|
next bytecode:
|
||||||
--> 0x00000000 01 00 00 00 41 intg 0x41 (test/fib.nas:0)
|
0x000848 4a 00 00 01 callfv 0x1(std/lib.nas:427)
|
||||||
0x00000001 0b 00 00 00 05 newf 0x5 (lib.nas:6)
|
0x000849 3d 00 00 00 pop 0x0(std/lib.nas:427)
|
||||||
0x00000002 02 00 00 00 02 intl 0x2 (lib.nas:6)
|
0x00084a 07 00 00 00 pnil 0x0(std/lib.nas:423)
|
||||||
0x00000003 0f 00 00 00 00 dyn 0x0 ("elems") (lib.nas:6)
|
0x00084b 56 00 00 00 ret 0x0(std/lib.nas:423)
|
||||||
0x00000004 32 00 00 00 07 jmp 0x7 (lib.nas:6)
|
0x00084c 03 00 00 5e loadg 0x5e(std/lib.nas:423)
|
||||||
0x00000005 40 00 00 00 00 callb 0x0 <__print@0x419c80> (lib.nas:7)
|
--> 0x00084d 0b 00 08 51 newf 0x851(test/fib.nas:1)
|
||||||
0x00000006 4a 00 00 00 00 ret 0x0 (lib.nas:7)
|
0x00084e 02 00 00 03 intl 0x3(test/fib.nas:1)
|
||||||
0x00000007 03 00 00 00 00 loadg 0x0 (lib.nas:6)
|
0x00084f 0d 00 00 08 para 0x8 (x)(test/fib.nas:1)
|
||||||
vm stack (0x7fffd0259138 <sp+65>, limit 10, total 0)
|
|
||||||
|
stack (0x55ccd0a1b9d0, limit 10, total 0)
|
||||||
>>
|
>>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1034,23 +1078,26 @@ source code:
|
||||||
for(var i=0;i<31;i+=1)
|
for(var i=0;i<31;i+=1)
|
||||||
print(fib(i),'\n');
|
print(fib(i),'\n');
|
||||||
|
|
||||||
|
|
||||||
next bytecode:
|
next bytecode:
|
||||||
0x00000548 0c 00 00 00 aa happ 0xaa ("running") (lib.nas:503)
|
0x000850 3e 00 08 60 jmp 0x860(test/fib.nas:1)
|
||||||
0x00000549 03 00 00 00 3e loadg 0x3e (lib.nas:498)
|
--> 0x000851 45 00 00 01 calll 0x1(test/fib.nas:3)
|
||||||
0x0000054a 0b 00 00 05 4e newf 0x54e (test/fib.nas:1)
|
0x000852 39 00 00 07 lessc 0x7 (2)(test/fib.nas:3)
|
||||||
0x0000054b 02 00 00 00 02 intl 0x2 (test/fib.nas:1)
|
0x000853 40 00 08 56 jf 0x856(test/fib.nas:3)
|
||||||
0x0000054c 0d 00 00 00 1b para 0x1b ("x") (test/fib.nas:1)
|
0x000854 45 00 00 01 calll 0x1(test/fib.nas:3)
|
||||||
0x0000054d 32 00 00 05 5d jmp 0x55d (test/fib.nas:1)
|
0x000855 56 00 00 00 ret 0x0(test/fib.nas:3)
|
||||||
--> 0x0000054e 39 00 00 00 01 calll 0x1 (test/fib.nas:3)
|
0x000856 44 00 00 5f callg 0x5f(test/fib.nas:4)
|
||||||
0x0000054f 2d 00 00 00 03 lessc 0x3 (2) (test/fib.nas:3)
|
0x000857 45 00 00 01 calll 0x1(test/fib.nas:4)
|
||||||
vm stack (0x7fffd0259138 <sp+65>, limit 10, total 7)
|
|
||||||
0x00000047 | pc | 0x566
|
stack (0x55ccd0a1b9d0, limit 10, total 8)
|
||||||
0x00000046 | addr | 0x0
|
0x000007 | pc | 0x869
|
||||||
0x00000045 | nil |
|
0x000006 | addr | 0x0
|
||||||
0x00000044 | num | 0
|
0x000005 | nil |
|
||||||
0x00000043 | nil |
|
0x000004 | nil |
|
||||||
0x00000042 | nil |
|
0x000003 | num | 0
|
||||||
0x00000041 | func | <0x88d2f0> entry:0x5
|
0x000002 | nil |
|
||||||
|
0x000001 | nil |
|
||||||
|
0x000000 | func | <0x55ccd0a58fa0> entry:0x487
|
||||||
>>
|
>>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1077,3 +1124,22 @@ Nasal REPL interpreter version 11.0 (Oct 7 2023 17:28:31)
|
||||||
|
|
||||||
>>>
|
>>>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
试试引入 `std/json.nas` 模块 ~
|
||||||
|
|
||||||
|
```bash
|
||||||
|
[nasal-repl] Initializating enviroment...
|
||||||
|
[nasal-repl] Initialization complete.
|
||||||
|
|
||||||
|
Nasal REPL interpreter version 11.1 (Nov 1 2023 23:37:30)
|
||||||
|
.h, .help | show help
|
||||||
|
.e, .exit | quit the REPL
|
||||||
|
.q, .quit | quit the REPL
|
||||||
|
.c, .clear | clear the screen
|
||||||
|
.s, .source | show source code
|
||||||
|
|
||||||
|
>>> use std.json;
|
||||||
|
{stringify:func(..) {..},parse:func(..) {..}}
|
||||||
|
|
||||||
|
>>>
|
||||||
|
```
|
||||||
|
|
|
@ -62,3 +62,27 @@ var example_module = func {
|
||||||
};
|
};
|
||||||
}();
|
}();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Import a module
|
||||||
|
|
||||||
|
Here is a module named `std/example_module.nas`:
|
||||||
|
|
||||||
|
```nasal
|
||||||
|
var a = 1;
|
||||||
|
```
|
||||||
|
|
||||||
|
Then there's a script file named `test.nas`, import module in this file using this way:
|
||||||
|
|
||||||
|
```nasal
|
||||||
|
use std.example_module;
|
||||||
|
|
||||||
|
println(example_module.a); # 1
|
||||||
|
```
|
||||||
|
|
||||||
|
Or this way:
|
||||||
|
|
||||||
|
```nasal
|
||||||
|
import("std/example_module.nas");
|
||||||
|
|
||||||
|
println(example_module.a); # 1
|
||||||
|
```
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1> Nasal | Not another scripting language!</h1>
|
<h1> Nasal | Not another scripting language!</h1>
|
||||||
|
<img src="/doc/pic/social.png" width="900" height="400" style="margin-left: 15px;"><br /></img>
|
||||||
<div class="badges">
|
<div class="badges">
|
||||||
<a href="https://github.com/ValKmjolnir/Nasal-Interpreter"><img src="https://img.shields.io/github/languages/code-size/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github"></img></a>
|
<a href="https://github.com/ValKmjolnir/Nasal-Interpreter"><img src="https://img.shields.io/github/languages/code-size/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github"></img></a>
|
||||||
<a href="https://github.com/ValKmjolnir/Nasal-Interpreter"><img src="https://img.shields.io/github/v/release/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github"></img></a>
|
<a href="https://github.com/ValKmjolnir/Nasal-Interpreter"><img src="https://img.shields.io/github/v/release/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github"></img></a>
|
||||||
|
|
|
@ -64,7 +64,7 @@ var set_new_ghost(var* args, usize size, gc* ngc) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
f64 num = args[1].num();
|
f64 num = args[1].num();
|
||||||
*((u32*)res.ghost().pointer) = static_cast<u32>(num);
|
*(reinterpret_cast<u32*>(res.ghost().pointer)) = static_cast<u32>(num);
|
||||||
std::cout << "set_new_ghost: successfully set ghost = " << num << "\n";
|
std::cout << "set_new_ghost: successfully set ghost = " << num << "\n";
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ var nas_connect(var* args, usize size, gc* ngc) {
|
||||||
memcpy(&addr.sin_addr, entry->h_addr, entry->h_length);
|
memcpy(&addr.sin_addr, entry->h_addr, entry->h_length);
|
||||||
return var::num(static_cast<double>(connect(
|
return var::num(static_cast<double>(connect(
|
||||||
args[0].num(),
|
args[0].num(),
|
||||||
(sockaddr*)&addr,
|
reinterpret_cast<sockaddr*>(&addr),
|
||||||
sizeof(sockaddr_in)
|
sizeof(sockaddr_in)
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ var nas_accept(var* args, usize size, gc* ngc) {
|
||||||
#else
|
#else
|
||||||
int client_sd = accept(args[0].num(), (sockaddr*)&client, (socklen_t*)&socklen);
|
int client_sd = accept(args[0].num(), (sockaddr*)&client, (socklen_t*)&socklen);
|
||||||
#endif
|
#endif
|
||||||
var res=ngc->temp = ngc->alloc(vm_hash);
|
var res = ngc->temp = ngc->alloc(vm_hash);
|
||||||
auto& hash = res.hash().elems;
|
auto& hash = res.hash().elems;
|
||||||
hash["sd"] = var::num(static_cast<double>(client_sd));
|
hash["sd"] = var::num(static_cast<double>(client_sd));
|
||||||
hash["ip"] = ngc->newstr(inet_ntoa(client.sin_addr));
|
hash["ip"] = ngc->newstr(inet_ntoa(client.sin_addr));
|
||||||
|
|
|
@ -260,7 +260,7 @@ var builtin_keys(context* ctx, gc* ngc) {
|
||||||
vec.push_back(ngc->newstr(iter.first));
|
vec.push_back(ngc->newstr(iter.first));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ngc->temp=nil;
|
ngc->temp = nil;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -320,6 +320,7 @@ while(1){
|
||||||
elsif(path=="/license")
|
elsif(path=="/license")
|
||||||
http.send(client,respond.ok(io.readfile("./LICENSE")));
|
http.send(client,respond.ok(io.readfile("./LICENSE")));
|
||||||
elsif(path=="/doc/pic/nasal.png" or
|
elsif(path=="/doc/pic/nasal.png" or
|
||||||
|
path=="/doc/pic/social.png" or
|
||||||
path=="/doc/pic/benchmark.png" or
|
path=="/doc/pic/benchmark.png" or
|
||||||
path=="/doc/pic/mandelbrot.png" or
|
path=="/doc/pic/mandelbrot.png" or
|
||||||
path=="/doc/pic/feigenbaum.png" or
|
path=="/doc/pic/feigenbaum.png" or
|
||||||
|
|
Loading…
Reference in New Issue