func checkStructMapAddr(v reflect.Value) error {
	if !v.IsValid() || v.CanAddr() || v.NumField() != 1 || v.Field(0).Kind() != reflect.Map {
		return nil
	}
	return unsupportCannotAddr
}
check type: struct{F map[T1]T2}
package tagexpr
import (
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"sync"
	"unsafe"
	"github.com/henrylee2cn/ameda"
)
type (
	Number  = float64
	Null    = interface{}
	Boolean = bool
	String  = string
)
type VM struct {
	tagName   string
	structJar map[uintptr]*structVM
	rw        sync.RWMutex
}
type structVM struct {
	vm                         *VM
	name                       string
	fields                     map[string]*fieldVM
	fieldSelectorList          []string
	fieldsWithIndirectStructVM []*fieldVM
	exprs                      map[string]*Expr
	exprSelectorList           []string
	ifaceTagExprGetters        []func(unsafe.Pointer, string, func(*TagExpr, error) error) error
}
type fieldVM struct {
	structField            reflect.StructField
	ptrDeep                int
	getPtr                 func(unsafe.Pointer) unsafe.Pointer
	elemType               reflect.Type
	elemKind               reflect.Kind
	valueGetter            func(unsafe.Pointer) interface{}
	reflectValueGetter     func(unsafe.Pointer, bool) reflect.Value
	exprs                  map[string]*Expr
	origin                 *structVM
	mapKeyStructVM         *structVM
	mapOrSliceElemStructVM *structVM
	mapOrSliceIfaceKinds   [2]bool  
	fieldSelector          string
	tagOp                  string
}
func New(tagName ...string) *VM {
	if len(tagName) == 0 {
		tagName = append(tagName, "")
	}
	return &VM{
		tagName:   tagName[0],
		structJar: make(map[uintptr]*structVM, 256),
	}
}
func (vm *VM) MustRun(structOrStructPtrOrReflectValue interface{}) *TagExpr {
	te, err := vm.Run(structOrStructPtrOrReflectValue)
	if err != nil {
		panic(err)
	}
	return te
}
var (
	unsupportNil        = errors.New("unsupport data: nil")
	unsupportCannotAddr = errors.New("unsupport data: can not addr")
)
func (vm *VM) Run(structPtrOrReflectValue interface{}) (*TagExpr, error) {
	var v reflect.Value
	switch t := structPtrOrReflectValue.(type) {
	case reflect.Value:
		v = ameda.DereferenceValue(t)
	default:
		v = ameda.DereferenceValue(reflect.ValueOf(t))
	}
	if err := checkStructMapAddr(v); err != nil {
		return nil, err
	}
	u := ameda.ValueFrom2(&v)
	ptr := unsafe.Pointer(u.Pointer())
	if ptr == nil {
		return nil, unsupportNil
	}
	tid := u.RuntimeTypeID()
	var err error
	vm.rw.RLock()
	s, ok := vm.structJar[tid]
	vm.rw.RUnlock()
	if !ok {
		vm.rw.Lock()
		s, ok = vm.structJar[tid]
		if !ok {
			s, err = vm.registerStructLocked(v.Type())
			if err != nil {
				vm.rw.Unlock()
				return nil, err
			}
		}
		vm.rw.Unlock()
	}
	return s.newTagExpr(ptr, ""), nil
}
func (vm *VM) RunAny(v interface{}, fn func(*TagExpr, error) error) error {
	vv, isReflectValue := v.(reflect.Value)
	if !isReflectValue {
		vv = reflect.ValueOf(v)
	}
	return vm.subRunAll(false, "", vv, fn)
}