Skip to content

Hello! 👋 My name is Nathan Weir. This is a fun personal project for using AI to build a bespoke, domain-specific programming language. It is not a serious, professional project. This site and the language itself are largely generated via Claude Code. If you find yourself programming with Weir, have fun - but use at your own risk!

Rust Integration

Weir’s compiler, runtime, and standard library are all implemented in Rust. This page explains how Rust code powers the language and how safe Rust functions are exposed to Weir programs.

Weir has two distinct layers for calling non-Weir code:

LayerSafetyMechanismExample
Rust runtimeSafeLinked at compile timeprintln, str, len, sqrt
C FFIunsafe requiredextern "C" + dlsym/linkerSDL_Init, abs, glfw*

The vast majority of “built-in” functions in Weir are actually Rust functions compiled into the runtime. They don’t require unsafe because the Rust compiler already enforces safety on that side.

Built-in functions like println, sqrt, len, and append are implemented in Rust across two crates:

The runtime crate provides core services:

  • Garbage collectorweir_gc_alloc, weir_gc_collect, root tracking
  • Arena allocatorweir_arena_alloc, bulk deallocation
  • String operations — allocation, concatenation, conversion
  • Vector operations — allocation, indexing, append
  • I/O — print, file read/write
  • Math — wrappers around libm functions

These are exported as extern "C" functions from Rust (so Cranelift can call them), but they’re safe Rust internally:

// In weir-runtime — safe Rust, exported for Cranelift
#[no_mangle]
pub extern "C" fn weir_println(val: i64) {
// Safe Rust implementation
println!("{}", format_value(val));
}

The interpreter implements the same built-ins as native Rust functions called directly during tree-walking evaluation:

// In weir-interp
fn builtin_println(args: &[Value]) -> Result<Value, InterpError> {
// Direct Rust implementation
println!("{}", args[0].display());
Ok(Value::Unit)
}

Every stage of the compiler is a Rust crate:

CratePurpose
weir-lexerTokenizer
weir-parserS-expression parser
weir-astAST types, pretty printing, TCO analysis
weir-macrosMacro expander
weir-typeckType checker with local inference
weir-codegenCranelift JIT/AOT backend
weir-interpTree-walking interpreter
weir-runtimeGC, arenas, runtime support
weir-pkgPackage system
weir-lspLanguage Server Protocol
weir-cliCLI frontend (clap)

The strongest argument for Rust is Cranelift — a Rust-native code generation library designed for fast runtime code generation. Cranelift prioritizes compilation speed over maximum optimization, which is exactly right for dev-mode live reloading.

Additional benefits:

  • Parser, type checker, LSP — benefit enormously from Rust’s type system and ownership model
  • Memory safety — the runtime core requires unsafe for executable memory management, but the majority of the codebase is safe
  • Ecosystemclap for CLI, tokio for async LSP, cranelift for codegen, libffi for interpreter FFI

Adding a new built-in function to Weir requires changes in three places:

  1. weir-typeck — register the function name and type signature in check_builtin_call
  2. weir-interp — implement the function in register_builtins
  3. weir-codegen — either emit inline Cranelift IR or call a weir-runtime C-exported function

The type checker, interpreter, and codegen must all agree on the function’s behavior and type signature.