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` | | Internal/static funcs | `_` + camelCase | `_resolveTopology`, `_execCmd` |
| File-scope globals | `_` + camelCase | `_default_allocator` | | File-scope globals | `_` + camelCase | `_default_allocator` |
| File-scope constants | SCREAMING_SNAKE | `MAX_NODE_NAME` | | 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 ### 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) the DAG in contiguous arrays (e.g. adjacency lists packed in flat buffers)
rather than individually allocated linked structures. 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 ## Documentation
Save research notes and implementation plans as markdown in `documents/`: Save research notes and implementation plans as markdown in `documents/`: