Give your model this link
faberlang.dev- Version
- 1.12.0
- Platforms
- macOS arm64 · Linux x64
- License
- MIT
A statically typed language for coding agents and human authors · MIT
Faber Romanus has a clear mechanical grammar, explicit static and generic types, and math-oriented operators. The same program is written and read in eight language surfaces, and compiles to Rust, TypeScript, Go, Swift and more — so a library you write once can go into the project you already have.
Your model reads that file, downloads the current release for
your machine, verifies its checksum, installs the faber command, and runs
faber check on a hello program. It all happens on your machine.
The language, public libraries, examples, and tooling ship under the MIT license. Radix, the compiler, is closed only while it is under active development. That is temporary, not a permanent fence.
faber convert --to en — English reader surface — the base spelling for everyday sourceclass Span {
const f64 low
const f64 high
fn contains(f64 x) → bool {
return self.low ≤ x and x ≤ self.high
}
fn center() → f64 {
return (self.low + self.high) ÷ 2.0
}
}
fn choose<T>(bool first, T a, T b) → T {
return first ✓ a ✗ b
}
main {
const Span bytes ← Span { low = 0.0, high = 255.0 }
print bytes.center()
print choose(bytes.contains(300.0), "inside", "outside")
print -7 / 2
}faber convert --to la — canonical Faber — the classical surface the language is named forgenus Span {
fixum f64 low
fixum f64 high
functio contains(f64 x) → bivalens {
redde ego.low ≤ x et x ≤ ego.high
}
functio center() → f64 {
redde (ego.low + ego.high) ÷ 2.0
}
}
functio choose<T>(bivalens first, T a, T b) → T {
redde first ✓ a ✗ b
}
incipit {
fixum Span bytes ← Span { low = 0.0, high = 255.0 }
nota bytes.center()
nota choose(bytes.contains(300.0), "inside", "outside")
nota -7 / 2
}faber convert --to th-TH — Thai — spaceless scriptชนิด Span {
คงที่ f64 low
คงที่ f64 high
ฟังก์ชัน contains(f64 x) → ตรรกะ {
คืน ตัวฉัน.low ≤ x และ x ≤ ตัวฉัน.high
}
ฟังก์ชัน center() → f64 {
คืน (ตัวฉัน.low + ตัวฉัน.high) ÷ 2.0
}
}
ฟังก์ชัน choose<T>(ตรรกะ first, T a, T b) → T {
คืน first ✓ a ✗ b
}
เริ่ม {
คงที่ Span bytes ← Span { low = 0.0, high = 255.0 }
บันทึก bytes.center()
บันทึก choose(bytes.contains(300.0), "inside", "outside")
บันทึก -7 / 2
}faber convert --to zh-Hans — Simplified Chinese类 Span {
常量 f64 low
常量 f64 high
函数 contains(f64 x) → 布尔 {
返回 自身.low ≤ x 且 x ≤ 自身.high
}
函数 center() → f64 {
返回 (自身.low + 自身.high) ÷ 2.0
}
}
函数 choose<T>(布尔 first, T a, T b) → T {
返回 first ✓ a ✗ b
}
入口 {
常量 Span bytes ← Span { low = 0.0, high = 255.0 }
显示 bytes.center()
显示 choose(bytes.contains(300.0), "inside", "outside")
显示 -7 / 2
}faber convert --to zh-Hant — Traditional Chinese類型 Span {
定值 f64 low
定值 f64 high
函式 contains(f64 x) → 布林 {
傳回 自身.low ≤ x 且 x ≤ 自身.high
}
函式 center() → f64 {
傳回 (自身.low + 自身.high) ÷ 2.0
}
}
函式 choose<T>(布林 first, T a, T b) → T {
傳回 first ✓ a ✗ b
}
入口 {
定值 Span bytes ← Span { low = 0.0, high = 255.0 }
註記 bytes.center()
註記 choose(bytes.contains(300.0), "inside", "outside")
註記 -7 / 2
}faber convert --to vi — Vietnamesekiểu Span {
hằng f64 low
hằng f64 high
hàm contains(f64 x) → logic {
trả tôi.low ≤ x và x ≤ tôi.high
}
hàm center() → f64 {
trả (tôi.low + tôi.high) ÷ 2.0
}
}
hàm choose<T>(logic first, T a, T b) → T {
trả first ✓ a ✗ b
}
bắt_đầu {
hằng Span bytes ← Span { low = 0.0, high = 255.0 }
ghi_chú bytes.center()
ghi_chú choose(bytes.contains(300.0), "inside", "outside")
ghi_chú -7 / 2
}faber convert --to ar — Arabic — right-to-left, bidi isolatedصنف Span {
ثابت f64 low
ثابت f64 high
دالة contains(f64 x) → منطقي {
أعد ذات.low ≤ x و x ≤ ذات.high
}
دالة center() → f64 {
أعد (ذات.low + ذات.high) ÷ 2.0
}
}
دالة choose<T>(منطقي first, T a, T b) → T {
أعد first ✓ a ✗ b
}
بداية {
ثابت Span bytes ← Span { low = 0.0, high = 255.0 }
اعرض bytes.center()
اعرض choose(bytes.contains(300.0), "inside", "outside")
اعرض -7 / 2
}faber convert --to hi — Hindi — Devanagariवर्ग Span {
स्थिर f64 low
स्थिर f64 high
फलन contains(f64 x) → तार्किक {
लौटाओ मैं.low ≤ x और x ≤ मैं.high
}
फलन center() → f64 {
लौटाओ (मैं.low + मैं.high) ÷ 2.0
}
}
फलन choose<T>(तार्किक first, T a, T b) → T {
लौटाओ first ✓ a ✗ b
}
आरंभ {
स्थिर Span bytes ← Span { low = 0.0, high = 255.0 }
दिखाओ bytes.center()
दिखाओ choose(bytes.contains(300.0), "inside", "outside")
दिखाओ -7 / 2
}$ faber run
127.5
outside
-4
One program, eight readings. Every tab is the compiler’s own rendering
(faber convert), and each one runs. Keywords, types and
diagnostics change; identifiers and string literals do not.
Reader locales
People should not need English to use a model for code, or to read what the model wrote. Each language has its own documentation home, written in that language. Source is written the same way: one reader locale per file, sealed against the others, so a Thai file contains Thai keywords and nothing else.
Latin is the canonical interchange form the language is named for. Reader locales also localize compiler diagnostics. See all languages · How reader locales work
Why Faber
A model writes best against a surface with few surprises. Faber keeps the rules small, regular and explicit, then shows the result in the reader’s language.
258 grammar productions, generated and checked as the parser’s
authority. One construct has one spelling. Arrows mean runtime effects
(← assign, → return, ⇥ error channel);
= and : only state compile-time facts.
Read the grammar
Declarations are type-first: f64 low, never low: f64.
Nullability is written T ∪ none. Generics are written out
(fn choose<T>), and crossing between integer and float is
an explicit ↦, not an accident.
Types and values
Integer / floors, so -7 / 2 is -4; true
division is ÷. Comparisons read as math (≤ ≥ ≠ ≈),
and tensor work has its own operators (· matmul,
⊙ elementwise). When math and hardware convention disagree,
Faber follows the math.
Glyphs and Latin
Diagnostics are coded and explainable. The documentation ships an agent index and focused skill guides at fixed paths, so a model can learn the language from the site itself. /llms.txt
Cross-compile
Faber compiles through one analyzed program to many targets. Write a
library in Faber, emit it in the language your project already uses, and
add it alongside your existing code. This small library, with no
generics and no main, is emitted below exactly as
radix emit produces it, and each panel was checked in its
own toolchain.
@ public
class Span {
const f64 low
const f64 high
fn contains(f64 x) → bool {
return self.low ≤ x and x ≤ self.high
}
fn center() → f64 {
return (self.low + self.high) ÷ 2.0
}
}
radix emit --target rust span.fab — builds as a Cargo package with faber build; uses the small faber runtime crate// … 9 lines of generated header and runtime shim elided …
#[derive(Clone, PartialEq)]
pub struct Span {
pub low: f64,
pub high: f64,
}
impl ::core::fmt::Debug for Span {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
write!(f, "Span {{ low = {}, high = {} }}", faber::display_fractus(*&self.low), faber::display_fractus(*&self.high))
}
}
impl Span {
pub fn contains(&self, x: f64) -> bool {
self.low <= x && x <= self.high
}
pub fn center(&self) -> f64 {
(self.low + self.high) / 2.0
}
}radix emit --target ts span.fab — a source file you add to your project; imports @faber/runtime// … 14 lines of generated header and runtime shim elided …
class Span {
low!: number;
high!: number;
toString(): string {
return "Span { low = " + __faberDisplay(this.low, "fractus") + ", high = " + __faberDisplay(this.high, "fractus") + " }";
}
contains(x: number): boolean {
return ((this.low <= x) && (x <= this.high));
}
center(): number {
return ((this.low + this.high) / 2);
}
}radix emit --target go span.fab — a source file in package main// Generated by radix - do not edit
package main
type Span struct {
Low float64
High float64
}
func (self *Span) Contains(x float64) bool {
_ = self
return ((float64(self.Low) <= float64(x)) && (float64(x) <= float64(self.High)))
}
func (self *Span) Center() float64 {
_ = self
return float64(((self.Low + self.High) / 2.0))
}radix emit --target swift span.fab — a source file; no runtime dependency// Generated by radix - do not edit
class Span {
var low: Double
var high: Double
init(low: Double, high: Double) {
self.low = low
self.high = high
}
func contains(x: Double) -> Bool {
return ((self.low <= x) && (x <= self.high))
}
func center() -> Double {
return ((self.low + self.high) / 2.0)
}
}
extension Span: CustomStringConvertible {
var description: String { return "Span { low = \(String(describing: self.low)), high = \(String(describing: self.high)) }" }
}Rust builds as a Cargo package today. TypeScript, Go and Swift give you source files to add to your project; assembling them into installable packages is not built yet. Support is stated target by target: generics and some operators do not lower to every target, and the target matrix records where. Read the target matrix
| Target | Emits | Package | Runs | In practice |
|---|---|---|---|---|
| Source for your existing project | ||||
| Rust | yes | yes | yes | The primary target: a full Cargo package, and runnable through faber. |
| TypeScript | yes | — | — | Source emission; package assembly is not built yet. |
| Go | yes | — | — | Source emission; package assembly is not built yet. |
| Swift | yes | — | — | Source emission; a subset. |
| Python | yes | — | — | Source emission; a limited subset. |
| Haskell | yes | — | — | Source emission; a limited subset. |
| Systems, native and device | ||||
| Native executable | yes | yes | yes | MIR lowered to LLVM, linked for the local host. |
| WebAssembly | yes | — | — | WAT text; binary conversion uses external tools. |
| LLVM IR | yes | yes | yes | Text for LLVM tooling; also the CUDA device route. |
| Metal | yes | yes | yes | Shader source; device execution through the Metal route. |
| WGSL | yes | — | — | WebGPU compute shader source. |
| Portable package images | ||||
| FHIR | yes | yes | yes | A portable analyzed-program package envelope. |
| FMIR | yes | yes | yes | A source-independent package image that faber can run. |
Libraries
The libraries are ordinary Faber source. They show what the language is for, and each one can be read, changed and emitted like your own code. Status is stated plainly.
norma:*.
Gradus
autograd and ML
Automatic differentiation, losses, optimizers and neural-network primitives. Models are pure functions; the backward pass is compiler-generated code.
Triga
graphics and geometry
Scene graph, materials and geometry modeled on three.js shapes, written as a small, readable Faber library.
Tela
early; UI and view protocol
Typed HTML and SVG view values with fail-closed validation and deterministic HTML and CSS output. The static renderer comes first.
Inferentia
in development
A local-first GGUF inference server written in Faber. Today it is a command-line shell; model loading and HTTP serving are the next stages.
Cista
package store
The package manager: install, resolve, inspect and cache Faber packages, independent of the compiler.
triga-budapest
triga:geometriaExample scenes built with Triga.
Grammar
The language is specified as 258 productions in a single EBNF, generated from one source and published in full. It is large enough to be expressive and regular enough to hold in your head or a model’s context. The reference pages are generated from the same source, so they cannot disagree with the parser.
Compute
The same language carries numeric and device work. Tensor operators and
@ nucleum kernels lower to WGSL, Metal and CUDA routes, and
Gradus uses them for
autograd. Device execution is explicit and fail-closed: a requested
backend never silently falls back to CPU. Bounded training runs on
accepted Metal and CUDA machines; device inference is not shipped.
Doors
For models
Machine surfaces are locale-less and live at the root:
/install.md to install,
/llms.txt for the index,
/agents/index.md for the
learning path, and
/.well-known/agent-skills/
for focused skill guides.