Faber

Multilingual semantic programming for application code and GPU work · MIT

Write compute programs
in the language you think in.

One typed program stays readable in the language you work in, then lowers toward application targets and a measured GPU path. Support is stated target by target.

The language, public libraries (including Gradus), 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.

See the language Gradus is the large open MIT autograd and ML library, with a structural inference surface. This is a short English program.
import from "gradus:loss" loss

main {
    const tensor<f32, []> seed ← empty
    const list<int> shape_2x2 ← [2, 2]
    const tensor<f32, [2, 2]> prediction ← seed.from_flat([1.0, 2.0, 3.0, 4.0], shape_2x2)
    const tensor<f32, [2, 2]> target ← seed.from_flat([1.0, 2.0, 3.0, 3.0], shape_2x2)
    const f32 value ← loss.mse_2x2(prediction, target)
    print value
}
Try it Install and a five-minute tour of the language. For agents Machine index at /llms.txt.

Readable in your language. Same meaning.

Faber’s reader locales change keywords, types, and diagnostics without changing program meaning. This example constructs two typed matrices, multiplies them, and reduces the product to a scalar. Pick a tab and that same compute program remains the same program. Identifiers and string literals stay intact, so teams can review durable code across language surfaces without a translation service in the middle.

main.fab · reader locale
faber convert --to en — English reader surface — the base spelling for everyday source
main {
    const tensor<f32, [2, 3]> a ← empty
    const tensor<f32, [3, 4]> b ← empty
    const tensor<f32, [2, 4]> product ← a · b
    print product
}
faber convert --to la — canonical Faber — the classical surface the language is named for
incipit {
    fixum tensor<f32, [2, 3]> a ← vacua
    fixum tensor<f32, [3, 4]> b ← vacua
    fixum tensor<f32, [2, 4]> product ← a · b
    nota product
}
faber convert --to th-TH — Thai — spaceless script
เริ่ม {
    คงที่ เทนเซอร์<f32, [2, 3]> a ← เซตว่าง
    คงที่ เทนเซอร์<f32, [3, 4]> b ← เซตว่าง
    คงที่ เทนเซอร์<f32, [2, 4]> product ← a · b
    บันทึก product
}
faber convert --to zh-Hans — Simplified Chinese
入口 {
    常量 张量<f32, [2, 3]> a ← 空集
    常量 张量<f32, [3, 4]> b ← 空集
    常量 张量<f32, [2, 4]> product ← a · b
    显示 product
}
faber convert --to zh-Hant — Traditional Chinese
入口 {
    定值 張量<f32, [2, 3]> a ← 空集
    定值 張量<f32, [3, 4]> b ← 空集
    定值 張量<f32, [2, 4]> product ← a · b
    註記 product
}
faber convert --to vi — Vietnamese
bắt_đầu {
    hằng ten_xo<f32, [2, 3]> a ← tập_rỗng
    hằng ten_xo<f32, [3, 4]> b ← tập_rỗng
    hằng ten_xo<f32, [2, 4]> product ← a · b
    ghi_chú product
}
faber convert --to ar — Arabic — right-to-left, bidi isolated
بداية {
    ثابت موتر<f32, [2, 3]> a ← فارغ
    ثابت موتر<f32, [3, 4]> b ← فارغ
    ثابت موتر<f32, [2, 4]> product ← a · b
    اعرض product
}
faber convert --to hi — Hindi — Devanagari
आरंभ {
    स्थिर टेंसर<f32, [2, 3]> a ← खाली
    स्थिर टेंसर<f32, [3, 4]> b ← खाली
    स्थिर टेंसर<f32, [2, 4]> product ← a · b
    दिखाओ product
}
$ faber run --interpret <package>
76.25

A reviewer sets their locale once. This is the compiler’s own rendering, so the program you approve is the program that ships.

One semantic program for applications and GPU work

The same analyzed program can feed application targets or a device program. Every target is a projection of HIR/MIR meaning — support is stated target by target. The target matrix is the source of truth, not a promise that every backend behaves the same way.

Every panel below is literal radix emit output. The matrix records where a target emits, validates, runs, or remains limited. See target matrix for the current boundary.

main.fab → target
radix emit --target rust main.fab — HIR projection — reviewable source; package product path via Cargo
// Generated by radix - do not edit
// Requires the faber language-runtime crate (add to Cargo.toml):
//   faber = { path = "../faber" }  # adjust path for your layout

fn main() {
    let a: faber::Tensor<f32> /* tensor<fractus<f32>, [2, 3]> */ = faber::Tensor::vacua();
    let b: faber::Tensor<f32> /* tensor<fractus<f32>, [3, 4]> */ = faber::Tensor::vacua();
    let product: faber::Tensor<f32> /* tensor<fractus<f32>, [2, 4]> */ = { let t6 = &a; t6.matmul(&(b)) }.expect("tensor matmul failed");
    println!("{:?}", product);
}
radix emit --target go main.fab — HIR projection — file emission + e2e floors
// Generated by radix - do not edit

package main

import "fmt"

type faberTensor[T any] struct {
    data []T
    shape []int
}

func faberTensorElementCount(shape []int) int {
    const maxInt = int(^uint(0) >> 1)
    total := 1
    for _, dim := range shape {
        if dim < 0 { panic("tensor shape dimension must be non-negative") }
        if dim > 0 && total > maxInt/dim { panic("tensor shape element count overflow") }
        total *= dim
    }
    return total
}

func faberIndexSlice(indices any) []int {
    switch values := indices.(type) {
        case []int:
            return append([]int{}, values...)
        case []uint32:
            out := make([]int, len(values)); for i, value := range values { out[i] = int(value) }; return out
        case []uint64:
            out := make([]int, len(values)); for i, value := range values { out[i] = int(value) }; return out
        case []int32:
            out := make([]int, len(values)); for i, value := range values { out[i] = int(value) }; return out
        case []int64:
            out := make([]int, len(values)); for i, value := range values { out[i] = int(value) }; return out
        default:
            panic("tensor index must be a numeric list")
    }
}

func faberTensorOffset(shape []int, rawIndices any) *int {
    const maxInt = int(^uint(0) >> 1)
    indices := faberIndexSlice(rawIndices)
    if len(indices) != len(shape) { return nil }
    offset := 0
    stride := 1
    for axis := len(shape) - 1; axis >= 0; axis-- {
        idx := indices[axis]
        dim := shape[axis]
        if dim < 0 || idx < 0 || idx >= dim { return nil }
        if idx > 0 && stride > (maxInt-offset)/idx { return nil }
        offset += idx * stride
        if dim > 0 && stride > maxInt/dim { return nil }
        stride *= dim
    }
    return &offset
}

func (t faberTensor[T]) Crea(fill T, shape []int) faberTensor[T] {
    data := make([]T, faberTensorElementCount(shape))
    for i := range data { data[i] = fill }
    return faberTensor[T]{data: data, shape: append([]int{}, shape...)}
}

func (t faberTensor[T]) Strue(data []T, shape []int) faberTensor[T] {
    if faberTensorElementCount(shape) != len(data) { panic("tensor structa element count does not match shape") }
    return faberTensor[T]{data: append([]T{}, data...), shape: append([]int{}, shape...)}
}

func (t faberTensor[T]) Longitudo() int { return len(t.shape) }
func (t faberTensor[T]) Magnitudines() []int { return append([]int{}, t.shape...) }
func (t faberTensor[T]) Planata() []T { return append([]T{}, t.data...) }
func (t faberTensor[T]) Materialize() faberTensor[T] { return faberTensor[T]{data: append([]T{}, t.data...), shape: append([]int{}, t.shape...)} }

func faberTensorAdd[T any](left T, right T) T {
    switch value := any(left).(type) {
        case int: return any(value + any(right).(int)).(T)
        case int32: return any(value + any(right).(int32)).(T)
        case int64: return any(value + any(right).(int64)).(T)
        case uint: return any(value + any(right).(uint)).(T)
        case uint32: return any(value + any(right).(uint32)).(T)
        case uint64: return any(value + any(right).(uint64)).(T)
        case float32: return any(value + any(right).(float32)).(T)
        case float64: return any(value + any(right).(float64)).(T)
        default: panic("tensor arithmetic requires numeric elements")
    }
}

func faberTensorMul[T any](left T, right T) T {
    switch value := any(left).(type) {
        case int: return any(value * any(right).(int)).(T)
        case int32: return any(value * any(right).(int32)).(T)
        case int64: return any(value * any(right).(int64)).(T)
        case uint: return any(value * any(right).(uint)).(T)
        case uint32: return any(value * any(right).(uint32)).(T)
        case uint64: return any(value * any(right).(uint64)).(T)
        case float32: return any(value * any(right).(float32)).(T)
        case float64: return any(value * any(right).(float64)).(T)
        default: panic("tensor arithmetic requires numeric elements")
    }
}

