tc-lang (Tig)
- title
- tc-lang (Tig)
- type
- toolbox
- summary
- Minimalist systems language transpiling to readable C11, with fat pointers, defer and errors
- tags
- language, systems-programming, c, transpiler, watchlist
- language
- C
- license
- MIT
- created
- 2026-07-21
- updated
- 2026-07-21
Tig (the repo is tc-lang) is a minimalist systems language by Alonso VM that transpiles to portable C11. The pitch is ergonomics over C without paying for a garbage collector, type inference, or a heavy runtime โ a language small enough to "fit in a single person's head", with 18 keywords. The compiler emits readable C that you hand to gcc or clang.
On the watchlist โ see watchlist โ because it's a pre-1.0, single-author project at around 40 stars aiming at OS-scale use.
How it works
Source-to-source, about 4,600 lines of C: lexer, parser, AST, checker, emitter, then C11 out to the system compiler. There is no optimizer, no intermediate representation, and no type inference โ codegen is essentially readable-C string concatenation. All the heavy lifting is deferred to gcc/clang, which keeps the compiler itself small and auditable.
The stated bootstrap plan has two stages. Stage0 permits an AI-generated C core (the current transpiler). Stage1, the self-hosting compiler, requires handwritten code โ AI-generated source is not allowed to count toward the self-host.
Distinctive syntax
Pointers come in two flavours: raw pointers written -> and fat pointers written => (a struct carrying .ptr + .len, with built-in slicing like arr[1:3]). strun unifies struct and union as a single spectrum, using & to mark shared-memory members. defer runs cleanup at scope exit. pin marks a binding scope-local immutable โ enforced at parse time, emitting nothing into the generated C.
Errors are a built-in type rather than a return-value convention. An error declaration carries context parameters plus cleanup, is raised with throw, and handled by try/catch โ where catch behaves like a match, including a _ wildcard. Diagnostics are Rust-style: colored output with error codes.
Concurrency has no boilerplate. An async fn auto-initializes the runtime; async functions are always void and communicate through built-in queue<T> / stack<T> channels. select waits on multiple operations, and @ transfers ownership. There's a global hot-reload mode (-H/--hot) built on a Host/DLL split: main stays in the host process while everything else compiles into a versioned hotlib_N.so/.dll reloaded through function-pointer stubs. @use "lib.tc" inlines another file at compile time, and C FFI is a "C"{ #include ... } block.
Usage
strun Point { x: i32; y: i32 }
fn main() -> i32 {
nums => [1, 2, 3, 4] // fat pointer / slice
part = nums[1:3] // built-in slicing
defer cleanup() // runs at scope exit
return 0
}
Ownership transfer and channels in async code:
async fn worker(q: queue<i32>) {
x = <- q // receive
}
Limitations
Explicitly not memory-safe: no borrow checker, no GC, manual alloc/free. Arenas are planned but not shipped, so today memory management is entirely on the programmer โ the same footgun profile as C, which it also doesn't try to hide behind a safety layer like safe-gc or the runtime checks in simplified-model-of-fil-c.
Licensing is ambiguous: the README carries an MIT badge, but GitHub detects no SPDX license file in the repo, so the actual grant is unclear until a LICENSE lands. The project's goals are stated ambitiously โ "the first usable systems language from Mexico" and "make an OS with it" โ against a single-author, pre-1.0 codebase.
Repo
github.com/alonsovm44/tc-lang โ C, MIT (per README badge; no SPDX license file detected by GitHub), ~40 stars.
Related
- zig โ a more mature C-replacement with the same no-GC, no-hidden-runtime stance, but a real type checker and comptime
- c3-lang โ another minimal C evolution transpiling close to C's model
- unsigned-sizes-c3-mistake โ a C3 retrospective on a specific design choice worth weighing against Tig's
- safe-gc, simplified-model-of-fil-c โ the memory-safety approaches Tig deliberately skips