addPathToExpr is roughly equivalent to this: func simpleAddPathToExpr((e dag.Expr, path []string) dag.Expr { for _, elem := range path { e = &dag.Dot{Kind: "Dot", LHS: e, RHS: elem} } return e } addPathToExpr differs in a few ways: - It returns a dag.This when possible. - It
(e dag.Expr, path []string)
| 740 | // - It descends to a dag.RecordExpr.Elem when possible. |
| 741 | // - It returns false when it cannot descend to a dag.RecordExpr.Elem. |
| 742 | func addPathToExpr(e dag.Expr, path []string) (dag.Expr, bool) { |
| 743 | if len(path) == 0 { |
| 744 | return e, true |
| 745 | } |
| 746 | switch e := e.(type) { |
| 747 | case *dag.RecordExpr: |
| 748 | var spread *dag.Spread |
| 749 | for _, elem := range slices.Backward(e.Elems) { |
| 750 | switch elem := elem.(type) { |
| 751 | case *dag.Field: |
| 752 | if elem.Name != path[0] { |
| 753 | continue |
| 754 | } |
| 755 | if spread != nil { |
| 756 | // Don't know which will win. |
| 757 | return e, false |
| 758 | } |
| 759 | return addPathToExpr(elem.Value, path[1:]) |
| 760 | case *dag.Spread: |
| 761 | if spread != nil { |
| 762 | // Don't know which will win. |
| 763 | return e, false |
| 764 | } |
| 765 | spread = elem |
| 766 | } |
| 767 | } |
| 768 | if spread == nil { |
| 769 | return e, false |
| 770 | } |
| 771 | return addPathToExpr(spread.Expr, path) |
| 772 | case *dag.ThisExpr: |
| 773 | return dag.NewThis(slices.Concat(e.Path, path)), true |
| 774 | } |
| 775 | for _, elem := range path { |
| 776 | e = &dag.DotExpr{Kind: "DotExpr", LHS: e, RHS: elem} |
| 777 | } |
| 778 | return e, true |
| 779 | } |
| 780 | |
| 781 | func recordElemsFieldsAndSpread(elems []dag.RecordElem) (map[string]dag.Expr, dag.Expr, bool) { |
| 782 | fields := map[string]dag.Expr{} |
no test coverage detected