OpenEX VM 解释器架构
本文档主要介绍了OpenEX解释器的结构以及原理,方便您更好的开发一个简单的解释器,为了方便和执行效率起见,字节码文件架构会采用特殊的存储方法
ByteCode 字节码文件
ByteCode 字节码
OpenEX中每个字节码都有自己的存储格式以及对应的二进制代码
OperationCode 运算指令
OpenEX的运算和操作指令都为单行,可以直接被逐行解析
助记符 | 二进制代码 | 格式 | 说明 |
---|---|---|---|
push | 0x02 | push <type> <data> | 将指定类型元素压入操作栈 |
add | 0x03 | add | 取栈顶两元素相加 |
sub | 0x04 | sub | 取栈顶两元素相减 |
mul | 0x05 | mul | 取栈顶两元素相乘 |
div | 0x06 | div | 取栈顶两元素相除 |
and | 0x07 | and | 取栈顶两元素进行与运算 |
or | 0x08 | or | 取栈顶两元素进行或运算 |
not | 0x09 | not | 取栈顶两元素进行非运算 |
big | 0x10 | big | 取栈顶两元素进行大于比较运算 |
less | 0x11 | less | 取栈顶两元素进行小于比较运算 |
equ | 0x12 | equ | 取栈顶两元素进行等于比较运算 |
big_equ | 0x13 | big_equ | 取栈顶两元素进行大于等于比较运算 |
less_equ | 0x14 | less_equ | 取栈顶两元素进行大于等于比较运算 |
StructCode 结构指令
OpenEX结构指令代表每一个脚本中的语句,其存储采用缩进的方式
invoke调用指令
- 二进制代码
0x01
- 助记符
invoke
lar数组定义指令
- 二进制代码
0x19
- 助记符
lar
nol空操作
- 二进制代码
0x00
- 助记符
nol
格式
数据类型
因push指令需要,以下会定义一些二进制代码代表一个值的类型
Head 文件头
OpenEX的字节码文件头由两个byte数据组成
script.ebc | |
---|---|
0x3a
为文件“魔数”,解释器会率先检查该魔数判断是否为OpenEX字节码文件
0x01
代表编译的版本号,因每个小版本号更新跨度不大,该版本号只会存储大版本号,如0.2.1
只会变成0.2.X
并转换成对应编号存储,0x01
代表AST版本的0.1.X
系列
Executor执行引擎
存储模型
OpenEX解释器会有一个全局变量池以及函数池
- 全局变量池 -负责存储
global
关键字定义的变量 - 函数池 -存储脚本内定义的各种函数
- 私有变量池 -存储
local
定义的变量,是线程私有的
线程管理器
因为OpenEX本质是支持多线程的,所以为统一结构,线程管理器需要具备能创建,中断,释放线程的能力,每个线程内配备一个操作栈用于表达式计算和私有变量池
如果非主线程发生解释器运行时异常,只会终止该线程的运行,其他线程不受影响,如果主线程发生运行时异常,则触发ShutdownHook后关闭解释器运行