Public repository: github.com/aetherbird/guji →

guji

A compiled language for text processing

Guji has static types, regex literals, and PEG grammar declarations. The compiler emits native executables through C.

Static typing· Self-hosted compiler· Native executables· Option and Result· Immutable bindings
grammar.guji
grammar Email {
    rule  TOP    { <user> '@' <domain> }
    token user   { \w+ }
    token domain { \w+ '.' \w+ }
}

sub main(): Int {
    match Email.parse('ada@example.com') {
        Some($b) {
            print($b.text)                          # ada@example.com
            match $b<user>   { Some($u) { print($u.text) } None { } }   # ada
            match $b<domain> { Some($d) { print($d.text) } None { } }   # example.com
        }
        None { print('invalid') }
    }
    0
}

A grammar declaration defines a parser. parse() returns Option[Bush], where Bush is the parse-tree type.

regex.guji
sub main(): Int {
    # lookahead: user part only if an @ follows
    match 'ada@example.com' ~~ /\w+(?=@)/ {
        Some($m) { print($m[0].unwrap()) }       # ada
        None     { print("no match") }
    }
    # backreference: find a doubled word
    match 'hey hey you' ~~ /(\w+) \1/ {
        Some($m) { print($m[1].unwrap()) }       # hey
        None     { print("no echo") }
    }
    # rewrite with a capture template
    print("2026-06-12".replace(/(\d+)-(\d+)-(\d+)/, '$3/$2/$1'))
    0
}

Literal patterns are checked at compile time. The dialect includes lookaround, backreferences, possessive quantifiers, and grapheme matching.

pipeline.guji
sub main(): Int {
    @nums = [1, 2, 3, 4, 5]
    $even = @nums.filter({ $_ % 2 == 0 }).map({ $_ * 2 })
    print("sum: { $even.sum() }")                # sum: 12

    %ages = {"ada": 36, "bo": 25}
    for $name, $age in %ages {
        print("$name is $age")
    }
    0
}

Topic lambdas use $_. Uniform call syntax allows functions such as filter, map, and sum to be chained.

types.guji
enum Shape {
    Circle($radius: Int)
    Square($side: Int)
}

sub area($s: Shape): Int {
    match $s {                       # checker proves this exhaustive
        Circle($r) { $r * $r * 3 }
        Square($n) { $n * $n }
    }
}

sub parse_age($s: Str): Result[Int, Str] {
    $n = $s.parse_int()?             # ? propagates the Err
    Ok($n)
}

Option represents absence, Result represents failure, and match expressions must be exhaustive.

Language overview

The main design choices in the current specification.

Regex and grammars

Regex literals and PEG grammar declarations are checked by the compiler and produce typed match or parse-tree values.

Static semantics

Guji uses type inference, immutable bindings, exhaustive match expressions, Option, and Result.

Native compilation

The compiler lowers Guji source to C and invokes the system C compiler. The result is a self-contained native executable.

First-class regex

Regex literals like /(?<user>\w+)/ and the ~~ match operator return an Option[Match] with named and positional captures.

PEG grammars

Declare grammar, rule, and token productions. Parsing returns a typed parse tree called Bush.

Static typing & inference

The compiler infers local types, bindings are immutable by default, and match expressions are checked for exhaustiveness.

Option, Result, ?

No nulls. Fallible code returns Option/Result, and ? propagates the empty/error case to the caller.

Compiles to native

The compiler lowers programs to C and invokes your system cc to produce a standalone native binary.

Functional-first

Topic lambdas use $_. Data-first uniform calls support chains such as .filter(...).map(...).sum().

Design principles

Section 1.1 of the language specification lists five principles.

  1. One obvious way. Prefer one idiomatic construct for a task and avoid redundant syntax.
  2. Functional-first. Bindings are immutable by default. Functions are values, and control constructs return values.
  3. Inferred static types. Every expression has a static type. The compiler infers local types when possible.
  4. Text is a first-class concern. Regex literals and grammar declarations have dedicated syntax and types.
  5. One binary. Ahead-of-time compilation produces a self-contained native executable.

Build the toolchain

shell
git clone https://github.com/aetherbird/guji.git
cd guji
bash selfhost/build_toolchain.sh
./dist/guji                              # start the REPL
Tutorial series

Get started with guji

Six parts covering setup and the main language features. Each part includes commands, code, and expected output.

Prerequisites

  • Some programming experience. The code here is short, but it helps to know what a function is.
  • A Linux x86-64 environment. That is where the current build and test scripts are exercised.
  • Build tools. Git, Bash, sha256sum, standard Unix utilities, and a C compiler available as cc.
  • Optional: Perl 5. Only the conformance harness needs it; the build and tutorial do not.

Prefer reference material? The full specification lives in the documentation.

Build guji

The current Guji toolchain is self-hosting and developed in public. Build it from the official source repository.

Requirements

Compiling Guji requires Git, Bash, a C compiler available as cc, sha256sum, and standard Unix utilities. The current scripts are exercised on Linux x86-64. The combined build_toolchain.sh workflow also runs fixed-point verification and uses timeout as a watchdog for those verification steps. Perl 5 is only required for the conformance harness.

