github.com/goplus/gox@v1.14.13-0.20240308130321-6ff7f61cfae8/ast.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  	"errors"
    18  	"fmt"
    19  	"go/ast"
    20  	"go/constant"
    21  	"go/token"
    22  	"go/types"
    23  	"log"
    24  	"math/big"
    25  	"reflect"
    26  	"strconv"
    27  	"strings"
    28  
    29  	"github.com/goplus/gox/internal"
    30  )
    31  
    32  var (
    33  	errTemplateRecvMethodCallUnexpected = errors.New("matchFuncCall (TemplateRecvMethod) unexpected")
    34  )
    35  
    36  // ----------------------------------------------------------------------------
    37  
    38  var (
    39  	underscore = &ast.Ident{Name: "_"}
    40  )
    41  
    42  var (
    43  	identTrue   = ident("true")
    44  	identFalse  = ident("false")
    45  	identNil    = ident("nil")
    46  	identAppend = ident("append")
    47  	identLen    = ident("len")
    48  	identCap    = ident("cap")
    49  	identNew    = ident("new")
    50  	identMake   = ident("make")
    51  	identIota   = ident("iota")
    52  )
    53  
    54  func ident(name string) *ast.Ident {
    55  	return &ast.Ident{Name: name}
    56  }
    57  
    58  func boolean(v bool) *ast.Ident {
    59  	if v {
    60  		return identTrue
    61  	}
    62  	return identFalse
    63  }
    64  
    65  func stringLit(val string) *ast.BasicLit {
    66  	return &ast.BasicLit{Kind: token.STRING, Value: strconv.Quote(val)}
    67  }
    68  
    69  func toRecv(pkg *Package, recv *types.Var) *ast.FieldList {
    70  	var names []*ast.Ident
    71  	if name := recv.Name(); name != "" {
    72  		names = []*ast.Ident{ident(name)}
    73  	}
    74  	fld := &ast.Field{Names: names, Type: toRecvType(pkg, recv.Type())}
    75  	return &ast.FieldList{List: []*ast.Field{fld}}
    76  }
    77  
    78  // -----------------------------------------------------------------------------
    79  // function type
    80  
    81  func toFieldList(pkg *Package, t *types.Tuple) []*ast.Field {
    82  	if t == nil {
    83  		return nil
    84  	}
    85  	n := t.Len()
    86  	flds := make([]*ast.Field, n)
    87  	for i := 0; i < n; i++ {
    88  		item := t.At(i)
    89  		var names []*ast.Ident
    90  		if name := item.Name(); name != "" {
    91  			names = []*ast.Ident{ident(name)}
    92  		}
    93  		typ := toType(pkg, item.Type())
    94  		flds[i] = &ast.Field{Names: names, Type: typ}
    95  	}
    96  	return flds
    97  }
    98  
    99  func toFields(pkg *Package, t *types.Struct) []*ast.Field {
   100  	n := t.NumFields()
   101  	flds := make([]*ast.Field, n)
   102  	for i := 0; i < n; i++ {
   103  		item := t.Field(i)
   104  		var names []*ast.Ident
   105  		if !item.Embedded() {
   106  			names = []*ast.Ident{{Name: item.Name()}}
   107  		}
   108  		typ := toType(pkg, item.Type())
   109  		fld := &ast.Field{Names: names, Type: typ}
   110  		if tag := t.Tag(i); tag != "" {
   111  			fld.Tag = toTag(tag)
   112  		}
   113  		flds[i] = fld
   114  	}
   115  	return flds
   116  }
   117  
   118  func toTag(tag string) *ast.BasicLit {
   119  	var s string
   120  	if strings.ContainsAny(tag, "`\r\n") {
   121  		s = strconv.Quote(tag)
   122  	} else {
   123  		s = "`" + tag + "`"
   124  	}
   125  	return &ast.BasicLit{Kind: token.STRING, Value: s}
   126  }
   127  
   128  func toVariadic(fld *ast.Field) {
   129  	t, ok := fld.Type.(*ast.ArrayType)
   130  	if !ok || t.Len != nil {
   131  		panic("TODO: not a slice type")
   132  	}
   133  	fld.Type = &ast.Ellipsis{Elt: t.Elt}
   134  }
   135  
   136  // -----------------------------------------------------------------------------
   137  
   138  func toType(pkg *Package, typ types.Type) ast.Expr {
   139  retry:
   140  	switch t := typ.(type) {
   141  	case *types.Basic: // bool, int, etc
   142  		return toBasicType(pkg, t)
   143  	case *types.Pointer:
   144  		return &ast.StarExpr{X: toType(pkg, t.Elem())}
   145  	case *types.Named:
   146  		return toNamedType(pkg, t)
   147  	case *types.Interface:
   148  		return toInterface(pkg, t)
   149  	case *types.Slice:
   150  		return toSliceType(pkg, t)
   151  	case *types.Array:
   152  		return toArrayType(pkg, t)
   153  	case *types.Map:
   154  		return toMapType(pkg, t)
   155  	case *types.Struct:
   156  		return toStructType(pkg, t)
   157  	case *types.Chan:
   158  		return toChanType(pkg, t)
   159  	case *types.Signature:
   160  		return toFuncType(pkg, t)
   161  	case *unboundType:
   162  		if t.tBound == nil {
   163  			panic("unbound type")
   164  		}
   165  		typ = t.tBound
   166  		goto retry
   167  	case *TypeParam:
   168  		return toObjectExpr(pkg, t.Obj())
   169  	case *Union:
   170  		return toUnionType(pkg, t)
   171  	}
   172  	log.Panicln("TODO: toType -", reflect.TypeOf(typ))
   173  	return nil
   174  }
   175  
   176  func toBasicType(pkg *Package, t *types.Basic) ast.Expr {
   177  	if t.Kind() == types.UnsafePointer {
   178  		return toObjectExpr(pkg, unsafeRef("Pointer"))
   179  	}
   180  	if (t.Info() & types.IsUntyped) != 0 {
   181  		panic("unexpected: untyped type")
   182  	}
   183  	return &ast.Ident{Name: t.Name()}
   184  }
   185  
   186  func isUntyped(pkg *Package, typ types.Type) bool {
   187  	switch t := typ.(type) {
   188  	case *types.Basic:
   189  		return (t.Info() & types.IsUntyped) != 0
   190  	case *types.Named:
   191  		switch t {
   192  		case pkg.utBigInt, pkg.utBigRat, pkg.utBigFlt:
   193  			return true
   194  		}
   195  	}
   196  	return false
   197  }
   198  
   199  func toChanType(pkg *Package, t *types.Chan) ast.Expr {
   200  	return &ast.ChanType{Value: toType(pkg, t.Elem()), Dir: chanDirs[t.Dir()]}
   201  }
   202  
   203  var (
   204  	chanDirs = [...]ast.ChanDir{
   205  		types.SendRecv: ast.SEND | ast.RECV,
   206  		types.SendOnly: ast.SEND,
   207  		types.RecvOnly: ast.RECV,
   208  	}
   209  )
   210  
   211  func toStructType(pkg *Package, t *types.Struct) ast.Expr {
   212  	list := toFields(pkg, t)
   213  	return &ast.StructType{Fields: &ast.FieldList{List: list}}
   214  }
   215  
   216  func toArrayType(pkg *Package, t *types.Array) ast.Expr {
   217  	var len ast.Expr
   218  	if n := t.Len(); n < 0 {
   219  		len = &ast.Ellipsis{}
   220  	} else {
   221  		len = &ast.BasicLit{Kind: token.INT, Value: strconv.FormatInt(t.Len(), 10)}
   222  	}
   223  	return &ast.ArrayType{Len: len, Elt: toType(pkg, t.Elem())}
   224  }
   225  
   226  func toSliceType(pkg *Package, t *types.Slice) ast.Expr {
   227  	return &ast.ArrayType{Elt: toType(pkg, t.Elem())}
   228  }
   229  
   230  func toMapType(pkg *Package, t *types.Map) ast.Expr {
   231  	return &ast.MapType{Key: toType(pkg, t.Key()), Value: toType(pkg, t.Elem())}
   232  }
   233  
   234  var (
   235  	universeAny = types.Universe.Lookup("any")
   236  )
   237  
   238  func toInterface(pkg *Package, t *types.Interface) ast.Expr {
   239  	if t == universeAny.Type() {
   240  		return ast.NewIdent("any")
   241  	} else if interfaceIsImplicit(t) && t.NumEmbeddeds() == 1 {
   242  		return toType(pkg, t.EmbeddedType(0))
   243  	}
   244  	var flds []*ast.Field
   245  	for i, n := 0, t.NumEmbeddeds(); i < n; i++ {
   246  		typ := toType(pkg, t.EmbeddedType(i))
   247  		fld := &ast.Field{Type: typ}
   248  		flds = append(flds, fld)
   249  	}
   250  	for i, n := 0, t.NumExplicitMethods(); i < n; i++ {
   251  		fn := t.ExplicitMethod(i)
   252  		name := ident(fn.Name())
   253  		typ := toFuncType(pkg, fn.Type().(*types.Signature))
   254  		fld := &ast.Field{Names: []*ast.Ident{name}, Type: typ}
   255  		flds = append(flds, fld)
   256  	}
   257  	return &ast.InterfaceType{Methods: &ast.FieldList{List: flds}}
   258  }
   259  
   260  // -----------------------------------------------------------------------------
   261  // expression
   262  
   263  func toExpr(pkg *Package, val interface{}, src ast.Node) *internal.Elem {
   264  	if val == nil {
   265  		return &internal.Elem{
   266  			Val:  identNil,
   267  			Type: types.Typ[types.UntypedNil],
   268  			Src:  src,
   269  		}
   270  	}
   271  	switch v := val.(type) {
   272  	case *ast.BasicLit:
   273  		return &internal.Elem{
   274  			Val:  v,
   275  			Type: types.Typ[toBasicKind(v.Kind)],
   276  			CVal: constant.MakeFromLiteral(v.Value, v.Kind, 0),
   277  			Src:  src,
   278  		}
   279  	case *types.TypeName:
   280  		switch typ := v.Type(); typ.(type) {
   281  		case *TyInstruction: // instruction as a type
   282  			return toObject(pkg, v, src)
   283  		default:
   284  			if debugInstr {
   285  				log.Printf("Val %v => Typ %v", v, typ)
   286  			}
   287  			return &internal.Elem{
   288  				Val: toType(pkg, typ), Type: NewTypeType(typ), Src: src,
   289  			}
   290  		}
   291  	case *types.Builtin:
   292  		name := v.Name()
   293  		o := pkg.builtin.TryRef(name)
   294  		if o == nil {
   295  			o = pkg.unsafe_.Ref(name)
   296  		}
   297  		return toObject(pkg, o, src)
   298  	case types.Object:
   299  		if v == iotaObj {
   300  			v := pkg.cb.iotav
   301  			return &internal.Elem{
   302  				Val:  identIota,
   303  				Type: types.Typ[types.UntypedInt],
   304  				CVal: constant.MakeInt64(int64(v)),
   305  				Src:  src,
   306  			}
   307  		}
   308  		return toObject(pkg, v, src)
   309  	case *Element:
   310  		return v
   311  	case int:
   312  		return &internal.Elem{
   313  			Val:  &ast.BasicLit{Kind: token.INT, Value: strconv.Itoa(v)},
   314  			Type: types.Typ[types.UntypedInt],
   315  			CVal: constant.MakeInt64(int64(v)),
   316  			Src:  src,
   317  		}
   318  	case string:
   319  		return &internal.Elem{
   320  			Val:  &ast.BasicLit{Kind: token.STRING, Value: strconv.Quote(v)},
   321  			Type: types.Typ[types.UntypedString],
   322  			CVal: constant.MakeString(v),
   323  			Src:  src,
   324  		}
   325  	case bool:
   326  		return &internal.Elem{
   327  			Val:  boolean(v),
   328  			Type: types.Typ[types.UntypedBool],
   329  			CVal: constant.MakeBool(v),
   330  			Src:  src,
   331  		}
   332  	case rune:
   333  		return &internal.Elem{
   334  			Val:  &ast.BasicLit{Kind: token.CHAR, Value: strconv.QuoteRune(v)},
   335  			Type: types.Typ[types.UntypedRune],
   336  			CVal: constant.MakeInt64(int64(v)),
   337  			Src:  src,
   338  		}
   339  	case float64:
   340  		val := strconv.FormatFloat(v, 'g', -1, 64)
   341  		if !strings.ContainsAny(val, ".e") {
   342  			val += ".0"
   343  		}
   344  		return &internal.Elem{
   345  			Val:  &ast.BasicLit{Kind: token.FLOAT, Value: val},
   346  			Type: types.Typ[types.UntypedFloat],
   347  			CVal: constant.MakeFloat64(v),
   348  			Src:  src,
   349  		}
   350  	}
   351  	panic("unexpected: unsupport value type")
   352  }
   353  
   354  var (
   355  	iotaObj = types.Universe.Lookup("iota")
   356  )
   357  
   358  func toBasicKind(tok token.Token) types.BasicKind {
   359  	return tok2BasicKinds[tok]
   360  }
   361  
   362  var (
   363  	tok2BasicKinds = [...]types.BasicKind{
   364  		token.INT:    types.UntypedInt,
   365  		token.STRING: types.UntypedString,
   366  		token.CHAR:   types.UntypedRune,
   367  		token.FLOAT:  types.UntypedFloat,
   368  		token.IMAG:   types.UntypedComplex,
   369  	}
   370  )
   371  
   372  func chgObject(pkg *Package, v types.Object, old *internal.Elem) *internal.Elem {
   373  	ret := toObject(pkg, v, old.Src)
   374  	if denoted := getDenoted(old.Val); denoted != nil {
   375  		setDenoted(ret.Val, denoted)
   376  	}
   377  	return ret
   378  }
   379  
   380  func toObject(pkg *Package, v types.Object, src ast.Node) *internal.Elem {
   381  	var cval constant.Value
   382  	if cv, ok := v.(*types.Const); ok {
   383  		cval = cv.Val()
   384  	}
   385  	return &internal.Elem{
   386  		Val: toObjectExpr(pkg, v), Type: realType(v.Type()), CVal: cval, Src: src,
   387  	}
   388  }
   389  
   390  func toObjectExpr(pkg *Package, v types.Object) ast.Expr {
   391  	atPkg, name := v.Pkg(), v.Name()
   392  	if atPkg == nil || atPkg == pkg.Types { // at universe or at this package
   393  		return ident(name)
   394  	}
   395  	if atPkg == pkg.builtin.Types { // at builtin package
   396  		if strings.HasPrefix(name, goxPrefix) {
   397  			opName := name[len(goxPrefix):]
   398  			if op, ok := nameToOps[opName]; ok {
   399  				switch op.Arity {
   400  				case 2:
   401  					return &ast.BinaryExpr{Op: op.Tok}
   402  				case 1:
   403  					return &ast.UnaryExpr{Op: op.Tok}
   404  				}
   405  			}
   406  		}
   407  		return ident(name)
   408  	}
   409  	x := pkg.file.newImport(atPkg.Name(), atPkg.Path())
   410  	return &ast.SelectorExpr{
   411  		X:   x,
   412  		Sel: ident(v.Name()),
   413  	}
   414  }
   415  
   416  type operator struct {
   417  	Tok   token.Token
   418  	Arity int
   419  }
   420  
   421  var (
   422  	nameToOps = map[string]operator{
   423  		"Add":    {token.ADD, 2},
   424  		"Sub":    {token.SUB, 2},
   425  		"Mul":    {token.MUL, 2},
   426  		"Quo":    {token.QUO, 2},
   427  		"Rem":    {token.REM, 2},
   428  		"Or":     {token.OR, 2},
   429  		"Xor":    {token.XOR, 2},
   430  		"And":    {token.AND, 2},
   431  		"AndNot": {token.AND_NOT, 2},
   432  
   433  		"LOr":  {token.LOR, 2},
   434  		"LAnd": {token.LAND, 2},
   435  
   436  		"Lsh": {token.SHL, 2},
   437  		"Rsh": {token.SHR, 2},
   438  
   439  		"LT": {token.LSS, 2},
   440  		"LE": {token.LEQ, 2},
   441  		"GT": {token.GTR, 2},
   442  		"GE": {token.GEQ, 2},
   443  		"EQ": {token.EQL, 2},
   444  		"NE": {token.NEQ, 2},
   445  
   446  		"Neg":  {token.SUB, 1},
   447  		"Dup":  {token.ADD, 1},
   448  		"Not":  {token.XOR, 1},
   449  		"LNot": {token.NOT, 1},
   450  		"Recv": {token.ARROW, 1},
   451  		"Addr": {token.AND, 1},
   452  	}
   453  )
   454  
   455  func toFuncCall(pkg *Package, fn *internal.Elem, args []*internal.Elem, flags InstrFlags) *internal.Elem {
   456  	ret, err := matchFuncCall(pkg, fn, args, flags)
   457  	if err != nil {
   458  		panic(err)
   459  	}
   460  	return ret
   461  }
   462  
   463  func unaryOp(pkg *Package, tok token.Token, args []*internal.Elem) constant.Value {
   464  	if len(args) == 1 {
   465  		if a := args[0].CVal; a != nil {
   466  			var prec uint
   467  			if isUnsigned(args[0].Type) {
   468  				prec = uint(pkg.Sizeof(args[0].Type) * 8)
   469  			}
   470  			return constant.UnaryOp(tok, a, prec)
   471  		}
   472  	}
   473  	return nil
   474  }
   475  
   476  func isUnsigned(typ types.Type) bool {
   477  retry:
   478  	switch t := typ.(type) {
   479  	case *types.Basic:
   480  		return (t.Info() & types.IsUnsigned) != 0
   481  	case *types.Named:
   482  		typ = t.Underlying()
   483  		goto retry
   484  	}
   485  	return false
   486  }
   487  
   488  func binaryOp(cb *CodeBuilder, tok token.Token, args []*internal.Elem) constant.Value {
   489  	if len(args) == 2 {
   490  		if a, b := args[0].CVal, args[1].CVal; a != nil && b != nil {
   491  			if tok == token.QUO && isNormalInt(cb, args[0]) && isNormalInt(cb, args[1]) {
   492  				tok = token.QUO_ASSIGN // issue #805
   493  			}
   494  			return doBinaryOp(a, tok, b)
   495  		}
   496  	}
   497  	return nil
   498  }
   499  
   500  func isBool(cb *CodeBuilder, arg *internal.Elem) bool { // is bool
   501  	return isBasicKind(cb, arg, types.IsBoolean)
   502  }
   503  
   504  func isNormalInt(cb *CodeBuilder, arg *internal.Elem) bool { // is integer but not bigint
   505  	return isBasicKind(cb, arg, types.IsInteger)
   506  }
   507  
   508  func isBasicKind(cb *CodeBuilder, arg *internal.Elem, kind types.BasicInfo) bool {
   509  	argType := arg.Type
   510  retry:
   511  	switch t := argType.(type) {
   512  	case *types.Basic:
   513  		return (t.Info() & kind) != 0
   514  	case *types.Named:
   515  		argType = cb.getUnderlying(t)
   516  		goto retry
   517  	}
   518  	return false
   519  }
   520  
   521  func doBinaryOp(a constant.Value, tok token.Token, b constant.Value) constant.Value {
   522  	switch binaryOpKinds[tok] {
   523  	case binaryOpNormal:
   524  		return constant.BinaryOp(a, tok, b)
   525  	case binaryOpCompare:
   526  		return constant.MakeBool(constant.Compare(a, tok, b))
   527  	default:
   528  		a, b = constant.ToInt(a), constant.ToInt(b)
   529  		if s, exact := constant.Int64Val(b); exact {
   530  			return constant.Shift(a, tok, uint(s))
   531  		}
   532  		panic("constant value is overflow")
   533  	}
   534  }
   535  
   536  const (
   537  	binaryOpNormal = iota
   538  	binaryOpCompare
   539  	binaryOpShift
   540  )
   541  
   542  var (
   543  	binaryOpKinds = [...]int{
   544  		token.ADD: 0, // +
   545  		token.SUB: 0, // -
   546  		token.MUL: 0, // *
   547  		token.QUO: 0, // /
   548  		token.REM: 0, // %
   549  
   550  		token.AND:     0,             // &
   551  		token.OR:      0,             // |
   552  		token.XOR:     0,             // ^
   553  		token.AND_NOT: 0,             // &^
   554  		token.SHL:     binaryOpShift, // <<
   555  		token.SHR:     binaryOpShift, // >>
   556  
   557  		token.LAND: 0, // &&
   558  		token.LOR:  0, // ||
   559  
   560  		token.LSS: binaryOpCompare,
   561  		token.LEQ: binaryOpCompare,
   562  		token.GTR: binaryOpCompare,
   563  		token.GEQ: binaryOpCompare,
   564  		token.EQL: binaryOpCompare,
   565  		token.NEQ: binaryOpCompare,
   566  	}
   567  )
   568  
   569  func getParamLen(sig *types.Signature) int {
   570  	n := sig.Params().Len()
   571  	if sig.Recv() != nil {
   572  		n++
   573  	}
   574  	return n
   575  }
   576  
   577  func getParam(sig *types.Signature, i int) *types.Var {
   578  	if sig.Recv() != nil {
   579  		i--
   580  	}
   581  	if i < 0 {
   582  		return sig.Recv()
   583  	}
   584  	return sig.Params().At(i)
   585  }
   586  
   587  func getParam1st(sig *types.Signature) int {
   588  	if sig.Recv() != nil {
   589  		return 1
   590  	}
   591  	return 0
   592  }
   593  
   594  // TODO: check if fn.recv != nil
   595  func matchFuncCall(pkg *Package, fn *internal.Elem, args []*internal.Elem, flags InstrFlags) (ret *internal.Elem, err error) {
   596  	fnType := fn.Type
   597  	if debugMatch {
   598  		ft := fnType
   599  		if t, ok := fnType.(*types.Signature); ok {
   600  			if ftex, ok := CheckSigFuncEx(t); ok {
   601  				ft = ftex
   602  			}
   603  		}
   604  		log.Println("==> MatchFuncCall", ft, "args:", len(args), "flags:", flags)
   605  	}
   606  	var it *instantiated
   607  	var sig *types.Signature
   608  	var cval constant.Value
   609  retry:
   610  	switch t := fnType.(type) {
   611  	case *types.Signature:
   612  		if t.TypeParams() != nil {
   613  			if (flags & instrFlagGopxFunc) == 0 {
   614  				rt, err := inferFunc(pkg, fn, t, nil, args, flags)
   615  				if err != nil {
   616  					return nil, pkg.cb.newCodeError(getSrcPos(fn.Src), err.Error())
   617  				}
   618  				sig = rt.(*types.Signature)
   619  				if debugMatch {
   620  					log.Println("==> InferFunc", sig)
   621  				}
   622  			} else {
   623  				fn, sig, args, err = boundTypeParams(pkg, fn, t, args, flags)
   624  				if err != nil {
   625  					return
   626  				}
   627  				flags &= ^instrFlagGopxFunc
   628  			}
   629  			break
   630  		}
   631  		if fex, ok := CheckFuncEx(t); ok {
   632  			switch ft := fex.(type) {
   633  			case *TyOverloadFunc:
   634  				backup := backupArgs(args)
   635  				for _, o := range ft.Funcs {
   636  					if ret, err = matchFuncCall(pkg, chgObject(pkg, o, fn), args, flags); err == nil {
   637  						if ret.CVal == nil && isUntyped(pkg, ret.Type) {
   638  							ret.CVal = builtinCall(fn, args)
   639  						}
   640  						if pkg.cb.rec != nil {
   641  							pkg.cb.rec.Call(fn.Src, o)
   642  						}
   643  						return
   644  					}
   645  					restoreArgs(args, backup)
   646  				}
   647  				return
   648  			case *TyOverloadMethod:
   649  				backup := backupArgs(args)
   650  				for _, o := range ft.Methods {
   651  					mfn := *fn
   652  					if (flags & instrFlagBinaryOp) != 0 { // from cb.BinaryOp
   653  						mfn.Type = methodToFuncSig(pkg, o, &mfn)
   654  					} else {
   655  						mfn.Val.(*ast.SelectorExpr).Sel = ident(o.Name())
   656  						mfn.Type = methodCallSig(o.Type())
   657  					}
   658  					if ret, err = matchFuncCall(pkg, &mfn, args, flags); err == nil {
   659  						fn.Val, fn.Type = mfn.Val, mfn.Type
   660  						if pkg.cb.rec != nil {
   661  							pkg.cb.rec.Call(fn.Src, o)
   662  						}
   663  						return
   664  					}
   665  					restoreArgs(args, backup)
   666  				}
   667  				return
   668  			case *TyTemplateRecvMethod:
   669  				err = errTemplateRecvMethodCallUnexpected
   670  				if denoted := getDenoted(fn.Val); denoted != nil {
   671  					if recv, ok := denoted.Data.(*Element); ok {
   672  						backup := backupArgs(args)
   673  						for i := 0; i < 2; i++ {
   674  							tfn := toObject(pkg, ft.Func, fn.Src)
   675  							targs := make([]*internal.Elem, len(args)+1)
   676  							targ0 := *recv
   677  							if i == 1 {
   678  								targ0.Val = &ast.UnaryExpr{Op: token.AND, X: targ0.Val}
   679  								targ0.Type = types.NewPointer(targ0.Type)
   680  							}
   681  							targs[0] = &targ0
   682  							for j, arg := range args {
   683  								targs[j+1] = arg
   684  							}
   685  							if ret, err = matchFuncCall(pkg, tfn, targs, flags|instrFlagGoptFunc); err == nil {
   686  								if pkg.cb.rec != nil {
   687  									if _, ok := CheckFuncEx(ft.Func.Type().(*types.Signature)); !ok {
   688  										pkg.cb.rec.Call(fn.Src, ft.Func)
   689  									}
   690  								}
   691  								return
   692  							}
   693  							if isPointer(targ0.Type) {
   694  								break
   695  							}
   696  							restoreArgs(args, backup)
   697  						}
   698  					}
   699  				}
   700  				return
   701  			case *tyTypeAsParams:
   702  				return matchFuncCall(pkg, chgObject(pkg, ft.obj, fn), args, flags|instrFlagGopxFunc)
   703  			}
   704  		} else if IsCSignature(t) {
   705  			sig = types.NewSignatureType(nil, nil, nil, t.Params(), t.Results(), t.Variadic())
   706  		} else {
   707  			sig = t
   708  		}
   709  	case *TemplateSignature: // template function
   710  		sig, it = t.instantiate()
   711  		if t.isUnaryOp() {
   712  			cval = unaryOp(pkg, t.tok(), args)
   713  		} else if t.isOp() {
   714  			cval = binaryOp(&pkg.cb, t.tok(), args)
   715  		} else if t.hasApproxType() {
   716  			flags |= instrFlagApproxType
   717  		}
   718  	case *TyInstruction:
   719  		return t.instr.Call(pkg, args, flags, fn.Src)
   720  	case *TypeType: // type convert
   721  		if on, ok := CheckOverloadNamed(t.typ); ok {
   722  			return matchOverloadNamedTypeCast(pkg, on.Obj, fn.Src, args, flags)
   723  		}
   724  		return matchTypeCast(pkg, t.typ, fn, args, flags)
   725  	case *types.Named:
   726  		fnType = pkg.cb.getUnderlying(t)
   727  		goto retry
   728  	case *inferFuncType:
   729  		sig = t.InstanceWithArgs(args, flags)
   730  		if debugMatch {
   731  			log.Println("==> InferFunc", sig)
   732  		}
   733  	default:
   734  		src, pos := pkg.cb.loadExpr(fn.Src)
   735  		pkg.cb.panicCodeErrorf(pos, "cannot call non-function %s (type %v)", src, fn.Type)
   736  	}
   737  	if err = matchFuncType(pkg, args, flags, sig, fn); err != nil {
   738  		return
   739  	}
   740  	tyRet := toRetType(sig.Results(), it)
   741  	if cval != nil { // untyped bigint/bigrat
   742  		if ret, ok := untypeBig(pkg, cval, tyRet); ok {
   743  			return ret, nil
   744  		}
   745  	}
   746  	switch t := fn.Val.(type) {
   747  	case *ast.BinaryExpr:
   748  		t.X, t.Y = checkParenExpr(args[0].Val), checkParenExpr(args[1].Val)
   749  		return &internal.Elem{Val: t, Type: tyRet, CVal: cval}, nil
   750  	case *ast.UnaryExpr:
   751  		t.X = args[0].Val
   752  		return &internal.Elem{Val: t, Type: tyRet, CVal: cval}, nil
   753  	}
   754  	var valArgs []ast.Expr
   755  	var recv = getParam1st(sig)
   756  	if n := len(args); n > recv { // for method, args[0] is already in fn.Val
   757  		valArgs = make([]ast.Expr, n-recv)
   758  		for i := recv; i < n; i++ {
   759  			valArgs[i-recv] = args[i].Val
   760  		}
   761  	}
   762  	return &internal.Elem{
   763  		Type: tyRet, CVal: cval,
   764  		Val: &ast.CallExpr{
   765  			Fun: fn.Val, Args: valArgs, Ellipsis: token.Pos(flags & InstrFlagEllipsis)},
   766  	}, nil
   767  }
   768  
   769  func matchOverloadNamedTypeCast(pkg *Package, t *types.TypeName, src ast.Node, args []*internal.Elem, flags InstrFlags) (ret *internal.Elem, err error) {
   770  	cast := gopxPrefix + t.Name() + "_Cast"
   771  	o := t.Pkg().Scope().Lookup(cast)
   772  	if o == nil {
   773  		err := pkg.cb.newCodeErrorf(getSrcPos(src), "typecast %v not found", t.Type())
   774  		return nil, err
   775  	}
   776  	fn := toObject(pkg, o, src)
   777  	return matchFuncCall(pkg, fn, args, flags|instrFlagGopxFunc)
   778  }
   779  
   780  func matchTypeCast(pkg *Package, typ types.Type, fn *internal.Elem, args []*internal.Elem, flags InstrFlags) (ret *internal.Elem, err error) {
   781  	fnVal := fn.Val
   782  	switch typ.(type) {
   783  	case *types.Pointer, *types.Chan:
   784  		fnVal = &ast.ParenExpr{X: fnVal}
   785  	}
   786  	if len(args) == 1 && ConvertibleTo(pkg, args[0].Type, typ) {
   787  		if args[0].CVal != nil {
   788  			if t, ok := typ.(*types.Named); ok {
   789  				o := t.Obj()
   790  				if at := o.Pkg(); at != nil {
   791  					tname := o.Name()
   792  					if checkUntypedOverflows(at.Scope(), tname, args[0]) {
   793  						src, pos := pkg.cb.loadExpr(args[0].Src)
   794  						err = pkg.cb.newCodeError(pos, fmt.Sprintf("cannot convert %v (untyped int constant %v) to type %v", src, args[0].CVal, tname))
   795  						return
   796  					}
   797  				}
   798  			}
   799  		}
   800  		goto finish
   801  	}
   802  
   803  	switch t := typ.(type) {
   804  	case *types.Basic:
   805  		if len(args) == 1 {
   806  			if ret, ok := CastFromBool(&pkg.cb, typ, args[0]); ok {
   807  				return ret, nil
   808  			}
   809  		}
   810  	case *types.Named:
   811  		o := t.Obj()
   812  		if at := o.Pkg(); at != nil {
   813  			tname := o.Name()
   814  			scope := at.Scope()
   815  			name := tname + "_Cast"
   816  			if cast := scope.Lookup(name); cast != nil {
   817  				if len(args) == 1 && args[0].CVal != nil {
   818  					if checkUntypedOverflows(scope, tname, args[0]) {
   819  						src, pos := pkg.cb.loadExpr(args[0].Src)
   820  						err = pkg.cb.newCodeError(pos, fmt.Sprintf("cannot convert %v (untyped int constant %v) to type %v", src, args[0].CVal, tname))
   821  						return
   822  					}
   823  				}
   824  				castFn := &internal.Elem{Val: toObjectExpr(pkg, cast), Type: cast.Type()}
   825  				if ret, err = matchFuncCall(pkg, castFn, args, flags); err == nil {
   826  					if ret.CVal == nil && len(args) == 1 && checkUntypedType(scope, tname) {
   827  						ret.CVal = args[0].CVal
   828  					}
   829  					return
   830  				}
   831  			}
   832  		}
   833  	}
   834  
   835  	switch len(args) {
   836  	case 1:
   837  		arg := args[0]
   838  		switch t := arg.Type.(type) {
   839  		case *types.Named:
   840  			if m := lookupMethod(t, "Gop_Rcast"); m != nil {
   841  				switch mt := m.Type().(type) {
   842  				case *types.Signature:
   843  					if funcs, ok := CheckOverloadMethod(mt); ok {
   844  						for _, o := range funcs {
   845  							if ret, err = matchRcast(pkg, arg, o, typ, flags); err == nil {
   846  								return
   847  							}
   848  						}
   849  					} else if ret, err = matchRcast(pkg, arg, m, typ, flags); err == nil {
   850  						return
   851  					}
   852  				}
   853  			}
   854  		}
   855  	case 0:
   856  		// T() means to return zero value of T
   857  		return pkg.cb.ZeroLit(typ).stk.Pop(), nil
   858  	}
   859  
   860  finish:
   861  	valArgs := make([]ast.Expr, len(args))
   862  	for i, v := range args { // TODO: type check
   863  		valArgs[i] = v.Val
   864  	}
   865  	ret = &internal.Elem{
   866  		Val:  &ast.CallExpr{Fun: fnVal, Args: valArgs, Ellipsis: token.Pos(flags & InstrFlagEllipsis)},
   867  		Type: typ,
   868  	}
   869  	if len(args) == 1 { // TODO: const value may changed by type-convert
   870  		ret.CVal = args[0].CVal
   871  	}
   872  	return
   873  }
   874  
   875  func matchRcast(pkg *Package, fn *internal.Elem, m types.Object, typ types.Type, flags InstrFlags) (ret *internal.Elem, err error) {
   876  	sig := m.Type().(*types.Signature)
   877  	if sig.Params().Len() != 0 {
   878  		log.Panicf("TODO: method %v should haven't no arguments\n", m)
   879  	}
   880  	n := 1
   881  	if (flags & InstrFlagTwoValue) != 0 {
   882  		n = 2
   883  	}
   884  	results := sig.Results()
   885  	if results.Len() != n {
   886  		return nil, fmt.Errorf("TODO: %v should return %d results", m, n)
   887  	}
   888  	if types.Identical(results.At(0).Type(), typ) {
   889  		return pkg.cb.Val(fn).MemberVal(m.Name()).CallWith(0, flags).stk.Pop(), nil
   890  	}
   891  	return nil, &MatchError{
   892  		Src: fn.Src, Arg: fn.Type, Param: typ, At: "Gop_Rcast",
   893  		Fset: pkg.cb.fset, intr: pkg.cb.interp,
   894  	}
   895  }
   896  
   897  // CastFromBool tries to cast a bool expression into integer. typ must be an integer type.
   898  func CastFromBool(cb *CodeBuilder, typ types.Type, v *Element) (ret *Element, ok bool) {
   899  	if ok = isBool(cb, v); ok {
   900  		if v.CVal != nil { // untyped bool
   901  			var val int
   902  			if constant.BoolVal(v.CVal) {
   903  				val = 1
   904  			}
   905  			return toExpr(nil, val, v.Src), true
   906  		}
   907  		pkg := cb.pkg
   908  		results := types.NewTuple(types.NewParam(token.NoPos, pkg.Types, "", typ))
   909  		ret = cb.NewClosure(nil, results, false).BodyStart(pkg).
   910  			If().Val(v).Then().Val(1).Return(1).
   911  			Else().Val(0).Return(1).
   912  			End().
   913  			End().Call(0).
   914  			stk.Pop()
   915  	}
   916  	return
   917  }
   918  
   919  func isPointer(typ types.Type) bool {
   920  	_, ok := typ.(*types.Pointer)
   921  	return ok
   922  }
   923  
   924  func checkParenExpr(x ast.Expr) ast.Expr {
   925  	switch v := x.(type) {
   926  	case *ast.CompositeLit:
   927  		return &ast.ParenExpr{X: x}
   928  	case *ast.SelectorExpr:
   929  		v.X = checkParenExpr(v.X)
   930  	}
   931  	return x
   932  }
   933  
   934  type backupElem struct {
   935  	typ types.Type
   936  	val ast.Expr
   937  }
   938  
   939  func backupArgs(args []*internal.Elem) []backupElem {
   940  	backup := make([]backupElem, len(args))
   941  	for i, arg := range args {
   942  		backup[i].typ, backup[i].val = arg.Type, arg.Val
   943  	}
   944  	return backup
   945  }
   946  
   947  func restoreArgs(args []*internal.Elem, backup []backupElem) {
   948  	for i, arg := range args {
   949  		arg.Type, arg.Val = backup[i].typ, backup[i].val
   950  	}
   951  }
   952  
   953  func copyArgs(args []*internal.Elem) []*internal.Elem {
   954  	backup := make([]*internal.Elem, len(args))
   955  	copy(backup, args)
   956  	return backup
   957  }
   958  
   959  func untypeBig(pkg *Package, cval constant.Value, tyRet types.Type) (*internal.Elem, bool) {
   960  	switch tyRet {
   961  	case pkg.utBigInt:
   962  		var val *big.Int
   963  		switch v := constant.Val(cval).(type) {
   964  		case int64:
   965  			val = big.NewInt(v)
   966  		case *big.Int:
   967  			val = v
   968  		case *big.Rat:
   969  			return pkg.cb.UntypedBigRat(v).stk.Pop(), true
   970  		default:
   971  			panic("unexpected constant")
   972  		}
   973  		return pkg.cb.UntypedBigInt(val).stk.Pop(), true
   974  	case pkg.utBigRat:
   975  		var val *big.Rat
   976  		switch v := constant.Val(cval).(type) {
   977  		case int64:
   978  			val = big.NewRat(v, 1)
   979  		case *big.Rat:
   980  			val = v
   981  		case *big.Int:
   982  			val = new(big.Rat).SetInt(v)
   983  		default:
   984  			panic("unexpected constant")
   985  		}
   986  		return pkg.cb.UntypedBigRat(val).stk.Pop(), true
   987  	case types.Typ[types.UntypedBool], types.Typ[types.Bool]:
   988  		return &internal.Elem{
   989  			Val: boolean(constant.BoolVal(cval)), Type: tyRet, CVal: cval,
   990  		}, true
   991  	}
   992  	return nil, false
   993  }
   994  
   995  func toRetType(t *types.Tuple, it *instantiated) types.Type {
   996  	if t == nil {
   997  		return nil
   998  	} else if t.Len() == 1 {
   999  		return it.normalize(t.At(0).Type())
  1000  	}
  1001  	return it.normalizeTuple(t)
  1002  }
  1003  
  1004  func matchFuncType(
  1005  	pkg *Package, args []*internal.Elem, flags InstrFlags, sig *types.Signature, fn *internal.Elem) error {
  1006  	if (flags & InstrFlagTwoValue) != 0 {
  1007  		if n := sig.Results().Len(); n != 2 {
  1008  			caller, pos := getFunExpr(fn)
  1009  			return pkg.cb.newCodeErrorf(pos, "assignment mismatch: 2 variables but %v returns %v values", caller, n)
  1010  		}
  1011  	}
  1012  	var t *types.Tuple
  1013  	n := len(args)
  1014  	if len(args) == 1 && checkTuple(&t, args[0].Type) {
  1015  		n = t.Len()
  1016  		args = make([]*internal.Elem, n)
  1017  		for i := 0; i < n; i++ {
  1018  			args[i] = &internal.Elem{Type: t.At(i).Type()}
  1019  		}
  1020  	} else if (flags&instrFlagApproxType) != 0 && n > 0 {
  1021  		if typ, ok := args[0].Type.(*types.Named); ok {
  1022  			switch t := pkg.cb.getUnderlying(typ).(type) {
  1023  			case *types.Slice, *types.Map, *types.Chan:
  1024  				args[0].Type = t
  1025  			}
  1026  		}
  1027  	}
  1028  	var at interface{}
  1029  	if fn == nil {
  1030  		at = "closure argument" // fn = nil means it is a closure
  1031  	} else {
  1032  		at = func() string {
  1033  			src, _ := pkg.cb.loadExpr(fn.Src)
  1034  			return "argument to " + src
  1035  		}
  1036  	}
  1037  	if sig.Variadic() {
  1038  		if (flags & InstrFlagEllipsis) == 0 {
  1039  			n1 := getParamLen(sig) - 1
  1040  			if n < n1 {
  1041  				caller, pos := getFunExpr(fn)
  1042  				return pkg.cb.newCodeErrorf(pos, "not enough arguments in call to %v\n\thave (%v)\n\twant %v",
  1043  					caller, getTypes(args), sig.Params())
  1044  			}
  1045  			tyVariadic, ok := getParam(sig, n1).Type().(*types.Slice)
  1046  			if !ok {
  1047  				return errors.New("TODO: tyVariadic not a slice")
  1048  			}
  1049  			if err := matchFuncArgs(pkg, args[:n1], sig, at); err != nil {
  1050  				return err
  1051  			}
  1052  			return matchElemType(pkg, args[n1:], tyVariadic.Elem(), at)
  1053  		}
  1054  	} else if (flags & InstrFlagEllipsis) != 0 {
  1055  		caller, pos := getFunExpr(fn)
  1056  		return pkg.cb.newCodeErrorf(pos, "cannot use ... in call to non-variadic %v", caller)
  1057  	}
  1058  	if nreq := getParamLen(sig); nreq != n {
  1059  		fewOrMany := "not enough"
  1060  		if n > nreq {
  1061  			fewOrMany = "too many"
  1062  		}
  1063  		caller, pos := getFunExpr(fn)
  1064  		return pkg.cb.newCodeErrorf(pos,
  1065  			"%s arguments in call to %s\n\thave (%v)\n\twant %v", fewOrMany, caller, getTypes(args), sig.Params())
  1066  	}
  1067  	return matchFuncArgs(pkg, args, sig, at)
  1068  }
  1069  
  1070  func matchFuncArgs(
  1071  	pkg *Package, args []*internal.Elem, sig *types.Signature, at interface{}) error {
  1072  	for i, arg := range args {
  1073  		if err := matchType(pkg, arg, getParam(sig, i).Type(), at); err != nil {
  1074  			return err
  1075  		}
  1076  	}
  1077  	return nil
  1078  }
  1079  
  1080  func checkFuncResults(pkg *Package, rets []*internal.Elem, results *types.Tuple, src ast.Node) {
  1081  	n := len(rets)
  1082  	need := results.Len()
  1083  	switch n {
  1084  	case 0:
  1085  		if need > 0 && isUnnamedParams(results) {
  1086  			pos := getSrcPos(src)
  1087  			pkg.cb.panicCodeErrorf(
  1088  				pos, "not enough arguments to return\n\thave ()\n\twant %v", results)
  1089  		}
  1090  		return
  1091  	case 1:
  1092  		if t, ok := rets[0].Type.(*types.Tuple); ok {
  1093  			if n1 := t.Len(); n1 != need {
  1094  				fewOrMany := "few"
  1095  				if n1 > need {
  1096  					fewOrMany = "many"
  1097  				}
  1098  				pos := getSrcPos(src)
  1099  				pkg.cb.panicCodeErrorf(
  1100  					pos, "too %s arguments to return\n\thave %v\n\twant %v", fewOrMany, t, results)
  1101  			}
  1102  			for i := 0; i < need; i++ {
  1103  				arg := &internal.Elem{Type: t.At(i).Type(), Src: src}
  1104  				if err := matchType(pkg, arg, results.At(i).Type(), "return argument"); err != nil {
  1105  					panic(err)
  1106  				}
  1107  			}
  1108  			return
  1109  		}
  1110  	}
  1111  	if n == need {
  1112  		for i := 0; i < need; i++ {
  1113  			if err := matchType(pkg, rets[i], results.At(i).Type(), "return argument"); err != nil {
  1114  				panic(err)
  1115  			}
  1116  		}
  1117  		return
  1118  	}
  1119  	fewOrMany := "few"
  1120  	if n > need {
  1121  		fewOrMany = "many"
  1122  	}
  1123  	pos := getSrcPos(src)
  1124  	pkg.cb.panicCodeErrorf(
  1125  		pos, "too %s arguments to return\n\thave (%v)\n\twant %v", fewOrMany, getTypes(rets), results)
  1126  }
  1127  
  1128  func getTypes(rets []*internal.Elem) string {
  1129  	typs := make([]string, len(rets))
  1130  	for i, ret := range rets {
  1131  		typs[i] = ret.Type.String()
  1132  	}
  1133  	return strings.Join(typs, ", ")
  1134  }
  1135  
  1136  func isUnnamedParams(t *types.Tuple) bool {
  1137  	if t == nil {
  1138  		return true
  1139  	}
  1140  	for i, n := 0, t.Len(); i < n; i++ {
  1141  		if t.At(i).Name() == "" {
  1142  			return true
  1143  		}
  1144  	}
  1145  	return false
  1146  }
  1147  
  1148  func matchElemType(pkg *Package, vals []*internal.Elem, elt types.Type, at interface{}) error {
  1149  	for _, val := range vals {
  1150  		if err := matchType(pkg, val, elt, at); err != nil {
  1151  			return err
  1152  		}
  1153  	}
  1154  	return nil
  1155  }
  1156  
  1157  func checkAssignType(pkg *Package, varRef types.Type, val *internal.Elem) {
  1158  	if rt, ok := varRef.(*refType); ok {
  1159  		if err := matchType(pkg, val, rt.typ, "assignment"); err != nil {
  1160  			panic(err)
  1161  		}
  1162  	} else if varRef == nil { // underscore
  1163  		// do nothing
  1164  		if t, ok := val.Type.(*inferFuncType); ok {
  1165  			t.Instance()
  1166  		}
  1167  	} else {
  1168  		panic("TODO: unassignable")
  1169  	}
  1170  }
  1171  
  1172  func checkAssign(pkg *Package, ref *internal.Elem, val types.Type, at string) {
  1173  	if rt, ok := ref.Type.(*refType); ok {
  1174  		elem := &internal.Elem{Type: val}
  1175  		if err := matchType(pkg, elem, rt.typ, at); err != nil {
  1176  			src, pos := pkg.cb.loadExpr(ref.Src)
  1177  			pkg.cb.panicCodeErrorf(
  1178  				pos, "cannot assign type %v to %s (type %v) in %s", val, src, rt.typ, at)
  1179  		}
  1180  	} else if ref.Type == nil { // underscore
  1181  		// do nothing
  1182  	} else {
  1183  		panic("TODO: unassignable")
  1184  	}
  1185  }
  1186  
  1187  type MatchError struct {
  1188  	Fset  dbgPositioner
  1189  	Src   ast.Node
  1190  	Arg   types.Type
  1191  	Param types.Type
  1192  	At    interface{}
  1193  
  1194  	intr  NodeInterpreter
  1195  	fstmt bool
  1196  }
  1197  
  1198  func strval(at interface{}) string {
  1199  	switch v := at.(type) {
  1200  	case string:
  1201  		return v
  1202  	case func() string:
  1203  		return v()
  1204  	default:
  1205  		panic("strval unexpected: unknown type")
  1206  	}
  1207  }
  1208  
  1209  func (p *MatchError) Message(fileLine string) string {
  1210  	if p.fstmt {
  1211  		return fmt.Sprintf(
  1212  			"%scannot use %v value as type %v in %s", fileLine, p.Arg, p.Param, strval(p.At))
  1213  	}
  1214  	src := ""
  1215  	if p.Src != nil {
  1216  		src = p.intr.LoadExpr(p.Src)
  1217  	}
  1218  	return fmt.Sprintf(
  1219  		"%scannot use %s (type %v) as type %v in %s", fileLine, src, p.Arg, p.Param, strval(p.At))
  1220  }
  1221  
  1222  func (p *MatchError) Pos() token.Pos {
  1223  	return getSrcPos(p.Src)
  1224  }
  1225  
  1226  func (p *MatchError) Error() string {
  1227  	pos := p.Fset.Position(p.Pos())
  1228  	return p.Message(pos.String() + ": ")
  1229  }
  1230  
  1231  // TODO: use matchType to all assignable check
  1232  func matchType(pkg *Package, arg *internal.Elem, param types.Type, at interface{}) error {
  1233  	if debugMatch {
  1234  		cval := ""
  1235  		if arg.CVal != nil {
  1236  			cval = fmt.Sprintf(" (%v)", arg.CVal)
  1237  		}
  1238  		log.Printf("==> MatchType %v%s, %v\n", arg.Type, cval, param)
  1239  	}
  1240  	if arg.Type == nil {
  1241  		src, pos := pkg.cb.loadExpr(arg.Src)
  1242  		return pkg.cb.newCodeError(pos, fmt.Sprintf("%v (no value) used as value", src))
  1243  	}
  1244  	// check untyped big int/rat/flt => interface
  1245  	switch arg.Type {
  1246  	case pkg.utBigInt, pkg.utBigRat, pkg.utBigFlt:
  1247  		typ := param
  1248  	retry:
  1249  		switch t := typ.(type) {
  1250  		case *types.Interface:
  1251  			arg.Type = DefaultConv(pkg, arg.Type, arg)
  1252  			if t.NumMethods() == 0 {
  1253  				return nil
  1254  			}
  1255  		case *types.Named:
  1256  			typ = t.Underlying()
  1257  			goto retry
  1258  		}
  1259  	}
  1260  	switch t := param.(type) {
  1261  	case *types.Named:
  1262  		if t2, ok := arg.Type.(*types.Basic); ok {
  1263  			if t == pkg.utBigInt {
  1264  				switch t2.Kind() {
  1265  				case types.UntypedInt:
  1266  					val, _ := new(big.Int).SetString(arg.CVal.ExactString(), 10)
  1267  					arg.Val = pkg.cb.UntypedBigInt(val).stk.Pop().Val
  1268  					return nil
  1269  				case types.UntypedFloat:
  1270  					val, ok := new(big.Int).SetString(arg.CVal.ExactString(), 10)
  1271  					if !ok {
  1272  						code, pos := pkg.cb.loadExpr(arg.Src)
  1273  						pkg.cb.panicCodeErrorf(pos, "cannot convert %v (untyped float constant) to %v", code, t)
  1274  					}
  1275  					arg.Val = pkg.cb.UntypedBigInt(val).stk.Pop().Val
  1276  					return nil
  1277  				}
  1278  			}
  1279  		}
  1280  	case *unboundType: // variable to bound type
  1281  		if t2, ok := arg.Type.(*unboundType); ok {
  1282  			if t2.tBound == nil {
  1283  				if t == t2 {
  1284  					return nil
  1285  				}
  1286  				return fmt.Errorf("TODO: can't match two unboundTypes")
  1287  			}
  1288  			arg.Type = t2.tBound
  1289  		}
  1290  		if t.tBound == nil {
  1291  			arg.Type = DefaultConv(pkg, arg.Type, arg)
  1292  			t.boundTo(pkg, arg.Type)
  1293  		}
  1294  		param = t.tBound
  1295  	case *unboundMapElemType:
  1296  		if t2, ok := arg.Type.(*unboundType); ok {
  1297  			if t2.tBound == nil {
  1298  				panic("TODO: don't pass unbound variables")
  1299  			}
  1300  			arg.Type = t2.tBound
  1301  		}
  1302  		arg.Type = DefaultConv(pkg, arg.Type, arg)
  1303  		mapTy := types.NewMap(Default(pkg, t.key), arg.Type)
  1304  		t.typ.boundTo(pkg, mapTy)
  1305  		return nil
  1306  	default:
  1307  		if isUnboundParam(param) {
  1308  			if t, ok := arg.Type.(*unboundType); ok {
  1309  				if t.tBound == nil {
  1310  					// panic("TODO: don't pass unbound variables as template function params.")
  1311  					return nil
  1312  				}
  1313  				arg.Type = t.tBound
  1314  			}
  1315  			return boundType(pkg, arg.Type, param, arg)
  1316  		}
  1317  	}
  1318  	if AssignableConv(pkg, arg.Type, param, arg) {
  1319  		return nil
  1320  	}
  1321  	return &MatchError{
  1322  		Src: arg.Src, Arg: arg.Type, Param: param, At: at, fstmt: arg.Val == nil,
  1323  		Fset: pkg.cb.fset, intr: pkg.cb.interp,
  1324  	}
  1325  }
  1326  
  1327  // -----------------------------------------------------------------------------
  1328  
  1329  func boundElementType(pkg *Package, elts []*internal.Elem, base, max, step int) types.Type {
  1330  	var tBound types.Type
  1331  	for i := base; i < max; i += step {
  1332  		e := elts[i]
  1333  		if tBound == e.Type {
  1334  			// nothing to do
  1335  		} else if tBound == nil || AssignableTo(pkg, tBound, e.Type) {
  1336  			tBound = e.Type
  1337  		} else if !AssignableTo(pkg, e.Type, tBound) {
  1338  			return TyEmptyInterface
  1339  		}
  1340  	}
  1341  	return tBound
  1342  }
  1343  
  1344  func constantToBigInt(v constant.Value) (*big.Int, bool) {
  1345  	if v.Kind() == constant.Int {
  1346  		return new(big.Int).SetString(v.String(), 10)
  1347  	}
  1348  	return new(big.Int).SetString(v.ExactString(), 10)
  1349  }
  1350  
  1351  func checkUntypedType(scope *types.Scope, tname string) bool {
  1352  	c, ok := scope.Lookup(tname + "_IsUntyped").(*types.Const)
  1353  	if ok {
  1354  		if val := c.Val(); val != nil && val.Kind() == constant.Bool {
  1355  			return constant.BoolVal(val)
  1356  		}
  1357  	}
  1358  	return false
  1359  }
  1360  
  1361  func checkUntypedOverflows(scope *types.Scope, tname string, arg *internal.Elem) bool {
  1362  	cmax, ok1 := scope.Lookup(tname + "_Max").(*types.Const)
  1363  	cmin, ok2 := scope.Lookup(tname + "_Min").(*types.Const)
  1364  	if ok1 || ok2 {
  1365  		cv, ok := constantToBigInt(arg.CVal)
  1366  		if ok {
  1367  			if ok1 {
  1368  				if max, ok := constantToBigInt(cmax.Val()); ok {
  1369  					if cv.Cmp(max) > 0 {
  1370  						return true
  1371  					}
  1372  				}
  1373  			}
  1374  			if ok2 {
  1375  				if min, ok := constantToBigInt(cmin.Val()); ok {
  1376  					if cv.Cmp(min) < 0 {
  1377  						return true
  1378  					}
  1379  				}
  1380  			}
  1381  		}
  1382  	}
  1383  	return false
  1384  }
  1385  
  1386  // -----------------------------------------------------------------------------