arabelatso/control-flow-abstraction-generator
Generate abstract Control Flow Graph (CFG) representations of programs showing loops, branches, and function calls for static analysis or verification. Use when users need to: (1) Visualize program control flow structure, (2) Generate CFGs for static analysis tools, (3) Create control flow abstractions for formal verification, (4) Analyze program paths and reachability, (5) Document program structure. Supports both function-level (intraprocedural) and program-level (interprocedural) analysis with multiple output formats (textual, DOT/Graphviz, JSON).
npx skills add https://github.com/ArabelaTso/Skills-4-SE --skill control-flow-abstraction-generator
Generate abstract Control Flow Graph representations of programs.
This skill analyzes program code and generates Control Flow Graphs (CFGs) that abstract the program's control flow structure. CFGs show how execution flows through the program via nodes (statements, conditions) and edges (control transfers), making them suitable for static analysis, formal verification, and program understanding.
Provide:
The skill will generate:
Identify program constructs:
Generate nodes for each construct:
Entry Node: Function/program start
ENTRY or function nameentryExit Node: Function/program end
EXIT or returnexitStatement Node: Regular statement
statementCondition Node: Branch decision
conditionMerge Node: Branch join point
MERGE or emptymergeConnect nodes with appropriate edges:
Sequential Edge: Normal flow
→True Edge: Condition true branch
T or trueFalse Edge: Condition false branch
F or falseBack Edge: Loop iteration
↶ or backCall Edge: Function invocation (interprocedural)
⇒ or callReturn Edge: Function return (interprocedural)
⇐ or returnLoops: Create back edges from body to header
Break: Create edge from break statement to loop exit
Continue: Create back edge from continue to loop header
Return: Create edge from return to EXIT node
Exceptions: Create exception edges from try block to catch handlers
Produce CFG in requested format(s):
Code:
def max_value(x, y):
if x > y:
result = x
else:
result = y
return result
CFG (Textual):
Node 1 (ENTRY):
Label: max_value
Successors: [2]
Node 2 (x > y):
Type: condition
Predecessors: [1]
Successors: [3 (true), 4 (false)]
Node 3 (result = x):
Type: statement
Predecessors: [2]
Successors: [5]
Node 4 (result = y):
Type: statement
Predecessors: [2]
Successors: [5]
Node 5 (MERGE):
Type: merge
Predecessors: [3, 4]
Successors: [6]
Node 6 (return result):
Type: statement
Predecessors: [5]
Successors: [7]
Node 7 (EXIT):
Predecessors: [6]
CFG (Visual):
ENTRY
↓
[x > y]
↓ ↓
T↓ ↓F
↓ ↓
[result=x] [result=y]
↓ ↓
└→MERGE←┘
↓
[return result]
↓
EXIT
CFG (DOT):
digraph CFG {
node [shape=box];
n1 [label="ENTRY", shape=ellipse];
n2 [label="x > y", shape=diamond];
n3 [label="result = x"];
n4 [label="result = y"];
n5 [label="MERGE", shape=circle];
n6 [label="return result"];
n7 [label="EXIT", shape=ellipse];
n1 -> n2;
n2 -> n3 [label="T", color=green];
n2 -> n4 [label="F", color=red];
n3 -> n5;
n4 -> n5;
n5 -> n6;
n6 -> n7;
}
Code:
def sum_to_n(n):
sum = 0
i = 0
while i < n:
sum += i
i += 1
return sum
CFG (Visual):
ENTRY
↓
[sum = 0]
↓
[i = 0]
↓
┌─────────┐
↓ ↑
[i < n] ↑ (back edge)
↓ ↓ ↑
T↓ ↓F ↑
↓ ↓ ↑
[sum += i] ↑
↓ ↑
[i += 1]──────┘
↓F
[return sum]
↓
EXIT
Key Features:
[i < n][i += 1] to [i < n]CFG (Textual):
Node 1 (ENTRY)
→ Node 2
Node 2 (sum = 0)
→ Node 3
Node 3 (i = 0)
→ Node 4
Node 4 (i < n) [LOOP HEADER]
→T Node 5
→F Node 7
Node 5 (sum += i)
→ Node 6
Node 6 (i += 1)
→ Node 4 [BACK EDGE]
Node 7 (return sum)
→ Node 8
Node 8 (EXIT)
Code:
def process(arr, threshold):
result = []
for item in arr:
if item > threshold:
result.append(item * 2)
else:
if item < 0:
continue
result.append(item)
return result
CFG (Visual):
ENTRY
↓
[result = []]
↓
[i = 0]
↓
┌──────────────────────┐
↓ ↑
[i < len(arr)] ↑
↓T ↑
[item = arr[i]] ↑
↓ ↑
[item > threshold] ↑
↓T ↓F ↑
[result.append [item<0] ↑
(item*2)] ↓T ↑
↓ └──────┘ (continue)
↓ ↓F
↓ [result.append(item)]
↓ ↓
└──→MERGE←──────┘
↓
[i += 1]───────┘
↓F
[return result]
↓
EXIT
Key Features:
Code:
def factorial(n):
if n <= 1:
return 1
return n * factorial(n-1)
def compute(x):
result = factorial(x)
return result + 1
Intraprocedural CFG (factorial only):
factorial:ENTRY
↓
[n <= 1]
↓ ↓
T↓ ↓F
↓ ↓
[return 1] [call factorial(n-1)]
↓ ↓
↓ [return n * result]
↓ ↓
└──→EXIT←───┘
Interprocedural CFG (with call edges):
compute:ENTRY
↓
[call factorial(x)] ⇒ factorial:ENTRY
↓ ↓
↓ [n <= 1]
↓ ↓ ↓
↓ ... ...
↓ ↓
[result = ...] ⇐ factorial:EXIT
↓
[return result + 1]
↓
compute:EXIT
Key Features:
Human-readable node and edge listing:
Node <id> (<label>):
Type: <type>
Predecessors: [<ids>]
Successors: [<ids>]
Graph visualization format:
digraph CFG {
node [shape=box];
n1 [label="...", shape=...];
n1 -> n2 [label="...", color=...];
}
Generate PNG/SVG with: dot -Tpng cfg.dot -o cfg.png
Machine-readable for tool integration:
{
"nodes": [
{"id": 1, "label": "...", "type": "..."}
],
"edges": [
{"from": 1, "to": 2, "type": "..."}
]
}
Scope: Single function
Nodes: Statements within function
Edges: Control flow within function
Calls: Treated as single statement nodes
Use cases:
Scope: Multiple functions
Nodes: Statements across all functions
Edges: Control flow + call/return edges
Calls: Explicit call and return edges
Use cases:
Node A dominates node B if every path from ENTRY to B passes through A.
Uses: Loop header identification, optimization
Node A post-dominates node B if every path from B to EXIT passes through A.
Uses: Control dependence, merge point identification
Node B is reachable from node A if there exists a path from A to B.
Uses: Dead code detection, path analysis
Maximal set of nodes where every node is reachable from every other.
Uses: Loop detection, cycle analysis
Pattern: Linear flow
See: cfg_patterns.md
Pattern: Diamond shape with merge
See: cfg_patterns.md
Pattern: Back edge from body to header
See: cfg_patterns.md
Pattern: Direct edges to exit/header
See: cfg_patterns.md
Pattern: Exception edges to handlers
See: cfg_patterns.md
Detailed CFG construction patterns:
Load this reference when:
Take arabelatso/control-flow-abstraction-generator from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.