Merge pull request #32 from ValKmjolnir/develop
📝 update release notes and tutorials
This commit is contained in:
commit
c8c233d1d4
96
README.md
96
README.md
|
@ -261,6 +261,30 @@ 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
|
||||
```
|
||||
|
||||
Nasal has many special global symbols:
|
||||
|
||||
```javascript
|
||||
globals; # hashmap including all global symbols and their values
|
||||
arg; # in global scope, arg is the command line arguments
|
||||
# in local scope, arg is the dynamic arguments of this function call
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
```javascript
|
||||
var a = 1;
|
||||
println(globals); # will print {a:1}
|
||||
```
|
||||
|
||||
```javascript
|
||||
# nasal a b c
|
||||
println(arg); # will print ["a", "b", "c"]
|
||||
|
||||
func() {
|
||||
println(arg);
|
||||
}(1, 2, 3); # will print [1, 2, 3]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary> Multi-assignment </summary>
|
||||
|
@ -767,6 +791,62 @@ If get this, Congratulations!
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary> Ghost Type(for lib developers) </summary>
|
||||
|
||||
It's quite easy to create a new ghost by yourself now.
|
||||
Look at the example below:
|
||||
|
||||
```c++
|
||||
const auto ghost_for_test = "ghost_for_test";
|
||||
|
||||
// declare destructor for ghost type
|
||||
void ghost_for_test_destructor(void* ptr) {
|
||||
std::cout << "ghost_for_test::destructor (0x";
|
||||
std::cout << std::hex << reinterpret_cast<u64>(ptr) << std::dec << ") {\n";
|
||||
delete static_cast<u32*>(ptr);
|
||||
std::cout << " delete 0x" << std::hex;
|
||||
std::cout << reinterpret_cast<u64>(ptr) << std::dec << ";\n";
|
||||
std::cout << "}\n";
|
||||
}
|
||||
|
||||
var create_new_ghost(var* args, usize size, gc* ngc) {
|
||||
var res = ngc->alloc(vm_obj);
|
||||
// create ghost type
|
||||
res.obj().set(ghost_for_test, ghost_for_test_destructor, new u32);
|
||||
return res;
|
||||
}
|
||||
|
||||
var print_new_ghost(var* args, usize size, gc* ngc) {
|
||||
var res = args[0];
|
||||
// check ghost type by the type name
|
||||
if (!res.objchk(ghost_for_test)) {
|
||||
std::cout << "print_new_ghost: not ghost for test type.\n";
|
||||
return nil;
|
||||
}
|
||||
std::cout << "print_new_ghost: " << res.obj() << " result = "
|
||||
<< *((u32*)res.obj().ptr) << "\n";
|
||||
return nil;
|
||||
}
|
||||
```
|
||||
|
||||
We use this function to create a new ghost type:
|
||||
|
||||
`void nas_ghost::set(const std::string&, nasal::nas_ghost::destructor, void*);`
|
||||
|
||||
`const std::string&` is the name of the ghost type.
|
||||
|
||||
`nasal::nas_ghost::destructor` is the pointer of the destructor of the ghost type.
|
||||
|
||||
`void*` is the pointer of the ghost type instance.
|
||||
|
||||
And we use this function to check if value is the correct ghost type:
|
||||
|
||||
`bool var::objchk(const std::string&);`
|
||||
|
||||
The parameter is the name of the ghost type.
|
||||
|
||||
</details>
|
||||
|
||||
## __Difference Between Andy's and This Interpreter__
|
||||
|
||||

|
||||
|
@ -1018,3 +1098,19 @@ We added experimental repl interpreter in v11.0.
|
|||
Use this command to use the repl interpreter:
|
||||
|
||||
> nasal -r
|
||||
|
||||
Then enjoy!
|
||||
|
||||
```bash
|
||||
[nasal-repl] Initializating enviroment...
|
||||
[nasal-repl] Initialization complete.
|
||||
|
||||
Nasal REPL interpreter version 11.0 (Oct 7 2023 17:28:31)
|
||||
.h, .help | show help
|
||||
.e, .exit | quit the REPL
|
||||
.q, .quit | quit the REPL
|
||||
.c, .clear | clear the screen
|
||||
.s, .source | show source code
|
||||
|
||||
>>>
|
||||
```
|
||||
|
|
|
@ -247,6 +247,30 @@ var (a,b,c)=[0,1,2]; # 从数组中初始化多个变量
|
|||
var (a,b,c)=(0,1,2); # 从元组中初始化多个变量
|
||||
```
|
||||
|
||||
Nasal 有很多特别的全局变量:
|
||||
|
||||
```javascript
|
||||
globals; # 包含所有全局声明变量名和对应数据的哈希表
|
||||
arg; # 在全局作用域,arg 是包含命令行参数的数组
|
||||
# 在局部作用域,arg 是函数调用时的动态参数数组
|
||||
```
|
||||
|
||||
具体实例:
|
||||
|
||||
```javascript
|
||||
var a = 1;
|
||||
println(globals); # 输出 {a:1}
|
||||
```
|
||||
|
||||
```javascript
|
||||
# nasal a b c
|
||||
println(arg); # 输出 ["a", "b", "c"]
|
||||
|
||||
func() {
|
||||
println(arg);
|
||||
}(1, 2, 3); # 输出 [1, 2, 3]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>多变量赋值</summary>
|
||||
|
@ -741,6 +765,61 @@ dylib.dlclose(dlhandle.lib);
|
|||
|
||||
</details>
|
||||
|
||||
<details><summary> 自定义类型(开发者教程) </summary>
|
||||
|
||||
创建一个自定义类型现在不是很困难。下面是使用示例:
|
||||
|
||||
```c++
|
||||
const auto ghost_for_test = "ghost_for_test";
|
||||
|
||||
// 声明自定义类型的析构函数
|
||||
void ghost_for_test_destructor(void* ptr) {
|
||||
std::cout << "ghost_for_test::destructor (0x";
|
||||
std::cout << std::hex << reinterpret_cast<u64>(ptr) << std::dec << ") {\n";
|
||||
delete static_cast<u32*>(ptr);
|
||||
std::cout << " delete 0x" << std::hex;
|
||||
std::cout << reinterpret_cast<u64>(ptr) << std::dec << ";\n";
|
||||
std::cout << "}\n";
|
||||
}
|
||||
|
||||
var create_new_ghost(var* args, usize size, gc* ngc) {
|
||||
var res = ngc->alloc(vm_obj);
|
||||
// 创建自定义类型
|
||||
res.obj().set(ghost_for_test, ghost_for_test_destructor, new u32);
|
||||
return res;
|
||||
}
|
||||
|
||||
var print_new_ghost(var* args, usize size, gc* ngc) {
|
||||
var res = args[0];
|
||||
// 用自定义类型的名字来检查是否是正确的自定义类型
|
||||
if (!res.objchk(ghost_for_test)) {
|
||||
std::cout << "print_new_ghost: not ghost for test type.\n";
|
||||
return nil;
|
||||
}
|
||||
std::cout << "print_new_ghost: " << res.obj() << " result = "
|
||||
<< *((u32*)res.obj().ptr) << "\n";
|
||||
return nil;
|
||||
}
|
||||
```
|
||||
|
||||
我们使用下面这个函数来创建一个自定义类型:
|
||||
|
||||
`void nas_ghost::set(const std::string&, nasal::nas_ghost::destructor, void*);`
|
||||
|
||||
`const std::string&` 是自定义类型的类型名。
|
||||
|
||||
`nasal::nas_ghost::destructor` 是自定义类型的析构函数指针。
|
||||
|
||||
`void*` 是指向自定义类型实例的指针。
|
||||
|
||||
我们使用下面的这个函数检测是否是正确的自定义类型:
|
||||
|
||||
`bool var::objchk(const std::string&);`
|
||||
|
||||
参数是自定义类型的类型名。
|
||||
|
||||
</details>
|
||||
|
||||
## __与andy解释器的不同之处__
|
||||
|
||||

|
||||
|
@ -982,3 +1061,19 @@ vm stack (0x7fffd0259138 <sp+65>, limit 10, total 7)
|
|||
v11.0 版本新增了交互式解释器 (REPL),使用如下命令开启:
|
||||
|
||||
> nasal -r
|
||||
|
||||
接下来就可以随便玩了~
|
||||
|
||||
```bash
|
||||
[nasal-repl] Initializating enviroment...
|
||||
[nasal-repl] Initialization complete.
|
||||
|
||||
Nasal REPL interpreter version 11.0 (Oct 7 2023 17:28:31)
|
||||
.h, .help | show help
|
||||
.e, .exit | quit the REPL
|
||||
.q, .quit | quit the REPL
|
||||
.c, .clear | clear the screen
|
||||
.s, .source | show source code
|
||||
|
||||
>>>
|
||||
```
|
||||
|
|
35
doc/dev.md
35
doc/dev.md
|
@ -9,6 +9,7 @@
|
|||
* [v2.0](#version-20-ast-last-update-2020831)
|
||||
* [v3.0](#version-30-ast-last-update-20201023)
|
||||
* [v5.0](#version-50-ast-last-update-202137)
|
||||
* [v11.0](#version-110-ast-latest)
|
||||
* [__Bytecode VM__](#bytecode-virtual-machine)
|
||||
* [v4.0](#version-40-vm-last-update-20201217)
|
||||
* [v5.0](#version-50-vm-last-update-202137)
|
||||
|
@ -17,8 +18,10 @@
|
|||
* [v7.0](#version-70-vm-last-update-2021108)
|
||||
* [v8.0](#version-80-vm-last-update-2022212)
|
||||
* [v9.0](#version-90-vm-last-update-2022518)
|
||||
* [v10.0](#version-100-vm-latest)
|
||||
* [v10.0](#version-100-vm-last-update-2022816)
|
||||
* [__Release Notes__](#release-notes)
|
||||
* [v8.0](#version-80-release)
|
||||
* [v11.0](#version-110-release)
|
||||
|
||||
## __Parser__
|
||||
|
||||
|
@ -97,6 +100,10 @@ AST interpreter leaves me too much things to do.
|
|||
If i continue saving this interpreter,
|
||||
it will be harder for me to make the bytecode vm become more efficient.
|
||||
|
||||
### version 11.0 ast (latest)
|
||||
|
||||
Change ast framework. Now we use visitor pattern.
|
||||
|
||||
## __Bytecode Virtual Machine__
|
||||
|
||||

|
||||
|
@ -513,7 +520,7 @@ func <0x2a3>:
|
|||
0x000002aa: 0c 00 00 00 6a happ 0x6a ("dlsym")
|
||||
```
|
||||
|
||||
### version 10.0 vm (latest)
|
||||
### version 10.0 vm (last update 2022/8/16)
|
||||
|
||||
2022/5/19 update:
|
||||
|
||||
|
@ -664,7 +671,29 @@ If do not change this line, only the debugger runs abnormally. this bug is fixed
|
|||
Another bug is that in `nasal_err.h:class nasal_err`, we should add a constructor for this class:
|
||||
|
||||
```C++
|
||||
nasal_err():error(0){}
|
||||
nasal_err(): error(0) {}
|
||||
```
|
||||
|
||||
This bug is fixed in `v9.0`. So we suggest that do not use `v8.0`.
|
||||
|
||||
### __version 11.0 release__
|
||||
|
||||
1. Use C++ `std=c++17`.
|
||||
|
||||
2. Change framework of ast, using visitor pattern.
|
||||
|
||||
3. New ast structure dump info format.
|
||||
|
||||
4. Change the way of module export, split library into different modules. Symbols begin with `_` will not be exported.
|
||||
|
||||
5. Change `stl` to `std`.
|
||||
|
||||
6. Add REPL interpreter.
|
||||
|
||||
7. Improve structure of virtual machine, split global symbol stack(stores global symbols' values) and value stack(using in process).
|
||||
|
||||
8. Delete operand `op_intg`, add operand `op_repl`.
|
||||
|
||||
9. Add `CMakeLists.txt` for cmake user(including `Visual Studio`).
|
||||
|
||||
10. New ghost type register process.
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* [v2.0](#version-20-ast-last-update-2020831)
|
||||
* [v3.0](#version-30-ast-last-update-20201023)
|
||||
* [v5.0](#version-50-ast-last-update-202137)
|
||||
* [v11.0](#version-110-ast-latest)
|
||||
* [__字节码虚拟机__](#字节码虚拟机)
|
||||
* [v4.0](#version-40-vm-last-update-20201217)
|
||||
* [v5.0](#version-50-vm-last-update-202137)
|
||||
|
@ -17,8 +18,10 @@
|
|||
* [v7.0](#version-70-vm-last-update-2021108)
|
||||
* [v8.0](#version-80-vm-last-update-2022212)
|
||||
* [v9.0](#version-90-vm-last-update-2022518)
|
||||
* [v10.0](#version-100-vm-latest)
|
||||
* [v10.0](#version-100-vm-last-update-2022816)
|
||||
* [__发行日志__](#发行日志)
|
||||
* [v8.0](#version-80-release)
|
||||
* [v11.0](#version-110-release)
|
||||
|
||||
## __语法分析__
|
||||
|
||||
|
@ -89,6 +92,10 @@ __该项目于2019/7/25正式开始__。
|
|||
|
||||
我改变想法了,树解释器给维护带来了太大的麻烦。如果想继续保留这个解释器,那么为了兼容性,字节码虚拟机的优化工作会更难推进。
|
||||
|
||||
### version 11.0 ast (latest)
|
||||
|
||||
改变了语法树的设计模式,采用访问者模式。
|
||||
|
||||
## __字节码虚拟机__
|
||||
|
||||

|
||||
|
@ -458,7 +465,7 @@ func <0x2a3>:
|
|||
0x000002aa: 0c 00 00 00 6a happ 0x6a ("dlsym")
|
||||
```
|
||||
|
||||
### version 10.0 vm (latest)
|
||||
### version 10.0 vm (last update 2022/8/16)
|
||||
|
||||
2022/5/19 update:
|
||||
|
||||
|
@ -597,7 +604,29 @@ in __`nasal_dbg.h:215`__: `auto canary=gc.stack+STACK_MAX_DEPTH-1;`
|
|||
另外一个bug在 `nasal_err.h:class nasal_err`这边,要给这个类添加一个构造函数来进行初始化,否则会出问题:
|
||||
|
||||
```C++
|
||||
nasal_err():error(0){}
|
||||
nasal_err(): error(0) {}
|
||||
```
|
||||
|
||||
同样这个也在`v9.0`中修复了。所以我们建议不要使用`v8.0`。
|
||||
|
||||
### __version 11.0 release__
|
||||
|
||||
1. 使用C++标准 `std=c++17`。
|
||||
|
||||
2. 改变语法树设计模式,采用访问者模式。
|
||||
|
||||
3. 全新的语法树结构输出格式。
|
||||
|
||||
4. 改变了导出模块的方式,把主要的库分成了多个模块。以`_`开头的变量不会被导出。
|
||||
|
||||
5. 文件夹`stl`更名为`std`。
|
||||
|
||||
6. 添加交互式解释器 (REPL)。
|
||||
|
||||
7. 优化虚拟机结构, 将全局数据栈 (存储全局变量的数据) 和操作数据栈 (用于运算) 分离。
|
||||
|
||||
8. 删除`op_intg`指令,添加`op_repl`指令。
|
||||
|
||||
9. 添加`CMakeLists.txt` (可在`Visual Studio`中使用)。
|
||||
|
||||
10. 全新的自定义类型注册流程。
|
||||
|
|
Loading…
Reference in New Issue