📝 change README.md & README_zh.md

This commit is contained in:
ValKmjolnir
2022-07-24 17:05:36 +08:00
parent afbee18e26
commit c702f02a8a
2 changed files with 126 additions and 176 deletions
+64 -87
View File
@@ -8,8 +8,8 @@
\_\ \/ \__,_|___/\__,_|_|
```
![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github)
![GitHub release (latest by date)](https://img.shields.io/github/v/release/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github)
![GitHub code size](https://img.shields.io/github/languages/code-size/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github)
![GitHub release(latest by date)](https://img.shields.io/github/v/release/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github)
![in dev](https://img.shields.io/badge/dev-v10.0-blue?style=flat-square&logo=github)
[![license](https://img.shields.io/badge/license-MIT-green?style=flat-square&logo=github)](../LICENSE)
@@ -20,20 +20,7 @@
* [__简介__](#简介)
* [__编译__](#编译)
* [__使用方法__](#使用方法)
* [__教程__](#教程)<details><summary>展开</summary>
* [基本类型](#基本类型)
* [运算符](#运算符)
* [定义变量](#定义变量)
* [多变量赋值](#多变量赋值)
* [条件语句](#条件语句)
* [循环语句](#循环语句)
* [生成子列表](#生成子列表)
* [特殊函数调用语法](#特殊函数调用语法)
* [lambda表达式](#lambda表达式)
* [闭包](#闭包)
* [trait(特性)](#特性)
* [内置函数](#内置函数)
* [模块](#模块开发者教程)</summary>
* [__教程__](#教程)
* [__发行日志__](../doc/dev_zh.md#发行日志)
* [__开发历史__](../doc/dev_zh.md)
* [__测试数据__](../doc/benchmark.md)
@@ -138,10 +125,10 @@ if(os.platform()=="windows")
## __教程__
nasal是非常容易上手的,你甚至可以在15分钟之内看完这里的基本教程并且直接开始编写你想要的程序。
Nasal是非常容易上手的,你甚至可以在15分钟之内看完这里的基本教程并且直接开始编写你想要的程序。
__如果你先前已经是C/C++,javascript选手,那么这个教程几乎可以不用看了……__ 在看完该教程之后,基本上你就完全掌握了这个语言:
### __基本类型__
<details><summary><text style="font-weight:700">基本类型</text></summary>
__`vm_none`__ 是特殊的错误类型。这个类型用于终止虚拟机的执行,用户是无法申请到这个类型的,该类型只能由字节码虚拟机自己在抛出错误时产生。
@@ -155,11 +142,9 @@ __`vm_num`__ 有三种形式:十进制,十六进制以及八进制。并且该
```javascript
# this language use '#' to write notes
var n=1; # dec
var n=2.71828; # dec
var n=2.147e16; # dec
var n=1e-10; # dec
var n=0x7fffffff; # hex
var n=0xAA55; # hex
var n=0o170001; # oct
```
@@ -170,9 +155,7 @@ __`vm_str`__ 也有三种不同的格式。第三种只允许包含一个的字
var s='str';
var s="another string";
var s=`c`;
# 该语言也支持一些特别的转义字符:
'\a'; '\b'; '\e'; '\f';
'\n'; '\r'; '\t'; '\v';
'\0'; '\\'; '\?'; '\'';
@@ -183,13 +166,7 @@ __`vm_vec`__ 有不受限制的长度并且可以存储所有类型的数据。(
```javascript
var vec=[];
var vec=[
0,
nil,
{},
[],
func(){return 0;}
];
var vec=[0,nil,{},[],func(){return 0}];
append(vec,0,1,2);
```
@@ -199,10 +176,9 @@ __`vm_hash`__ 使用哈希表(类似于`python`中的字典),通过键值对
var hash={
member1:nil,
member2:"str",
'member3':'member\'s name can also be a string constant',
function:func(){
var a=me.member2~me.member3;
return a;
"member3":"member\'s name can also be a string constant",
funct:func(){
return me.member2~me.member3;
}
};
```
@@ -210,14 +186,10 @@ var hash={
__`vm_func`__ 函数类型。(实际上在这个语言里函数也是一种lambda表达式)
```javascript
var f=func(x,y,z){
return nil;
}
var f=func{
return 1024;
}
var f=func(x,y,z,default1=1,default2=2){
return x+y+z+default1+default2;
var f=func(x,y,z){return nil;}
var f=func{return 114514;}
var f=func(x,y,z,deft=1){
return x+y+z+deft;
}
var f=func(args...){
var sum=0;
@@ -227,25 +199,19 @@ var f=func(args...){
}
```
__`vm_upval`__ 是用于存储闭包数据的特殊类型。这种类型只在`nasal_vm`中使用,用于确保闭包是可以正确使用的
__`vm_upval`__ 是存储闭包数据的特殊类型, 在 __`nasal_vm`__ 中使用,用于确保闭包功能正常
__`vm_obj`__ 是一种用来存储用户自定义数据的特别类型。这意味着你可以在nasal中使用C/C++的一些复杂数据结构。如果你想为nasal添加一种新的数据结构,那么就可以使用这个类型的数据。这种类型的数据一般由内置函数或者库开发者提供的模块函数生成
__`vm_obj`__ 是用来存储C/C++的一些复杂数据结构。这种类型的数据一般由内置函数或者库开发者提供的模块函数生成。如果你想为nasal添加一种新的数据结构, 可以看下文如何通过修改本项目来添加自己的内置函数
</details>
<details><summary><text style="font-weight:700">运算符</text></summary>
Nasal拥有基本的四种数学运算符 `+` `-` `*` `/`以及一个特别的运算符 `~`,这个运算符用于拼接两个字符串。
```javascript
var new_obj=func(){
return __my_obj();
}
var obj=new_obj();
```
### __运算符__
nasal拥有基本的四种数学运算符 `+` `-` `*` `/`以及一个特别的运算符 `~`,这个运算符用于拼接两个字符串。
```javascript
1+2-1*2/1;
1+2-(1+3)*(2+4)/(16-9);
'str1'~'str2';
(1+2)*(3+4)
```
对于条件语句,可以使用`==` `!=` `<` `>` `<=` `>=`来比较两个数据。`and` `or` 有着与C/C++中 `&&` `||`运算符相同的功能,用于连接两个不同的条件语句。
@@ -268,14 +234,13 @@ nasal拥有基本的四种数学运算符 `+` `-` `*` `/`以及一个特别的
```javascript
a=b=c=d=1;
a+=1;
a-=1;
a*=1;
a/=1;
a+=1; a-=1; a*=1; a/=1;
a~='string';
```
### __定义变量__
</details>
<details><summary><text style="font-weight:700">定义变量</text></summary>
```javascript
var a=1;
@@ -285,7 +250,9 @@ var (a,b,c)=(0,1,2);
(var a,b,c)=(0,1,2);
```
### __多变量赋值__
</details>
<details><summary><text style="font-weight:700">多变量赋值</text></summary>
最后这个语句通常用于交换两个变量的数据,类似于Python中的操作。
@@ -295,7 +262,9 @@ var (a,b,c)=(0,1,2);
(a,b)=(b,a);
```
### __条件语句__
</details>
<details><summary><text style="font-weight:700">条件语句</text></summary>
nasal在提供`else if`的同时还有另外一个关键字`elsif`。该关键字与`else if`有相同的功能。
@@ -311,14 +280,15 @@ if(1){
}
```
### __循环语句__
</details>
<details><summary><text style="font-weight:700">循环语句</text></summary>
while循环和for循环大体上与C/C++是一致的。
```javascript
while(condition)
continue;
for(var i=0;i<10;i+=1)
break;
```
@@ -339,7 +309,9 @@ foreach(var i;elem)
print(i);
```
### __生成子列表__
</details>
<details><summary><text style="font-weight:700">生成子列表(subvec)</text></summary>
nasal提供了下面第一句的类似语法来从列表中随机或者按照一个区间获取数据,并且拼接生成一个新的列表。当然如果中括号内只有一个下标的话,你会直接获得这个下标对应的数据而不是一个子列表。如果直接对string使用下标来获取内容的话,会得到对应字符的 __ascii值__。如果你想进一步获得这个字符串,可以尝试使用内置函数`chr()`。
@@ -349,7 +321,9 @@ a[-1,1,0:2,0:,:3,:,nil:8,3:nil,nil:nil];
"hello world"[0];
```
### __特殊函数调用语法__
</details>
<details><summary><text style="font-weight:700">特殊函数调用语法</text></summary>
这种特别的调用方式有时非常有用,但是切记这种调用方式不是很高效,因为哈希表会使用字符串比对来找到数据存放的位置。
@@ -357,7 +331,9 @@ a[-1,1,0:2,0:,:3,:,nil:8,3:nil,nil:nil];
f(x:0,y:nil,z:[]);
```
### __lambda表达式__
</details>
<details><summary><text style="font-weight:700">lambda表达式</text></summary>
正如上文所述,函数有这样一种直接编写函数体并且直接调用的方式:
@@ -381,7 +357,9 @@ var fib=func(f){
);
```
### __闭包__
</details>
<details><summary><text style="font-weight:700">闭包</text></summary>
闭包是一种特别的作用域,你可以从这个作用域中获取其保存的所有变量,而这些变量原本不是你当前运行的函数的局部作用域中的。下面这个例子里,结果是`1`:
@@ -408,7 +386,9 @@ var student=func(n,a){
}
```
### __特性__
</details>
<details><summary><text style="font-weight:700">特性与继承</text></summary>
当然,也有另外一种办法来面向对象编程,那就是利用`trait`。
@@ -485,7 +465,9 @@ println(d());
因为执行`a.get`时在`trait.get`函数的属性中进行了`me=a`的操作。而`b.get`则执行了`me=b`的操作。所以在运行`var d=b.get`后实际上c也变成`b.get`了。
如果你想要用这种小技巧来让程序运行更高效的话,最好是要知道这里存在这样一个机制。
### __内置函数__
</details>
<details><summary><text style="font-weight:700">原生内置函数以及模块导入(import)语法</text></summary>
这个部分对于纯粹的使用者来说是不需要了解的,它将告诉你我们是如何为这个解释器添加新的内置函数的。如果你对于添加自己私人订制的内置函数很感兴趣,那么这个部分可能会帮到你,并且……
@@ -594,7 +576,9 @@ nas_ref builtin_keys(nas_ref* local,nasal_gc& gc)
}
```
### __模块(开发者教程)__
</details>
<details><summary><text style="font-weight:700">模块(开发者教程)</text></summary>
如果只有上文中那种方式来添加你自定义的函数到nasal中,这肯定是非常麻烦的。因此,我们实现了一组实用的内置函数来帮助你添加你自己创建的模块。
@@ -707,6 +691,8 @@ dylib.dlclose(dlhandle);
832040
```
</details>
## __与andy解释器的不同之处__
### 1. 必须用`var`定义变量
@@ -820,6 +806,8 @@ vm stack(0x7fffff539c28<sp+80>, limit 10, total 1):
使用命令 __`-d`__ 或 __`--detail`__ 后,trace back信息会包含更多的细节内容:
<details><summary>展开堆栈错误信息</summary>
```javascript
hello
[vm] error: error occurred this line
@@ -854,6 +842,8 @@ local(0x7ffff42f3d68<sp+86>):
0x00000001 | str | <0x1932480> error occurred t...
```
</details>
## __调试器__
在`v8.0`版本中我们添加了调试器。
@@ -892,23 +882,10 @@ vm stack(0x7fffce09e6e8<sp+80>, limit 10, total 0)
```javascript
source code:
var fib=func(x)
{
--> if(x<2) return x;
return fib(x-1)+fib(x-2);
}
for(var i=0;i<31;i+=1)
print(fib(i),'\n');
...
next bytecode:
0x00000518: 02 00 00 00 02 intl 0x2 (test/fib.nas:1)
0x00000519: 0d 00 00 00 1a para 0x1a ("x") (test/fib.nas:1)
0x0000051a: 32 00 00 05 2a jmp 0x52a (test/fib.nas:1)
--> 0x0000051b: 39 00 00 00 01 calll 0x1 (test/fib.nas:3)
0x0000051c: 2d 00 00 00 03 lessc 0x3 (2) (test/fib.nas:3)
0x0000051d: 34 00 00 05 20 jf 0x520 (test/fib.nas:3)
0x0000051e: 39 00 00 00 01 calll 0x1 (test/fib.nas:3)
0x0000051f: 4a 00 00 00 00 ret 0x0 (test/fib.nas:3)
...
vm stack(0x7fffce09e6e8<sp+80>, limit 10, total 7)
0x00000056 | pc | 0x533
0x00000055 | addr | 0x0