注意:
AST-IR规范相对于STVC-TAC规范是一种“更古老”的编码规范,我们建议编译器和虚拟机采用更先进的STVC-TAC规范。但AST-IR仍然是一种稳定,方便的格式。
AST-IR(以下简称AstIr)是一种将抽象语法树(以下简称Ast)转为迭代表示方式的编码结构。
基于AstIr的编译器的基本运作原理是:在编译生成Ast后,将Ast转为AstIr的二进制编码文件,最后交给虚拟机运行,虚拟机将AstIr复原成Running-Ast数据结构(这种数据结构与编译器生成的Ast略有差别),然后递归执行。
有关Running-Ast的解释,我引用编译器开发文档的解释:
Ast和Running-Ast的区别就在于:Running-Ast的叶子节点皆为AstLeaf,而Ast非然。
不难见得,Running-Ast是为了适应AstIr而诞生的结构。
对于AstIr的结构解释和示例,我将其放到了文末的“AST-IR格式附注”中。
一个AstIr文件结构由以下几种规则构成:
Ast.hpp的_AstType为准,特别的,结束单元的类型是-1);后四字节是单元的数据,如果该单元是逻辑单元或结束单元,则后四字节默认为0,如果该单元是数据单元,则后四字节为数据的二进制存储(采用大端存储,以Python的大端存储为标准),数据单元的种类以文末的“数据单元附表”为准。| 单元类型 | 对应的数据 |
|---|---|
| ast::AstAnonClass | father_flag |
| ast::AstExpression | ass_type |
| ast::AstBinary | operator_type |
| ast::AstUnary | operator_type |
| ast::AstPostfix | postfix_type |
AstIr的格式和HTML的格式类似:由逻辑单元、数据单元和结束单元组成。一棵Ast可以通过深度优先遍历转为AstIr。
这样的描述也许会较为拗口,我们来看一个示例:
考虑以下Ast:
Add |-a |-Sub |--b |--1该Ast可以转为以下AstIr:
<Add> //此为逻辑单元,以此类推 <data val=a> //此为数据单元,以此类推 <Sub> <data val=b> <data val=1> <end> //此为结束单元,以此类推 <end>这段AstIr和上面的Ast本质上是等价的。这样只需将Ast转为AstIr,就能获得一系列单元,方便存入文件。
逻辑单元本质上就是Ast节点的非叶子节点,数据单元本质上就是Ast节点的叶子节点。
一个常量表由常量表长度(占4字节)和若干个常量组成,其中常量又由常量类型(占1字节)和常量值组成:
其中每种类型的编码格式如下:
一个常量表下标默认为4字节。
摘自
STVC-TAC二进制编码规范,2025年4月26日