func (field *Field) AddTag(key, value string) {
	field.Tag.Set(key, value)
}
AddTag adds key-value pair to tag
package build
import (
	"bytes"
	"encoding/gob"
	"errors"
	"sort"
	"strconv"
	"strings"
	"github.com/midlang/mid/src/mid/ast"
	"github.com/midlang/mid/src/mid/lexer"
	"github.com/mkideal/log"
)
var (
	ErrAmbiguousNames = errors.New("ambiguous names")
)
func init() {
	gob.Register(&Field{})
	gob.Register(&Bean{})
	gob.Register(&File{})
	gob.Register(&Package{})
	gob.Register(ExprBase{})
	gob.Register(TypeBase{})
	gob.Register(&BasicLit{})
	gob.Register(&BasicType{})
	gob.Register(&ArrayType{})
	gob.Register(&MapType{})
	gob.Register(&VectorType{})
	gob.Register(&GenDecl{})
	gob.Register(&ImportSpec{})
	gob.Register(&ConstSpec{})
	gob.Register(&StructType{})
	gob.Register(&FuncType{})
}
func BuildDoc(doc *ast.CommentGroup) string {
	if doc == nil {
		return ""
	}
	text := doc.Text()
	if text != "" {
		text += "\n"
	}
	return text
}
func BuildComment(comment *ast.CommentGroup) string {
	if comment == nil {
		return ""
	}
	text := comment.Text()
	return text
}
func BuildTag(tag *ast.BasicLit) Tag {
	if tag == nil {
		return ""
	}
	s := tag.Value
	const q = "`"
	if strings.HasPrefix(s, q) {
		s = strings.TrimPrefix(s, q)
	}
	if strings.HasSuffix(s, q) {
		s = strings.TrimSuffix(s, q)
	}
	return Tag(s)
}
func BuildIdent(ident *ast.Ident) string {
	if ident == nil {
		return ""
	}
	return ident.Name
}
func BuildIdentList(idents []*ast.Ident) []string {
	if len(idents) == 0 {
		return []string{}
	}
	strs := make([]string, 0, len(idents))
	for _, ident := range idents {
		strs = append(strs, BuildIdent(ident))
	}
	return strs
}
type Tag string
func (tag Tag) Clone() *Tag {
	x := Tag(string(tag))
	return &x
}
func (tag Tag) String() string { return string(tag) }
func (tag Tag) HasKey(key string) bool {
	_, ok := tag.Lookup(key)
	return ok
}
func (tag Tag) Get(key string) string {
	value, _ := tag.Lookup(key)
	return value
}
func (tag *Tag) Set(key, value string) string {
	pairs, _, index := tag.parse(key)
	if index >= 0 {
		pairs[index][1] = value
	} else {
		pairs = append(pairs, tagpair{key, value})
	}
	*tag = Tag(tag.format(pairs))
	return ""
}
func (tag *Tag) Del(key string) string {
	pairs, _, index := tag.parse(key)
	if index >= 0 {
		pairs = append(pairs[:index], pairs[index+1:]...)
	}
	*tag = Tag(tag.format(pairs))
	return ""
}
func (tag Tag) Lookup(key string) (value string, ok bool) {
	_, value, index := tag.parse(key)
	return value, index >= 0
}
type tagpair [2]string
func (tag Tag) format(pairs []tagpair) string {
	var buf bytes.Buffer
	for i, pair := range pairs {
		if i > 0 {
			buf.WriteByte(' ')
		}
		buf.WriteString(pair[0])
		buf.WriteByte(':')
		buf.WriteByte('"')
		buf.WriteString(pair[1])
		buf.WriteByte('"')
	}
	return buf.String()
}
func (tag Tag) parse(key string) (pairs []tagpair, value string, index int) {
	pairs = make([]tagpair, 0)
	index = -1
	count := 0
	for tag != "" {
		i := 0
		for i < len(tag) && tag[i] == ' ' {
			i++
		}
		tag = tag[i:]
		if tag == "" {
			break
		}
		i = 0
		for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
			i++
		}
		if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
			break
		}
		name := string(tag[:i])
		tag = tag[i+1:]
		i = 1
		for i < len(tag) && tag[i] != '"' {
			if tag[i] == '\\' {
				i++
			}
			i++
		}
		if i >= len(tag) {
			break
		}
		qvalue := string(tag[:i+1])
		tag = tag[i+1:]
		v, err := strconv.Unquote(qvalue)
		if err != nil {
			continue
		}
		if key == name && key != "" && index == -1 {
			value = v
			index = len(pairs)
		}
		pairs = append(pairs, tagpair{name, v})
		count++
	}
	return
}
type Field struct {
	Doc     string
	Options []string
	Type    Type
	Names   []string
	Default Expr
	Tag     Tag
	Comment string
}
func (field Field) Name() (string, error) {
	if len(field.Names) == 0 {
		return "", nil
	}
	if len(field.Names) == 1 {
		return field.Names[0], nil
	}
	return "", ErrAmbiguousNames
}
func (field Field) Value() string {
	switch e := field.Default.(type) {
	case *BasicLit:
		return e.Value
	}
	panic("unsupported expr")
}
func (field Field) GetTag(key string) string {
	return field.Tag.Get(key)
}
func (field Field) HasTag(key string) bool {
	_, ok := field.Tag.Lookup(key)
	return ok
}