Skip to main content
Partial implementation. Only allocate (including its custom-size syntax) and free are supported by the current Hypotenuse Compiler. autoremove and Robbery are not yet implemented. See Compiler Status.
C△ gives you full control over memory while adding safer, more expressive tools on top of raw C heap management. Instead of reaching directly for malloc and free, you have three distinct mechanisms at your disposal: manual allocation with allocate and free, automatic deallocation with autoremove, and ownership transfer through Robbery. Together, they let you write systems code that is both precise and resistant to common memory bugs.

Stack vs Heap

Variables you declare normally live on the stack and are reclaimed automatically when their enclosing scope exits. To keep data alive beyond a scope — or to allocate large buffers — you put it on the heap using the allocate keyword.
LocationHowNotes
StackNormal variable declarationFreed automatically on scope exit
Heapallocate keywordMust be freed manually or via autoremove

allocate — Heap Allocation

Use allocate to place a variable or array on the heap. There are two syntax forms depending on whether you want an array of elements or a single variable with a specific byte size.
// Allocate an array of N elements
allocate int buffer[256];
allocate string names[10];

// Allocate a single variable with a custom byte size
allocate int x(64);   // one int backed by 64 bytes
SyntaxMeaning
allocate int buf[256]Array of 256 int elements on the heap
allocate int x(64)Single variable allocated with a 64-byte backing size
Custom byte sizes specified with the parenthesis form are bounds-checked at compile time. If the requested size is incompatible with the declared type, the compiler reports an error before generating any code.

free — Manual Deallocation

Call free to release the heap memory you allocated with allocate. The pointer is invalidated immediately after the call.
allocate int x(8);   // allocate 8 bytes
x = 42;
free(x);             // release the allocation
Forgetting to free a heap variable is a memory leak. If the allocation does not need to outlive the current scope, use autoremove instead so the compiler handles deallocation for you.

autoremove — Automatic Heap Deallocation

Prefix allocate with autoremove and the compiler’s simulation pass takes responsibility for freeing the memory. The pass performs static analysis to find the last use of the variable and inserts a free call at exactly that point during code generation. You may still free the pointer at any point, as long as it’s not being used before its last use.
autoremove allocate int buf[512];
// ... use buf freely ...
// free is inserted automatically after the last use
Prefer autoremove whenever you allocate memory that does not need to outlive the current scope. You get heap allocation with zero manual bookkeeping and zero runtime overhead — the free is woven in at compile time unless manually done.
Because the simulation pass runs before code generation, there is no runtime cost for this analysis. The emitted C code contains an ordinary free call placed at precisely the right line.

Robbery — Ownership Transfer

Robbery handles the case where an autoremove variable is about to be freed but another pointer still needs its memory. When a second pointer takes the address of an autoremove variable at the point the original would drop, the new pointer inherits ownership and becomes a plain heap variable — one that you manage manually or hand off to another autoremove binding.
autoremove allocate int data[100];

// data is about to reach its last use — backup steals ownership
int* backup = &data;

// backup is now a plain heap variable; data is gone
// no double-free, no dangling pointer
// no need to free the robbed variable
The simulation pass validates every robbery before emitting code. If the transfer would create a use-after-free or a double-free, the compiler rejects the program with a clear diagnostic. You will never need to free a robbed variable when programming.

Lifecycle Summary

The three memory flows map directly onto the three mechanisms:
[allocate]  →  [use]  →  [free]
    ↑ manual: you call free yourself

[autoremove allocate]  →  [use]  →  [auto-free at last use]
    ↑ simulation pass: compiler inserts free at compile time

[autoremove]  →  [robbery]  →  [plain heap variable]
    ↑ ownership transfer: new pointer takes over, original is gone

Rules & Gotchas

  • Do not double-free a variable after it has already been freed
  • Do not try to access an already freed portion of memory
  • Avoid leaks in memory as much as possible and try to use robbery to aid in this