func faberTensorSub[T any](left T, right T) T {
    switch value := any(left).(type) {
        case int: return any(value - any(right).(int)).(T)
        case int32: return any(value - any(right).(int32)).(T)
        case int64: return any(value - any(right).(int64)).(T)
        case uint: return any(value - any(right).(uint)).(T)
        case uint32: return any(value - any(right).(uint32)).(T)
        case uint64: return any(value - any(right).(uint64)).(T)
        case float32: return any(value - any(right).(float32)).(T)
        case float64: return any(value - any(right).(float64)).(T)
        default: panic("tensor arithmetic requires numeric elements")
    }
}

func faberTensorShapeEqual(left []int, right []int) bool {
    if len(left) != len(right) { return false }
    for i, dim := range left { if dim != right[i] { return false } }
    return true
}

func faberTensorMean[T any](data []T) T {
    if len(data) == 0 { panic("tensor media requires non-empty data") }
    switch any(data[0]).(type) {
        case float32:
            var total float32
            for _, value := range data { total += any(value).(float32) }
            return any(total / float32(len(data))).(T)
        case float64:
            var total float64
            for _, value := range data { total += any(value).(float64) }
            return any(total / float64(len(data))).(T)
        default: panic("tensor media requires floating-point elements")
    }
}

func (t faberTensor[T]) Summa() T {
    var total T
    for _, value := range t.data { total = faberTensorAdd(total, value) }
    return total
}

func (t faberTensor[T]) Media() T { return faberTensorMean(t.data) }

func (a faberTensor[T]) Addita(b faberTensor[T]) faberTensor[T] {
    if !faberTensorShapeEqual(a.shape, b.shape) { panic("tensor elementwise arithmetic requires equal shapes") }
    data := make([]T, len(a.data))
    for i := range data { data[i] = faberTensorAdd(a.data[i], b.data[i]) }
    return faberTensor[T]{data: data, shape: append([]int{}, a.shape...)}
}

func (a faberTensor[T]) Subtrahe(b faberTensor[T]) faberTensor[T] {
    if !faberTensorShapeEqual(a.shape, b.shape) { panic("tensor elementwise arithmetic requires equal shapes") }
    data := make([]T, len(a.data))
    for i := range data { data[i] = faberTensorSub(a.data[i], b.data[i]) }
    return faberTensor[T]{data: data, shape: append([]int{}, a.shape...)}
}

func (a faberTensor[T]) Multiplica(b faberTensor[T]) faberTensor[T] {
    if !faberTensorShapeEqual(a.shape, b.shape) { panic("tensor elementwise arithmetic requires equal shapes") }
    data := make([]T, len(a.data))
    for i := range data { data[i] = faberTensorMul(a.data[i], b.data[i]) }
    return faberTensor[T]{data: data, shape: append([]int{}, a.shape...)}
}

func (a faberTensor[T]) Matmul(b faberTensor[T]) faberTensor[T] {
    if len(a.shape) != 2 || len(b.shape) != 2 || a.shape[1] != b.shape[0] { panic("tensor matmul requires compatible rank-2 shapes") }
    rows, inner, cols := a.shape[0], a.shape[1], b.shape[1]
    data := make([]T, rows*cols)
    for row := 0; row < rows; row++ {
        for col := 0; col < cols; col++ {
            var sum T
            for k := 0; k < inner; k++ { sum = faberTensorAdd(sum, faberTensorMul(a.data[row*inner+k], b.data[k*cols+col])) }
            data[row*cols+col] = sum
        }
    }
    return faberTensor[T]{data: data, shape: []int{rows, cols}}
}

func (t faberTensor[T]) Forma(shape []int) faberTensor[T] {
    if faberTensorElementCount(shape) != len(t.data) { panic("tensor forma (reshape) element count mismatch") }
    return faberTensor[T]{data: append([]T{}, t.data...), shape: append([]int{}, shape...)}
}

func (t faberTensor[T]) Accipe(indices any) *T {
    offset := faberTensorOffset(t.shape, indices)
    if offset == nil || *offset < 0 || *offset >= len(t.data) { return nil }
    return &t.data[*offset]
}

func (t *faberTensor[T]) Ponde(indices any, value T) {
    offset := faberTensorOffset(t.shape, indices)
    if offset == nil || *offset < 0 || *offset >= len(t.data) { panic("tensor ponde invalid index") }
    t.data[*offset] = value
}

