github.com/expr-lang/expr@v1.16.9/optimizer/in_array.go (about) 1 package optimizer 2 3 import ( 4 "reflect" 5 6 . "github.com/expr-lang/expr/ast" 7 ) 8 9 type inArray struct{} 10 11 func (*inArray) Visit(node *Node) { 12 switch n := (*node).(type) { 13 case *BinaryNode: 14 if n.Operator == "in" { 15 if array, ok := n.Right.(*ArrayNode); ok { 16 if len(array.Nodes) > 0 { 17 t := n.Left.Type() 18 if t == nil || t.Kind() != reflect.Int { 19 // This optimization can be only performed if left side is int type, 20 // as runtime.in func uses reflect.Map.MapIndex and keys of map must, 21 // be same as checked value type. 22 goto string 23 } 24 25 for _, a := range array.Nodes { 26 if _, ok := a.(*IntegerNode); !ok { 27 goto string 28 } 29 } 30 { 31 value := make(map[int]struct{}) 32 for _, a := range array.Nodes { 33 value[a.(*IntegerNode).Value] = struct{}{} 34 } 35 Patch(node, &BinaryNode{ 36 Operator: n.Operator, 37 Left: n.Left, 38 Right: &ConstantNode{Value: value}, 39 }) 40 } 41 42 string: 43 for _, a := range array.Nodes { 44 if _, ok := a.(*StringNode); !ok { 45 return 46 } 47 } 48 { 49 value := make(map[string]struct{}) 50 for _, a := range array.Nodes { 51 value[a.(*StringNode).Value] = struct{}{} 52 } 53 Patch(node, &BinaryNode{ 54 Operator: n.Operator, 55 Left: n.Left, 56 Right: &ConstantNode{Value: value}, 57 }) 58 } 59 60 } 61 } 62 } 63 } 64 }