3.4 KiB
3.4 KiB
python裂解器设计思路——ZYM
开发步骤
- 编写底层工具,并测试(函数调用相关的简单测试)。
- 在不考虑函数调用的情况下,以链为单位编写、调试自动机
- 测试函数相关的底层工具
- 增加考虑有函数调用时的情况,以链为单位编写、调试自动机
模块划分
libs
、generated
、resources
目录:libs
目录存放第三方库,其中int2048是我的上个大作业,用以提供大整数运算支持;json是提供json解析支持,出处https://github.com/nlohmann/json;clipp是提供命令行参数解析支持,出处https://github.com/muellan/clipp。ANTLR框架存放于generated
、resources
目录中。test
目录:存放测试相关,有一个进程级测试调度核心及相关配置文件、数据点,通过ctest_config接入CTest框架使得CTest可以调用进程级测试调度核心include
目录:裂解器直接相关的头文件src
目录:裂解器直接相关的实现文件。main
负责解析命令行参数,解析代码,并访问根节点,同时处理异常;utils
负责执行类型转换、数据解析等底层工作,保证Evalvisitor
的简洁性;names
负责维护变量和函数的注册和调用。
主要重难点
数据流
数据存储与传递方式
bool
:底层实现为内置bool,传递时打包成any统一传递。只在输出时输出"True"
或者"False"
int
:底层实现为int2048,传递时打包成any统一传递float
:底层实现为内置double,传递时打包成any统一传递str
:底层实现为std::string
,传递时打包成any统一传递- 元组:底层实现为
std::vector<std::any>
,传递时打包成any统一传递。函数参数列表不视作元组,特殊处理。 None
:底层实现为自定义NoneType
,传递时打包成any统一传递。
特殊处理
数值流在出现赋值时如何兼容左右值。 法一:将变量区分引用状态(通过一个专门的类来实现)和值状态,懒求解
控制流
控制流:在数值(包括None)返回值的基础上,新增一个控制类型的范围值(break、continue、return共用同一个),传递时打包成any统一传递,用控制类型这个类型本身区分控制流和数据流。
函数的定义与调用
用一个FucntionContainer
类管理所有函数,定义时记录参数状况和函数体的地址(存放在结构体FunctionItem
里面),用FucntionContainer::AddFunction
注册函数,调用时使用FucntionContainer::CallFunction
,新开一个栈,把实际参数赋值给形式参数后调用函数体。
变量的生效范围与作用域
设置全局作用域与局部作用域,全局作用域是一个std::unordered_map<std::string,std::any>
,局部作用域是一个std::stack<std::unordered_map<std::string,std::any>>
,两者封装在一个VariableContainer
类里面,对外提供CreateFrame
、DestroyFrame
、ReadVariable
、WriteVariable
四个接口。
关键细节
元组
底层实现为std::vector<std::any>
,传递时打包成any统一传递。由于区分左右值,因此需要在合适的时候把右值解引用为左值。
函数传参
按照一定规则确定赋值的对应关系,注意要在新建一层栈之前把实际参数从右值解引用为左值,然后调用特殊版的VariableContainer::WriteVariable
以支持形式参数遮蔽同名全局变量。