github.com/joomcode/cue@v0.4.4-0.20221111115225-539fe3512047/internal/core/adt/optional.go (about) 1 // Copyright 2020 CUE Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package adt 16 17 // MatchAndInsert finds matching optional parts for a given Arc and adds its 18 // conjuncts. Bulk fields are only applied if no fields match, and additional 19 // constraints are only added if neither regular nor bulk fields match. 20 func (o *StructInfo) MatchAndInsert(c *OpContext, arc *Vertex) { 21 env := o.Env 22 23 closeInfo := o.CloseInfo 24 closeInfo.IsClosed = false 25 26 // Match normal fields 27 matched := false 28 outer: 29 for _, f := range o.Fields { 30 if f.Label == arc.Label { 31 for _, e := range f.Optional { 32 arc.AddConjunct(MakeConjunct(env, e, closeInfo)) 33 } 34 matched = true 35 break outer 36 } 37 } 38 39 f := arc.Label 40 if !f.IsRegular() { 41 return 42 } 43 var label Value 44 45 if int64(f.Index()) == MaxIndex { 46 f = 0 47 } else if o.types&HasComplexPattern != 0 && f.IsString() { 48 label = f.ToValue(c) 49 } 50 51 if len(o.Bulk) > 0 { 52 bulkEnv := *env 53 bulkEnv.DynamicLabel = f 54 bulkEnv.Deref = nil 55 bulkEnv.Cycles = nil 56 57 // match bulk optional fields / pattern properties 58 for _, b := range o.Bulk { 59 // if matched && f.additional { 60 // continue 61 // } 62 if matchBulk(c, env, b, f, label) { 63 matched = true 64 info := closeInfo.SpawnSpan(b.Value, ConstraintSpan) 65 arc.AddConjunct(MakeConjunct(&bulkEnv, b, info)) 66 } 67 } 68 } 69 70 if matched || len(o.Additional) == 0 { 71 return 72 } 73 74 addEnv := *env 75 addEnv.Deref = nil 76 addEnv.Cycles = nil 77 78 // match others 79 for _, x := range o.Additional { 80 info := closeInfo 81 if _, ok := x.expr().(*Top); !ok { 82 info = info.SpawnSpan(x, ConstraintSpan) 83 } 84 // TODO: consider moving in above block (2 lines up). 85 arc.AddConjunct(MakeConjunct(&addEnv, x, info)) 86 } 87 } 88 89 // matchBulk reports whether feature f matches the filter of x. It evaluation of 90 // the filter is erroneous, it returns false and the error will be set in c. 91 func matchBulk(c *OpContext, env *Environment, x *BulkOptionalField, f Feature, label Value) bool { 92 v := env.evalCached(c, x.Filter) 93 v = Unwrap(v) 94 95 // Fast-track certain cases. 96 switch x := v.(type) { 97 case *Bottom: 98 if c.errs == nil { 99 c.AddBottom(x) 100 } 101 return false 102 case *Top: 103 return true 104 105 case *BasicType: 106 return x.K&StringKind != 0 107 108 case *BoundValue: 109 switch x.Kind() { 110 case StringKind: 111 if label == nil { 112 return false 113 } 114 str := label.(*String).Str 115 return x.validateStr(c, str) 116 117 case IntKind: 118 return x.validateInt(c, int64(f.Index())) 119 } 120 } 121 122 if label == nil { 123 return false 124 } 125 126 n := Vertex{} 127 m := MakeRootConjunct(env, v) 128 n.AddConjunct(m) 129 n.AddConjunct(MakeRootConjunct(m.Env, label)) 130 131 c.inConstraint++ 132 n.Finalize(c) 133 c.inConstraint-- 134 135 b, _ := n.BaseValue.(*Bottom) 136 return b == nil 137 }