func (t *faberTensor[T]) Reple(value T) {
    for i := range t.data { t.data[i] = value }
}

func (t faberTensor[T]) Sectio(start int, end int) faberTensor[T] {
    if len(t.shape) == 0 || start < 0 || end < start || end > t.shape[0] { panic("tensor sectio invalid slice bounds") }
    inner := faberTensorElementCount(t.shape[1:])
    shape := append([]int{end - start}, t.shape[1:]...)
    return faberTensor[T]{data: append([]T{}, t.data[start*inner:end*inner]...), shape: shape}
}

func main() {
    a := faberTensor[float32]{}.Crea(*new(float32), []int{2, 3})
    b := faberTensor[float32]{}.Crea(*new(float32), []int{3, 4})
    product := a.Matmul(b)
    fmt.Println(product)
}
radix emit --target ts main.fab — HIR projection — file emission + e2e floors
// … 242 lines of generated display/runtime shim elided …

        const a: FaberTensor<number> = FaberTensor.empty<number>([2, 3]);
        const b: FaberTensor<number> = FaberTensor.empty<number>([3, 4]);
        const product: FaberTensor<number> = a.matmul(b);
        console.log(__faberDisplay(product, { kind: "tensor", element: "fractus" }));
    }})();
radix emit --target llvm-text main.fab — MIR staging text for external LLVM tools — not embedded native codegen
; Generated by radix MIR LLVM IR probe - experimental artifact.
%FaberRtSliceV1 = type { ptr, i64 }
%FaberRtExitV1 = type i64
%FaberRtPtrResultV1 = type { i32, ptr }
%FaberRtStatusV1 = type { i32 }
@__faber_rt_v1_context = linkonce_odr global ptr null
@__faber_rt_v1_status = linkonce_odr global i32 0
declare void @__faber_rt_v1_fatal(ptr, %FaberRtSliceV1) noreturn
declare void @__faber_rt_v1_numerus_overflow(ptr) noreturn


; @runtime __faber_rt_v1_diagnostic_nota_ptr category=host-integration
declare i32 @__faber_rt_v1_diagnostic_nota_ptr(ptr, ptr)
; @runtime __faber_rt_v1_tensor_matmul category=core-semantics
declare %FaberRtPtrResultV1 @__faber_rt_v1_tensor_matmul(ptr, ptr, ptr)
; @runtime __faber_rt_v1_tensor_new category=core-semantics
declare %FaberRtPtrResultV1 @__faber_rt_v1_tensor_new(ptr, i32)

define void @incipit() {
    entry:
      %l0.addr = alloca ptr
      %l1.addr = alloca ptr
      %l2.addr = alloca ptr
      %t0.addr = alloca ptr
      %t1.addr = alloca ptr
      %t2.addr = alloca ptr
      br label %b0
    b0:
      %faber.context0 = load ptr, ptr @__faber_rt_v1_context
      %faber.tensor.result0 = call %FaberRtPtrResultV1 @__faber_rt_v1_tensor_new(ptr %faber.context0, i32 5)
      %faber.tensor.status0 = extractvalue %FaberRtPtrResultV1 %faber.tensor.result0, 0
      %faber.tensor.value0 = extractvalue %FaberRtPtrResultV1 %faber.tensor.result0, 1
      %faber.old.status0 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error0 = icmp ne i32 %faber.old.status0, 0
      %faber.latched.status0 = select i1 %faber.has.error0, i32 %faber.old.status0, i32 %faber.tensor.status0
      store i32 %faber.latched.status0, ptr @__faber_rt_v1_status
      store ptr %faber.tensor.value0, ptr %t0.addr
      %load1 = load ptr, ptr %t0.addr
      store ptr %load1, ptr %l0.addr
      %faber.context2 = load ptr, ptr @__faber_rt_v1_context
      %faber.tensor.result2 = call %FaberRtPtrResultV1 @__faber_rt_v1_tensor_new(ptr %faber.context2, i32 5)
      %faber.tensor.status2 = extractvalue %FaberRtPtrResultV1 %faber.tensor.result2, 0
      %faber.tensor.value2 = extractvalue %FaberRtPtrResultV1 %faber.tensor.result2, 1
      %faber.old.status2 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error2 = icmp ne i32 %faber.old.status2, 0
      %faber.latched.status2 = select i1 %faber.has.error2, i32 %faber.old.status2, i32 %faber.tensor.status2
      store i32 %faber.latched.status2, ptr @__faber_rt_v1_status
      store ptr %faber.tensor.value2, ptr %t1.addr
      %load3 = load ptr, ptr %t1.addr
      store ptr %load3, ptr %l1.addr
      %load5 = load ptr, ptr %l0.addr
      %faber.context4 = load ptr, ptr @__faber_rt_v1_context
      %load6 = load ptr, ptr %l1.addr
      %faber.tensor.result4 = call %FaberRtPtrResultV1 @__faber_rt_v1_tensor_matmul(ptr %faber.context4, ptr %load5, ptr %load6)
      %faber.tensor.status4 = extractvalue %FaberRtPtrResultV1 %faber.tensor.result4, 0
      %faber.tensor.value4 = extractvalue %FaberRtPtrResultV1 %faber.tensor.result4, 1
      %faber.old.status4 = load i32, ptr @__faber_rt_v1_status
      %faber.has.error4 = icmp ne i32 %faber.old.status4, 0
      %faber.latched.status4 = select i1 %faber.has.error4, i32 %faber.old.status4, i32 %faber.tensor.status4
      store i32 %faber.latched.status4, ptr @__faber_rt_v1_status
      store ptr %faber.tensor.value4, ptr %t2.addr
      %load7 = load ptr, ptr %t2.addr
      store ptr %load7, ptr %l2.addr
      %faber.context8 = load ptr, ptr @__faber_rt_v1_context
      %faber.diag.status8 = call i32 @__faber_rt_v1_diagnostic_nota_ptr(ptr %faber.context8, ptr null)
      ret void
}

