Code proved correct,
compiled to native speed.
Byron is a compiler and prover for Ada and SPARK, the language NVIDIA chose for its security-critical firmware. Write it with braces like C or Rust, as typed Python, or as Ada itself. Byron proves there is no overflow, no out-of-bounds index and no broken contract, then compiles your program to native code.
Safe
Types that mean something
Strong static types, with ranges you declare: a percentage is 0 to 100 and the compiler holds you to it. No undefined behaviour, no null dereferences, no garbage collector.
Proved
Checked before it runs
Every contract and every run-time check is proved when you build, with no separate tool to remember. When a proof fails, you get the input that breaks it.
Fast
Native, with nothing left to check
Byron compiles through LLVM to native code. A check that is proved is removed from the binary, so the safety costs nothing at run time.
A first program
Pick the syntax
that reads like home.
The same small package, with a contract on each function, in each of Byron's three syntaxes. All three prove the same twelve checks, run the same way and print the same output.
package Counters {
pub fn clamp(value, low, high: Integer) -> Integer
requires low <= high
ensures result in low..=high
{
if value < low {
return low;
} else if value > high {
return high;
}
return value;
}
pub fn increment(count: inout Natural)
requires count < Natural::Last
ensures count == old(count) + 1
{
count += 1;
}
} from byron import Natural, ensures, requires, result
def clamp(value: int, low: int, high: int) -> int:
requires(low <= high)
ensures(low <= result <= high)
if value < low:
return low
elif value > high:
return high
return value
def increment(count: Natural) -> Natural:
requires(count < Natural.last)
ensures(result == count + 1)
return count + 1 package Counters is
function Clamp (Value, Low, High : Integer) return Integer
with Pre => Low <= High,
Post => Clamp'Result in Low .. High;
procedure Increment (Count : in out Natural)
with Pre => Count < Natural'Last,
Post => Count = Count'Old + 1;
end Counters; package body Counters is
function Clamp (Value, Low, High : Integer) return Integer is
begin
if Value < Low then
return Low;
elsif Value > High then
return High;
else
return Value;
end if;
end Clamp;
procedure Increment (Count : in out Natural) is
begin
Count := Count + 1;
end Increment;
end Counters; $ byronc prove
proved 12 of 12 checks in 3 subprograms (5 statically, 7 by the solver)
$ byronc run
hits: 2
clamped: 10 requires and ensures are the contract:
what a caller must promise, and what the function promises back.
byronc run proves and runs at once;
byronc build links a native executable.
Bring what you know
Your instincts,
Ada's guarantees.
You don't have to learn Ada's syntax to get Ada's safety. Byron is one language with three spellings, and a project can mix all three: they share one prover, one compiler and one set of guarantees.
From C, C++, Rust or Go · .leon
Leon
Braces, fn, let and var,
pub, and method chains like
xs.filter(x => x > 0).sum(). A call marks what it
may change, increment(&hits), and forgetting the
& is an error with a fix-it.
From Python · .py
Leno
Typed Python, with lists, range, classes and
generators. Contracts are ordinary calls,
requires(...) and ensures(...), so a Leno
program is still a Python program: CPython prints what the native
build prints.
From Ada · .ads · .adb
Noel
Ada 2022 itself, with SPARK's contracts. Every legal Byron program is a legal Ada program with the same meaning, and Byron's test suite holds it to GNAT and GNATprove.
byronc translate
Move between them at any time.
byronc translate --to noel rewrites a Leon or Leno
project as Ada, comments included, and back again. Start in the
syntax your team knows, and hand the proved Ada to anyone who needs
it.
Why Ada
The safe language
that was here first.
Ada was designed for software that must not fail, and SPARK adds proof on top. Both are having a moment, for good reasons.
Chosen by NVIDIA for security-critical firmware
NVIDIA moved security-critical firmware for its GPUs from C to SPARK, the provable form of Ada that Byron is built around. Its engineers reported generated code as fast as their C, and with every property proved, no run-time checks to pay for.
Sources: AdaCore case study , DevClass
Rust-grade safety, without fighting a borrow checker
Ada's parameter modes, in, out and in out, let the compiler decide how to pass a value, so most code never touches a pointer and there are no lifetimes to annotate. Where you do use pointers, ownership rules like Rust's apply, and only there.
Proof, not just memory safety
Memory safety rules out one class of bug. SPARK goes further: it proves your program has no overflow, no out-of-range value and no division by zero, and that it does what its contracts say.
Mature, standard and battle-tested
Ada is an ISO standard, now Ada 2022, with decades of use in avionics, rail and space. Every Byron program is legal Ada, so what you write is never locked in.
When a proof fails
The input that breaks it.
Take the requires line out of Leon's increment
and the proof fails. Byron doesn't just say "might overflow": it
finds the values that break the program, replays them to show the
failure is real, and proposes the precondition that excludes
exactly those values, already proved to be enough.
Every diagnostic is numbered, and byronc explain B4101
prints what it means and what to do. Diagnostics come as text or as
JSON for editors and agents.
$ byronc prove
error[B4101]: overflow check fails
--> ./src/counters.leon:17:15
|
17 | count += 1;
| ^^^^ might overflow `Integer` (-2147483648 .. 2147483647)
|
= note: replaying these values on the program reaches this check and it fails
= counterexample: fails when count = Integer::Last
= failing inputs: exactly count >= Integer::Last
= help: a precondition `count <= 2147483646` on `Counters.increment` excludes exactly the values that fail, and is proved to make this check pass
1 error emitted
proved 9 of 10 checks in 3 subprograms (4 statically, 5 by the solver) What is proved
Proof is a phase
of compilation.
A build succeeds only when flow analysis passes and every verification condition is discharged. There is no separate tool to remember to run, and no gap between the program that was proved and the program that ships.
Run-time checks
Every check Ada makes — overflow, range, index, division by zero, null, discriminants, tags, lengths — is proved never to fail. Proved checks are left out of the code, and LLVM is told the arithmetic they guard cannot wrap.
Contracts
Pre and Post, Contract_Cases, Exceptional_Cases, loop invariants and variants, type invariants, predicates and assertions. Ghost code and mathematical models exist for proof only and are erased.
Flow
Every variable is initialised before it is read, Global and Depends tell the truth, and ownership rules hold for access values, so there is no aliasing the prover cannot see.
Concurrency
Ada 2022's Jorvik profile: tasks and protected objects. Byron proves there are no data races, no blocking inside protected actions, and that priority ceilings are respected.
Exceptions
A procedure may propagate only the exceptions its Exceptional_Cases list, with their consequences proved. Any other raise must be proved unreachable, and checks never raise at all.
Devices
Volatile objects with SPARK's external properties, objects at fixed addresses, and overlays the prover can trust: the groundwork for drivers and embedded code.
See them at work in the examples: pipelines with generated loop invariants, Python lists with proved bounds, and tasks proved free of data races.
One command
Everything in
byronc.
The compiler, prover, JIT, REPL, formatter, translator and language server are one program. In the REPL, proof is advisory and run-time checks stay on, so a failed check is reported and you're back at the prompt.
byronc run
Prove, compile in memory and run, in one step.
byronc build
Prove, compile each unit to an object file and link a native executable.
byronc repl
Declarations, statements and expressions, with run-time checks on.
byronc translate
Rewrite a project in another syntax, comments included.
byronc explain
The full explanation of any numbered diagnostic, with an example and the fix.
byronc lsp
A language server: diagnostics, hover, go to definition, fix-its, formatting.
byronc stubs
Python stubs, so pyright and mypy read Leno code as they read any other.
--certificates
Keep each proof's unsat core in files you commit, re-checked anywhere without search.
$ byronc repl --syntax leon
byron> import Counters; use Counters;
byron> var hits = Natural::Last;
byron> clamp(42, 0, 10)
10
byron> increment(&hits);
<input 4>:1:12: run-time check failed [B5101]: the precondition of `increment` might not hold
warning[B5101]: precondition fails at a call
--> <input 4>:1:12
|
1 | increment(&hits);
| ^^^^ the precondition of `increment` might not hold
|
::: ./src/counters.leon:15:18
|
15 | requires count < Natural::Last
| --------------------- precondition
|
= note: running the program reaches this check and it fails
= note: advisory mode: this is checked when the program runs
1 warning emitted Status
Under active development.
Byron is young and moving fast, and everything it ships carries a permissive licence. If you build software that has to be right, we'd like to hear from you.