-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathevaluator.go
87 lines (75 loc) · 2.41 KB
/
evaluator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// Package evaluator evaluates an expression in the form of s-expression
package evaluator
import "errors"
var (
// ErrNotFound means the unknow string within the expression cannot be Get from neither functions or params
ErrNotFound = errors.New("neither function not variable found")
// ErrInvalidResult means the invalid result type expected with the real output
ErrInvalidResult = errors.New("invalid result type")
)
// Expression stands for an expression which can be evaluated by passing required params
type Expression struct {
exp sexp
}
// New will return a Expression by parsing the given expression string
func New(expr string) (Expression, error) {
exp, err := parse(expr)
if err != nil {
return Expression{}, err
}
return Expression{
exp: exp,
}, nil
}
// Eval evaluates the Expression with params and return the real value in the type of interface
func (e Expression) Eval(params Params) (interface{}, error) {
return e.exp.evaluate(params)
}
// EvalBool invokes method Eval and does boolean type assertion, return ErrInvalidResult if the type of result is not boolean
func (e Expression) EvalBool(params Params) (bool, error) {
r, err := e.exp.evaluate(params)
if err != nil {
return false, err
}
b, ok := r.(bool)
if !ok {
return false, ErrInvalidResult
}
return b, nil
}
// Properties returns the field names in an Expression.
// e.g. Expression constructed by `(or (and (between age 18 80) (eq gender "male") )`
// returns "age", "gender" by calling Properties.
func (e Expression) Properties() []string {
return e.exp.properties()
}
// MapParams is a simple map implementation of Params interface
type MapParams map[string]interface{}
// Get is the only method required by Params interface
func (p MapParams) Get(name string) (interface{}, error) {
v, ok := p[name]
if !ok {
return nil, ErrNotFound
}
return v, nil
}
// Params defines a Get method which gets required param for the expression
type Params interface {
Get(name string) (interface{}, error)
}
// Eval is a handy encapsulation to parse the expression and evaluate it
func Eval(expr string, params Params) (interface{}, error) {
e, err := New(expr)
if err != nil {
return nil, err
}
return e.Eval(params)
}
// EvalBool is same as Eval but return a boolean result instead of interface type
func EvalBool(expr string, params Params) (bool, error) {
e, err := New(expr)
if err != nil {
return false, err
}
return e.EvalBool(params)
}