> ## Documentation Index
> Fetch the complete documentation index at: https://hypotenuse.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# C△ Syntax Guide: Variables, Functions, and Control Flow

> Learn C△ syntax from imports and variables to structs, lambdas, dynamic arrays, and namespaces — all extending familiar C11 conventions.

C△ extends C11 syntax with new constructs while staying familiar to C programmers. Source files use the `.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) |

<Note>
  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.
</Note>

## Imports and Modules

C△ uses `using` 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.

```c theme={null}
// Import everything from a system library (searched in PLIBS/)
using <plstd>

// Import a specific function from a system library.
// When you import a single symbol this way, the library name in the current
// file is rewritten to that symbol — so `plstd` is no longer in scope here,
// only `printd` is.
using printd from <plstd>

// Import a specific function from a local library file
using helper from "utils"

// Globalize an entire library — all its symbols enter the current scope
// so you can call them unqualified (e.g. `printd(...)`).
// `expose` takes the *current* library name. After `using printd from <plstd>`
// the library name is `printd`, so the correct form is `expose printd`.
expose printd

// Globalize only a specific namespace from a library
expose io@lib;

// Explicit namespace access without globalizing — function@namespace syntax.
// Use this when you haven't exposed the library. After a selective
// `using printd from <plstd>`, the access form is `printd@printd(...)`.
printd@printd("value: %d\n", 42);

// Intra-file variable import — share a variable across functions in the same file
using scopeName&myVar
```

<Tip>
  Prefer `using specificFunction from <lib>` over `using <lib>` when you only need one or two symbols — it keeps your namespace clean and makes dependencies explicit.
</Tip>

## Variables

C△ supports every C11 variable declaration unchanged, and adds three new forms: the first-class `string` type, the `auto` inferred type, and multi-variable packing.

```c theme={null}
// Standard C types — unchanged from C11
int x = 5;
float pi = 3.14;
char c = 'A';

// C△ first-class string type
string name = "Hypotenuse";

// Inferred type — the compiler deduces the type from the initializer
auto value = 42;
auto label = "hello";

// Multiple variable packing — all three variables are initialized to 10
auto x, z, w = 10;
```

<Note>
  `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`.
</Note>

<Warning>
  **`auto` (inferred type) and multi-variable packing are not yet implemented** in the current compiler. `string` and standard C11 declarations work. See [Compiler Status](/reference/compiler-status).
</Warning>

## Control Flow

C△ inherits all C11 control-flow statements without modification. Use `if`/`else`, `for`, `while`, `do`/`while`, `switch`, `break`, `continue`, `return`, and `goto` exactly as you would in C11.

```c theme={null}
// Conditional branching
if (x > 0) {
    printd(x);
} else {
    printd(0);
}

// Counted loop
for (int i = 0; i < 10; i++) {
    printd(i);
}

// Condition-based loop
while (x > 0) {
    x--;
}
```

## 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 a `tuple` pointer.

```c theme={null}
// Standard function — identical to C11
int add(int a, int b) {
    return a + b;
}

// Variadic argument stream — args is a pointer to a tuple of all arguments
int sum(tuple args*) {
    // iterate over args to accumulate the sum
}
```

<Tip>
  The `tuple args*` variadic form gives you a typed, iterable view of arguments at runtime — more ergonomic than C's `<stdarg.h>` approach.
</Tip>

<Warning>
  **Variadic `tuple args*` is not yet implemented** — `tuple` is not supported in the current compiler. Standard fixed-arity functions work. See [Compiler Status](/reference/compiler-status).
</Warning>

## Lambdas (`lamb`)

<Warning>
  **`lamb` is not yet implemented** in the current compiler. See [Compiler Status](/reference/compiler-status).
</Warning>

<Warning>
  **Not implemented yet.** `lamb` (named lambdas) is part of the language design but is not supported by the current compiler. See [Compiler Status](/reference/compiler-status).
</Warning>

Named lambdas let you define single-expression functions in one line. The return type is inferred automatically, so you never need to annotate it.

```c theme={null}
lamb double(int num) = num * 2;
lamb add(int a, int b) = a + b;

// Call a lambda exactly like a regular function
auto result = double(5);   // result = 10
```

<Note>
  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.
</Note>

## Structs

<Warning>
  **Struct constructors/destructors (`init`/`end`), member functions, and `typed struct` inheritance are not yet implemented.** Plain C-style structs (fields only) work via the C11 baseline. See [Compiler Status](/reference/compiler-status).
</Warning>

C△ provides two kinds of struct: **plain structs** and **`typed` structs**. Both support an `init` constructor lifecycle and an `end` destructor lifecycle, as well as member functions.

<Tabs>
  <Tab title="Plain Struct">
    Plain structs have constructors and member functions but **no inheritance**. Use them for lightweight data types where you don't need polymorphism.

    ```c theme={null}
    struct Point(int x, int y) {
        init {
            int self.x = x;
            int self.y = y;
        }

        int distanceTo(Point other) {
            // compute and return distance
        }

        end {
            // cleanup runs when the struct goes out of scope
        }
    }
    ```
  </Tab>

  <Tab title="Typed Struct (Inheritance)">
    A `typed` struct becomes a **native type** in the compiler and supports inheritance using the `&ParentName` syntax. Multiple inheritance is supported; conflicting methods are resolved by addressing the parent namespace explicitly.

    ```c theme={null}
    typed struct Animal(string name) {
        init { string self.name = name; }
        string speak() {
            return "...";
        }
        end { /* cleanup */ }
    }

    // Single inheritance
    typed struct Dog&Animal(string name) {
        init { /* initialize Dog */ }
        string speak() {
            return "Woof!";
        }
        end { /* cleanup */ }
    }

    // Multiple inheritance
    typed struct PoliceDog&Dog&Animal(string name, int badge) {
        init { /* initialize PoliceDog */ }
        // Constructor chain runs: Animal → Dog → PoliceDog
        // Resolve method conflicts with parent namespace syntax:
        //   obj.Dog.speak()   or   obj.Animal.speak()
        end { /* cleanup */ }
    }
    ```
  </Tab>
</Tabs>

<Warning>
  When two parent types define the same method name, calling that method directly on a `typed` struct with multiple inheritance is ambiguous. Always qualify the call with the parent name — for example, `obj.Dog.speak()` — to resolve the conflict explicitly.
</Warning>

## 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.

```c theme={null}
dynam int numbers = [1, 2, 3, 4, 5];

// Append a value to the end
numbers.push(6);

// Remove the element at index 0
numbers.remove(0);

// Get the current number of elements
int count = len(numbers);
```

<Note>
  `len()` is a **base function** built into the language itself — it is not part of any library and requires no import.
</Note>

## Tuples

<Warning>
  **`tuple` is not yet implemented** in the current compiler. The variadic `tuple args*` form depends on it and is also unavailable. See [Compiler Status](/reference/compiler-status).
</Warning>

A `tuple` is a heterogeneous, dynamically-sized list that can hold values of mixed types. Index into it with `[]` and grow it with `.push()`.

```c theme={null}
tuple t = [1, "hello", 3.14];

// Access elements by index
auto first  = t[0];    // 1
auto second = t[1];    // "hello"

// Append a new element (any type)
t.push("added");

// Get the number of elements
int count = len(t);    // count = 4
```

<Tip>
  Tuples are ideal for collecting heterogeneous return values or passing mixed-type argument streams to variadic functions (`tuple args*`).
</Tip>

## 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.

```c theme={null}
// Named asm function — `return` sends back whatever is in rax (x86_64) or x0 (ARM64).
// A return-type annotation is optional when your assembly already populates that register.
asm addInts(int a, int b) {
    syntax x86_64_linux
    section .text
    mov rax, a
    mov rbx, b
    add rax, rbx
    return
}

// Anonymous asm block — must exit explicitly (here, sys_exit on Linux)
asm {
    syntax x86_64_linux
    section .text
    mov rax, 60      // sys_exit
    mov rdi, 0
    syscall
}
```

<Note>
  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](/language/assembly) page for the full reference — including all syntax targets, anonymous `asm` blocks, and the rules for data declarations.
</Note>

## Namespaces

Use `space` to declare a named namespace, `@` to access its members without globalizing it, and `expose` to bring all its symbols directly into scope.

```c theme={null}
// Declare a namespace
space mySpace {
    int myspacevar = 0;
}

// Access a member with the @ operator (member@namespace)
random@mySpace();

// Globalize a namespace — members become directly accessible
expose mySpace;
random();   // now accessible without @ qualifier
```

<Accordion title="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.
</Accordion>

## 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.

<Note>
  `len()` on `string` and `dynam` works in the current compiler. `tuple` is not yet implemented — see [Compiler Status](/reference/compiler-status).
</Note>

```c theme={null}
string s = "hello";
int l = len(s);           // l = 5

dynam int arr = [1, 2, 3];
int n = len(arr);         // n = 3

tuple t = [1, "hi", 3.14];
int t_len = len(t);       // t_len = 3
```
