Skip to content

Commit 1cab6d5

Browse files
committed
Add demo support for C
1 parent c3c4bb0 commit 1cab6d5

File tree

6 files changed

+132
-63
lines changed

6 files changed

+132
-63
lines changed

bun.lockb

847 Bytes
Binary file not shown.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"web-tree-sitter": "^0.23.0"
1212
},
1313
"devDependencies": {
14+
"@codemirror/lang-cpp": "^6.0.2",
1415
"@codemirror/lang-go": "^6.0.1",
1516
"@eslint/js": "^9.9.1",
1617
"@rollup/plugin-wasm": "^6.2.2",

src/demo/src/App.svelte

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
<script>
22
import Demo from "../../frontend/src/lib/Demo.svelte";
3-
import demoCode from "./assets/demo.go?raw";
3+
import demoCodeGo from "./assets/demo.go?raw";
4+
import demoCodeC from "./assets/demo.c?raw";
45
</script>
56

67
<main>
7-
<Demo code={demoCode} />
8+
<Demo codeGo={demoCodeGo} codeC={demoCodeC} />
89
</main>
910

1011
<style>

src/demo/src/assets/demo.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
struct tm *getdate(const char *s) {
2+
static struct tm tmbuf;
3+
struct tm *ret = 0;
4+
char *datemsk = getenv("DATEMSK");
5+
FILE *f = 0;
6+
char fmt[100], *p;
7+
int cs;
8+
9+
pthread_setcancelstate(PTHREAD_CANCEL_DEFERRED, &cs);
10+
11+
if (!datemsk) {
12+
getdate_err = 1;
13+
goto out;
14+
}
15+
16+
f = fopen(datemsk, "rbe");
17+
if (!f) {
18+
if (errno == ENOMEM)
19+
getdate_err = 6;
20+
else
21+
getdate_err = 2;
22+
goto out;
23+
}
24+
25+
while (fgets(fmt, sizeof fmt, f)) {
26+
p = strptime(s, fmt, &tmbuf);
27+
if (p && !*p) {
28+
ret = &tmbuf;
29+
goto out;
30+
}
31+
}
32+
33+
if (ferror(f))
34+
getdate_err = 5;
35+
else
36+
getdate_err = 7;
37+
out:
38+
if (f)
39+
fclose(f);
40+
pthread_setcancelstate(cs, 0);
41+
return ret;
42+
}

src/frontend/src/lib/Demo.svelte

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,32 @@
11
<script lang="ts">
22
import CodeMirror from "svelte-codemirror-editor";
33
import { go } from "@codemirror/lang-go";
4+
import { cpp } from "@codemirror/lang-cpp";
45
import Graph from "./Graph.svelte";
6+
import type { Language } from "../../../control-flow/cfg";
57
6-
export let code = "func Example() {\n\tif x {\n\t\treturn\n\t}\n}";
8+
export let codeGo = "func Example() {\n\tif x {\n\t\treturn\n\t}\n}";
9+
export let codeC = "void main() {\n\tif (x) {\n\t\treturn;\n\t}\n}";
10+
11+
let languages: {
12+
language: Language;
13+
text: string;
14+
}[] = [
15+
{ language: "Go" as Language, text: "Go" },
16+
{ language: "C" as Language, text: "C" },
17+
];
18+
let selection = languages[0];
19+
let code = codeGo;
20+
$: {
21+
switch (selection.language) {
22+
case "C":
23+
code = codeC;
24+
break;
25+
case "Go":
26+
code = codeGo;
27+
break;
28+
}
29+
}
730
831
let simplify = true;
932
let flatSwitch = false;
@@ -20,14 +43,32 @@
2043
>
2144
</div>
2245
</header>
23-
<div>
24-
<div class="editor">
25-
<CodeMirror
26-
bind:value={code}
27-
lang={go()}
28-
tabSize={4}
29-
lineWrapping={true}
30-
/>
46+
<div class="editor">
47+
<div class="controls">
48+
<select bind:value={selection} on:change={(e) => console.log(selection)}>
49+
{#each languages as language}
50+
<option value={language}>
51+
{language.text}
52+
</option>
53+
{/each}
54+
</select>
55+
</div>
56+
<div class="codemirror">
57+
{#if selection.language === "Go"}
58+
<CodeMirror
59+
bind:value={codeGo}
60+
lang={go()}
61+
tabSize={4}
62+
lineWrapping={true}
63+
/>
64+
{:else}
65+
<CodeMirror
66+
bind:value={codeC}
67+
lang={cpp()}
68+
tabSize={4}
69+
lineWrapping={true}
70+
/>
71+
{/if}
3172
</div>
3273
</div>
3374
<div class="graph">
@@ -38,7 +79,7 @@
3879
<input type="checkbox" id="flatSwitch" bind:checked={flatSwitch} />
3980
<label for="flatSwitch">Flat Switch</label>
4081
</div>
41-
<Graph {code} {simplify} {flatSwitch} />
82+
<Graph {code} language={selection.language} {simplify} {flatSwitch} />
4283
</div>
4384
</main>
4485

@@ -66,6 +107,10 @@
66107
margin-top: 1rem;
67108
margin-left: 1rem;
68109
}
110+
111+
.codemirror {
112+
padding-top: 1rem;
113+
}
69114
.graph,
70115
.editor {
71116
background-color: white;

src/frontend/src/lib/Graph.svelte

Lines changed: 31 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,24 @@
11
<script lang="ts">
22
import Parser from "web-tree-sitter";
3-
import { newCFGBuilder } from "../../../control-flow/cfg";
3+
import { newCFGBuilder, type Language } from "../../../control-flow/cfg";
44
import { mergeNodeAttrs } from "../../../control-flow/cfg-defs";
55
import { graphToDot } from "../../../control-flow/render";
66
import { simplifyCFG, trimFor } from "../../../control-flow/graph-ops";
77
import { Graphviz } from "@hpcc-js/wasm-graphviz";
8-
import { getFirstFunction, initializeParser } from "./utils";
8+
import { getFirstFunction, initializeParsers, type Parsers } from "./utils";
99
10-
let parser: Parser;
10+
let parsers: Parsers;
1111
let graphviz: Graphviz;
12-
let svg: string = "";
13-
let ast: string = "";
14-
let dot: string = "";
1512
export let code: string;
13+
export let language: Language;
1614
export let verbose: boolean = false;
1715
export let simplify: boolean = true;
1816
export let trim: boolean = true;
1917
export let flatSwitch: boolean = false;
20-
export let showDot: boolean = false;
21-
export let showAST: boolean = false;
2218
2319
async function initialize() {
24-
parser = await initializeParser();
20+
parsers = await initializeParsers();
2521
graphviz = await Graphviz.load();
26-
return { parser, graphviz };
2722
}
2823
2924
interface RenderOptions {
@@ -33,40 +28,34 @@
3328
readonly flatSwitch: boolean;
3429
}
3530
36-
function renderCode(code: string, options: RenderOptions) {
37-
const { trim, simplify, verbose } = options;
38-
const tree = parser.parse(code);
31+
function renderCode(
32+
code: string,
33+
language: Language,
34+
options: RenderOptions,
35+
) {
36+
const { trim, simplify, verbose, flatSwitch } = options;
37+
const tree = parsers[language].parse(code);
38+
const functionSyntax = getFirstFunction(tree);
39+
const builder = newCFGBuilder(language, { flatSwitch });
3940
40-
const functionNode = getFirstFunction(tree);
41+
let cfg = builder.buildCFG(functionSyntax);
4142
42-
ast = functionNode
43-
.toString()
44-
.replaceAll(
45-
"(",
46-
"<div style='margin-left:10px;border-left: 1px #888 solid;'>",
47-
)
48-
.replaceAll(")", "</div>");
49-
console.log(functionNode.childForFieldName("name").text);
50-
let builder = newCFGBuilder("Go", { flatSwitch });
51-
let cfg = builder.buildCFG(functionNode);
52-
if (!cfg) {
53-
return;
54-
}
43+
if (!cfg) return "";
44+
if (trim) cfg = trimFor(cfg);
45+
if (simplify) cfg = simplifyCFG(cfg, mergeNodeAttrs);
5546
56-
if (trim) {
57-
cfg = trimFor(cfg);
58-
}
47+
const dot = graphToDot(cfg, verbose);
5948
60-
if (simplify) {
61-
cfg = simplifyCFG(cfg, mergeNodeAttrs);
62-
}
63-
dot = graphToDot(cfg, verbose);
6449
return graphviz.dot(dot);
6550
}
6651
67-
function renderWrapper(code: string, options: RenderOptions) {
52+
function renderWrapper(
53+
code: string,
54+
language: Language,
55+
options: RenderOptions,
56+
) {
6857
try {
69-
return renderCode(code, options);
58+
return renderCode(code, language, options);
7059
} catch (error) {
7160
return `<p style='border: 2px red solid;'>${error.toString()}</p>`;
7261
}
@@ -76,23 +65,14 @@
7665
<div class="results">
7766
{#await initialize() then}
7867
<div class="graph">
79-
{@html renderWrapper(code, { simplify, verbose, trim, flatSwitch })}
68+
{@html renderWrapper(code, language, {
69+
simplify,
70+
verbose,
71+
trim,
72+
flatSwitch,
73+
})}
8074
</div>
8175
{/await}
82-
{#if showAST}
83-
<br />
84-
<details>
85-
<summary>AST</summary>
86-
{@html ast}
87-
</details>
88-
{/if}
89-
{#if showDot}
90-
<br />
91-
<details>
92-
<summary>DOT</summary>
93-
<pre>{dot}</pre>
94-
</details>
95-
{/if}
9676
</div>
9777

9878
<style>

0 commit comments

Comments
 (0)