Skip to content

Repository files navigation

Glyph Language Compiler (glyphc)

CI version

The Glyph programming language compiler, written in Rust.

Glyph transpiles to C (GNU statement expressions) and builds with GCC or clang into plain native binaries. It also hosts NeuralScript (.ns), a typed AOT tensor language for CPU/CUDA code generation.

Philosophy

Glyphc joins explicit systems programming and typed ML graphs in one inspectable toolchain: from source to native artifacts without a mandatory Python or GC layer. The project manifesto is available in Russian as Философия Glyphc.

┌──────────┐   glyphc    ┌────────────┐   gcc/clang   ┌─────────┐
│ .glyph   │ ──────────▶ │     .c     │ ─────────────▶ │ binary  │
└──────────┘   (Rust)    └────────────┘               └─────────┘

Features

  • Static typing: Int64, UInt64, Float64, Bool, String, Bytes
  • Flow-sensitive static analysis: using a List/Map after .free() (or freeing it twice) is rejected at compile time until reassignment
  • User types: @struct, @enum with payload data in variants
  • @impl methods: obj.method(args), receiver is the first parameter
  • Control flow: if/else, match (including variant patterns with payload), while, loop, for .. in
  • Guards: #guard(cond) else { ... };
  • Modules: @module, @use, @pub, qualified calls math::sqrt
  • @const named constants (compiled to static const)
  • Typed lists List<T>: literals [..], indexing arr[i], slices arr[a..b]/arr[a..=b], ranges 0..10, .len(), append, for x in xs, ++ concatenation, == for POD lists, refcounted buffers with xs.free()
  • Maps Map<String, V>: literal #{ "k": v }, indexing m["k"] read/write, .put(), .get() -> Option<V>, .len(), .free(), iteration for k in m yields keys
  • Result/Option with payloads and drop(box) freeing
  • Generic functions: @fn identity<T>(x: T) -> T — monomorphization, type inference by argument and let annotations, nested types (Option<T>, List<T>)
  • Concurrency (M:N worker pool): @fn async, lazy handles Async<T>, spawn/await, typed channels Channel<T>(capacity), send/recv/close, select over recv/await with timeout(ms)/default arms
  • Built-in test framework: @test, asserts, glyphc test
  • glyphc fmt: comment-preserving canonical indentation + --check/--write

NeuralScript (nns)

NeuralScript (.ns) — neural-network DSL, now integrated into glyphc as glyphc nns. The original C++ implementation was ported to Rust with byte-identical codegen and merged into the single glyphc binary.

glyphc nns file.ns --check                          # typecheck only, no codegen
glyphc nns file.ns --cpp                            # emit C++ to stdout
glyphc nns file.ns --cpp --runtime                  # emit C++ + runtime header
glyphc nns examples/nns/mlp.ns --cpp --runtime | gcc -x c - -o a.out && ./a.out
glyphc nns file.ns --cuda --runtime                 # emit CUDA + runtime header
glyphc nns file.ns --cuda --runtime -o out.cu       # write to file

Flags: --check (no codegen), --cpp / --cuda (select backend), --runtime (prepend runtime header), -o/--output <file> (write to file instead of stdout).