define %FaberRtExitV1 @__faber_program_entry_v1(ptr %context) {
    entry:
      store ptr %context, ptr @__faber_rt_v1_context
      call void @incipit()
      %faber.entry.status = load i32, ptr @__faber_rt_v1_status
      %faber.entry.status.ext = zext i32 %faber.entry.status to i64
      %faber.entry.shifted = shl i64 %faber.entry.status.ext, 32
      %faber.entry.packed = or i64 0, %faber.entry.shifted
      ret %FaberRtExitV1 %faber.entry.packed
}

Compiler lanes

LaneTargets / outputs
Localeen (base surface) · la (canonical classical) · th-TH · zh-Hans · zh-Hant · ar · vi · hi
HIRRust · Faber · TypeScript · Go · Swift
AIR (autograd)Typed HIR → reverse-mode AD / fusion → MIR
MIRLLVM · WASM · WGSL · S-expression · FMIR
GPUMetal · CUDA
PackagingFHIR · FMIR

Training through Metal or CUDA

The ordinary faber run --backend metal|cuda route executes a bounded device-program subset on accepted Metal and CUDA machines. The accepted dual-backend MLP training path runs device-resident forward, AIR-generated backward, and optimizer update steps with gradient mapping and per-element numeric comparison against a pinned CPU oracle.

$ faber run --backend metal <package>
$ faber run --backend cuda  <package>

This is a bounded training proof, not a claim of a general training framework, broad hardware coverage, or a released package surface. Device execution is explicit and fail-closed: a requested backend does not silently fall back to CPU.

Read the device execution contract · Open the training proof

One kernel, backend-specific output

A function marked @ nucleum is a compute kernel. The source stays small while Faber emits backend-specific shader code. These panels show the lowering surface; the real-device route above is the narrower product proof.

@ nucleum
functio multiplico(tf32[16, 8] a, tf32[8, 16] b, tf32[16, 16] out, u32 id) → vacuum {
    fixum tf32[16, 16] c ← a.matmul(b)
}
kernel.fab → GPU
radix emit --target wgsl-text kernel.fab — WebGPU compute shader
// Generated by radix wgsl-text (supported-with-limitations compute source).

var<workgroup> shared_a: array<f32, 64u>;
var<workgroup> shared_b: array<f32, 64u>;

@group(0) @binding(0) var<storage, read> a_in: array<f32>;
@group(0) @binding(1) var<storage, read> b_in: array<f32>;
@group(0) @binding(2) var<storage, read_write> output: array<f32>;

