goeval

package module
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 21, 2024 License: BSD-3-Clause Imports: 10 Imported by: 0

README

GoEval

Provides support for evaluating arbitrary C-like artithmetic/string expressions.

How do I use it?

GoEval can evaluate expressions with parameters, arimethetic, logical, and string operations:

  • basic expression: 10 > 0
  • parameterized expression: foo > 0
  • special parameterized expression: $.["foo bar"] > 0$.["response-time"] > 0
  • nested parameterized expression: foo.bar > 0foo.bar[0] > 0foo["bar"] > 0$.["foo bar"].$.["foo baz"] > 0
  • gjson expression: $["response-time"] > 0$["data.items.0"] < 0
  • arithmetic expression: (requests_made * requests_succeeded / 100) >= 90
  • string expression: http_response_body == "service is ok"
  • float64 expression: (mem_used / total_mem) * 100
  • date comparator: date(2022-05-02) > date(2022-05-01 23:59:59)
  • date timestamp comparator: date(1651467728) > date("2022-05-01 23:59:59")
  • strlen("someReallyLongInputString") <= 16

It can easily be extended with custom functions or operators:

custom comparator: max(1,2,3) > 1

What operators and types does this support?

  • Modifiers: + - / * %
  • Comparators: > >= < <= == != =~ !~ in
  • Logical ops: || &&
  • Numeric constants, as 64-bit floating point (12345.678)
  • String constants ("foo", 'bar', baz)
  • Boolean constants: true false
  • Parenthesis to control order of evaluation ( )
  • Arrays (anything separated by , within parenthesis: [1, 2, 'foo', bar], bar is variable)
  • Prefixes: ! - ~
  • Ternary conditional: ? :
  • Null coalescence: ??

Functions

func TestFunc(t *testing.T) {
	val, err := Full(
		WithFunc("max", func(args ...any) (any, error) {
			if len(args) == 0 {
				return 0, nil
			}
			max := func(a, b float64) float64 {
				if a > b {
					return a
				}
				return b
			}
			var val float64
			val, ok := args[0].(float64)
			if !ok {
				return 0, fmt.Errorf("max() expects number arguments")
			}
			for i, arg := range args {
				if i == 0 {
					continue
				}
				arg, ok := arg.(float64)
				if !ok {
					return 0, fmt.Errorf("max() expects number arguments")
				}
				val = max(val, arg)
			}
			return val, nil
		}),
	).EvalFloat(`max(1,2,3,a)`, map[string]any{"a": float64(6)})
	if err != nil {
		t.Fatalf("Eval() error = %v", err)
	}
	t.Log(val == 6)
	// output: true
}

Benchmarks

For a very rough idea of performance, here are the results output from a benchmark run on a Mac (i9-9900K).

goos: darwin
goarch: amd64
pkg: github.com/StrangeYear/goeval
cpu: Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz
BenchmarkEvaluationSingle-16                 	 2371440	       508.2 ns/op
BenchmarkEvaluationNumericLiteral-16         	  979606	      1178 ns/op
BenchmarkEvaluationLiteralModifiers-16       	  604010	      1903 ns/op
BenchmarkEvaluationParameter-16              	 1344694	       885.3 ns/op
BenchmarkEvaluationParameters-16             	  712880	      1594 ns/op
BenchmarkEvaluationParametersModifiers-16    	  478978	      2434 ns/op
BenchmarkComplexExpression-16                	  143646	      8187 ns/op
BenchmarkRegexExpression-16                  	  451497	      2595 ns/op
BenchmarkFunc-16                             	  268068	      4476 ns/op
BenchmarkJSON-16                             	  460448	      2557 ns/op
BenchmarkNested-16                           	  520017	      2287 ns/op
BenchmarkSpecial-16                          	 1323009	       908.7 ns/op
PASS

Documentation

Index

Constants

