docs(compiler): clarify analysis and template loading contracts

This commit is contained in:
2026-11-15 19:46:25 +08:00
parent d8f195e907
commit a275d6ee55
3 changed files with 13 additions and 7 deletions
+7 -4
View File
@@ -33,7 +33,7 @@ pub enum NameBinding {
#[derive(Debug, Clone, PartialEq, Eq)]
/// 一次名称表达式的解析结果;名字加源码跨度定位具体使用点,避免同名出现互相混淆。
pub struct NameUse {
// 名称文本;Scope 使用它作为代码名,NameUse 使用它标识被读取的名称。
// 本次读取的名称文本,生成器与 span 联合匹配,取得该表达式的绑定。
pub name: String,
// 原源码中的半开字节范围,用于诊断及生成阶段定位。
pub span: Span,
@@ -46,7 +46,7 @@ pub struct NameUse {
pub struct Scope {
// 决定赋值存局部还是全局,以及是否允许 return。
pub kind: ScopeKind,
// 名称文本;Scope 使用它作为代码名,NameUse 使用它标识被读取的名称。
// 根的合成诊断名或源码函数名;生成器同时用 span 区分不同类的同名方法。
pub name: String,
// 原源码中的半开字节范围,用于诊断及生成阶段定位。
pub span: Span,
@@ -57,7 +57,8 @@ pub struct Scope {
}
#[derive(Debug, Clone)]
/// compile_ast 把整个解析结果交给 codegen;模板生成不再自行猜测名称绑定。
/// analyze 返回、compile_ast 交给 codegen 的分析结果;根布局和每个函数体布局分开保存。
/// 字段公开以供宿主/测试检查,但改动此表不会更新原 AST,也没有公开入口把任意改表直接编译。
pub struct SymbolTable {
// 根代码单元,即模块、表达式或交互输入的作用域。
pub root: Scope,
@@ -86,6 +87,8 @@ fn declaration_name(declaration: &Decl) -> &frontend::ast::Name {
/// shadows the global for the entire function, but cannot be read early.
/// compile_ast 和直接分析测试调用;options 仅声明额外全局名,返回根及各函数的绑定布局。
/// 函数体先收集所有局部名,因此后面的 let 也会遮蔽前面的全局读取,但未初始化读取会报错。
/// 直接调用只做本阶段的名称/控制流分析,不执行 AstDocument 跨度验证、类型解析或字节码验证;
/// 需要完整流水线的宿主使用 compile_ast/compile_source,不能把此处成功视为代码已可执行。
pub fn analyze(root: &AstRoot, options: &CompileOptions) -> Result<SymbolTable, Diagnostic> {
// 交互模式要求恰好一条语句;空输入或批量输入不是本编译入口支持的单位。
if let AstRoot::Interactive(input) = root
@@ -96,7 +99,7 @@ pub fn analyze(root: &AstRoot, options: &CompileOptions) -> Result<SymbolTable,
"interactive input must contain exactly one statement",
));
}
// 宿主名称先去重,后续加入源码声明;这里只声明合法名称,不持有实际 VM 值。
// 宿主名称先去重,后续加入源码声明;这里只登记文本,不校验其是否符合词法名称规则或提供 VM 值。
let mut globals: BTreeSet<String> = options.globals.iter().cloned().collect();
// 在分析任何代码前拒绝空宿主名,避免不可解析的名称混入绑定集合。
if globals.contains("") {
+4 -2
View File
@@ -21,7 +21,7 @@ pub struct CompiledCode {
}
impl CompiledCode {
/// 宿主/测试检查已解码指令及偏移,借用模板,不执行代码。
/// 宿主/测试检查已解码指令及偏移,借用模板,不执行代码;子代码常量此时仍为 Nil 占位。
pub fn instructions(&self) -> &[DecodedInstruction] {
self.code.instructions()
}
@@ -55,6 +55,8 @@ impl CompiledCode {
/// released on both success and failure, including partial recursive loads.
/// 宿主/测试显式装入目标 VM;成功返回一个拥有代码根,调用者执行完成后负责 release。
/// 已分配子根无论后续成功或失败都在外层归还,父代码成功分配时已有自己的常量内部边。
/// Tessera Candidate 或开发者页面安装器持有这份代码根;本方法不运行模块、不安装 globals,
/// 每次 load 重新分配目标堆身份,模板可复用,调用者仍需显式执行并清理返回值。
pub fn load(&self, vm: &mut Vm) -> Result<ObjectRef, VmError> {
// 记录本次已成功加载的子代码拥有根,外层统一归还,覆盖递归中途失败。
let mut roots = Vec::new();
@@ -483,7 +485,7 @@ impl<'a> Emitter<'a> {
/// 数值字面量和已合并符号的字面量共用,直接从十进制拼写构造精确数值,不经过 f64。
fn number(&mut self, spelling: &str, span: Span) -> Result<(), Diagnostic> {
// 根据拼写中的小数点选择精确十进制或整数解析,失败保留字面量跨度。
// 当前源码数字不含指数,按小数点选择精确十进制或整数解析;手工 AST 拼写也走此选择而不重分词。
let value = if spelling.contains('.') {
EndorNumber::decimal(spelling)
} else {
+2 -1
View File
@@ -39,7 +39,8 @@ pub fn compile_source(
compile_ast(&root, source, options).map_err(|error| source.annotate(error))
}
/// compile_source 及已有 AST 的宿主/测试调用;先验证结构与跨度,再分析名称,最后输出代码模板。
/// compile_source、Tessera 源码计划/开发者页面安装器及已有 AST 的宿主/测试调用;
/// 先验证结构与跨度,再分析名称,最后输出代码模板。
/// 传入 source 必须是期望匹配的位置快照;跨度有效只说明位置在范围内,不能证明 AST 与文本语义相同。
/// Compile an AST against its original source snapshot. Span validation does
/// not prove the AST's semantic equivalence to the supplied text.