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  }