4-编程语言与状态枚举
4-编程语言与状态枚举

4-编程语言与状态枚举

本文档介绍 Judge0 中两个核心枚举类型:编程语言(Language) 和 执行状态(Status)。这两个枚举是代码执行平台的基础数据模型,分别定义了系统支持的编程语言种类以及代码提交的执行结果状态。

状态枚举(Status)

状态定义

Status 枚举类位于 app/enumerations/status.rb,定义了代码提交的 14 种执行状态。每种状态都有唯一的数字标识 ID 和友好的英文描述名称。

graph TB
    subgraph "执行状态分类"
        subgraph "处理中状态"
            Q[queue<br/>排队中]
            P[process<br/>处理中]
        end

        subgraph "成功状态"
            AC[ac<br/>Accepted<br/>通过]
        end

        subgraph "失败状态"
            subgraph "答案错误"
                WA[wa<br/>Wrong Answer<br/>答案错误]
            end

            subgraph "超时"
                TLE[tle<br/>Time Limit<br/>超时]
            end

            subgraph "编译错误"
                CE[ce<br/>Compilation Error<br/>编译错误]
            end

            subgraph "运行时错误"
                S11[sigsegv<br/>SIGSEGV<br/>段错误]
                S25[sigxfsz<br/>SIGXFSZ<br/>文件大小超限]
                S8[sigfpe<br/>SIGFPE<br/>浮点异常]
                S6[sigabrt<br/>SIGABRT<br/>中止]
                NZEC[nzec<br/>NZEC<br/>非零退出码]
                O[other<br/>其他错误]
            end

            subgraph "系统错误"
                BOX[boxerr<br/>Internal Error<br/>内部错误]
                EXE[exeerr<br/>Exec Format Error<br/>执行格式错误]
            end
        end
    end

状态码对照表:

枚举键名 ID 名称 含义说明
queue 1 In Queue 提交已接收,正在队列中等待执行
process 2 Processing 正在编译或运行代码
ac 3 Accepted 答案正确,测试全部通过
wa 4 Wrong Answer 答案错误,输出与期望不符
tle 5 Time Limit Exceeded CPU 时间超出限制
ce 6 Compilation Error 编译失败
sigsegv 7 Runtime Error (SIGSEGV) 段错误(访问非法内存)
sigxfsz 8 Runtime Error (SIGXFSZ) 文件大小超出限制
sigfpe 9 Runtime Error (SIGFPE) 浮点运算异常
sigabrt 10 Runtime Error (SIGABRT) 程序异常中止
nzec 11 Runtime Error (NZEC) 非零退出码(程序异常退出)
other 12 Runtime Error (Other) 其他运行时错误
boxerr 13 Internal Error 系统内部错误
exeerr 14 Exec Format Error 可执行文件格式错误

Sources: status.rb

运行时错误状态映射

Status 枚举包含一个特殊的类方法 find_runtime_error_by_status_code,用于将 Linux 系统信号码映射为对应的运行时错误状态。这是处理程序异常退出的核心逻辑。

def self.find_runtime_error_by_status_code(status_code)
  case status_code.to_i
    when 11 then Status.sigsegv    # SIGSEGV - 段错误
    when 25 then Status.sigxfsz    # SIGXFSZ - 文件大小超限
    when 8  then Status.sigfpe     # SIGFPE  - 浮点异常
    when 6  then Status.sigabrt   # SIGABRT - 程序中止
    else Status.other             # 其他错误
  end
end

该方法在 IsolateJob 的 determine_status 方法中被调用,当隔离环境返回 “SG”(Signaled)状态时,根据退出信号确定具体的运行时错误类型。

Sources: status.rb Sources: isolate_job.rb

状态转换流程

stateDiagram-v2
    [*] --> queue: 提交创建
    queue --> process: 开始执行
    process --> ce: 编译失败
    process --> ac: 答案正确
    process --> wa: 答案错误
    process --> tle: 超时
    process --> sigsegv: 段错误
    process --> sigxfsz: 文件超限
    process --> sigfpe: 浮点异常
    process --> sigabrt: 程序中止
    process --> nzec: 非零退出码
    process --> other: 其他错误
    process --> boxerr: 系统错误
    process --> exeerr: 格式错误