@compute @workgroup_size(8, 8, 1)
fn multiplico(@builtin(global_invocation_id) id: vec3<u32>, @builtin(local_invocation_id) local_id: vec3<u32>) {
  let i: u32 = id.x;
var acc: f32 = 0.0;
let row = id.y;
let col = id.x;
let ty = local_id.y;
let tx = local_id.x;
for (var k_tile: u32 = 0u; k_tile < 1u; k_tile++) {
    let k_start = k_tile * 8u;
    let a_idx = row * 8u + (k_start + tx);
    if (a_idx < 16u * 8u) { shared_a[ty * 8u + tx] = a_in[a_idx]; }
    if (a_idx >= 16u * 8u) { shared_a[ty * 8u + tx] = 0.0; }
    let b_idx = col * 8u + (k_start + ty);
    if (col < 16u && (k_start + ty) < 8u) { shared_b[ty * 8u + tx] = b_in[b_idx]; }
    if (col >= 16u || (k_start + ty) >= 8u) { shared_b[ty * 8u + tx] = 0.0; }
    workgroupBarrier();
    for (var kk: u32 = 0u; kk < 8u; kk++) {
        acc += shared_a[ty * 8u + kk] * shared_b[kk * 8u + tx];
    }
    workgroupBarrier();
}
let out_idx = row * 16u + col;
if (row < 16u && col < 16u) { output[out_idx] = acc; }
}
radix emit --target metal-text kernel.fab — Apple GPU compute shader
// Generated by radix metal-text (supported-with-limitations compute source).
#include <metal_stdlib>
using namespace metal;

kernel void multiplico(
    device const float* a_in [[buffer(0)]],
    device const float* b_in [[buffer(1)]],
    device float* output [[buffer(2)]],
    uint3 id [[thread_position_in_grid]],
    uint3 local_id [[thread_position_in_threadgroup]]
) {
    uint i = id.x;
threadgroup float shared_a[64];
threadgroup float shared_b[64];
float acc = 0.0;
uint row = id.y;
uint col = id.x;
uint ty = local_id.y;
uint tx = local_id.x;
for (uint k_tile = 0u; k_tile < 1u; k_tile++) {
    uint k_start = k_tile * 8u;
    uint a_idx = row * 8u + (k_start + tx);
    if (a_idx < 16u * 8u) { shared_a[ty * 8u + tx] = a_in[a_idx]; }
    if (a_idx >= 16u * 8u) { shared_a[ty * 8u + tx] = 0.0; }
    uint b_idx = col * 8u + (k_start + ty);
    if (col < 16u && (k_start + ty) < 8u) { shared_b[ty * 8u + tx] = b_in[b_idx]; }
    if (col >= 16u || (k_start + ty) >= 8u) { shared_b[ty * 8u + tx] = 0.0; }
    threadgroup_barrier(mem_flags::mem_threadgroup);
    for (uint kk = 0u; kk < 8u; kk++) {
        acc += shared_a[ty * 8u + kk] * shared_b[kk * 8u + tx];
    }
    threadgroup_barrier(mem_flags::mem_threadgroup);
}
uint out_idx = row * 16u + col;
if (row < 16u && col < 16u) { output[out_idx] = acc; }
}

Inference is being built next

Faber-owned GPU inference is in active development behind a pinned model contract and a correctness oracle. The CPU oracle track (admission, dequant, decoder ops, greedy decode agreement) is engineering-real; end-to-end device inference is not shipped, and this is not a broad GGUF product claim.

Follow the AI and GPU examples while the persistent inference path is built.

Build the rest of the application around it

Triga is a graphics and geometry engine written in Faber. These frames are supporting evidence that the same language can carry application and GPU-shaped work — not a replacement for the training and inference path above.

A low-poly 3D scene of a bridge with towers and lamp posts over water, rendered by Triga
Scene graph, materials, lighting — triga-budapest
A procedurally generated 3D terrain with lakes and hills, rendered by Triga
Procedural heightmap terrain, biome shading
Eight primitive 3D shapes — cylinder, cone, cube, torus, plane and others — rendered by Triga
Primitive geometry set from triga:geometria

Fast enough to use like a script

Faber also runs with no build step. faber run --interpret takes source through parse, typecheck and MIR lowering, then steps the MIR in-process — no rustc, no linker, no build directory.

Same program, end to end, median of 15 runs (M-series Mac)
CommandWall clock
faber run --interpret (incl. full typecheck)4.4 ms
python3 script.py (no typecheck)13.3 ms

Reproduce with the scripting docs. A statically typed language should not be slower to start than a dynamic one, and it isn't.

Where to go

Reading this as a model?

Machine surfaces are locale-less and live at the root: /llms.txt for the index, /agents/index.md for the learning path, and /.well-known/agent-skills/ for focused skill guides.