internal/conformance API

internal/conformance は適合性フロントエンドが共有する結果モデルです。ソース位置、処置(disposition)付きのケースごとの結果、固定された集計規則に基づく実行サマリ、決定的なシャード選択を提供します。frontend/gda_expr、frontend/itl_expr、frontend/mpfr_expr、frontend/testfloat_expr および internal/runner_cli はこれを基盤とし、その型をそれぞれ独自の公開型でラップしています。これは内部パッケージです。Luna-Flow/floating モジュール外のコードからはインポートできず、インターフェースは予告なく変更される可能性があります。そのため、このページの例はコンパイルされません。チュートリアルと設計ページも参照してください。

インポート(モジュール内部からのみ):

import {
  "Luna-Flow/floating/internal/conformance",
}

ソース位置

SourceLocation

SourceLocation は名前付きソース内の位置です。

pub struct SourceLocation {
  // private fields
} derive(Eq, @debug.Debug)

SourceLocation::new

SourceLocation::new(source, line, column?) は位置を作成します。

pub fn SourceLocation::new(String, Int, column? : Int) -> Self

column の既定値は 1 です。行と列は少なくとも 1 になるよう切り上げられるため、位置は常に実在する文字位置を指します。

SourceLocation::source, SourceLocation::line, SourceLocation::column

これらのアクセサは各構成要素を返します。

pub fn SourceLocation::source(Self) -> String
pub fn SourceLocation::line(Self) -> Int
pub fn SourceLocation::column(Self) -> Int
///|
test "locations are one-based" {
  let location = @conformance.SourceLocation::new("a.txt", 0, column=-3)
  inspect(location.line(), content="1")
  inspect(location.column(), content="1")
}

ケースの結果

CaseDisposition

CaseDisposition は選択されたケースを分類します。

pub(all) enum CaseDisposition {
  Executable
  Diagnostic(String)
  Legacy(String)
  Unsupported(String)
} derive(Eq, @debug.Debug)
  • Executable:ケースは実行された。その passed フラグが意味を持つ。
  • Diagnostic(reason):ケースがこの種類のテストとして有効でない(例:プレースホルダ行)。
  • Legacy(reason):ケースがコーパス形式の旧バージョンに属する。
  • Unsupported(reason):ケースは有効だが、実装がその機能を提供していない。

CaseResult

CaseResult は 1 つのケースの結果です。

pub struct CaseResult {
  // private fields
} derive(Eq, @debug.Debug)

CaseResult::new, CaseResult::executable

CaseResult::new(id, disposition, passed, message?) は結果を構築します。CaseResult::executable(id, passed, message?) は Executable を指定した new です。

pub fn CaseResult::new(String, CaseDisposition, Bool, message? : String) -> Self
pub fn CaseResult::executable(String, Bool, message? : String) -> Self

message の既定値は "" です。disposition と passed の間の整合性は検査されません。サマリは実行可能な結果についてのみ passed を読みます。

CaseResult::id, disposition, passed, message

これらのアクセサは格納されたフィールドを返します。

pub fn CaseResult::id(Self) -> String
pub fn CaseResult::disposition(Self) -> CaseDisposition
pub fn CaseResult::passed(Self) -> Bool
pub fn CaseResult::message(Self) -> String

シャーディング

ShardSpec

ShardSpec は検証済みの組(シャード数、シャード番号)です。

pub struct ShardSpec {
  // private fields
} derive(Eq, @debug.Debug)

ShardSpec::try_new, ShardSpec::new

ShardSpec::try_new(count, index) は検証してシャードを構築します。ShardSpec::new は Err を返す代わりに同じメッセージで中断(abort)します。

pub fn ShardSpec::try_new(Int, Int) -> Result[Self, String]
pub fn ShardSpec::new(Int, Int) -> Self

エラー:count <= 0 のとき "shard count must be positive"、0 <= index < count でないとき "shard index must be within shard count"。

ShardSpec::count, ShardSpec::index

これらのアクセサはシャード数 nn と番号 ii を返します。

pub fn ShardSpec::count(Self) -> Int
pub fn ShardSpec::index(Self) -> Int

ShardSpec::selects

shard.selects(k) は、序数 k のケースがこのシャードに属するとき、すなわち k mod n=ik \bmod n = i のときに真となります。

pub fn ShardSpec::selects(Self, Int) -> Bool

序数は非負であることが想定されています(MoonBit の % は被除数の符号を保持します)。

///|
test "round-robin selection" {
  let shard = @conformance.ShardSpec::new(3, 1)
  let picked = [0, 1, 2, 3, 4, 5, 6].filter(k => shard.selects(k))
  debug_inspect(picked, content="[1, 4]")
  inspect(@conformance.ShardSpec::try_new(0, 0) is Err(_), content="true")
}

実行サマリ

RunSummary

RunSummary は 1 回の実行またはシャードの結果を集計します。

pub struct RunSummary {
  // private fields
} derive(Eq, @debug.Debug)

RunSummary::from_results

RunSummary::from_results(total, results) は results を集計し、total をシャード選択前のケース数として記録します。

pub fn RunSummary::from_results(Int, Array[CaseResult]) -> Self

各結果は一度だけ数えられます。Executable の結果は passed() に従って成功または失敗として、それ以外の結果はスキップとして、かつ各処置のカウンタに数えられます。結果はコピーされます。

RunSummary::merge

RunSummary::merge(parts) はシャードのサマリを結合します。

pub fn RunSummary::merge(Array[Self]) -> Self

すべてのカウンタは合計されますが、total_cases だけは例外で、各部分の最大値になります。結果は parts の順に連結されます。空配列は空のサマリを与えます。

カウンタ、results と success

これらのアクセサはカウンタ、結果のコピー、判定を返します。

pub fn RunSummary::total_cases(Self) -> Int
pub fn RunSummary::selected_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::skipped_cases(Self) -> Int
pub fn RunSummary::diagnostic_cases(Self) -> Int
pub fn RunSummary::legacy_cases(Self) -> Int
pub fn RunSummary::unsupported_cases(Self) -> Int
pub fn RunSummary::results(Self) -> Array[CaseResult]
pub fn RunSummary::success(Self) -> Bool

selected_cases は結果の個数です。次の恒等式

selected=executable+skipped,executable=passed+failed,skipped=diagnostic+legacy+unsupported\begin{aligned} \text{selected} &= \text{executable} + \text{skipped}, \\ \text{executable} &= \text{passed} + \text{failed}, \\ \text{skipped} &= \text{diagnostic} + \text{legacy} + \text{unsupported} \end{aligned}

は from_results または merge で構築されたすべてのサマリで成り立ちます。success() は failed_cases() == 0 です。スキップされたケースがこれを偽にすることはありません。より厳格な判定を必要とするフロントエンド(itl_expr は診断でも失敗とします)は独自の規則を追加します。

///|
test "summary counting" {
  let summary = @conformance.RunSummary::from_results(10, [
    @conformance.CaseResult::executable("a", true),
    @conformance.CaseResult::executable("b", false, message="mismatch"),
    @conformance.CaseResult::new("c", @conformance.Unsupported("op"), false),
  ])
  inspect(summary.total_cases(), content="10")
  inspect(summary.selected_cases(), content="3")
  inspect(summary.skipped_cases(), content="1")
  inspect(summary.success(), content="false")
}

トレイト実装

等価性と Debug

5 つの型はすべて Eq と Debug を derive しています。これらの昇格メソッドはすべてのフィールドを比較し、値を表示します。新しいコードでは ==、!=、debug_inspect を使用してください。

pub fn SourceLocation::equal(Self, Self) -> Bool
pub fn SourceLocation::not_equal(Self, Self) -> Bool
pub fn SourceLocation::to_repr(Self) -> @debug.Repr
pub fn CaseDisposition::equal(Self, Self) -> Bool
pub fn CaseDisposition::not_equal(Self, Self) -> Bool
pub fn CaseDisposition::to_repr(Self) -> @debug.Repr
pub fn CaseResult::equal(Self, Self) -> Bool
pub fn CaseResult::not_equal(Self, Self) -> Bool
pub fn CaseResult::to_repr(Self) -> @debug.Repr
pub fn ShardSpec::equal(Self, Self) -> Bool
pub fn ShardSpec::not_equal(Self, Self) -> Bool
pub fn ShardSpec::to_repr(Self) -> @debug.Repr
pub fn RunSummary::equal(Self, Self) -> Bool
pub fn RunSummary::not_equal(Self, Self) -> Bool
pub fn RunSummary::to_repr(Self) -> @debug.Repr

公開インターフェース全体

このスナップショットは、パッケージの生成された pkg.generated.mbti です。説明文とインターフェースが食い違う場合は、こちらが正となります。

// Generated using `moon info`, DON'T EDIT IT
package "Luna-Flow/floating/internal/conformance"

import {
  "moonbitlang/core/debug",
}

// Values

// Errors

// Types and methods
pub(all) enum CaseDisposition {
  Executable
  Diagnostic(String)
  Legacy(String)
  Unsupported(String)
} derive(Eq, @debug.Debug)
pub fn CaseDisposition::equal(Self, Self) -> Bool
pub fn CaseDisposition::not_equal(Self, Self) -> Bool
pub fn CaseDisposition::to_repr(Self) -> @debug.Repr

pub struct CaseResult {
  // private fields
} derive(Eq, @debug.Debug)
pub fn CaseResult::disposition(Self) -> CaseDisposition
pub fn CaseResult::equal(Self, Self) -> Bool
pub fn CaseResult::executable(String, Bool, message? : String) -> Self
pub fn CaseResult::id(Self) -> String
pub fn CaseResult::message(Self) -> String
pub fn CaseResult::new(String, CaseDisposition, Bool, message? : String) -> Self
pub fn CaseResult::not_equal(Self, Self) -> Bool
pub fn CaseResult::passed(Self) -> Bool
pub fn CaseResult::to_repr(Self) -> @debug.Repr

pub struct RunSummary {
  // private fields
} derive(Eq, @debug.Debug)
pub fn RunSummary::diagnostic_cases(Self) -> Int
pub fn RunSummary::equal(Self, Self) -> Bool
pub fn RunSummary::executable_cases(Self) -> Int
pub fn RunSummary::failed_cases(Self) -> Int
pub fn RunSummary::from_results(Int, Array[CaseResult]) -> Self
pub fn RunSummary::legacy_cases(Self) -> Int
pub fn RunSummary::merge(Array[Self]) -> Self
pub fn RunSummary::not_equal(Self, Self) -> Bool
pub fn RunSummary::passed_cases(Self) -> Int
pub fn RunSummary::results(Self) -> Array[CaseResult]
pub fn RunSummary::selected_cases(Self) -> Int
pub fn RunSummary::skipped_cases(Self) -> Int
pub fn RunSummary::success(Self) -> Bool
pub fn RunSummary::to_repr(Self) -> @debug.Repr
pub fn RunSummary::total_cases(Self) -> Int
pub fn RunSummary::unsupported_cases(Self) -> Int

pub struct ShardSpec {
  // private fields
} derive(Eq, @debug.Debug)
pub fn ShardSpec::count(Self) -> Int
pub fn ShardSpec::equal(Self, Self) -> Bool
pub fn ShardSpec::index(Self) -> Int
pub fn ShardSpec::new(Int, Int) -> Self
pub fn ShardSpec::not_equal(Self, Self) -> Bool
pub fn ShardSpec::selects(Self, Int) -> Bool
pub fn ShardSpec::to_repr(Self) -> @debug.Repr
pub fn ShardSpec::try_new(Int, Int) -> Result[Self, String]

pub struct SourceLocation {
  // private fields
} derive(Eq, @debug.Debug)
pub fn SourceLocation::column(Self) -> Int
pub fn SourceLocation::equal(Self, Self) -> Bool
pub fn SourceLocation::line(Self) -> Int
pub fn SourceLocation::new(String, Int, column? : Int) -> Self
pub fn SourceLocation::not_equal(Self, Self) -> Bool
pub fn SourceLocation::source(Self) -> String
pub fn SourceLocation::to_repr(Self) -> @debug.Repr

// Type aliases

// Traits