github.com/goplus/gox@v1.14.13-0.20240308130321-6ff7f61cfae8/template.go (about)

     1  /*
     2   Copyright 2021 The GoPlus Authors (goplus.org)
     3   Licensed under the Apache License, Version 2.0 (the "License");
     4   you may not use this file except in compliance with the License.
     5   You may obtain a copy of the License at
     6       http://www.apache.org/licenses/LICENSE-2.0
     7   Unless required by applicable law or agreed to in writing, software
     8   distributed under the License is distributed on an "AS IS" BASIS,
     9   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10   See the License for the specific language governing permissions and
    11   limitations under the License.
    12  */
    13  
    14  package gox
    15  
    16  import (
    17  	"fmt"
    18  	"go/constant"
    19  	"go/token"
    20  	"go/types"
    21  	"log"
    22  	"math/big"
    23  
    24  	"github.com/goplus/gox/internal"
    25  )
    26  
    27  // ----------------------------------------------------------------------------
    28  
    29  type Contract interface {
    30  	Match(pkg *Package, t types.Type) bool
    31  	String() string
    32  }
    33  
    34  type TemplateParamType struct {
    35  	name     string
    36  	contract Contract
    37  	idxFlag  int
    38  }
    39  
    40  func NewTemplateParamType(idx int, name string, contract Contract) *TemplateParamType {
    41  	return &TemplateParamType{idxFlag: idx, name: name, contract: contract}
    42  }
    43  
    44  func (p *TemplateParamType) Underlying() types.Type { return p }
    45  func (p *TemplateParamType) String() string {
    46  	return fmt.Sprintf("TemplateParamType{name: %v}", p.name)
    47  }
    48  
    49  func (p *TemplateParamType) idx() int {
    50  	return p.idxFlag &^ paramAllowUntyped
    51  }
    52  
    53  func (p *TemplateParamType) allowUntyped() bool {
    54  	return (p.idxFlag & paramAllowUntyped) != 0
    55  }
    56  
    57  const (
    58  	paramAllowUntyped = 0x10000
    59  )
    60  
    61  // ----------------------------------------------------------------------------
    62  
    63  type unboundFuncParam struct {
    64  	tBound types.Type
    65  	typ    *TemplateParamType
    66  	parg   *internal.Elem
    67  }
    68  
    69  func (p *unboundFuncParam) boundTo(pkg *Package, t types.Type, parg *internal.Elem) {
    70  	if !p.typ.allowUntyped() {
    71  		t = DefaultConv(pkg, t, parg)
    72  	}
    73  	p.tBound, p.parg = t, parg
    74  }
    75  
    76  func (p *unboundFuncParam) Underlying() types.Type { return p }
    77  func (p *unboundFuncParam) String() string {
    78  	return fmt.Sprintf("unboundFuncParam{typ: %v}", p.tBound)
    79  }
    80  
    81  type unboundProxyParam struct {
    82  	real types.Type
    83  }
    84  
    85  func (p *unboundProxyParam) Underlying() types.Type { return p }
    86  func (p *unboundProxyParam) String() string {
    87  	return fmt.Sprintf("unboundProxyParam{typ: %v}", p.real)
    88  }
    89  
    90  func getElemTypeIf(t types.Type, parg *internal.Elem) types.Type {
    91  	if parg != nil && parg.CVal != nil {
    92  		if tb, ok := t.(*types.Basic); ok && (tb.Info()&types.IsFloat) != 0 {
    93  			if constant.ToInt(parg.CVal).Kind() == constant.Int {
    94  				return types.Typ[types.UntypedInt]
    95  			}
    96  		}
    97  	}
    98  	return t
    99  }
   100  
   101  type boundTypeError struct {
   102  	a, b types.Type
   103  }
   104  
   105  func (p *boundTypeError) Error() string {
   106  	return fmt.Sprintf("boundType %v => %v failed", p.a, p.b)
   107  }
   108  
   109  func boundType(pkg *Package, arg, param types.Type, parg *internal.Elem) error {
   110  	switch p := param.(type) {
   111  	case *unboundFuncParam: // template function param
   112  		if p.tBound == nil {
   113  			if !p.typ.contract.Match(pkg, arg) {
   114  				return fmt.Errorf("TODO: contract.Match %v => %v failed", arg, p.typ.contract)
   115  			}
   116  			p.boundTo(pkg, arg, parg)
   117  		} else if !AssignableConv(pkg, getElemTypeIf(arg, parg), p.tBound, parg) {
   118  			if !(isUntyped(pkg, p.tBound) && AssignableConv(pkg, p.tBound, arg, p.parg)) {
   119  				return &boundTypeError{a: arg, b: p.tBound}
   120  			}
   121  			p.tBound = arg
   122  		}
   123  		return nil
   124  	case *unboundProxyParam:
   125  		switch param := p.real.(type) {
   126  		case *types.Pointer:
   127  			switch t := arg.(type) {
   128  			case *types.Pointer:
   129  				return boundType(pkg, t.Elem(), param.Elem(), nil) // TODO: expr = nil
   130  			case *refType:
   131  				return boundType(pkg, t.typ, param.Elem(), nil)
   132  			}
   133  		case *types.Array:
   134  			if t, ok := arg.(*types.Array); ok && param.Len() == t.Len() {
   135  				return boundType(pkg, t.Elem(), param.Elem(), nil) // TODO: expr = nil
   136  			}
   137  		case *types.Map:
   138  			if t, ok := arg.(*types.Map); ok {
   139  				if err1 := boundType(pkg, t.Key(), param.Key(), nil); err1 != nil { // TODO: expr = nil
   140  					return &boundTypeError{a: t.Key(), b: param.Key()}
   141  				}
   142  				return boundType(pkg, t.Elem(), param.Elem(), nil) // TODO: expr = nil
   143  			}
   144  		case *types.Chan:
   145  			if t, ok := arg.(*types.Chan); ok {
   146  				if dir := t.Dir(); dir == param.Dir() || dir == types.SendRecv {
   147  					return boundType(pkg, t.Elem(), param.Elem(), nil) // TODO: expr = nil
   148  				}
   149  			}
   150  		case *types.Struct:
   151  			panic("TODO: boundType struct")
   152  		default:
   153  			log.Panicln("TODO: boundType - unknown type:", param)
   154  		}
   155  		return fmt.Errorf("TODO: bound %v => unboundProxyParam", arg)
   156  	case *types.Slice:
   157  		typ := arg
   158  	retry:
   159  		switch t := typ.(type) {
   160  		case *types.Slice:
   161  			return boundType(pkg, t.Elem(), p.Elem(), nil) // TODO: expr = nil
   162  		case *types.Named:
   163  			typ = pkg.cb.getUnderlying(t)
   164  			goto retry
   165  		}
   166  		return fmt.Errorf("TODO: bound slice failed - %v not a slice", arg)
   167  	case *types.Signature:
   168  		panic("TODO: boundType function signature")
   169  	default:
   170  		if AssignableConv(pkg, arg, param, parg) {
   171  			return nil
   172  		}
   173  	}
   174  	return fmt.Errorf("TODO: bound %v => %v", arg, param)
   175  }
   176  
   177  // Default returns the default "typed" type for an "untyped" type;
   178  // it returns the incoming type for all other types. The default type
   179  // for untyped nil is untyped nil.
   180  func Default(pkg *Package, t types.Type) types.Type {
   181  	return DefaultConv(pkg, t, nil)
   182  }
   183  
   184  func DefaultConv(pkg *Package, t types.Type, pv *Element) types.Type {
   185  	switch typ := t.(type) {
   186  	case *types.Named:
   187  		o := typ.Obj()
   188  		if at := o.Pkg(); at != nil {
   189  			name := o.Name() + "_Default"
   190  			if typName := at.Scope().Lookup(name); typName != nil {
   191  				if tn, ok := typName.(*types.TypeName); ok && tn.IsAlias() {
   192  					typ := tn.Type()
   193  					if pv != nil {
   194  						if ok = assignable(pkg, t, typ.(*types.Named), pv); !ok {
   195  							log.Panicln("==> DefaultConv failed:", t, typ)
   196  						}
   197  						if debugMatch {
   198  							log.Println("==> DefaultConv", t, typ)
   199  						}
   200  					}
   201  					return typ
   202  				}
   203  			}
   204  		}
   205  	case *inferFuncType:
   206  		return typ.Instance()
   207  	case *types.Signature:
   208  		if funcs, ok := CheckOverloadFunc(typ); ok {
   209  			if len(funcs) == 1 {
   210  				o := funcs[0]
   211  				if pv != nil {
   212  					pv.Val = toObjectExpr(pkg, o)
   213  				}
   214  				return o.Type()
   215  			}
   216  			log.Panicln("==> DefaultConv failed: overload functions have no default type")
   217  		}
   218  	default:
   219  		return types.Default(t)
   220  	}
   221  	return t
   222  }
   223  
   224  func ConvertibleTo(pkg *Package, V, T types.Type) bool {
   225  	pkg.cb.ensureLoaded(V)
   226  	pkg.cb.ensureLoaded(T)
   227  	if V == types.Typ[types.UnsafePointer] {
   228  		if _, ok := T.(*types.Pointer); ok {
   229  			return true
   230  		}
   231  	}
   232  	return types.ConvertibleTo(V, T)
   233  }
   234  
   235  // AssignableTo reports whether a value of type V is assignable to a variable of type T.
   236  func AssignableTo(pkg *Package, V, T types.Type) bool {
   237  	return AssignableConv(pkg, V, T, nil)
   238  }
   239  
   240  func AssignableConv(pkg *Package, V, T types.Type, pv *Element) bool {
   241  	pkg.cb.ensureLoaded(V)
   242  	pkg.cb.ensureLoaded(T)
   243  	V, T = realType(V), realType(T)
   244  	switch v := V.(type) {
   245  	case *refType: // ref type
   246  		if t, ok := T.(*types.Pointer); ok {
   247  			V, T = v.typ, t.Elem()
   248  		} else {
   249  			V = v.typ
   250  		}
   251  	case *inferFuncType:
   252  		V = v.Instance()
   253  	case *types.Signature:
   254  		if funcs, ok := CheckOverloadFunc(v); ok {
   255  			if len(funcs) == 1 {
   256  				o := funcs[0]
   257  				V = o.Type()
   258  				if pv != nil {
   259  					pv.Val = toObjectExpr(pkg, o)
   260  					pv.Type = V
   261  				}
   262  			}
   263  		}
   264  	default:
   265  		V = getElemTypeIf(V, pv)
   266  	}
   267  	if types.AssignableTo(V, T) {
   268  		if t, ok := T.(*types.Basic); ok { // untyped type
   269  			vkind := V.(*types.Basic).Kind()
   270  			tkind := t.Kind()
   271  			switch {
   272  			case vkind >= types.UntypedInt && vkind <= types.UntypedComplex:
   273  				if tkind <= types.Uintptr && pv != nil && outOfRange(tkind, pv.CVal) {
   274  					if debugMatch {
   275  						log.Printf("==> AssignableConv %v (%v): value is out of %v range", V, pv.CVal, T)
   276  					}
   277  					return false
   278  				}
   279  				if tkind >= types.UntypedInt && tkind <= types.UntypedComplex {
   280  					if vkind == tkind || vkind == types.UntypedRune {
   281  						return true
   282  					}
   283  					return tkind != types.UntypedRune && tkind > vkind
   284  				}
   285  				if vkind == types.UntypedFloat {
   286  					return tkind >= types.Float32
   287  				}
   288  				if vkind == types.UntypedComplex {
   289  					return tkind >= types.Complex64
   290  				}
   291  			}
   292  		}
   293  		return true
   294  	}
   295  	if t, ok := T.(*types.Named); ok {
   296  		ok = assignable(pkg, V, t, pv)
   297  		if debugMatch && pv != nil {
   298  			log.Println("==> AssignableConv", V, T, ok)
   299  		}
   300  		return ok
   301  	}
   302  	if pkg.implicitCast != nil {
   303  		return pkg.implicitCast(pkg, V, T, pv)
   304  	}
   305  	return false
   306  }
   307  
   308  func outOfRange(tkind types.BasicKind, cval constant.Value) bool {
   309  	// untyped int may not a constant. For an example:
   310  	//    func GetValue(shift uint) uint {
   311  	//       return 1 << shift
   312  	//    }
   313  	if cval == nil {
   314  		return false
   315  	}
   316  	rg := tkindRanges[tkind]
   317  	return constant.Compare(cval, token.LSS, rg[0]) || constant.Compare(cval, token.GTR, rg[1])
   318  }
   319  
   320  const (
   321  	intSize    = 32 << (^uint(0) >> 63)
   322  	intptrSize = 32 << (^uintptr(0) >> 63)
   323  	maxUint    = (1 << intSize) - 1
   324  	maxUintptr = (1 << intptrSize) - 1
   325  	maxUint8   = (1 << 8) - 1
   326  	maxUint16  = (1 << 16) - 1
   327  	maxUint32  = (1 << 32) - 1
   328  	maxUint64  = (1 << 64) - 1
   329  	minInt     = -(1 << (intSize - 1))
   330  	maxInt     = (1 << (intSize - 1)) - 1
   331  	minInt8    = -(1 << (8 - 1))
   332  	maxInt8    = (1 << (8 - 1)) - 1
   333  	minInt16   = -(1 << (16 - 1))
   334  	maxInt16   = (1 << (16 - 1)) - 1
   335  	minInt32   = -(1 << (32 - 1))
   336  	maxInt32   = (1 << (32 - 1)) - 1
   337  	minInt64   = -(1 << (64 - 1))
   338  	maxInt64   = (1 << (64 - 1)) - 1
   339  )
   340  
   341  var (
   342  	tkindRanges = [...][2]constant.Value{
   343  		types.Int:     {constant.MakeInt64(minInt), constant.MakeInt64(maxInt)},
   344  		types.Int8:    {constant.MakeInt64(minInt8), constant.MakeInt64(maxInt8)},
   345  		types.Int16:   {constant.MakeInt64(minInt16), constant.MakeInt64(maxInt16)},
   346  		types.Int32:   {constant.MakeInt64(minInt32), constant.MakeInt64(maxInt32)},
   347  		types.Int64:   {constant.MakeInt64(minInt64), constant.MakeInt64(maxInt64)},
   348  		types.Uint:    {constant.MakeInt64(0), constant.MakeUint64(maxUint)},
   349  		types.Uint8:   {constant.MakeInt64(0), constant.MakeUint64(maxUint8)},
   350  		types.Uint16:  {constant.MakeInt64(0), constant.MakeUint64(maxUint16)},
   351  		types.Uint32:  {constant.MakeInt64(0), constant.MakeUint64(maxUint32)},
   352  		types.Uint64:  {constant.MakeInt64(0), constant.MakeUint64(maxUint64)},
   353  		types.Uintptr: {constant.MakeInt64(0), constant.MakeUint64(maxUintptr)},
   354  	}
   355  )
   356  
   357  func assignable(pkg *Package, v types.Type, t *types.Named, pv *internal.Elem) bool {
   358  	o := t.Obj()
   359  	if at := o.Pkg(); at != nil {
   360  		tname := o.Name()
   361  		scope := at.Scope()
   362  		name := tname + "_Init"
   363  		if ini := scope.Lookup(name); ini != nil {
   364  			if v == types.Typ[types.UntypedInt] {
   365  				switch t {
   366  				case pkg.utBigInt, pkg.utBigRat:
   367  					if pv != nil {
   368  						switch cv := constant.Val(pv.CVal).(type) {
   369  						case *big.Int:
   370  							nv := pkg.cb.UntypedBigInt(cv).stk.Pop()
   371  							pv.Type, pv.Val = nv.Type, nv.Val
   372  						}
   373  					}
   374  					return true
   375  				}
   376  			}
   377  			if pv.CVal != nil {
   378  				if checkUntypedOverflows(scope, tname, pv) {
   379  					return false
   380  				}
   381  			}
   382  			fn := &internal.Elem{Val: toObjectExpr(pkg, ini), Type: ini.Type()}
   383  			arg := &internal.Elem{Type: v}
   384  			if pv != nil {
   385  				arg.Val, arg.CVal, arg.Src = pv.Val, pv.CVal, pv.Src
   386  			}
   387  			ret, err := matchFuncCall(pkg, fn, []*internal.Elem{arg}, 0)
   388  			if err == nil {
   389  				if pv != nil {
   390  					pv.Val = ret.Val
   391  				}
   392  				return true
   393  			}
   394  		}
   395  	}
   396  	return false
   397  }
   398  
   399  func ComparableTo(pkg *Package, varg, targ *Element) bool {
   400  	V, T := varg.Type, targ.Type
   401  	if v, ok := V.(*types.Basic); ok {
   402  		if (v.Info() & types.IsUntyped) != 0 {
   403  			return untypedComparable(pkg, v, varg, T)
   404  		}
   405  	}
   406  	if t, ok := T.(*types.Basic); ok {
   407  		if (t.Info() & types.IsUntyped) != 0 {
   408  			return untypedComparable(pkg, t, targ, V)
   409  		}
   410  	}
   411  	if getUnderlying(pkg, V) == getUnderlying(pkg, T) {
   412  		return true
   413  	}
   414  	return AssignableConv(pkg, V, T, varg) || AssignableConv(pkg, T, V, targ)
   415  }
   416  
   417  func untypedComparable(pkg *Package, v *types.Basic, varg *Element, t types.Type) bool {
   418  	kind := v.Kind()
   419  	if kind == types.UntypedNil {
   420  	retry:
   421  		switch tt := t.(type) {
   422  		case *types.Interface, *types.Slice, *types.Pointer, *types.Map, *types.Signature, *types.Chan:
   423  			return true
   424  		case *types.Basic:
   425  			return tt.Kind() == types.UnsafePointer // invalid: nil == nil
   426  		case *types.Named:
   427  			t = pkg.cb.getUnderlying(tt)
   428  			goto retry
   429  		}
   430  	} else {
   431  		switch u := getUnderlying(pkg, t).(type) {
   432  		case *types.Basic:
   433  			switch v.Kind() {
   434  			case types.UntypedBool:
   435  				return (u.Info() & types.IsBoolean) != 0
   436  			case types.UntypedFloat:
   437  				if constant.ToInt(varg.CVal).Kind() != constant.Int {
   438  					return (u.Info() & (types.IsFloat | types.IsComplex)) != 0
   439  				}
   440  				fallthrough
   441  			case types.UntypedInt, types.UntypedRune:
   442  				return (u.Info() & types.IsNumeric) != 0
   443  			case types.UntypedComplex:
   444  				return (u.Info() & types.IsComplex) != 0
   445  			case types.UntypedString:
   446  				return (u.Info() & types.IsString) != 0
   447  			}
   448  		case *types.Interface:
   449  			return u.Empty()
   450  		}
   451  	}
   452  	return false
   453  }
   454  
   455  // NewSignature returns a new function type for the given receiver, parameters,
   456  // and results, either of which may be nil. If variadic is set, the function
   457  // is variadic, it must have at least one parameter, and the last parameter
   458  // must be of unnamed slice type.
   459  func NewSignature(recv *types.Var, params, results *types.Tuple, variadic bool) *types.Signature {
   460  	return types.NewSignatureType(recv, nil, nil, params, results, variadic)
   461  }
   462  
   463  // NewSlice returns a new slice type for the given element type.
   464  func NewSlice(elem types.Type) types.Type {
   465  	return types.NewSlice(elem)
   466  }
   467  
   468  // NewMap returns a new map for the given key and element types.
   469  func NewMap(key, elem types.Type) types.Type {
   470  	var t types.Type = types.NewMap(key, elem)
   471  	if isUnboundParam(key) || isUnboundParam(elem) {
   472  		t = &unboundProxyParam{real: t}
   473  	}
   474  	return t
   475  }
   476  
   477  // NewChan returns a new channel type for the given direction and element type.
   478  func NewChan(dir types.ChanDir, elem types.Type) types.Type {
   479  	var t types.Type = types.NewChan(dir, elem)
   480  	if isUnboundParam(elem) {
   481  		t = &unboundProxyParam{real: t}
   482  	}
   483  	return t
   484  }
   485  
   486  // NewArray returns a new array type for the given element type and length.
   487  // A negative length indicates an unknown length.
   488  func NewArray(elem types.Type, len int64) types.Type {
   489  	var t types.Type = types.NewArray(elem, len)
   490  	if isUnboundParam(elem) {
   491  		t = &unboundProxyParam{real: t}
   492  	}
   493  	return t
   494  }
   495  
   496  // NewPointer returns a new pointer type for the given element (base) type.
   497  func NewPointer(elem types.Type) types.Type {
   498  	var t types.Type = types.NewPointer(elem)
   499  	if isUnboundParam(elem) {
   500  		t = &unboundProxyParam{real: t}
   501  	}
   502  	return t
   503  }
   504  
   505  func isUnboundParam(typ types.Type) bool {
   506  	switch t := typ.(type) {
   507  	case *unboundFuncParam:
   508  		return true
   509  	case *TemplateParamType:
   510  		return true
   511  	case *unboundProxyParam:
   512  		return true
   513  	case *types.Slice:
   514  		return isUnboundParam(t.Elem())
   515  	case *types.Signature:
   516  		return isUnboundSignature(t)
   517  	}
   518  	return false
   519  }
   520  
   521  func isUnboundVar(v *types.Var) bool {
   522  	if v == nil {
   523  		return false
   524  	}
   525  	return isUnboundParam(v.Type())
   526  }
   527  
   528  func isUnboundTuple(t *types.Tuple) bool {
   529  	for i, n := 0, t.Len(); i < n; i++ {
   530  		if isUnboundVar(t.At(i)) {
   531  			return true
   532  		}
   533  	}
   534  	return false
   535  }
   536  
   537  func isUnboundSignature(sig *types.Signature) bool {
   538  	return isUnboundVar(sig.Recv()) ||
   539  		isUnboundTuple(sig.Params()) ||
   540  		isUnboundTuple(sig.Results())
   541  }
   542  
   543  // ----------------------------------------------------------------------------
   544  
   545  type instantiated struct {
   546  	tparams []*unboundFuncParam
   547  	results bool
   548  }
   549  
   550  func (p *instantiated) normalize(t types.Type) types.Type {
   551  	if p != nil && p.results {
   552  		t, _ = toNormalize(p.tparams, t)
   553  	}
   554  	return t
   555  }
   556  
   557  func (p *instantiated) normalizeTuple(t *types.Tuple) *types.Tuple {
   558  	if p != nil && p.results {
   559  		t, _ = toNormalizeTuple(p.tparams, t)
   560  	}
   561  	return t
   562  }
   563  
   564  func toNormalize(tparams []*unboundFuncParam, typ types.Type) (types.Type, bool) {
   565  	switch tt := typ.(type) {
   566  	case *unboundFuncParam:
   567  		if tt.tBound == nil {
   568  			log.Panicln("TODO: unbound type -", tt.typ.name)
   569  		}
   570  		return tt.tBound, true
   571  	case *unboundProxyParam:
   572  		switch t := tt.real.(type) {
   573  		case *types.Pointer:
   574  			elem, _ := toNormalize(tparams, t.Elem())
   575  			return types.NewPointer(elem), true
   576  		case *types.Array:
   577  			elem, _ := toNormalize(tparams, t.Elem())
   578  			return types.NewArray(elem, t.Len()), true
   579  		case *types.Map:
   580  			key, _ := toNormalize(tparams, t.Key())
   581  			elem, _ := toNormalize(tparams, t.Elem())
   582  			return types.NewMap(key, elem), true
   583  		case *types.Chan:
   584  			elem, _ := toNormalize(tparams, t.Elem())
   585  			return types.NewChan(t.Dir(), elem), true
   586  		case *types.Struct:
   587  			panic("TODO: toNormalize struct")
   588  		default:
   589  			log.Panicln("TODO: toNormalize - unknown type:", t)
   590  		}
   591  	case *unboundType:
   592  		if tt.tBound == nil {
   593  			log.Panicln("TODO: unbound type")
   594  		}
   595  		return tt.tBound, true
   596  	case *types.Slice:
   597  		if elem, ok := toNormalize(tparams, tt.Elem()); ok {
   598  			return types.NewSlice(elem), true
   599  		}
   600  	case *types.Signature:
   601  		return toNormalizeSignature(tparams, tt)
   602  	}
   603  	return typ, false
   604  }
   605  
   606  func toNormalizeVar(tparams []*unboundFuncParam, param *types.Var) (*types.Var, bool) {
   607  	if param == nil {
   608  		return nil, false
   609  	}
   610  	if t, changed := toNormalize(tparams, param.Type()); changed {
   611  		return types.NewParam(param.Pos(), param.Pkg(), param.Name(), t), true
   612  	}
   613  	return param, false
   614  }
   615  
   616  func toNormalizeTuple(tparams []*unboundFuncParam, params *types.Tuple) (*types.Tuple, bool) {
   617  	n := params.Len()
   618  	vars := make([]*types.Var, n)
   619  	var ok, changed bool
   620  	for i := 0; i < n; i++ {
   621  		if vars[i], ok = toNormalizeVar(tparams, params.At(i)); ok {
   622  			changed = true
   623  		}
   624  	}
   625  	if changed {
   626  		return types.NewTuple(vars...), true
   627  	}
   628  	return params, false
   629  }
   630  
   631  func toNormalizeSignature(
   632  	tparams []*unboundFuncParam, sig *types.Signature) (*types.Signature, bool) {
   633  	recv, ok1 := toNormalizeVar(tparams, sig.Recv())
   634  	params, ok2 := toNormalizeTuple(tparams, sig.Params())
   635  	results, ok3 := toNormalizeTuple(tparams, sig.Results())
   636  	if ok1 || ok2 || ok3 {
   637  		return types.NewSignatureType(recv, nil, nil, params, results, sig.Variadic()), true
   638  	}
   639  	return sig, false
   640  }
   641  
   642  // ----------------------------------------------------------------------------
   643  
   644  const (
   645  	tokUnaryFlag      token.Token = 0x80000
   646  	tokFlagApproxType token.Token = 0x40000 // ~T
   647  	tokFlagAll                    = tokUnaryFlag | tokFlagApproxType
   648  )
   649  
   650  // TemplateSignature: type of template function
   651  type TemplateSignature struct {
   652  	params  []*TemplateParamType
   653  	sig     *types.Signature
   654  	tokFlag token.Token // tok + unary flag, only for builtin operator
   655  }
   656  
   657  func (p *TemplateSignature) tok() token.Token {
   658  	return p.tokFlag &^ tokFlagAll
   659  }
   660  
   661  func (p *TemplateSignature) hasApproxType() bool {
   662  	return (p.tokFlag & tokFlagApproxType) != 0
   663  }
   664  
   665  func (p *TemplateSignature) isOp() bool {
   666  	return (p.tokFlag &^ tokFlagApproxType) != 0
   667  }
   668  
   669  func (p *TemplateSignature) isUnaryOp() bool {
   670  	return (p.tokFlag & tokUnaryFlag) != 0
   671  }
   672  
   673  func assertValidTemplateSignature(tsig *TemplateSignature) {
   674  	for i, param := range tsig.params {
   675  		if param.idx() != i {
   676  			panic("TODO: invalid TemplateSignature - incorrect index")
   677  		}
   678  	}
   679  }
   680  
   681  // NewTemplateSignature creates type of a template function.
   682  func NewTemplateSignature(
   683  	templateParams []*TemplateParamType,
   684  	recv *types.Var, params, results *types.Tuple, variadic bool, tok ...token.Token) *TemplateSignature {
   685  
   686  	var tokFlag token.Token
   687  	if tok != nil {
   688  		tokFlag = tok[0]
   689  	}
   690  	tsig := &TemplateSignature{
   691  		params:  templateParams,
   692  		sig:     types.NewSignatureType(recv, nil, nil, params, results, variadic),
   693  		tokFlag: tokFlag,
   694  	}
   695  	if tsig.isOp() {
   696  		for _, tparam := range templateParams {
   697  			tparam.idxFlag |= paramAllowUntyped
   698  		}
   699  	}
   700  	assertValidTemplateSignature(tsig)
   701  	return tsig
   702  }
   703  
   704  func (p *TemplateSignature) Underlying() types.Type { return p }
   705  func (p *TemplateSignature) String() string {
   706  	return fmt.Sprintf("TemplateSignature{%v}", p.sig)
   707  }
   708  
   709  // TODO: check name
   710  func (p *TemplateSignature) instantiate() (*types.Signature, *instantiated) {
   711  	tparams := make([]*unboundFuncParam, len(p.params))
   712  	for i, param := range p.params {
   713  		tparams[i] = &unboundFuncParam{typ: param}
   714  	}
   715  	sig, _, instantiatedResults := toInstantiateSignature(tparams, p.sig)
   716  	return sig, &instantiated{tparams: tparams, results: instantiatedResults}
   717  }
   718  
   719  func toInstantiate(tparams []*unboundFuncParam, typ types.Type) (types.Type, bool) {
   720  	switch tt := typ.(type) {
   721  	case *TemplateParamType:
   722  		return tparams[tt.idx()], true
   723  	case *unboundProxyParam:
   724  		switch t := tt.real.(type) {
   725  		case *types.Pointer:
   726  			elem, _ := toInstantiate(tparams, t.Elem())
   727  			return &unboundProxyParam{types.NewPointer(elem)}, true
   728  		case *types.Array:
   729  			elem, _ := toInstantiate(tparams, t.Elem())
   730  			return &unboundProxyParam{types.NewArray(elem, t.Len())}, true
   731  		case *types.Map:
   732  			key, _ := toInstantiate(tparams, t.Key())
   733  			elem, _ := toInstantiate(tparams, t.Elem())
   734  			return &unboundProxyParam{types.NewMap(key, elem)}, true
   735  		case *types.Chan:
   736  			elem, _ := toInstantiate(tparams, t.Elem())
   737  			return &unboundProxyParam{types.NewChan(t.Dir(), elem)}, true
   738  		case *types.Struct:
   739  			panic("TODO: instantiate struct")
   740  		default:
   741  			log.Panicln("TODO: toInstantiate - unknown type:", t)
   742  		}
   743  	case *types.Slice:
   744  		if elem, ok := toInstantiate(tparams, tt.Elem()); ok {
   745  			return types.NewSlice(elem), true
   746  		}
   747  	case *types.Signature:
   748  		t, ok, _ := toInstantiateSignature(tparams, tt)
   749  		return t, ok
   750  	}
   751  	return typ, false
   752  }
   753  
   754  func toInstantiateVar(tparams []*unboundFuncParam, param *types.Var) (*types.Var, bool) {
   755  	if param == nil {
   756  		return nil, false
   757  	}
   758  	if t, changed := toInstantiate(tparams, param.Type()); changed {
   759  		return types.NewParam(param.Pos(), param.Pkg(), param.Name(), t), true
   760  	}
   761  	return param, false
   762  }
   763  
   764  func toInstantiateTuple(tparams []*unboundFuncParam, params *types.Tuple) (*types.Tuple, bool) {
   765  	n := params.Len()
   766  	vars := make([]*types.Var, n)
   767  	var ok, changed bool
   768  	for i := 0; i < n; i++ {
   769  		if vars[i], ok = toInstantiateVar(tparams, params.At(i)); ok {
   770  			changed = true
   771  		}
   772  	}
   773  	if changed {
   774  		return types.NewTuple(vars...), true
   775  	}
   776  	return params, false
   777  }
   778  
   779  func toInstantiateSignature(
   780  	tparams []*unboundFuncParam, sig *types.Signature) (*types.Signature, bool, bool) {
   781  	recv, ok1 := toInstantiateVar(tparams, sig.Recv())
   782  	params, ok2 := toInstantiateTuple(tparams, sig.Params())
   783  	results, ok3 := toInstantiateTuple(tparams, sig.Results())
   784  	if ok1 || ok2 || ok3 {
   785  		return types.NewSignatureType(recv, nil, nil, params, results, sig.Variadic()), true, ok3
   786  	}
   787  	return sig, false, ok3
   788  }
   789  
   790  // ----------------------------------------------------------------------------
   791  
   792  // TemplateFunc: template function
   793  type TemplateFunc struct {
   794  	*types.Func
   795  	sig *TemplateSignature
   796  }
   797  
   798  // NewTemplateFunc creates a template function.
   799  func NewTemplateFunc(pos token.Pos, pkg *types.Package, name string, tsig *TemplateSignature) *TemplateFunc {
   800  	return &TemplateFunc{sig: tsig, Func: types.NewFunc(pos, pkg, name, tsig.sig)}
   801  }
   802  
   803  // NewTemplateFunc return the type of specified template function.
   804  func (p *TemplateFunc) Type() types.Type {
   805  	return p.sig
   806  }
   807  
   808  // ----------------------------------------------------------------------------