> ## 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△ Type System: Primitives, Strings, Arrays, and Structs

> Explore C△'s full type system — C11 primitives, first-class strings, inferred types, dynamic arrays, tuples, structs, and format specifiers.

C△ inherits all C11 primitive types and adds several modern first-class types designed for safe, expressive systems programming. You can use every C11 type exactly as you would in standard C, and layer in C△'s new types wherever they simplify your code. This page covers every type you can reach for in C△, with examples drawn directly from the language.

## Primitive Types

The following types are inherited unchanged from C11. Their sizes, signedness, and semantics are identical to what you already know.

| Type           | Size    | Description                     |
| -------------- | ------- | ------------------------------- |
| `int`          | 4 bytes | Signed 32-bit integer           |
| `unsigned int` | 4 bytes | Unsigned 32-bit integer         |
| `short`        | 2 bytes | Signed 16-bit integer           |
| `long`         | 8 bytes | Signed 64-bit integer           |
| `char`         | 1 byte  | Single byte / ASCII character   |
| `float`        | 4 bytes | Single-precision floating-point |
| `double`       | 8 bytes | Double-precision floating-point |
| `void`         | —       | No type / no return value       |

## Pointers

C△ supports standard C-style pointers with the same `*` and `&` syntax you already know from C11. No new syntax is introduced.

```c theme={null}
// Pointer declarations
int*   ptr;     // Pointer to int
int**  ptr2;    // Pointer to pointer to int
char*  str;     // Pointer to char (C-string)
void*  vptr;    // Generic (untyped) pointer
```

```c theme={null}
// Address-of and dereference
int x    = 42;
int* ptr = &x;   // & yields the address of x
int y    = *ptr; // * dereferences ptr — y is now 42
```

<Note>
  C△'s `autoremove allocate` feature is designed to manage heap-allocated pointer lifetimes automatically. It is **not yet implemented** in the current compiler — see [Compiler Status](/reference/compiler-status).
</Note>

## `string` — First-Class String

`string` is a built-in, automatically memory-managed type for text. Unlike `char*`, you do not manage the underlying buffer yourself — the compiler handles allocation and deallocation.

```c theme={null}
string greeting = "Hello, world!";
string name     = "Hypotenuse";

// Concatenate with the + operator
string full = greeting + " " + name;

// Equality and inequality — compile to strcmp calls under the hood
if (greeting == "Hello, world!") { /* true */ }
if (name != "Other") { /* true */ }
```

<Tip>
  Use `string` instead of `char*` for any text that doesn't need to cross a C ABI boundary. Reserve `char*` for interop with external C libraries.
</Tip>

## `auto` — Type Inference

Declare a variable with `auto` and the compiler infers its type from the initializer. The type is resolved during the simulation pass and is fully type-aware at runtime — `auto` does not mean "untyped".

```c theme={null}
auto x = 42;       // inferred as int
auto s = "hello";  // inferred as string
auto f = 3.14;     // inferred as double
```

You can also pack multiple variables into a single `auto` declaration when they share the same initial value:

```c theme={null}
auto x, z, w = 10;   // all three initialized to 10, each inferred as int
```

<Warning>
  `auto` in C△ is **not** the C11 storage-class specifier — that meaning has been removed entirely. Writing `auto` with C11 intent will raise a `SyntaxError`.
</Warning>

## `dynam` — Dynamic Array

A `dynam` array is a typed, resizable array that grows and shrinks at runtime. You declare it with a bracketed initializer list and modify it with built-in methods.

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

numbers.push(6);      // append 6 to the end
numbers.pop();        // remove and discard the last element
numbers.remove(0);    // remove the element at index 0

int size = len(numbers);   // current number of elements
```

<Note>
  `dynam` arrays have **no fixed capacity**. The runtime expands or contracts the backing allocation automatically — you never call `realloc` manually.
</Note>

## `tuple` — Heterogeneous List

A `tuple` is a dynamically-sized list that holds values of **mixed types**. Access elements by zero-based index, append with `.push()`, and query length with `len()`.

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

auto first  = t[0];    // 1       (int)
auto second = t[1];    // "hello" (string)

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

int t_len = len(t);    // 5 — includes the newly pushed element
```

<Tip>
  Tuples are the backbone of C△'s variadic function support. When you declare a function with `tuple args*`, the compiler packs all call-site arguments into a `tuple` that you can iterate over at runtime.
</Tip>

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

## Struct Types

C△ provides two struct variants. Choose **plain struct** for data types that need constructors and methods but not polymorphism. Choose **`typed` struct** when you need inheritance and want the type to be recognized natively by the compiler.

<Accordion title="Plain Struct">
  Plain structs support an `init` constructor lifecycle, an `end` destructor lifecycle, and member functions. They do **not** support inheritance.

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

      end { /* cleanup on scope exit */ }

      float length() {
          return sqrt(x * x + y * y);
      }
  }

  Vec2 v = Vec2(3.0, 4.0);
  printd("%f", v.length());   // 5.0
  ```

  The `self` keyword gives member functions access to the struct's own fields. It is optional but recommended for clarity when field names shadow parameter names.
</Accordion>

<Accordion title="Typed Struct — Inheritance">
  A `typed` struct becomes a **native type** in the compiler and supports single and multiple inheritance. Declare parent types with `&ParentName` immediately after the struct name.

  ```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 */ }
  }

  Dog d = Dog("Rex");
  printd("%s", d.speak());   // Woof!
  ```

  **Multiple inheritance** chains additional parents left to right. Constructors execute in declaration order (left to right). When two parents define the same method name, qualify the call with the parent struct name to resolve the conflict:

  ```c theme={null}
  typed struct PoliceDog&Dog&Animal(string name, int badge) {
      init { /* initialize PoliceDog */ }
      // Constructor order: Animal → Dog → PoliceDog
      // Disambiguate conflicting methods:
      //   obj.Animal.speak()   — calls Animal's speak
      //   obj.Dog.speak()      — calls Dog's speak
      end { /* cleanup */ }
  }
  ```
</Accordion>

<Warning>
  When multiple parent types define the same method, calling that method directly on the child is **ambiguous** and will not compile. Always resolve conflicts by qualifying with the parent name: `obj.Dog.speak()`.
</Warning>

## Type Format Specifiers

Use these specifiers with `printd` and other formatted-output functions to match each C△ type to its correct format token. The `%k` specifier is unique to C△ and handles `auto` variables whose concrete type is only known at runtime.

| Specifier   | Type                                        |
| ----------- | ------------------------------------------- |
| `%d`        | `int`                                       |
| `%ld`       | `long`                                      |
| `%lld`      | `long long`                                 |
| `%u`        | `unsigned`                                  |
| `%o`        | `octal`                                     |
| `%x` / `%X` | `hex` (lowercase / uppercase)               |
| `%p`        | `pointer`                                   |
| `%f`        | `float` / `double`                          |
| `%s`        | `string` / `char*`                          |
| `%c`        | `char`                                      |
| `%k`        | `auto` (dynamic type — resolved at runtime) |

<Tip>
  When printing an `auto` variable whose type you don't know at compile time, use `%k`. The compiler's simulation pass resolves the underlying type and formats the value correctly.
</Tip>
