internal/runner_cli 教程

本页面向维护者,介绍如何借助 internal/runner_cli 的共享辅助函数在 cli/ 中编写符合性运行器:解析通用选项、收集并读取语料文件、报告诊断、打印 JSON 摘要并选择退出码。该包是 Luna-Flow/floating 的内部包;这些示例不会针对已发布的模块进行编译。

快速入门

在模块内部导入这些辅助函数和一个前端:

import {
  "Luna-Flow/floating/internal/runner_cli",
  "Luna-Flow/floating/frontend/gda_expr",
}

一个最小的运行器(run 接收完整的参数向量,程序名在首位):

///|
pub fn run(arguments : Array[String]) -> Int {
  let common = match @runner_cli.parse_common_options(arguments) {
    Ok(value) => value
    Err(message) => {
      println(message)
      return 2
    }
  }
  let files = match @runner_cli.collect_files(common.remaining(), ".decTest") {
    Ok(value) => value
    Err(message) => {
      println(message)
      return 2
    }
  }
  let documents = []
  for path in files {
    guard @runner_cli.read_source(path) is Ok(text) else {
      println("cannot read file: " + path)
      return 2
    }
    match @gda_expr.parse_dectest(path, text) {
      Ok(document) => documents.push(document)
      Err(diagnostics) => {
        let first = diagnostics[0]
        println(
          @runner_cli.format_diagnostic_at(
            first.span().source(),
            first.span().line(),
            first.message(),
          ),
        )
        return 2
      }
    }
  }
  let summary = @gda_expr.execute_documents(
    documents,
    options=@gda_expr.RunOptions::new(
      shard_count=common.shard_count(),
      shard_index=common.shard_index(),
    ),
  )
  if common.json() {
    println(
      @runner_cli.json_stringify(
        @runner_cli.json_object([
          ("totalCases", @runner_cli.json_int(summary.total_cases())),
          ("failedCases", @runner_cli.json_int(summary.failed_cases())),
        ]),
      ),
    )
  }
  if summary.success() { 0 } else { 1 }
}

日常任务

遵循退出码约定

cli/ 中的所有运行器都使用相同的退出码,tools/*.py 依赖于此:

代码含义
0所有已执行的用例都通过(并且在严格模式下没有不支持的用例)
1至少一个用例失败,或严格模式发现了不支持的用例
2用法错误、文件无法读取或解析诊断

添加运行器专用选项

parse_common_options 会把它不认识的所有参数按顺序留在 remaining() 中。从该数组中解析你自己的选项,其余的视为路径。如果你的运行器不能分片,请传入 allow_shard=false;此时分片选项会保留在 remaining() 中,你的解析器应将其作为未知选项拒绝。

保持输出机器可读

给出 --json 时,每次调用只打印一个 JSON 对象。用 json_object 构造它,使键的顺序与你列出的顺序一致,并对计数使用 json_int,使其打印为整数。

深入了解

  • cli/ 中的四个运行器都是完整的示例:gda_expr_cli、itl_expr_cli、mpfr_expr_cli 和 testfloat_expr_cli。
  • 用 sh tools/run_moon_clean_exec.sh run --release --target native src/cli -- --help 构建 native 分发器。
  • 在包含该模块的工作区中运行辅助函数的测试:moon test -p Luna-Flow/floating/internal/runner_cli。

常见陷阱

  • 程序名。 parse_common_options 会跳过 arguments[0]。请传入完整的向量,而不是去掉程序名的切片,否则第一个真正的参数会丢失。
  • 不递归搜索目录。 collect_files 只列出目录的直接条目。
  • 不匹配的文件会被静默丢弃。 没有该后缀的文件参数会被忽略,不会报告。
  • 实际上仅支持 native。 文件访问经由 moonbitlang/x/fs;运行器在 native 目标上构建和运行。

后续步骤