Skip to content

Commit 12b53e9

Browse files
committed
Move data preparation to UI side of debugger
1 parent d0d38b7 commit 12b53e9

File tree

2 files changed

+198
-170
lines changed

2 files changed

+198
-170
lines changed

rust/cubesql/cubesql/egraph-debug-template/src/index.tsx

Lines changed: 177 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22,32 +22,53 @@ import { z } from 'zod';
2222

2323
import statesData from './states.json';
2424

25-
const InputNodeData = z.object({
26-
id: z.string(),
27-
label: z.string(),
28-
comboId: z.string(),
25+
type InputNodeData = {
26+
id: string;
27+
label: string;
28+
comboId: string;
29+
};
30+
31+
type InputEdgeData = {
32+
source: string;
33+
target: string;
34+
};
35+
36+
type InputComboData = {
37+
id: string;
38+
label: string;
39+
};
40+
41+
const EClassDebugData = z.object({
42+
id: z.number(),
43+
canon: z.number(),
2944
});
30-
type InputNodeData = z.infer<typeof InputNodeData>;
45+
type EClassDebugData = z.infer<typeof EClassDebugData>;
3146

32-
const InputEdgeData = z.object({
33-
source: z.string(),
34-
target: z.string(),
47+
const ENodeDebugData = z.object({
48+
enode: z.string(),
49+
eclass: z.number(),
50+
children: z.array(z.number()),
3551
});
36-
type InputEdgeData = z.infer<typeof InputEdgeData>;
52+
type ENodeDebugData = z.infer<typeof ENodeDebugData>;
3753

38-
const InputComboData = z.object({
39-
id: z.string(),
40-
label: z.string(),
54+
const EGraphDebugState = z.object({
55+
eclasses: z.array(EClassDebugData),
56+
enodes: z.array(ENodeDebugData),
4157
});
42-
type InputComboData = z.infer<typeof InputComboData>;
58+
type EGraphDebugState = z.infer<typeof EGraphDebugState>;
59+
60+
type PreparedStateData = {
61+
nodes: Array<InputNodeData>;
62+
removedNodes: Array<InputNodeData>;
63+
edges: Array<InputEdgeData>;
64+
removedEdges: Array<InputEdgeData>;
65+
combos: Array<InputComboData>;
66+
removedCombos: Array<InputComboData>;
67+
appliedRules: Array<string>;
68+
};
4369

4470
const StateData = z.object({
45-
nodes: z.array(InputNodeData),
46-
removedNodes: z.array(InputNodeData),
47-
edges: z.array(InputEdgeData),
48-
removedEdges: z.array(InputEdgeData),
49-
combos: z.array(InputComboData),
50-
removedCombos: z.array(InputComboData),
71+
egraph: EGraphDebugState,
5172
appliedRules: z.array(z.string()),
5273
});
5374
type StateData = z.infer<typeof StateData>;
@@ -61,14 +82,139 @@ type NodeData = {
6182
type Node = ReactFlowNode<NodeData>;
6283
type Edge = ReactFlowEdge<null>;
6384

64-
const states = InputData.parse(statesData);
85+
const states: InputData = InputData.parse(statesData);
86+
87+
function prepareStates(states: InputData): Array<PreparedStateData> {
88+
const result = [];
89+
let previousDebugData:
90+
| {
91+
nodes: Array<InputNodeData>;
92+
edges: Array<InputEdgeData>;
93+
combos: Array<InputComboData>;
94+
}
95+
| undefined;
96+
97+
for (const { egraph, appliedRules } of states) {
98+
let nodes = egraph.enodes
99+
.map((node) => {
100+
return {
101+
id: `${node.eclass}-${node.enode}`,
102+
label: node.enode,
103+
comboId: `c${node.eclass}`,
104+
} as InputNodeData;
105+
})
106+
.concat(
107+
egraph.eclasses.map((eclass) => {
108+
return {
109+
id: eclass.id.toString(),
110+
label: eclass.id.toString(),
111+
comboId: `c${eclass.id}`,
112+
} as InputNodeData;
113+
}),
114+
);
115+
116+
let edges = egraph.enodes
117+
.map((node) => {
118+
return {
119+
source: node.eclass.toString(),
120+
target: `${node.eclass}-${node.enode}`,
121+
} as InputEdgeData;
122+
})
123+
.concat(
124+
egraph.enodes.flatMap((node) => {
125+
return node.children.map((child) => {
126+
return {
127+
source: `${node.eclass}-${node.enode}`,
128+
target: child.toString(),
129+
};
130+
});
131+
}),
132+
);
133+
134+
let combos = egraph.eclasses.map((eclass) => {
135+
return {
136+
id: `c${eclass.id}`,
137+
label: `#${eclass.id}`,
138+
} as InputComboData;
139+
});
140+
141+
const nodesClone = nodes.slice();
142+
const edgesClone = edges.slice();
143+
const combosClone = combos.slice();
144+
145+
let removedNodes: Array<InputNodeData> = [];
146+
let removedEdges: Array<InputEdgeData> = [];
147+
let removedCombos: Array<InputComboData> = [];
148+
149+
if (previousDebugData !== undefined) {
150+
const {
151+
nodes: prevNodes,
152+
edges: prevEdges,
153+
combos: prevCombos,
154+
} = previousDebugData;
155+
nodes = nodes.filter(
156+
(n) => !prevNodes.some((ln) => ln.id === n.id),
157+
);
158+
edges = edges.filter(
159+
(n) =>
160+
!prevEdges.some(
161+
(ln) =>
162+
ln.source === n.source && ln.target === n.target,
163+
),
164+
);
165+
combos = combos.filter(
166+
(n) => !prevCombos.some((ln) => ln.id === n.id),
167+
);
168+
169+
removedNodes = prevNodes.slice();
170+
removedNodes = removedNodes.filter(
171+
(n) => !nodesClone.some((ln) => ln.id === n.id),
172+
);
173+
174+
removedEdges = prevEdges.slice();
175+
removedEdges = removedEdges.filter(
176+
(n) =>
177+
!edgesClone.some(
178+
(ln) =>
179+
ln.source === n.source && ln.target === n.target,
180+
),
181+
);
182+
183+
removedCombos = prevCombos.slice();
184+
removedCombos = removedCombos.filter(
185+
(n) => !combosClone.some((ln) => ln.id === n.id),
186+
);
187+
}
188+
189+
let debugData = {
190+
nodes,
191+
edges,
192+
combos,
193+
removedNodes,
194+
removedEdges,
195+
removedCombos,
196+
appliedRules,
197+
} as PreparedStateData;
198+
199+
result.push(debugData);
200+
previousDebugData = {
201+
nodes: nodesClone,
202+
edges: edgesClone,
203+
combos: combosClone,
204+
};
205+
}
206+
207+
return result;
208+
}
209+
210+
let preparedStates = prepareStates(states);
65211

66212
// First is initial state
67-
const totalIterations = states.length - 1;
213+
const totalIterations = preparedStates.length - 1;
68214
const data = {
69-
nodes: states[0].nodes,
70-
edges: states[0].edges,
71-
combos: states[0].combos,
215+
nodes: preparedStates[0].nodes,
216+
edges: preparedStates[0].edges,
217+
combos: preparedStates[0].combos,
72218
};
73219
const sizeByNode = (n: InputNodeData): [number, number] => [
74220
60 + n.label.length * 5,
@@ -409,7 +555,7 @@ const LayoutFlow = () => {
409555
}
410556
let newNodes = preNodes;
411557
let newEdges = preEdges;
412-
const toRemove = states[stateIdx];
558+
const toRemove = preparedStates[stateIdx];
413559
let toRemoveNodeIds = (toRemove.nodes as Array<{ id: string }>)
414560
.concat(toRemove.combos)
415561
.map((n) => n.id);
@@ -428,7 +574,7 @@ const LayoutFlow = () => {
428574
newEdges = newEdges.concat(
429575
Object.keys(edgeMap).map((key) => edgeMap[key]),
430576
);
431-
const toHighlight = states[stateIdx - 1];
577+
const toHighlight = preparedStates[stateIdx - 1];
432578
const toHighlightNodeIds = (toHighlight.nodes as Array<{ id: string }>)
433579
.concat(toHighlight.combos)
434580
.map((n) => n.id);
@@ -446,13 +592,13 @@ const LayoutFlow = () => {
446592
};
447593

448594
const nextState = () => {
449-
if (stateIdx === states.length - 1) {
595+
if (stateIdx === preparedStates.length - 1) {
450596
return;
451597
}
452598
let newNodes = preNodes;
453599
let newEdges = preEdges;
454600
setStateIdx(stateIdx + 1);
455-
const toAdd = states[stateIdx + 1];
601+
const toAdd = preparedStates[stateIdx + 1];
456602
let toRemoveNodeIds = (toAdd.removedNodes as Array<{ id: string }>)
457603
.concat(toAdd.removedCombos)
458604
.map((n) => n.id);
@@ -590,7 +736,9 @@ const LayoutFlow = () => {
590736
))}
591737
</div>
592738
<div>
593-
<span>{states[stateIdx].appliedRules.join(', ')}</span>
739+
<span>
740+
{preparedStates[stateIdx].appliedRules.join(', ')}
741+
</span>
594742
</div>
595743
</Panel>
596744
</ReactFlow>

0 commit comments

Comments
 (0)