尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

roc 语言中的类型化小数模式匹配:从 issue 10134 快照测试看 F32/F64 字面量后缀的解析与类型约束

roc 语言中的类型化小数模式匹配:从 issue 10134 快照测试看 F32/F64 字面量后缀的解析与类型约束 roc 语言中的类型化小数模式匹配从 issue 10134 快照测试看 F32/F64 字面量后缀的解析与类型约束【免费下载链接】rocA fast, friendly, functional language.项目地址: https://gitcode.com/GitHub_Trending/ro/roc导读本文以 roc 编译器仓库中的快照测试文档 issue_10134_typed_frac_patterns.md 为核心线索讲解 roc 语言中「带显式类型后缀的小数字面量」如1.5.F32、1.5.F64在match模式pattern中的语法、解析、规范化和类型检查行为。读者将掌握如何书写带类型后缀的小数模式、编译器各阶段如何表示与处理这类模式、以及后缀类型与匹配上下文类型不一致时会得到怎样的错误诊断——这些内容同时以编译器源码与配套快照为证据可直接用于 roc 语言开发与编译器源码阅读。一、背景什么是「类型化小数模式」roc 是一门快速、友好、函数式的编程语言。与其他函数式语言类似roc 使用match表达式做模式匹配。在普通的小数字面量之外roc 还支持带显式类型后缀的小数字面量例如1.5.F32、1.5.F64、1.5.Dec等。其中.F32、.F64后缀表示该字面量的类型注解type annotation / type suffix。当这种字面量出现在match的**分支模式pattern**中时便构成一个「类型化小数模式」typed fractional pattern。本文关联文档 issue_10134_typed_frac_patterns.md 正是针对这一语法特性的快照测试其描述为Explicitly typed F32 and F64 fractional literals are valid patterns显式类型化的 F32 与 F64 小数字面量是合法的模式。关联的兄弟快照仓库中还有一个同 issue 的配套快照 issue_10134_typed_frac_pattern_suffix_mismatch.md它验证了反向情形当模式后缀类型与match上下文类型不一致时编译器会报出类型不匹配错误。两篇快照互为镜像共同构成对该特性的完整验证。二、快照测试文档结构速览roc 的快照测试文件采用分节结构每一节对应编译器流水线的一个阶段。以本文关联文档为例各节的含义如下小节阶段说明# META元信息description一句话描述被测特性typesnippet表示这是代码片段型快照# SOURCE输入被测的 roc 源码片段# EXPECTED期望结果NIL表示无错误、编译通过# PROBLEMS问题报告NIL表示没有产生任何诊断# TOKENS词法分析输入被切分出的 token 序列# PARSE语法分析解析出的抽象语法树AST# FORMATTED格式化NO CHANGE表示源码已符合 roc fmt 的输出格式# CANONICALIZE规范化规范化后的中间表示canonical IR# TYPES类型检查推断出的类型快照测试基础设施的说明可参见 snapshot_tool 源码其模块注释明确指出快照捕获了编译器在「tokenization、parsing、canonicalization、type checking」等每个编译阶段的行为用于确保编译器行为符合预期。三、被测代码两个带类型后缀的小数模式关联文档中的# SOURCE是完整的可运行 roc 代码classify32 : F32 - I64 classify32 |n| match n { 1.5.F32 1 _ 0 } classify64 : F64 - I64 classify64 |n| match n { 1.5.F64 1 _ 0 }要点拆解classify32 : F32 - I64与classify64 : F64 - I64是类型注解classify32接受一个F32返回I64classify64接受F64返回I64。两个函数体都是|n| match n { ... }即把参数n与分支模式进行匹配。分支1.5.F32 1的含义是当n精确等于字面量1.5且该字面量按F32类型解释时返回1。兜底分支_ 0覆盖其余所有情况。这段代码的# EXPECTED为NIL、# PROBLEMS为NIL# FORMATTED为NO CHANGE说明该源码是合法、可编译、且已符合标准格式化风格的代码。四、词法阶段Float与NoSpaceDotUpperIdent两个 token 的配合# TOKENS节展示了词法分析tokenization结果以classify32为例LowerIdent,OpColon,UpperIdent,OpArrow,UpperIdent, LowerIdent,OpAssign,OpBar,LowerIdent,OpBar,KwMatch,LowerIdent,OpenCurly, Float,NoSpaceDotUpperIdent,OpFatArrow,Int, Underscore,OpFatArrow,Int, CloseCurly, EndOfFile,值得注意的关键点数字1.5被整体词法化为一个Floattoken小数点与小数部分都属于数字字面量不会被拆分。紧随其后的.F32被词法化为NoSpaceDotUpperIdent——一个紧贴无空格的点号加大写标识符token。这个 token 的存在正是「类型后缀」在词法层的标志它区分了「小数后紧跟类型后缀」与「小数后跟随其他语法元素」两种情形。对应OpFatArrow整数1、0对应Int通配符_对应Underscore每个表达式以EndOfFile收尾。两个函数体的 token 序列完全对称仅后缀类型标识不同.F32与.F64都词法化为NoSpaceDotUpperIdent类型名本身由上层解析阶段解析。五、语法阶段p-typed-frac模式节点的生成# PARSE节展示了解析后的 AST其中模式分支被解析为(branch (p-typed-frac (raw 1.5) (type F32)) (e-int (raw 1)))即解析器为1.5.F32 1生成一个p-typed-frac模式节点携带两个信息小数文本1.5与类型标识F32。classify64对应地生成(p-typed-frac (raw 1.5) (type F64))。在源码层面解析器的这段逻辑位于 src/parse/Parser.zig 的模式前缀处理分支pattern_prefix状态机约第 6401–6440 行。其处理顺序可以归纳为遇到Floattoken 后先调用NumericLiteral.deprecatedSuffixFromSource检查是否存在已废弃的数字后缀写法如f32、f64这类旧式后缀若存在会同时产生一个废弃后缀诊断deprecated number suffix diagnostic。若旧式废弃后缀解析出了类型标识则直接构造typed_frac模式。否则检查下一个 token 是否为NoSpaceDotUpperIdent若是则把紧跟的类型标识解析出来构造typed_frac模式节点src/parse/AST.zig 中Pattern.Tag.typed_frac结构体约第 1362–1367 行字段包括number_tok、type_ident、literal与region。若既无旧式后缀、也没有紧跟的类型标识则退化为普通的frac无类型后缀的小数模式。同理在表达式一侧也存在对应的typed_frac表达式节点e-typed-frac见 src/parse/AST.zig 约第 2840–2855 行的Expr.Tag.typed_frac说明该语法在模式与表达式两处都受支持。六、规范化阶段小数模式被降级为「小十进制」模式# CANONICALIZE节展示了规范化后的中间表示canonical IR。以classify32为例(branch (patterns (pattern (degenerate false) (p-small-dec))) (value (e-num (value 1))))关键观察类型化小数模式在规范化阶段被归一化为p-small-dec小十进制数模式degenerate false表示这是一个正常的、非退化的模式degenerate true通常表示无法匹配任何值的模式。分支值1被表示为e-num数字字面量表达式。整个函数体被表示为d-let加 lambdae-lambda加e-match的结构并携带函数类型注解(ty-fn ... (ty-lookup (name F32) (builtin)) (ty-lookup (name I64) (builtin)))其中(builtin)标明F32、I64都是内建类型。也就是说模式中显式的.F32/.F64后缀在规范化后被吸收进模式本身成为对该小数模式匹配值的类型约束规范化的p-small-dec不再区分 F32 还是 F64具体类型信息已经转移到类型检查阶段发挥作用。七、类型检查阶段后缀约束的最终体现# TYPES节给出了类型推断结果(inferred-types (defs (patt (type F32 - I64)) (patt (type F64 - I64))) (expressions (expr (type F32 - I64)) (expr (type F64 - I64))))classify32与classify64被分别推断为F32 - I64与F64 - I64与函数顶部的类型注解完全一致证明类型化小数模式既参与了模式匹配又与其后缀类型保持一致。类型约束的「威力」在配套快照 issue_10134_typed_frac_pattern_suffix_mismatch.md 中体现得淋漓尽致。该快照的源码为classify : F64 - I64 classify |n| match n { 1.5.F32 1 _ 0 }这里match的对象n类型是F64而第一个分支模式1.5.F32的后缀类型是F32。该快照的# EXPECTED为TYPE MISMATCH# PROBLEMS节给出完整错误报告其核心内容是错误标题Type Mismatch类型不匹配定位到classify函数体内的match第 2 行第 16 列起。The first pattern is trying to match:F32第一个模式试图匹配的类型是F32。But the expression between thematchparenthesis has the type:F64而match括号之间的表达式类型是F64。结论These can never match!二者永远无法匹配并提示 Either the pattern or expression has a problem.这证明显式类型后缀对模式构成独立约束与 match 上下文的类型必须一致。模式后缀类型并非「提示」或「风格建议」而是一条强制的类型检查规则。八、实战要点与用法总结综合两篇快照与源码可以总结出以下可直接上手的规则合法的写法在match分支模式中书写小数时可紧跟无空格的点号大写类型后缀如1.5.F32、1.5.F64、1.5.Dec。后缀类型须与match对象的类型一致。类型约束是双向一致的后缀类型既约束模式本身也必须与match上下文被匹配表达式的类型兼容否则编译失败并给出TYPE MISMATCH诊断。词法层面1.5是单一Floattoken.F32是NoSpaceDotUpperIdenttoken二者之间不能有空格。与旧式后缀的关系解析器会先检测旧式已废弃数字后缀如f32/f64风格并给出废弃诊断推荐使用点号大写类型后缀的现代写法。空匹配兜底务必提供_ ...之类的兜底分支否则对于非匹配值将落入未覆盖分支roc 要求 match 穷尽。如何在本仓库中验证本仓库的快照测试文件就是最直接的验证素材阅读 issue_10134_typed_frac_patterns.md 观察通过案例的完整编译流水线阅读 issue_10134_typed_frac_pattern_suffix_mismatch.md 观察失败案例的类型错误报告。若需在本地运行快照测试可通过本仓库的快照测试工具src/snapshot_tool/main.zig结合构建脚本执行快照文件所在目录 test/snapshots/issue 还包含大量其他 issue 回归用例可作为同类语法特性的对比参考。九、总结类型化小数模式typed fractional pattern是 roc 语言中「字面量类型注解」与「模式匹配」两大特性的交汇点。通过 issue_10134_typed_frac_patterns.md 这一快照测试我们可以完整观察到它从词法FloatNoSpaceDotUpperIdent、语法p-typed-frac、规范化p-small-dec到类型检查F32 - I64/F64 - I64的全链路行为而它的反向用例则清晰展示了后缀类型约束被违反时的报错形态。对 roc 使用者而言这是写出类型安全、可穷尽匹配代码的基础知识对编译器学习者而言这又是一份极佳的「单一特性贯穿多阶段流水线」的活教材。【免费下载链接】rocA fast, friendly, functional language.项目地址: https://gitcode.com/GitHub_Trending/ro/roc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表