Documentation
¶
Index ¶
- func AsBool() conf.Option
- func AsFloat64() conf.Option
- func AsInt64() conf.Option
- func Compile(input string, ops ...conf.Option) (*vm.Program, error)
- func Env(i interface{}) conf.Option
- func Eval(input string, env interface{}) (interface{}, error)
- func Operator(operator string, fn ...string) conf.Option
- func Optimize(b bool) conf.Option
- func Parse(input string, ops ...conf.Option) (*vm.Program, error)deprecated
- func Run(program *vm.Program, env interface{}) (interface{}, error)
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AsBool ¶ added in v1.2.0
AsBool tells the compiler to expect boolean result.
Example ¶
package main
import (
"fmt"
"github.com/antonmedv/expr"
)
func main() {
env := map[string]int{
"foo": 0,
}
program, err := expr.Compile("foo >= 0", expr.Env(env), expr.AsBool())
if err != nil {
fmt.Printf("%v", err)
return
}
output, err := expr.Run(program, env)
if err != nil {
fmt.Printf("%v", err)
return
}
fmt.Printf("%v", output.(bool))
}
Output: true
func AsFloat64 ¶ added in v1.2.0
AsFloat64 tells the compiler to expect float64 result.
Example ¶
package main
import (
"fmt"
"github.com/antonmedv/expr"
)
func main() {
program, err := expr.Compile("42", expr.AsFloat64())
if err != nil {
fmt.Printf("%v", err)
return
}
output, err := expr.Run(program, nil)
if err != nil {
fmt.Printf("%v", err)
return
}
fmt.Printf("%v", output.(float64))
}
Output: 42
func AsInt64 ¶ added in v1.2.0
AsInt64 tells the compiler to expect int64 result.
Example ¶
package main
import (
"fmt"
"github.com/antonmedv/expr"
)
func main() {
env := map[string]float64{
"foo": 3,
}
program, err := expr.Compile("foo + 2", expr.Env(env), expr.AsInt64())
if err != nil {
fmt.Printf("%v", err)
return
}
output, err := expr.Run(program, env)
if err != nil {
fmt.Printf("%v", err)
return
}
fmt.Printf("%v", output.(int64))
}
Output: 5
func Compile ¶ added in v1.2.0
Compile parses and compiles given input expression to bytecode program.
Example ¶
package main
import (
"fmt"
"github.com/antonmedv/expr"
)
func main() {
env := map[string]interface{}{
"foo": 1,
"bar": 99,
}
program, err := expr.Compile("foo in 1..99 and bar in 1..99", expr.Env(env))
if err != nil {
fmt.Printf("%v", err)
return
}
output, err := expr.Run(program, env)
if err != nil {
fmt.Printf("%v", err)
return
}
fmt.Printf("%v", output)
}
Output: true
func Env ¶ added in v1.0.7
Env specifies expected input of env for type checks. If struct is passed, all fields will be treated as variables, as well as all fields of embedded structs and struct itself. If map is passed, all items will be treated as variables. Methods defined on this type will be available as functions.
Example ¶
package main
import (
"fmt"
"github.com/antonmedv/expr"
)
func main() {
type Segment struct {
Origin string
}
type Passengers struct {
Adults int
}
type Request struct {
Segments []*Segment
Passengers *Passengers
Marker string
Meta map[string]interface{}
}
code := `Segments[0].Origin == "MOW" && Passengers.Adults == 2 && Marker == "test" && Meta["accept"]`
program, err := expr.Compile(code, expr.Env(&Request{}))
if err != nil {
fmt.Printf("%v", err)
return
}
request := &Request{
Segments: []*Segment{
{Origin: "MOW"},
},
Passengers: &Passengers{
Adults: 2,
},
Marker: "test",
Meta: map[string]interface{}{"accept": true},
}
output, err := expr.Run(program, request)
if err != nil {
fmt.Printf("%v", err)
return
}
fmt.Printf("%v", output)
}
Output: true
Example (With_undefined_variables) ¶
package main
import (
"fmt"
"github.com/antonmedv/expr"
)
func main() {
env := map[string]interface{}{
"foo": 0,
"bar": 0,
}
program, err := expr.Compile(`foo + (bar != nil ? bar : 2)`, expr.Env(env))
if err != nil {
fmt.Printf("%v", err)
return
}
request := map[string]interface{}{
"foo": 3,
}
output, err := expr.Run(program, request)
if err != nil {
fmt.Printf("%v", err)
return
}
fmt.Printf("%v", output)
}
Output: 5
func Eval ¶
Eval parses, compiles and runs given input.
Example ¶
package main
import (
"fmt"
"github.com/antonmedv/expr"
)
func main() {
output, err := expr.Eval("'hello world'", nil)
if err != nil {
fmt.Printf("err: %v", err)
return
}
fmt.Printf("%v", output)
}
Output: hello world
Example (Error) ¶
package main
import (
"fmt"
"github.com/antonmedv/expr"
)
func main() {
output, err := expr.Eval("(boo + bar]", nil)
if err != nil {
fmt.Printf("%v", err)
return
}
fmt.Printf("%v", output)
}
Output: syntax error: mismatched input ']' expecting ')' (1:11) | (boo + bar] | ..........^
Example (Map) ¶
package main
import (
"fmt"
"strings"
"github.com/antonmedv/expr"
)
func main() {
env := map[string]interface{}{
"foo": 1,
"bar": []string{"zero", "hello world"},
"swipe": func(in string) string {
return strings.Replace(in, "world", "user", 1)
},
}
output, err := expr.Eval("swipe(bar[foo])", env)
if err != nil {
fmt.Printf("%v", err)
return
}
fmt.Printf("%v", output)
}
Output: hello user
Example (Map_method) ¶
package main
import (
"fmt"
"strings"
"github.com/antonmedv/expr"
)
func main() {
env := mockMapEnv{
"foo": 1,
"bar": []string{"zero", "hello world"},
}
program, err := expr.Compile("Swipe(bar[foo])", expr.Env(env))
if err != nil {
fmt.Printf("%v", err)
return
}
output, err := expr.Run(program, env)
if err != nil {
fmt.Printf("%v", err)
return
}
fmt.Printf("%v", output)
}
type mockMapEnv map[string]interface{}
func (mockMapEnv) Swipe(in string) string {
return strings.Replace(in, "world", "user", 1)
}
Output: hello user
Example (Marshal) ¶
package main
import (
"encoding/json"
"fmt"
"github.com/antonmedv/expr"
"github.com/antonmedv/expr/vm"
)
func main() {
env := map[string]int{
"foo": 1,
"bar": 2,
}
program, err := expr.Compile("(foo + bar) in [1, 2, 3]", expr.Env(env))
if err != nil {
fmt.Printf("%v", err)
return
}
b, err := json.Marshal(program)
if err != nil {
fmt.Printf("%v", err)
return
}
unmarshaledProgram := &vm.Program{}
err = json.Unmarshal(b, unmarshaledProgram)
if err != nil {
fmt.Printf("%v", err)
return
}
output, err := expr.Run(unmarshaledProgram, env)
if err != nil {
fmt.Printf("%v", err)
return
}
fmt.Printf("%v", output)
}
Output: true
Example (Matches) ¶
package main
import (
"fmt"
"github.com/antonmedv/expr"
)
func main() {
output, err := expr.Eval(`"a" matches "a("`, nil)
if err != nil {
fmt.Printf("%v", err)
return
}
fmt.Printf("%v", output)
}
Output: error parsing regexp: missing closing ): `a(` (1:13) | "a" matches "a(" | ............^
Example (Struct) ¶
package main
import (
"fmt"
"github.com/antonmedv/expr"
)
func main() {
type C struct{ C int }
type B struct{ B *C }
type A struct{ A B }
env := A{B{&C{42}}}
output, err := expr.Eval("A.B.C", env)
if err != nil {
fmt.Printf("%v", err)
return
}
fmt.Printf("%v", output)
}
Output: 42
func Operator ¶ added in v1.2.0
Operator allows to override binary operator with function.
Example ¶
package main
import (
"fmt"
"github.com/antonmedv/expr"
)
func main() {
type Place struct {
Code string
}
type Segment struct {
Origin Place
}
type Helpers struct {
PlaceEq func(p Place, s string) bool
}
type Request struct {
Segments []*Segment
Helpers
}
code := `Segments[0].Origin == "MOW" && PlaceEq(Segments[0].Origin, "MOW")`
program, err := expr.Compile(code, expr.Env(&Request{}), expr.Operator("==", "PlaceEq"))
if err != nil {
fmt.Printf("%v", err)
return
}
request := &Request{
Segments: []*Segment{
{Origin: Place{Code: "MOW"}},
},
Helpers: Helpers{PlaceEq: func(p Place, s string) bool {
return p.Code == s
}},
}
output, err := expr.Run(program, request)
if err != nil {
fmt.Printf("%v", err)
return
}
fmt.Printf("%v", output)
}
Output: true
Example (Time) ¶
package main
import (
"fmt"
"time"
"github.com/antonmedv/expr"
)
func main() {
type Segment struct {
Date time.Time
}
type Request struct {
Segments []Segment
Before func(a, b time.Time) bool
Date func(s string) time.Time
}
code := `Date("2001-01-01") < Segments[0].Date`
program, err := expr.Compile(code, expr.Env(&Request{}), expr.Operator("<", "Before"))
if err != nil {
fmt.Printf("%v", err)
return
}
request := &Request{
Segments: []Segment{
{Date: time.Date(2019, 7, 1, 0, 0, 0, 0, time.UTC)},
},
Before: func(a, b time.Time) bool {
return a.Before(b)
},
Date: func(s string) time.Time {
date, err := time.Parse("2006-01-02", s)
if err != nil {
panic(err)
}
return date
},
}
output, err := expr.Run(program, request)
if err != nil {
fmt.Printf("%v", err)
return
}
fmt.Printf("%v", output)
}
Output: true
Types ¶
This section is empty.