编程语言配置(Language)

语言模型结构

Language 模型定义在 app/models/language.rb,对应数据库中的 languages 表。

class Language < ApplicationRecord
  validates :name, presence: true
  validates :source_file, :run_cmd, presence: true, unless: -> { is_project }
  default_scope { where(is_archived: false).order(name: :asc) }

  def is_project
    name == "Multi-file program"
  end
end

数据库表结构包含以下字段:

字段名 类型 说明
id integer 语言唯一标识符
name string 语言显示名称(如 “Python (3.8.1)”)
source_file string 源代码文件名(如 “main.py”)
run_cmd string 运行命令的模板字符串
compile_cmd string 编译命令的模板字符串(可选)
is_archived boolean 是否已归档(默认 false)

Sources: language.rb Sources: schema.rb

语言配置文件

Judge0 将语言配置分为两个文件:db/languages/active.rb(当前活跃语言)和 db/languages/archived.rb(已归档语言)。

活跃语言配置示例:

{
  id: 71,
  name: "Python (3.8.1)",
  is_archived: false,
  source_file: "script.py",
  run_cmd: "/usr/local/python-3.8.1/bin/python3 script.py"
}

编译型语言配置示例:

{
  id: 48,
  name: "C (GCC 7.4.0)",
  is_archived: false,
  source_file: "main.c",
  compile_cmd: "/usr/local/gcc-7.4.0/bin/gcc %s main.c",
  run_cmd: "./a.out"
}

Sources: active.rb Sources: active.rb

支持的编程语言总览

Judge0 原生支持 47 种活跃编程语言,涵盖多种编程范式:

类别 语言列表
系统编程 C (GCC 7.4.0/8.3.0/9.2.0), C (Clang 7.0.1), C++ (GCC 7.4.0/8.3.0/9.2.0, Clang 7.0.1), Rust
Web 开发 JavaScript (Node.js 12.14.0), TypeScript (3.7.4), PHP (7.4.1), Ruby (2.7.0)
JVM 生态 Java (OpenJDK 13.0.1), Kotlin (1.3.70), Scala (2.13.2), Groovy (3.0.3), Clojure (1.10.1)
.NET 生态 C# (Mono 6.6.0.161), F# (.NET Core SDK 3.1.202), Visual Basic.Net
函数式 Haskell (GHC 8.8.1), OCaml (4.09.0), Elixir (1.9.4), Erlang (OTP 22.2)
脚本语言 Python (2.7.17, 3.8.1), Perl (5.28.1), Bash (5.0.0), Lua (5.3.5)
科学计算 R (4.0.0), Octave (5.1.0), SQL (SQLite 3.27.2)
传统语言 Pascal (FPC 3.0.4), Fortran (GFortran 9.2.0), COBOL (GnuCOBOL 2.2), Basic (FBC 1.07.1), Prolog
其他 Assembly (NASM 2.14.02), Common Lisp (SBCL 2.0.0), D (DMD 2.089.1), Swift (5.2.3), Objective-C, Go (1.13.5)

Sources: active.rb

命令模板语法

语言配置中的 run_cmd 和 compile_cmd 使用 %s 作为源代码文件的占位符。当执行时,系统会将 %s 替换为实际的安全参数。

模板使用示例:

# Python 解释型语言 - 只需运行命令
run_cmd: "/usr/local/python-3.8.1/bin/python3 script.py"

# C 编译型语言 - 编译 + 运行
compile_cmd: "/usr/local/gcc-9.2.0/bin/gcc %s main.c"
run_cmd: "./a.out"

# C++ 编译型语言 - 需要设置库路径
compile_cmd: "/usr/local/gcc-9.2.0/bin/g++ %s main.cpp"
run_cmd: "LD_LIBRARY_PATH=/usr/local/gcc-9.2.0/lib64 ./a.out"

