
编程语言编译器语言运行时开发工具【免费下载链接】unisonA friendly programming language from the future项目地址https://gitcode.com/gh_mirrors/un/unison点击查看免费下载本文以 unison-src/transcripts/idempotent/fix3634.md 这份幂等回归测试idempotent transcript为骨架解析 Unison 文档系统Doc2中docExample代码示例的渲染行为并对照base库中syntax.docExample的实现与解析器源码说明{{ docExample 0 (x - J x) }}这类写法为何会渲染为x - J x以及引号延迟 thunk在示例中的处理方式。读完本文你将掌握 Doc2 文档中内嵌代码示例的标准写法、docExample参数语义以及如何借助 transcript 机制验证文档渲染输出。一、背景什么是 idempotent transcriptUnison 项目使用一种名为 transcript 的机制做端到端回归测试把一段带ucmUnison Codebase Manager命令与.u/.uu源码的 Markdown 文件交给测试框架执行将 UCM 的真实输出回填到 ucm :added-by-ucm代码块中再与人工维护的 ucm代码块比对。fix3634.md位于 unison-src/transcripts/idempotent/ 目录下属于“幂等”类别——即同样的输入重复执行应得到稳定一致的输出这类测试常用于锁定某一 bug 修复后的行为防止日后回归。这份文档编号对应 GitHub issue #3634从内容看它锁定的正是Doc2 文档中docExample代码示例的渲染输出过去带引号thunk 标记的示例表达式可能被错误地连带渲染出引号修复后应只渲染去引号后的表达式。二、测试内容逐行解读1. 准备基础库环境 builtins.mergeiobuiltins.mergeio会把内建的输入输出能力IO 等 builtins合并进当前分支使后续脚本可以使用builtins相关定义。这里使用:hide选项表示该命令的执行过程不出现在 transcript 的最终输出中只作为前置准备步骤。2. 定义数据类型与文档值structural type M a N | J a d {{ {{ docExample 0 (x - J x) }} {J} }}这段脚本同时做了三件事定义了一个结构类型M a它有两个构造子无参的N和带一个参数a的J a。这里的J是构造子之后文档中用{J}引用它。用{{ ... }}块语法定义了一个Doc2类型的文档值d。文档正文包含一个{{ docExample 0 (x - J x) }}内联代码示例以及一个{J}类型/构造子链接。3. 检测到的变更Loading changes detected in scratch.u. structural type M a d : Doc2 Run update to apply these changes to your codebase.这是 transcript 框架自动回填的输出UCM 检测到 scratch 文件中的新增定义——M a类型和类型为Doc2的d并提示可用update将变更应用到 codebase。注意d : Doc2说明{{ ... }}块语法的结果类型是文档类型Doc2。4. 添加定义并展示文档 add Okay, Im searching the branch for code that needs to be updated... Done. display d x - J x Jadd把 scratch 中的定义加入 codebase随后 display d在终端渲染该文档。关键断言就在这里{{ docExample 0 (x - J x) }}被渲染为x - J x外层反引号表示等宽代码引号不再出现{J}被渲染为J即解析为一个指向构造子J的链接。三、docExample语法深入1. 定义与类型docExample并非关键字而是base库中名为syntax.docExample的普通函数。在 unison-src/transcripts-using-base/doc.md.files/syntax.u 中可以看到它的完整定义syntax.docExample : Nat - {g1} t - Doc syntax.docExample n a Special (Example n (term a))它接收两个参数参数类型含义nNat渲染示例时忽略丢弃前n个函数参数使示例聚焦在最内层调用a{g1} t一个延迟的能力项thunk里面是待展示的表达式Special (Example n (term a))表明docExample是文档系统中的“特殊形式”它的参数a会被当作代码示例处理而不是求值结果。2. 参数n的语义n表示“渲染时忽略前几个参数”。看 syntax.u 中关于内联片段的说明{{ docExample 2 (f x - f x sqr 1) }}— the 2 says to ignore the first two arguments when rendering.也就是说docExample 2 (f x - ...)只展示函数体部分把f x这两个绑定参数隐藏而 fix3634 中docExample 0 (x - J x)的0表示一个参数都不忽略完整展示x - J x。当示例表达式只是单个函数应用时可以直接用双反引号包裹等价于docExample 1sqr x is equivalent to{{ docExample 1 (x - sqr x) }}。3. 单引号的作用在 Unison 中表示“延迟”把一个表达式包成 thunk{g1} t。docExample的第二个参数要求是延迟的因此标准写法是{{ docExample 0 (x - J x) }}。渲染时这个外层 thunk 只作为“携带待展示代码”的容器不会显示为(...)这正是 fix3634 验证的核心行为。四、源码级原理Doc.Example是如何解析的在解析器 parser-typechecker/src/Unison/Syntax/TermParser.hs 的doc2Block中文档叶子节点Doc.Example code的处理逻辑如下第 791-799 行Doc.Example code - do trm - subParse term code pure . Term.apps (f d Example) $ case trm of tm(Term.Apps _ xs) - let fvs List.Extra.nubOrd $ concatMap (toList . Term.freeVars) xs n Term.nat (ann tm) (fromIntegral (length fvs)) lam addDelay $ Term.lam (ann tm) ((mempty,) $ fvs) tm in [n, lam] tm - [Term.nat (ann tm) 0, addDelay tm]这段代码印证了上述语义对{{ ... }}内的代码先做一次子解析subParse term code得到项trm如果trm是一个函数应用链Term.Apps _ xs则统计所有参数的自由变量数量length fvs把它作为n对应docExample 0、docExample 2中的数字并把参数包成 lambda 后整体延迟addDelay如果trm不是应用链则n 0、直接延迟该项。由此可以推断docExample n ...中的数字n由解析器自动计算并传给syntax.docExample渲染端再依据n决定隐藏几个前置参数。fix3634 中(x - J x)是单参数 lambda 形式自由变量统计与延迟化处理后最终渲染为x - J x。另一处佐证来自docExampleBlock解析器对文档顶层代码块Doc.ExampleBlock code使用block False True syntax.docExampleBlockTermParser.hs并固定以Term.nat ... 0作为忽略参数个数生成ExampleBlock 0 ...形式——即块级示例默认不忽略任何参数。而在打印端parser-typechecker/src/Unison/Syntax/TermPrinter.hs 的toDocExample与toDocExampleBlock第 2185-2186 行负责把Example/ExampleBlock特殊形式还原为docExample/docExampleBlock的源码文本保证文档可往返round-trip打印而不丢语义。五、{J}链接的渲染{J}在文档中属于“嵌入链接”embed link{Some}是术语链接、{type Optional}是类型链接见 syntax.u 中的说明。解析器中docEmbedLinkTermParser.hs按引用级别分派类型/构造子引用生成syntax.docEmbedTypeLink术语引用生成syntax.docEmbedTermLink并延迟处理。fix3634 的display d输出中{J}渲染为J说明文档系统正确地把构造子J解析为类型链接并显示其名称而M类型在文中被引用时也能以{type M}的方式链接。六、如何运行与验证该测试与其它 transcript 一样不需要手工搭建环境即可复现预期输出在 UCM 中执行builtins.mergeio准备内置环境将M a类型与d : Doc2文档写入 scratch 文件依次执行add与display d断言终端输出严格为x - J x与J两行与 fix3634.md 中的期望输出一致。若渲染结果中出现了(x - J x)或丢失链接格式即说明docExample的 thunk 剥离或类型链接解析出现回归。类似的文档渲染断言还大量出现在 unison-src/transcripts/pretty-print-libraries.output.md例如第 907-939 行对docExample 2 do a b - a b等逻辑表达式的说明中可作为编写 Doc2 文档的参考范本。七、小结从 fix3634.md 这一份简短回归测试可以提炼出 Doc2 代码示例的三条实战结论写法{{ docExample 0 (x - J x) }}——docExample需要显式数字与一个单引号延迟的表达式语义数字n控制渲染时忽略的前置参数个数thunk 引号仅作携带代码的容器不会被打印实现该行为由 TermParser.hs 中的自由变量统计与延迟化逻辑、syntax.u 中的syntax.docExample定义共同保证并由幂等 transcript 持续锁定。赞分享编程语言编译器语言运行时开发工具【免费下载链接】unisonA friendly programming language from the future项目地址https://gitcode.com/gh_mirrors/un/unison点击查看免费下载相关推荐Unison 文档块内嵌代码围栏的解析与回显以 fix2244 回归测试为例Unison 文档块内嵌代码围栏的解析与回显以 fix2244 回归测试为例 导读 本文以 fix2244.md https://link.gitcode.c编程语言编译器语言运行时开发工具OpenCompass Inference-PPL 指南基于预标注位置的困惑度评测实现与配置OpenCompass Inference PPL 指南基于预标注位置的困惑度评测实现与配置 导读 本文围绕 OpenCompass 中的 Inference编程语言编译器语言运行时开发工具Unison 回归测试实战从 fix3939 看 docs 命令与 Doc2 文档字面量的工作机制Unison 回归测试实战从 fix3939 看 docs 命令与 Doc2 文档字面量的工作机制 本文以 Unison 仓库中的回归测试 unison sr编程语言编译器语言运行时开发工具上一篇gogcli 电子表格列宽调整指南用 gog sheets resize-columns 在终端里精确控制 Google Sheets 列宽下一篇VS Code 扩展实战教程使用 Language Model API 为编辑器生成 AI 代码注释Code Tutor创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考