Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

12. Cargo workspace: library plus thin CLI

  • Status: Accepted
  • Date: 2026-09-02

Context

The implementation could be a single binary crate, a single library crate with a [[bin]], or a workspace with separate library and binary crates.

Two forces: the language should be embeddable (the spec-test harness in 0002 is itself an embedder, and a public release benefits from being usable as a library), and the CLI concerns (argument parsing, REPL line editing, terminal colours) should not leak into the language core.

Decision

A Cargo workspace with two members:

  • crates/korrin — the entire language: lexer, parser, resolver, interpreter, and the run / Interpreter embedding API. No dependency on any CLI or terminal crate. This is what gets published to crates.io.
  • crates/korrin-cli — the korrin binary. Depends on korrin plus clap and rustyline. Contains only: parse args, read source, call the library, print results and diagnostics.

Shared dependency versions, lints, and package metadata live in the workspace Cargo.toml ([workspace.dependencies], [workspace.lints], [workspace.package]).

Consequences

  • The library is testable and reusable without pulling in clap/rustyline.
  • The line between "language" and "tool" is enforced by the crate boundary, not by discipline.
  • Two Cargo.tomls and a workspace root to maintain — minor.
  • Future crates (korrin-fmt, a fuzz target, a language server) drop in as new workspace members without restructuring.
  • Cargo.lock is committed, since the workspace produces a shipped binary.

Alternatives considered

  • Single crate with src/lib.rs + src/main.rs. Simplest, but the binary's dependencies become the library's dependencies for anyone who depends on it, and there is no hard wall against CLI code creeping into language modules.
  • Split the library further now (separate korrin-lexer, korrin-parser, …). Premature. The stages share types freely and are changing together; internal modules give the same organisation without publishing five crates that must be versioned in lockstep. Revisit if a stage needs independent release.