| From | Voilà takes |
|---|---|
| Go | braces, packages, channels, select, familiar func |
| Rust | ownership + moves + deterministic destruction — without lifetime annotations |
| REXX | say, parse, exact decimal arithmetic, learn-it-in-an-afternoon |
| C | the printf verbs everyone already knows |
package main
use "std/fmt"
use "std/os"
exception BadRecord { line int, why str }
struct Txn { acct int, holder str, amount dec }
func parse_txn(n int, line str) Txn {
parse line "|" acct "|" holder "|" amount // REXX-style templates
if trim(acct) == "" { throw BadRecord{line: n, why: "empty account"} }
return Txn{
acct: int(trim(acct)), // throws ConvError on junk
holder: title(trim(holder)),
amount: dec(trim(amount)), // exact decimal, always
}
}
func main() {
numeric digits 31 // REXX heritage: exact money
var total = 0d
let f = must os.open("TXN.DAT") // error value → exception
defer f.close() // runs on every exit path
each i, line in f.lines() {
try {
let t = parse_txn(i + 1, line)
total += t.amount
fmt.printf("%6d %-24s %12.2f\n", t.acct, t.holder, t.amount)
} catch e: BadRecord {
fmt.eprintf("skipping line %d: %s\n", e.line, e.why)
}
}
fmt.printf("%-24s %14.2f\n", "TOTAL", total) // exact to 31 digits
}-
No leaks. The type graph must be acyclic through owning edges; back-edges are
weak[T]. Refcounts always reach zero:error: type `Node` forms an ownership cycle through field `parent` --> tree.voi:4:5 | 4 | parent shared[Node] | ^^^^^^^^^^^^ owning edge back to `Node` = note: owning cycles can leak; Voilà forbids them = help: use `weak[Node]` for a back-edge -
No dangling. Borrows can't be stored in structs, channels, or escaping closures — so they can't dangle, and nobody writes
'a. -
No orphaned tasks.
spawnlives insidegroup { }; the group joins all of its tasks before it exits. A failing task cancels its siblings and the failure rethrows at the boundary. -
No silent precision loss.
u16 → intis free;i64 → floatis a compile error until you writefloat(x). Overflow traps. -
No 59.96999999999999.
19.99d * 3d == 59.97d. Exactly.
try group {
spawn fetch("https://a.example")
spawn fetch("https://b.example") // throws? siblings get cancelled,
} // everyone is joined, error surfaces hereChannels move their payloads (ch <- v kills v in the sender), so
data races are unrepresentable. A million tasks is a normal Tuesday.
let p = try parse_port(s) // propagate the error value
let p = parse_port(s) else 8080 // or default it
let p = must parse_port(s) // or promote it to an exception
let r = attempt risky() // or demote an exception to a valuevoilac/ |
the compiler, written in Voilà — lex · par · load · chk · low · cg |
voilac/lex par |
full grammar: interpolation, nested comments, semicolon insertion, the arena AST |
voilac/chk |
acyclicity rule, widening lattice, exhaustive match, use-after-move, compile-time printf checking |
voilac/cg |
C backend: IR → C → cc. Real native binaries; zero leaks under leaks |
runtime/ |
libvoila: the C runtime — refcounted values (no GC), exact decimals, exceptions, tasks/channels/select |
| 📚 stdlib | fmt str os math time json log conv sort rand uuid |
voila build -S |
register-IR assembly listings in HLASM style — location counter, constant pool, DSECTs, ≤79 columns |
bootstrap/voilac.c |
the seed: the C the compiler emits for itself — the portability fallback so cc alone can bootstrap a fresh machine (./bootstrap.bash) |
| tests | goldens, negative fixtures, and the fixpoint: the compiler compiled by itself emits identical C (TESTING.md) |
Voilà builds itself. If you already have a Voilà binary (≥ 0.4.1), ./build.sh
uses it to build the compiler — the self-hosted path:
$ ./build.sh # Voilà builds Voilà
==> bootstrap: prebuilt binary bin/voila (0.4.1)
✓ fixpoint: C(voilac-1) == C(voilac-2)
✓ optimized fixpoint: C(-O3, gen1) == C(-O3, gen2)
✓ bin/voila-0.4.2On a fresh machine with only a C compiler and no Voilà yet, ./bootstrap.bash
compiles the checked-in C seed into the first binary, then builds:
$ ./bootstrap.bash # cc the seed → the first voila, then build
✓ build/voila-seed
✓ fixpoint: C(voilac-1) == C(voilac-2)
✓ bin/voila-0.4.2Then:
$ bin/voila run samples/04_calculator.voi
$ bin/voila check samples/07_orgchart.voi
$ bin/voila build samples/10_life.voi -o life && ./life
$ leaks --atExit -- ./life # refcounting: 0 leaks, 0 bytes
$ ./selftest.bash # the toolchain reproduces every goldenSee TESTING.md for the full procedure and BOOTSTRAP.md for how the compiler compiles itself.
This distro supplies 14 sample programs which are also used in the Programming Handbook.
| Sample | Shows off |
|---|---|
01_worker_pool.voi |
8-worker prime-counting pool: group/spawn/channels/join |
02_accounts.voi |
fixed-width mainframe records, column parse, exact dec totals |
03_txnreport.voi |
exceptions + error values cooperating; typed catch; defer |
04_calculator.voi |
a full recursive-descent evaluator in ~200 lines: enums, match, T! |
05_pipeline.voi |
channel pipeline stages, select, group timeout, cancellation |
06_wordfreq.voi |
text analytics: translate, fields, ordered maps, sort_by |
07_orgchart.voi |
shared/weak trees — the acyclicity rule in action |
08_shapes.voi |
traits + dynamic dispatch + generic Stack[T] |
09_jsonreport.voi |
typed & dynamic JSON, dec-safe money round-trips |
10_life.voi |
Conway's Life on a torus: 2-D slices, str.Builder frames |
11_echo.voi |
a TCP echo service with std/net: listen/accept, thread-per-connection |
12_udp.voi |
connectionless UDP messaging: send_to/recv_from |
13_http.voi |
a minimal HTTP/1.0 client and server on raw sockets |
14_unix.voi |
local IPC over a Unix-domain socket: a tiny command service |
Voilà is completely self-hosted: the compiler is written in Voilà, and the
normal way to build it (./build.sh) is to have a prior Voilà binary
(≥ 0.4.1) compile voilac/*.voi, then have that compile it again, and assert
the two emit byte-identical C — the self-hosting fixpoint. Building 0.4.2
needs a 0.4.1 (or newer) Voilà; that is the minimum.
To bring Voilà up on a machine that has no Voilà binary at all, one generation
of the compiler's own C output is checked in as bootstrap/voilac.c — a
fossil, not a source. ./bootstrap.bash compiles it with cc into the first
native binary, which then drives the same self-hosted build. (cc is still the
backend inside every voila build either way — Voilà emits C.) It originally
bootstrapped from a Go compiler that no longer exists; every stage of the Voilà
one was diffed against it, byte for byte, over every file in this repository —
and then it was deleted.
The optimizer is opt-in: without -O, the output is byte-identical to
0.3. With it (darwin/arm64, best-of-N; Linux/amd64 gains are similar or
larger):
| benchmark | what it stresses | default | -O3 |
delta |
|---|---|---|---|---|
bench/b2_life.voi |
int arithmetic in loops | 1181 ms | 710 ms | −40 % |
bench/b6_partasks.voi |
tasks + channels | 851 ms | 716 ms | −16 % |
bench/b1_queens.voi |
recursion via parameters | 4153 ms | 3589 ms | −14 % |
bench/b5_churn.voi |
struct allocation | 810 ms | 742 ms | −8 % |
bench/b4_ledger.voi |
dec money arithmetic |
987 ms | 971 ms | −2 % (by design: dec is exact, never unboxed) |
Compile time (10-kline self-compile): load 2.26 s → 1.0 s; a small
program's voila build 0.9 s → ~0.12 s (the runtime library is now
compiled once and cached). Full tables: bench/BASELINE.md,
bench/RESULTS.md.
- ✅ Self-hosted — the compiler is written in Voilà; the fixpoint holds
- ✅ Native binaries, multi-file packages, the full checker,
run/build/check - ✅ An optimizing backend (0.4):
-O1scalar cleanup,-O2frame elision,-O3typed unboxing +cc -O3, opt-in--native— same outputs, same trap messages, byte-for-byte, at every level - ✅
std/net(0.4.1): TCP, UDP and Unix-domain sockets — and the first standard package written in Voilà on a thin C syscall shim, the template for Voilà-authored std packages to come - ⬜ interprocedural unboxing (parameters are still boxed) and native
for-range counters — the next performance frontier - ⬜ green threads (tasks are OS threads today: right semantics, wrong cost model)
- ⬜
std/regex,std/http;voila fmt/test/repl; the flow-sensitive borrow checker
📕 Docs: start with Getting Started — a
tutorial from hello.voi through a parallel eight-queens solver to a network
service, every program tested on every build. Then the Programming Manual,
the reference — written in the house style of the IBM mainframe language
references, syntax diagrams included — and the
Language Specification.
Voilà is free software under the GNU General Public License, version 2 — see LICENSE.
Voilà: Rust's guarantees, Go's plumbing, REXX's manners.