func mapSubtype(t Type, callback func(t Type) bool) {
	if goOn := callback(t); goOn {
		t.MapSubtypes(callback)
	}
}
Helper function used by all MapSubtypes implementations.
The difference between this function and using t.MapSubtypes(c) directly is that
this function calls c with t itself too.
package have
import (
	"bytes"
	"fmt"
	gotoken "go/token"
)
const Blank = "_"
type Expr interface {
	Pos() gotoken.Pos
}
type expr struct {
	pos gotoken.Pos
}
type Stmt interface {
	Expr
	Label() *Object
}
type stmt struct {
	expr
	label *Object
}
type declStmt interface {
	Decls() []string
}
type ObjectExpr interface {
	Expr
	ReferedObject() Object
}
type SimpleStmt interface {
	Stmt
}
type TopLevelStmt struct {
	Stmt
	deps []string
	unboundTypes  map[string][]DeclaredType
	unboundIdents map[string][]*Ident
}
func (s *TopLevelStmt) Deps() []string {
	return s.deps
}
func (s *TopLevelStmt) loadDeps() {
	uniqMap := make(map[string]bool)
	for name := range s.unboundTypes {
		uniqMap[name] = true
	}
	for name := range s.unboundIdents {
		uniqMap[name] = true
	}
	s.deps = make([]string, 0, len(uniqMap))
	for name := range uniqMap {
		s.deps = append(s.deps, name)
	}
}
func (s *TopLevelStmt) Decls() []string {
	var result []string
	switch stmt := s.Stmt.(type) {
	case *VarStmt:
		stmt.Vars.eachPair(func(v *Variable, init Expr) {
			result = append(result, v.name)
		})
	case *StructStmt:
		result = append(result, stmt.Decl.Name())
	case *TypeDecl:
		result = append(result, stmt.Name())
	case *IfaceStmt:
		result = append(result, stmt.Iface.name)
	case *GenericFunc:
		result = append(result, stmt.Name())
	case *GenericStruct:
		result = append(result, stmt.Name())
	case *ImportStmt, *AssignStmt, *SendStmt, *SwitchStmt, *ExprStmt, *IfStmt, *ForStmt, *ForRangeStmt, *BranchStmt, *LabelStmt:
	case declStmt:
		result = stmt.Decls()
	default:
		panic(fmt.Errorf("todo %#v", s.Stmt))
	}
	return result
}
type ObjectType int
const (
	OBJECT_VAR = ObjectType(iota + 1)
	OBJECT_TYPE
	OBJECT_PACKAGE
	OBJECT_LABEL
	OBJECT_GENERIC
	OBJECT_GENERIC_TYPE
)
type Object interface {
	Name() string
	ObjectType() ObjectType
}
type Variable struct {
	name string
	Type Type
	init Expr
}
func (o *Variable) Name() string           { return o.name }
func (o *Variable) ObjectType() ObjectType { return OBJECT_VAR }
type LabelStmt struct {
	stmt
	name       string
	Branchable Stmt  
}
func (l *LabelStmt) Name() string           { return l.name }
func (l *LabelStmt) ObjectType() ObjectType { return OBJECT_LABEL }
type ImportStmt struct {
	stmt
	name, path string
	pkg        *Package
}
func (i *ImportStmt) Name() string           { return i.name }
func (i *ImportStmt) ObjectType() ObjectType { return OBJECT_PACKAGE }
type WhenStmt struct {
	stmt
	Args     []Type
	Branches []*WhenBranch
}
type WhenBranch struct {
	stmt
	Predicates []*WhenPredicate
	Code       *CodeBlock
	True       bool
}
type WhenPredicateKind int
const (
	WHEN_KIND_IS = WhenPredicateKind(iota + 1)
	WHEN_KIND_IMPLEMENTS
	WHEN_KIND_DEFAULT
)
type WhenPredicate struct {
	Kind   WhenPredicateKind
	Target Type
}
func TokenToWhenPred(t *Token) WhenPredicateKind {
	switch t.Type {
	case TOKEN_IS:
		return WHEN_KIND_IS
	case TOKEN_IMPLEMENTS:
		return WHEN_KIND_IMPLEMENTS
	case TOKEN_DEFAULT:
		return WHEN_KIND_DEFAULT
	default:
		panic("Wrong token")
	}
}
type TypeDecl struct {
	stmt
	name        string
	AliasedType Type
	Methods     map[string]*FuncDecl
}
func (o *TypeDecl) Name() string           { return o.name }
func (o *TypeDecl) ObjectType() ObjectType { return OBJECT_TYPE }
func (o *TypeDecl) Type() Type {
	if o.AliasedType == nil {
		return &SimpleType{simpleTypeStrToID[o.name]}
	}
	return &CustomType{Name: o.name, Decl: o}
}
type GenericParamTypeDecl struct {
	stmt
	name string
}
func (g *GenericParamTypeDecl) Name() string           { return g.name }
func (g *GenericParamTypeDecl) ObjectType() ObjectType { return OBJECT_GENERIC_TYPE }
var builtinTypeNames []string = []string{"bool", "byte", "complex128", "complex64", "error", "float32",
	"float64", "int", "int16", "int32", "int64", "int8", "rune",
	"string", "uint", "uint16", "uint32", "uint64", "uint8", "uintptr"}
