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, isMembertrue 或 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,或都为空,或下端点相等且上端点相等(按数值比较,因此 −0=+0-0 = +0)。当期望文本包含 _ 时,装饰也必须相等。只要期望文本是 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

total=executable+unsupported+diagnostic\text{total} = \text{executable} + \text{unsupported} + \text{diagnostic} 且 executable=passed+failed\text{executable} = \text{passed} + \text{failed}。当没有可执行用例失败并且没有诊断用例时,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