internal/core/eval: fix multi-conjunct pattern constraints
Change-Id: I9842281e9fbb8f004b8a17b90c479bc79f4e15f2
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6703
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/testdata/eval/bulk.txtar b/cue/testdata/eval/bulk.txtar
index c32e0e0..dd0a305 100644
--- a/cue/testdata/eval/bulk.txtar
+++ b/cue/testdata/eval/bulk.txtar
@@ -12,8 +12,36 @@
}
}
+t1: {
+ #a: {
+ [>"e" & <"z"]: int
+ }
+ b: #a & { f: 4 }
+ c: #a & { z: 4 }
+}
+
+t2: {
+ #a: {
+ ["x" | "y"]: int
+ }
+ b: #a & { x: 4 }
+ c: #a & { z: 4 }
+}
+
-- out/eval --
-(struct){
+Errors:
+t1.c: field `z` not allowed:
+ ./in.cue:15:3
+ ./in.cue:15:7
+ ./in.cue:19:11
+t2.c: field `z` not allowed:
+ ./in.cue:23:3
+ ./in.cue:23:7
+ ./in.cue:27:11
+
+Result:
+(_|_){
+ // [eval]
a: (struct){
foo: (struct){
a: (int){ 1 }
@@ -29,6 +57,36 @@
name: (string){ "foobar" }
}
}
+ t1: (_|_){
+ // [eval]
+ #a: (#struct){
+ }
+ b: (#struct){
+ f: (int){ 4 }
+ }
+ c: (_|_){
+ // [eval] t1.c: field `z` not allowed:
+ // ./in.cue:15:3
+ // ./in.cue:15:7
+ // ./in.cue:19:11
+ z: (int){ 4 }
+ }
+ }
+ t2: (_|_){
+ // [eval]
+ #a: (#struct){
+ }
+ b: (#struct){
+ x: (int){ 4 }
+ }
+ c: (_|_){
+ // [eval] t2.c: field `z` not allowed:
+ // ./in.cue:23:3
+ // ./in.cue:23:7
+ // ./in.cue:27:11
+ z: (int){ 4 }
+ }
+ }
}
-- out/compile --
--- in.cue
@@ -47,4 +105,26 @@
c: 2
}
})
+ t1: {
+ #a: {
+ [(>"e" & <"z")]: int
+ }
+ b: (〈0;#a〉 & {
+ f: 4
+ })
+ c: (〈0;#a〉 & {
+ z: 4
+ })
+ }
+ t2: {
+ #a: {
+ [("x"|"y")]: int
+ }
+ b: (〈0;#a〉 & {
+ x: 4
+ })
+ c: (〈0;#a〉 & {
+ z: 4
+ })
+ }
}
diff --git a/internal/core/eval/optionals.go b/internal/core/eval/optionals.go
index 3dc1884..0426c18 100644
--- a/internal/core/eval/optionals.go
+++ b/internal/core/eval/optionals.go
@@ -16,7 +16,9 @@
// TODO: rename this file to fieldset.go
-import "cuelang.org/go/internal/core/adt"
+import (
+ "cuelang.org/go/internal/core/adt"
+)
// fieldSet represents the fields for a single struct literal, along
// the constraints of fields that may be added.
@@ -169,33 +171,22 @@
// TODO: handle dynamically
return
}
- switch f := v.(type) {
- case *adt.Num:
- // Just assert an error. Lists have not been expanded yet at
- // this point, so there is no need to check for existing
- //fields.
- l, err := adt.MakeLabel(x.Src, c.Int64(f), adt.IntLabel)
- if err != nil {
- c.AddErr(err)
- return
- }
- o.bulk = append(o.bulk, bulkField{labelMatcher(l), x})
+ if m := o.getMatcher(c, v); m != nil {
+ o.bulk = append(o.bulk, bulkField{m, x})
+ }
+}
+
+func (o *fieldSet) getMatcher(c *adt.OpContext, v adt.Value) fieldMatcher {
+ switch f := v.(type) {
case *adt.Top:
- o.bulk = append(o.bulk, bulkField{typeMatcher(adt.TopKind), x})
+ return typeMatcher(adt.TopKind)
case *adt.BasicType:
- o.bulk = append(o.bulk, bulkField{typeMatcher(f.K), x})
-
- case *adt.String:
- l := c.Label(f)
- o.bulk = append(o.bulk, bulkField{labelMatcher(l), x})
-
- case adt.Validator:
- o.bulk = append(o.bulk, bulkField{validateMatcher{f}, x})
+ return typeMatcher(f.K)
default:
- // TODO(err): not allowed type
+ return o.newPatternMatcher(c, v)
}
}
@@ -212,12 +203,6 @@
Match(c *adt.OpContext, f adt.Feature) bool
}
-type labelMatcher adt.Feature
-
-func (m labelMatcher) Match(c *adt.OpContext, f adt.Feature) bool {
- return adt.Feature(m) == f
-}
-
type typeMatcher adt.Kind
func (m typeMatcher) Match(c *adt.OpContext, f adt.Feature) bool {
@@ -231,15 +216,6 @@
return false
}
-type validateMatcher struct {
- adt.Validator
-}
-
-func (m validateMatcher) Match(c *adt.OpContext, f adt.Feature) bool {
- v := f.ToValue(c)
- return c.Validate(m.Validator, v) == nil
-}
-
type dynamicMatcher struct {
env *adt.Environment
expr adt.Expr
@@ -259,3 +235,20 @@
}
return f.SelectorString(c) == s.Str
}
+
+type patternMatcher adt.Conjunct
+
+func (m patternMatcher) Match(c *adt.OpContext, f adt.Feature) bool {
+ v := adt.Vertex{}
+ v.AddConjunct(adt.Conjunct(m))
+ label := f.ToValue(c)
+ v.AddConjunct(adt.MakeConjunct(m.Env, label))
+ v.Finalize(c)
+ b, _ := v.Value.(*adt.Bottom)
+ return b == nil
+}
+
+func (o *fieldSet) newPatternMatcher(ctx *adt.OpContext, x adt.Value) fieldMatcher {
+ c := adt.MakeConjunct(o.env, x)
+ return patternMatcher(c)
+}