资讯详情

资讯详情

Roc 语言数值字符串解析:从 `from_str` 快照测试看 F32、I64、U128、I128 的边界行为

Roc 语言数值字符串解析从from_str快照测试看 F32、I64、U128、I128 的边界行为【免费下载链接】rocA fast, friendly, functional language.项目地址: https://gitcode.com/GitHub_Trending/ro/roc本篇文章以 Roc 编译器仓库中的 REPL 快照测试 test/snapshots/repl/num_from_str_various_types.md 为骨架系统讲解 Roc 语言中Str - Try(Num, [BadNumStr, ..])这一数值解析家族的核心行为支持的类型集合、合法/非法输入的分界、有符号与无符号整型的边界值语义以及 REPL 中通过from_str得到的Ok/Err(BadNumStr)输出格式。读完本文你将能准确预判任意字符串在各数值类型上的解析结果并理解其底层实现与 JSON 解码等内置库之间的调用关系。快照测试是什么一个可执行、可回归验证的 REPL 会话该文件属于 Roc 编译器仓库的快照测试snapshot test体系。它的格式分为三段META声明测试的description本次为 from_str for various numeric types (F32, I64, U128, I128)与typerepl即这是一个 REPL 会话快照SOURCE以»开头的若干行是逐条输入 REPL 的 Roc 表达式OUTPUT每条表达式对应的实际输出用---分隔# PROBLEMS为NIL表示该会话没有编译诊断信息。这种快照测试的价值在于REPL 的每一行输出都会被严格比对任何解析行为的变化如边界值判定、错误类型改名都会导致测试失败从而保证from_str的行为在编译器演进过程中保持稳定可回归。支持from_str的数值类型全集在 src/build/roc/Builtin.roc 中可以看到编译器内置了完整的一套字符串解析声明全部遵循统一的签名u8_from_str : Str - Try(U8, [BadNumStr, ..]) i8_from_str : Str - Try(I8, [BadNumStr, ..]) u16_from_str : Str - Try(U16, [BadNumStr, ..]) i16_from_str : Str - Try(I16, [BadNumStr, ..]) u32_from_str : Str - Try(U32, [BadNumStr, ..]) i32_from_str : Str - Try(I32, [BadNumStr, ..]) u64_from_str : Str - Try(U64, [BadNumStr, ..]) i64_from_str : Str - Try(I64, [BadNumStr, ..]) u128_from_str : Str - Try(U128, [BadNumStr, ..]) i128_from_str : Str - Try(I128, [BadNumStr, ..]) dec_from_str : Str - Try(Dec, [BadNumStr, ..]) f32_from_str : Str - Try(F32, [BadNumStr, ..]) f64_from_str : Str - Try(F64, [BadNumStr, ..])这些底层函数进一步被封装为各类型上的公开方法如U8.from_str、I64.from_str、F32.from_str等。以 Builtin.roc 中的几个为例公开方法会额外处理Numeral数字字面量输入from_numeral_with先把字面量规整成字符串再调用对应的from_str解析见 Builtin.roc解析失败时统一返回Err(InvalidNumeral(invalid numeric literal))。而本快照测试聚焦的是直接传入字符串文本的场景。逐条解读快照中的九组 REPL 输入以下对照 num_from_str_various_types.md 的 SOURCE/OUTPUT逐条分析其语义。1. 浮点解析F32.from_str» F32.from_str(3.14) # Ok(3.14) » F32.from_str(invalid) # Err(BadNumStr)3.14是合法的小数字面量文本解析成功REPL 打印Ok(3.14)Ok携带解析得到的 F32 值invalid无法被识别为数值返回Err(BadNumStr)。注意错误标签是BadNumStr而非自定义错误——这正对应声明中Try(F32, [BadNumStr, ..])的可扩展标签联合BadNumStr是必选项调用方还可以追加自己的错误标签。2. 有符号 64 位整型边界I64.from_str» I64.from_str(-9223372036854775808) # Ok(-9223372036854775808) » I64.from_str(9223372036854775807) # Ok(9223372036854775807) » I64.from_str(9223372036854775808) # Err(BadNumStr)I64 的取值范围是-2^63到2^63 - 1即-9223372036854775808到9223372036854775807最小值的文本可以精确解析最大值的文本同样可以精确解析超出最大值 1 的9223372036854775808则触发溢出检测返回Err(BadNumStr)。这三条用例精确定义了 I64 解析的边界闭区间包含两端越界即报错而不是回绕wrap-around。这一点对金融计算、ID 解析等对数值精度敏感的场景至关重要。3. 无符号 128 位整型U128.from_str» U128.from_str(0) # Ok(0) » U128.from_str(12345678901234567890) # Ok(12345678901234567890)U128 是 Roc 中可表示的最大无符号整型范围 0 到2^128 - 1。0与 20 位的12345678901234567890约 1.23e19已远超 U64 上限都能无损解析。需要留意U128 不接受负号若传入-1会返回Err(BadNumStr)这一点可参见 Builtin.roc 中U128.from_str的 expect 用例。4. 有符号 128 位整型I128.from_str» I128.from_str(-12345678901234567890) # Ok(-12345678901234567890) » I128.from_str(12345678901234567890) # Ok(12345678901234567890)同样的 20 位数字在 I128 下带符号与不带符号均可解析说明 I128 覆盖的负区间到正区间足够容纳该量级。I128 的范围是-2^127到2^127 - 1是整型解析的“终极形态”当数值可能超过 64 位时应优先选用U128.from_str/I128.from_str。错误语义BadNumStr与Try标签联合所有*_from_str的返回类型都是Try(Num, [BadNumStr, ..])即Result(Num, [BadNumStr, ..])的别名。这意味着成功时携带解析后的数值Ok(3.14)、Ok(0)等失败时携带BadNumStr标签表示“字符串不是合法的数值文本”标签联合末尾的..是开放标签允许调用方在错误分支中补充自定义错误类型。从实现侧看Zig 层的解析函数如 src/builtins/dec.zig 中的RocDec.fromStr把所有解析失败统一映射为null注释明确写道“All parse failures currently map to null; the Roc wrapper reports that as BadNumStr.”所有解析失败目前都映射为 nullRoc 包装层将其报告为 BadNumStr。因此快照中看到的Err(BadNumStr)是 Roc 层对底层失败的一体化表达——字符串格式非法与数值越界共享同一个错误标签调用方无法仅凭BadNumStr区分二者如需区分须在调用前自行校验字符串形态。从源码看实现原理声明与数字字面量路径from_str一族在 Builtin.roc 中集中声明。除了直接解析字符串外同一套解析器还被数字字面量转换复用from_numeral_with将Num.Numeral内部的 base-256 位表示digits_before_pt/digits_after_pt通过base256_to_decimal_digits转成十进制字符串后送入from_str见 Builtin.roc保证“字面量转数值”与“字符串解析”走同一条校验管线。整型解析的两级调用以I64为例公开方法与底层函数的分工是I64.from_str : Str - Try(I64, [BadNumStr, ..]) # 内部委托给 i64_from_str后者再参与 from_numeral_with、int_from_digits 等 i64_from_str : Str - Try(I64, [BadNumStr, ..])源码中的声明显示i64_from_str等函数与u8_from_int_digits、int_from_digits等辅助函数协作见 Builtin.roc其中int_from_digits系列负责把字节数组形式的数字位组装为字符串后再统一解析从而在整型、Dec、F32/F64 之间复用同一套边界检查。实战延伸from_str在内置库中的典型消费场景from_str并非孤立存在它被 Roc 内置库广泛用于文本与数据格式解析其中最典型的是 JSON 解码。在 Builtin.roc 中可以看到JSON 值的解码逻辑按目标类型分派Input(raw) Json.parse_json_unsigned_int(raw, u8_from_str) Input(raw) Json.parse_json_signed_int(raw, i64_from_str) Input(raw) Json.parse_json_unsigned_int(raw, u128_from_str) Input(raw) Json.parse_json_signed_int(raw, i128_from_str) Input(raw) Json.parse_json_number(raw, f32_from_str) # ... 以及 Dec.from_str / F64.from_str 对应的分支即decode一个数字字段时底层正是把 JSON 中携带的数字文本交给对应的from_str。因此本文快照测试覆盖的“合法文本可解析、越界文本报BadNumStr”语义直接决定了 JSON 解码的成败。对 JSON 对象键名的解析Builtin.roc也复用了同一套*_from_str函数。如何在本地 REPL 验证这些行为快照中的每一行都以»前缀表示 REPL 输入你可以打开 Roc REPL逐条输入» F32.from_str(3.14) » I64.from_str(-9223372036854775808) » U128.from_str(12345678901234567890) » I128.from_str(-12345678901234567890)观察输出是否与快照一致也可自行扩展边界用例如U128.from_str(-1)、I64.from_str(9223372036854775808)来加深对溢出语义的理解。该快照位于 test/snapshots/repl/num_from_str_various_types.md仓库的快照测试体系会通过对比该文件中的 OUTPUT 段来自动回归验证这些行为是理解 Roc 数值解析契约最直接、最权威的参考。小结Roc 的from_str家族覆盖 U8U128、I8I128、Dec、F32、F64 共 13 种数值类型统一返回Try(Num, [BadNumStr, ..])整型解析严格遵循类型边界越界返回Err(BadNumStr)而非回绕I64 的最小值/最大值与超界一例在快照中被精确钉死浮点与整型共用BadNumStr错误标签底层 Zig 实现将一切解析失败映射为 null由 Roc 包装层统一报告同样的解析器被数字字面量转换与 JSON 解码复用理解from_str的行为即理解 Roc 内置库中大量文本数值处理的底层契约。【免费下载链接】rocA fast, friendly, functional language.项目地址: https://gitcode.com/GitHub_Trending/ro/roc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →