feat: generate unified AST and editor contracts from ASDL
Verify databases and deploy Aster VM / verify-and-deploy (push) Successful in 7m55s
Verify databases and deploy Aster VM / verify-and-deploy (push) Successful in 7m55s
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
# AST 模型、ASDL 与跨工具接口
|
||||
|
||||
Endor 的 AST 节点统一由 [Endor.asdl](../../crates/frontend/Endor.asdl) 定义。它描述节点及字段;lexer.peg 描述字符识别,grammar.peg 描述语法与节点构造。ASDL 与语法各自维护一个职责,不引入 CST 或 Python type/元类;AST 位于 frontend,运行时对象位于 objects。
|
||||
|
||||
## 生成关系
|
||||
|
||||
```text
|
||||
Endor.asdl → scripts/generate_ast.py
|
||||
├─ src/ast/generated.rs:Rust 节点、Serde 与 Spanned
|
||||
├─ src/ast/visitor.rs:Rust Visitor/walk_*
|
||||
├─ editor/ast.ts:TypeScript 类型、Visitor/walk*
|
||||
└─ editor/ast.schema.json:JSON Schema 2020-12
|
||||
```
|
||||
|
||||
路径均相对 crates/frontend。生成器使用 Python 标准库和 rustfmt,无额外 Python 包、build.rs 或构建时网络访问。产物提交到 Git,普通 Cargo 构建直接使用它们。开发修改 schema 后,在仓库根执行:
|
||||
|
||||
```sh
|
||||
python3 scripts/generate_ast.py --write
|
||||
python3 scripts/generate_ast.py --check
|
||||
```
|
||||
|
||||
这两条命令是源码生成/静态检查,可在本地使用;行为测试仍仅在指定远端执行。CI 检查生成同步,并运行生成器回归检查与工作区测试。
|
||||
|
||||
ASDL 支持 module、产品类型 `(Type field, ...)`、构造器联合 `A(...) | B(...)`、`*` 序列、`?` 可选字段、`--` 行注释。内建 string 是拥有文本的 String,span 对应共享的 UTF-8 Span,schema_id 是交换契约标识。生成器检查重复名称、字段、未知类型和不支持的语法;这是项目使用的 ASDL 子集,不声称兼容 CPython ASDL 的全部扩展。
|
||||
|
||||
Rust 用 struct/enum、Vec/Option 表达结构;生成器在按值依赖图的回边放置 Box,Vec 已经断开按值递归。增加节点后,Rust 类型、两种语言的遍历接口和 JSON Schema 由同一次生成更新。
|
||||
|
||||
## 根、声明、语句、表达式
|
||||
|
||||
| 层级 | 当前数据模型 |
|
||||
| --- | --- |
|
||||
| AstRoot | Module(Program)、Expression(Expr)、Interactive(InteractiveInput) |
|
||||
| Program | declarations: Vec<Decl> 与 span;当前声明种类为 Function |
|
||||
| Decl/DeclKind | 声明的位置及其具体种类;Function 保存参数、返回类型名称和 Block |
|
||||
| Block | statements: Vec<Stmt> 与 span,不再用固定的 bindings/result 字段表示 |
|
||||
| Stmt/StmtKind | Binding、Return、Expression、Declaration;每条语句有自身范围 |
|
||||
| ReturnStatement | 可选表达式与范围;当前源码中的 return 仍要求表达式 |
|
||||
| Expr/ExprKind | 名称、数字原文、字符串、符号、一元/二元运算、成员和调用 |
|
||||
|
||||
参数与返回类型仍为 Name,只保留语法,不实施类型或名称检查。Program::functions() 提供函数迭代便捷接口。旧的 Program.functions、Block.bindings/result/return_span 字段已移除;源码构造和使用方改为声明/语句列表。ExprKind 的既有表达式结构保留。
|
||||
|
||||
AST 数据模型允许一般语句列表,不代表 parser 接受了所有组合。模块仍要求一个或多个函数;函数体仍接受 let* 后跟一个带值 return。Interactive 模式接受一次函数声明、let 绑定或表达式,必须消费完整输入;不创建交互会话,不处理续行提示,不执行语言代码。多条交互提交由宿主分别解析。条件、循环、导入、类等尚未实现,也不加入 FunctionType 这种 Python 专用入口。
|
||||
|
||||
## 解析与位置
|
||||
|
||||
parse_ast(&str, ParseMode) 和 parse_source_ast(&SourceUnit, ParseMode) 返回 AstRoot;ParseMode 包含 Module、Expression、Interactive。原有 parse/parse_expression/parse_source/parse_source_expression 保留对应的具体返回类型。带来源入口的诊断仍记录名称/URI/修订和行列。
|
||||
|
||||
Spanned 为有位置的节点提供 span()、source_text(&str)、location(&str)。Span::slice/location 拒绝反向、越界或截断 UTF-8 字符的范围;行列是一基 Unicode 标量列,CRLF 算一次换行。Span 不携带源码身份,调用方需关联原始 SourceUnit;AST JSON 本身不含源码、文件路径、URI 或资源修订。
|
||||
|
||||
## 遍历与分析
|
||||
|
||||
生成的 Rust Visitor 有每个节点/种类的 visit_* 方法、默认 walk_* 函数,以及 enter_node/leave_node 钩子。Error 为关联类型,子节点失败时默认遍历返回错误,并配对调用已进入节点的离开钩子。可在 visit_function、visit_binding、visit_expr 等位置实现名称分析或字节码生成。
|
||||
|
||||
覆盖 visit_* 后,调用 walk_* 可继续访问子节点;覆盖方法自身的钩子管理由实现者决定,直接调用 walk_* 不会重复调用当前节点的 visit_*。这些接口只提供遍历,尚未实现名称绑定、闭包捕获分析或字节码生成。TypeScript Visitor 对应编辑器使用,回调返回 false 可跳过子树。
|
||||
|
||||
## JSON 交换
|
||||
|
||||
frontend 使用工作区已有的 serde/serde_json。AstDocument 是带 schema 和 root 的交换外壳,提供 new、to_json、from_json、validate、validate_source。构造/读取/写出时检查 schema 标识、位置顺序、父子范围包含关系及 JS 安全整数范围;validate_source 额外检查给定原文的长度和 UTF-8 字符边界,不比较原文与节点的程序含义。
|
||||
|
||||
构造器联合按 `{"kind":"Variant","data":...}` 编码,无字段的运算符联合使用字符串。产品类型使用字段对象;未知字段和未知构造器拒绝。可选字段可省略或为 null,标准写出为 null。数字保留源码拼写字符串,不经浮点转换。
|
||||
|
||||
AST_SCHEMA_ID 从 Endor.asdl 的 UTF-8 文本计算 SHA-256,包含注释与空白;生成器读取时使用 Python 的统一换行规则。它标识这套 AST 接口定义,区别于用户资源修订、编译器或 VM 版本。修改 schema 后旧标识被拒绝,尚无历史格式迁移。改变生成器的交换编码或内建位置类型契约时,也必须更新 ASDL 顶部的 Wire contract 版本说明,使标识随之变化。直接调用 Serde 是结构编解码,跨边界应使用 AstDocument 方法执行完整校验;JSON Schema 不表达所有位置约束。
|
||||
|
||||
CLI 可提供具体的交换输出:
|
||||
|
||||
```sh
|
||||
cli parse --json source.endor
|
||||
cli parse --mode expression --json -
|
||||
cli parse --mode interactive --json -
|
||||
```
|
||||
|
||||
文件/stdin 阅读保持原有 UTF-8 和错误来源规则,stdin 到 EOF 后才解析。普通 cli parse 输出 AstRoot 的 Debug 文本,稳定交换使用带 schema 的 JSON;所有入口均不执行源码。命令在指定远端运行。
|
||||
|
||||
检查源码见 [frontend/tests](../../crates/frontend/tests/README.md) 和 [生成器检查](../../scripts/test_generate_ast.py),边界见 [验证](../operations/validation.md)。返回 [运行时索引](README.md)。
|
||||
Reference in New Issue
Block a user