prover API 参考
prover 包(Luna-Flow/QED/prover)运行定理脚本。它解析一个脚本或一个脚本文件,按要求安装命题前奏,降级每个目标,用 tactics 包运行各步骤(自行调度 { ... } 分支块),并返回内核定理、结构化失败,或对含 hole 的脚本返回未完成证明报告。它还发布回归语料,把用户手册与测试联系起来。
该包负责编排与报告,不持有任何逻辑权威。prover 设计说明了结果模型,prover 教程演示如何从 MoonBit 运行脚本。
选项
ProverOptions、default_prover_options 与 prover_options
ProverOptions 只有一个开关:运行前是否把命题前奏安装到状态中。default_prover_options() 将其打开;prover_options(b) 显式设置。
pub struct ProverOptions {
auto_install_prelude : Bool
}
pub fn default_prover_options() -> ProverOptions
pub fn prover_options(Bool) -> ProverOptions
没有前奏时,T、F 和目录中的定理不可用,除非状态已经定义了它们。
运行脚本
prove_theorem_script_detailed
prove_theorem_script_detailed(state, src, opts) 运行一个定理脚本,并返回三态结果。
pub fn prove_theorem_script_detailed(@kernel.KernelState, String, ProverOptions) -> ProverRunResult
头部绑定子 (x : A) 成为目标的局部量。步骤按顺序运行;后接分支块的步骤先运行,然后每个块在各自的框架中针对其子目标运行。第一个失败的步骤会终止脚本。hole 使脚本以未完成状态终止。如果所有步骤都成功但仍有剩余目标,结果是带 UnsolvedGoals 的失败。
prove_theorem_script 与 prove_theorem_script_with_diagnostics
这些函数运行一个脚本,返回定理和状态,或将失败或未完成报告作为错误返回。
pub fn prove_theorem_script(@kernel.KernelState, String, ProverOptions) -> Result[(@kernel.KernelState, @kernel.Thm), ProverScriptError]
pub fn prove_theorem_script_with_diagnostics(@kernel.KernelState, String, ProverOptions) -> Result[(@kernel.KernelState, @kernel.Thm), ProverScriptError]
这两个函数目前行为相同;两者都在 ProverScriptError 中携带完整诊断。返回的状态就是证明运行时所在的状态,在被要求时已安装前奏;证明出的定理不会加入其中。
prove_theorem_file_results_detailed
prove_theorem_file_results_detailed(state, src, opts) 运行文件中的每个定理(定理之间以 qed 行分隔),并为每个定理返回一个结果。
pub fn prove_theorem_file_results_detailed(@kernel.KernelState, String, ProverOptions) -> ProverFileRunResult
失败或未完成的定理不会终止整个文件:后面的定理仍会被检查。只有当文件无法解析或前奏无法安装时,整个文件才失败(FileFailed)。
prove_theorem_file_detailed
prove_theorem_file_detailed 运行一个文件,并将其汇总为一个结果:若有失败则取第一个失败,否则若有未完成定理则取第一个未完成的,否则取最后一个成功。
pub fn prove_theorem_file_detailed(@kernel.KernelState, String, ProverOptions) -> ProverRunResult
结果
ProverRunResult
ProverRunResult 是一个脚本的运行结果。
pub enum ProverRunResult {
Proved(ProverSuccess)
Failed(ProverFailure)
Unfinished(ProverUnfinished)
}
ProverSuccess
ProverSuccess 携带定理、脚本名以及证明所在的状态。
pub struct ProverSuccess {
state : @kernel.KernelState
theorem_name : String
thm : @kernel.Thm
}
ProverFailure
ProverFailure 描述脚本在何处、因何失败。
pub struct ProverFailure {
theorem_name : String?
kind : ProverDiagnosticKind
detail : String
raw_offset : Int?
goal_src : String?
goal_span : @parser.SourceSpan?
step_index : Int?
branch_path : Array[Int]
step_span : @parser.SourceSpan?
step_src : String?
current_goal : @tactics.Goal?
local_hyps : Array[ProverLocalHyp]
error : ProverError
}
kind 和 error 说明哪一层失败;detail 渲染该错误。位置字段在源文本中定位失败:解析错误用 raw_offset,降级错误用目标区间,策略错误则用步骤索引、分支路径、步骤区间和步骤文本,并附带该处的目标和局部量。不适用的字段为 None 或空。
ProverUnfinished
ProverUnfinished 报告到达 hole 的脚本。
pub struct ProverUnfinished {
theorem_name : String
detail : String
raw_offset : Int?
goal_src : String?
goal_span : @parser.SourceSpan?
step_index : Int?
branch_path : Array[Int]
step_span : @parser.SourceSpan?
step_src : String?
current_goal : @tactics.Goal
local_hyps : Array[ProverLocalHyp]
hole_name : String?
}
它具有与失败相同的位置字段,还有该 hole 所代表的目标(总是存在)以及 hole 的名字(如果有)。它不是定理。
ProverLocalHyp 与 prover_local_hyp
ProverLocalHyp 是报告中具名的局部假设;prover_local_hyp 构造一个。
pub struct ProverLocalHyp {
name : String
term : @kernel.Term
}
pub fn prover_local_hyp(String, @kernel.Term) -> ProverLocalHyp
prover_unfinished
prover_unfinished 由各字段构造一个 Unfinished 结果,字段顺序为:定理名、目标源文本、目标区间、步骤索引、分支路径、步骤区间、步骤源文本、当前目标、局部量、hole 名、详情和原始偏移。
pub fn prover_unfinished(String, String?, @parser.SourceSpan?, Int?, Array[Int], @parser.SourceSpan?, String?, @tactics.Goal, Array[ProverLocalHyp], String?, String, Int?) -> ProverRunResult
它供需要固定未完成报告的测试和渲染器使用。
ProverError 与 ProverDiagnosticKind
ProverError 包装失败那一层的错误;ProverDiagnosticKind 给出该层的名称。
pub enum ProverError {
Parse(@parser.ParseError)
Bridge(@parser.ParseBridgeError)
Tactic(@tactics.TacticExecError)
Sig(@kernel.SigError)
Logic(@kernel.LogicError)
}
pub enum ProverDiagnosticKind {
Parse
Bridge
Tactic
Sig
Logic
}
ProverScriptError
ProverScriptError 是 prove_theorem_script 的错误一侧。
pub enum ProverScriptError {
Failure(ProverFailure)
Unfinished(ProverUnfinished)
}
ProverFileRunResult、ProverFileReport 与 ProverFileItemResult
文件运行要么整体失败,要么按顺序为每个定理产生一项。
pub enum ProverFileRunResult {
FileChecked(ProverFileReport)
FileFailed(ProverFailure)
}
pub struct ProverFileReport {
state : @kernel.KernelState
items : Array[ProverFileItemResult]
}
pub enum ProverFileItemResult {
ProverItemProved(ProverSuccess)
ProverItemFailed(ProverFailure)
ProverItemUnfinished(ProverUnfinished)
}
test "run scripts" {
let st = @kernel.empty_kernel_state()
let opts = @prover.default_prover_options()
let ok = @prover.prove_theorem_script_detailed(st, "theorem truth_file : ⊢ T := by exact truth", opts)
inspect(ok is @prover.Proved({ theorem_name: "truth_file", .. }), content="true")
// the manual's bad_branch example: a structured failure
let bad = @prover.prove_theorem_script_detailed(
st,
"theorem bad_branch (x : bool) : ⊢ x -> x ∨ x := by\n intro h\n left { exact truth }",
opts,
)
guard bad is @prover.Failed(f) else { fail("expected a failure") }
inspect(f.detail, content="GoalShapeMismatch(exact witness does not directly close current goal)")
assert_eq((f.step_index, f.branch_path, f.step_src), (Some(3), [1], Some("exact truth")))
// a hole is reported, not proved
let unf = @prover.prove_theorem_script_detailed(
st,
"theorem unfinished_branch (x : bool) : ⊢ x -> x ∨ (x ∨ x) := by\n intro h\n right { right { hole h1 } }",
opts,
)
guard unf is @prover.Unfinished(u) else { fail("expected an unfinished proof") }
assert_eq((u.hole_name, u.step_index, u.branch_path), (Some("h1"), Some(4), [1, 1]))
}
test "run a file" {
let src =
#|theorem before_hole : ⊢ T := by exact truth
#|qed
#|
#|theorem unfinished_demo (x : bool) : ⊢ x -> x ∨ (x ∨ x) := by
#| intro h
#| right { right { hole h1 } }
#|qed
#|
#|theorem after_hole : ⊢ T := by exact truth
#|qed
let st = @kernel.empty_kernel_state()
guard @prover.prove_theorem_file_results_detailed(st, src, @prover.default_prover_options())
is @prover.FileChecked(report) else {
fail("expected the file to parse")
}
let kinds = report.items.map(item => match item {
@prover.ProverItemProved(_) => "ok"
@prover.ProverItemFailed(_) => "error"
@prover.ProverItemUnfinished(_) => "unfinished"
})
assert_eq(kinds, ["ok", "unfinished", "ok"])
}
该文件是 examples/multi_with_hole.qed。
回归语料
语料(corpus)是测试运行、文档可引用的脚本的唯一列表。每个用例有标识符、脚本、步骤布局,以及它所展示的能力或失败。
positive_corpus_cases、negative_corpus_cases、unfinished_corpus_cases 与 quantifier_corpus_cases
这些函数返回各类用例。
pub fn positive_corpus_cases() -> Array[PositiveCorpusCase]
pub fn negative_corpus_cases() -> Array[NegativeCorpusCase]
pub fn unfinished_corpus_cases() -> Array[UnfinishedCorpusCase]
pub fn quantifier_corpus_cases() -> Array[QuantifierCorpusCase]
PositiveCorpusCase
正例在声明布尔常量 const_names 之后,必须证明 expected_goal。
pub struct PositiveCorpusCase {
case_id : String
const_names : Array[String]
expected_goal : String
script : String
layout : ScriptLayout
catalog_class : PositiveCatalogClass
capability : PositiveTacticCapability
}
NegativeCorpusCase
反例必须以错误形态 expected_error 失败。这些常量被声明为布尔值、一元或二元布尔函数。
pub struct NegativeCorpusCase {
case_id : String
bool_consts : Array[String]
unary_bool_consts : Array[String]
binary_bool_consts : Array[String]
script : String
layout : ScriptLayout
failure_class : NegativeFailureClass
expected_error : NegativeErrorShape
}
UnfinishedCorpusCase
未完成用例必须在给定的步骤、分支路径和 hole 处停止,并带有给定的详情。
pub struct UnfinishedCorpusCase {
case_id : String
const_names : Array[String]
expected_goal : String
script : String
layout : ScriptLayout
expected_step_index : Int
expected_branch_path : Array[Int]
expected_hole_name : String?
expected_detail : String
}
QuantifierCorpusCase 与 QuantifierSurfaceOutcome
量词用例涵盖绑定子和原始 forall 的表层语法,结果可能是成功、失败或未完成。
pub struct QuantifierCorpusCase {
case_id : String
script : String
layout : ScriptLayout
kind : MappingCaseKind
outcome : QuantifierSurfaceOutcome
capability_label : String
manual_anchor : String
expected_step_index : Int?
expected_branch_path : Array[Int]
expected_hole_name : String?
expected_detail : String?
}
pub enum QuantifierSurfaceOutcome {
QuantifierSuccess
QuantifierFailure
QuantifierUnfinished
}
分类枚举
这些枚举对用例分类;下面的标签函数把它们渲染为测试和文档中使用的稳定字符串。
pub enum ScriptLayout {
InlineSequential
BlockSequential
BranchStructured
}
pub enum PositiveCatalogClass {
LocalFact
DirectClose
ImplicationBacked
ContextDerived
StructuralOnly
}
pub enum PositiveTacticCapability {
IntroExact
Assumption
ExactNamedDirectClose
ExactContextDerived
ApplyLocalImp
ApplyNamedImp
Split
Left
Right
Mixed
}
pub enum NegativeFailureClass {
FailureUnknownName
FailureWrongModeTheoremUsage
FailureGoalShapeMismatch
FailureNonBoolConnector
FailureUnsupportedHonestFailure
FailureShadowingOrScopeDrift
}
pub enum NegativeErrorShape {
ErrorTacticUnknownName
ErrorTacticApplyMismatch
ErrorTacticGoalShapeMismatch
ErrorTacticUnsolvedGoals
ErrorLogicNotBoolTerm
}
script_layout_label、catalog_label、capability_label、negative_failure_class_label、negative_error_shape_label 与 quantifier_surface_outcome_label
这些函数返回分类值的稳定 snake-case 标签,例如 inline_sequential、local_fact 或 intro_exact。
pub fn script_layout_label(ScriptLayout) -> String
pub fn catalog_label(PositiveCatalogClass) -> String
pub fn capability_label(PositiveTacticCapability) -> String
pub fn negative_failure_class_label(NegativeFailureClass) -> String
pub fn negative_error_shape_label(NegativeErrorShape) -> String
pub fn quantifier_surface_outcome_label(QuantifierSurfaceOutcome) -> String
映射矩阵
映射矩阵把每个语料用例链接到它可出现的文档锚点,例如 manual:runnable_examples,并说明它是否为公开示例。
MappingMatrixEntry 和 mapping_matrix_entries
pub struct MappingMatrixEntry {
case_id : String
kind : MappingCaseKind
script : String
catalog_or_failure_label : String
capability_or_error_label : String
doc_anchor : String
doc_visibility : MappingDocVisibility
}
pub fn mapping_matrix_entries() -> Array[MappingMatrixEntry]
MappingCaseKind、mapping_case_positive、mapping_case_negative 和 mapping_case_unfinished
MappingCaseKind 表示一个用例是正例、反例还是未完成;这三个函数返回它的构造子。
pub enum MappingCaseKind {
PositiveCase
NegativeCase
UnfinishedCase
}
pub fn mapping_case_positive() -> MappingCaseKind
pub fn mapping_case_negative() -> MappingCaseKind
pub fn mapping_case_unfinished() -> MappingCaseKind
MappingDocVisibility 及其构造函数
MappingDocVisibility 表示一个用例是否可以在文档中作为示例引用、作为失败示例引用,或完全不可引用。mapping_doc_visibility_public_unfinished_example 返回 PublicExample:未完成的示例属于公开示例。
pub enum MappingDocVisibility {
PublicExample
PublicFailureExample
InternalOnly
}
pub fn mapping_doc_visibility_public_example() -> MappingDocVisibility
pub fn mapping_doc_visibility_public_failure_example() -> MappingDocVisibility
pub fn mapping_doc_visibility_public_unfinished_example() -> MappingDocVisibility
pub fn mapping_doc_visibility_internal_only() -> MappingDocVisibility
test "corpus" {
let first = @prover.positive_corpus_cases()[0]
inspect(first.case_id, content="pos_intro_exact_identity")
inspect(first.script, content="theorem pos_intro_exact_identity : ⊢ P -> P := by intro h; exact h")
inspect(@prover.capability_label(first.capability), content="intro_exact")
// every corpus case appears in the mapping matrix with an anchor
let entry = @prover.mapping_matrix_entries().search_by(e => e.case_id == first.case_id).unwrap()
inspect(@prover.mapping_matrix_entries()[entry].doc_anchor, content="manual:runnable_examples")
}