diff --git a/README.md b/README.md index 2a00439b..e12c4b90 100644 --- a/README.md +++ b/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] +``` +
Multi-assignment @@ -767,6 +791,62 @@ If get this, Congratulations!
+
Ghost Type(for lib developers) + +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(ptr) << std::dec << ") {\n"; + delete static_cast(ptr); + std::cout << " delete 0x" << std::hex; + std::cout << reinterpret_cast(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. + +
+ ## __Difference Between Andy's and This Interpreter__ ![error](./doc/gif/error.gif) @@ -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 + +>>> +``` diff --git a/doc/README_zh.md b/doc/README_zh.md index a803ce1c..8e5bf11d 100644 --- a/doc/README_zh.md +++ b/doc/README_zh.md @@ -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] +``` +
多变量赋值 @@ -741,6 +765,61 @@ dylib.dlclose(dlhandle.lib);
+
自定义类型(开发者教程) + +创建一个自定义类型现在不是很困难。下面是使用示例: + +```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(ptr) << std::dec << ") {\n"; + delete static_cast(ptr); + std::cout << " delete 0x" << std::hex; + std::cout << reinterpret_cast(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&);` + +参数是自定义类型的类型名。 + +
+ ## __与andy解释器的不同之处__ ![error](../doc/gif/error.gif) @@ -982,3 +1061,19 @@ vm stack (0x7fffd0259138 , 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 + +>>> +``` diff --git a/doc/dev.md b/doc/dev.md index dd03a9ff..9d61ff64 100644 --- a/doc/dev.md +++ b/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__ ![op](../doc/gif/opcode.gif) @@ -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. diff --git a/doc/dev_zh.md b/doc/dev_zh.md index 83e5dda2..4a8fc240 100644 --- a/doc/dev_zh.md +++ b/doc/dev_zh.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) * [__字节码虚拟机__](#字节码虚拟机) * [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) + +改变了语法树的设计模式,采用访问者模式。 + ## __字节码虚拟机__ ![op](../doc/gif/opcode.gif) @@ -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. 全新的自定义类型注册流程。