Skip to main content

VS Code Extension

The Verum Language Support extension is the primary IDE integration for Verum. It is a thin VS Code wrapper around verum lsp and verum dap — the heavy lifting (parsing, type-checking, refinement validation, CBGR analysis, SMT-backed verification) happens in the verum binary. The extension contributes the editor surface: highlighting, snippets, commands, inlay hints, code actions, the profile dashboard, and the debug integration.

Install

From the Marketplace

ext install verum-lang.verum

From a .vsix file

code --install-extension verum-language-0.2.0.vsix

The extension requires the verum binary on $PATH (or set verum.lsp.serverPath to an absolute path). Install the toolchain per Installation.

What ships inside

ComponentWhat it doesPowered by
TextMate grammarOffline syntax highlighting grammar-complete against grammar/verum.ebnf — keywords, refinement predicates, raw multiline strings, tagged literals, @attribute(args).syntaxes/verum.tmLanguage.json
Semantic highlightingLSP-driven additions on top of TextMate: refinement vs. regular types, CBGR reference tiers, proof identifiers, context providers / consumers.verum lsptextDocument/semanticTokens
SnippetsPrefix-driven scaffolds for type is, is protocol { }, implement for, mount, fn-verify-formal, nursery, select, refinement shapes, tagged literals, proof blocks.snippets/verum.json
DiagnosticsParse errors, type errors, refinement counter-examples, CBGR warnings — on-type, debounced, with concrete witness values.verum lsptextDocument/publishDiagnostics
Code actionsPromote &T&checked T, insert runtime-check fallback, weaken refinement, convert to sigma type.verum/getQuickFixes custom request
Inlay hintsInferred refinement types, inferred generic parameters, CBGR tier hints.verum/getInlayHints custom request
Profile dashboardWebview showing verification / CBGR / compile metrics, hot-spot navigation.verum/getProfile custom request
Debug adapterLaunch / step / breakpoints via verum dap speaking DAP over stdio.verum dap --transport stdio
Task providerbuild / run / test / check wired to verum with the $verum problem matcher.VS Code task API
Terminal linksfile.vr:42:10 in any terminal becomes a clickable link.VS Code terminal-link API

Activation

The extension activates on any of:

  • Opening a .vr file (onLanguage:verum).
  • Opening a workspace that contains Verum.toml or any .vr file.
  • Starting a debug session of type: verum.

On activation the extension spawns:

${verum.lsp.serverPath} lsp --transport stdio

and keeps the client alive for the life of the window. The first .vr you open triggers the LSP's project analysis; subsequent edits reuse the incremental pipeline.

Commands

All commands live under the Verum category (Ctrl/Cmd-Shift-P):

CommandDefault bindingEffect
Verum: Run Current FileCmd+Shift+Rverum run <file> in an editor terminal.
Verum: Run Testverum test <file> --filter <fn> at the cursor.
Verum: Verify Function ContractsRe-verify @verify(...) obligations under the cursor.
Verum: Promote to &checked ReferenceCmd+Alt+CAsk the server to upgrade &T&checked T with proof comment.
Verum: Add Runtime Check (Result<T, E>)Wrap in a runtime fallback when escape-analysis fails.
Verum: Infer Refinement TypeCmd+Alt+RAsk the server for a refinement suggestion for the symbol at cursor.
Verum: Validate Refinement at CursorCmd+Alt+VOne-shot SMT validation of the refinement at the cursor.
Verum: Profile Current FileRun profiling; results populate the dashboard.
Verum: Open Profile DashboardFocus the explorer-pane webview.
Verum: Restart Language ServerKill and respawn verum lsp.
Verum: Show Language Server StatusCurrent state + crash count.
Verum: Format DocumentCmd+Shift+FDelegates to LSP formatter.

Configuration

The extension reads settings under verum.*. The defaults match the recommendations in CLI and LSP.

LSP

SettingDefaultMeaning
verum.lsp.enabletrueMaster switch.
verum.lsp.serverPath"verum"Path to the verum binary.
verum.lsp.validationMode"quick"quick (< 100 ms) / thorough (< 1 s) / complete (unbounded).
verum.lsp.enableRefinementValidationtrueRun SMT-backed refinement validation while typing.
verum.lsp.showCounterexamplestrueAttach concrete witness values to refinement errors.
verum.lsp.showInlayHintstrueInline inferred types and CBGR tiers.
verum.lsp.diagnosticDelay200 msDebounce between keystroke and validation.
verum.lsp.smtSolver"auto"auto / z3 / cvc5. auto lets the compiler's capability router pick. Override only to reproduce a specific result.
verum.lsp.smtTimeout50 msPer-obligation SMT timeout for live validation (build-time timeout is separate; see Verum.toml [verify] solver_timeout_ms).
verum.lsp.cacheValidationResultstrueCache SMT results keyed by goal hash.
verum.lsp.trace.server"off"messages / verbose dumps LSP traffic to the output channel.

CBGR

SettingDefaultMeaning
verum.cbgr.enableProfilingfalseEnable CBGR per-deref profiling (≈ 15 ns overhead).
verum.cbgr.showOptimizationHintstrueInline hints when a reference could be promoted to &checked.

Verification

SettingDefaultMeaning
verum.verification.showCostWarningstrueWarn when a single obligation exceeds the slow threshold.
verum.verification.slowThresholdMs5000Slow-verification threshold.

Code lens / formatting / debug

SettingDefaultMeaning
verum.codeLens.enabletrueAll code lenses on/off.
verum.codeLens.showRunButtontrue"▶ Run" above fn main.
verum.codeLens.showTestButtontrue"▶ Test" above @test fn.
verum.codeLens.showReferencestrueReference count above every top-level symbol.
verum.formatting.enabletrueFormat on save.
verum.semanticHighlighting.enabletrueUse LSP semantic tokens on top of TextMate.
verum.debug.defaultTier"interpreter"interpreter (VBC, full step/breakpoint support) or aot (LLVM, reduced).
verum.debug.dapServerPath""Override the DAP server path; empty falls back to verum.lsp.serverPath.

Settings changes are forwarded live via workspace/didChangeConfiguration — no restart needed for any of them.

Syntax-highlighting model

The grammar is grammar-driven: every keyword, literal form, and attribute shape in grammar/verum.ebnf has a corresponding TextMate pattern. Key points:

  • Keywords. All four tiers — reserved (let / fn / is), primary (type / where / using), control-flow, async, proof — are matched exhaustively. Rust-style struct / enum / trait / impl / ref / move / drop are not Verum syntax and are not highlighted.
  • Strings. Triple-quoted """...""" (always raw, always multiline), byte strings b"...", interpolated f"..." / f"""...""" (with {expr:format} format-spec scope inside), character literals 'x'.
  • Tagged literals. sql#"""...""" and its ~40 format-tag friends (json, json5, yaml, toml, xml, html, csv, rx, url, d, dur, ip, b64, hex, sh, css, lua, asm, …) with language-specific embedded scopes where it makes sense, plus ${expr} interpolation.
  • Refinement predicates. The { self > 0 && self <= 100 } shape after a type reference is detected heuristically and scoped as meta.refinement.verum, with self highlighted as a language variable.
  • Attributes. @derive(A, B) highlights each derivee; @verify(formal) validates against the 9 strategies in the spec; @name(args) gets generic parameter/value scopes.
  • No #[...]. Verum uses @ exclusively; there are no Rust-style hash attributes.
  • No name! macros. Verum has no macro-bang syntax — compile-time constructs all use @ (@derive, @const, @cfg, @sql_query, user-defined @my_macro).

Snippets cheatsheet

The most common prefixes:

PrefixExpands to
fnFunction definition
fn-verify-formal@verify(formal) fn ... requires ... ensures ...
fn-throwsFunction with typed error boundary
fn-usingFunction with using [Context] clause
typeType alias
type-refinedRefinement type (Int { self > 0 })
type-record / type-variantRecord / sum type
type-newtypeOpaque wrapper (type X is (Int);)
protocoltype X is protocol { ... }
impl / impl-generic / impl-whereimplement [Proto] for Type forms
mount / mount-items / mount-as / mount-globModule imports
match-maybe / match-resultPattern-match on Maybe<T> / Result<T, E>
try / try-finally / try-fullError handling blocks
defer / errdeferScoped cleanup
async-fn / spawn / nursery / selectAsync / structured concurrency
ref-checked / ref-unsafeCBGR tier sigils
theorem / lemma / proof / calc / forall / existsProof constructs
sql / rx / json / html / url / dateTagged literal scaffolds
fstring / fstring-multi / raw-stringString literal shapes

Debugging

The extension ships a VS Code debug configuration type verum. Press F5 inside any .vr file to launch the default config:

{
"type": "verum",
"request": "launch",
"name": "Debug Verum Program",
"program": "${file}",
"stopOnEntry": false,
"tier": "interpreter"
}

tier: "interpreter" runs the program through the VBC interpreter with full DAP support (step-into, step-over, breakpoints, variable inspection). tier: "aot" links native and exposes a reduced breakpoint set. The initial configuration palette provides three scaffolds: Debug Current File, Debug with Arguments, Debug (Stop on Entry).

Tasks

The extension registers a verum task type. In .vscode/tasks.json:

{
"type": "verum",
"task": "build", // build | run | test | check
"problemMatcher": ["$verum"]
}

The $verum problem matcher parses error[V####]: … / --> file.vr:L:C outputs and surfaces them as diagnostics in the Problems panel.

Troubleshooting

Status bar shows Verum: Error

The LSP server failed to start. Check the Verum Language Server output channel for the actual stderr. Most likely causes:

  • verum not on $PATH — fix verum.lsp.serverPath.
  • verum version too old for the grammar in your file — re-download the binary from GitHub Releases and replace /usr/local/bin/verum.
  • Corporate VPN rewrites certificates — unrelated; LSP uses stdio.

verum.lsp.smtSolver set to z3 produces different results from auto

Expected — auto races Z3 and CVC5 according to the goal shape. Prefer auto for correctness-critical work and z3 or cvc5 only when reproducing a specific solver's trace. See Verification / SMT routing.

@verify(formal) obligations time out while typing

verum.lsp.validationMode defaults to quick (≤ 100 ms budget). For hot files you're actively proving, bump to thorough — it accepts a 1 s ceiling and retries with a different tactic. For full solver budgets, verify at build time via verum check rather than on-type.

"Cannot promote: escape analysis could not prove safety"

Verum: Promote to &checked Reference asks the compiler to upgrade a CBGR reference to the zero-cost tier. If the escape analysis can't prove that the reference is stack-local, the promotion is refused. Use Verum: Add Runtime Check (Result<T, E>) instead, which wraps the deref in a fallible result.

See also

  • LSP — the protocol-level feature set the extension surfaces.
  • CLI — the commands invoked by task / run / test / debug actions.
  • Installation — install the verum binary the extension drives.
  • Playbook — terminal UI with the same indexing infrastructure.