From 8937b8f8d2e89b96a1e89bcb7e3bf3b7faa773c9 Mon Sep 17 00:00:00 2001 From: Codex Bot Date: Sun, 15 Nov 2026 18:21:28 +0800 Subject: [PATCH] docs(compiler): explain compilation entry points and source examples --- crates/compiler/examples/calls.endor | 8 ++++++++ crates/compiler/examples/hello.endor | 3 ++- crates/compiler/examples/literal.endor | 2 +- crates/compiler/examples/number.endor | 4 ++++ crates/compiler/examples/shadowing.endor | 8 ++++++++ crates/compiler/src/lib.rs | 22 ++++++++++++++++++++++ 6 files changed, 45 insertions(+), 2 deletions(-) diff --git a/crates/compiler/examples/calls.endor b/crates/compiler/examples/calls.endor index 4d5744c..90fdd0f 100644 --- a/crates/compiler/examples/calls.endor +++ b/crates/compiler/examples/calls.endor @@ -1,13 +1,21 @@ +// compiler/tests/pipeline.rs 将此文件作为模块编译,加载后由测试调用 main,检查前向全局函数查找。 // The callee is declared after main. Parameters, locals and calls use wordcode. +// 模块入口由宿主/测试在模块执行完成后调用;先 echo,再把局部结果交给 relay。 function main(): String { + // 直接调用后面声明的 echo,返回值写入当前帧的 message 局部槽。 let message = echo("函数调用已接通") + // 将局部值作为实参传给 relay,返回其结果给宿主。 return relay(message) } +// main 调用的中转函数;value 是当前帧参数槽,继续调用全局 echo。 function relay(value: String): String { + // 普通函数调用逐层返回相同字符串,验证嵌套调用的参数传递与返回。 return echo(value) } +// main 和 relay 共用的恒等函数,参数值直接成为调用结果。 function echo(value: String): String { + // 无额外转换,直接把参数值交给调用者。 return value } diff --git a/crates/compiler/examples/hello.endor b/crates/compiler/examples/hello.endor index 74f4030..2cfbf7e 100644 --- a/crates/compiler/examples/hello.endor +++ b/crates/compiler/examples/hello.endor @@ -1,4 +1,5 @@ -// cli run crates/compiler/examples/hello.endor → 你好,Endor 🌱 +// compiler/tests/pipeline.rs 编译并加载本模块后调用 main,期望返回“你好,Endor 🌱”。 function main(): String { + // 返回 Unicode 文本字面量,测试核对编译及 VM 返回过程保留原文。 return "你好,Endor 🌱" } diff --git a/crates/compiler/examples/literal.endor b/crates/compiler/examples/literal.endor index d60820f..fdbd795 100644 --- a/crates/compiler/examples/literal.endor +++ b/crates/compiler/examples/literal.endor @@ -1,2 +1,2 @@ -// cli eval crates/compiler/examples/literal.endor +// compiler/tests/pipeline.rs 以 Expression 模式编译此文件,VM 执行后直接取得文本;不定义 main。 "表达式 → 字节码 → VM" diff --git a/crates/compiler/examples/number.endor b/crates/compiler/examples/number.endor index 3da4a47..89c9073 100644 --- a/crates/compiler/examples/number.endor +++ b/crates/compiler/examples/number.endor @@ -1,5 +1,9 @@ +// compiler/tests/pipeline.rs 按 Module 模式编译,执行模块后调用 main 并按精确十进制值比较。 // Signed decimal constants retain all digits; no f64 conversion or arithmetic. +// 由测试/宿主调用,验证长十进制带符号常量经过编译与返回仍不丢精度。 function main(): Number { + // 字面量保存所有十进制数字,不先经 f64;源码负号经 signed_literal 合入精确数值拼写。 let value = -123456789012345678901234567890.00100 + // 返回局部槽中的数值,用于检查整个管线保持原来的精确值。 return value } diff --git a/crates/compiler/examples/shadowing.endor b/crates/compiler/examples/shadowing.endor index e509fdb..16578b0 100644 --- a/crates/compiler/examples/shadowing.endor +++ b/crates/compiler/examples/shadowing.endor @@ -1,13 +1,21 @@ +// compiler/tests/pipeline.rs 加载模块并调用 main,检查函数值传参及局部名优先于全局声明。 // A parameter can shadow a module function, and functions are ordinary values. +// main 把此全局函数作为普通值传入 invoke;实际调用时返回收到的参数。 function echo(value: String): String { + // 恒等返回,不改变用于确认调用链的文本。 return value } +// main 调用;参数 echo 遮蔽同名模块函数,value 保存待转发的字符串。 function invoke(echo: Callable, value: String): String { + // 从局部参数 echo 复制函数值,而非再次查找模块的同名全局。 let chosen = echo + // 经局部 chosen 间接调用函数,把 value 作为实参并返回调用结果。 return chosen(value) } +// 宿主/测试入口,先取得全局 echo 函数值,再传给 invoke 的同名参数。 function main(): String { + // invoke 内部用局部参数解析 echo,最终应原样返回这段文本。 return invoke(echo, "局部名称优先") } diff --git a/crates/compiler/src/lib.rs b/crates/compiler/src/lib.rs index bdaec01..4b5f72d 100644 --- a/crates/compiler/src/lib.rs +++ b/crates/compiler/src/lib.rs @@ -1,31 +1,46 @@ +//! 宿主与集成测试使用的源码编译门面:输出不依赖 VM 堆的模板,显式加载后才得到代码对象。 //! Minimal source-to-wordcode compiler. Analysis and emission do not allocate //! VM objects; a compiled unit can be loaded into independent VMs explicitly. +// 名称分析决定局部槽与全局名字表,供下一个字节码生成阶段使用。 mod analysis; +// 生成可跨 VM 复用的代码模板;仅显式 load 时才分配目标 VM 的对象。 mod codegen; +// 对宿主和测试公开名称解析结果,便于检查绑定与源码位置。 pub use analysis::{NameBinding, NameUse, Scope, ScopeKind, SymbolTable, analyze}; +// 宿主取得模板后负责选择 VM 并调用 CompiledCode::load。 pub use codegen::CompiledCode; use frontend::ast::{AstDocument, AstRoot}; use frontend::{Diagnostic, DiagnosticKind, ParseMode, SourceDiagnostic, SourceUnit, Span}; +/// 宿主通过 compile_source/compile_ast 提供的编译选项;名称分析据此允许访问宿主全局或内置名。 +/// 这里只声明名称,宿主仍需在执行前向 VM 的环境字典提供实际值。 /// Names supplied by the host's globals or builtins dictionary. These are /// compile-time declarations only; loading code never injects their values. #[derive(Debug, Clone, Default)] pub struct CompileOptions { + // 编译期已知名称列表;analyze 与源码声明共同解析可用的全局名,不在此持有 VM 值。 pub globals: Vec, } +/// 宿主及 compiler 集成测试的源码编译入口:按指定模式解析,再校验 AST、解析名称并生成模板。 +/// source 提供文件身份与原始文本;mode 决定模块、表达式或交互根;options 声明额外宿主名称。 +/// 解析错误已有源码诊断;后续编译错误在这里附加同一源码的位置和片段,成功不执行任何 VM 指令。 pub fn compile_source( source: &SourceUnit, mode: ParseMode, options: &CompileOptions, ) -> Result { + // 前端根据模式返回对应 AstRoot,解析失败立即把带源码信息的错误传给宿主。 let root = frontend::parse_source_ast(source, mode)?; + // AST 入口返回不含源码快照的 Diagnostic;在此统一补上 SourceUnit 上下文。 compile_ast(&root, source, options).map_err(|error| source.annotate(error)) } +/// compile_source 及已有 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. pub fn compile_ast( @@ -33,8 +48,10 @@ pub fn compile_ast( source: &SourceUnit, options: &CompileOptions, ) -> Result { + // 包装并校验 AST 文档结构,再检查节点跨度对当前 source 文本是否有效;不修改调用方的树。 AstDocument::new(root.clone()) .and_then(|document| document.validate_source(source.text())) + // 文档结构/跨度验证错误归入编译错误,尚无可靠单一节点位置,使用默认跨度。 .map_err(|error| { diagnostic( DiagnosticKind::Compilation, @@ -42,11 +59,16 @@ pub fn compile_ast( error.to_string(), ) })?; + // 收集并解析所有作用域的绑定及代码布局;错误会阻止生成阶段继续。 let symbols = analyze(root, options)?; + // 生成器按解析后的槽/名字索引编码,不在此加载模板或分配 VM 堆对象。 codegen::generate(root, source, &symbols) } +/// 本模块的 AST 验证及 analysis/codegen 的错误辅助函数共用,统一构造不带源码快照的诊断。 +/// kind 区分语义/编译错误,span 标记位置,message 接受可转 String 的说明;语法期望项留空。 fn diagnostic(kind: DiagnosticKind, span: Span, message: impl Into) -> Diagnostic { + // 编译器错误没有解析器的“期望 token”列表,源码上下文由上层 compile_source 统一附加。 Diagnostic { kind, span,