Skip to content

Commit

Permalink
d2ir: Glob review fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
nhooyr committed Jul 30, 2023
1 parent 6fdf4b0 commit 6ca36e6
Show file tree
Hide file tree
Showing 6 changed files with 1,381 additions and 69 deletions.
11 changes: 10 additions & 1 deletion d2ast/d2ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -749,7 +749,16 @@ func (kp *KeyPath) Copy() *KeyPath {

func (kp *KeyPath) HasDoubleGlob() bool {
for _, el := range kp.Path {
if el.ScalarString() == "**" {
if el.UnquotedString != nil && el.ScalarString() == "**" {
return true
}
}
return false
}

func (kp *KeyPath) HasGlob() bool {
for _, el := range kp.Path {
if el.UnquotedString != nil && len(el.UnquotedString.Pattern) > 0 {
return true
}
}
Expand Down
12 changes: 1 addition & 11 deletions d2ir/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -661,17 +661,7 @@ func (c *compiler) _compileEdges(refctx *RefContext) {
refctx.ScopeMap.appendFieldReferences(0, refctx.Edge.Dst, refctx)
}
} else {
_, err := refctx.ScopeMap.EnsureField(refctx.Edge.Src, refctx, true)
if err != nil {
c.err.Errors = append(c.err.Errors, err.(d2ast.Error))
continue
}
_, err = refctx.ScopeMap.EnsureField(refctx.Edge.Dst, refctx, true)
if err != nil {
c.err.Errors = append(c.err.Errors, err.(d2ast.Error))
continue
}

var err error
ea, err = refctx.ScopeMap.CreateEdge(eid, refctx)
if err != nil {
c.err.Errors = append(c.err.Errors, err.(d2ast.Error))
Expand Down
76 changes: 19 additions & 57 deletions d2ir/d2ir.go
Original file line number Diff line number Diff line change
Expand Up @@ -935,34 +935,11 @@ func (m *Map) getEdges(eid *EdgeID, refctx *RefContext, ea *[]*Edge) error {
return nil
}

srcKP := d2ast.MakeKeyPath(eid.SrcPath)
lastMatch := 0
for i, el := range srcKP.Path {
for j := lastMatch; j < len(refctx.Edge.Src.Path); j++ {
realEl := refctx.Edge.Src.Path[j]
if el.ScalarString() == realEl.ScalarString() {
srcKP.Path[i] = realEl
lastMatch += j + 1
}
}
}
dstKP := d2ast.MakeKeyPath(eid.DstPath)
lastMatch = 0
for i, el := range dstKP.Path {
for j := lastMatch; j < len(refctx.Edge.Dst.Path); j++ {
realEl := refctx.Edge.Dst.Path[j]
if el.ScalarString() == realEl.ScalarString() {
dstKP.Path[i] = realEl
lastMatch += j + 1
}
}
}

srcFA, err := m.EnsureField(srcKP, nil, false)
srcFA, err := refctx.ScopeMap.EnsureField(refctx.Edge.Src, nil, false)
if err != nil {
return err
}
dstFA, err := m.EnsureField(dstKP, nil, false)
dstFA, err := refctx.ScopeMap.EnsureField(refctx.Edge.Dst, nil, false)
if err != nil {
return err
}
Expand Down Expand Up @@ -1045,51 +1022,36 @@ func (m *Map) createEdge(eid *EdgeID, refctx *RefContext, ea *[]*Edge) error {
return d2parser.Errorf(refctx.Edge.Dst.Path[ij].Unbox(), "edge with board keyword alone doesn't make sense")
}

srcKP := d2ast.MakeKeyPath(eid.SrcPath)
lastMatch := 0
for i, el := range srcKP.Path {
for j := lastMatch; j < len(refctx.Edge.Src.Path); j++ {
realEl := refctx.Edge.Src.Path[j]
if el.ScalarString() == realEl.ScalarString() {
srcKP.Path[i] = realEl
lastMatch += j + 1
}
}
}
dstKP := d2ast.MakeKeyPath(eid.DstPath)
lastMatch = 0
for i, el := range dstKP.Path {
for j := lastMatch; j < len(refctx.Edge.Dst.Path); j++ {
realEl := refctx.Edge.Dst.Path[j]
if el.ScalarString() == realEl.ScalarString() {
dstKP.Path[i] = realEl
lastMatch += j + 1
}
}
}

srcFA, err := m.EnsureField(srcKP, nil, true)
srcFA, err := refctx.ScopeMap.EnsureField(refctx.Edge.Src, refctx, true)
if err != nil {
return err
}
dstFA, err := m.EnsureField(dstKP, nil, true)
dstFA, err := refctx.ScopeMap.EnsureField(refctx.Edge.Dst, refctx, true)
if err != nil {
return err
}

for _, src := range srcFA {
for _, dst := range dstFA {
if src == dst && (len(srcFA) > 1 || len(dstFA) > 1) {
if src == dst && (refctx.Edge.Src.HasGlob() || refctx.Edge.Dst.HasGlob()) {
// Globs do not make self edges.
continue
}

if srcKP.HasDoubleGlob() || dstKP.HasDoubleGlob() {
// If either has a double glob we only select leafs, those without children.
if src.Map().IsContainer() || dst.Map().IsContainer() {
if refctx.Edge.Src.HasDoubleGlob() {
// If src has a double glob we only select leafs, those without children.
if src.Map().IsContainer() {
continue
}
if ParentBoard(src) != ParentBoard(dst) {
continue
}
}
if refctx.Edge.Dst.HasDoubleGlob() {
// If dst has a double glob we only select leafs, those without children.
if dst.Map().IsContainer() {
continue
}
// If either has a double glob we ignore connections across boards
if ParentBoard(src) != ParentBoard(dst) {
continue
}
Expand Down Expand Up @@ -1121,7 +1083,7 @@ func (m *Map) createEdge2(eid *EdgeID, refctx *RefContext, src, dst *Field) (*Ed

eid.Index = nil
eid.Glob = true
ea := m.GetEdges(eid, refctx)
ea := m.GetEdges(eid, nil)
index := len(ea)
eid.Index = &index
eid.Glob = false
Expand Down Expand Up @@ -1400,7 +1362,7 @@ func IDA(n Node) (ida []string) {
}
}

// RelIDA returns the absolute path to n relative to p.
// RelIDA returns the path to n relative to p.
func RelIDA(p, n Node) (ida []string) {
for {
f, ok := n.(*Field)
Expand Down
29 changes: 29 additions & 0 deletions d2ir/pattern_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,35 @@ d
assertQuery(t, m, 0, 0, nil, "(* -> *)[*]")
},
},
{
name: "double-glob/edge/1",
run: func(t testing.TB) {
m, err := compile(t, `fast: {
a
far
}
task: {
a
}
task.** -> fast
`)
assert.Success(t, err)
assertQuery(t, m, 5, 1, nil, "")
},
},
{
name: "double-glob/edge/2",
run: func(t testing.TB) {
m, err := compile(t, `a
**.b -> c
`)
assert.Success(t, err)
assertQuery(t, m, 3, 1, nil, "")
},
},
}

runa(t, tca)
Expand Down
Loading

0 comments on commit 6ca36e6

Please sign in to comment.