langkit 1.0.0

A builder library for creating programming languages in Rust
Documentation

langkit

crates.io docs.rs CI License

Langkit is a Rust builder library for creating programming languages with a simple, high level API. The goal is to let you build a usable language with minimal boilerplate while keeping control when you need it.

Status

Version 1.0.0 is released. The public API is stable and follows semver.

Highlights

  • Built in module packs via lang.lib("base") (math, io, fs, net, time, http).
  • File imports with module namespacing (import "utils.arc" -> utils.*).
  • Bytecode cache and fast rebuilds (.lbc).
  • Minimal LSP diagnostics and a JSON-RPC LSP loop.
  • Tiny macro helpers: @include("file"), @repeat(n){...}.
  • REPL with history.
  • Structs with methods and field access (fn Type.method(self) { ... }).
  • Collections: map, set, tuple helpers.

Install

cargo add langkit

For development from source:

git clone https://github.com/livsy29/langkit.git
cd langkit
cargo build

MSRV

Minimum supported Rust version: 1.85.0 (edition 2024).

Feature Flags

No optional feature flags are defined yet.

Quick Start (with error handling)

use langkit::{Lang, Typing, Value};

fn main() {
    let mut lang = Lang::new();
    lang.name("arc");
    lang.extension(".arc");
    lang.var("let");
    lang.mut_kw("var");
    lang.assign("=");
    lang.typing(Typing::Dynamic);
    lang.mode(langkit::Mode::Compiler);
    lang.lib("base");

    lang.token("print");
    lang.action("print", Box::new(|args| {
        let s: Vec<String> = args.iter().map(|a| a.to_string()).collect();
        println!("{}", s.join(" "));
        Value::Null
    }));

    if let Err(e) = lang.run("let x = 5\nprint x") {
        eprintln!("Error: {}", e);
    }
}

Configuration

You can configure behavior in code or via config:

# langkit.toml
name = "arc"
extension = ".arc"
typing = "dynamic"
lib = "base"
build_dir = "build"
libs_dir = "libs"
safe = "safe"

Inline config (at the top of a source file):

#langkit
name = "arc"
extension = ".arc"
lib = "base"
#end

Examples

Examples and tests in the repo:

Import

main.arc

import "utils.arc"
print utils.add(2, 3)

utils.arc

fn add(a, b) { return a + b }

Struct + Method

struct Person { name, age }
fn Person.greet(self) { print self.name }
let p = Person("Ann", 20)
p.greet()

Map / Set / Tuple

let m = map_new()
m = map_set(m, "name", "Ann")
print map_get(m, "name")

let s = set_new()
s = set_add(s, 1)
print set_has(s, 1)

let t = tuple(1, "x", 3)
print tuple_get(t, 1)

Imports and Modules

  • import "file.arc" loads the file and namespaces its symbols by file stem.
  • Imported functions and structs are called as module.symbol.
  • Search paths include the current file directory and libs_dir if set.

Bytecode Cache

If a .lbc file is newer than the source, it is used automatically:

main.arc -> main.lbc

You can also build explicitly:

lang build main.arc

To build a native executable (AOT wrapper):

lang build main.arc --exe

Size-optimized builds are used by default for --exe (LTO + strip + opt-level z).

LSP

Minimal JSON diagnostics are supported:

lang check main.arc --lsp
lang lsp

REPL

lang repl

CLI (example)

lang run main.arc
lang check main.arc
lang build main.arc
lang build main.arc --exe
lang test tests
lang repl

Testing in the Language

Assertions exist as normal calls:

assert(x > 0)
assert_eq(a, b)
assert_ne(a, b)

Custom Modules

use langkit::{Lang, Module, Value};

let mut lang = Lang::new();
let mut m = Module::new("my");
m.action("hello", Box::new(|_| Value::Str("hi".into())));
lang.module(m);

Then in the language:

import "my"
print my.hello()

FFI

FFI modules can be registered via lang.ffi("mylib.dll") and are exposed under a module name. The library must export a langkit_register function that registers functions.

Roadmap

Short 1.0.x focus areas live in ROADMAP.md.

Changelog

See CHANGELOG.md.

Release Process

Recommended flow for releases:

  1. Follow semver for versioning.
  2. Update Cargo.toml version.
  3. git commit the changes.
  4. git tag vX.Y.Z
  5. git push --tags
  6. cargo publish

CI Recommendation

Use GitHub Actions to run tests on each push and publish on tags. See .github/workflows/ci.yml as a baseline and add a publish workflow if needed.

Contributing

Please read CONTRIBUTING.md before opening PRs.

Code of Conduct

See CODE_OF_CONDUCT.md.

License

MIT, see LICENSE.