mirror of
https://github.com/hanzoai/expr.git
synced 2026-09-24 16:58:58 +00:00
79 lines
1.8 KiB
Go
79 lines
1.8 KiB
Go
package conf
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
|
|
"github.com/antonmedv/expr/ast"
|
|
"github.com/antonmedv/expr/vm/runtime"
|
|
)
|
|
|
|
type Config struct {
|
|
Env interface{}
|
|
Types TypesTable
|
|
MapEnv bool
|
|
DefaultType reflect.Type
|
|
Operators OperatorsTable
|
|
Expect reflect.Kind
|
|
Optimize bool
|
|
Strict bool
|
|
ConstFns map[string]reflect.Value
|
|
Visitors []ast.Visitor
|
|
}
|
|
|
|
func New(env interface{}) *Config {
|
|
c := &Config{
|
|
Operators: make(map[string][]string),
|
|
ConstFns: make(map[string]reflect.Value),
|
|
Optimize: true,
|
|
}
|
|
c.WithEnv(env)
|
|
return c
|
|
}
|
|
|
|
func (c *Config) WithEnv(env interface{}) {
|
|
var mapEnv bool
|
|
var mapValueType reflect.Type
|
|
if _, ok := env.(map[string]interface{}); ok {
|
|
mapEnv = true
|
|
} else {
|
|
if reflect.ValueOf(env).Kind() == reflect.Map {
|
|
mapValueType = reflect.TypeOf(env).Elem()
|
|
}
|
|
}
|
|
|
|
c.Env = env
|
|
c.Types = CreateTypesTable(env)
|
|
c.MapEnv = mapEnv
|
|
c.DefaultType = mapValueType
|
|
c.Strict = true
|
|
}
|
|
|
|
func (c *Config) Operator(operator string, fns ...string) {
|
|
c.Operators[operator] = append(c.Operators[operator], fns...)
|
|
for _, fn := range fns {
|
|
fnType, ok := c.Types[fn]
|
|
if !ok || fnType.Type.Kind() != reflect.Func {
|
|
panic(fmt.Errorf("function %s for %s operator does not exist in the environment", fn, operator))
|
|
}
|
|
requiredNumIn := 2
|
|
if fnType.Method {
|
|
requiredNumIn = 3 // As first argument of method is receiver.
|
|
}
|
|
if fnType.Type.NumIn() != requiredNumIn || fnType.Type.NumOut() != 1 {
|
|
panic(fmt.Errorf("function %s for %s operator does not have a correct signature", fn, operator))
|
|
}
|
|
}
|
|
}
|
|
|
|
func (c *Config) ConstExpr(name string) {
|
|
if c.Env == nil {
|
|
panic("no environment is specified for ConstExpr()")
|
|
}
|
|
fn := reflect.ValueOf(runtime.Fetch(c.Env, name))
|
|
if fn.Kind() != reflect.Func {
|
|
panic(fmt.Errorf("const expression %q must be a function", name))
|
|
}
|
|
c.ConstFns[name] = fn
|
|
}
|