this repo has no description
0
fork

Configure Feed

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

cue: add builtins and and or

These allow computing disjunctions and
conjunctions, for instance resulting from
comprehensions.

Change-Id: I1db6566c9114d70017c923e93f1c1d4091085db9
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/1920
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Marcel van Lohuizen <mpvl@google.com>

authored by

Marcel van Lohuizen and committed by
Marcel van Lohuizen
a460fe84 9ee652dd

+106
+4
cue/ast.go
··· 345 345 346 346 case "len": 347 347 return lenBuiltin 348 + case "and": 349 + return andBuiltin 350 + case "or": 351 + return orBuiltin 348 352 } 349 353 if r, ok := predefinedRanges[n.Name]; ok { 350 354 return r
+39
cue/builtin.go
··· 24 24 "path" 25 25 "sort" 26 26 27 + "cuelang.org/go/cue/errors" 27 28 "cuelang.org/go/cue/parser" 28 29 ) 29 30 ··· 131 132 }, 132 133 } 133 134 135 + var andBuiltin = &builtin{ 136 + Name: "and", 137 + Params: []kind{listKind}, 138 + Result: intKind, 139 + Func: func(c *callCtxt) { 140 + iter := c.list(0) 141 + if !iter.Next() { 142 + c.ret = &top{baseValue{c.src}} 143 + return 144 + } 145 + u := iter.Value().path.v 146 + for iter.Next() { 147 + u = mkBin(c.ctx, c.src.Pos(), opUnify, u, iter.Value().path.v) 148 + } 149 + c.ret = u 150 + }, 151 + } 152 + 153 + var orBuiltin = &builtin{ 154 + Name: "or", 155 + Params: []kind{stringKind | bytesKind | listKind | structKind}, 156 + Result: intKind, 157 + Func: func(c *callCtxt) { 158 + iter := c.list(0) 159 + d := []dValue{} 160 + for iter.Next() { 161 + d = append(d, dValue{iter.Value().path.v, false}) 162 + } 163 + c.ret = &disjunction{baseValue{c.src}, d} 164 + if len(d) == 0 { 165 + c.ret = errors.New("empty or") 166 + } 167 + }, 168 + } 169 + 134 170 func (x *builtin) kind() kind { 135 171 return lambdaKind 136 172 } ··· 176 212 } 177 213 }() 178 214 x.Func(&call) 215 + if e, ok := call.ret.(value); ok { 216 + return e 217 + } 179 218 return convert(ctx, x, call.ret) 180 219 } 181 220
+15
cue/builtin_test.go
··· 113 113 }, { 114 114 testExpr(`len('f\x20\x20')`), 115 115 `3`, 116 + }, { 117 + testExpr(`and([string, "foo"])`), 118 + `"foo"`, 119 + }, { 120 + testExpr(`and([string, =~"fo"]) & "foo"`), 121 + `"foo"`, 122 + }, { 123 + testExpr(`and([])`), 124 + `_`, 125 + }, { 126 + testExpr(`or([1, 2, 3]) & 2`), 127 + `2`, 128 + }, { 129 + testExpr(`or([])`), 130 + `_|_(builtin:or:empty or)`, 116 131 }} 117 132 for _, tc := range testCases { 118 133 t.Run("", func(t *testing.T) {
+26
cue/resolve_test.go
··· 1311 1311 out: `<0>{obj: <1>{<>: <2>(Name: string)-><3>{a: (*"dummy" | string) if true yield ("sub"): <4>{as: <3>.a}}, ` + 1312 1312 `foo: <5>{a: "bar", sub: <6>{as: "bar"}}}}`, 1313 1313 }, { 1314 + desc: "builtins", 1315 + in: ` 1316 + a1: { 1317 + a: and([b, c]) 1318 + b: =~"oo" 1319 + c: =~"fo" 1320 + } 1321 + a2: a1 & { a: "foo" } 1322 + a3: a1 & { a: "bar" } 1323 + 1324 + o1: { 1325 + a: or([b, c]) 1326 + b: string 1327 + c: "bar" 1328 + } 1329 + o2: o1 & { a: "foo" } 1330 + o3: o1 & { a: "foo", b: "baz" } 1331 + `, 1332 + out: `<0>{` + 1333 + `a1: <1>{a: (=~"oo" & =~"fo"), b: =~"oo", c: =~"fo"}, ` + 1334 + `a2: <2>{a: "foo", b: =~"oo", c: =~"fo"}, ` + 1335 + `a3: <3>{a: _|_((=~"oo" & "bar"):"bar" does not match =~"oo"), b: =~"oo", c: =~"fo"}, ` + 1336 + `o1: <4>{a: string, b: string, c: "bar"}, ` + 1337 + `o2: <5>{a: "foo", b: string, c: "bar"}, ` + 1338 + `o3: <6>{a: _|_((builtin:or ([<7>.b,<7>.c]) & "foo"):empty disjunction: failed to unify: baz != foo), b: "baz", c: "bar"}}`, 1339 + }, { 1314 1340 desc: "self-reference cycles conflicts with strings", 1315 1341 in: ` 1316 1342 a: {
+22
doc/ref/spec.md
··· 2251 2251 len({a:1, b:2}) 2 2252 2252 ``` 2253 2253 2254 + ### `and` 2255 + 2256 + The built-in function `and` takes a list and returns the result of applying 2257 + the `&` operator to all elements in the list. 2258 + It returns top for the empty list. 2259 + 2260 + Expression: Result 2261 + and([a, b]) a & b 2262 + and([a]) a 2263 + and([]) _ 2264 + 2265 + ### `or` 2266 + 2267 + The built-in function `or` takes a list and returns the result of applying 2268 + the `|` operator to all elements in the list. 2269 + It returns bottom for the empty list. 2270 + 2271 + Expression: Result 2272 + and([a, b]) a | b 2273 + and([a]) a 2274 + and([]) _|_ 2275 + 2254 2276 2255 2277 ## Cycles 2256 2278