d2ir: Add d2ir -> d2ast for stringifying the IR

This commit is contained in:
Anmol Sethi 2023-01-16 05:31:18 -08:00
parent 91149543f5
commit 10ca5e2ce1
No known key found for this signature in database
GPG key ID: 25BC68888A99A8BA
3 changed files with 134 additions and 28 deletions

View file

@ -650,6 +650,14 @@ type KeyPath struct {
Path []*StringBox `json:"path"`
}
func MakeKeyPath(a []string) *KeyPath {
var kp *KeyPath
for _, el := range a {
kp.Path = append(kp.Path, MakeValueBox(RawString(el, true)).StringBox())
}
return kp
}
type Edge struct {
Range Range `json:"range"`
@ -731,6 +739,37 @@ type ArrayNodeBox struct {
Map *Map `json:"map,omitempty"`
}
func MakeArrayNodeBox(an ArrayNode) ArrayNodeBox {
var ab ArrayNodeBox
switch an := an.(type) {
case *Comment:
ab.Comment = an
case *BlockComment:
ab.BlockComment = an
case *Substitution:
ab.Substitution = an
case *Null:
ab.Null = an
case *Boolean:
ab.Boolean = an
case *Number:
ab.Number = an
case *UnquotedString:
ab.UnquotedString = an
case *DoubleQuotedString:
ab.DoubleQuotedString = an
case *SingleQuotedString:
ab.SingleQuotedString = an
case *BlockString:
ab.BlockString = an
case *Array:
ab.Array = an
case *Map:
ab.Map = an
}
return ab
}
func (ab ArrayNodeBox) Unbox() ArrayNode {
switch {
case ab.Comment != nil:

View file

@ -214,12 +214,7 @@ func testCompileField(t *testing.T) {
assertField(t, m, 1, 0, nil)
f := assertField(t, m, 0, 0, nil, "x")
f_a, ok := f.Composite.(*d2ir.Array)
if !ok {
t.Fatalf("unexpected type: %T", f.Composite)
} else {
assert.Equal(t, 4, len(f_a.Values))
}
assert.String(t, `[1; 2; 3; 4]`, f.Composite.String())
},
},
}

View file

@ -1,7 +1,6 @@
package d2ir
import (
"encoding/json"
"errors"
"fmt"
"strings"
@ -12,7 +11,9 @@ import (
type Node interface {
node()
ast() d2ast.Node
Copy(newp Parent) Node
fmt.Stringer
}
var _ Node = &Scalar{}
@ -68,6 +69,12 @@ func (n *Map) value() {}
func (n *Array) composite() {}
func (n *Map) composite() {}
func (n *Scalar) String() string { return d2format.Format(n.ast()) }
func (n *Field) String() string { return d2format.Format(n.ast()) }
func (n *Edge) String() string { return d2format.Format(n.ast()) }
func (n *Array) String() string { return d2format.Format(n.ast()) }
func (n *Map) String() string { return d2format.Format(n.ast()) }
type Scalar struct {
parent Parent
Value d2ast.Scalar `json:"value"`
@ -91,10 +98,6 @@ func (s *Scalar) Equal(s2 *Scalar) bool {
}
func (s *Scalar) String() string {
return d2format.Format(s.Value)
}
type Map struct {
parent Parent
Fields []*Field `json:"fields"`
@ -160,6 +163,21 @@ type EdgeID struct {
Index *int `json:"index"`
}
func NewEdgeIDs(k *d2ast.Key) (eida []*EdgeID) {
for _, ke := range k.Edges {
eida = append(eida, &EdgeID{
SrcPath: d2format.KeyPath(ke.Src),
SrcArrow: ke.SrcArrow == "<",
DstPath: d2format.KeyPath(ke.Dst),
DstArrow: ke.DstArrow == ">",
})
}
if k.EdgeIndex != nil && k.EdgeIndex.Int != nil {
eida[0].Index = k.EdgeIndex.Int
}
return eida
}
func (eid *EdgeID) Copy() *EdgeID {
tmp := *eid
eid = &tmp
@ -447,25 +465,79 @@ func (m *Map) EnsureEdge(eid *EdgeID) (*Edge, error) {
return e, nil
}
func (m *Map) String() string {
b, err := json.Marshal(m)
if err != nil {
panic(fmt.Sprintf("d2ir: failed to marshal d2ir.Map: %v", err))
}
return string(b)
func (s *Scalar) ast() d2ast.Node {
return s.Value
}
func NewEdgeIDs(k *d2ast.Key) (eida []*EdgeID) {
for _, ke := range k.Edges {
eida = append(eida, &EdgeID{
SrcPath: d2format.KeyPath(ke.Src),
SrcArrow: ke.SrcArrow == "<",
DstPath: d2format.KeyPath(ke.Dst),
DstArrow: ke.DstArrow == ">",
})
func (f *Field) ast() d2ast.Node {
k := &d2ast.Key{
Key: &d2ast.KeyPath{
Path: []*d2ast.StringBox{
d2ast.MakeValueBox(d2ast.RawString(f.Name, true)).StringBox(),
},
},
}
if k.EdgeIndex != nil && k.EdgeIndex.Int != nil {
eida[0].Index = k.EdgeIndex.Int
if f.Primary != nil {
k.Primary = d2ast.MakeValueBox(f.Primary.ast().(d2ast.Value)).ScalarBox()
}
return eida
if f.Composite != nil {
k.Value = d2ast.MakeValueBox(f.Composite.ast().(d2ast.Value))
}
return k
}
func (e *Edge) ast() d2ast.Node {
astEdge := &d2ast.Edge{}
astEdge.Src = d2ast.MakeKeyPath(e.ID.SrcPath)
if e.ID.SrcArrow {
astEdge.SrcArrow = "<"
}
astEdge.Dst = d2ast.MakeKeyPath(e.ID.DstPath)
if e.ID.DstArrow {
astEdge.DstArrow = ">"
}
k := &d2ast.Key{
Edges: []*d2ast.Edge{astEdge},
}
if e.Primary != nil {
k.Primary = d2ast.MakeValueBox(e.Primary.ast().(d2ast.Value)).ScalarBox()
}
if e.Map != nil {
k.Value = d2ast.MakeValueBox(e.Map.ast().(*d2ast.Map))
}
return k
}
func (a *Array) ast() d2ast.Node {
if a == nil {
return nil
}
astArray := &d2ast.Array{}
for _, av := range a.Values {
astArray.Nodes = append(astArray.Nodes, d2ast.MakeArrayNodeBox(av.ast().(d2ast.ArrayNode)))
}
return astArray
}
func (m *Map) ast() d2ast.Node {
if m == nil {
return nil
}
astMap := &d2ast.Map{}
if m.parent != nil {
astMap.Range = d2ast.MakeRange(",1:0:0-1:0:0")
}
for _, f := range m.Fields {
astMap.Nodes = append(astMap.Nodes, d2ast.MakeMapNodeBox(f.ast().(d2ast.MapNode)))
}
for _, e := range m.Edges {
astMap.Nodes = append(astMap.Nodes, d2ast.MakeMapNodeBox(e.ast().(d2ast.MapNode)))
}
return astMap
}