@nahisaho/musubix-dfg 3.4.5 → 3.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/musubix-dfg.js +158 -0
- package/package.json +2 -1
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MUSUBIX DFG CLI
|
|
4
|
+
* Data Flow Graph and Control Flow Graph analysis
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { program } from 'commander';
|
|
10
|
+
import { createDFGAnalyzer, createCFGAnalyzer } from '../dist/index.js';
|
|
11
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
12
|
+
import { resolve } from 'path';
|
|
13
|
+
|
|
14
|
+
const VERSION = '3.4.6';
|
|
15
|
+
|
|
16
|
+
program
|
|
17
|
+
.name('musubix-dfg')
|
|
18
|
+
.description('MUSUBIX Data Flow Graph and Control Flow Graph analysis')
|
|
19
|
+
.version(VERSION);
|
|
20
|
+
|
|
21
|
+
program
|
|
22
|
+
.command('analyze')
|
|
23
|
+
.description('Analyze code and generate DFG/CFG')
|
|
24
|
+
.argument('<file>', 'Source file to analyze')
|
|
25
|
+
.option('-t, --type <type>', 'Analysis type (dfg|cfg|both)', 'both')
|
|
26
|
+
.option('-o, --output <file>', 'Output file (default: stdout)')
|
|
27
|
+
.option('-f, --format <format>', 'Output format (json|dot|mermaid)', 'json')
|
|
28
|
+
.action(async (file, options) => {
|
|
29
|
+
try {
|
|
30
|
+
const filePath = resolve(process.cwd(), file);
|
|
31
|
+
const code = readFileSync(filePath, 'utf-8');
|
|
32
|
+
|
|
33
|
+
const results = {};
|
|
34
|
+
|
|
35
|
+
if (options.type === 'dfg' || options.type === 'both') {
|
|
36
|
+
const dfgAnalyzer = createDFGAnalyzer();
|
|
37
|
+
results.dfg = await dfgAnalyzer.analyze(code, { filePath });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (options.type === 'cfg' || options.type === 'both') {
|
|
41
|
+
const cfgAnalyzer = createCFGAnalyzer();
|
|
42
|
+
results.cfg = await cfgAnalyzer.analyze(code, { filePath });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let output;
|
|
46
|
+
switch (options.format) {
|
|
47
|
+
case 'json':
|
|
48
|
+
output = JSON.stringify(results, null, 2);
|
|
49
|
+
break;
|
|
50
|
+
case 'dot':
|
|
51
|
+
output = formatAsDot(results);
|
|
52
|
+
break;
|
|
53
|
+
case 'mermaid':
|
|
54
|
+
output = formatAsMermaid(results);
|
|
55
|
+
break;
|
|
56
|
+
default:
|
|
57
|
+
output = JSON.stringify(results, null, 2);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (options.output) {
|
|
61
|
+
writeFileSync(options.output, output);
|
|
62
|
+
console.log(`Output written to ${options.output}`);
|
|
63
|
+
} else {
|
|
64
|
+
console.log(output);
|
|
65
|
+
}
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error(`Error: ${error.message}`);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
program
|
|
73
|
+
.command('dependencies')
|
|
74
|
+
.description('Extract variable dependencies from code')
|
|
75
|
+
.argument('<file>', 'Source file to analyze')
|
|
76
|
+
.option('-v, --variable <name>', 'Focus on specific variable')
|
|
77
|
+
.action(async (file, options) => {
|
|
78
|
+
try {
|
|
79
|
+
const filePath = resolve(process.cwd(), file);
|
|
80
|
+
const code = readFileSync(filePath, 'utf-8');
|
|
81
|
+
|
|
82
|
+
const dfgAnalyzer = createDFGAnalyzer();
|
|
83
|
+
const dfg = await dfgAnalyzer.analyze(code, { filePath });
|
|
84
|
+
|
|
85
|
+
if (options.variable) {
|
|
86
|
+
const deps = dfg.getDependencies(options.variable);
|
|
87
|
+
console.log(`Dependencies for '${options.variable}':`);
|
|
88
|
+
deps.forEach(dep => console.log(` - ${dep}`));
|
|
89
|
+
} else {
|
|
90
|
+
console.log('All dependencies:');
|
|
91
|
+
console.log(JSON.stringify(dfg.getAllDependencies(), null, 2));
|
|
92
|
+
}
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.error(`Error: ${error.message}`);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
function formatAsDot(results) {
|
|
100
|
+
const lines = ['digraph G {'];
|
|
101
|
+
|
|
102
|
+
if (results.dfg) {
|
|
103
|
+
lines.push(' subgraph cluster_dfg {');
|
|
104
|
+
lines.push(' label = "Data Flow Graph";');
|
|
105
|
+
results.dfg.nodes?.forEach(node => {
|
|
106
|
+
lines.push(` "${node.id}" [label="${node.label || node.id}"];`);
|
|
107
|
+
});
|
|
108
|
+
results.dfg.edges?.forEach(edge => {
|
|
109
|
+
lines.push(` "${edge.source}" -> "${edge.target}";`);
|
|
110
|
+
});
|
|
111
|
+
lines.push(' }');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (results.cfg) {
|
|
115
|
+
lines.push(' subgraph cluster_cfg {');
|
|
116
|
+
lines.push(' label = "Control Flow Graph";');
|
|
117
|
+
results.cfg.nodes?.forEach(node => {
|
|
118
|
+
lines.push(` "${node.id}" [label="${node.label || node.id}"];`);
|
|
119
|
+
});
|
|
120
|
+
results.cfg.edges?.forEach(edge => {
|
|
121
|
+
lines.push(` "${edge.source}" -> "${edge.target}";`);
|
|
122
|
+
});
|
|
123
|
+
lines.push(' }');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
lines.push('}');
|
|
127
|
+
return lines.join('\n');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function formatAsMermaid(results) {
|
|
131
|
+
const lines = ['flowchart TD'];
|
|
132
|
+
|
|
133
|
+
if (results.dfg) {
|
|
134
|
+
lines.push(' subgraph DFG["Data Flow Graph"]');
|
|
135
|
+
results.dfg.nodes?.forEach(node => {
|
|
136
|
+
lines.push(` ${node.id}["${node.label || node.id}"]`);
|
|
137
|
+
});
|
|
138
|
+
results.dfg.edges?.forEach(edge => {
|
|
139
|
+
lines.push(` ${edge.source} --> ${edge.target}`);
|
|
140
|
+
});
|
|
141
|
+
lines.push(' end');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (results.cfg) {
|
|
145
|
+
lines.push(' subgraph CFG["Control Flow Graph"]');
|
|
146
|
+
results.cfg.nodes?.forEach(node => {
|
|
147
|
+
lines.push(` ${node.id}["${node.label || node.id}"]`);
|
|
148
|
+
});
|
|
149
|
+
results.cfg.edges?.forEach(edge => {
|
|
150
|
+
lines.push(` ${edge.source} --> ${edge.target}`);
|
|
151
|
+
});
|
|
152
|
+
lines.push(' end');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return lines.join('\n');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nahisaho/musubix-dfg",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.6",
|
|
4
4
|
"description": "MUSUBIX Data Flow Graph and Control Flow Graph analysis for neuro-symbolic code understanding",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
"node": ">=20.0.0"
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
+
"commander": "^11.1.0",
|
|
64
65
|
"typescript": "^5.7.2"
|
|
65
66
|
},
|
|
66
67
|
"devDependencies": {
|