this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

cue: add ReferencePath

Change-Id: I7f8024aca1200995368600010d3e024d7bd7c9a3
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/9421
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>

+114 -32
+33
cue/path.go
··· 469 469 func (p pathError) feature(r adt.Runtime) adt.Feature { 470 470 return adt.InvalidLabel 471 471 } 472 + 473 + func valueToSel(v adt.Value) Selector { 474 + switch x := adt.Unwrap(v).(type) { 475 + case *adt.Num: 476 + i, err := x.X.Int64() 477 + if err != nil { 478 + return Selector{&pathError{errors.Promote(err, "invalid number")}} 479 + } 480 + return Index(int(i)) 481 + case *adt.String: 482 + return Str(x.Str) 483 + default: 484 + return Selector{pathError{errors.Newf(token.NoPos, "dynamic selector")}} 485 + } 486 + } 487 + 488 + func featureToSel(f adt.Feature, r adt.Runtime) Selector { 489 + switch f.Typ() { 490 + case adt.StringLabel: 491 + return Str(f.StringValue(r)) 492 + case adt.IntLabel: 493 + return Index(f.Index()) 494 + case adt.DefinitionLabel: 495 + return Def(f.IdentString(r)) 496 + case adt.HiddenLabel, adt.HiddenDefinitionLabel: 497 + ident := f.IdentString(r) 498 + pkg := f.PkgID(r) 499 + return Hid(ident, pkg) 500 + } 501 + return Selector{pathError{ 502 + errors.Newf(token.NoPos, "unexpected feature type %v", f.Typ()), 503 + }} 504 + }
+41 -24
cue/types.go
··· 1849 1849 // inst.Lookup(path) resolves to the same value, or no path if this value is not 1850 1850 // a reference. If a reference contains index selection (foo[bar]), it will 1851 1851 // only return a reference if the index resolves to a concrete value. 1852 + // 1853 + // Deprecated: use ReferencePath 1852 1854 func (v Value) Reference() (inst *Instance, path []string) { 1855 + root, p := v.ReferencePath() 1856 + if !root.Exists() { 1857 + return nil, nil 1858 + } 1859 + 1860 + inst = getImportFromNode(v.idx, root.v) 1861 + for _, sel := range p.Selectors() { 1862 + switch x := sel.sel.(type) { 1863 + case stringSelector: 1864 + path = append(path, string(x)) 1865 + default: 1866 + path = append(path, sel.String()) 1867 + } 1868 + } 1869 + 1870 + return inst, path 1871 + } 1872 + 1873 + // ReferencePath returns the value and path referred to by this value such that 1874 + // value.LookupPath(path) resolves to the same value, or no path if this value 1875 + // is not a reference. 1876 + func (v Value) ReferencePath() (root Value, p Path) { 1853 1877 // TODO: don't include references to hidden fields. 1854 1878 if v.v == nil || len(v.v.Conjuncts) != 1 { 1855 - return nil, nil 1879 + return Value{}, Path{} 1856 1880 } 1857 1881 ctx := v.ctx() 1858 1882 c := v.v.Conjuncts[0] 1859 1883 1860 - return reference(v.idx, ctx, c.Env, c.Expr()) 1884 + x, path := reference(v.idx, ctx, c.Env, c.Expr()) 1885 + if x == nil { 1886 + return Value{}, Path{} 1887 + } 1888 + return makeValue(v.idx, x), Path{path: path} 1861 1889 } 1862 1890 1863 - func reference(rt *runtime.Runtime, c *adt.OpContext, env *adt.Environment, r adt.Expr) (inst *Instance, path []string) { 1891 + func reference(rt *runtime.Runtime, c *adt.OpContext, env *adt.Environment, r adt.Expr) (inst *adt.Vertex, path []Selector) { 1864 1892 ctx := c 1865 1893 defer ctx.PopState(ctx.PushState(env, r.Source())) 1866 1894 ··· 1875 1903 case *adt.FieldReference: 1876 1904 env := ctx.Env(x.UpCount) 1877 1905 inst, path = mkPath(rt, nil, env.Vertex) 1878 - path = append(path, x.Label.SelectorString(c)) 1906 + path = appendSelector(path, featureToSel(x.Label, rt)) 1879 1907 1880 1908 case *adt.LabelReference: 1881 1909 env := ctx.Env(x.UpCount) ··· 1885 1913 env := ctx.Env(x.UpCount) 1886 1914 inst, path = mkPath(rt, nil, env.Vertex) 1887 1915 v, _ := ctx.Evaluate(env, x.Label) 1888 - str := ctx.StringValue(v) 1889 - path = append(path, str) 1916 + path = appendSelector(path, valueToSel(v)) 1890 1917 1891 1918 case *adt.ImportReference: 1892 - imp := x.ImportPath.StringValue(ctx) 1893 - inst = getImportFromPath(rt, imp) 1919 + inst, _ = rt.LoadImport(rt.LabelStr(x.ImportPath)) 1894 1920 1895 1921 case *adt.SelectorExpr: 1896 1922 inst, path = reference(rt, c, env, x.X) 1897 - path = append(path, x.Sel.SelectorString(ctx)) 1923 + path = appendSelector(path, featureToSel(x.Sel, rt)) 1898 1924 1899 1925 case *adt.IndexExpr: 1900 1926 inst, path = reference(rt, c, env, x.X) 1901 1927 v, _ := ctx.Evaluate(env, x.Index) 1902 - str := ctx.StringValue(v) 1903 - path = append(path, str) 1928 + path = appendSelector(path, valueToSel(v)) 1904 1929 } 1905 1930 if inst == nil { 1906 1931 return nil, nil ··· 1908 1933 return inst, path 1909 1934 } 1910 1935 1911 - func mkPath(ctx *runtime.Runtime, a []string, v *adt.Vertex) (inst *Instance, path []string) { 1936 + func mkPath(r *runtime.Runtime, a []Selector, v *adt.Vertex) (root *adt.Vertex, path []Selector) { 1912 1937 if v.Parent == nil { 1913 - return getImportFromNode(ctx, v), a 1938 + return v, a 1914 1939 } 1915 - inst, path = mkPath(ctx, a, v.Parent) 1916 - path = append(path, v.Label.SelectorString(ctx)) 1917 - return inst, path 1940 + root, path = mkPath(r, a, v.Parent) 1941 + path = appendSelector(path, featureToSel(v.Label, r)) 1942 + return root, path 1918 1943 } 1919 - 1920 - // // References reports all references used to evaluate this value. It does not 1921 - // // report references for sub fields if v is a struct. 1922 - // // 1923 - // // Deprecated: can be implemented in terms of Reference and Expr. 1924 - // func (v Value) References() [][]string { 1925 - // panic("deprecated") 1926 - // } 1927 1944 1928 1945 type options struct { 1929 1946 concrete bool // enforce that values are concrete
+40 -8
cue/types_test.go
··· 3104 3104 } 3105 3105 } 3106 3106 3107 - func TestReference(t *testing.T) { 3107 + func TestReferencePath(t *testing.T) { 3108 3108 testCases := []struct { 3109 3109 input string 3110 3110 want string ··· 3120 3120 want: "a", 3121 3121 }, { 3122 3122 input: "v: w: x: a.b.c, a: b: c: 1", 3123 - want: "a b c", 3123 + want: "a.b.c", 3124 3124 }, { 3125 3125 input: "v: w: x: w.a.b.c, v: w: a: b: c: 1", 3126 - want: "v w a b c", 3126 + want: "v.w.a.b.c", 3127 3127 }, { 3128 3128 input: `v: w: x: w.a.b.c, v: w: a: b: c: 1, #D: 3, opt?: 3, "v\(#D)": 3, X: {a: 3}, X`, 3129 - want: "v w a b c", 3129 + want: "v.w.a.b.c", 3130 3130 }, { 3131 - input: `v: w: x: w.a[bb]["c"], v: w: a: b: c: 1, bb: "b"`, 3132 - want: "v w a b c", 3131 + input: ` 3132 + v: w: x: w.a[bb]["c"] 3133 + v: w: a: b: c: 1 3134 + bb: "b"`, 3135 + want: "v.w.a.b.c", 3136 + }, { 3137 + input: ` 3138 + X="\(y)": 1 3139 + v: w: x: X // TODO: Move up for crash 3140 + y: "foo"`, 3141 + want: "foo", 3142 + }, { 3143 + input: ` 3144 + v: w: _ 3145 + v: [X=string]: x: a[X] 3146 + a: w: 1`, 3147 + want: "a.w", 3133 3148 }, { 3134 3149 input: `v: { 3135 3150 for t in src { ··· 3138 3153 } 3139 3154 }, 3140 3155 src: ["x", "y"]`, 3141 - want: "v w tx", 3156 + want: "v.w.tx", 3142 3157 }, { 3143 3158 input: ` 3144 3159 v: w: x: a ··· 3167 3182 var r Runtime 3168 3183 inst, _ := r.Compile("in", tc.input) // getInstance(t, tc.input) 3169 3184 v := inst.Lookup("v", "w", "x") 3185 + 3186 + root, path := v.ReferencePath() 3187 + if got := path.String(); got != tc.want { 3188 + t.Errorf("\n got %v;\nwant %v", got, tc.want) 3189 + } 3190 + 3191 + if tc.want != "" { 3192 + want := "1" 3193 + if tc.alt != "" { 3194 + want = tc.alt 3195 + } 3196 + v := fmt.Sprint(root.LookupPath(path)) 3197 + if v != want { 3198 + t.Errorf("path resolved to %s; want %s", v, want) 3199 + } 3200 + } 3201 + 3170 3202 inst, a := v.Reference() 3171 - if got := strings.Join(a, " "); got != tc.want { 3203 + if got := strings.Join(a, "."); got != tc.want { 3172 3204 t.Errorf("\n got %v;\nwant %v", got, tc.want) 3173 3205 } 3174 3206