# AST-IR编码文件文档

> 注意：``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文件结构由以下几种规则构成：

* 每个词法单元文件的开头必须要有两字节的二进制码：0xABDB，此魔数用于区分于其他文件
* 在0xABDB后面，必须要跟着三字节的版本号，对于版本号X.Y.Z，则必须依次跟着X，Y，Z的数值，各为一字节
* 在三字节的版本号后面，需要跟着常量表（有关常量表的叙述在“STVC-TAC二进制编码规范”中有提及，因此我将其解释放到了文末的“常量表附注”中）
* 常量表后面，需要跟着若干个AstIr的单元，如果有指定，还需在单元中穿插文件调试信息
* 无论是逻辑单元，数据单元还是结束单元，每个单元的二进制长度都是八字节，前四字节是单元的类型（以``Ast.hpp``的``_AstType``为准，特别的，结束单元的类型是-1）；后四字节是单元的数据，如果该单元是逻辑单元或结束单元，则后四字节默认为0，如果该单元是数据单元，则后四字节为数据的二进制存储（采用大端存储，以Python的大端存储为标准），数据单元的种类以文末的“数据单元附表”为准。
* 如果指定需要写入调试信息，则还需要遵循以下规则
* * 在写入第一个单元之前，先写入该单元所在的文件和行号
* * 若一个单元所在的文件与上一个单元不一样，则需要写入当前单元所在文件
* * 若一个单元所在的行号与上一个单元不一样，则需要写入当前单元所在行号
* * 写入当前单元所在行号，需要先写入四字节的数值-2，然后输出四字节的行号
* * 写入当前单元所在文件，需要先写入四字节的数值-3，接着写入四字节的长度（文件名字节长度），最后逐字节地写入文件名

### 数据单元附表

|单元类型|对应的数据|
|:-|:-|
|ast::AstAnonClass|isHaveFather|
|ast::AstExpression|ass_type|
|ast::AstBinary|getOperatorType()|
|ast::AstUnary|getOperatorType()|
|ast::AstPostfix|getPostfixType()|

### AST-IR格式附注

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节点的叶子节点。

> 摘自``编译器开发文档``，2025年4月26日

### 常量表附注

一个常量表由常量表长度（占4字节）和若干个常量组成，其中常量又由常量类型（占1字节）和常量值组成：

其中每种类型的编码格式如下：

* 整数类型：占4字节，即数值
* 单精度浮点类型：占4字节，即数值
* 双精度浮点类型：占8字节，即数值
* 字符串类型：占4+len字节，其中前4字节记录字符串长度（即l，长度按字节计），后len字节为字符串值
* 标识符类型：占4+len字节，其中前4字节记录标识符长度（即len，长度按字节计），后len字节为标识符名

一个常量表下标默认为4字节。

> 摘自``STVC-TAC二进制编码规范``，2025年4月26日