1
2
3 package d2ir
4
5 import (
6 "errors"
7 "fmt"
8 "strings"
9
10 "oss.terrastruct.com/util-go/go2"
11
12 "oss.terrastruct.com/d2/d2ast"
13 "oss.terrastruct.com/d2/d2format"
14 "oss.terrastruct.com/d2/d2graph"
15 "oss.terrastruct.com/d2/d2parser"
16 "oss.terrastruct.com/d2/d2target"
17 )
18
19
20
21 type Node interface {
22 node()
23 Copy(newParent Node) Node
24 Parent() Node
25 Primary() *Scalar
26 Map() *Map
27 Equal(n2 Node) bool
28
29 AST() d2ast.Node
30 fmt.Stringer
31
32 LastRef() Reference
33 LastPrimaryRef() Reference
34 LastPrimaryKey() *d2ast.Key
35 }
36
37 var _ Node = &Scalar{}
38 var _ Node = &Field{}
39 var _ Node = &Edge{}
40 var _ Node = &Array{}
41 var _ Node = &Map{}
42
43 type Value interface {
44 Node
45 value()
46 }
47
48 var _ Value = &Scalar{}
49 var _ Value = &Array{}
50 var _ Value = &Map{}
51
52 type Composite interface {
53 Node
54 Value
55 composite()
56 }
57
58 var _ Composite = &Array{}
59 var _ Composite = &Map{}
60
61 func (n *Scalar) node() {}
62 func (n *Field) node() {}
63 func (n *Edge) node() {}
64 func (n *Array) node() {}
65 func (n *Map) node() {}
66
67 func (n *Scalar) Parent() Node { return n.parent }
68 func (n *Field) Parent() Node { return n.parent }
69 func (n *Edge) Parent() Node { return n.parent }
70 func (n *Array) Parent() Node { return n.parent }
71 func (n *Map) Parent() Node { return n.parent }
72
73 func (n *Scalar) Primary() *Scalar { return n }
74 func (n *Field) Primary() *Scalar { return n.Primary_ }
75 func (n *Edge) Primary() *Scalar { return n.Primary_ }
76 func (n *Array) Primary() *Scalar { return nil }
77 func (n *Map) Primary() *Scalar { return nil }
78
79 func (n *Scalar) Map() *Map { return nil }
80 func (n *Field) Map() *Map {
81 if n == nil {
82 return nil
83 }
84 if n.Composite == nil {
85 return nil
86 }
87 return n.Composite.Map()
88 }
89 func (n *Edge) Map() *Map {
90 if n == nil {
91 return nil
92 }
93 return n.Map_
94 }
95 func (n *Array) Map() *Map { return nil }
96 func (n *Map) Map() *Map { return n }
97
98 func (n *Scalar) value() {}
99 func (n *Array) value() {}
100 func (n *Map) value() {}
101
102 func (n *Array) composite() {}
103 func (n *Map) composite() {}
104
105 func (n *Scalar) String() string { return d2format.Format(n.AST()) }
106 func (n *Field) String() string { return d2format.Format(n.AST()) }
107 func (n *Edge) String() string { return d2format.Format(n.AST()) }
108 func (n *Array) String() string { return d2format.Format(n.AST()) }
109 func (n *Map) String() string { return d2format.Format(n.AST()) }
110
111 func (n *Scalar) LastRef() Reference { return parentRef(n) }
112 func (n *Map) LastRef() Reference { return parentRef(n) }
113 func (n *Array) LastRef() Reference { return parentRef(n) }
114
115 func (n *Scalar) LastPrimaryRef() Reference { return parentPrimaryRef(n) }
116 func (n *Map) LastPrimaryRef() Reference { return parentPrimaryRef(n) }
117 func (n *Array) LastPrimaryRef() Reference { return parentPrimaryRef(n) }
118
119 func (n *Scalar) LastPrimaryKey() *d2ast.Key { return parentPrimaryKey(n) }
120 func (n *Map) LastPrimaryKey() *d2ast.Key { return parentPrimaryKey(n) }
121 func (n *Array) LastPrimaryKey() *d2ast.Key { return parentPrimaryKey(n) }
122
123 type Reference interface {
124 reference()
125
126 AST() d2ast.Node
127 Primary() bool
128 Context() *RefContext
129
130 DueToGlob() bool
131 DueToLazyGlob() bool
132 }
133
134 var _ Reference = &FieldReference{}
135 var _ Reference = &EdgeReference{}
136
137 func (r *FieldReference) reference() {}
138 func (r *EdgeReference) reference() {}
139 func (r *FieldReference) Context() *RefContext { return r.Context_ }
140 func (r *EdgeReference) Context() *RefContext { return r.Context_ }
141 func (r *FieldReference) DueToGlob() bool { return r.DueToGlob_ }
142 func (r *EdgeReference) DueToGlob() bool { return r.DueToGlob_ }
143 func (r *FieldReference) DueToLazyGlob() bool { return r.DueToLazyGlob_ }
144 func (r *EdgeReference) DueToLazyGlob() bool { return r.DueToLazyGlob_ }
145
146 type Scalar struct {
147 parent Node
148 Value d2ast.Scalar `json:"value"`
149 }
150
151 func (s *Scalar) Copy(newParent Node) Node {
152 tmp := *s
153 s = &tmp
154
155 s.parent = newParent
156 return s
157 }
158
159 func (s *Scalar) Equal(n2 Node) bool {
160 s2 := n2.(*Scalar)
161 if _, ok := s.Value.(d2ast.String); ok {
162 if _, ok = s2.Value.(d2ast.String); ok {
163 return s.Value.ScalarString() == s2.Value.ScalarString()
164 }
165 }
166 return s.Value.Type() == s2.Value.Type() && s.Value.ScalarString() == s2.Value.ScalarString()
167 }
168
169 type Map struct {
170 parent Node
171 Fields []*Field `json:"fields"`
172 Edges []*Edge `json:"edges"`
173
174 globs []*globContext
175 }
176
177 func (m *Map) initRoot() {
178 m.parent = &Field{
179 Name: "root",
180 References: []*FieldReference{{
181 Context_: &RefContext{
182 ScopeMap: m,
183 },
184 }},
185 }
186 }
187
188 func (m *Map) Copy(newParent Node) Node {
189 tmp := *m
190 m = &tmp
191
192 m.parent = newParent
193 pfields := m.Fields
194 m.Fields = make([]*Field, 0, len(pfields))
195 for _, f := range pfields {
196 m.Fields = append(m.Fields, f.Copy(m).(*Field))
197 }
198 m.Edges = append([]*Edge(nil), m.Edges...)
199 for i := range m.Edges {
200 m.Edges[i] = m.Edges[i].Copy(m).(*Edge)
201 }
202 if m.parent == nil {
203 m.initRoot()
204 }
205 return m
206 }
207
208
209 func (m *Map) CopyBase(newParent Node) *Map {
210 if m == nil {
211 return (&Map{}).Copy(newParent).(*Map)
212 }
213
214 layers := m.DeleteField("layers")
215 scenarios := m.DeleteField("scenarios")
216 steps := m.DeleteField("steps")
217
218 m2 := m.Copy(newParent).(*Map)
219 if layers != nil {
220 m.Fields = append(m.Fields, layers)
221 }
222 if scenarios != nil {
223 m.Fields = append(m.Fields, scenarios)
224 }
225 if steps != nil {
226 m.Fields = append(m.Fields, steps)
227 }
228 return m2
229 }
230
231
232 func (m *Map) Root() bool {
233
234
235
236 f, ok := m.parent.(*Field)
237 if !ok {
238 return false
239 }
240 return f.Root()
241 }
242
243 func (f *Field) Root() bool {
244 return f.parent == nil
245 }
246
247 type BoardKind string
248
249 const (
250 BoardLayer BoardKind = "layer"
251 BoardScenario BoardKind = "scenario"
252 BoardStep BoardKind = "step"
253 )
254
255
256
257 func NodeBoardKind(n Node) BoardKind {
258 var f *Field
259 switch n := n.(type) {
260 case *Field:
261 if n.parent == nil {
262 return BoardLayer
263 }
264 f = ParentField(n)
265 case *Map:
266 var ok bool
267 f, ok = n.parent.(*Field)
268 if !ok {
269 return ""
270 }
271 if f.Root() {
272 return BoardLayer
273 }
274 f = ParentField(f)
275 }
276 if f == nil {
277 return ""
278 }
279 switch f.Name {
280 case "layers":
281 return BoardLayer
282 case "scenarios":
283 return BoardScenario
284 case "steps":
285 return BoardStep
286 default:
287 return ""
288 }
289 }
290
291 type Field struct {
292
293 parent Node
294
295 Name string `json:"name"`
296
297
298
299 Primary_ *Scalar `json:"primary,omitempty"`
300 Composite Composite `json:"composite,omitempty"`
301
302 References []*FieldReference `json:"references,omitempty"`
303 }
304
305 func (f *Field) Copy(newParent Node) Node {
306 tmp := *f
307 f = &tmp
308
309 f.parent = newParent
310 f.References = append([]*FieldReference(nil), f.References...)
311 if f.Primary_ != nil {
312 f.Primary_ = f.Primary_.Copy(f).(*Scalar)
313 }
314 if f.Composite != nil {
315 f.Composite = f.Composite.Copy(f).(Composite)
316 }
317 return f
318 }
319
320 func (f *Field) LastPrimaryRef() Reference {
321 for i := len(f.References) - 1; i >= 0; i-- {
322 if f.References[i].Primary() {
323 return f.References[i]
324 }
325 }
326 return nil
327 }
328
329 func (f *Field) LastPrimaryKey() *d2ast.Key {
330 fr := f.LastPrimaryRef()
331 if fr == nil {
332 return nil
333 }
334 return fr.(*FieldReference).Context_.Key
335 }
336
337 func (f *Field) LastRef() Reference {
338 return f.References[len(f.References)-1]
339 }
340
341 type EdgeID struct {
342 SrcPath []string `json:"src_path"`
343 SrcArrow bool `json:"src_arrow"`
344
345 DstPath []string `json:"dst_path"`
346 DstArrow bool `json:"dst_arrow"`
347
348
349 Index *int `json:"index"`
350 Glob bool `json:"glob"`
351 }
352
353 func NewEdgeIDs(k *d2ast.Key) (eida []*EdgeID) {
354 for _, ke := range k.Edges {
355 eid := &EdgeID{
356 SrcPath: ke.Src.IDA(),
357 SrcArrow: ke.SrcArrow == "<",
358 DstPath: ke.Dst.IDA(),
359 DstArrow: ke.DstArrow == ">",
360 }
361 if k.EdgeIndex != nil {
362 eid.Index = k.EdgeIndex.Int
363 eid.Glob = k.EdgeIndex.Glob
364 }
365 eida = append(eida, eid)
366 }
367 return eida
368 }
369
370 func (eid *EdgeID) Copy() *EdgeID {
371 tmp := *eid
372 eid = &tmp
373
374 eid.SrcPath = append([]string(nil), eid.SrcPath...)
375 eid.DstPath = append([]string(nil), eid.DstPath...)
376 return eid
377 }
378
379 func (eid *EdgeID) Match(eid2 *EdgeID) bool {
380 if eid.Index != nil && eid2.Index != nil {
381 if *eid.Index != *eid2.Index {
382 return false
383 }
384 }
385
386 if len(eid.SrcPath) != len(eid2.SrcPath) {
387 return false
388 }
389 if eid.SrcArrow != eid2.SrcArrow {
390 return false
391 }
392 for i, s := range eid.SrcPath {
393 if !strings.EqualFold(s, eid2.SrcPath[i]) {
394 return false
395 }
396 }
397
398 if len(eid.DstPath) != len(eid2.DstPath) {
399 return false
400 }
401 if eid.DstArrow != eid2.DstArrow {
402 return false
403 }
404 for i, s := range eid.DstPath {
405 if !strings.EqualFold(s, eid2.DstPath[i]) {
406 return false
407 }
408 }
409
410 return true
411 }
412
413
414
415 func (eid *EdgeID) resolve(m *Map) (_ *EdgeID, _ *Map, common []string, _ error) {
416 eid = eid.Copy()
417 maxUnderscores := go2.Max(countUnderscores(eid.SrcPath), countUnderscores(eid.DstPath))
418 for i := 0; i < maxUnderscores; i++ {
419 if eid.SrcPath[0] == "_" {
420 eid.SrcPath = eid.SrcPath[1:]
421 } else {
422 mf := ParentField(m)
423 eid.SrcPath = append([]string{mf.Name}, eid.SrcPath...)
424 }
425 if eid.DstPath[0] == "_" {
426 eid.DstPath = eid.DstPath[1:]
427 } else {
428 mf := ParentField(m)
429 eid.DstPath = append([]string{mf.Name}, eid.DstPath...)
430 }
431 m = ParentMap(m)
432 if m == nil {
433 return nil, nil, nil, errors.New("invalid underscore")
434 }
435 }
436
437 for len(eid.SrcPath) > 1 && len(eid.DstPath) > 1 {
438 if !strings.EqualFold(eid.SrcPath[0], eid.DstPath[0]) || eid.SrcPath[0] == "*" {
439 return eid, m, common, nil
440 }
441 common = append(common, eid.SrcPath[0])
442 eid.SrcPath = eid.SrcPath[1:]
443 eid.DstPath = eid.DstPath[1:]
444 }
445
446 return eid, m, common, nil
447 }
448
449 type Edge struct {
450
451 parent Node
452
453 ID *EdgeID `json:"edge_id"`
454
455 Primary_ *Scalar `json:"primary,omitempty"`
456 Map_ *Map `json:"map,omitempty"`
457
458 References []*EdgeReference `json:"references,omitempty"`
459 }
460
461 func (e *Edge) Copy(newParent Node) Node {
462 tmp := *e
463 e = &tmp
464
465 e.parent = newParent
466 e.References = append([]*EdgeReference(nil), e.References...)
467 if e.Primary_ != nil {
468 e.Primary_ = e.Primary_.Copy(e).(*Scalar)
469 }
470 if e.Map_ != nil {
471 e.Map_ = e.Map_.Copy(e).(*Map)
472 }
473 return e
474 }
475
476 func (e *Edge) LastPrimaryRef() Reference {
477 for i := len(e.References) - 1; i >= 0; i-- {
478 fr := e.References[i]
479 if fr.Context_.Key.EdgeKey == nil && !fr.DueToLazyGlob() {
480 return fr
481 }
482 }
483 return nil
484 }
485
486 func (e *Edge) LastPrimaryKey() *d2ast.Key {
487 er := e.LastPrimaryRef()
488 if er == nil {
489 return nil
490 }
491 return er.(*EdgeReference).Context_.Key
492 }
493
494 func (e *Edge) LastRef() Reference {
495 return e.References[len(e.References)-1]
496 }
497
498 type Array struct {
499 parent Node
500 Values []Value `json:"values"`
501 }
502
503 func (a *Array) Copy(newParent Node) Node {
504 tmp := *a
505 a = &tmp
506
507 a.parent = newParent
508 a.Values = append([]Value(nil), a.Values...)
509 for i := range a.Values {
510 a.Values[i] = a.Values[i].Copy(a).(Value)
511 }
512 return a
513 }
514
515 type FieldReference struct {
516 String d2ast.String `json:"string"`
517 KeyPath *d2ast.KeyPath `json:"key_path"`
518
519 Context_ *RefContext `json:"context"`
520 DueToGlob_ bool `json:"due_to_glob"`
521 DueToLazyGlob_ bool `json:"due_to_lazy_glob"`
522 }
523
524
525
526 func (fr *FieldReference) Primary() bool {
527 if fr.KeyPath == fr.Context_.Key.Key {
528 return len(fr.Context_.Key.Edges) == 0 && fr.KeyPathIndex() == len(fr.KeyPath.Path)-1
529 } else if fr.KeyPath == fr.Context_.Key.EdgeKey {
530 return len(fr.Context_.Key.Edges) == 1 && fr.KeyPathIndex() == len(fr.KeyPath.Path)-1
531 }
532 return false
533 }
534
535 func (fr *FieldReference) KeyPathIndex() int {
536 for i, sb := range fr.KeyPath.Path {
537 if sb.Unbox() == fr.String {
538 return i
539 }
540 }
541 panic("d2ir.KeyReference.KeyPathIndex: String not in KeyPath?")
542 }
543
544 func (fr *FieldReference) EdgeDest() bool {
545 return fr.KeyPath == fr.Context_.Edge.Dst
546 }
547
548 func (fr *FieldReference) InEdge() bool {
549 return fr.Context_.Edge != nil
550 }
551
552 func (fr *FieldReference) AST() d2ast.Node {
553 if fr.String == nil {
554
555 return fr.Context_.Scope
556 }
557 return fr.String
558 }
559
560 type EdgeReference struct {
561 Context_ *RefContext `json:"context"`
562 DueToGlob_ bool `json:"due_to_glob"`
563 DueToLazyGlob_ bool `json:"due_to_lazy_glob"`
564 }
565
566 func (er *EdgeReference) AST() d2ast.Node {
567 return er.Context_.Edge
568 }
569
570
571
572 func (er *EdgeReference) Primary() bool {
573 return len(er.Context_.Key.Edges) == 1 && er.Context_.Key.EdgeKey == nil
574 }
575
576 type RefContext struct {
577 Edge *d2ast.Edge `json:"edge"`
578 Key *d2ast.Key `json:"key"`
579 Scope *d2ast.Map `json:"-"`
580 ScopeMap *Map `json:"-"`
581 ScopeAST *d2ast.Map `json:"-"`
582 }
583
584 func (rc *RefContext) Copy() *RefContext {
585 tmp := *rc
586 return &tmp
587 }
588
589 func (rc *RefContext) EdgeIndex() int {
590 for i, e := range rc.Key.Edges {
591 if e == rc.Edge {
592 return i
593 }
594 }
595 return -1
596 }
597
598 func (rc *RefContext) Equal(rc2 *RefContext) bool {
599
600
601 return rc.Key.Equals(rc2.Key) && rc.Scope == rc2.Scope && rc.ScopeAST == rc2.ScopeAST
602 }
603
604 func (m *Map) FieldCountRecursive() int {
605 if m == nil {
606 return 0
607 }
608 acc := len(m.Fields)
609 for _, f := range m.Fields {
610 if f.Map() != nil {
611 acc += f.Map().FieldCountRecursive()
612 }
613 }
614 for _, e := range m.Edges {
615 if e.Map_ != nil {
616 acc += e.Map_.FieldCountRecursive()
617 }
618 }
619 return acc
620 }
621
622 func (m *Map) IsContainer() bool {
623 if m == nil {
624 return false
625 }
626 for _, f := range m.Fields {
627 _, isReserved := d2graph.ReservedKeywords[f.Name]
628 if !isReserved {
629 return true
630 }
631 }
632 return false
633 }
634
635 func (m *Map) EdgeCountRecursive() int {
636 if m == nil {
637 return 0
638 }
639 acc := len(m.Edges)
640 for _, f := range m.Fields {
641 if f.Map() != nil {
642 acc += f.Map().EdgeCountRecursive()
643 }
644 }
645 for _, e := range m.Edges {
646 if e.Map_ != nil {
647 acc += e.Map_.EdgeCountRecursive()
648 }
649 }
650 return acc
651 }
652
653 func (m *Map) GetClassMap(name string) *Map {
654 root := RootMap(m)
655 classes := root.Map().GetField("classes")
656 if classes != nil && classes.Map() != nil {
657 class := classes.Map().GetField(name)
658 if class != nil && class.Map() != nil {
659 return class.Map()
660 }
661 }
662 return nil
663 }
664
665 func (m *Map) GetField(ida ...string) *Field {
666 for len(ida) > 0 && ida[0] == "_" {
667 m = ParentMap(m)
668 if m == nil {
669 return nil
670 }
671 }
672 return m.getField(ida)
673 }
674
675 func (m *Map) getField(ida []string) *Field {
676 if len(ida) == 0 {
677 return nil
678 }
679
680 s := ida[0]
681 rest := ida[1:]
682
683 if s == "_" {
684 return nil
685 }
686
687 for _, f := range m.Fields {
688 if !strings.EqualFold(f.Name, s) {
689 continue
690 }
691 if len(rest) == 0 {
692 return f
693 }
694 if f.Map() != nil {
695 return f.Map().getField(rest)
696 }
697 }
698 return nil
699 }
700
701
702 func (m *Map) EnsureField(kp *d2ast.KeyPath, refctx *RefContext, create bool, c *compiler) ([]*Field, error) {
703 i := 0
704 for kp.Path[i].Unbox().ScalarString() == "_" {
705 m = ParentMap(m)
706 if m == nil {
707 return nil, d2parser.Errorf(kp.Path[i].Unbox(), "invalid underscore: no parent")
708 }
709 if i+1 == len(kp.Path) {
710 return nil, d2parser.Errorf(kp.Path[i].Unbox(), "field key must contain more than underscores")
711 }
712 i++
713 }
714
715 var gctx *globContext
716 if refctx != nil && refctx.Key.HasGlob() && c != nil {
717 gctx = c.getGlobContext(refctx)
718 }
719
720 var fa []*Field
721 err := m.ensureField(i, kp, refctx, create, gctx, c, &fa)
722 if len(fa) > 0 && c != nil && len(c.globRefContextStack) == 0 {
723 for _, gctx2 := range c.globContexts() {
724 old := c.lazyGlobBeingApplied
725 c.lazyGlobBeingApplied = true
726 c.compileKey(gctx2.refctx)
727 c.lazyGlobBeingApplied = old
728 }
729 }
730 return fa, err
731 }
732
733 func (m *Map) ensureField(i int, kp *d2ast.KeyPath, refctx *RefContext, create bool, gctx *globContext, c *compiler, fa *[]*Field) error {
734 filter := func(f *Field, passthrough bool) bool {
735 if gctx != nil {
736 var ks string
737 if refctx.Key.HasTripleGlob() {
738 ks = d2format.Format(d2ast.MakeKeyPath(IDA(f)))
739 } else {
740 ks = d2format.Format(d2ast.MakeKeyPath(BoardIDA(f)))
741 }
742 if !kp.HasGlob() {
743 if !passthrough {
744 gctx.appliedFields[ks] = struct{}{}
745 }
746 return true
747 }
748
749 lastEl := kp.Path[len(kp.Path)-1]
750 if len(refctx.Key.Edges) == 0 || lastEl.UnquotedString == nil || len(lastEl.UnquotedString.Pattern) == 0 || kp == refctx.Key.Key || kp == refctx.Key.EdgeKey {
751 if _, ok := gctx.appliedFields[ks]; ok {
752 return false
753 }
754 }
755 if !passthrough {
756 gctx.appliedFields[ks] = struct{}{}
757 }
758 }
759 return true
760 }
761 faAppend := func(fa2 ...*Field) {
762 for _, f := range fa2 {
763 if filter(f, false) {
764 *fa = append(*fa, f)
765 }
766 }
767 }
768
769 us, ok := kp.Path[i].Unbox().(*d2ast.UnquotedString)
770 if ok && us.Pattern != nil {
771 fa2, ok := m.multiGlob(us.Pattern)
772 if ok {
773 if i == len(kp.Path)-1 {
774 faAppend(fa2...)
775 } else {
776 for _, f := range fa2 {
777 if !filter(f, true) {
778 continue
779 }
780 if f.Map() == nil {
781 f.Composite = &Map{
782 parent: f,
783 }
784 }
785 err := f.Map().ensureField(i+1, kp, refctx, create, gctx, c, fa)
786 if err != nil {
787 return err
788 }
789 }
790 }
791 return nil
792 }
793 for _, f := range m.Fields {
794 if matchPattern(f.Name, us.Pattern) {
795 if i == len(kp.Path)-1 {
796 faAppend(f)
797 } else {
798 if !filter(f, true) {
799 continue
800 }
801 if f.Map() == nil {
802 f.Composite = &Map{
803 parent: f,
804 }
805 }
806 err := f.Map().ensureField(i+1, kp, refctx, create, gctx, c, fa)
807 if err != nil {
808 return err
809 }
810 }
811 }
812 }
813 return nil
814 }
815
816 head := kp.Path[i].Unbox().ScalarString()
817
818 if _, ok := d2graph.ReservedKeywords[strings.ToLower(head)]; ok {
819 head = strings.ToLower(head)
820 if _, ok := d2graph.CompositeReservedKeywords[head]; !ok && i < len(kp.Path)-1 {
821 return d2parser.Errorf(kp.Path[i].Unbox(), fmt.Sprintf(`"%s" must be the last part of the key`, head))
822 }
823 }
824
825 if head == "_" {
826 return d2parser.Errorf(kp.Path[i].Unbox(), `parent "_" can only be used in the beginning of paths, e.g. "_.x"`)
827 }
828
829 if head == "classes" && NodeBoardKind(m) == "" {
830 return d2parser.Errorf(kp.Path[i].Unbox(), "%s is only allowed at a board root", head)
831 }
832
833 if findBoardKeyword(head) != -1 && NodeBoardKind(m) == "" {
834 return d2parser.Errorf(kp.Path[i].Unbox(), "%s is only allowed at a board root", head)
835 }
836
837 for _, f := range m.Fields {
838 if !strings.EqualFold(f.Name, head) {
839 continue
840 }
841
842
843 if refctx != nil {
844 f.References = append(f.References, &FieldReference{
845 String: kp.Path[i].Unbox(),
846 KeyPath: kp,
847 Context_: refctx,
848 DueToGlob_: len(c.globRefContextStack) > 0,
849 DueToLazyGlob_: c.lazyGlobBeingApplied,
850 })
851 }
852
853 if i+1 == len(kp.Path) {
854 faAppend(f)
855 return nil
856 }
857 if !filter(f, true) {
858 return nil
859 }
860 if _, ok := f.Composite.(*Array); ok {
861 return d2parser.Errorf(kp.Path[i].Unbox(), "cannot index into array")
862 }
863 if f.Map() == nil {
864 f.Composite = &Map{
865 parent: f,
866 }
867 }
868 return f.Map().ensureField(i+1, kp, refctx, create, gctx, c, fa)
869 }
870
871 if !create {
872 return nil
873 }
874 shape := ParentShape(m)
875 if _, ok := d2graph.ReservedKeywords[strings.ToLower(head)]; !ok && len(c.globRefContextStack) > 0 {
876 if shape == d2target.ShapeClass || shape == d2target.ShapeSQLTable {
877 return nil
878 }
879 }
880 f := &Field{
881 parent: m,
882 Name: head,
883 }
884 defer func() {
885 if i < kp.FirstGlob() {
886 return
887 }
888 for _, grefctx := range c.globRefContextStack {
889 var ks string
890 if grefctx.Key.HasTripleGlob() {
891 ks = d2format.Format(d2ast.MakeKeyPath(IDA(f)))
892 } else {
893 ks = d2format.Format(d2ast.MakeKeyPath(BoardIDA(f)))
894 }
895 gctx2 := c.getGlobContext(grefctx)
896 gctx2.appliedFields[ks] = struct{}{}
897 }
898 }()
899
900 if refctx != nil {
901 f.References = append(f.References, &FieldReference{
902 String: kp.Path[i].Unbox(),
903 KeyPath: kp,
904 Context_: refctx,
905 DueToGlob_: len(c.globRefContextStack) > 0,
906 DueToLazyGlob_: c.lazyGlobBeingApplied,
907 })
908 }
909 if !filter(f, true) {
910 return nil
911 }
912 m.Fields = append(m.Fields, f)
913 if i+1 == len(kp.Path) {
914 faAppend(f)
915 return nil
916 }
917 if f.Composite == nil {
918 f.Composite = &Map{
919 parent: f,
920 }
921 }
922 return f.Map().ensureField(i+1, kp, refctx, create, gctx, c, fa)
923 }
924
925 func (m *Map) DeleteEdge(eid *EdgeID) *Edge {
926 if eid == nil {
927 return nil
928 }
929
930 for i, e := range m.Edges {
931 if e.ID.Match(eid) {
932 m.Edges = append(m.Edges[:i], m.Edges[i+1:]...)
933 return e
934 }
935 }
936 return nil
937 }
938
939 func (m *Map) DeleteField(ida ...string) *Field {
940 if len(ida) == 0 {
941 return nil
942 }
943
944 s := ida[0]
945 rest := ida[1:]
946
947 for i, f := range m.Fields {
948 if !strings.EqualFold(f.Name, s) {
949 continue
950 }
951 if len(rest) == 0 {
952 for _, fr := range f.References {
953 for _, e := range m.Edges {
954 for _, er := range e.References {
955 if er.Context_ == fr.Context_ {
956 m.DeleteEdge(e.ID)
957 break
958 }
959 }
960 }
961 }
962 m.Fields = append(m.Fields[:i], m.Fields[i+1:]...)
963
964
965
966 parent := ParentField(f)
967 for keywordHolder := range d2graph.ReservedKeywordHolders {
968 if parent != nil && parent.Name == keywordHolder && len(parent.Map().Fields) == 0 {
969 keywordHolderParentMap := ParentMap(parent)
970 for i, f := range keywordHolderParentMap.Fields {
971 if f.Name == keywordHolder {
972 keywordHolderParentMap.Fields = append(keywordHolderParentMap.Fields[:i], keywordHolderParentMap.Fields[i+1:]...)
973 break
974 }
975 }
976 }
977 }
978 return f
979 }
980 if f.Map() != nil {
981 return f.Map().DeleteField(rest...)
982 }
983 }
984 return nil
985 }
986
987 func (m *Map) GetEdges(eid *EdgeID, refctx *RefContext, c *compiler) []*Edge {
988 if refctx != nil {
989 var gctx *globContext
990 if refctx.Key.HasGlob() && c != nil {
991 gctx = c.ensureGlobContext(refctx)
992 }
993 var ea []*Edge
994 m.getEdges(eid, refctx, gctx, &ea)
995 return ea
996 }
997
998 eid, m, common, err := eid.resolve(m)
999 if err != nil {
1000 return nil
1001 }
1002 if len(common) > 0 {
1003 f := m.GetField(common...)
1004 if f == nil {
1005 return nil
1006 }
1007 if f.Map() != nil {
1008 return f.Map().GetEdges(eid, nil, nil)
1009 }
1010 return nil
1011 }
1012
1013 var ea []*Edge
1014 for _, e := range m.Edges {
1015 if e.ID.Match(eid) {
1016 ea = append(ea, e)
1017 }
1018 }
1019 return ea
1020 }
1021
1022 func (m *Map) getEdges(eid *EdgeID, refctx *RefContext, gctx *globContext, ea *[]*Edge) error {
1023 eid, m, common, err := eid.resolve(m)
1024 if err != nil {
1025 return err
1026 }
1027
1028 if len(common) > 0 {
1029 commonKP := d2ast.MakeKeyPath(common)
1030 lastMatch := 0
1031 for i, el := range commonKP.Path {
1032 for j := lastMatch; j < len(refctx.Edge.Src.Path); j++ {
1033 realEl := refctx.Edge.Src.Path[j]
1034 if el.ScalarString() == realEl.ScalarString() {
1035 commonKP.Path[i] = realEl
1036 lastMatch += j + 1
1037 }
1038 }
1039 }
1040 fa, err := m.EnsureField(commonKP, nil, false, nil)
1041 if err != nil {
1042 return nil
1043 }
1044 for _, f := range fa {
1045 if _, ok := f.Composite.(*Array); ok {
1046 return d2parser.Errorf(refctx.Edge.Src, "cannot index into array")
1047 }
1048 if f.Map() == nil {
1049 f.Composite = &Map{
1050 parent: f,
1051 }
1052 }
1053 err = f.Map().getEdges(eid, refctx, gctx, ea)
1054 if err != nil {
1055 return err
1056 }
1057 }
1058 return nil
1059 }
1060
1061 srcFA, err := refctx.ScopeMap.EnsureField(refctx.Edge.Src, nil, false, nil)
1062 if err != nil {
1063 return err
1064 }
1065 dstFA, err := refctx.ScopeMap.EnsureField(refctx.Edge.Dst, nil, false, nil)
1066 if err != nil {
1067 return err
1068 }
1069
1070 for _, src := range srcFA {
1071 for _, dst := range dstFA {
1072 eid2 := eid.Copy()
1073 eid2.SrcPath = RelIDA(m, src)
1074 eid2.DstPath = RelIDA(m, dst)
1075
1076 ea2 := m.GetEdges(eid2, nil, nil)
1077 for _, e := range ea2 {
1078 if gctx != nil {
1079 var ks string
1080 if refctx.Key.HasTripleGlob() {
1081 ks = d2format.Format(d2ast.MakeKeyPath(IDA(e)))
1082 } else {
1083 ks = d2format.Format(d2ast.MakeKeyPath(BoardIDA(e)))
1084 }
1085 if _, ok := gctx.appliedEdges[ks]; ok {
1086 continue
1087 }
1088 gctx.appliedEdges[ks] = struct{}{}
1089 }
1090 *ea = append(*ea, ea2...)
1091 }
1092 }
1093 }
1094 return nil
1095 }
1096
1097 func (m *Map) CreateEdge(eid *EdgeID, refctx *RefContext, c *compiler) ([]*Edge, error) {
1098 var ea []*Edge
1099 var gctx *globContext
1100 if refctx != nil && refctx.Key.HasGlob() && c != nil {
1101 gctx = c.ensureGlobContext(refctx)
1102 }
1103 err := m.createEdge(eid, refctx, gctx, c, &ea)
1104 if len(ea) > 0 && c != nil && len(c.globRefContextStack) == 0 {
1105 for _, gctx2 := range c.globContexts() {
1106 old := c.lazyGlobBeingApplied
1107 c.lazyGlobBeingApplied = true
1108 c.compileKey(gctx2.refctx)
1109 c.lazyGlobBeingApplied = old
1110 }
1111 }
1112 return ea, err
1113 }
1114
1115 func (m *Map) createEdge(eid *EdgeID, refctx *RefContext, gctx *globContext, c *compiler, ea *[]*Edge) error {
1116 if ParentEdge(m) != nil {
1117 return d2parser.Errorf(refctx.Edge, "cannot create edge inside edge")
1118 }
1119
1120 eid, m, common, err := eid.resolve(m)
1121 if err != nil {
1122 return d2parser.Errorf(refctx.Edge, err.Error())
1123 }
1124 if len(common) > 0 {
1125 commonKP := d2ast.MakeKeyPath(common)
1126 lastMatch := 0
1127 for i, el := range commonKP.Path {
1128 for j := lastMatch; j < len(refctx.Edge.Src.Path); j++ {
1129 realEl := refctx.Edge.Src.Path[j]
1130 if el.ScalarString() == realEl.ScalarString() {
1131 commonKP.Path[i] = realEl
1132 lastMatch += j + 1
1133 }
1134 }
1135 }
1136 fa, err := m.EnsureField(commonKP, nil, true, c)
1137 if err != nil {
1138 return err
1139 }
1140 for _, f := range fa {
1141 if _, ok := f.Composite.(*Array); ok {
1142 return d2parser.Errorf(refctx.Edge.Src, "cannot index into array")
1143 }
1144 if f.Map() == nil {
1145 f.Composite = &Map{
1146 parent: f,
1147 }
1148 }
1149 err = f.Map().createEdge(eid, refctx, gctx, c, ea)
1150 if err != nil {
1151 return err
1152 }
1153 }
1154 return nil
1155 }
1156
1157 ij := findProhibitedEdgeKeyword(eid.SrcPath...)
1158 if ij != -1 {
1159 return d2parser.Errorf(refctx.Edge.Src.Path[ij].Unbox(), "reserved keywords are prohibited in edges")
1160 }
1161 ij = findBoardKeyword(eid.SrcPath...)
1162 if ij == len(eid.SrcPath)-1 {
1163 return d2parser.Errorf(refctx.Edge.Src.Path[ij].Unbox(), "edge with board keyword alone doesn't make sense")
1164 }
1165
1166 ij = findProhibitedEdgeKeyword(eid.DstPath...)
1167 if ij != -1 {
1168 return d2parser.Errorf(refctx.Edge.Dst.Path[ij].Unbox(), "reserved keywords are prohibited in edges")
1169 }
1170 ij = findBoardKeyword(eid.DstPath...)
1171 if ij == len(eid.DstPath)-1 {
1172 return d2parser.Errorf(refctx.Edge.Dst.Path[ij].Unbox(), "edge with board keyword alone doesn't make sense")
1173 }
1174
1175 srcFA, err := refctx.ScopeMap.EnsureField(refctx.Edge.Src, refctx, true, c)
1176 if err != nil {
1177 return err
1178 }
1179 dstFA, err := refctx.ScopeMap.EnsureField(refctx.Edge.Dst, refctx, true, c)
1180 if err != nil {
1181 return err
1182 }
1183
1184 for _, src := range srcFA {
1185 for _, dst := range dstFA {
1186 if src == dst && (refctx.Edge.Src.HasGlob() || refctx.Edge.Dst.HasGlob()) {
1187
1188 continue
1189 }
1190
1191 if refctx.Edge.Src.HasMultiGlob() {
1192
1193 if src.Map().IsContainer() {
1194 continue
1195 }
1196 if NodeBoardKind(src) != "" || ParentBoard(src) != ParentBoard(dst) {
1197 continue
1198 }
1199 }
1200 if refctx.Edge.Dst.HasMultiGlob() {
1201
1202 if dst.Map().IsContainer() {
1203 continue
1204 }
1205 if NodeBoardKind(dst) != "" || ParentBoard(src) != ParentBoard(dst) {
1206 continue
1207 }
1208 }
1209
1210 eid2 := eid.Copy()
1211 eid2.SrcPath = RelIDA(m, src)
1212 eid2.DstPath = RelIDA(m, dst)
1213
1214 e, err := m.createEdge2(eid2, refctx, gctx, c, src, dst)
1215 if err != nil {
1216 return err
1217 }
1218 if e != nil {
1219 *ea = append(*ea, e)
1220 }
1221 }
1222 }
1223 return nil
1224 }
1225
1226 func (m *Map) createEdge2(eid *EdgeID, refctx *RefContext, gctx *globContext, c *compiler, src, dst *Field) (*Edge, error) {
1227 if NodeBoardKind(src) != "" {
1228 return nil, d2parser.Errorf(refctx.Edge.Src, "cannot create edges between boards")
1229 }
1230 if NodeBoardKind(dst) != "" {
1231 return nil, d2parser.Errorf(refctx.Edge.Dst, "cannot create edges between boards")
1232 }
1233 if ParentBoard(src) != ParentBoard(dst) {
1234 return nil, d2parser.Errorf(refctx.Edge, "cannot create edges between boards")
1235 }
1236
1237 eid.Index = nil
1238 eid.Glob = true
1239 ea := m.GetEdges(eid, nil, nil)
1240 index := len(ea)
1241 eid.Index = &index
1242 eid.Glob = false
1243 e := &Edge{
1244 parent: m,
1245 ID: eid,
1246 References: []*EdgeReference{{
1247 Context_: refctx,
1248 DueToGlob_: len(c.globRefContextStack) > 0,
1249 DueToLazyGlob_: c.lazyGlobBeingApplied,
1250 }},
1251 }
1252
1253 if gctx != nil {
1254 var ks string
1255
1256 e2 := e.Copy(e.Parent()).(*Edge)
1257 e2.ID = e2.ID.Copy()
1258 e2.ID.Index = nil
1259 if refctx.Key.HasTripleGlob() {
1260 ks = d2format.Format(d2ast.MakeKeyPath(IDA(e2)))
1261 } else {
1262 ks = d2format.Format(d2ast.MakeKeyPath(BoardIDA(e2)))
1263 }
1264 if _, ok := gctx.appliedEdges[ks]; ok {
1265 return nil, nil
1266 }
1267 gctx.appliedEdges[ks] = struct{}{}
1268 }
1269
1270 m.Edges = append(m.Edges, e)
1271
1272 return e, nil
1273 }
1274
1275 func (s *Scalar) AST() d2ast.Node {
1276 return s.Value
1277 }
1278
1279 func (f *Field) AST() d2ast.Node {
1280 k := &d2ast.Key{
1281 Key: &d2ast.KeyPath{
1282 Path: []*d2ast.StringBox{
1283 d2ast.MakeValueBox(d2ast.RawString(f.Name, true)).StringBox(),
1284 },
1285 },
1286 }
1287
1288 if f.Primary_ != nil {
1289 k.Primary = d2ast.MakeValueBox(f.Primary_.AST().(d2ast.Value)).ScalarBox()
1290 }
1291 if f.Composite != nil {
1292 k.Value = d2ast.MakeValueBox(f.Composite.AST().(d2ast.Value))
1293 }
1294
1295 return k
1296 }
1297
1298 func (e *Edge) AST() d2ast.Node {
1299 astEdge := &d2ast.Edge{}
1300
1301 astEdge.Src = d2ast.MakeKeyPath(e.ID.SrcPath)
1302 if e.ID.SrcArrow {
1303 astEdge.SrcArrow = "<"
1304 }
1305 astEdge.Dst = d2ast.MakeKeyPath(e.ID.DstPath)
1306 if e.ID.DstArrow {
1307 astEdge.DstArrow = ">"
1308 }
1309
1310 k := &d2ast.Key{
1311 Edges: []*d2ast.Edge{astEdge},
1312 }
1313
1314 if e.Primary_ != nil {
1315 k.Primary = d2ast.MakeValueBox(e.Primary_.AST().(d2ast.Value)).ScalarBox()
1316 }
1317 if e.Map_ != nil {
1318 k.Value = d2ast.MakeValueBox(e.Map_.AST().(*d2ast.Map))
1319 }
1320
1321 return k
1322 }
1323
1324 func (e *Edge) IDString() string {
1325 ast := e.AST().(*d2ast.Key)
1326 if e.ID.Index != nil {
1327 ast.EdgeIndex = &d2ast.EdgeIndex{
1328 Int: e.ID.Index,
1329 }
1330 }
1331 ast.Primary = d2ast.ScalarBox{}
1332 ast.Value = d2ast.ValueBox{}
1333 return d2format.Format(ast)
1334 }
1335
1336 func (a *Array) AST() d2ast.Node {
1337 if a == nil {
1338 return nil
1339 }
1340 astArray := &d2ast.Array{}
1341 for _, av := range a.Values {
1342 astArray.Nodes = append(astArray.Nodes, d2ast.MakeArrayNodeBox(av.AST().(d2ast.ArrayNode)))
1343 }
1344 return astArray
1345 }
1346
1347 func (m *Map) AST() d2ast.Node {
1348 if m == nil {
1349 return nil
1350 }
1351 astMap := &d2ast.Map{}
1352 if m.Root() {
1353 astMap.Range = d2ast.MakeRange(",0:0:0-1:0:0")
1354 } else {
1355 astMap.Range = d2ast.MakeRange(",1:0:0-2:0:0")
1356 }
1357 for _, f := range m.Fields {
1358 astMap.Nodes = append(astMap.Nodes, d2ast.MakeMapNodeBox(f.AST().(d2ast.MapNode)))
1359 }
1360 for _, e := range m.Edges {
1361 astMap.Nodes = append(astMap.Nodes, d2ast.MakeMapNodeBox(e.AST().(d2ast.MapNode)))
1362 }
1363 return astMap
1364 }
1365
1366 func (m *Map) appendFieldReferences(i int, kp *d2ast.KeyPath, refctx *RefContext, c *compiler) {
1367 sb := kp.Path[i]
1368 f := m.GetField(sb.Unbox().ScalarString())
1369 if f == nil {
1370 return
1371 }
1372
1373 f.References = append(f.References, &FieldReference{
1374 String: sb.Unbox(),
1375 KeyPath: kp,
1376 Context_: refctx,
1377 DueToGlob_: len(c.globRefContextStack) > 0,
1378 DueToLazyGlob_: c.lazyGlobBeingApplied,
1379 })
1380 if i+1 == len(kp.Path) {
1381 return
1382 }
1383 if f.Map() != nil {
1384 f.Map().appendFieldReferences(i+1, kp, refctx, c)
1385 }
1386 }
1387
1388 func RootMap(m *Map) *Map {
1389 if m.Root() {
1390 return m
1391 }
1392 return RootMap(ParentMap(m))
1393 }
1394
1395 func ParentMap(n Node) *Map {
1396 for {
1397 n = n.Parent()
1398 if n == nil {
1399 return nil
1400 }
1401 if m, ok := n.(*Map); ok {
1402 return m
1403 }
1404 }
1405 }
1406
1407 func ParentField(n Node) *Field {
1408 for {
1409 n = n.Parent()
1410 if n == nil {
1411 return nil
1412 }
1413 if f, ok := n.(*Field); ok {
1414 return f
1415 }
1416 }
1417 }
1418
1419 func IsVar(n Node) bool {
1420 for {
1421 if n == nil {
1422 return false
1423 }
1424 if NodeBoardKind(n) != "" {
1425 return false
1426 }
1427 if f, ok := n.(*Field); ok && f.Name == "vars" {
1428 return true
1429 }
1430 n = n.Parent()
1431 }
1432 }
1433
1434 func ParentBoard(n Node) Node {
1435 for {
1436 n = n.Parent()
1437 if n == nil {
1438 return nil
1439 }
1440 if NodeBoardKind(n) != "" {
1441 return n
1442 }
1443 }
1444 }
1445
1446 func ParentEdge(n Node) *Edge {
1447 for {
1448 n = n.Parent()
1449 if n == nil {
1450 return nil
1451 }
1452 if e, ok := n.(*Edge); ok {
1453 return e
1454 }
1455 }
1456 }
1457
1458 func ParentShape(n Node) string {
1459 for {
1460 f, ok := n.(*Field)
1461 if ok {
1462 if f.Map() != nil {
1463 shapef := f.Map().GetField("shape")
1464 if shapef != nil && shapef.Primary() != nil {
1465 return shapef.Primary().Value.ScalarString()
1466 }
1467 }
1468 }
1469 n = n.Parent()
1470 if n == nil {
1471 return ""
1472 }
1473 }
1474 }
1475
1476 func countUnderscores(p []string) int {
1477 for i, el := range p {
1478 if el != "_" {
1479 return i
1480 }
1481 }
1482 return 0
1483 }
1484
1485 func findBoardKeyword(ida ...string) int {
1486 for i := range ida {
1487 if _, ok := d2graph.BoardKeywords[ida[i]]; ok {
1488 return i
1489 }
1490 }
1491 return -1
1492 }
1493
1494 func findProhibitedEdgeKeyword(ida ...string) int {
1495 for i := range ida {
1496 if _, ok := d2graph.SimpleReservedKeywords[ida[i]]; ok {
1497 return i
1498 }
1499 if _, ok := d2graph.ReservedKeywordHolders[ida[i]]; ok {
1500 return i
1501 }
1502 }
1503 return -1
1504 }
1505
1506 func parentRef(n Node) Reference {
1507 f := ParentField(n)
1508 if f != nil {
1509 return f.LastRef()
1510 }
1511 e := ParentEdge(n)
1512 if e != nil {
1513 return e.LastRef()
1514 }
1515 return nil
1516 }
1517
1518 func parentPrimaryRef(n Node) Reference {
1519 f := ParentField(n)
1520 if f != nil {
1521 return f.LastPrimaryRef()
1522 }
1523 e := ParentEdge(n)
1524 if e != nil {
1525 return e.LastPrimaryRef()
1526 }
1527 return nil
1528 }
1529
1530 func parentPrimaryKey(n Node) *d2ast.Key {
1531 f := ParentField(n)
1532 if f != nil {
1533 return f.LastPrimaryKey()
1534 }
1535 e := ParentEdge(n)
1536 if e != nil {
1537 return e.LastPrimaryKey()
1538 }
1539 return nil
1540 }
1541
1542
1543 func BoardIDA(n Node) (ida []string) {
1544 for {
1545 switch n := n.(type) {
1546 case *Field:
1547 if n.Root() || NodeBoardKind(n) != "" {
1548 reverseIDA(ida)
1549 return ida
1550 }
1551 ida = append(ida, n.Name)
1552 case *Edge:
1553 ida = append(ida, n.IDString())
1554 }
1555 n = n.Parent()
1556 if n == nil {
1557 reverseIDA(ida)
1558 return ida
1559 }
1560 }
1561 }
1562
1563
1564 func IDA(n Node) (ida []string) {
1565 for {
1566 switch n := n.(type) {
1567 case *Field:
1568 ida = append(ida, n.Name)
1569 if n.Root() {
1570 reverseIDA(ida)
1571 return ida
1572 }
1573 case *Edge:
1574 ida = append(ida, n.IDString())
1575 }
1576 n = n.Parent()
1577 if n == nil {
1578 reverseIDA(ida)
1579 return ida
1580 }
1581 }
1582 }
1583
1584
1585 func RelIDA(p, n Node) (ida []string) {
1586 for {
1587 switch n := n.(type) {
1588 case *Field:
1589 ida = append(ida, n.Name)
1590 if n.Root() {
1591 reverseIDA(ida)
1592 return ida
1593 }
1594 case *Edge:
1595 ida = append(ida, n.String())
1596 }
1597 n = n.Parent()
1598 f, fok := n.(*Field)
1599 e, eok := n.(*Edge)
1600 if n == nil || (fok && (f.Root() || f == p || f.Composite == p)) || (eok && (e == p || e.Map_ == p)) {
1601 reverseIDA(ida)
1602 return ida
1603 }
1604 }
1605 }
1606
1607 func reverseIDA(ida []string) {
1608 for i := 0; i < len(ida)/2; i++ {
1609 tmp := ida[i]
1610 ida[i] = ida[len(ida)-i-1]
1611 ida[len(ida)-i-1] = tmp
1612 }
1613 }
1614
1615 func (f *Field) Equal(n2 Node) bool {
1616 f2 := n2.(*Field)
1617
1618 if f.Name != f2.Name {
1619 return false
1620 }
1621 if !f.Primary_.Equal(f2.Primary_) {
1622 return false
1623 }
1624 if !f.Composite.Equal(f2.Composite) {
1625 return false
1626 }
1627 return true
1628 }
1629
1630 func (e *Edge) Equal(n2 Node) bool {
1631 e2 := n2.(*Edge)
1632
1633 if !e.ID.Match(e2.ID) {
1634 return false
1635 }
1636 if !e.Primary_.Equal(e2.Primary_) {
1637 return false
1638 }
1639 if !e.Map_.Equal(e2.Map_) {
1640 return false
1641 }
1642 return true
1643 }
1644
1645 func (a *Array) Equal(n2 Node) bool {
1646 a2 := n2.(*Array)
1647
1648 if len(a.Values) != len(a2.Values) {
1649 return false
1650 }
1651
1652 for i := range a.Values {
1653 if !a.Values[i].Equal(a2.Values[i]) {
1654 return false
1655 }
1656 }
1657
1658 return true
1659 }
1660
1661 func (m *Map) Equal(n2 Node) bool {
1662 m2 := n2.(*Map)
1663
1664 if len(m.Fields) != len(m2.Fields) {
1665 return false
1666 }
1667 if len(m.Edges) != len(m2.Edges) {
1668 return false
1669 }
1670
1671 for i := range m.Fields {
1672 if !m.Fields[i].Equal(m2.Fields[i]) {
1673 return false
1674 }
1675 }
1676 for i := range m.Edges {
1677 if !m.Edges[i].Equal(m2.Edges[i]) {
1678 return false
1679 }
1680 }
1681
1682 return true
1683 }
1684
1685 func (m *Map) InClass(key *d2ast.Key) bool {
1686 classes := m.Map().GetField("classes")
1687 if classes == nil || classes.Map() == nil {
1688 return false
1689 }
1690
1691 for _, class := range classes.Map().Fields {
1692 if class.Map() == nil {
1693 continue
1694 }
1695 classF := class.Map().GetField(key.Key.IDA()...)
1696 if classF == nil {
1697 continue
1698 }
1699
1700 for _, ref := range classF.References {
1701 if ref.Context_.Key == key {
1702 return true
1703 }
1704 }
1705 }
1706 return false
1707 }
1708
1709 func (m *Map) IsClass() bool {
1710 parentBoard := ParentBoard(m)
1711 if parentBoard.Map() == nil {
1712 return false
1713 }
1714 classes := parentBoard.Map().GetField("classes")
1715 if classes == nil || classes.Map() == nil {
1716 return false
1717 }
1718
1719 for _, class := range classes.Map().Fields {
1720 if class.Map() == m {
1721 return true
1722 }
1723 }
1724 return false
1725 }
1726
View as plain text