github.com/bytedance/go-tagexpr/v2@v2.9.8/spec_operator.go (about) 1 // Copyright 2019 Bytedance Inc. All Rights Reserved. 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 tagexpr 16 17 import ( 18 "context" 19 "math" 20 ) 21 22 // --------------------------- Operator --------------------------- 23 24 type additionExprNode struct{ exprBackground } 25 26 func (ae *additionExprNode) String() string { 27 return "+" 28 } 29 30 func newAdditionExprNode() ExprNode { return &additionExprNode{} } 31 32 func (ae *additionExprNode) Run(ctx context.Context, currField string, tagExpr *TagExpr) interface{} { 33 // positive number or Addition 34 v0 := ae.leftOperand.Run(ctx, currField, tagExpr) 35 v1 := ae.rightOperand.Run(ctx, currField, tagExpr) 36 if s0, ok := toFloat64(v0, false); ok { 37 s1, _ := toFloat64(v1, true) 38 return s0 + s1 39 } 40 if s0, ok := toString(v0, false); ok { 41 s1, _ := toString(v1, true) 42 return s0 + s1 43 } 44 return v0 45 } 46 47 type multiplicationExprNode struct{ exprBackground } 48 49 func (ae *multiplicationExprNode) String() string { 50 return "*" 51 } 52 53 func newMultiplicationExprNode() ExprNode { return &multiplicationExprNode{} } 54 55 func (ae *multiplicationExprNode) Run(ctx context.Context, currField string, tagExpr *TagExpr) interface{} { 56 v0, _ := toFloat64(ae.leftOperand.Run(ctx, currField, tagExpr), true) 57 v1, _ := toFloat64(ae.rightOperand.Run(ctx, currField, tagExpr), true) 58 return v0 * v1 59 } 60 61 type divisionExprNode struct{ exprBackground } 62 63 func (de *divisionExprNode) String() string { 64 return "/" 65 } 66 67 func newDivisionExprNode() ExprNode { return &divisionExprNode{} } 68 69 func (de *divisionExprNode) Run(ctx context.Context, currField string, tagExpr *TagExpr) interface{} { 70 v1, _ := toFloat64(de.rightOperand.Run(ctx, currField, tagExpr), true) 71 if v1 == 0 { 72 return math.NaN() 73 } 74 v0, _ := toFloat64(de.leftOperand.Run(ctx, currField, tagExpr), true) 75 return v0 / v1 76 } 77 78 type subtractionExprNode struct{ exprBackground } 79 80 func (de *subtractionExprNode) String() string { 81 return "-" 82 } 83 84 func newSubtractionExprNode() ExprNode { return &subtractionExprNode{} } 85 86 func (de *subtractionExprNode) Run(ctx context.Context, currField string, tagExpr *TagExpr) interface{} { 87 v0, _ := toFloat64(de.leftOperand.Run(ctx, currField, tagExpr), true) 88 v1, _ := toFloat64(de.rightOperand.Run(ctx, currField, tagExpr), true) 89 return v0 - v1 90 } 91 92 type remainderExprNode struct{ exprBackground } 93 94 func (re *remainderExprNode) String() string { 95 return "%" 96 } 97 98 func newRemainderExprNode() ExprNode { return &remainderExprNode{} } 99 100 func (re *remainderExprNode) Run(ctx context.Context, currField string, tagExpr *TagExpr) interface{} { 101 v1, _ := toFloat64(re.rightOperand.Run(ctx, currField, tagExpr), true) 102 if v1 == 0 { 103 return math.NaN() 104 } 105 v0, _ := toFloat64(re.leftOperand.Run(ctx, currField, tagExpr), true) 106 return float64(int64(v0) % int64(v1)) 107 } 108 109 type equalExprNode struct{ exprBackground } 110 111 func (ee *equalExprNode) String() string { 112 return "==" 113 } 114 115 func newEqualExprNode() ExprNode { return &equalExprNode{} } 116 117 func (ee *equalExprNode) Run(ctx context.Context, currField string, tagExpr *TagExpr) interface{} { 118 v0 := ee.leftOperand.Run(ctx, currField, tagExpr) 119 v1 := ee.rightOperand.Run(ctx, currField, tagExpr) 120 if v0 == v1 { 121 return true 122 } 123 if s0, ok := toFloat64(v0, false); ok { 124 if s1, ok := toFloat64(v1, true); ok { 125 return s0 == s1 126 } 127 } 128 if s0, ok := toString(v0, false); ok { 129 if s1, ok := toString(v1, true); ok { 130 return s0 == s1 131 } 132 return false 133 } 134 switch r := v0.(type) { 135 case bool: 136 r1, ok := v1.(bool) 137 if ok { 138 return r == r1 139 } 140 case nil: 141 return v1 == nil 142 } 143 return false 144 } 145 146 type notEqualExprNode struct{ equalExprNode } 147 148 func (ne *notEqualExprNode) String() string { 149 return "!=" 150 } 151 152 func newNotEqualExprNode() ExprNode { return ¬EqualExprNode{} } 153 154 func (ne *notEqualExprNode) Run(ctx context.Context, currField string, tagExpr *TagExpr) interface{} { 155 return !ne.equalExprNode.Run(ctx, currField, tagExpr).(bool) 156 } 157 158 type greaterExprNode struct{ exprBackground } 159 160 func (ge *greaterExprNode) String() string { 161 return ">" 162 } 163 164 func newGreaterExprNode() ExprNode { return &greaterExprNode{} } 165 166 func (ge *greaterExprNode) Run(ctx context.Context, currField string, tagExpr *TagExpr) interface{} { 167 v0 := ge.leftOperand.Run(ctx, currField, tagExpr) 168 v1 := ge.rightOperand.Run(ctx, currField, tagExpr) 169 if s0, ok := toFloat64(v0, false); ok { 170 if s1, ok := toFloat64(v1, true); ok { 171 return s0 > s1 172 } 173 } 174 if s0, ok := toString(v0, false); ok { 175 if s1, ok := toString(v1, true); ok { 176 return s0 > s1 177 } 178 return false 179 } 180 return false 181 } 182 183 type greaterEqualExprNode struct{ exprBackground } 184 185 func (ge *greaterEqualExprNode) String() string { 186 return ">=" 187 } 188 189 func newGreaterEqualExprNode() ExprNode { return &greaterEqualExprNode{} } 190 191 func (ge *greaterEqualExprNode) Run(ctx context.Context, currField string, tagExpr *TagExpr) interface{} { 192 v0 := ge.leftOperand.Run(ctx, currField, tagExpr) 193 v1 := ge.rightOperand.Run(ctx, currField, tagExpr) 194 if s0, ok := toFloat64(v0, false); ok { 195 if s1, ok := toFloat64(v1, true); ok { 196 return s0 >= s1 197 } 198 } 199 if s0, ok := toString(v0, false); ok { 200 if s1, ok := toString(v1, true); ok { 201 return s0 >= s1 202 } 203 return false 204 } 205 return false 206 } 207 208 type lessExprNode struct{ exprBackground } 209 210 func (le *lessExprNode) String() string { 211 return "<" 212 } 213 214 func newLessExprNode() ExprNode { return &lessExprNode{} } 215 216 func (le *lessExprNode) Run(ctx context.Context, currField string, tagExpr *TagExpr) interface{} { 217 v0 := le.leftOperand.Run(ctx, currField, tagExpr) 218 v1 := le.rightOperand.Run(ctx, currField, tagExpr) 219 if s0, ok := toFloat64(v0, false); ok { 220 if s1, ok := toFloat64(v1, true); ok { 221 return s0 < s1 222 } 223 } 224 if s0, ok := toString(v0, false); ok { 225 if s1, ok := toString(v1, true); ok { 226 return s0 < s1 227 } 228 return false 229 } 230 return false 231 } 232 233 type lessEqualExprNode struct{ exprBackground } 234 235 func (le *lessEqualExprNode) String() string { 236 return "<=" 237 } 238 239 func newLessEqualExprNode() ExprNode { return &lessEqualExprNode{} } 240 241 func (le *lessEqualExprNode) Run(ctx context.Context, currField string, tagExpr *TagExpr) interface{} { 242 v0 := le.leftOperand.Run(ctx, currField, tagExpr) 243 v1 := le.rightOperand.Run(ctx, currField, tagExpr) 244 if s0, ok := toFloat64(v0, false); ok { 245 if s1, ok := toFloat64(v1, true); ok { 246 return s0 <= s1 247 } 248 } 249 if s0, ok := toString(v0, false); ok { 250 if s1, ok := toString(v1, true); ok { 251 return s0 <= s1 252 } 253 return false 254 } 255 return false 256 } 257 258 type andExprNode struct{ exprBackground } 259 260 func (ae *andExprNode) String() string { 261 return "&&" 262 } 263 264 func newAndExprNode() ExprNode { return &andExprNode{} } 265 266 func (ae *andExprNode) Run(ctx context.Context, currField string, tagExpr *TagExpr) interface{} { 267 for _, e := range [2]ExprNode{ae.leftOperand, ae.rightOperand} { 268 if !FakeBool(e.Run(ctx, currField, tagExpr)) { 269 return false 270 } 271 } 272 return true 273 } 274 275 type orExprNode struct{ exprBackground } 276 277 func (oe *orExprNode) String() string { 278 return "||" 279 } 280 281 func newOrExprNode() ExprNode { return &orExprNode{} } 282 283 func (oe *orExprNode) Run(ctx context.Context, currField string, tagExpr *TagExpr) interface{} { 284 for _, e := range [2]ExprNode{oe.leftOperand, oe.rightOperand} { 285 if FakeBool(e.Run(ctx, currField, tagExpr)) { 286 return true 287 } 288 } 289 return false 290 }