View Source
const (
	Nil = iota
	Boolean
	Number
	String
	Array
	Time
	Duration
	Json
	Struct
	Map
	Interface
)
View Source
const AND = 57353
View Source
const EQ = 57347
View Source
const GTE = 57349
View Source
const IDENTIFIER = 57357
View Source
const IN = 57356
View Source
const LTE = 57350
View Source
const NC = 57355
View Source
const NEQ = 57348
View Source
const NRE = 57352
View Source
const OR = 57354
View Source
const RE = 57351
View Source
const VALUE = 57346

Variables

This section is empty.

Functions

func EvalBool

func EvalBool(expr string, args ...any) (bool, error)

func EvalFloat

func EvalFloat(expr string, args ...any) (float64, error)

func EvalInt

func EvalInt(expr string, args ...any) (int, error)

func EvalString

func EvalString(expr string, args ...any) (string, error)

func SelectValue

func SelectValue(value any, key string) any

Types

type Evaluable

type Evaluable struct {
	// contains filtered or unexported fields
}

func Full

func Full(opts ...Option) *Evaluable

func NewEvaluable

func NewEvaluable(opts ...Option) *Evaluable

func (*Evaluable) Eval

func (e *Evaluable) Eval(expr string, args ...any) (val Value, tokens []string, err error)

func (*Evaluable) EvalBool

func (e *Evaluable) EvalBool(expr string, args ...any) (bool, error)

func (*Evaluable) EvalFloat

func (e *Evaluable) EvalFloat(expr string, args ...any) (float64, error)

func (*Evaluable) EvalInt

func (e *Evaluable) EvalInt(expr string, args ...any) (int, error)

func (*Evaluable) EvalString

func (e *Evaluable) EvalString(expr string, args ...any) (string, error)

type Func

type Func func(...any) (any, error)

type Operator

type Operator func(any, any) (any, error)

type Option

type Option func(*Evaluable)

func WithFunc

func WithFunc(name string, fn Func) Option

type Value

type Value struct {
	// contains filtered or unexported fields
}

func Eval

func Eval(expr string, args ...any) (Value, []string, error)

func NewValue

func NewValue(name string, v any) Value

func (Value) Add added in v1.0.2

func (v Value) Add(v2 Value) Value

func (Value) And added in v1.0.2

func (v Value) And(v2 Value) Value

func (Value) Array

func (v Value) Array() []any

func (Value) Boolean

func (v Value) Boolean() bool

func (Value) Div added in v1.0.2

func (v Value) Div(v2 Value) Value

func (Value) Eq added in v1.0.2

func (v Value) Eq(v2 Value) Value

func (Value) Float

func (v Value) Float() float64

func (Value) Gt added in v1.0.2

func (v Value) Gt(v2 Value) Value

func (Value) Gte added in v1.0.2

func (v Value) Gte(v2 Value) Value

func (Value) In added in v1.0.2

func (v Value) In(v2 Value) Value

func (Value) Int

func (v Value) Int() int

func (Value) Lt added in v1.0.2

func (v Value) Lt(v2 Value) Value

func (Value) Lte added in v1.0.2

func (v Value) Lte(v2 Value) Value

func (Value) Match added in v1.0.2

func (v Value) Match(v2 Value) Value

func (Value) Mod added in v1.0.2

func (v Value) Mod(v2 Value) Value

func (Value) Multi added in v1.0.2

func (v Value) Multi(v2 Value) Value

func (Value) Nc added in v1.0.2

func (v Value) Nc(v2 Value) Value

func (Value) Neq added in v1.0.2

func (v Value) Neq(v2 Value) Value

func (Value) Not added in v1.0.2

func (v Value) Not() Value

func (Value) Nre added in v1.0.2

func (v Value) Nre(v2 Value) Value

func (Value) Or added in v1.0.2

func (v Value) Or(v2 Value) Value

func (Value) Re added in v1.0.2

func (v Value) Re(v2 Value) Value

func (Value) String

func (v Value) String() string

func (Value) Sub added in v1.0.2

func (v Value) Sub(v2 Value) Value

func (Value) Ternary added in v1.0.2

func (v Value) Ternary(v2 Value, v3 Value) Value

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL