.ctri extension, and library files use .plib. Because C△ inherits the full C11 grammar, any valid C11 code you already know — including pointers, enums, unions, and typedef — continues to work exactly as expected.
File Extensions
Every file you write in C△ falls into one of two roles, indicated by its extension:| Extension | Purpose |
|---|---|
.ctri | C△ source file (executable or translation unit) |
.plib | C△ library file (self-contained, no separate header needed) |
The compiler determines whether a
.ctri file is an executable or a library unit by checking for the presence of a main function. Library files (.plib) are written in ordinary C△ — they support dynam arrays, typed struct inheritance, and all other language features. Unlike C, there is no separate header file or preprocessor step.Imports and Modules
C△ usesusing and expose to bring library symbols into scope. The compiler performs auto-import: it inspects which functions and variables your file actually references and inserts only the necessary imports automatically. If nothing from a library is used, the compiler will not insert it.
Variables
C△ supports every C11 variable declaration unchanged, and adds three new forms: the first-classstring type, the auto inferred type, and multi-variable packing.
auto in C△ means inferred/dynamic type — it does not carry the C11 auto storage-class meaning, which has been removed. Using C11 auto will raise a SyntaxError.Control Flow
C△ inherits all C11 control-flow statements without modification. Useif/else, for, while, do/while, switch, break, continue, return, and goto exactly as you would in C11.
Functions
Declare functions using the same syntax as C11. C△ adds one new form: the variadic argument stream, which collects all call-site arguments into atuple pointer.
Lambdas (lamb)
Named lambdas let you define single-expression functions in one line. The return type is inferred automatically, so you never need to annotate it.
Lambdas defined with
lamb are named — they are callable by name anywhere in the same file after their definition. They are not anonymous closures; use regular functions if you need recursion or multiple statements.Structs
C△ provides two kinds of struct: plain structs andtyped structs. Both support an init constructor lifecycle and an end destructor lifecycle, as well as member functions.
- Plain Struct
- Typed Struct (Inheritance)
Plain structs have constructors and member functions but no inheritance. Use them for lightweight data types where you don’t need polymorphism.
Dynamic Arrays (dynam)
A dynam array grows and shrinks at runtime with no fixed capacity. Declare one with a bracketed initializer list, then use the built-in methods to modify it.
len() is a base function built into the language itself — it is not part of any library and requires no import.Tuples
Atuple is a heterogeneous, dynamically-sized list that can hold values of mixed types. Index into it with [] and grow it with .push().
Inline Assembly (asm)
C△ lets you embed assembly directly in a source file using the asm keyword. There are two forms: named asm functions (callable from C△ code) and anonymous asm {} blocks (inline). Declare the target architecture with syntax, open the appropriate text section, write your instructions, and exit cleanly — non-void asm functions must end with return; anonymous blocks must end with an explicit sys_exit syscall.
Each
asm block is compiled to a separate .asm file, assembled with NASM, and linked into the final binary by GCC. You do not manage this pipeline yourself. See the Inline Assembly page for the full reference — including all syntax targets, anonymous asm blocks, and the rules for data declarations.Namespaces
Usespace to declare a named namespace, @ to access its members without globalizing it, and expose to bring all its symbols directly into scope.
When to use @ vs expose
When to use @ vs expose
Use the
@ operator when you want to reference a single symbol from a namespace without polluting your current scope. Use expose when you need frequent access to many symbols from the same namespace and name collisions are not a concern.Built-in Functions
The following functions are built into the language itself — they require no import and are always available.len(collection) — Length
len() returns the number of elements in a string, dynam array, or tuple. It works uniformly across all three collection types.
len() on string and dynam works in the current compiler. tuple is not yet implemented — see Compiler Status.