Sources: active.rb Sources: active.rb

特殊语言:多文件项目

ID 为 89 的 “Multi-file program” 是一种特殊语言,允许用户上传 ZIP 压缩包,包含多个源文件和自定义的 compile.sh/run.sh 脚本。

{
  id: 89,
  name: "Multi-file program",
  is_archived: false
  # 注意:没有 source_file、run_cmd、compile_cmd
  # 用户需要提供 compile.sh 和/或 run.sh 脚本
}

对于这种特殊语言,is_project 方法返回 true,跳过源代码文件的验证。

Sources: active.rb Sources: language.rb

API 中的枚举表示

序列化器定义

Status 和 Language 都配有专门的序列化器,用于生成 API 响应:

StatusSerializer – 将状态对象转换为 API 响应格式:

class StatusSerializer < ActiveModel::Serializer
  attribute(:id) { object.id }
  attribute(:description) { object.name }
end

LanguageSerializer – 返回语言的所有配置信息:

class LanguageSerializer < ActiveModel::Serializer
  attributes :id, :name, :is_archived, :source_file, :compile_cmd, :run_cmd
end

Sources: status_serializer.rb Sources: language_serializer.rb

API 响应示例

当查询提交状态时,Status 在响应中以嵌套对象形式返回:

{
  "token": "abc123",
  "status": {
    "id": 3,
    "description": "Accepted"
  },
  "language": {
    "id": 71,
    "name": "Python (3.8.1)"
  }
}

Sources: submission_serializer.rb Sources: submission_serializer.rb

状态与语言的关联使用

Submission 模型中的关联

在 Submission 模型中,通过 enumeration :status 声明建立了与 Status 枚举的关联:

class Submission < ApplicationRecord
  # ...验证规则...
  enumeration :status

  def status
    Status.find_by(id: status_id)
  end

  def status=(status)
    self.status_id = status.id
  end
end

Sources: submission.rb Sources: submission.rb

控制器中的状态检查

在 SubmissionsController 的 destroy 方法中,通过 Status 枚举检查提交是否可以删除:

def destroy
  submission = Submission.find_by!(token: params[:token])
  if submission.status == Status.queue || submission.status == Status.process
    render json: {
      error: "submission cannot be deleted because its status is #{submission.status.id}"
    }, status: :bad_request
    return
  end
  submission.delete
end

Sources: submissions_controller.rb

IsolateJob 中的状态更新

IsolateJob 是实际执行代码的核心组件,它根据执行结果设置不同的 Status:

# 开始处理时
submission.update(status: Status.process, started_at: DateTime.now)

# 编译失败时
submission.status = Status.ce

# 运行验证时
submission.status = determine_status(metadata[:status], submission.exit_signal)

Sources: isolate_job.rb Sources: isolate_job.rb Sources: isolate_job.rb

架构关系图

erDiagram
    Submission ||--o| Language : "language_id"
    Submission ||--o| Status : "status_id"

    Language {
        int id PK
        string name
        string source_file
        string compile_cmd
        string run_cmd
        boolean is_archived
    }

    Status {
        int id PK
        string name
        string queue "In Queue"
        string process "Processing"
        string ac "Accepted"
        string wa "Wrong Answer"
        string tle "Time Limit Exceeded"
        string ce "Compilation Error"
        string sigsegv "Runtime Error (SIGSEGV)"
        string sigxfsz "Runtime Error (SIGXFSZ)"
        string sigfpe "Runtime Error (SIGFPE)"
        string sigabrt "Runtime Error (SIGABRT)"
        string nzec "Runtime Error (NZEC)"
        string other "Runtime Error (Other)"
        string boxerr "Internal Error"
        string exeerr "Exec Format Error"
    }

    Submission {
        int id PK
        text source_code
        int language_id FK
        int status_id FK
        text stdin
        text expected_output
        text stdout
        decimal time
        int memory
    }

下一步学习

在理解了枚举系统之后,建议继续学习以下内容:

相关条目

  • 3-提交(Submission)核心概念
  • 10-Language 语言配置模型

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注