d2ir: Add d2ir -> d2ast for stringifying the IR
This commit is contained in:
parent
91149543f5
commit
10ca5e2ce1
3 changed files with 134 additions and 28 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
116
d2ir/d2ir.go
116
d2ir/d2ir.go
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue