github.com/DataDog/datadog-agent/pkg/security/secl@v0.55.0-devel.0.20240517055856-10c4965fea94/compiler/eval/eval.go (about)

     1  // Unless explicitly stated otherwise all files in this repository are licensed
     2  // under the Apache License Version 2.0.
     3  // This product includes software developed at Datadog (https://www.datadoghq.com/).
     4  // Copyright 2016-present Datadog, Inc.
     5  
     6  //go:generate operators -output eval_operators.go
     7  
     8  // Package eval holds eval related files
     9  package eval
    10  
    11  import (
    12  	"errors"
    13  	"fmt"
    14  	"reflect"
    15  	"regexp"
    16  	"strconv"
    17  	"strings"
    18  
    19  	"github.com/alecthomas/participle/lexer"
    20  
    21  	"github.com/DataDog/datadog-agent/pkg/security/secl/compiler/ast"
    22  )
    23  
    24  // defines factor applied by specific operator
    25  const (
    26  	FunctionWeight       = 5
    27  	InArrayWeight        = 10
    28  	HandlerWeight        = 50
    29  	RegexpWeight         = 100
    30  	InPatternArrayWeight = 1000
    31  	IteratorWeight       = 2000
    32  )
    33  
    34  // BoolEvalFnc describe a eval function return a boolean
    35  type BoolEvalFnc = func(ctx *Context) bool
    36  
    37  func extractField(field string, state *State) (Field, Field, RegisterID, error) {
    38  	if state.regexpCache.arraySubscriptFindRE == nil {
    39  		state.regexpCache.arraySubscriptFindRE = regexp.MustCompile(`\[([^\]]*)\]`)
    40  	}
    41  	if state.regexpCache.arraySubscriptReplaceRE == nil {
    42  		state.regexpCache.arraySubscriptReplaceRE = regexp.MustCompile(`(.+)\[[^\]]+\](.*)`)
    43  	}
    44  
    45  	var regID RegisterID
    46  	ids := state.regexpCache.arraySubscriptFindRE.FindStringSubmatch(field)
    47  
    48  	switch len(ids) {
    49  	case 0:
    50  		return field, "", "", nil
    51  	case 2:
    52  		regID = ids[1]
    53  	default:
    54  		return "", "", "", fmt.Errorf("wrong register format for fields: %s", field)
    55  	}
    56  
    57  	resField := state.regexpCache.arraySubscriptReplaceRE.ReplaceAllString(field, `$1$2`)
    58  	itField := state.regexpCache.arraySubscriptReplaceRE.ReplaceAllString(field, `$1`)
    59  
    60  	return resField, itField, regID, nil
    61  }
    62  
    63  type ident struct {
    64  	Pos   lexer.Position
    65  	Ident *string
    66  }
    67  
    68  func identToEvaluator(obj *ident, opts *Opts, state *State) (interface{}, lexer.Position, error) {
    69  	if accessor, ok := opts.Constants[*obj.Ident]; ok {
    70  		return accessor, obj.Pos, nil
    71  	}
    72  
    73  	if state.macros != nil {
    74  		if macro, ok := state.macros[*obj.Ident]; ok {
    75  			return macro.Value, obj.Pos, nil
    76  		}
    77  	}
    78  
    79  	field, itField, regID, err := extractField(*obj.Ident, state)
    80  	if err != nil {
    81  		return nil, obj.Pos, err
    82  	}
    83  
    84  	// transform extracted field to support legacy SECL fields
    85  	if opts.LegacyFields != nil {
    86  		if newField, ok := opts.LegacyFields[field]; ok {
    87  			field = newField
    88  		}
    89  		if newField, ok := opts.LegacyFields[field]; ok {
    90  			itField = newField
    91  		}
    92  	}
    93  
    94  	// extract iterator
    95  	var iterator Iterator
    96  	if itField != "" {
    97  		if iterator, err = state.model.GetIterator(itField); err != nil {
    98  			return nil, obj.Pos, err
    99  		}
   100  	} else {
   101  		// detect whether a iterator is along the path
   102  		var candidate string
   103  		for _, node := range strings.Split(field, ".") {
   104  			if candidate == "" {
   105  				candidate = node
   106  			} else {
   107  				candidate = candidate + "." + node
   108  			}
   109  
   110  			iterator, err = state.model.GetIterator(candidate)
   111  			if err == nil {
   112  				break
   113  			}
   114  		}
   115  	}
   116  
   117  	if iterator != nil {
   118  		// Force "_" register for now.
   119  		if regID != "" && regID != "_" {
   120  			return nil, obj.Pos, NewRegisterNameNotAllowed(obj.Pos, regID, errors.New("only `_` is supported"))
   121  		}
   122  
   123  		// regID not specified or `_` generate one
   124  		if regID == "" || regID == "_" {
   125  			regID = state.newAnonymousRegID()
   126  		}
   127  
   128  		if info, exists := state.registersInfo[regID]; exists {
   129  			if info.field != itField {
   130  				return nil, obj.Pos, NewRegisterMultipleFields(obj.Pos, regID, errors.New("used by multiple fields"))
   131  			}
   132  
   133  			info.subFields[field] = true
   134  		} else {
   135  			info = &registerInfo{
   136  				field:    itField,
   137  				iterator: iterator,
   138  				subFields: map[Field]bool{
   139  					field: true,
   140  				},
   141  			}
   142  			state.registersInfo[regID] = info
   143  		}
   144  	}
   145  
   146  	accessor, err := state.model.GetEvaluator(field, regID)
   147  	if err != nil {
   148  		return nil, obj.Pos, err
   149  	}
   150  
   151  	state.UpdateFields(field)
   152  
   153  	return accessor, obj.Pos, nil
   154  }
   155  
   156  func arrayToEvaluator(array *ast.Array, opts *Opts, state *State) (interface{}, lexer.Position, error) {
   157  	if len(array.Numbers) != 0 {
   158  		var evaluator IntArrayEvaluator
   159  		evaluator.AppendValues(array.Numbers...)
   160  		return &evaluator, array.Pos, nil
   161  	} else if len(array.StringMembers) != 0 {
   162  		var evaluator StringValuesEvaluator
   163  		evaluator.AppendMembers(array.StringMembers...)
   164  		return &evaluator, array.Pos, nil
   165  	} else if array.Ident != nil {
   166  		if state.macros != nil {
   167  			if macro, ok := state.macros[*array.Ident]; ok {
   168  				return macro.Value, array.Pos, nil
   169  			}
   170  		}
   171  
   172  		// could be an iterator
   173  		return identToEvaluator(&ident{Pos: array.Pos, Ident: array.Ident}, opts, state)
   174  	} else if array.Variable != nil {
   175  		varName, ok := isVariableName(*array.Variable)
   176  		if !ok {
   177  			return nil, array.Pos, NewError(array.Pos, "invalid variable name '%s'", *array.Variable)
   178  		}
   179  		return evaluatorFromVariable(varName, array.Pos, opts)
   180  	} else if array.CIDR != nil {
   181  		var values CIDRValues
   182  		if err := values.AppendCIDR(*array.CIDR); err != nil {
   183  			return nil, array.Pos, NewError(array.Pos, "invalid CIDR '%s'", *array.CIDR)
   184  		}
   185  
   186  		evaluator := &CIDRValuesEvaluator{
   187  			Value:     values,
   188  			ValueType: IPNetValueType,
   189  		}
   190  		return evaluator, array.Pos, nil
   191  	} else if len(array.CIDRMembers) != 0 {
   192  		var values CIDRValues
   193  		for _, member := range array.CIDRMembers {
   194  			if member.CIDR != nil {
   195  				if err := values.AppendCIDR(*member.CIDR); err != nil {
   196  					return nil, array.Pos, NewError(array.Pos, "invalid CIDR '%s'", *member.CIDR)
   197  				}
   198  			} else if member.IP != nil {
   199  				if err := values.AppendIP(*member.IP); err != nil {
   200  					return nil, array.Pos, NewError(array.Pos, "invalid IP '%s'", *member.IP)
   201  				}
   202  			}
   203  		}
   204  
   205  		evaluator := &CIDRValuesEvaluator{
   206  			Value:     values,
   207  			ValueType: IPNetValueType,
   208  		}
   209  		return evaluator, array.Pos, nil
   210  	}
   211  
   212  	return nil, array.Pos, NewError(array.Pos, "unknown array element type")
   213  }
   214  
   215  func isVariableName(str string) (string, bool) {
   216  	if strings.HasPrefix(str, "${") && strings.HasSuffix(str, "}") {
   217  		return str[2 : len(str)-1], true
   218  	}
   219  	return "", false
   220  }
   221  
   222  func evaluatorFromVariable(varname string, pos lexer.Position, opts *Opts) (interface{}, lexer.Position, error) {
   223  	variable := opts.VariableStore.Get(varname)
   224  	if variable == nil {
   225  		return nil, pos, NewError(pos, "variable '%s' doesn't exist", varname)
   226  	}
   227  
   228  	return variable.GetEvaluator(), pos, nil
   229  }
   230  
   231  func stringEvaluatorFromVariable(str string, pos lexer.Position, opts *Opts) (interface{}, lexer.Position, error) {
   232  	var evaluators []*StringEvaluator
   233  
   234  	doLoc := func(sub string) error {
   235  		if varname, ok := isVariableName(sub); ok {
   236  			evaluator, pos, err := evaluatorFromVariable(varname, pos, opts)
   237  			if err != nil {
   238  				return err
   239  			}
   240  
   241  			switch evaluator := evaluator.(type) {
   242  			case *StringArrayEvaluator:
   243  				evaluators = append(evaluators, &StringEvaluator{
   244  					EvalFnc: func(ctx *Context) string {
   245  						return strings.Join(evaluator.EvalFnc(ctx), ",")
   246  					}})
   247  			case *IntArrayEvaluator:
   248  				evaluators = append(evaluators, &StringEvaluator{
   249  					EvalFnc: func(ctx *Context) string {
   250  						var result string
   251  						for i, number := range evaluator.EvalFnc(ctx) {
   252  							if i != 0 {
   253  								result += ","
   254  							}
   255  							result += strconv.FormatInt(int64(number), 10)
   256  						}
   257  						return result
   258  					}})
   259  			case *StringEvaluator:
   260  				evaluators = append(evaluators, evaluator)
   261  			case *IntEvaluator:
   262  				evaluators = append(evaluators, &StringEvaluator{
   263  					EvalFnc: func(ctx *Context) string {
   264  						return strconv.FormatInt(int64(evaluator.EvalFnc(ctx)), 10)
   265  					}})
   266  			default:
   267  				return NewError(pos, "variable type not supported '%s'", varname)
   268  			}
   269  		} else {
   270  			evaluators = append(evaluators, &StringEvaluator{Value: sub})
   271  		}
   272  
   273  		return nil
   274  	}
   275  
   276  	var last int
   277  	for _, loc := range variableRegex.FindAllIndex([]byte(str), -1) {
   278  		if loc[0] > 0 {
   279  			if err := doLoc(str[last:loc[0]]); err != nil {
   280  				return nil, pos, err
   281  			}
   282  		}
   283  		if err := doLoc(str[loc[0]:loc[1]]); err != nil {
   284  			return nil, pos, err
   285  		}
   286  		last = loc[1]
   287  	}
   288  	if last < len(str) {
   289  		if err := doLoc(str[last:]); err != nil {
   290  			return nil, pos, err
   291  		}
   292  	}
   293  
   294  	return &StringEvaluator{
   295  		Value:     str,
   296  		ValueType: VariableValueType,
   297  		EvalFnc: func(ctx *Context) string {
   298  			var result string
   299  			for _, evaluator := range evaluators {
   300  				if evaluator.EvalFnc != nil {
   301  					result += evaluator.EvalFnc(ctx)
   302  				} else {
   303  					result += evaluator.Value
   304  				}
   305  			}
   306  			return result
   307  		},
   308  	}, pos, nil
   309  }
   310  
   311  // StringEqualsWrapper makes use of operator overrides
   312  func StringEqualsWrapper(a *StringEvaluator, b *StringEvaluator, state *State) (*BoolEvaluator, error) {
   313  	var evaluator *BoolEvaluator
   314  	var err error
   315  
   316  	if a.OpOverrides != nil && a.OpOverrides.StringEquals != nil {
   317  		evaluator, err = a.OpOverrides.StringEquals(a, b, state)
   318  	} else if b.OpOverrides != nil && b.OpOverrides.StringEquals != nil {
   319  		evaluator, err = b.OpOverrides.StringEquals(a, b, state)
   320  	} else {
   321  		evaluator, err = StringEquals(a, b, state)
   322  	}
   323  	if err != nil {
   324  		return nil, err
   325  	}
   326  
   327  	return evaluator, nil
   328  }
   329  
   330  // StringArrayContainsWrapper makes use of operator overrides
   331  func StringArrayContainsWrapper(a *StringEvaluator, b *StringArrayEvaluator, state *State) (*BoolEvaluator, error) {
   332  	var evaluator *BoolEvaluator
   333  	var err error
   334  
   335  	if a.OpOverrides != nil && a.OpOverrides.StringArrayContains != nil {
   336  		evaluator, err = a.OpOverrides.StringArrayContains(a, b, state)
   337  	} else if b.OpOverrides != nil && b.OpOverrides.StringArrayContains != nil {
   338  		evaluator, err = b.OpOverrides.StringArrayContains(a, b, state)
   339  	} else {
   340  		evaluator, err = StringArrayContains(a, b, state)
   341  	}
   342  	if err != nil {
   343  		return nil, err
   344  	}
   345  
   346  	return evaluator, nil
   347  }
   348  
   349  // StringValuesContainsWrapper makes use of operator overrides
   350  func StringValuesContainsWrapper(a *StringEvaluator, b *StringValuesEvaluator, state *State) (*BoolEvaluator, error) {
   351  	var evaluator *BoolEvaluator
   352  	var err error
   353  
   354  	if a.OpOverrides != nil && a.OpOverrides.StringValuesContains != nil {
   355  		evaluator, err = a.OpOverrides.StringValuesContains(a, b, state)
   356  	} else {
   357  		evaluator, err = StringValuesContains(a, b, state)
   358  	}
   359  	if err != nil {
   360  		return nil, err
   361  	}
   362  
   363  	return evaluator, nil
   364  }
   365  
   366  // StringArrayMatchesWrapper makes use of operator overrides
   367  func StringArrayMatchesWrapper(a *StringArrayEvaluator, b *StringValuesEvaluator, state *State) (*BoolEvaluator, error) {
   368  	var evaluator *BoolEvaluator
   369  	var err error
   370  
   371  	if a.OpOverrides != nil && a.OpOverrides.StringArrayMatches != nil {
   372  		evaluator, err = a.OpOverrides.StringArrayMatches(a, b, state)
   373  	} else {
   374  		evaluator, err = StringArrayMatches(a, b, state)
   375  	}
   376  	if err != nil {
   377  		return nil, err
   378  	}
   379  
   380  	return evaluator, nil
   381  }
   382  
   383  func nodeToEvaluator(obj interface{}, opts *Opts, state *State) (interface{}, lexer.Position, error) {
   384  	var err error
   385  	var boolEvaluator *BoolEvaluator
   386  	var pos lexer.Position
   387  	var cmp, unary, next interface{}
   388  
   389  	switch obj := obj.(type) {
   390  	case *ast.BooleanExpression:
   391  		return nodeToEvaluator(obj.Expression, opts, state)
   392  	case *ast.Expression:
   393  		cmp, pos, err = nodeToEvaluator(obj.Comparison, opts, state)
   394  		if err != nil {
   395  			return nil, pos, err
   396  		}
   397  
   398  		if obj.Op != nil {
   399  			cmpBool, ok := cmp.(*BoolEvaluator)
   400  			if !ok {
   401  				return nil, obj.Pos, NewTypeError(obj.Pos, reflect.Bool)
   402  			}
   403  
   404  			next, pos, err = nodeToEvaluator(obj.Next, opts, state)
   405  			if err != nil {
   406  				return nil, pos, err
   407  			}
   408  
   409  			nextBool, ok := next.(*BoolEvaluator)
   410  			if !ok {
   411  				return nil, pos, NewTypeError(pos, reflect.Bool)
   412  			}
   413  
   414  			switch *obj.Op {
   415  			case "||", "or":
   416  				boolEvaluator, err = Or(cmpBool, nextBool, state)
   417  				if err != nil {
   418  					return nil, obj.Pos, err
   419  				}
   420  				return boolEvaluator, obj.Pos, nil
   421  			case "&&", "and":
   422  				boolEvaluator, err = And(cmpBool, nextBool, state)
   423  				if err != nil {
   424  					return nil, obj.Pos, err
   425  				}
   426  				return boolEvaluator, obj.Pos, nil
   427  			}
   428  			return nil, pos, NewOpUnknownError(obj.Pos, *obj.Op)
   429  		}
   430  		return cmp, obj.Pos, nil
   431  	case *ast.BitOperation:
   432  		unary, pos, err = nodeToEvaluator(obj.Unary, opts, state)
   433  		if err != nil {
   434  			return nil, pos, err
   435  		}
   436  
   437  		if obj.Op != nil {
   438  			bitInt, ok := unary.(*IntEvaluator)
   439  			if !ok {
   440  				return nil, obj.Pos, NewTypeError(obj.Pos, reflect.Int)
   441  			}
   442  
   443  			next, pos, err = nodeToEvaluator(obj.Next, opts, state)
   444  			if err != nil {
   445  				return nil, pos, err
   446  			}
   447  
   448  			nextInt, ok := next.(*IntEvaluator)
   449  			if !ok {
   450  				return nil, pos, NewTypeError(pos, reflect.Int)
   451  			}
   452  
   453  			switch *obj.Op {
   454  			case "&":
   455  				intEvaluator, err := IntAnd(bitInt, nextInt, state)
   456  				if err != nil {
   457  					return nil, pos, err
   458  				}
   459  				return intEvaluator, obj.Pos, nil
   460  			case "|":
   461  				IntEvaluator, err := IntOr(bitInt, nextInt, state)
   462  				if err != nil {
   463  					return nil, pos, err
   464  				}
   465  				return IntEvaluator, obj.Pos, nil
   466  			case "^":
   467  				IntEvaluator, err := IntXor(bitInt, nextInt, state)
   468  				if err != nil {
   469  					return nil, pos, err
   470  				}
   471  				return IntEvaluator, obj.Pos, nil
   472  			}
   473  			return nil, pos, NewOpUnknownError(obj.Pos, *obj.Op)
   474  		}
   475  		return unary, obj.Pos, nil
   476  
   477  	case *ast.ArithmeticOperation:
   478  		// Process the first operand
   479  		first, pos, err := nodeToEvaluator(obj.First, opts, state)
   480  		if err != nil {
   481  			return nil, pos, err
   482  		}
   483  
   484  		// If it's just one element (is a bitoperation: maybe a string, an int ....)
   485  		if len(obj.Rest) == 0 {
   486  			return first, obj.Pos, nil
   487  		}
   488  
   489  		// Else it's an operation, so it must be an int
   490  		currInt, ok := first.(*IntEvaluator)
   491  		if !ok {
   492  			return nil, obj.Pos, NewTypeError(obj.Pos, reflect.Int)
   493  		}
   494  
   495  		// Process the remaining operations and operands
   496  		for _, arithElem := range obj.Rest {
   497  			// Handle the operand
   498  			operand, pos, err := nodeToEvaluator(arithElem.Operand, opts, state)
   499  			if err != nil {
   500  				return nil, pos, err
   501  			}
   502  			operandInt, ok := operand.(*IntEvaluator)
   503  			if !ok {
   504  				return nil, pos, NewTypeError(pos, reflect.Int)
   505  			}
   506  
   507  			// Perform the operation on the current and next operands
   508  			switch arithElem.Op {
   509  			case "+":
   510  				currInt, err = IntPlus(currInt, operandInt, state)
   511  				if err != nil {
   512  					return nil, pos, err
   513  				}
   514  
   515  			case "-":
   516  				currInt, err = IntMinus(currInt, operandInt, state)
   517  				if err != nil {
   518  					return nil, pos, err
   519  				}
   520  			}
   521  		}
   522  
   523  		// Return the final result after processing all operations and operands
   524  		currInt.isFromArithmeticOperation = true
   525  		return currInt, obj.Pos, nil
   526  
   527  	case *ast.Comparison:
   528  		unary, pos, err = nodeToEvaluator(obj.ArithmeticOperation, opts, state)
   529  		if err != nil {
   530  			return nil, pos, err
   531  		}
   532  
   533  		if obj.ArrayComparison != nil {
   534  			next, pos, err = nodeToEvaluator(obj.ArrayComparison, opts, state)
   535  			if err != nil {
   536  				return nil, pos, err
   537  			}
   538  
   539  			switch unary := unary.(type) {
   540  			case *BoolEvaluator:
   541  				switch nextBool := next.(type) {
   542  				case *BoolArrayEvaluator:
   543  					boolEvaluator, err = ArrayBoolContains(unary, nextBool, state)
   544  					if err != nil {
   545  						return nil, pos, err
   546  					}
   547  					if *obj.ArrayComparison.Op == "notin" {
   548  						return Not(boolEvaluator, state), obj.Pos, nil
   549  					}
   550  					return boolEvaluator, obj.Pos, nil
   551  				default:
   552  					return nil, pos, NewArrayTypeError(pos, reflect.Array, reflect.Bool)
   553  				}
   554  			case *StringEvaluator:
   555  				switch nextString := next.(type) {
   556  				case *StringArrayEvaluator:
   557  					boolEvaluator, err = StringArrayContainsWrapper(unary, nextString, state)
   558  					if err != nil {
   559  						return nil, pos, err
   560  					}
   561  				case *StringValuesEvaluator:
   562  					boolEvaluator, err = StringValuesContainsWrapper(unary, nextString, state)
   563  					if err != nil {
   564  						return nil, pos, err
   565  					}
   566  				default:
   567  					return nil, pos, NewArrayTypeError(pos, reflect.Array, reflect.String)
   568  				}
   569  				if *obj.ArrayComparison.Op == "notin" {
   570  					return Not(boolEvaluator, state), obj.Pos, nil
   571  				}
   572  				return boolEvaluator, obj.Pos, nil
   573  			case *StringValuesEvaluator:
   574  				switch nextStringArray := next.(type) {
   575  				case *StringArrayEvaluator:
   576  					boolEvaluator, err = StringArrayMatchesWrapper(nextStringArray, unary, state)
   577  					if err != nil {
   578  						return nil, pos, err
   579  					}
   580  					if *obj.ArrayComparison.Op == "notin" {
   581  						return Not(boolEvaluator, state), obj.Pos, nil
   582  					}
   583  					return boolEvaluator, obj.Pos, nil
   584  				default:
   585  					return nil, pos, NewArrayTypeError(pos, reflect.Array, reflect.String)
   586  				}
   587  			case *StringArrayEvaluator:
   588  				switch nextStringArray := next.(type) {
   589  				case *StringValuesEvaluator:
   590  					boolEvaluator, err = StringArrayMatchesWrapper(unary, nextStringArray, state)
   591  					if err != nil {
   592  						return nil, pos, err
   593  					}
   594  					if *obj.ArrayComparison.Op == "notin" {
   595  						return Not(boolEvaluator, state), obj.Pos, nil
   596  					}
   597  					return boolEvaluator, obj.Pos, nil
   598  				default:
   599  					return nil, pos, NewArrayTypeError(pos, reflect.Array, reflect.String)
   600  				}
   601  			case *IntEvaluator:
   602  				switch nextInt := next.(type) {
   603  				case *IntArrayEvaluator:
   604  					boolEvaluator, err = IntArrayEquals(unary, nextInt, state)
   605  					if err != nil {
   606  						return nil, pos, err
   607  					}
   608  					if *obj.ArrayComparison.Op == "notin" {
   609  						return Not(boolEvaluator, state), obj.Pos, nil
   610  					}
   611  					return boolEvaluator, obj.Pos, nil
   612  				default:
   613  					return nil, pos, NewArrayTypeError(pos, reflect.Array, reflect.Int)
   614  				}
   615  			case *IntArrayEvaluator:
   616  				switch nextIntArray := next.(type) {
   617  				case *IntArrayEvaluator:
   618  					boolEvaluator, err = IntArrayMatches(unary, nextIntArray, state)
   619  					if err != nil {
   620  						return nil, pos, err
   621  					}
   622  					if *obj.ArrayComparison.Op == "notin" {
   623  						return Not(boolEvaluator, state), obj.Pos, nil
   624  					}
   625  					return boolEvaluator, obj.Pos, nil
   626  				default:
   627  					return nil, pos, NewArrayTypeError(pos, reflect.Array, reflect.Int)
   628  				}
   629  			case *CIDREvaluator:
   630  				switch nextCIDR := next.(type) {
   631  				case *CIDREvaluator:
   632  					nextIP, ok := next.(*CIDREvaluator)
   633  					if !ok {
   634  						return nil, pos, NewTypeError(pos, reflect.TypeOf(CIDREvaluator{}).Kind())
   635  					}
   636  
   637  					boolEvaluator, err = CIDREquals(unary, nextIP, state)
   638  					if err != nil {
   639  						return nil, obj.Pos, err
   640  					}
   641  					switch *obj.ArrayComparison.Op {
   642  					case "in", "allin":
   643  						return boolEvaluator, obj.Pos, nil
   644  					case "notin":
   645  						return Not(boolEvaluator, state), obj.Pos, nil
   646  					}
   647  					return nil, pos, NewOpUnknownError(obj.Pos, *obj.ArrayComparison.Op)
   648  				case *CIDRValuesEvaluator:
   649  					switch *obj.ArrayComparison.Op {
   650  					case "in", "allin":
   651  						boolEvaluator, err = CIDRValuesContains(unary, nextCIDR, state)
   652  						if err != nil {
   653  							return nil, pos, err
   654  						}
   655  						return boolEvaluator, obj.Pos, nil
   656  					case "notin":
   657  						boolEvaluator, err = CIDRValuesContains(unary, nextCIDR, state)
   658  						if err != nil {
   659  							return nil, pos, err
   660  						}
   661  						return Not(boolEvaluator, state), obj.Pos, nil
   662  					}
   663  					return nil, pos, NewOpUnknownError(obj.Pos, *obj.ArrayComparison.Op)
   664  				case *CIDRArrayEvaluator:
   665  					switch *obj.ArrayComparison.Op {
   666  					case "in", "allin":
   667  						boolEvaluator, err = CIDRArrayContains(unary, nextCIDR, state)
   668  						if err != nil {
   669  							return nil, pos, err
   670  						}
   671  						return boolEvaluator, obj.Pos, nil
   672  					case "notin":
   673  						boolEvaluator, err = CIDRArrayContains(unary, nextCIDR, state)
   674  						if err != nil {
   675  							return nil, pos, err
   676  						}
   677  						return Not(boolEvaluator, state), obj.Pos, nil
   678  					}
   679  					return nil, pos, NewOpUnknownError(obj.Pos, *obj.ArrayComparison.Op)
   680  				default:
   681  					return nil, pos, NewCIDRTypeError(pos, reflect.Array, next)
   682  				}
   683  			case *CIDRArrayEvaluator:
   684  				switch nextCIDR := next.(type) {
   685  				case *CIDRValuesEvaluator:
   686  					switch *obj.ArrayComparison.Op {
   687  					case "in":
   688  						boolEvaluator, err = CIDRArrayMatches(unary, nextCIDR, state)
   689  						if err != nil {
   690  							return nil, pos, err
   691  						}
   692  						return boolEvaluator, obj.Pos, nil
   693  					case "allin":
   694  						boolEvaluator, err = CIDRArrayMatchesAll(unary, nextCIDR, state)
   695  						if err != nil {
   696  							return nil, pos, err
   697  						}
   698  						return boolEvaluator, obj.Pos, nil
   699  					case "notin":
   700  						boolEvaluator, err = CIDRArrayMatches(unary, nextCIDR, state)
   701  						if err != nil {
   702  							return nil, pos, err
   703  						}
   704  						return Not(boolEvaluator, state), obj.Pos, nil
   705  					}
   706  					return nil, pos, NewOpUnknownError(obj.Pos, *obj.ArrayComparison.Op)
   707  				default:
   708  					return nil, pos, NewCIDRTypeError(pos, reflect.Array, next)
   709  				}
   710  			case *CIDRValuesEvaluator:
   711  				switch nextCIDR := next.(type) {
   712  				case *CIDREvaluator:
   713  					switch *obj.ArrayComparison.Op {
   714  					case "in", "allin":
   715  						boolEvaluator, err = CIDRValuesContains(nextCIDR, unary, state)
   716  						if err != nil {
   717  							return nil, obj.Pos, err
   718  						}
   719  						return boolEvaluator, obj.Pos, nil
   720  					case "notin":
   721  						boolEvaluator, err = CIDRValuesContains(nextCIDR, unary, state)
   722  						if err != nil {
   723  							return nil, obj.Pos, err
   724  						}
   725  						return Not(boolEvaluator, state), obj.Pos, nil
   726  					}
   727  					return nil, pos, NewOpUnknownError(obj.Pos, *obj.ArrayComparison.Op)
   728  				case *CIDRArrayEvaluator:
   729  					switch *obj.ArrayComparison.Op {
   730  					case "allin":
   731  						boolEvaluator, err = CIDRArrayMatchesAll(nextCIDR, unary, state)
   732  						if err != nil {
   733  							return nil, obj.Pos, err
   734  						}
   735  						return boolEvaluator, obj.Pos, nil
   736  					case "in":
   737  						boolEvaluator, err = CIDRArrayMatches(nextCIDR, unary, state)
   738  						if err != nil {
   739  							return nil, pos, err
   740  						}
   741  						return boolEvaluator, obj.Pos, nil
   742  					case "notin":
   743  						boolEvaluator, err = CIDRArrayMatches(nextCIDR, unary, state)
   744  						if err != nil {
   745  							return nil, pos, err
   746  						}
   747  						return Not(boolEvaluator, state), obj.Pos, nil
   748  					}
   749  					return nil, pos, NewOpUnknownError(obj.Pos, *obj.ArrayComparison.Op)
   750  				default:
   751  					return nil, pos, NewCIDRTypeError(pos, reflect.Array, next)
   752  				}
   753  			default:
   754  				return nil, pos, NewTypeError(pos, reflect.Array)
   755  			}
   756  		} else if obj.ScalarComparison != nil {
   757  			next, pos, err = nodeToEvaluator(obj.ScalarComparison, opts, state)
   758  			if err != nil {
   759  				return nil, pos, err
   760  			}
   761  
   762  			switch unary := unary.(type) {
   763  			case *BoolEvaluator:
   764  				nextBool, ok := next.(*BoolEvaluator)
   765  				if !ok {
   766  					return nil, pos, NewTypeError(pos, reflect.Bool)
   767  				}
   768  
   769  				switch *obj.ScalarComparison.Op {
   770  				case "!=":
   771  					boolEvaluator, err = BoolEquals(unary, nextBool, state)
   772  					if err != nil {
   773  						return nil, pos, err
   774  					}
   775  					return Not(boolEvaluator, state), obj.Pos, nil
   776  				case "==":
   777  					boolEvaluator, err = BoolEquals(unary, nextBool, state)
   778  					if err != nil {
   779  						return nil, pos, err
   780  					}
   781  					return boolEvaluator, obj.Pos, nil
   782  				}
   783  				return nil, pos, NewOpUnknownError(obj.Pos, *obj.ScalarComparison.Op)
   784  			case *BoolArrayEvaluator:
   785  				nextBool, ok := next.(*BoolEvaluator)
   786  				if !ok {
   787  					return nil, pos, NewTypeError(pos, reflect.Bool)
   788  				}
   789  
   790  				switch *obj.ScalarComparison.Op {
   791  				case "!=":
   792  					boolEvaluator, err = BoolArrayEquals(nextBool, unary, state)
   793  					if err != nil {
   794  						return nil, pos, err
   795  					}
   796  					return Not(boolEvaluator, state), obj.Pos, nil
   797  				case "==":
   798  					boolEvaluator, err = BoolArrayEquals(nextBool, unary, state)
   799  					if err != nil {
   800  						return nil, pos, err
   801  					}
   802  					return boolEvaluator, obj.Pos, nil
   803  				}
   804  				return nil, pos, NewOpUnknownError(obj.Pos, *obj.ScalarComparison.Op)
   805  			case *StringEvaluator:
   806  				nextString, ok := next.(*StringEvaluator)
   807  				if !ok {
   808  					return nil, pos, NewTypeError(pos, reflect.String)
   809  				}
   810  
   811  				switch *obj.ScalarComparison.Op {
   812  				case "!=":
   813  					boolEvaluator, err = StringEqualsWrapper(unary, nextString, state)
   814  					if err != nil {
   815  						return nil, obj.Pos, err
   816  					}
   817  					return Not(boolEvaluator, state), obj.Pos, nil
   818  				case "!~":
   819  					if nextString.EvalFnc != nil {
   820  						return nil, obj.Pos, &ErrNonStaticPattern{Field: nextString.Field}
   821  					}
   822  
   823  					// force pattern if needed
   824  					if nextString.ValueType == ScalarValueType {
   825  						nextString.ValueType = PatternValueType
   826  					}
   827  
   828  					boolEvaluator, err = StringEqualsWrapper(unary, nextString, state)
   829  					if err != nil {
   830  						return nil, obj.Pos, err
   831  					}
   832  					return Not(boolEvaluator, state), obj.Pos, nil
   833  				case "==":
   834  					boolEvaluator, err = StringEqualsWrapper(unary, nextString, state)
   835  					if err != nil {
   836  						return nil, obj.Pos, err
   837  					}
   838  					return boolEvaluator, obj.Pos, nil
   839  				case "=~":
   840  					if nextString.EvalFnc != nil {
   841  						return nil, obj.Pos, &ErrNonStaticPattern{Field: nextString.Field}
   842  					}
   843  
   844  					// force pattern if needed
   845  					if nextString.ValueType == ScalarValueType {
   846  						nextString.ValueType = PatternValueType
   847  					}
   848  
   849  					boolEvaluator, err = StringEqualsWrapper(unary, nextString, state)
   850  					if err != nil {
   851  						return nil, obj.Pos, err
   852  					}
   853  					return boolEvaluator, obj.Pos, nil
   854  				}
   855  				return nil, pos, NewOpUnknownError(obj.Pos, *obj.ScalarComparison.Op)
   856  			case *CIDREvaluator:
   857  				switch nextIP := next.(type) {
   858  				case *CIDREvaluator:
   859  					switch *obj.ScalarComparison.Op {
   860  					case "!=":
   861  						boolEvaluator, err = CIDREquals(unary, nextIP, state)
   862  						if err != nil {
   863  							return nil, obj.Pos, err
   864  						}
   865  						return Not(boolEvaluator, state), obj.Pos, nil
   866  					case "==":
   867  						boolEvaluator, err = CIDREquals(unary, nextIP, state)
   868  						if err != nil {
   869  							return nil, obj.Pos, err
   870  						}
   871  						return boolEvaluator, obj.Pos, nil
   872  					}
   873  					return nil, pos, NewOpUnknownError(obj.Pos, *obj.ScalarComparison.Op)
   874  				}
   875  			case *StringArrayEvaluator:
   876  				nextString, ok := next.(*StringEvaluator)
   877  				if !ok {
   878  					return nil, pos, NewTypeError(pos, reflect.String)
   879  				}
   880  
   881  				switch *obj.ScalarComparison.Op {
   882  				case "!=":
   883  					boolEvaluator, err = StringArrayContainsWrapper(nextString, unary, state)
   884  					if err != nil {
   885  						return nil, obj.Pos, err
   886  					}
   887  					return Not(boolEvaluator, state), obj.Pos, nil
   888  				case "==":
   889  					boolEvaluator, err = StringArrayContainsWrapper(nextString, unary, state)
   890  					if err != nil {
   891  						return nil, obj.Pos, err
   892  					}
   893  					return boolEvaluator, obj.Pos, nil
   894  				case "!~":
   895  					if nextString.EvalFnc != nil {
   896  						return nil, obj.Pos, &ErrNonStaticPattern{Field: nextString.Field}
   897  					}
   898  
   899  					// force pattern if needed
   900  					if nextString.ValueType == ScalarValueType {
   901  						nextString.ValueType = PatternValueType
   902  					}
   903  
   904  					boolEvaluator, err = StringArrayContainsWrapper(nextString, unary, state)
   905  					if err != nil {
   906  						return nil, obj.Pos, err
   907  					}
   908  					return Not(boolEvaluator, state), obj.Pos, nil
   909  				case "=~":
   910  					if nextString.EvalFnc != nil {
   911  						return nil, obj.Pos, &ErrNonStaticPattern{Field: nextString.Field}
   912  					}
   913  
   914  					// force pattern if needed
   915  					if nextString.ValueType == ScalarValueType {
   916  						nextString.ValueType = PatternValueType
   917  					}
   918  
   919  					boolEvaluator, err = StringArrayContainsWrapper(nextString, unary, state)
   920  					if err != nil {
   921  						return nil, obj.Pos, err
   922  					}
   923  					return boolEvaluator, obj.Pos, nil
   924  				}
   925  			case *IntEvaluator:
   926  				switch nextInt := next.(type) {
   927  				case *IntEvaluator:
   928  					if nextInt.isDuration {
   929  						if unary.isFromArithmeticOperation {
   930  							switch *obj.ScalarComparison.Op {
   931  							case "<":
   932  								boolEvaluator, err = DurationLesserThanArithmeticOperation(unary, nextInt, state)
   933  								if err != nil {
   934  									return nil, obj.Pos, err
   935  								}
   936  								return boolEvaluator, obj.Pos, nil
   937  							case "<=":
   938  								boolEvaluator, err = DurationLesserOrEqualThanArithmeticOperation(unary, nextInt, state)
   939  								if err != nil {
   940  									return nil, obj.Pos, err
   941  								}
   942  								return boolEvaluator, obj.Pos, nil
   943  							case ">":
   944  								boolEvaluator, err = DurationGreaterThanArithmeticOperation(unary, nextInt, state)
   945  								if err != nil {
   946  									return nil, obj.Pos, err
   947  								}
   948  								return boolEvaluator, obj.Pos, nil
   949  							case ">=":
   950  								boolEvaluator, err = DurationGreaterOrEqualThanArithmeticOperation(unary, nextInt, state)
   951  								if err != nil {
   952  									return nil, obj.Pos, err
   953  								}
   954  								return boolEvaluator, obj.Pos, nil
   955  							case "==":
   956  								boolEvaluator, err = DurationEqualArithmeticOperation(unary, nextInt, state)
   957  								if err != nil {
   958  									return nil, obj.Pos, err
   959  								}
   960  								return boolEvaluator, obj.Pos, nil
   961  							}
   962  
   963  						} else {
   964  							switch *obj.ScalarComparison.Op {
   965  							case "<":
   966  								boolEvaluator, err = DurationLesserThan(unary, nextInt, state)
   967  								if err != nil {
   968  									return nil, obj.Pos, err
   969  								}
   970  								return boolEvaluator, obj.Pos, nil
   971  							case "<=":
   972  								boolEvaluator, err = DurationLesserOrEqualThan(unary, nextInt, state)
   973  								if err != nil {
   974  									return nil, obj.Pos, err
   975  								}
   976  								return boolEvaluator, obj.Pos, nil
   977  							case ">":
   978  								boolEvaluator, err = DurationGreaterThan(unary, nextInt, state)
   979  								if err != nil {
   980  									return nil, obj.Pos, err
   981  								}
   982  								return boolEvaluator, obj.Pos, nil
   983  							case ">=":
   984  								boolEvaluator, err = DurationGreaterOrEqualThan(unary, nextInt, state)
   985  								if err != nil {
   986  									return nil, obj.Pos, err
   987  								}
   988  								return boolEvaluator, obj.Pos, nil
   989  							case "==":
   990  								boolEvaluator, err = DurationEqual(unary, nextInt, state)
   991  								if err != nil {
   992  									return nil, obj.Pos, err
   993  								}
   994  								return boolEvaluator, obj.Pos, nil
   995  							}
   996  						}
   997  					} else {
   998  						switch *obj.ScalarComparison.Op {
   999  						case "<":
  1000  							boolEvaluator, err = LesserThan(unary, nextInt, state)
  1001  							if err != nil {
  1002  								return nil, obj.Pos, err
  1003  							}
  1004  							return boolEvaluator, obj.Pos, nil
  1005  						case "<=":
  1006  							boolEvaluator, err = LesserOrEqualThan(unary, nextInt, state)
  1007  							if err != nil {
  1008  								return nil, obj.Pos, err
  1009  							}
  1010  							return boolEvaluator, obj.Pos, nil
  1011  						case ">":
  1012  							boolEvaluator, err = GreaterThan(unary, nextInt, state)
  1013  							if err != nil {
  1014  								return nil, obj.Pos, err
  1015  							}
  1016  							return boolEvaluator, obj.Pos, nil
  1017  						case ">=":
  1018  							boolEvaluator, err = GreaterOrEqualThan(unary, nextInt, state)
  1019  							if err != nil {
  1020  								return nil, obj.Pos, err
  1021  							}
  1022  							return boolEvaluator, obj.Pos, nil
  1023  						case "!=":
  1024  							boolEvaluator, err = IntEquals(unary, nextInt, state)
  1025  							if err != nil {
  1026  								return nil, obj.Pos, err
  1027  							}
  1028  
  1029  							return Not(boolEvaluator, state), obj.Pos, nil
  1030  						case "==":
  1031  							boolEvaluator, err = IntEquals(unary, nextInt, state)
  1032  							if err != nil {
  1033  								return nil, obj.Pos, err
  1034  							}
  1035  							return boolEvaluator, obj.Pos, nil
  1036  						default:
  1037  							return nil, pos, NewOpUnknownError(obj.Pos, *obj.ScalarComparison.Op)
  1038  						}
  1039  					}
  1040  				case *IntArrayEvaluator:
  1041  					nextIntArray := next.(*IntArrayEvaluator)
  1042  
  1043  					switch *obj.ScalarComparison.Op {
  1044  					case "<":
  1045  						boolEvaluator, err = IntArrayLesserThan(unary, nextIntArray, state)
  1046  						if err != nil {
  1047  							return nil, obj.Pos, err
  1048  						}
  1049  						return boolEvaluator, obj.Pos, nil
  1050  					case "<=":
  1051  						boolEvaluator, err = IntArrayLesserOrEqualThan(unary, nextIntArray, state)
  1052  						if err != nil {
  1053  							return nil, obj.Pos, err
  1054  						}
  1055  						return boolEvaluator, obj.Pos, nil
  1056  					case ">":
  1057  						boolEvaluator, err = IntArrayGreaterThan(unary, nextIntArray, state)
  1058  						if err != nil {
  1059  							return nil, obj.Pos, err
  1060  						}
  1061  						return boolEvaluator, obj.Pos, nil
  1062  					case ">=":
  1063  						boolEvaluator, err = IntArrayGreaterOrEqualThan(unary, nextIntArray, state)
  1064  						if err != nil {
  1065  							return nil, obj.Pos, err
  1066  						}
  1067  						return boolEvaluator, obj.Pos, nil
  1068  					case "!=":
  1069  						boolEvaluator, err = IntArrayEquals(unary, nextIntArray, state)
  1070  						if err != nil {
  1071  							return nil, obj.Pos, err
  1072  						}
  1073  						return Not(boolEvaluator, state), obj.Pos, nil
  1074  					case "==":
  1075  						boolEvaluator, err = IntArrayEquals(unary, nextIntArray, state)
  1076  						if err != nil {
  1077  							return nil, obj.Pos, err
  1078  						}
  1079  						return boolEvaluator, obj.Pos, nil
  1080  					default:
  1081  						return nil, pos, NewOpUnknownError(obj.Pos, *obj.ScalarComparison.Op)
  1082  					}
  1083  				}
  1084  				return nil, pos, NewTypeError(pos, reflect.Int)
  1085  			case *IntArrayEvaluator:
  1086  				nextInt, ok := next.(*IntEvaluator)
  1087  				if !ok {
  1088  					return nil, pos, NewTypeError(pos, reflect.Int)
  1089  				}
  1090  
  1091  				if nextInt.isDuration {
  1092  					switch *obj.ScalarComparison.Op {
  1093  					case "<":
  1094  						boolEvaluator, err = DurationArrayLesserThan(nextInt, unary, state)
  1095  						if err != nil {
  1096  							return nil, obj.Pos, err
  1097  						}
  1098  						return boolEvaluator, obj.Pos, nil
  1099  					case "<=":
  1100  						boolEvaluator, err = DurationArrayLesserOrEqualThan(nextInt, unary, state)
  1101  						if err != nil {
  1102  							return nil, obj.Pos, err
  1103  						}
  1104  						return boolEvaluator, obj.Pos, nil
  1105  					case ">":
  1106  						boolEvaluator, err = DurationArrayGreaterThan(nextInt, unary, state)
  1107  						if err != nil {
  1108  							return nil, obj.Pos, err
  1109  						}
  1110  						return boolEvaluator, obj.Pos, nil
  1111  					case ">=":
  1112  						boolEvaluator, err = DurationArrayGreaterOrEqualThan(nextInt, unary, state)
  1113  						if err != nil {
  1114  							return nil, obj.Pos, err
  1115  						}
  1116  						return boolEvaluator, obj.Pos, nil
  1117  					}
  1118  				} else {
  1119  					switch *obj.ScalarComparison.Op {
  1120  					case "<":
  1121  						boolEvaluator, err = IntArrayGreaterThan(nextInt, unary, state)
  1122  						if err != nil {
  1123  							return nil, obj.Pos, err
  1124  						}
  1125  						return boolEvaluator, obj.Pos, nil
  1126  					case "<=":
  1127  						boolEvaluator, err = IntArrayGreaterOrEqualThan(nextInt, unary, state)
  1128  						if err != nil {
  1129  							return nil, obj.Pos, err
  1130  						}
  1131  						return boolEvaluator, obj.Pos, nil
  1132  					case ">":
  1133  						boolEvaluator, err = IntArrayLesserThan(nextInt, unary, state)
  1134  						if err != nil {
  1135  							return nil, obj.Pos, err
  1136  						}
  1137  						return boolEvaluator, obj.Pos, nil
  1138  					case ">=":
  1139  						boolEvaluator, err = IntArrayLesserOrEqualThan(nextInt, unary, state)
  1140  						if err != nil {
  1141  							return nil, obj.Pos, err
  1142  						}
  1143  						return boolEvaluator, obj.Pos, nil
  1144  					case "!=":
  1145  						boolEvaluator, err = IntArrayEquals(nextInt, unary, state)
  1146  						if err != nil {
  1147  							return nil, obj.Pos, err
  1148  						}
  1149  						return Not(boolEvaluator, state), obj.Pos, nil
  1150  					case "==":
  1151  						boolEvaluator, err = IntArrayEquals(nextInt, unary, state)
  1152  						if err != nil {
  1153  							return nil, obj.Pos, err
  1154  						}
  1155  						return boolEvaluator, obj.Pos, nil
  1156  					}
  1157  					return nil, pos, NewOpUnknownError(obj.Pos, *obj.ScalarComparison.Op)
  1158  				}
  1159  			}
  1160  		} else {
  1161  			return unary, pos, nil
  1162  		}
  1163  
  1164  	case *ast.ArrayComparison:
  1165  		return nodeToEvaluator(obj.Array, opts, state)
  1166  
  1167  	case *ast.ScalarComparison:
  1168  		return nodeToEvaluator(obj.Next, opts, state)
  1169  
  1170  	case *ast.Unary:
  1171  		if obj.Op != nil {
  1172  			unary, pos, err = nodeToEvaluator(obj.Unary, opts, state)
  1173  			if err != nil {
  1174  				return nil, pos, err
  1175  			}
  1176  
  1177  			switch *obj.Op {
  1178  			case "!", "not":
  1179  				unaryBool, ok := unary.(*BoolEvaluator)
  1180  				if !ok {
  1181  					return nil, pos, NewTypeError(pos, reflect.Bool)
  1182  				}
  1183  
  1184  				return Not(unaryBool, state), obj.Pos, nil
  1185  			case "-":
  1186  				unaryInt, ok := unary.(*IntEvaluator)
  1187  				if !ok {
  1188  					return nil, pos, NewTypeError(pos, reflect.Int)
  1189  				}
  1190  
  1191  				return Minus(unaryInt, state), pos, nil
  1192  			case "^":
  1193  				unaryInt, ok := unary.(*IntEvaluator)
  1194  				if !ok {
  1195  					return nil, pos, NewTypeError(pos, reflect.Int)
  1196  				}
  1197  
  1198  				return IntNot(unaryInt, state), pos, nil
  1199  			}
  1200  			return nil, pos, NewOpUnknownError(obj.Pos, *obj.Op)
  1201  		}
  1202  
  1203  		return nodeToEvaluator(obj.Primary, opts, state)
  1204  	case *ast.Primary:
  1205  		switch {
  1206  		case obj.Ident != nil:
  1207  			return identToEvaluator(&ident{Pos: obj.Pos, Ident: obj.Ident}, opts, state)
  1208  		case obj.Number != nil:
  1209  			return &IntEvaluator{
  1210  				Value: *obj.Number,
  1211  			}, obj.Pos, nil
  1212  		case obj.Variable != nil:
  1213  			varname, ok := isVariableName(*obj.Variable)
  1214  			if !ok {
  1215  				return nil, obj.Pos, NewError(obj.Pos, "internal variable error '%s'", varname)
  1216  			}
  1217  
  1218  			return evaluatorFromVariable(varname, obj.Pos, opts)
  1219  		case obj.Duration != nil:
  1220  			return &IntEvaluator{
  1221  				Value:      *obj.Duration,
  1222  				isDuration: true,
  1223  			}, obj.Pos, nil
  1224  		case obj.String != nil:
  1225  			str := *obj.String
  1226  
  1227  			// contains variables
  1228  			if len(variableRegex.FindAllIndex([]byte(str), -1)) > 0 {
  1229  				return stringEvaluatorFromVariable(str, obj.Pos, opts)
  1230  			}
  1231  
  1232  			return &StringEvaluator{
  1233  				Value:     str,
  1234  				ValueType: ScalarValueType,
  1235  			}, obj.Pos, nil
  1236  		case obj.Pattern != nil:
  1237  			evaluator := &StringEvaluator{
  1238  				Value:     *obj.Pattern,
  1239  				ValueType: PatternValueType,
  1240  			}
  1241  			return evaluator, obj.Pos, nil
  1242  		case obj.Regexp != nil:
  1243  			evaluator := &StringEvaluator{
  1244  				Value:     *obj.Regexp,
  1245  				ValueType: RegexpValueType,
  1246  			}
  1247  			return evaluator, obj.Pos, nil
  1248  		case obj.IP != nil:
  1249  			ipnet, err := ParseCIDR(*obj.IP)
  1250  			if err != nil {
  1251  				return nil, obj.Pos, NewError(obj.Pos, "invalid IP '%s'", *obj.IP)
  1252  			}
  1253  
  1254  			evaluator := &CIDREvaluator{
  1255  				Value:     *ipnet,
  1256  				ValueType: IPNetValueType,
  1257  			}
  1258  			return evaluator, obj.Pos, nil
  1259  		case obj.CIDR != nil:
  1260  			ipnet, err := ParseCIDR(*obj.CIDR)
  1261  			if err != nil {
  1262  				return nil, obj.Pos, NewError(obj.Pos, "invalid CIDR '%s'", *obj.CIDR)
  1263  			}
  1264  
  1265  			evaluator := &CIDREvaluator{
  1266  				Value:     *ipnet,
  1267  				ValueType: IPNetValueType,
  1268  			}
  1269  			return evaluator, obj.Pos, nil
  1270  		case obj.SubExpression != nil:
  1271  			return nodeToEvaluator(obj.SubExpression, opts, state)
  1272  		default:
  1273  			return nil, obj.Pos, NewError(obj.Pos, "unknown primary '%s'", reflect.TypeOf(obj))
  1274  		}
  1275  	case *ast.Array:
  1276  		return arrayToEvaluator(obj, opts, state)
  1277  	}
  1278  
  1279  	return nil, lexer.Position{}, NewError(lexer.Position{}, "unknown entity '%s'", reflect.TypeOf(obj))
  1280  }