frontend/itl_expr API
frontend/itl_expr 解析 ITF1788 套件(IEEE 1788-2015 区间标准的测试数据)中 ITL 格式的区间测试用例,并针对 ball_float 执行它们。它是一个纯库:命令行运行器是 cli/itl_expr_cli。教程逐步介绍工作流程,设计页面给出通过规则。
在 moon.pkg 中导入该包:
import {
"Luna-Flow/floating/frontend/itl_expr",
}
解析
parse_itl
parse_itl(source) 将 ITL 文本解析为用例。
pub fn parse_itl(String) -> Result[Array[ItlCase], Array[String]]
文本被逐行读取,每行都会被修剪:
- 以
//开头的行和空行被跳过;以/*开头的行开始一个块注释,该注释结束于其后第一个包含*/的行(或同一行); testcase NAME …开始一个新块;NAME是testcase之后的单词,其后必须跟一个空格,否则记录诊断"invalid testcase declaration";语句计数器从 0 重新开始;- 等于
}的行被跳过; - 其他每一行都(以一个空格)追加到当前语句中,以
;结尾的行使语句完成。
一个已完成的语句 left = expected 在第一个 = 处切分。左侧在方括号之外按空格和制表符切分为单词;第一个单词是运算,其余为操作数。用例 id 为 NAME:k,其中 k 从 1 开始统计块内的语句(第一个 testcase 之前的语句使用名称 anonymous)。不含 = 或不含运算的语句分别产生诊断 "NAME:k: missing '='" 或 "NAME:k: missing operation";最后一个 ; 之后剩余的文本产生 "unterminated ITL statement"。没有诊断时结果为 Ok(cases),否则为 Err(diagnostics)。
ItlCase
ItlCase 是一条已解析的语句。
pub struct ItlCase {
// private fields
} derive(Eq, @debug.Debug)
ItlCase::id, operation, operands, expected
这些方法返回 id NAME:k、运算单词、操作数单词的副本,以及期望文本(已修剪,包含任何装饰后缀)。
pub fn ItlCase::id(Self) -> String
pub fn ItlCase::operation(Self) -> String
pub fn ItlCase::operands(Self) -> Array[String]
pub fn ItlCase::expected(Self) -> String
执行
execute_case
execute_case(case, precision?) 执行一个用例并返回其结果。
pub fn execute_case(ItlCase, precision? : Int) -> ItlResult
precision(默认 53)是读取端点时使用的二进制位精度。无论 precision 为何,区间结果都用 @ball_float.BallContext::binary64() 舍入,因此对于 ITF1788 数据,默认值才是有意义的取值。
操作数和期望值按如下方式读取。区间字面量为 [lo,hi]、[empty]、[entire] 或 [nai],后面可选地跟 _dec,其中 dec 为 com、dac、def、trv、ill 之一(默认 com)。端点为可带符号的 inf/infinity、十六进制浮点数 0x…p…,或十进制文本。十进制和十六进制端点以 precision 位按就近舍入(偶数优先)舍入。
用例根据其运算和期望值进行分派:
| 用例 | 运算 | 预期 | 比较 |
|---|---|---|---|
| 布尔 | isEmpty, isEntire, isNaI, isCommonInterval, isSingleton, equal, subset, interior, disjoint, precedes, strictPrecedes, less, strictLess, isMember | true 或 false | 布尔值相等 |
| 重叠 | overlap | 一个重叠状态名(before、meets、overlaps、starts、containedBy、finishes、equals、after、metBy、overlappedBy、startedBy、contains、finishedBy、bothEmpty、firstEmpty、secondEmpty、undefined) | 名称相等 |
| 数值 | inf, sup, mid, rad, wid, mag, mig | 一个端点 | 数值相等 |
| 一元 | pos, neg, abs, recip, sqr, sqrt, exp, exp2, exp10, log, log2, log10, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh | 区间 | 集合相等 |
| 三元 | fma | 区间 | 集合相等 |
| 整数幂 | pown(第二个操作数为整数) | 区间 | 集合相等 |
| 二元 | add, sub, mul, div, pow, atan2, min, max, intersection, convexHull, cancelPlus, cancelMinus | 区间 | 集合相等 |
“集合相等”的含义是:两者都是 NaI,或都为空,或下端点相等且上端点相等(按数值比较,因此 )。当期望文本包含 _ 时,装饰也必须相等。只要期望文本是 true 或 false,就选择布尔分派。
处置结果:
- 用例已运行时为
Executable;passed()给出结果; - 以下情况为
Unsupported(reason):未知运算;二元分派的用例其期望值不是区间(例如后面跟有signal注记的期望值);二元分派的用例其操作数不是两个;或二元布尔谓词的第二个操作数缺失或无法读取; - 以下情况为
Diagnostic(reason):布尔用例的第一个操作数无法读取;重叠、数值、一元、三元或整数幂分派中的某个操作数或期望值无法读取;或二元分派的某个操作数不是区间字面量。
execute_case 不会因用例内容而中止。
summarize_results
summarize_results(results) 对一组结果进行计数。
pub fn summarize_results(Array[ItlResult]) -> RunSummary
total_cases 是列表的长度。
结果
ItlDisposition
ItlDisposition 说明一个用例是否被执行。
pub(all) enum ItlDisposition {
Executable
Unsupported(String)
Diagnostic(String)
}
ItlResult
ItlResult 是一个用例的结果。
pub struct ItlResult {
// private fields
}
ItlResult::id, disposition, passed, message
这些方法返回用例 id、处置结果、该用例是否通过,以及一条消息:成功时为空,不匹配时为 "expected E, got A"(区间由 BallFloatDecorated::to_string 打印),其他情况下为简短的原因或出错的文本。
pub fn ItlResult::id(Self) -> String
pub fn ItlResult::disposition(Self) -> ItlDisposition
pub fn ItlResult::passed(Self) -> Bool
pub fn ItlResult::message(Self) -> String
RunSummary
RunSummary 汇总一组结果。
pub struct RunSummary {
// private fields
}
RunSummary 计数器与结果
这些方法返回各项计数、结果的副本以及总体判定。
pub fn RunSummary::total_cases(Self) -> Int
pub fn RunSummary::executable_cases(Self) -> Int
pub fn RunSummary::passed_cases(Self) -> Int
pub fn RunSummary::failed_cases(Self) -> Int
pub fn RunSummary::unsupported_cases(Self) -> Int
pub fn RunSummary::diagnostic_cases(Self) -> Int
pub fn RunSummary::results(Self) -> Array[ItlResult]
pub fn RunSummary::success(Self) -> Bool
且 。当没有可执行用例失败并且没有诊断用例时,success() 为真;不受支持的用例不影响它。
///|
test "itl summary" {
let source =
#|testcase s {
#| sub [1.0,2.0] [3.0,4.0] = [-3.0,-1.0];
#| sqr [-2.0,1.0] = [0.0,4.0];
#| mid [1.0,2.0] = 1.5;
#| isEmpty [empty] = true;
#|}
let summary = @itl_expr.summarize_results(
@itl_expr.parse_itl(source).unwrap().map(c => @itl_expr.execute_case(c)),
)
inspect(summary.total_cases(), content="4")
inspect(summary.passed_cases(), content="4")
}
trait 实现
ItlCase::equal, ItlCase::not_equal, ItlCase::to_repr
这些方法比较两个用例的所有字段,并为 Debug 渲染一个用例。新代码中请使用 ==、!= 和 debug_inspect。
pub fn ItlCase::equal(Self, Self) -> Bool
pub fn ItlCase::not_equal(Self, Self) -> Bool
pub fn ItlCase::to_repr(Self) -> @debug.Repr
完整公共接口
此快照是该包生成的 pkg.generated.mbti。当正文与接口不一致时,以接口为准。
// Generated using `moon info`, DON'T EDIT IT
package "Luna-Flow/floating/frontend/itl_expr"
import {
"moonbitlang/core/debug",
}
// Values
pub fn execute_case(ItlCase, precision? : Int) -> ItlResult
pub fn parse_itl(String) -> Result[Array[ItlCase], Array[String]]
pub fn summarize_results(Array[ItlResult]) -> RunSummary
// Errors
// Types and methods
pub struct ItlCase {
// private fields
} derive(Eq, @debug.Debug)
pub fn ItlCase::equal(Self, Self) -> Bool
pub fn ItlCase::expected(Self) -> String
pub fn ItlCase::id(Self) -> String
pub fn ItlCase::not_equal(Self, Self) -> Bool
pub fn ItlCase::operands(Self) -> Array[String]
pub fn ItlCase::operation(Self) -> String
pub fn ItlCase::to_repr(Self) -> @debug.Repr
pub(all) enum ItlDisposition {
Executable
Unsupported(String)
Diagnostic(String)
}
pub struct ItlResult {
// private fields
}
pub fn ItlResult::disposition(Self) -> ItlDisposition
pub fn ItlResult::id(Self) -> String
pub fn ItlResult::message(Self) -> String
pub fn ItlResult::passed(Self) -> Bool
pub struct RunSummary {
// private fields
}
pub fn RunSummary::diagnostic_cases(Self) -> Int
pub fn RunSummary::executable_cases(Self) -> Int
pub fn RunSummary::failed_cases(Self) -> Int
pub fn RunSummary::passed_cases(Self) -> Int
pub fn RunSummary::results(Self) -> Array[ItlResult]
pub fn RunSummary::success(Self) -> Bool
pub fn RunSummary::total_cases(Self) -> Int
pub fn RunSummary::unsupported_cases(Self) -> Int
// Type aliases
// Traits