var builtinTypes map[string]*TypeDecl = map[string]*TypeDecl{}
func initVarDecls() {
	for _, name := range builtinTypeNames {
		builtinTypes[name] = &TypeDecl{
			name:        name,
			AliasedType: nil,  
		}
	}
}
func GetBuiltinType(name string) (*TypeDecl, bool) {
	t, ok := builtinTypes[name]
	return t, ok
}
type CodeBlock struct {
	Statements []Stmt
	Labels     map[string]*LabelStmt
}
func (cb *CodeBlock) AddLabel(l *LabelStmt) error {
	if _, ok := cb.Labels[l.Name()]; ok {
		return fmt.Errorf("Label `%s` declared more than once", l.Name())
	}
	cb.Labels[l.Name()] = l
	return nil
}
type AssignStmt struct {
	stmt
	Lhs, Rhs []Expr
	Token    *Token
}
type SendStmt struct {
	stmt
	Lhs, Rhs Expr
}
type StructStmt struct {
	stmt
	Struct *StructType
	Decl   *TypeDecl
}
type IfaceStmt struct {
	stmt
	Iface *IfaceType
}
type VarDecl struct {
	Vars  []*Variable
	Inits []Expr
}
func (vd *VarDecl) eachPair(callback func(v *Variable, init Expr)) {
	for i, v := range vd.Vars {
		init := Expr(nil)
		if i < len(vd.Inits) {
			init = vd.Inits[i]
		}
		callback(v, init)
	}
}
type VarStmt struct {
	stmt
	Vars       DeclChain
	IsFuncStmt bool
}
type DeclChain []*VarDecl
func (ad DeclChain) eachPair(callback func(v *Variable, init Expr)) {
	for _, vd := range ad {
		vd.eachPair(callback)
	}
}
func (ad DeclChain) countVars() int {
	count := 0
	for _, vd := range ad {
		count += len(vd.Vars)
	}
	return count
}
type PassStmt struct {
	stmt
}
type IfBranch struct {
	stmt
	ScopedVar Stmt
	Condition Expr
	Code      *CodeBlock
}
type IfStmt struct {
	stmt
	Branches []*IfBranch
}
type SwitchBranch struct {
	stmt
	Values []Expr
	Code   *CodeBlock
	TypeSwitchVar *Variable
}
type SwitchStmt struct {
	stmt
	ScopedVar Stmt
	Value    Stmt
	Branches []*SwitchBranch
}
type ForStmt struct {
	stmt
	ScopedVar  Stmt
	Condition  Expr
	RepeatStmt SimpleStmt
	Code       *CodeBlock
}
type ForRangeStmt struct {
	stmt
	ScopedVars  *VarDecl
	OutsideVars []Expr
	Series      Expr
	Code        *CodeBlock
}
type ExprStmt struct {
	stmt
	Expression Expr
}
type BranchStmt struct {
	stmt
	Token *Token
	Right *Ident
	GotoLabel *LabelStmt
	Branchable Stmt
}
type ReturnStmt struct {
	stmt
	Func   *FuncDecl
	Values []Expr
}
type compilerMacro struct {
	stmt
	Active bool
	Args   []Expr
}
type Generic interface {
	Object
	Signature() (name string, params []string)
	Instantiate(tc *TypesContext, params ...Type) (Object, string, []error)
	Code() []rune
	Imports() Imports
	Location() (tfile *gotoken.File, offset int)
}
type GenericStruct struct {
	stmt
	params []string
	struc  *StructType
	code    []rune
	imports Imports
	tfile  *gotoken.File
	offset int
}
func (gs *GenericStruct) Name() string                  { return gs.struc.Name }
func (gs *GenericStruct) Signature() (string, []string) { return gs.struc.Name, gs.params }
func (gs *GenericStruct) ObjectType() ObjectType        { return OBJECT_GENERIC }
func (gs *GenericStruct) Instantiate(tc *TypesContext, params ...Type) (Object, string, []error) {
	instKey := NewInstKey(gs, params)
	i, ok := tc.instantiations[instKey]
	if ok {
		return i.Object, "sliwka", nil
	}
	r := &Instantiation{
		Generic: gs,
		Params:  params,
		tc:      tc,
	}
	tc.instantiations[instKey] = r
	errs := r.ParseAndCheck()
	if len(errs) > 0 {
		return nil, "", errs
	}
	return r.Object, "sliwka", nil
}
func (gs *GenericStruct) Code() []rune                   { return gs.code }
func (gs *GenericStruct) Imports() Imports               { return gs.imports }
func (gs *GenericStruct) Location() (*gotoken.File, int) { return gs.tfile, gs.offset }
type GenericFunc struct {
	stmt
	params []string
	Func   *FuncDecl
	code    []rune
	imports Imports
	tfile  *gotoken.File
	offset int
}
func (gf *GenericFunc) Name() string                  { return gf.Func.name }
func (gf *GenericFunc) Signature() (string, []string) { return gf.Func.name, gf.params }
func (gf *GenericFunc) ObjectType() ObjectType        { return OBJECT_GENERIC }
func (gf *GenericFunc) Instantiate(tc *TypesContext, params ...Type) (Object, string, []error) {
	instKey := NewInstKey(gf, params)
	i, ok := tc.instantiations[instKey]
	if ok {
		return i.Object, i.getGoName(), nil
	}
	r := &Instantiation{
		Generic: gf,
		Params:  params,
		tc:      tc,
	}
	tc.instantiations[instKey] = r
	errs := r.ParseAndCheck()
	if len(errs) > 0 {
		return nil, "", errs
	}
	return r.Object, r.getGoName(), nil
}
func (gf *GenericFunc) Code() []rune                   { return gf.code }
func (gf *GenericFunc) Imports() Imports               { return gf.imports }
func (gf *GenericFunc) Location() (*gotoken.File, int) { return gf.tfile, gf.offset }
type GenericParamType struct {
	Name     string
	Concrete Type
}
func (t *GenericParamType) Known() bool {
	if t.Concrete == nil {
		return false
	}
	return t.Concrete.Known()
}
func (t *GenericParamType) String() string {
	if t.Concrete == nil {
		return t.Name
	}
	return t.Concrete.String()
}
func (t *GenericParamType) Kind() Kind                             { return KIND_GENERIC_PARAM }
func (t *GenericParamType) ZeroValue() string                      { return t.Concrete.ZeroValue() }
func (t *GenericParamType) MapSubtypes(callback func(t Type) bool) {}
type GenericType struct {
	Name string
	Package *ImportStmt
	Params []Type
	Generic *GenericStruct
	Struct *StructType
}
func (t *GenericType) Known() bool {
	for _, p := range t.Params {
		if !p.Known() {
			return false
		}
	}
	return true
}
func (t *GenericType) String() string {
	b := &bytes.Buffer{}
	b.WriteString(t.Generic.Name() + "[")
	for i, p := range t.Params {
		b.WriteString(p.String())
		if i+1 < len(t.Params) {
			b.WriteString(", ")
		}
	}
	b.WriteByte(']')
	return b.String()
}
func (t *GenericType) Kind() Kind { return KIND_GENERIC_INST }
func (t *GenericType) ZeroValue() string {
	return t.Struct.ZeroValue()
}
func (t *GenericType) MapSubtypes(callback func(t Type) bool) {
	for _, p := range t.Params {
		mapSubtype(p, callback)
	}
}
func (t *GenericType) RootType() Type {
	return t.Struct
}
func (t *GenericType) NamePtr() *string {
	return &t.Name
}
func (t *GenericType) PackagePtr() *ImportStmt {
	return t.Package
}
type Kind int
const (
	KIND_SIMPLE = Kind(iota + 1)
	KIND_ARRAY
	KIND_SLICE
	KIND_MAP
	KIND_POINTER
	KIND_CUSTOM
	KIND_STRUCT
	KIND_INTERFACE
	KIND_TUPLE
	KIND_FUNC
	KIND_CHAN
	KIND_GENERIC_PARAM
	KIND_GENERIC_INST
	KIND_UNKNOWN
)
type Type interface {
	Known() bool
	String() string
	Kind() Kind
	ZeroValue() string
	MapSubtypes(callback func(t Type) bool)
}
type DeclaredType interface {
	Type
	NamePtr() *string
	RootType() Type
	PackagePtr() *ImportStmt
}