@@ -22,32 +22,53 @@ import { z } from 'zod';
2222
2323import 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
4470const 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} ) ;
5374type StateData = z . infer < typeof StateData > ;
@@ -61,14 +82,139 @@ type NodeData = {
6182type Node = ReactFlowNode < NodeData > ;
6283type 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 ;
68214const 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} ;
73219const 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