Step 07 · CLI design & looking ahead to LSP
Unified CLI
minilang <command> <args>
run <file|-> parse + evaluate
fmt <file|-> pretty-print
ast <file|-> dump AST
repl interactive read-eval-print loop
Patterns to adopt early:
-for stdin everywhere a file is accepted. Pipe-friendly.- Exit codes matter: 0 success, 64 usage error, 65 source error, 70 internal error (we follow rough sysexits.h conventions).
- Subcommand-first so
minilang fmt --checkandminilang run --debughave separate option spaces — no flag conflicts. - One binary, many commands simplifies install + distribution.
What's missing for production
minilang check <file>— parse + typecheck, no eval, machine-readable JSON output (--format=json).minilang test <file>— discover and run inline tests.minilang doc— extract docstrings → HTML.minilang lsp— Language Server Protocol stdio mode.
LSP — the natural next step
Every tool we built — span-tracking lexer, error-recovering parser, structured diagnostics, pretty printer — is what an LSP server needs. Sketch:
client → JSON-RPC → textDocument/didOpen { uri, text }
→ store in document map, run lex + parse
→ publishDiagnostics { uri, diagnostics }
client → JSON-RPC → textDocument/didChange { uri, edits }
→ incremental re-parse (or full)
→ publishDiagnostics
client → JSON-RPC → textDocument/formatting → call format(program)
client → JSON-RPC → textDocument/hover { position }
→ look up enclosing AST node, return doc/type
The hardest parts:
- Incremental parsing to keep latency low on large files (tree-sitter solves this; rust-analyzer rolls its own).
- Indexing across files for cross-file go-to-definition / find-references.
- Cancellation — long-running analyses must be interruptable.
All of those build on the foundations we laid here. Diagnostic codes, spans, and AST formatter aren't optional in an LSP world — they're the contract you have with the editor.
Connection to the rest of the curriculum
- cp-16 (capstone compiler suite) reuses this CLI shell.
- cp-17 (capstone JIT) layers
compileandjitsubcommands on top. - cp-18 (MLIR framework) adds
dump-mlirandlowerstages.
The unifying lesson: a great compiler is also a great library, and the CLI / REPL / LSP are just thin shells over that library.