docs(compiler): clarify analysis and template loading contracts
This commit is contained in:
@@ -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("") {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user