func (m *Macro) RegisterFunc(funcName string, fn interface{}) {
	fullFn := convertBuilderFunc(fn)
	m.registerFunc(funcName, fullFn)
}
RegisterFunc registers a parameter function
to that macro.
Accepts the func name ("range")
and the function body, which should return an EvaluatorFunc
a bool (it will be converted to EvaluatorFunc later on),
i.e RegisterFunc("min", func(minValue int) func(paramValue string) bool){})
package macro
import (
	"fmt"
	"reflect"
	"regexp"
	"strconv"
	"unicode"
	"github.com/kataras/iris/core/router/macro/interpreter/ast"
)
type EvaluatorFunc func(paramValue string) bool
func NewEvaluatorFromRegexp(expr string) (EvaluatorFunc, error) {
	if expr == "" {
		return nil, fmt.Errorf("empty regex expression")
	}
	if i := expr[len(expr)-1]; i != '$' && i != '*' {
		expr += "$"
	}
	r, err := regexp.Compile(expr)
	if err != nil {
		return nil, err
	}
	return r.MatchString, nil
}
func MustNewEvaluatorFromRegexp(expr string) EvaluatorFunc {
	r, err := NewEvaluatorFromRegexp(expr)
	if err != nil {
		panic(err)
	}
	return r
}
var (
	goodParamFuncReturnType  = reflect.TypeOf(func(string) bool { return false })
	goodParamFuncReturnType2 = reflect.TypeOf(EvaluatorFunc(func(string) bool { return false }))
)
func goodParamFunc(typ reflect.Type) bool {
	if typ.Kind() == reflect.Func {
		if typ.NumOut() == 1 {
			typOut := typ.Out(0)
			if typOut == goodParamFuncReturnType || typOut == goodParamFuncReturnType2 {
				return true
			}
		}
	}
	return false
}
func goodParamFuncName(name string) bool {
	if name == "" {
		return false
	}
	for _, r := range name {
		switch {
		case r == '_':
		case !unicode.IsLetter(r):
			return false
		}
	}
	return true
}
func convertBuilderFunc(fn interface{}) ParamEvaluatorBuilder {
	typFn := reflect.TypeOf(fn)
	if !goodParamFunc(typFn) {
		return nil
	}
	numFields := typFn.NumIn()
	return func(args []ast.ParamFuncArg) EvaluatorFunc {
		if len(args) != numFields {
			panic("args should be the same len as numFields")
		}
		var argValues []reflect.Value
		for i := 0; i < numFields; i++ {
			field := typFn.In(i)
			arg := args[i]
			if field.Kind() != reflect.TypeOf(arg).Kind() {
				panic("fields should have the same type")
			}
			argValues = append(argValues, reflect.ValueOf(arg))
		}
		evalFn := reflect.ValueOf(fn).Call(argValues)[0].Interface()
		var evaluator EvaluatorFunc
		if _v, ok := evalFn.(EvaluatorFunc); ok {
			evaluator = _v
		} else if _v, ok = evalFn.(func(string) bool); ok {
			evaluator = _v
		}
		return func(paramValue string) bool {
			return evaluator(paramValue)
		}
	}
}
type (
	Macro struct {
		Evaluator EvaluatorFunc
		funcs     []ParamFunc
	}
	ParamEvaluatorBuilder func([]ast.ParamFuncArg) EvaluatorFunc
	ParamFunc struct {
		Name string
		Func ParamEvaluatorBuilder
	}
)
func newMacro(evaluator EvaluatorFunc) *Macro {
	return &Macro{Evaluator: evaluator}
}