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.
One obvious way. Prefer one idiomatic construct for a task and avoid redundant syntax.
Functional-first. Bindings are immutable by default. Functions are values, and control constructs return values.
Inferred static types. Every expression has a static type. The compiler infers local types when possible.
Text is a first-class concern. Regex literals and grammar declarations have dedicated syntax and types.
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
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.
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.