1 unstable release
Uses new Rust 2024
| new 0.1.0 | May 13, 2026 |
|---|
#378 in Programming languages
Used in 4 crates
215KB
5.5K
SLoC
A three-layer programming language ecosystem — designed for both humans and AI agents. Named after types, its core concept.
Strict compiler rules and enforced conventions make it hard to write bad code — for anyone. Lints are errors, not warnings.
T is fully implemented — a C-level language with two syntaxes (SLN and C-style), compiling to C. Ty is functional — adds generics, const execution, callable tuples, operator overloading, and UFCS on top of T. Tyr compiles end-to-end — natural-language syntax with phonotactic auto-bracketing, compiling through Ty to C.
T: Tutorial | Reference | C Interop Ty: Tutorial | Reference | T Interop Tyr: Tutorial
C, but consistent
T is explicit and low-level: no generics, no closures, no garbage collection. Everything you need from C, nothing you don't. Newtypes replace structs, aliases, and constructors.
SLN Syntax (.sln.t)
fn fibonacci (n) (i32) i64
label loop (i a b) (i32 i64 i64) (0 0 1)
if (>= i n)
return a
jump loop (+ i 1) b (+ a b)
print "fib(20) =" (fibonacci 20)
C Syntax (.c.t)
fn fibonacci(n: i32) -> i64 {
label loop(i: i32 = 0, a: i64 = 0, b: i64 = 1);
if i >= n { return a; }
jump loop(i + 1, b, a + b);
}
print("fib(20) =", fibonacci(20));
Both syntaxes parse to the same AST. No fn main needed — top-level statements are auto-wrapped.
Features
- Newtypes:
type Meters = f64creates a distinct type (not an alias). Implicit downcast, explicit upcast viaMeters: 42.0/(Meters 42.0). Tuple newtypes (type Point = x & y) replace structs, with fields resolved by type. Enum newtypes (type Result = ok | err) are sum types. - Types:
bool,i8–i128,u8–u128,isize/usize,f32,f64, pointers (&T/|T), arrays ([T]N), vectors ({T}N), slices ([T]), tuples, enums, named types, functions - Control flow:
if/else,match,label/jump(loops via goto with parameters),defer - Bindings (type annotations optional, types are inferred):
let x 42— value, not addressableref x 42— immutable reference (&T), auto-deref in value contextsvar x 42— mutable reference (|T), auto-deref in value contexts, assignable
- Auto-deref:
varandrefare automatically dereferenced for operators, conditions, print, return, etc. — and automatically passed by reference to pointer parameters. - Pointers:
&Tshared,|Tmutable. Field access (.) preserves the reference state. - Slices:
arr[]creates a slice from an array,arr[start, end]creates a sub-slice - Repeat literals:
[0]5expands to[0, 0, 0, 0, 0],{0.0}3for vectors - Assignment returns old value (
set/:=):x, y := y, xis swap.let old = current := new_valuecaptures the replaced value. - Multi-let:
let x, y = 1, 2;/(let x 1 y 2)— multiple bindings in one statement - Compound assignment:
+=,-=,*=,/=/(set+ x 1),(set- x 1) - Defer:
defer statementexecutes before everyreturnand at function end (LIFO order) - Lints (always errors, not warnings): unused bindings, self-assignment, chained swap, compound assignment, unreachable code, division by zero, dead labels, recursion, nesting depth (max 4), unnecessary return, unnecessary intermediate variable, duplicate type definitions, identity casts
- Visibility:
pubfor external linkage (default is internal/static).import/externfor C interop. - Import:
import "file.c.t"(source expansion),import "lib.th"(header format),import "stdio.h"(C header) - Stdlib:
import "math.th","memory.th","string.th","file.th","process.th","convert.th" - Number literals: decimal, hex (
0xFF,0x14.8), octal (0o77), binary (0b1010), with underscore separators (1_000) - Three-way cast system:
Type: valuefor newtype construction,.Typefor newtype downcast,asfor unsafe pointer casts only (pointer↔integer, pointer↔pointer). Numeric conversions use constructor:u32: x. No implicit conversions. - Type-based arguments: function arguments matched by type, not position. Same-type and subtype parameters rejected — use newtypes. Shorthand:
fn test(x, y)=fn test(x: x, y: y). Pointer shorthand:fn f(|Node). - Null pointers:
nullkeyword, compatible with any pointer type.pointer == null/pointer != nullfor checks.pointer == 0rejected. - Function pointers:
call(f, x)/(call f x)for indirect calls - Print:
printoutputs arguments separated by spaces with newline —print x "hello" 3.14 - WGSL backend:
t wgsl file.c.tgenerates WebGPU shading language (shader compilation) - Constants:
const MAX u32 1024
Build & Run
t build file.c.t # compile to binary
t run file.c.t # compile and run
t c file.c.t # output generated C
t wgsl file.c.t # output generated WGSL
t check file.c.t # parse + resolve (no compile)
t header lib.c.t # generate .th header
t repl # interactive REPL (--sln for SLN)
t --version # show version
Works with both .sln.t (SLN) and .c.t (C-syntax) files.
All the features you need. None that you don't.
The name says it: types matter. In Ty, every function is a type plus an implementation. Every operation has a name. The type system is the language. Compiles down to T.
Core Idea: fn = type + impl
type n = i32;
fn twice n -> i32 { n.i32 * 2 }
is sugar for:
type n = i32;
type twice = n;
impl twice -> i32 { n.i32 * 2 }
Constructing a tuple with an impl -> ReturnType auto-evaluates it. Without impl, construction produces data.
Generics
fn identity[T] T -> T { it }
print(identity(42), identity(true));
Generic parameter it is a placeholder for the concrete type. Each instantiation is monomorphized into a concrete function.
Features
- Callable tuples:
fnis sugar fortype+impl— evaluation as construction - Generics: type and const parameters in
[T]/[]Nsyntax, monomorphized at compile time - Const execution:
const fnevaluated at compile time — enables compile-time type construction - Operator overloading:
import "operators.c.ty"; impl add[Vec2] & Vec2 -> Vec2 { ... } - UFCS:
x.f(y)=f(x, y)— any argument can be the receiver - Implicit fields:
impl point -> f64 { sqrt(x * x + y * y) }— tuple fields available directly - Impl blocks: make types callable with
impl Type -> ReturnType { body } - No traits: polymorphism through type-based dispatch on tuples
- Imports: Ty-to-Ty and Ty-to-T imports, stdlib access
- REPL:
ty repl— interactive, compiles through full Ty → T → C pipeline - Everything from T: newtypes, if/else, print, top-level statements
Build & Run
ty build file.c.ty # compile to binary
ty run file.c.ty # compile and run
ty c file.c.ty # output generated C (via T)
ty check file.c.ty # parse + resolve (no compile)
ty repl # interactive REPL
ty --version # show version
Think, then compute
Tyr is natural language-inspired. No parentheses, no braces — nesting is determined by each word's consonant structure. Compiles to Ty.
Core Idea: Words Are Syntax
Every word belongs to one of four types, recognizable from its consonants:
| Word Type | Structure | Effect |
|---|---|---|
| Object | Consonants before + after vowel | Closes a level |
| Specifier | Consonants only before vowel | Qualifies next Object |
| Relation | Consonants only after vowel | Opens a level |
| Modifier | Starts with stop (b/c/d) | Transforms previous word |
an van van → add(1, 1) = 2
ul an van van zan → mul(add(1, 1), 6) = 12
da an van van → sub(1, 1) = 0 (da = opposite)
in an van van sum → let sum = add(1, 1)
No definitions — types and operations are words in the vocabulary. Programs compose existing words.
Crate Structure
| Crate | Description |
|---|---|
t-ree |
T AST definitions |
t-parser_sln |
SLN source → T AST |
t-parser_c |
C-syntax source → T AST |
t-backend_c |
T AST → C code |
t-backend_wgsl |
T AST → WGSL shader code |
t-repl |
Shared REPL implementation |
t |
T CLI |
ty-ree |
Ty AST definitions (extends T with generics, lifetimes, impl) |
ty-parser |
Ty C-syntax source → Ty AST |
ty-parser_sln |
Ty SLN source → Ty AST |
ty-backend_t |
Ty AST → T AST (monomorphization + lowering) |
ty |
Ty CLI |
tyr-core |
Abstract Tyr type-system traits (Evaluable, Specifier, Relation, Modifier) |
tyr-syntax |
Tyr source → parsed sentences (phonotactics + auto-bracketing) |
tyr-grammar |
Mathematical grammar (rational numbers, sets) |
tyr-backend_ty |
Tyr sentences → Ty AST |
tyr |
Tyr CLI + REPL |
Dependencies
- token-parser 0.5 — typed token parsing
- rslnp 0.4 — SLN (Scopes List Notation) parser
- A C compiler (
cc)
Error Reporting
All errors include line:column locations, corrected for import expansion. The resolver reports all errors at once instead of stopping at the first. Error messages suggest fixes:
Resolution error: 5:1: in 'sort': parameters 'index' (index) and 'ids' (|u64) have conflicting types — use distinct newtypes
Resolution error: 12:14: type u64 has no field 'u32' — use 'u32: value' for numeric conversions
Parse error: 3:12: redundant parameter name 'n: meters' — use 'meters' shorthand instead
Lint error: 8:5: use 'pos += <value>' instead of 'pos := pos + <value>'
Designed with AI in Mind
Strict rules, no ambiguity, and enforced conventions mean that AI-generated code is clean and correct by construction. The same properties make it pleasant for humans: less to remember, fewer surprises, one way to do things.