57 lines
2.2 KiB
Markdown
57 lines
2.2 KiB
Markdown
---
|
|
name: prism-dag
|
|
description: DAG / graph patterns for Prism — adjacency list rules, arena allocation, Kahn's algorithm, flat buffer layout
|
|
license: MIT
|
|
compatibility: opencode
|
|
metadata:
|
|
domain: core
|
|
---
|
|
## What I do
|
|
|
|
Captures the conventions for Prism's directed acyclic graph (DAG) implementation: how edges are stored, how the graph is validated, and how to avoid common pitfalls.
|
|
|
|
## When to use me
|
|
|
|
Use this when working on graph/DAG structures (`pr_graph.h`, `pr_graph.c`, or `scratchpad/dag.c`), adding new node types, or modifying the topological sort / cycle detection logic.
|
|
|
|
## Conventions
|
|
|
|
### Adjacency lists — separate edge nodes
|
|
|
|
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 and corrupts the graph.
|
|
|
|
```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 edge nodes. Always NULL-check the result — arena allocators can fail if the backing buffer is exhausted.
|
|
|
|
### Flat buffer layout
|
|
|
|
For hot-path graph evaluation, prefer SoA layouts and keep the DAG in contiguous arrays rather than individually allocated linked structures.
|
|
|
|
### Cycle detection
|
|
|
|
Use Kahn's algorithm integrated into `prGraphAddEdge` for cycle detection with rollback. When an edge would create a cycle, the edge is not added and the function returns an error.
|
|
|
|
### Memory management
|
|
|
|
Stack-allocate where possible; pass `WpAllocator *` explicitly for heap allocations.
|