Roc 语言%与//运算符优先级解析从 issue 9712 回归测试看左结合规则与 REPL 快照验证【免费下载链接】rocA fast, friendly, functional language.项目地址: https://gitcode.com/GitHub_Trending/ro/roc1 % 10 // 100到底该先算哪个在 Roc 语言中这个看似简单的表达式背后隐藏着一个运算符优先级回归测试——repro_issue_9712_mod_floordiv_precedence.md。本文以该快照测试文件为主线深入 Roc 编译器的词法分析与绑定优先级binding power实现讲解%取模与//整除为何必须从左到右解析为(1 % 10) // 100以及 REPL 快照测试如何机械地验证这一行为。读完你将掌握 Roc 运算符优先级的底层机制、快照测试文件的格式规范与更新流程。背景issue 9712 到底修复了什么Roc 是一门fast, friendly, functional的语言其编译器即当前仓库在 src/parse/Parser.zig 中统一维护所有二元运算符的优先级。issue 9712 描述的缺陷是当取模运算符%与整除运算符//出现在同一表达式中时如果解析器将//的优先级错误地置于%之上表达式1 % 10 // 100会被解析为1 % (10 // 100)。按数学计算10 // 100整除结果为 0于是整个表达式退化为1 % 0——对零取模直接导致运行时崩溃。正确的语义要求这两个运算符属于同一优先级组并保持左结合left-associative使1 % 10 // 100解析为(1 % 10) // 100先得1 % 10 1再1 // 100 0安全得到结果 0全程不崩溃。逐段解析快照文件META / SOURCE / OUTPUT / PROBLEMS该回归测试位于 test/snapshots/repro_issue_9712_mod_floordiv_precedence.md全文仅四个段落却完整编码了一次 REPL 求值的全部期望# META ~~~ini descriptionrepro for https://github.com/roc-lang/roc/issues/9712—1 % 10 // 100 must parse left-to-right as (1 % 10) // 100 0, not crash typerepl ~~~ # SOURCE ~~~roc » 1 % 10 // 100 ~~~ # OUTPUT 0.0 # PROBLEMS NILMETA以ini代码块声明快照元数据。description用一句话记录该测试的动机——复现 issue 9712强调1 % 10 // 100必须按从左到右解析为(1 % 10) // 100 0而非崩溃typerepl声明这是 REPL 类型的快照详见 test/snapshots/README.md 中关于快照类型的说明与file、expr、snippet等类型区分开来。SOURCE»是 Roc REPL 的输入提示符其后是要在 REPL 会话中逐行求值的表达式。快照工具正是以»为分隔符切分输入见下文源码分析。OUTPUT记录 REPL 求值输出的期望值0.0。注意结果以浮点形式呈现——这是 REPL 表达式求值器对数值表达式的输出格式由解释器内省输出路径决定见 src/snapshot_tool/main.zig 的lirInterpreterInspectedStr调用。数值上(1 % 10) // 100 1 // 100 0与0.0等价。PROBLEMSNIL表示该表达式在编译全流程词法、语法、canonicalization、类型检查中没有产生任何诊断报告。若优先级解析出错导致崩溃或类型错误此段将不再是NIL从而让回归测试立即失败。词法层面//与%如何被切分为 Token优先级问题的第一层证据在词法分析器 src/parse/tokenize.zig 中。//与%分别被切分为独立的运算符 Token字符/的切分逻辑tokenize.zig当当前位置的下一个字符也是/时一次性消费两个字符并生成.OpDoubleSlash整除运算符//否则生成单个.OpSlash普通除法/。这说明//是单一 Token而不是两个/的拼接语法层由此才能对//单独赋优先级。字符%的切分逻辑tokenize.zig消费单个字符并生成.OpPercent取模运算符%。Token 定义本身也印证了这一点.OpSlash与.OpPercent同属于二元运算符 Token 枚举tokenize.zig而.OpDoubleSlash则单独存在。Token 化完成后的 Token 流即为解析器优先级表下节的输入。解析层面绑定优先级表与乘法组的左结合规则优先级决策的真正核心在解析器 src/parse/Parser.zig 中。Roc 使用 Pratt 解析器风格的绑定优先级binding power表每个运算符同时记录左右两侧的优先级数值pub const BinOpBp struct { left: u8, right: u8 };相关条目如下Parser.zig运算符 Tokenleftright说明OpStar*3233乘法OpSlash/3233除法OpDoubleSlash//3233整除OpPercent%3233取模OpPlus2223加法OpBinaryMinus-2223减法源码注释对此给出了精确的语义解释Parser.zig*、/、//、%构成同一个乘法优先级组组内彼此左结合——因为right left当解析器在右操作数位置遇到同组的下一个运算符时其left32无法满足left min_bp此时最小可接受优先级为 33于是循环终止不会把后续运算符吞进右操作数。具体到1 % 10 // 100解析1遇到%left32, right33进入右操作数解析min_bp设为 33解析10遇到//left32——但32 33不成立//不被吞入%的右操作数%的解析完成得到(1 % 10)随后//作为同一层级的下一运算符继续左结合解析最终得到(1 % 10) // 100。同理该组整体绑定比加法组22/23更紧即a b % c // d会先归组为a ((b % c) // d)。这一设计与常见 C 系语言的乘法/除法/取模同级左结合语义一致也是 Roc friendly 设计理念在运算符层面的体现。实操运行与更新这条 REPL 快照测试快照测试的驱动工具由 build.zig 暴露为zig build run-snapshot-tool步骤用法与说明详见 test/snapshots/README.md# 运行/重新生成全部快照 zig build run-snapshot-tool # 只处理当前这条优先级回归快照 zig build run-snapshot-tool -- test/snapshots/repro_issue_9712_mod_floordiv_precedence.md # 用当前编译器输出覆盖期望值OUTPUT 段 zig build run-snapshot-tool -- test/snapshots/repro_issue_9712_mod_floordiv_precedence.md --update-expected # 带解释器 trace 调试 REPL 快照仅限 typerepl 且单文件 zig build run-snapshot-tool -- test/snapshots/repro_issue_9712_mod_floordiv_precedence.md --trace-eval工作流程上.rules 亦有记载当修改编译器后运行zig build run-snapshot-tool通过 diff 审查快照变化是否为预期行为。若解析器优先级表被误改本快照的OUTPUT会从0.0变为崩溃错误文本或异常值测试随即暴露回归。快照工具的 CLI 校验逻辑对--trace-eval有强约束它只能用于typerepl快照且只能搭配单个文件使用src/snapshot_tool/main.zig与本文件类型完全匹配。源码视角REPL 快照的机械执行流程REPL 快照并非手写结果而是由工具按固定管线生成与校验的核心实现位于 src/snapshot_tool/main.zig分发processSnapshotFile检测content.meta.node_type .repl后转交processReplSnapshotmain.zig后者依次生成 HTML 包装、META、SOURCE、OUTPUT、PROBLEMS 各段main.zig。切分输入generateReplOutputSection以»为分隔符把 SOURCE 切成若干条 REPL 输入main.zig每条输入经snapshotReplStep分发为定义 / 表达式 / 语句表达式三种求值模式之一main.zig。求值输出表达式最终由 LIR 解释器求值并经lirInterpreterInspectedStr转成字符串main.zig多步输出之间以独立的---行分隔空输出如纯类型标注步骤也按位置保留main.zig。更新或校验在--update-expected模式下把实际输出写回快照文件在校验模式下与实际输出比对并报告差异。正是这套管线保证了语法语义正确性与渲染展示效果分离普通快照含本文件的PROBLEMS段记录的是诊断的规范化 S-expression见 test/snapshots/README.md不含任何盒式绘制字符、ANSI 转义等渲染细节——NIL即无任何报告的规范表示。本快照的PROBLEMS: NIL因此意味着该表达式在全部编译阶段均无错误与警告。小结一条快照背后的完整语义链条回到最初的问题1 % 10 // 100在 Roc 中之所以安全求值为0.0是因为从词法//作为独立 Token 切分到语法*、/、//、%共享 left32/right33 的同一乘法优先级组且组内左结合再到快照测试OUTPUT: 0.0、PROBLEMS: NIL形成了一条完整的、可机械验证的语义链条。对编译器开发者而言这条快照既是 issue 9712 的回归防线也是理解 Roc 运算符优先级设计的绝佳入口对语言使用者而言记住乘法组内一律从左到右这一规则即可安全混用%、//、*、/必要时用括号显式表达意图。进一步探索建议阅读 src/parse/tokenize.zig 中运算符 Token 的完整枚举与%、//的切分分支阅读 src/parse/Parser.zig 中BinOpBp定义、bin_op_bp_table全表及分组注释阅读 test/snapshots/README.md 了解普通快照与 reporting 快照的分工浏览 test/snapshots/binops.md 等同类快照对比其他二元运算符的解析期望。【免费下载链接】rocA fast, friendly, functional language.项目地址: https://gitcode.com/GitHub_Trending/ro/roc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
Voyager 消息时间戳(Message Timestamps)功能指南:为 Gemini 对话标注精确发送时间 AI 应用前端 【免费下载链接】voyager Enhancement suite for Gemini, AI Studio, Claude & ChatGPT — plus a prompt manager for any websites, DeepSeek Harness included. / 面向 Gemini、AI Studio、Claude 与 ChatGPT 的增强套件;其中的提示词管理器可用… · 2026/9/21 1:43:41
DNV-OS-B101金属材料规范全解析:海工材料选型与验收关键要点 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/21 1:43:41
MCP Python SDK 依赖注入实战:用 Resolve 让工具参数对模型不可见 MCP Python SDK 依赖注入实战:用 Resolve 让工具参数对模型不可见 【免费下载链接】python-sdk The official Python SDK for Model Context Protocol servers and clients 项目地址: https://gitcode.com/gh_mirrors/pythonsd/python-sdk
工具(t… · 2026/9/21 1:43:41
AI桌面助手自动执行与权限管理实战:安全与效率如何平衡 "允许访问这个文件夹吗?"2026年,几乎所有主流AI桌面助手首次启动时都会弹出这句授权请求。对比2023年那个"只会写诗聊天"的AI,你手里的桌面助手如今会读文件、改配置、运行命令、批量删除重复文件,甚至自己写… · 2026/9/21 2:22:47
极摩客迷你主机本地AI部署指南:从内存核显到Ollama实战 最近身边折腾本地 AI 的朋友明显多了,以前找我配电脑都是先问显卡显存、电源瓦数,最近画风全变了:上来就问能不能在自己家里跑 DeepSeek,聊天记录不想出本机,公司文档想整理成私有知识库,还有人想把本地模型… · 2026/9/21 2:22:47
ESD保护版图设计核心细节:从电流路径到镇流电阻的实战指南 简介:面向集成电路设计与可靠性工程师的ESD(静电放电)保护专题文档,系统梳理静电放电对CMOS芯片的危害机理,并围绕接地栅NMOS(GGNMOS)器件物理分析,详解ESD保护结构的设计原理、版图… · 2026/9/21 2:22:47
CAN总线实战指南:STM32多节点实时通信系统搭建与避坑全记录 简介:一份基于STM32的CAN总线多节点工业控制系统设计资料,面向具备嵌入式开发基础、熟悉STM32与C语言的软硬件工程师和工业自动化研发人员,目标是从零构建高可靠、可扩展的工业现场通信网络,实现电机控制、传感器采集、阀门执行和… · 2026/9/21 2:22:47
Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化 直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡… · 2026/9/21 0:02:39
Word表格编号全攻略:从列表编号到题注交叉引用 写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技… · 2026/9/21 0:02:39
从第一个站到第二个站:独立开发者的静态网站选型与落地实践 1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&… · 2026/9/20 0:00:41
agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程 agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程 【免费下载链接】agentic-awesome-skills AAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and … · 2026/9/21 0:00:18
gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析 gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析 【免费下载链接】gin-vue-admin 🚀ViteVue3Gin拥有AI辅助的基础开发平台,企业级业务AI开发解决方案,内置mcp辅助服务,内置skills管理,… · 2026/9/21 0:00:18