Examples live in examples/nns/*.ns (e.g. examples/nns/mlp.ns). The complete reference is in docs/nns.md.

Install

Requires Rust (1.85+) and gcc (or clang) on PATH.

The easiest installation is the release installer:

curl -fsSL https://raw.githubusercontent.com/MrModelOS/Glyph/main/install.sh | bash
# optional: install into ~/.local/bin
curl -fsSL https://raw.githubusercontent.com/MrModelOS/Glyph/main/install.sh | bash -s -- --prefix ~/.local/bin

For a source install or development checkout:

cargo install --git https://github.com/MrModelOS/Glyph --locked
# or
git clone https://github.com/MrModelOS/Glyph.git
cd Glyph
cargo build --release

A container image can be built locally with docker build -t glyphc .; the resulting image exposes the glyphc binary. Tagged Linux, macOS, and Windows archives with SHA-256 checksums are published on the Releases page. The documentation site is built from docs/ by the Pages workflow.

Quick start

Start a project with the built-in scaffold:

glyphc new hello
cd hello
glyphc build

Or compile a single file:

hello.glyph:

@fn main() -> Void {
    let name: String = "World";
    let greeting: String = "Hello, " ++ name ++ "!";
    print(greeting);
}
glyphc run --input hello.glyph
# Hello, World!

There is also a real interactive demo — the 15-puzzle — with lists, slicing, read_line, and @tests:

glyphc run --input examples/fifteen.glyph

CLI

Subcommand Description
compile --input f.glyph [-o out.c] [--emit-ir] [--no-typecheck] Transpile to C (default output.c)
check --input f.glyph Check syntax and types without codegen
tokens --input f.glyph Show the token stream
ast --input f.glyph Show the AST
run --input f.glyph [--compiler gcc] [--opt -O2] Compile and run (inherits stdio)
build [--profile dev|release] Build a project described by glyph.toml
fmt --input f.glyph [--write] [--check] Canonical indentation/whitespace; comments preserved (prints to stdout by default)
test [-i f.glyph] [--compiler gcc] [--opt -O2] Run @test functions (scans ./src without -i)
nns <file.ns> [--check] [--cpp] [--simd] [--cuda] [--runtime] [--mlir] [--fp16] [-o <file>] NeuralScript tensor compiler: --check shape-check only, --cpp/--simd/--cuda select the backend (default CUDA), --runtime emits the C-ABI runtime, --mlir dumps IR, --fp16 enables the experimental CUDA header mode, -o writes to a file (default stdout)
new <name> / init [name] Create a glyph.toml project scaffold
lsp LSP server alias for glyphc --lsp (also glyphc --lsp as flag) — live diagnostics, hover, completion, go-to-definition
glyphc --lsp LSP server (flag form): live diagnostics (lexer/parser/typechecker, full spans), hover and completion

Common flags: -h/--help, -V/--version. nns details: docs/nns.md; editor setup: docs/editors.md. A minimal VS Code extension is available in editors/vscode-glyph.

Language tour

Full reference: English · Русский. Highlights:

@struct Point { x: Float64, y: Float64 }

@impl Point {
    @fn norm(p: Point) -> Float64 {
        return sqrt(p.x * p.x + p.y * p.y);
    }
}

@enum Shape {
    Circle(Float64),
    Rectangle(Float64, Float64),
    Point,
}

@fn area(s: Shape) -> Float64 {
    match s {
        | Shape::Circle(r) => 3.14159 * r * r
        | Shape::Rectangle(w, h) => w * h
        | Shape::Point => 0.0
    }
}

@fn distance(a: Point, b: Point) -> Float64 {
    let dx: Float64 = b.x - a.x;
    let dy: Float64 = b.y - a.y;
    return sqrt(dx * dx + dy * dy);
}

@fn main() -> Void {
    let p: Point = Point { x: 3.0, y: 4.0 };
    print_float(p.norm());          // 5.0

    let arr: List<Int64> = [1, 2, 3];
    arr.append(4);
    let both: List<Int64> = arr ++ arr;
    let slice: List<Int64> = arr[1..3];
    print_float(area(Shape::Circle(5.0)));
}

Errors and generics:

@fn divide(a: Int64, b: Int64) -> Result<Int64, String> {
    #guard(b != 0) else {
        return Result::Err("division by zero");
    };
    return Result::Ok(a / b);
}

@fn identity<T>(x: T) -> T { return x; }

@fn main() {
    let q: Int64 = match divide(10, 2) {
        | Ok(v) => v,
        | Err(e) => -1
    };
    let s: String = identity("hello");
    print_int(q);
}

Concurrency, modules, and asserts are documented in docs/language.md.

Testing

cargo build
cargo test          # 100 unit + 25 integration tests (CLI smoke + NeuralScript)
examples/run_all.sh # compiles and runs every example
glyphc test -i examples/fifteen.glyph

examples/fifteen.glyph is a real interactive program (15-puzzle) written in Glyph: lists, slicing, functions, read_line, and @tests. examples/list_refs.glyph demonstrates the refcounted list semantics, and examples/maps.glyph shows the Map<String, V> runtime (#{} literal, indexing, put/get/len/free, for k in m).

Performance

Glyph compiles to C and inherits the C toolchain: scalar code compiles to the same machine code, and the runtime overhead is proportional to the allocation/GC features you use. The table below compares identical algorithms on one machine (min of 3 runs, gcc 16.2.1 -O2, rustc 1.98.1 --release with LTO; meant to show the ballpark, not to be a rigorous benchmark).

workload        glyph     c      rust   ratio (glyph/c)
loop_sum         476ms  471ms   549ms        1.01x
list_append       13ms   14ms    14ms        0.93x
map_put_get       43ms   40ms    43ms        1.07x

Hardware: 11th Gen Intel Core i5-1135G7, 2026-09-10. loop_sum sums i % 7 over a runtime size (400M iterations); list_append appends 5M int64s to a dynamic array and sums them; map_put_get puts+gets 500k string-key entries across a 100-key churn. All three implementations produce identical output. Reproduce with:

bash bench/gen.sh /tmp/bench 5000000
LOOP_IN=400000000 bash bench/run.sh /tmp/bench

Notes:

  • loop_sum is at parity with C (1.01x) and edges out Rust (549ms vs 476ms) — the loop, modulo and integer arithmetic emit the same code gcc would write by hand, minus LLVM's optimizer noise on the hot induction loop.
  • list_append uses a refcounted growable buffer that doubles its capacity geometrically, so appends amortize to O(1) like C's realloc array; the runtime helpers are static inline, so the hot loop inlines to a plain store — at parity with C.
  • map_put_get rehashes geometrically (load factor ≤ 0.75) and keys built temporarily by int_to_string/++/substring... are freed right after the put/get/index call, so the string churn that used to be measured (and leak) is gone. At 1.07x it sits between C (fixed 256 buckets) and Rust's hashbrown.

Limitations

  • Runtime is unmanaged: Result/Option payloads are heap boxes freed via drop(box); async handles and channels are not auto-released
  • Generics cover functions only (no generic structs/enums/impl, no trait bounds); calling a generic function inside a generic body needs concrete types
  • List<T>: ==/!= works only for POD scalars; slices are copies
  • Map<String, V>: iteration (for k in m) walks hash buckets, so key order is not insertion order; keys are String only
  • The use-after-free / double-free detector is statement-flow based and does not track aliases: let y = xs; xs.free(); y.len() is not yet caught, and a free inside a match arm is treated as having happened after the match
  • Concurrency: no GC; async generic functions unsupported; select arms must be recv()/await and its wait loop polls at ~1 ms granularity
  • LSP server: diagnostics from lexer/parser/typechecker with full source spans, cursor hover and keyword completion; textDocumentSync = Full

License

MIT

About

Glyph — a Rust systems language that transpiles to readable C, with built-in NeuralScript AOT CPU/CUDA tensor compilation, LSP, tests, and reproducible releases.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages