1
1
package d2ir
2
2
3
3
import (
4
+ "fmt"
4
5
"html"
5
6
"io/fs"
6
7
"net/url"
@@ -43,10 +44,10 @@ type compiler struct {
43
44
// Used to prevent field globs causing infinite loops.
44
45
globRefContextStack []* RefContext
45
46
// Used to check whether ampersands are allowed in the current map.
46
- mapRefContextStack []* RefContext
47
- lazyGlobBeingApplied bool
48
- markedFieldsForDeletion map [* Map ]map [string ]struct {}
49
- markedEdgesForDeletion map [* Map ][] * EdgeID
47
+ mapRefContextStack []* RefContext
48
+ lazyGlobBeingApplied bool
49
+ deletedFieldsPool map [* Map ]map [string ]* Field
50
+ deletedEdgesPool map [* Map ]map [ string ] * Edge
50
51
}
51
52
52
53
type CompileOptions struct {
@@ -67,10 +68,10 @@ func Compile(ast *d2ast.Map, opts *CompileOptions) (*Map, []string, error) {
67
68
err : & d2parser.ParseError {},
68
69
fs : opts .FS ,
69
70
70
- seenImports : make (map [string ]struct {}),
71
- utf16Pos : opts .UTF16Pos ,
72
- markedFieldsForDeletion : make (map [* Map ]map [string ]struct {} ),
73
- markedEdgesForDeletion : make (map [* Map ][] * EdgeID ),
71
+ seenImports : make (map [string ]struct {}),
72
+ utf16Pos : opts .UTF16Pos ,
73
+ deletedFieldsPool : make (map [* Map ]map [string ]* Field ),
74
+ deletedEdgesPool : make (map [* Map ]map [ string ] * Edge ),
74
75
}
75
76
m := & Map {}
76
77
m .initRoot ()
@@ -85,7 +86,6 @@ func Compile(ast *d2ast.Map, opts *CompileOptions) (*Map, []string, error) {
85
86
c .compileMap (m , ast , ast )
86
87
c .compileSubstitutions (m , nil )
87
88
c .overlayClasses (m )
88
- c .processMarkedDeletions (m )
89
89
90
90
if ! c .err .Empty () {
91
91
return nil , nil , c .err
@@ -868,14 +868,30 @@ func (c *compiler) _compileField(f *Field, refctx *RefContext) {
868
868
// For vars, if we delete the field, it may just resolve to an outer scope var of the same name
869
869
// Instead we keep it around, so that resolveSubstitutions can find it
870
870
if ! IsVar (ParentMap (f )) {
871
- c .markFieldForDeletion (ParentMap (f ), f .Name .ScalarString ())
871
+ parentMap := ParentMap (f )
872
+ key := f .Name .ScalarString ()
873
+
874
+ // Save to pool before deletion
875
+ c .saveDeletedField (parentMap , key , f )
876
+
877
+ // Now delete
878
+ parentMap .DeleteField (key )
872
879
}
873
880
}
874
881
return
875
882
}
876
883
877
884
if len (refctx .Key .Edges ) == 0 && (refctx .Key .Primary .NotNull != nil || refctx .Key .Value .NotNull != nil ) {
878
- c .unmarkFieldForDeletion (ParentMap (f ), f .Name .ScalarString ())
885
+ println ("\033 [1;31m--- DEBUG:" , "=======================" , "\033 [m" )
886
+ parentMap := ParentMap (f )
887
+ key := f .Name .ScalarString ()
888
+
889
+ // Try to restore from pool
890
+ restoredField := c .restoreDeletedField (parentMap , key )
891
+ if restoredField != nil {
892
+ // Add the field back to the parent map
893
+ parentMap .Fields = append (parentMap .Fields , restoredField )
894
+ }
879
895
return
880
896
}
881
897
@@ -1157,12 +1173,23 @@ func (c *compiler) _compileEdges(refctx *RefContext) {
1157
1173
for i , eid := range eida {
1158
1174
if ! eid .Glob && (refctx .Key .Primary .Null != nil || refctx .Key .Value .Null != nil ) {
1159
1175
if ! c .lazyGlobBeingApplied {
1160
- c .markEdgeForDeletion (refctx .ScopeMap , eid )
1176
+ edges := refctx .ScopeMap .GetEdges (eid , nil , nil )
1177
+ if len (edges ) > 0 {
1178
+ // Save to pool before deletion
1179
+ c .saveDeletedEdge (refctx .ScopeMap , eid , edges [0 ])
1180
+ }
1181
+
1182
+ // Now delete
1183
+ refctx .ScopeMap .DeleteEdge (eid )
1161
1184
}
1162
1185
continue
1163
1186
}
1164
1187
if ! eid .Glob && (refctx .Key .Primary .NotNull != nil || refctx .Key .Value .NotNull != nil ) {
1165
- c .unmarkEdgeForDeletion (refctx .ScopeMap , eid )
1188
+ restoredEdge := c .restoreDeletedEdge (refctx .ScopeMap , eid )
1189
+ if restoredEdge != nil {
1190
+ // Add the edge back to the scope map
1191
+ refctx .ScopeMap .Edges = append (refctx .ScopeMap .Edges , restoredEdge )
1192
+ }
1166
1193
continue
1167
1194
}
1168
1195
@@ -1311,50 +1338,93 @@ func (c *compiler) compileArray(dst *Array, a *d2ast.Array, scopeAST *d2ast.Map)
1311
1338
}
1312
1339
}
1313
1340
1314
- func (c * compiler ) markFieldForDeletion (parent * Map , key string ) {
1315
- if c .markedFieldsForDeletion [parent ] == nil {
1316
- c .markedFieldsForDeletion [parent ] = make (map [string ]struct {})
1341
+ func (c * compiler ) saveDeletedField (parent * Map , key string , field * Field ) {
1342
+ fmt .Printf ("DEBUG: Saving deleted field: %s in map %p\n " , key , parent )
1343
+ if c .deletedFieldsPool == nil {
1344
+ c .deletedFieldsPool = make (map [* Map ]map [string ]* Field )
1317
1345
}
1318
- c.markedFieldsForDeletion [parent ][key ] = struct {}{}
1346
+ if c .deletedFieldsPool [parent ] == nil {
1347
+ c .deletedFieldsPool [parent ] = make (map [string ]* Field )
1348
+ }
1349
+ c.deletedFieldsPool [parent ][key ] = field
1319
1350
}
1320
1351
1321
- func (c * compiler ) unmarkFieldForDeletion (parent * Map , key string ) {
1322
- if c .markedFieldsForDeletion [parent ] != nil {
1323
- delete (c .markedFieldsForDeletion [parent ], key )
1352
+ func (c * compiler ) restoreDeletedField (parent * Map , key string ) * Field {
1353
+ if c .deletedFieldsPool == nil || c .deletedFieldsPool [parent ] == nil {
1354
+ return nil
1355
+ }
1356
+
1357
+ field , ok := c.deletedFieldsPool [parent ][key ]
1358
+ if ! ok {
1359
+ return nil
1324
1360
}
1361
+
1362
+ fmt .Printf ("DEBUG: Restoring deleted field: %s in map %p\n " , key , parent )
1363
+ delete (c .deletedFieldsPool [parent ], key )
1364
+ return field
1325
1365
}
1326
1366
1327
- func (c * compiler ) markEdgeForDeletion (parent * Map , eid * EdgeID ) {
1328
- c .markedEdgesForDeletion [parent ] = append (c .markedEdgesForDeletion [parent ], eid .Copy ())
1367
+ func (c * compiler ) saveDeletedEdge (parent * Map , eid * EdgeID , edge * Edge ) {
1368
+ fmt .Printf ("DEBUG: Saving deleted edge in map %p\n " , parent )
1369
+ if c .deletedEdgesPool == nil {
1370
+ c .deletedEdgesPool = make (map [* Map ]map [string ]* Edge )
1371
+ }
1372
+ if c .deletedEdgesPool [parent ] == nil {
1373
+ c .deletedEdgesPool [parent ] = make (map [string ]* Edge )
1374
+ }
1375
+
1376
+ // Create a string key for the edge
1377
+ var key string
1378
+ if eid .SrcArrow {
1379
+ key = "<-"
1380
+ }
1381
+ key += strings .Join (stringifyPath (eid .SrcPath ), "." )
1382
+ key += "->"
1383
+ if eid .DstArrow {
1384
+ key += ">"
1385
+ }
1386
+ key += strings .Join (stringifyPath (eid .DstPath ), "." )
1387
+ if eid .Index != nil {
1388
+ key += fmt .Sprintf ("[%d]" , * eid .Index )
1389
+ }
1390
+
1391
+ c.deletedEdgesPool [parent ][key ] = edge
1329
1392
}
1330
1393
1331
- func (c * compiler ) unmarkEdgeForDeletion (parent * Map , eid * EdgeID ) {
1332
- edges := c .markedEdgesForDeletion [parent ]
1333
- for i , e := range edges {
1334
- if e .Match (eid ) {
1335
- // Remove this edge from the slice
1336
- c .markedEdgesForDeletion [parent ] = append (edges [:i ], edges [i + 1 :]... )
1337
- break
1338
- }
1394
+ func stringifyPath (path []d2ast.String ) []string {
1395
+ result := make ([]string , len (path ))
1396
+ for i , s := range path {
1397
+ result [i ] = s .ScalarString ()
1339
1398
}
1399
+ return result
1340
1400
}
1341
1401
1342
- func (c * compiler ) processMarkedDeletions (m * Map ) {
1343
- // Process field deletions
1344
- for parent , keys := range c .markedFieldsForDeletion {
1345
- for key := range keys {
1346
- parent .DeleteField (key )
1347
- }
1402
+ func (c * compiler ) restoreDeletedEdge (parent * Map , eid * EdgeID ) * Edge {
1403
+ if c .deletedEdgesPool == nil || c .deletedEdgesPool [parent ] == nil {
1404
+ return nil
1348
1405
}
1349
1406
1350
- // Process edge deletions
1351
- for parent , edges := range c .markedEdgesForDeletion {
1352
- for _ , eid := range edges {
1353
- parent .DeleteEdge (eid )
1354
- }
1407
+ // Create a string key for the edge
1408
+ var key string
1409
+ if eid .SrcArrow {
1410
+ key = "<-"
1411
+ }
1412
+ key += strings .Join (stringifyPath (eid .SrcPath ), "." )
1413
+ key += "->"
1414
+ if eid .DstArrow {
1415
+ key += ">"
1416
+ }
1417
+ key += strings .Join (stringifyPath (eid .DstPath ), "." )
1418
+ if eid .Index != nil {
1419
+ key += fmt .Sprintf ("[%d]" , * eid .Index )
1420
+ }
1421
+
1422
+ edge , ok := c.deletedEdgesPool [parent ][key ]
1423
+ if ! ok {
1424
+ return nil
1355
1425
}
1356
1426
1357
- // Clear the tracking maps
1358
- c . markedFieldsForDeletion = make ( map [ * Map ] map [ string ] struct {} )
1359
- c . markedEdgesForDeletion = make ( map [ * Map ][] * EdgeID )
1427
+ fmt . Printf ( "DEBUG: Restoring deleted edge in map %p \n " , parent )
1428
+ delete ( c . deletedEdgesPool [ parent ], key )
1429
+ return edge
1360
1430
}
0 commit comments