I I Language C-shaped systems programming

Transpiles to C

i

A C-shaped language that transpiles to C, keeps the native toolchain intact, and adds cleaner declarations, monomorphized generics, reflection, and a small standard library.

Direct

Generates C, keeps the runtime visible, and lets the normal C toolchain do the final native build.

Generic

Monomorphized structs and procedures give you reusable data structures without moving into C++.

Reflective

Structs and enums produce metadata for fields, offsets, names, sizes, and future tooling.

Syntax Examples

The same pieces in context

Basics

Quickstart

Build, translate, compile

Initialize modules

Pull Haikal, tree-sitter, and support scripts.

git submodule update --init --recursive

Build compiler

Builds I.exe and copies the compiler plus src/std into the package folder.

python bunyan.py build debug

Install package

Add the package folder to PATH. The compiler finds its sibling std automatically.

C:\devel\i-windows-x64

Run an I project

Bunyan calls I.exe, writes generated C under build\i_gen, then compiles it normally.

python bunyan.py run debug

Features

Small syntax, real C output

I is designed as a focused compiler front-end. The generated C remains visible and normal toolchains do the final build.

Declaration-first syntax

Variables, types, procedures, and globals use name: type, keeping type information near the symbol being introduced.

Generics with monomorphization

Generic structs and procs use <T>. Concrete uses such as Array<i32> emit concrete C names.

Template specialization

Known types in generic positions specialize the body, so print<Payload> is the typed extension point behind printfmt.

Type-operation generics

Generic procedures can call typed operations such as eq<T>, add<T>, or print<T>; concrete specializations provide the behavior.

C-shaped control flow

if, for, while, do while, switch, break, and continue map directly to C.

Enum member access

Enum values use namespaced dot syntax such as Mode.Attack, while generated C keeps stable concrete symbol names.

Interop by design

Use external for declarations that already exist in C headers and external_emit when I should emit a prototype.

Generated module headers

The compiler writes a companion header next to the generated C so imports can type-check against I modules.

Reflection metadata

Struct and enum output includes reflection records for names, sizes, fields, offsets, and enum values.

Readable diagnostics

Lexer, parser, and semantic errors include source path, line, and column.

C Interop

Use C without hiding it

I emits C includes, defines, declarations, and line directives. The generated C is an artifact you can inspect and debug.

Imports

import "math.i"
cinclude "stdio.h"
define("SAHA_IMPLEMENTATION")

import is for I modules. C headers are included through emitted C includes.

External declarations

puts: proc(text: *const char)->i32 = { external; }
fx_step: proc(dt: f32)->void = { external_emit; }

external type-checks only. external_emit also writes a C prototype.

Compiler CLI

I.exe compile src\main.i -o build\i_gen\main.c --header build\i_gen\main.h
I.exe check src\main.i --diagnostics=json

Use compile, check, symbols, or lsp. Project-local imports use --importdir; packaged std is found next to I.exe.

Build Flow

What happens when you run it

  1. 1

    Building the compiler repo produces I.exe and copies src/std beside it.

  2. 2

    An I project invokes I.exe compile from PATH or a package folder.

  3. 3

    I.exe resolves project imports plus its sibling std package.

  4. 4

    Generated C and headers are written under build\i_gen.

  5. 5

    The normal C compiler links generated I output with any C/vendor sources.