Update AGENTS.md

This commit is contained in:
Abdelrahman Said
2026-06-28 13:50:45 +01:00
parent 65cb66dfca
commit 5f7312d616
+52
View File
@@ -28,6 +28,9 @@ All code follows the patterns established in `src/wapp/`. The project prefix is
| Internal/static funcs | `_` + camelCase | `_resolveTopology`, `_execCmd` |
| File-scope globals | `_` + camelCase | `_default_allocator` |
| File-scope constants | SCREAMING_SNAKE | `MAX_NODE_NAME` |
| Variables | snake_case | `vertex_count`, `edge_node` |
- **Variable names**: Prefer descriptive names (e.g. `vertex_count` over `vc`, `edge_node` over `en`). Short names (`i`, `j`, `n`) are acceptable only in tight loop counters or trivial index variables. Avoid single-letter names in non-trivial scopes, and avoid abbreviated names that require the reader to hold a mental dictionary.
### Formatting
@@ -118,6 +121,55 @@ prefer SoA layouts, batch processing, and minimise pointer chasing. Keep
the DAG in contiguous arrays (e.g. adjacency lists packed in flat buffers)
rather than individually allocated linked structures.
### Graph / adjacency lists
Adjacency list nodes must be **separately allocated from the vertex array**.
Never use the vertex struct itself as a linked-list node in another vertex's
adjacency chain — that shares the `next` pointer between two roles (vertex state
vs. edge linking) and causes edges to splice into unintended chains.
```c
// correct — per-edge copy on the arena
static void addEdge(PrGraph *g, const WpAllocator *alloc, u64 from, u64 to) {
PrVertex *src = &g->vertices[from];
PrVertex *dst = wpMemAllocatorAlloc(alloc, sizeof(PrVertex));
if (!dst) { /* handle OOM */ return; }
dst->id = g->vertices[to].id;
dst->value = g->vertices[to].value;
dst->next = src->next;
src->next = dst;
}
// wrong — reuses the destination vertex as the list node
static void addEdge_bad(PrGraph *g, u64 from, u64 to) {
PrVertex *src = &g->vertices[from];
PrVertex *dest = &g->vertices[to];
dest->next = src->next;
src->next = dest; // overwrites dest->next used elsewhere
}
```
Arena bump allocation (`wpMemAllocatorAlloc`) is the natural fit for building
graph structures: per-edge nodes live in the arena and are freed in one shot
when the arena is destroyed.
Always NULL-check the result of `wpMemAllocatorAlloc` — even arena allocators
can fail if the backing buffer is exhausted.
### WpArray usage
| Scenario | API | Size must be… |
|----------|-----|---------------|
| Stack (local, short-lived) | `wpArrayWithCapacity` | compile-time constant |
| Heap (arena-backed) | `wpArrayAllocCapacity` | runtime value |
`wpArrayWithCapacity` creates a VLA-like compound literal on the stack —
passing a runtime variable triggers undefined behaviour and compiler warnings.
Use `wpArrayAllocCapacity` with an arena allocator for runtime sizes.
Initialise arrays with `WP_ARRAY_INIT_FILLED` to set `count = capacity`
immediately, allowing direct indexing.
## Documentation
Save research notes and implementation plans as markdown in `documents/`: