📝 update README
This commit is contained in:
parent
4c95d622f6
commit
ac8652f864
65
README.md
65
README.md
|
@ -140,7 +140,7 @@ Reading this tutorial will not takes you over 15 minutes.
|
|||
__If you have learnt C/C++/Javascript before, this will take less time.__
|
||||
You could totally use it after reading this simple tutorial:
|
||||
|
||||
<details><summary><text style="font-weight:700;font-size:medium"> basic value type </text></summary>
|
||||
<details><summary> basic value type </summary>
|
||||
|
||||
__`vm_none`__ is error type.
|
||||
This type is used to interrupt the execution of virtual machine and will not be created by user program.
|
||||
|
@ -219,7 +219,7 @@ This type is often created by native-function of nasal. If want to define your o
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700;font-size:medium"> operators </text></summary>
|
||||
<details><summary> operators </summary>
|
||||
|
||||
Nasal has basic math operators `+` `-` `*` `/` and a special operator `~` that links two strings together.
|
||||
|
||||
|
@ -255,7 +255,7 @@ a~='string';
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700;font-size:medium"> definition </text></summary>
|
||||
<details><summary> definition </summary>
|
||||
|
||||
```javascript
|
||||
var a=1;
|
||||
|
@ -267,7 +267,7 @@ var (a,b,c)=(0,1,2);
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700;font-size:medium"> multi-assignment </text></summary>
|
||||
<details><summary> multi-assignment </summary>
|
||||
|
||||
The last one is often used to swap two variables.
|
||||
|
||||
|
@ -279,7 +279,7 @@ The last one is often used to swap two variables.
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700;font-size:medium"> conditional expression </text></summary>
|
||||
<details><summary> conditional expression </summary>
|
||||
|
||||
In nasal there's a new key word `elsif`.
|
||||
It has the same functions as `else if`.
|
||||
|
@ -298,7 +298,7 @@ if(1){
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700;font-size:medium"> loop </text></summary>
|
||||
<details><summary> loop </summary>
|
||||
|
||||
While loop and for loop is simalar to C/C++.
|
||||
|
||||
|
@ -327,7 +327,7 @@ foreach(var i;elem)
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700;font-size:medium"> subvec </text></summary>
|
||||
<details><summary> subvec </summary>
|
||||
|
||||
Nasal provides this special syntax to help user generate a new vector by getting values by one index or getting values by indexes in a range from an old vector.
|
||||
If there's only one index in the bracket, then we will get the value directly.
|
||||
|
@ -342,7 +342,7 @@ a[-1,1,0:2,0:,:3,:,nil:8,3:nil,nil:nil];
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700;font-size:medium"> special function call </text></summary>
|
||||
<details><summary> special function call </summary>
|
||||
|
||||
This is of great use but is not very efficient
|
||||
(because hashmap use string as the key to compare).
|
||||
|
@ -353,7 +353,7 @@ f(x:0,y:nil,z:[]);
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700;font-size:medium"> lambda </text></summary>
|
||||
<details><summary> lambda </summary>
|
||||
|
||||
Also functions have this kind of use:
|
||||
|
||||
|
@ -380,7 +380,7 @@ var fib=func(f){
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700;font-size:medium"> closure </text></summary>
|
||||
<details><summary> closure </summary>
|
||||
|
||||
Closure means you could get the variable that is not in the local scope of a function that you called.
|
||||
Here is an example, result is `1`:
|
||||
|
@ -410,7 +410,7 @@ var student=func(n,a){
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700;font-size:medium"> trait </text></summary>
|
||||
<details><summary> trait </summary>
|
||||
|
||||
Also there's another way to OOP, that is `trait`.
|
||||
|
||||
|
@ -492,7 +492,7 @@ If you want to use this trick to make the program running more efficiently, you
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700;font-size:medium"> native functions and module import </text></summary>
|
||||
<details><summary> native functions and module import </summary>
|
||||
|
||||
This part shows how we add native functions in this nasal interpreter.
|
||||
If you are interested in this part, this may help you.
|
||||
|
@ -607,7 +607,7 @@ nas_ref builtin_keys(nas_ref* local,nasal_gc& gc)
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700;font-size:medium"> modules(for lib developers) </text></summary>
|
||||
<details><summary> modules(for lib developers) </summary>
|
||||
|
||||
If there is only one way to add your own functions into nasal,
|
||||
that is really inconvenient.
|
||||
|
@ -743,17 +743,14 @@ foreach(i;[0,1,2,3])
|
|||
print(i)
|
||||
```
|
||||
|
||||
This program can run normally with output 0 1 2 3.
|
||||
But take a look at the iterator 'i',
|
||||
this symbol is defined in foreach without using keyword 'var'.
|
||||
I think this design will make programmers filling confused.
|
||||
This is ambiguous that programmers maybe difficult to find the 'i' is defined here.
|
||||
Without 'var', programmers may think this 'i' is defined anywhere else.
|
||||
This program can run normally.
|
||||
But take a look at the iterator `i`,
|
||||
it is defined in foreach without using keyword `var`.
|
||||
I think this design will make programmers feeling confused that they maybe hard to find the `i` is defined here.
|
||||
Without `var`, they may think this `i` is defined anywhere else.
|
||||
|
||||
So in this new interpreter i use a more strict syntax to force users to use 'var' to define iterator of forindex and foreach.
|
||||
If you forget to add the keyword 'var',
|
||||
and you haven't defined this symbol before,
|
||||
you will get this:
|
||||
So in this interpreter i use a more strict syntax to force users to use `var` to define iterator of forindex and foreach.
|
||||
If you forget to add the keyword `var`, you will get this:
|
||||
|
||||
```javascript
|
||||
[code] test.nas:2 undefined symbol "i".
|
||||
|
@ -764,17 +761,17 @@ foreach(i;[0,1,2,3])
|
|||
|
||||
### 2. default dynamic arguments not supported
|
||||
|
||||
In this new interpreter,
|
||||
function doesn't put dynamic arguments into vector `arg` automatically.
|
||||
In this interpreter,
|
||||
function doesn't put dynamic args into vector `arg` by default.
|
||||
So if you use `arg` without definition,
|
||||
you'll get an error of `undefined symbol`.
|
||||
|
||||
## __Trace Back Info__
|
||||
|
||||
When the interpreter crashes,
|
||||
When interpreter crashes,
|
||||
it will print trace back information:
|
||||
|
||||
### 1. native function `die`
|
||||
<details><summary>1. native function [die]</summary>
|
||||
|
||||
Function `die` is used to throw error and crash immediately.
|
||||
|
||||
|
@ -803,7 +800,9 @@ vm stack(0x7fffcd21bc68<sp+80>, limit 10, total 12):
|
|||
0x00000052 | nil |
|
||||
```
|
||||
|
||||
### 2. stack overflow crash info
|
||||
</details>
|
||||
|
||||
<details><summary>2. stack overflow crash info</summary>
|
||||
|
||||
Here is an example of stack overflow:
|
||||
|
||||
|
@ -832,7 +831,9 @@ vm stack(0x7fffd3781d58<sp+80>, limit 10, total 8108):
|
|||
0x00001ff2 | addr | 0x7fffd37a16e8
|
||||
```
|
||||
|
||||
### 3. normal vm error crash info
|
||||
</details>
|
||||
|
||||
<details><summary>3. normal vm error crash info</summary>
|
||||
|
||||
Error will be thrown if there's a fatal error when executing:
|
||||
|
||||
|
@ -850,12 +851,12 @@ vm stack(0x7fffff539c28<sp+80>, limit 10, total 1):
|
|||
0x00000050 | num | 0
|
||||
```
|
||||
|
||||
### 4. detailed crash info
|
||||
</details>
|
||||
|
||||
<details><summary>4. detailed crash info</summary>
|
||||
|
||||
Use command __`-d`__ or __`--detail`__ the trace back info will show more details:
|
||||
|
||||
<details><summary>show trace back info</summary>
|
||||
|
||||
```javascript
|
||||
hello
|
||||
[vm] error: error occurred this line
|
||||
|
|
|
@ -128,7 +128,7 @@ if(os.platform()=="windows")
|
|||
Nasal是非常容易上手的,你甚至可以在15分钟之内看完这里的基本教程并且直接开始编写你想要的程序。
|
||||
__如果你先前已经是C/C++,javascript选手,那么这个教程几乎可以不用看了……__ 在看完该教程之后,基本上你就完全掌握了这个语言:
|
||||
|
||||
<details><summary><text style="font-weight:700">基本类型</text></summary>
|
||||
<details><summary>基本类型</summary>
|
||||
|
||||
__`vm_none`__ 是特殊的错误类型。这个类型用于终止虚拟机的执行,用户是无法申请到这个类型的,该类型只能由字节码虚拟机自己在抛出错误时产生。
|
||||
|
||||
|
@ -205,7 +205,7 @@ __`vm_obj`__ 是用来存储C/C++的一些复杂数据结构。这种类型的
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700">运算符</text></summary>
|
||||
<details><summary>运算符</summary>
|
||||
|
||||
Nasal拥有基本的四种数学运算符 `+` `-` `*` `/`以及一个特别的运算符 `~`,这个运算符用于拼接两个字符串。
|
||||
|
||||
|
@ -240,7 +240,7 @@ a~='string';
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700">定义变量</text></summary>
|
||||
<details><summary>定义变量</summary>
|
||||
|
||||
```javascript
|
||||
var a=1;
|
||||
|
@ -252,7 +252,7 @@ var (a,b,c)=(0,1,2);
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700">多变量赋值</text></summary>
|
||||
<details><summary>多变量赋值</summary>
|
||||
|
||||
最后这个语句通常用于交换两个变量的数据,类似于Python中的操作。
|
||||
|
||||
|
@ -264,7 +264,7 @@ var (a,b,c)=(0,1,2);
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700">条件语句</text></summary>
|
||||
<details><summary>条件语句</summary>
|
||||
|
||||
nasal在提供`else if`的同时还有另外一个关键字`elsif`。该关键字与`else if`有相同的功能。
|
||||
|
||||
|
@ -282,7 +282,7 @@ if(1){
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700">循环语句</text></summary>
|
||||
<details><summary>循环语句</summary>
|
||||
|
||||
while循环和for循环大体上与C/C++是一致的。
|
||||
|
||||
|
@ -311,7 +311,7 @@ foreach(var i;elem)
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700">生成子列表(subvec)</text></summary>
|
||||
<details><summary>生成子列表(subvec)</summary>
|
||||
|
||||
nasal提供了下面第一句的类似语法来从列表中随机或者按照一个区间获取数据,并且拼接生成一个新的列表。当然如果中括号内只有一个下标的话,你会直接获得这个下标对应的数据而不是一个子列表。如果直接对string使用下标来获取内容的话,会得到对应字符的 __ascii值__。如果你想进一步获得这个字符串,可以尝试使用内置函数`chr()`。
|
||||
|
||||
|
@ -323,7 +323,7 @@ a[-1,1,0:2,0:,:3,:,nil:8,3:nil,nil:nil];
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700">特殊函数调用语法</text></summary>
|
||||
<details><summary>特殊函数调用语法</summary>
|
||||
|
||||
这种特别的调用方式有时非常有用,但是切记这种调用方式不是很高效,因为哈希表会使用字符串比对来找到数据存放的位置。
|
||||
|
||||
|
@ -333,7 +333,7 @@ f(x:0,y:nil,z:[]);
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700">lambda表达式</text></summary>
|
||||
<details><summary>lambda表达式</summary>
|
||||
|
||||
正如上文所述,函数有这样一种直接编写函数体并且直接调用的方式:
|
||||
|
||||
|
@ -359,7 +359,7 @@ var fib=func(f){
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700">闭包</text></summary>
|
||||
<details><summary>闭包</summary>
|
||||
|
||||
闭包是一种特别的作用域,你可以从这个作用域中获取其保存的所有变量,而这些变量原本不是你当前运行的函数的局部作用域中的。下面这个例子里,结果是`1`:
|
||||
|
||||
|
@ -388,7 +388,7 @@ var student=func(n,a){
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700">特性与继承</text></summary>
|
||||
<details><summary>特性与继承</summary>
|
||||
|
||||
当然,也有另外一种办法来面向对象编程,那就是利用`trait`。
|
||||
|
||||
|
@ -467,7 +467,7 @@ println(d());
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700">原生内置函数以及模块导入(import)语法</text></summary>
|
||||
<details><summary>原生内置函数以及模块导入(import)语法</summary>
|
||||
|
||||
这个部分对于纯粹的使用者来说是不需要了解的,它将告诉你我们是如何为这个解释器添加新的内置函数的。如果你对于添加自己私人订制的内置函数很感兴趣,那么这个部分可能会帮到你,并且……
|
||||
|
||||
|
@ -578,7 +578,7 @@ nas_ref builtin_keys(nas_ref* local,nasal_gc& gc)
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary><text style="font-weight:700">模块(开发者教程)</text></summary>
|
||||
<details><summary>模块(开发者教程)</summary>
|
||||
|
||||
如果只有上文中那种方式来添加你自定义的函数到nasal中,这肯定是非常麻烦的。因此,我们实现了一组实用的内置函数来帮助你添加你自己创建的模块。
|
||||
|
||||
|
@ -707,9 +707,9 @@ foreach(i;[0,1,2,3])
|
|||
print(i)
|
||||
```
|
||||
|
||||
这个程序会正常输出`0 1 2 3`。然而这个`i`标识符实际上在这里是被第一次定义,而且没有使用`var`。我认为这样的设计很容易让使用者迷惑。很有可能很多使用者都没有发现这里实际上是第一次定义`i`的地方。没有使用`var`的定义会让程序员认为这个`i`也许是在别的地方定义的。
|
||||
这个程序可以正常运行。然而这个`i`标识符实际上在这里是被第一次定义,而且没有使用`var`。我认为这样的设计很容易让使用者迷惑。他们可能都没有发现这里实际上是第一次定义`i`的地方。没有使用`var`的定义会让程序员认为这个`i`也许是在别的地方定义的。
|
||||
|
||||
所以在这个新的解释器中,我直接使用严格的语法检查方法来强行要求用户必须要使用`var`来定义新的变量或者迭代器。如果你忘了加这个关键字,并且你没有在别的地方声明过这个变量,那么你就会得到这个:
|
||||
所以在这个解释器中,我直接使用严格的语法检查方法来强行要求用户必须要使用`var`来定义新的变量或者迭代器。如果你忘了加这个关键字,那么你就会得到这个:
|
||||
|
||||
```javascript
|
||||
[code] test.nas:2 undefined symbol "i".
|
||||
|
@ -726,7 +726,7 @@ foreach(i;[0,1,2,3])
|
|||
|
||||
当解释器崩溃时,它会反馈错误产生过程的堆栈追踪信息:
|
||||
|
||||
### 1. 内置函数`die`
|
||||
<details><summary>1. 内置函数die</summary>
|
||||
|
||||
`die`函数用于直接抛出错误并终止执行。
|
||||
|
||||
|
@ -755,7 +755,9 @@ vm stack(0x7fffcd21bc68<sp+80>, limit 10, total 12):
|
|||
0x00000052 | nil |
|
||||
```
|
||||
|
||||
### 2. 栈溢出信息
|
||||
</details>
|
||||
|
||||
<details><summary>2. 栈溢出</summary>
|
||||
|
||||
这是一个会导致栈溢出的例子:
|
||||
|
||||
|
@ -784,7 +786,9 @@ vm stack(0x7fffd3781d58<sp+80>, limit 10, total 8108):
|
|||
0x00001ff2 | addr | 0x7fffd37a16e8
|
||||
```
|
||||
|
||||
### 3. 运行时错误
|
||||
</details>
|
||||
|
||||
<details><summary>3. 运行时错误</summary>
|
||||
|
||||
如果在执行的时候出现错误,程序会直接终止执行:
|
||||
|
||||
|
@ -802,12 +806,12 @@ vm stack(0x7fffff539c28<sp+80>, limit 10, total 1):
|
|||
0x00000050 | num | 0
|
||||
```
|
||||
|
||||
### 4. 详细的崩溃信息
|
||||
</details>
|
||||
|
||||
<details><summary>4. 详细的崩溃信息</summary>
|
||||
|
||||
使用命令 __`-d`__ 或 __`--detail`__ 后,trace back信息会包含更多的细节内容:
|
||||
|
||||
<details><summary>展开堆栈错误信息</summary>
|
||||
|
||||
```javascript
|
||||
hello
|
||||
[vm] error: error occurred this line
|
||||
|
|
Loading…
Reference in New Issue