Skip to content

Commit

Permalink
Merge pull request #1552 from nhooyr/lazy-globs
Browse files Browse the repository at this point in the history
d2ir: Implement lazy globs and triple glob
  • Loading branch information
nhooyr authored Sep 5, 2023
2 parents 24a1e00 + 64c2c84 commit dd131f8
Show file tree
Hide file tree
Showing 117 changed files with 90,869 additions and 10,496 deletions.
231 changes: 225 additions & 6 deletions d2ast/d2ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,15 @@ func (m *Map) IsFileMap() bool {
return m.Range.Start.Line == 0 && m.Range.Start.Column == 0
}

func (m *Map) HasFilter() bool {
for _, n := range m.Nodes {
if n.MapKey != nil && (n.MapKey.Ampersand || n.MapKey.NotAmpersand) {
return true
}
}
return false
}

// TODO: require @ on import values for readability
type Key struct {
Range Range `json:"range"`
Expand Down Expand Up @@ -641,7 +650,79 @@ type Key struct {
Value ValueBox `json:"value"`
}

// TODO maybe need to compare Primary
func (mk1 *Key) D2OracleEquals(mk2 *Key) bool {
if mk1.Ampersand != mk2.Ampersand {
return false
}
if (mk1.Key == nil) != (mk2.Key == nil) {
return false
}
if (mk1.EdgeIndex == nil) != (mk2.EdgeIndex == nil) {
return false
}
if (mk1.EdgeKey == nil) != (mk2.EdgeKey == nil) {
return false
}
if len(mk1.Edges) != len(mk2.Edges) {
return false
}
if (mk1.Value.Map == nil) != (mk2.Value.Map == nil) {
if mk1.Value.Map != nil && len(mk1.Value.Map.Nodes) > 0 {
return false
}
if mk2.Value.Map != nil && len(mk2.Value.Map.Nodes) > 0 {
return false
}
} else if (mk1.Value.Unbox() == nil) != (mk2.Value.Unbox() == nil) {
return false
}

if mk1.Key != nil {
if len(mk1.Key.Path) != len(mk2.Key.Path) {
return false
}
for i, id := range mk1.Key.Path {
if id.Unbox().ScalarString() != mk2.Key.Path[i].Unbox().ScalarString() {
return false
}
}
}
if mk1.EdgeKey != nil {
if len(mk1.EdgeKey.Path) != len(mk2.EdgeKey.Path) {
return false
}
for i, id := range mk1.EdgeKey.Path {
if id.Unbox().ScalarString() != mk2.EdgeKey.Path[i].Unbox().ScalarString() {
return false
}
}
}

if mk1.Value.Map != nil && len(mk1.Value.Map.Nodes) > 0 {
if len(mk1.Value.Map.Nodes) != len(mk2.Value.Map.Nodes) {
return false
}
for i := range mk1.Value.Map.Nodes {
if !mk1.Value.Map.Nodes[i].MapKey.Equals(mk2.Value.Map.Nodes[i].MapKey) {
return false
}
}
}

if mk1.Value.Unbox() != nil {
if (mk1.Value.ScalarBox().Unbox() == nil) != (mk2.Value.ScalarBox().Unbox() == nil) {
return false
}
if mk1.Value.ScalarBox().Unbox() != nil {
if mk1.Value.ScalarBox().Unbox().ScalarString() != mk2.Value.ScalarBox().Unbox().ScalarString() {
return false
}
}
}

return true
}

func (mk1 *Key) Equals(mk2 *Key) bool {
if mk1.Ampersand != mk2.Ampersand {
return false
Expand All @@ -652,12 +733,22 @@ func (mk1 *Key) Equals(mk2 *Key) bool {
if (mk1.EdgeIndex == nil) != (mk2.EdgeIndex == nil) {
return false
}
if mk1.EdgeIndex != nil {
if !mk1.EdgeIndex.Equals(mk2.EdgeIndex) {
return false
}
}
if (mk1.EdgeKey == nil) != (mk2.EdgeKey == nil) {
return false
}
if len(mk1.Edges) != len(mk2.Edges) {
return false
}
for i := range mk1.Edges {
if !mk1.Edges[i].Equals(mk2.Edges[i]) {
return false
}
}
if (mk1.Value.Map == nil) != (mk2.Value.Map == nil) {
if mk1.Value.Map != nil && len(mk1.Value.Map.Nodes) > 0 {
return false
Expand Down Expand Up @@ -712,6 +803,15 @@ func (mk1 *Key) Equals(mk2 *Key) bool {
}
}

if mk1.Primary.Unbox() != nil {
if (mk1.Primary.Unbox() == nil) != (mk2.Primary.Unbox() == nil) {
return false
}
if mk1.Primary.ScalarString() != mk2.Primary.ScalarString() {
return false
}
}

return true
}

Expand All @@ -723,7 +823,43 @@ func (mk *Key) SetScalar(scalar ScalarBox) {
}
}

func (mk *Key) HasQueryGlob() bool {
func (mk *Key) HasGlob() bool {
if mk.Key.HasGlob() {
return true
}
for _, e := range mk.Edges {
if e.Src.HasGlob() || e.Dst.HasGlob() {
return true
}
}
if mk.EdgeIndex != nil && mk.EdgeIndex.Glob {
return true
}
if mk.EdgeKey.HasGlob() {
return true
}
return false
}

func (mk *Key) HasTripleGlob() bool {
if mk.Key.HasTripleGlob() {
return true
}
for _, e := range mk.Edges {
if e.Src.HasTripleGlob() || e.Dst.HasTripleGlob() {
return true
}
}
if mk.EdgeIndex != nil && mk.EdgeIndex.Glob {
return true
}
if mk.EdgeKey.HasTripleGlob() {
return true
}
return false
}

func (mk *Key) SupportsGlobFilters() bool {
if mk.Key.HasGlob() && len(mk.Edges) == 0 {
return true
}
Expand All @@ -736,6 +872,11 @@ func (mk *Key) HasQueryGlob() bool {
return false
}

func (mk *Key) Copy() *Key {
mk2 := *mk
return &mk2
}

type KeyPath struct {
Range Range `json:"range"`
Path []*StringBox `json:"path"`
Expand Down Expand Up @@ -763,30 +904,78 @@ func (kp *KeyPath) Copy() *KeyPath {
return &kp2
}

func (kp *KeyPath) HasDoubleGlob() bool {
func (kp *KeyPath) Last() *StringBox {
return kp.Path[len(kp.Path)-1]
}

func IsDoubleGlob(pattern []string) bool {
return len(pattern) == 3 && pattern[0] == "*" && pattern[1] == "" && pattern[2] == "*"
}

func IsTripleGlob(pattern []string) bool {
return len(pattern) == 5 && pattern[0] == "*" && pattern[1] == "" && pattern[2] == "*" && pattern[3] == "" && pattern[4] == "*"
}

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

func (kp *KeyPath) HasGlob() bool {
func (kp *KeyPath) FirstGlob() int {
if kp == nil {
return -1
}
for i, el := range kp.Path {
if el.UnquotedString != nil && len(el.UnquotedString.Pattern) > 0 {
return i
}
}
return -1
}

func (kp *KeyPath) HasTripleGlob() bool {
if kp == nil {
return false
}
for _, el := range kp.Path {
if el.UnquotedString != nil && len(el.UnquotedString.Pattern) > 0 {
if el.UnquotedString != nil && IsTripleGlob(el.UnquotedString.Pattern) {
return true
}
}
return false
}

func (kp *KeyPath) HasMultiGlob() bool {
if kp == nil {
return false
}
for _, el := range kp.Path {
if el.UnquotedString != nil && (IsDoubleGlob(el.UnquotedString.Pattern) || IsTripleGlob(el.UnquotedString.Pattern)) {
return true
}
}
return false
}

func (kp1 *KeyPath) Equals(kp2 *KeyPath) bool {
if len(kp1.Path) != len(kp2.Path) {
return false
}
for i, id := range kp1.Path {
if id.Unbox().ScalarString() != kp2.Path[i].Unbox().ScalarString() {
return false
}
}
return true
}

type Edge struct {
Range Range `json:"range"`

Expand All @@ -799,6 +988,22 @@ type Edge struct {
DstArrow string `json:"dst_arrow"`
}

func (e1 *Edge) Equals(e2 *Edge) bool {
if !e1.Src.Equals(e2.Src) {
return false
}
if e1.SrcArrow != e2.SrcArrow {
return false
}
if !e1.Dst.Equals(e2.Dst) {
return false
}
if e1.DstArrow != e2.DstArrow {
return false
}
return true
}

type EdgeIndex struct {
Range Range `json:"range"`

Expand All @@ -807,6 +1012,16 @@ type EdgeIndex struct {
Glob bool `json:"glob"`
}

func (ei1 *EdgeIndex) Equals(ei2 *EdgeIndex) bool {
if ei1.Int != ei2.Int {
return false
}
if ei1.Glob != ei2.Glob {
return false
}
return true
}

type Substitution struct {
Range Range `json:"range"`

Expand Down Expand Up @@ -1082,6 +1297,10 @@ func (sb ScalarBox) Unbox() Scalar {
}
}

func (sb ScalarBox) ScalarString() string {
return sb.Unbox().ScalarString()
}

// StringBox is used to box String for JSON persistence.
type StringBox struct {
UnquotedString *UnquotedString `json:"unquoted_string,omitempty"`
Expand Down
32 changes: 16 additions & 16 deletions d2compiler/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -322,21 +322,21 @@ func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) {
}
for _, fr := range f.References {
if fr.Primary() {
if fr.Context.Key.Value.Map != nil {
obj.Map = fr.Context.Key.Value.Map
if fr.Context_.Key.Value.Map != nil {
obj.Map = fr.Context_.Key.Value.Map
}
}
r := d2graph.Reference{
Key: fr.KeyPath,
KeyPathIndex: fr.KeyPathIndex(),

MapKey: fr.Context.Key,
MapKeyEdgeIndex: fr.Context.EdgeIndex(),
Scope: fr.Context.Scope,
ScopeAST: fr.Context.ScopeAST,
MapKey: fr.Context_.Key,
MapKeyEdgeIndex: fr.Context_.EdgeIndex(),
Scope: fr.Context_.Scope,
ScopeAST: fr.Context_.ScopeAST,
}
if fr.Context.ScopeMap != nil && !d2ir.IsVar(fr.Context.ScopeMap) {
scopeObjIDA := d2graphIDA(d2ir.BoardIDA(fr.Context.ScopeMap))
if fr.Context_.ScopeMap != nil && !d2ir.IsVar(fr.Context_.ScopeMap) {
scopeObjIDA := d2graphIDA(d2ir.BoardIDA(fr.Context_.ScopeMap))
r.ScopeObj = obj.Graph.Root.EnsureChild(scopeObjIDA)
}
obj.References = append(obj.References, r)
Expand Down Expand Up @@ -725,14 +725,14 @@ func (c *compiler) compileEdge(obj *d2graph.Object, e *d2ir.Edge) {
edge.Label.MapKey = e.LastPrimaryKey()
for _, er := range e.References {
r := d2graph.EdgeReference{
Edge: er.Context.Edge,
MapKey: er.Context.Key,
MapKeyEdgeIndex: er.Context.EdgeIndex(),
Scope: er.Context.Scope,
ScopeAST: er.Context.ScopeAST,
}
if er.Context.ScopeMap != nil && !d2ir.IsVar(er.Context.ScopeMap) {
scopeObjIDA := d2graphIDA(d2ir.BoardIDA(er.Context.ScopeMap))
Edge: er.Context_.Edge,
MapKey: er.Context_.Key,
MapKeyEdgeIndex: er.Context_.EdgeIndex(),
Scope: er.Context_.Scope,
ScopeAST: er.Context_.ScopeAST,
}
if er.Context_.ScopeMap != nil && !d2ir.IsVar(er.Context_.ScopeMap) {
scopeObjIDA := d2graphIDA(d2ir.BoardIDA(er.Context_.ScopeMap))
r.ScopeObj = edge.Src.Graph.Root.EnsureChild(scopeObjIDA)
}
edge.References = append(edge.References, r)
Expand Down
Loading

0 comments on commit dd131f8

Please sign in to comment.