Build the toolchain

git clone https://github.com/aetherbird/guji.git
cd guji
bash selfhost/build_toolchain.sh

The verified self-hosting build creates three local artifacts under dist/:

  • guji: interpreter
  • guji2c: compiler launcher
  • guji2c.bin: self-hosted compiler

Run and compile

# Interpret a source file
./dist/guji program.guji

# Compile it, then run the native executable
./dist/guji2c program.guji program selfhost/rt/runtime_prologue.c
./program

Verify the implementation

The repository includes tests for the Perl conformance harness itself. These tests do not require a built Guji toolchain:

prove -v conform/t

After the build, conform/gujiconform can compare the interpreter and compiler against the same fixture corpus. See the repository instructions for the full command.

Development status

Guji is under active development. The public repository contains the Guji-written compiler and interpreter, maintained C runtime, digest-pinned bootstrap seed, conformance harness, fixtures, and the canonical language specification. Concurrency through hatch, channels, and select is part of the implemented language surface. Consult the current specification for exact semantics.

Historical v0.0.2 binaries

These downloads contain the retired Go implementation. They remain available for release-history and reproducibility purposes, but they are not the current Guji implementation.

Verify archived artifacts against SHA256SUMS. Guji is dual-licensed MIT OR Apache-2.0.

News

Releases and announcements from the guji project.

2026-08-05 · Project

The self-hosting Guji toolchain is now public

Guji development now lives at github.com/aetherbird/guji. The repository contains the Guji-written interpreter and compiler, maintained C runtime, digest-verified bootstrap seed, conformance harness, fixtures, and the language specification.

The retired Go implementation is intentionally excluded. Build the current toolchain with bash selfhost/build_toolchain.sh, then use dist/guji to interpret programs or dist/guji2c to compile them.

2026-06-12 · Release

guji v0.0.2: modules, generics, and expanded regex support

Version 0.0.2 added modules, user-defined generics, and more of the specified regex dialect to the retired Go interpreter and native compiler.

  • Modules (§16). import path::name, pub exports, and qualified access are supported. The compiler includes the import closure in one native binary.
  • User-defined generics (§3.3). Your own sub first[T], enum Box[T], and class Pair[K, V] declarations are type checked, inferred, and monomorphized in native builds.
  • Regex dialect (§13). Lookaround, backreferences, possessive quantifiers, atomic groups, the <{ … }> splice, and grapheme matching (\X, \p{RGI_Emoji}) on a purpose-built backtracking engine.
  • Closure capture. Capturing lambdas use heap-allocated environments, fixing v0.0.1's shared-capture divergence.
  • 115-fixture acceptance suite (up from 83): every fixture compiles natively and must byte-match the interpreter's output and exit code.

Browse the archived v0.0.2 binaries. They were built from commit 703bf6b; checksums in SHA256SUMS.

2026-06-11 · Release

guji v0.0.1: first public release

Version 0.0.1 was the first public release of the retired Go implementation. It included a tree-walking interpreter with a REPL, a native compiler validated by an 83-fixture acceptance suite, regex support, and PEG grammars. Binaries were published for Linux, macOS, and Windows.

Built from commit c6d531b. All artifacts remain at /files/.

Community

Project links, contribution guidance, and current governance.

Project status

guji is an owner-led project under active development. The language surface is specified, the implementation is under active development. The implementation history, the build notes, and the public repository document the current state.

Getting the source

The current source is public at github.com/aetherbird/guji, dual-licensed MIT OR Apache-2.0. It includes the self-hosted tools, C runtime, test harness, fixtures, and the canonical specification.

Contributing

Development happens in public. Use the issue tracker for reproducible bugs and proposals. Open an issue before a large patch. The tutorial provides setup instructions and examples.

Governance

The project is currently owner-led. A public proposal process can be added when language decisions involve multiple maintainers. A foundation is not planned. The deferred-features appendix records features that are outside the current specification.

FAQ

What is Guji for?

Guji is a statically typed compiled language with dedicated syntax and types for text processing. Regex literals and PEG grammar declarations are checked by the compiler.

Is guji production-ready?

No. Guji is under active development, and the current build and test scripts are exercised on Linux x86-64. The public conformance fixtures document the implemented coverage.

Why the sigils?

$scalar, @list, and %map identify a binding's shape. The type checker still tracks the complete static type.

What's a Bush?

The parse-tree type a grammar produces. Email.parse($s) returns Option[Bush]; each named production becomes an addressable sub-tree ($b<user>) with its matched text (.text).

Is there a package manager?

Not yet. Modules are file-based with qualified imports. The mirror.guji.dev name is reserved, but no registry service is running.

Is Guji self-hosting?

Yes. The current interpreter and compiler are written in Guji and use a maintained C runtime. A checked-in, digest-pinned generated C seed enters the bootstrap chain; the build verifies that reproduced compiler generations match. The earlier Go implementation is retired.

404

Page not found

The requested page does not exist.

Return home