func (tr *TypeRegistry) Init() {
	tr.Types = make(map[string]reflect.Type, 1000)
	tr.Insts = make(map[string]interface{}, 1000)
	tr.Props = make(map[string]map[string]interface{}, 1000)
	tr.ShortNames = make(map[string]string, 1000)
	{
		var BoolProps = map[string]interface{}{
			"basic-type": true,
		}
		ob := false
		tr.AddType(&ob, BoolProps)
	}
	{
		var IntProps = map[string]interface{}{
			"basic-type": true,
		}
		ob := int(0)
		tr.AddType(&ob, IntProps)
	}
	{
		ob := int8(0)
		tr.AddType(&ob, nil)
	}
	{
		ob := int16(0)
		tr.AddType(&ob, nil)
	}
	{
		ob := int32(0)
		tr.AddType(&ob, nil)
	}
	{
		ob := int64(0)
		tr.AddType(&ob, nil)
	}
	{
		ob := uint(0)
		tr.AddType(&ob, nil)
	}
	{
		ob := uint8(0)
		tr.AddType(&ob, nil)
	}
	{
		ob := uint16(0)
		tr.AddType(&ob, nil)
	}
	{
		ob := uint32(0)
		tr.AddType(&ob, nil)
	}
	{
		ob := uint64(0)
		tr.AddType(&ob, nil)
	}
	{
		ob := uintptr(0)
		tr.AddType(&ob, nil)
	}
	{
		ob := float32(0)
		tr.AddType(&ob, nil)
	}
	{
		var Float64Props = map[string]interface{}{
			"basic-type": true,
		}
		ob := float64(0)
		tr.AddType(&ob, Float64Props)
	}
	{
		ob := complex64(0)
		tr.AddType(&ob, nil)
	}
	{
		ob := complex128(0)
		tr.AddType(&ob, nil)
	}
	{
		var StringProps = map[string]interface{}{
			"basic-type": true,
		}
		ob := ""
		tr.AddType(&ob, StringProps)
	}
}
Init initializes the type registry, including adding basic types
package kit
import (
	"fmt"
	"log"
	"path"
	"reflect"
	"strings"
	"sync"
)
type TypeRegistry struct {
	Types map[string]reflect.Type
	ShortNames map[string]string
	Props map[string]map[string]interface{}
	Insts map[string]interface{}
}
var Types TypeRegistry
func LongTypeName(typ reflect.Type) string {
	return typ.PkgPath() + "." + typ.Name()
}
func ShortTypeName(typ reflect.Type) string {
	return path.Base(typ.PkgPath()) + "." + typ.Name()
}
var TypesMu sync.RWMutex
func (tr *TypeRegistry) AddType(obj interface{}, props map[string]interface{}) reflect.Type {
	if tr.Types == nil {
		tr.Init()
	}
	typ := reflect.TypeOf(obj).Elem()
	lnm := LongTypeName(typ)
	snm := ShortTypeName(typ)
	tr.ShortNames[lnm] = snm
	tr.Types[snm] = typ
	tr.Insts[lnm] = obj
	if props != nil {
		nwprops := make(map[string]interface{}, len(props))
		for key, val := range props {
			nwprops[key] = val
		}
		tr.Props[lnm] = nwprops
	}
	return typ
}
func (tr *TypeRegistry) InheritTypeProps(typ reflect.Type) bool {
	if typ.Kind() != reflect.Struct || typ.NumField() == 0 {
		return false
	}
	embfld := typ.Field(0)  
	if !embfld.Anonymous {
		return false
	}
	pp := tr.Properties(embfld.Type, false)
	if pp == nil {
		return false
	}
	var myp *map[string]interface{}
	for k, v := range *pp {
		if strings.HasPrefix(k, "EnumType:") {
			if myp == nil {
				myp = tr.Properties(typ, true)
			}
			SetTypeProp(*myp, k, v)
			fmt.Printf("typ: %v inh: %v\n", ShortTypeName(typ), k)
		}
	}
	return myp != nil
}
func (tr *TypeRegistry) TypeName(typ reflect.Type) string {
	lnm := LongTypeName(typ)
	if snm, ok := tr.ShortNames[lnm]; ok {
		return snm
	}
	snm := ShortTypeName(typ)
	TypesMu.Lock()
	tr.ShortNames[lnm] = snm
	TypesMu.Unlock()
	return snm
}
func (tr *TypeRegistry) Type(typeName string) reflect.Type {
	if typ, ok := tr.Types[typeName]; ok {
		return typ
	}
	return nil
}
func (tr *TypeRegistry) InstByName(typeName string) interface{} {
	if inst, ok := tr.Insts[typeName]; ok {
		return inst
	}
	return nil
}
func (tr *TypeRegistry) Inst(typ reflect.Type) interface{} {
	return tr.InstByName(LongTypeName(typ))
}
func (tr *TypeRegistry) PropsByName(typeName string, makeNew bool) *map[string]interface{} {
	TypesMu.Lock()
	defer TypesMu.Unlock()
	tp, ok := tr.Props[typeName]
	if !ok {
		if !makeNew {
			return nil
		}
		tp = make(map[string]interface{})
		tr.Props[typeName] = tp
	}
	return &tp
}
func (tr *TypeRegistry) Properties(typ reflect.Type, makeNew bool) *map[string]interface{} {
	return tr.PropsByName(LongTypeName(typ), makeNew)
}
func TypeProp(props map[string]interface{}, key string) (interface{}, bool) {
	TypesMu.RLock()
	val, ok := props[key]
	TypesMu.RUnlock()
	return val, ok
}
func SetTypeProp(props map[string]interface{}, key string, val interface{}) {
	TypesMu.Lock()
	props[key] = val
	TypesMu.Unlock()
}
func (tr *TypeRegistry) PropByName(typeName, propKey string) (interface{}, bool) {
	TypesMu.RLock()
	defer TypesMu.RUnlock()
	tp, ok := tr.Props[typeName]
	if !ok {
		return nil, false
	}
	p, ok := tp[propKey]
	return p, ok
}
func (tr *TypeRegistry) Prop(typ reflect.Type, propKey string) (interface{}, bool) {
	return tr.PropByName(LongTypeName(typ), propKey)
}
func (tr *TypeRegistry) SetProps(typ reflect.Type, props map[string]interface{}) {
	TypesMu.Lock()
	defer TypesMu.Unlock()
	tr.Props[LongTypeName(typ)] = props
}
func (tr *TypeRegistry) AllImplementersOf(iface reflect.Type, includeBases bool) []reflect.Type {
	if iface.Kind() != reflect.Interface {
		log.Printf("kit.TypeRegistry AllImplementersOf -- type is not an interface: %v\n", iface)
		return nil
	}
	tl := make([]reflect.Type, 0)
	for _, typ := range tr.Types {
		if !includeBases {
			if btp, ok := tr.Prop(typ, "base-type"); ok {
				if bt, ok := ToBool(btp); ok && bt {
					continue
				}
			}
		}
		nptyp := NonPtrType(typ)
		if nptyp.Kind() != reflect.Struct {
			continue
		}
		if EmbedImplements(typ, iface) {
			tl = append(tl, typ)
		}
	}
	return tl
}
func (tr *TypeRegistry) AllEmbedsOf(embed reflect.Type, inclusive, includeBases bool) []reflect.Type {
	tl := make([]reflect.Type, 0)
	for _, typ := range tr.Types {
		if !inclusive && typ == embed {
			continue
		}
		if !includeBases {
			if btp, ok := tr.Prop(typ, "base-type"); ok {
				if bt, ok := ToBool(btp); ok && bt {
					continue
				}
			}
		}
		if TypeEmbeds(typ, embed) {
			tl = append(tl, typ)
		}
	}
	return tl
}
func (tr *TypeRegistry) AllTagged(key string) []reflect.Type {
	tl := make([]reflect.Type, 0)
	for _, typ := range tr.Types {
		_, ok := tr.Prop(typ, key)
		if !ok {
			continue
		}
		tl = append(tl, typ)
	}
	return tl
}