...

Source file src/golang.org/x/tools/go/ssa/interp/ops.go

Documentation: golang.org/x/tools/go/ssa/interp

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package interp
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"go/constant"
    11  	"go/token"
    12  	"go/types"
    13  	"os"
    14  	"reflect"
    15  	"strings"
    16  	"sync"
    17  	"unsafe"
    18  
    19  	"golang.org/x/tools/go/ssa"
    20  	"golang.org/x/tools/internal/aliases"
    21  	"golang.org/x/tools/internal/typeparams"
    22  )
    23  
    24  // If the target program panics, the interpreter panics with this type.
    25  type targetPanic struct {
    26  	v value
    27  }
    28  
    29  func (p targetPanic) String() string {
    30  	return toString(p.v)
    31  }
    32  
    33  // If the target program calls exit, the interpreter panics with this type.
    34  type exitPanic int
    35  
    36  // constValue returns the value of the constant with the
    37  // dynamic type tag appropriate for c.Type().
    38  func constValue(c *ssa.Const) value {
    39  	if c.Value == nil {
    40  		return zero(c.Type()) // typed zero
    41  	}
    42  	// c is not a type parameter so it's underlying type is basic.
    43  
    44  	if t, ok := c.Type().Underlying().(*types.Basic); ok {
    45  		// TODO(adonovan): eliminate untyped constants from SSA form.
    46  		switch t.Kind() {
    47  		case types.Bool, types.UntypedBool:
    48  			return constant.BoolVal(c.Value)
    49  		case types.Int, types.UntypedInt:
    50  			// Assume sizeof(int) is same on host and target.
    51  			return int(c.Int64())
    52  		case types.Int8:
    53  			return int8(c.Int64())
    54  		case types.Int16:
    55  			return int16(c.Int64())
    56  		case types.Int32, types.UntypedRune:
    57  			return int32(c.Int64())
    58  		case types.Int64:
    59  			return c.Int64()
    60  		case types.Uint:
    61  			// Assume sizeof(uint) is same on host and target.
    62  			return uint(c.Uint64())
    63  		case types.Uint8:
    64  			return uint8(c.Uint64())
    65  		case types.Uint16:
    66  			return uint16(c.Uint64())
    67  		case types.Uint32:
    68  			return uint32(c.Uint64())
    69  		case types.Uint64:
    70  			return c.Uint64()
    71  		case types.Uintptr:
    72  			// Assume sizeof(uintptr) is same on host and target.
    73  			return uintptr(c.Uint64())
    74  		case types.Float32:
    75  			return float32(c.Float64())
    76  		case types.Float64, types.UntypedFloat:
    77  			return c.Float64()
    78  		case types.Complex64:
    79  			return complex64(c.Complex128())
    80  		case types.Complex128, types.UntypedComplex:
    81  			return c.Complex128()
    82  		case types.String, types.UntypedString:
    83  			if c.Value.Kind() == constant.String {
    84  				return constant.StringVal(c.Value)
    85  			}
    86  			return string(rune(c.Int64()))
    87  		}
    88  	}
    89  
    90  	panic(fmt.Sprintf("constValue: %s", c))
    91  }
    92  
    93  // fitsInt returns true if x fits in type int according to sizes.
    94  func fitsInt(x int64, sizes types.Sizes) bool {
    95  	intSize := sizes.Sizeof(types.Typ[types.Int])
    96  	if intSize < sizes.Sizeof(types.Typ[types.Int64]) {
    97  		maxInt := int64(1)<<((intSize*8)-1) - 1
    98  		minInt := -int64(1) << ((intSize * 8) - 1)
    99  		return minInt <= x && x <= maxInt
   100  	}
   101  	return true
   102  }
   103  
   104  // asInt64 converts x, which must be an integer, to an int64.
   105  //
   106  // Callers that need a value directly usable as an int should combine this with fitsInt().
   107  func asInt64(x value) int64 {
   108  	switch x := x.(type) {
   109  	case int:
   110  		return int64(x)
   111  	case int8:
   112  		return int64(x)
   113  	case int16:
   114  		return int64(x)
   115  	case int32:
   116  		return int64(x)
   117  	case int64:
   118  		return x
   119  	case uint:
   120  		return int64(x)
   121  	case uint8:
   122  		return int64(x)
   123  	case uint16:
   124  		return int64(x)
   125  	case uint32:
   126  		return int64(x)
   127  	case uint64:
   128  		return int64(x)
   129  	case uintptr:
   130  		return int64(x)
   131  	}
   132  	panic(fmt.Sprintf("cannot convert %T to int64", x))
   133  }
   134  
   135  // asUint64 converts x, which must be an unsigned integer, to a uint64
   136  // suitable for use as a bitwise shift count.
   137  func asUint64(x value) uint64 {
   138  	switch x := x.(type) {
   139  	case uint:
   140  		return uint64(x)
   141  	case uint8:
   142  		return uint64(x)
   143  	case uint16:
   144  		return uint64(x)
   145  	case uint32:
   146  		return uint64(x)
   147  	case uint64:
   148  		return x
   149  	case uintptr:
   150  		return uint64(x)
   151  	}
   152  	panic(fmt.Sprintf("cannot convert %T to uint64", x))
   153  }
   154  
   155  // asUnsigned returns the value of x, which must be an integer type, as its equivalent unsigned type,
   156  // and returns true if x is non-negative.
   157  func asUnsigned(x value) (value, bool) {
   158  	switch x := x.(type) {
   159  	case int:
   160  		return uint(x), x >= 0
   161  	case int8:
   162  		return uint8(x), x >= 0
   163  	case int16:
   164  		return uint16(x), x >= 0
   165  	case int32:
   166  		return uint32(x), x >= 0
   167  	case int64:
   168  		return uint64(x), x >= 0
   169  	case uint, uint8, uint32, uint64, uintptr:
   170  		return x, true
   171  	}
   172  	panic(fmt.Sprintf("cannot convert %T to unsigned", x))
   173  }
   174  
   175  // zero returns a new "zero" value of the specified type.
   176  func zero(t types.Type) value {
   177  	switch t := t.(type) {
   178  	case *types.Basic:
   179  		if t.Kind() == types.UntypedNil {
   180  			panic("untyped nil has no zero value")
   181  		}
   182  		if t.Info()&types.IsUntyped != 0 {
   183  			// TODO(adonovan): make it an invariant that
   184  			// this is unreachable.  Currently some
   185  			// constants have 'untyped' types when they
   186  			// should be defaulted by the typechecker.
   187  			t = types.Default(t).(*types.Basic)
   188  		}
   189  		switch t.Kind() {
   190  		case types.Bool:
   191  			return false
   192  		case types.Int:
   193  			return int(0)
   194  		case types.Int8:
   195  			return int8(0)
   196  		case types.Int16:
   197  			return int16(0)
   198  		case types.Int32:
   199  			return int32(0)
   200  		case types.Int64:
   201  			return int64(0)
   202  		case types.Uint:
   203  			return uint(0)
   204  		case types.Uint8:
   205  			return uint8(0)
   206  		case types.Uint16:
   207  			return uint16(0)
   208  		case types.Uint32:
   209  			return uint32(0)
   210  		case types.Uint64:
   211  			return uint64(0)
   212  		case types.Uintptr:
   213  			return uintptr(0)
   214  		case types.Float32:
   215  			return float32(0)
   216  		case types.Float64:
   217  			return float64(0)
   218  		case types.Complex64:
   219  			return complex64(0)
   220  		case types.Complex128:
   221  			return complex128(0)
   222  		case types.String:
   223  			return ""
   224  		case types.UnsafePointer:
   225  			return unsafe.Pointer(nil)
   226  		default:
   227  			panic(fmt.Sprint("zero for unexpected type:", t))
   228  		}
   229  	case *types.Pointer:
   230  		return (*value)(nil)
   231  	case *types.Array:
   232  		a := make(array, t.Len())
   233  		for i := range a {
   234  			a[i] = zero(t.Elem())
   235  		}
   236  		return a
   237  	case *types.Named:
   238  		return zero(t.Underlying())
   239  	case *aliases.Alias:
   240  		return zero(aliases.Unalias(t))
   241  	case *types.Interface:
   242  		return iface{} // nil type, methodset and value
   243  	case *types.Slice:
   244  		return []value(nil)
   245  	case *types.Struct:
   246  		s := make(structure, t.NumFields())
   247  		for i := range s {
   248  			s[i] = zero(t.Field(i).Type())
   249  		}
   250  		return s
   251  	case *types.Tuple:
   252  		if t.Len() == 1 {
   253  			return zero(t.At(0).Type())
   254  		}
   255  		s := make(tuple, t.Len())
   256  		for i := range s {
   257  			s[i] = zero(t.At(i).Type())
   258  		}
   259  		return s
   260  	case *types.Chan:
   261  		return chan value(nil)
   262  	case *types.Map:
   263  		if usesBuiltinMap(t.Key()) {
   264  			return map[value]value(nil)
   265  		}
   266  		return (*hashmap)(nil)
   267  	case *types.Signature:
   268  		return (*ssa.Function)(nil)
   269  	}
   270  	panic(fmt.Sprint("zero: unexpected ", t))
   271  }
   272  
   273  // slice returns x[lo:hi:max].  Any of lo, hi and max may be nil.
   274  func slice(x, lo, hi, max value) value {
   275  	var Len, Cap int
   276  	switch x := x.(type) {
   277  	case string:
   278  		Len = len(x)
   279  	case []value:
   280  		Len = len(x)
   281  		Cap = cap(x)
   282  	case *value: // *array
   283  		a := (*x).(array)
   284  		Len = len(a)
   285  		Cap = cap(a)
   286  	}
   287  
   288  	l := int64(0)
   289  	if lo != nil {
   290  		l = asInt64(lo)
   291  	}
   292  
   293  	h := int64(Len)
   294  	if hi != nil {
   295  		h = asInt64(hi)
   296  	}
   297  
   298  	m := int64(Cap)
   299  	if max != nil {
   300  		m = asInt64(max)
   301  	}
   302  
   303  	switch x := x.(type) {
   304  	case string:
   305  		return x[l:h]
   306  	case []value:
   307  		return x[l:h:m]
   308  	case *value: // *array
   309  		a := (*x).(array)
   310  		return []value(a)[l:h:m]
   311  	}
   312  	panic(fmt.Sprintf("slice: unexpected X type: %T", x))
   313  }
   314  
   315  // lookup returns x[idx] where x is a map.
   316  func lookup(instr *ssa.Lookup, x, idx value) value {
   317  	switch x := x.(type) { // map or string
   318  	case map[value]value, *hashmap:
   319  		var v value
   320  		var ok bool
   321  		switch x := x.(type) {
   322  		case map[value]value:
   323  			v, ok = x[idx]
   324  		case *hashmap:
   325  			v = x.lookup(idx.(hashable))
   326  			ok = v != nil
   327  		}
   328  		if !ok {
   329  			v = zero(instr.X.Type().Underlying().(*types.Map).Elem())
   330  		}
   331  		if instr.CommaOk {
   332  			v = tuple{v, ok}
   333  		}
   334  		return v
   335  	}
   336  	panic(fmt.Sprintf("unexpected x type in Lookup: %T", x))
   337  }
   338  
   339  // binop implements all arithmetic and logical binary operators for
   340  // numeric datatypes and strings.  Both operands must have identical
   341  // dynamic type.
   342  func binop(op token.Token, t types.Type, x, y value) value {
   343  	switch op {
   344  	case token.ADD:
   345  		switch x.(type) {
   346  		case int:
   347  			return x.(int) + y.(int)
   348  		case int8:
   349  			return x.(int8) + y.(int8)
   350  		case int16:
   351  			return x.(int16) + y.(int16)
   352  		case int32:
   353  			return x.(int32) + y.(int32)
   354  		case int64:
   355  			return x.(int64) + y.(int64)
   356  		case uint:
   357  			return x.(uint) + y.(uint)
   358  		case uint8:
   359  			return x.(uint8) + y.(uint8)
   360  		case uint16:
   361  			return x.(uint16) + y.(uint16)
   362  		case uint32:
   363  			return x.(uint32) + y.(uint32)
   364  		case uint64:
   365  			return x.(uint64) + y.(uint64)
   366  		case uintptr:
   367  			return x.(uintptr) + y.(uintptr)
   368  		case float32:
   369  			return x.(float32) + y.(float32)
   370  		case float64:
   371  			return x.(float64) + y.(float64)
   372  		case complex64:
   373  			return x.(complex64) + y.(complex64)
   374  		case complex128:
   375  			return x.(complex128) + y.(complex128)
   376  		case string:
   377  			return x.(string) + y.(string)
   378  		}
   379  
   380  	case token.SUB:
   381  		switch x.(type) {
   382  		case int:
   383  			return x.(int) - y.(int)
   384  		case int8:
   385  			return x.(int8) - y.(int8)
   386  		case int16:
   387  			return x.(int16) - y.(int16)
   388  		case int32:
   389  			return x.(int32) - y.(int32)
   390  		case int64:
   391  			return x.(int64) - y.(int64)
   392  		case uint:
   393  			return x.(uint) - y.(uint)
   394  		case uint8:
   395  			return x.(uint8) - y.(uint8)
   396  		case uint16:
   397  			return x.(uint16) - y.(uint16)
   398  		case uint32:
   399  			return x.(uint32) - y.(uint32)
   400  		case uint64:
   401  			return x.(uint64) - y.(uint64)
   402  		case uintptr:
   403  			return x.(uintptr) - y.(uintptr)
   404  		case float32:
   405  			return x.(float32) - y.(float32)
   406  		case float64:
   407  			return x.(float64) - y.(float64)
   408  		case complex64:
   409  			return x.(complex64) - y.(complex64)
   410  		case complex128:
   411  			return x.(complex128) - y.(complex128)
   412  		}
   413  
   414  	case token.MUL:
   415  		switch x.(type) {
   416  		case int:
   417  			return x.(int) * y.(int)
   418  		case int8:
   419  			return x.(int8) * y.(int8)
   420  		case int16:
   421  			return x.(int16) * y.(int16)
   422  		case int32:
   423  			return x.(int32) * y.(int32)
   424  		case int64:
   425  			return x.(int64) * y.(int64)
   426  		case uint:
   427  			return x.(uint) * y.(uint)
   428  		case uint8:
   429  			return x.(uint8) * y.(uint8)
   430  		case uint16:
   431  			return x.(uint16) * y.(uint16)
   432  		case uint32:
   433  			return x.(uint32) * y.(uint32)
   434  		case uint64:
   435  			return x.(uint64) * y.(uint64)
   436  		case uintptr:
   437  			return x.(uintptr) * y.(uintptr)
   438  		case float32:
   439  			return x.(float32) * y.(float32)
   440  		case float64:
   441  			return x.(float64) * y.(float64)
   442  		case complex64:
   443  			return x.(complex64) * y.(complex64)
   444  		case complex128:
   445  			return x.(complex128) * y.(complex128)
   446  		}
   447  
   448  	case token.QUO:
   449  		switch x.(type) {
   450  		case int:
   451  			return x.(int) / y.(int)
   452  		case int8:
   453  			return x.(int8) / y.(int8)
   454  		case int16:
   455  			return x.(int16) / y.(int16)
   456  		case int32:
   457  			return x.(int32) / y.(int32)
   458  		case int64:
   459  			return x.(int64) / y.(int64)
   460  		case uint:
   461  			return x.(uint) / y.(uint)
   462  		case uint8:
   463  			return x.(uint8) / y.(uint8)
   464  		case uint16:
   465  			return x.(uint16) / y.(uint16)
   466  		case uint32:
   467  			return x.(uint32) / y.(uint32)
   468  		case uint64:
   469  			return x.(uint64) / y.(uint64)
   470  		case uintptr:
   471  			return x.(uintptr) / y.(uintptr)
   472  		case float32:
   473  			return x.(float32) / y.(float32)
   474  		case float64:
   475  			return x.(float64) / y.(float64)
   476  		case complex64:
   477  			return x.(complex64) / y.(complex64)
   478  		case complex128:
   479  			return x.(complex128) / y.(complex128)
   480  		}
   481  
   482  	case token.REM:
   483  		switch x.(type) {
   484  		case int:
   485  			return x.(int) % y.(int)
   486  		case int8:
   487  			return x.(int8) % y.(int8)
   488  		case int16:
   489  			return x.(int16) % y.(int16)
   490  		case int32:
   491  			return x.(int32) % y.(int32)
   492  		case int64:
   493  			return x.(int64) % y.(int64)
   494  		case uint:
   495  			return x.(uint) % y.(uint)
   496  		case uint8:
   497  			return x.(uint8) % y.(uint8)
   498  		case uint16:
   499  			return x.(uint16) % y.(uint16)
   500  		case uint32:
   501  			return x.(uint32) % y.(uint32)
   502  		case uint64:
   503  			return x.(uint64) % y.(uint64)
   504  		case uintptr:
   505  			return x.(uintptr) % y.(uintptr)
   506  		}
   507  
   508  	case token.AND:
   509  		switch x.(type) {
   510  		case int:
   511  			return x.(int) & y.(int)
   512  		case int8:
   513  			return x.(int8) & y.(int8)
   514  		case int16:
   515  			return x.(int16) & y.(int16)
   516  		case int32:
   517  			return x.(int32) & y.(int32)
   518  		case int64:
   519  			return x.(int64) & y.(int64)
   520  		case uint:
   521  			return x.(uint) & y.(uint)
   522  		case uint8:
   523  			return x.(uint8) & y.(uint8)
   524  		case uint16:
   525  			return x.(uint16) & y.(uint16)
   526  		case uint32:
   527  			return x.(uint32) & y.(uint32)
   528  		case uint64:
   529  			return x.(uint64) & y.(uint64)
   530  		case uintptr:
   531  			return x.(uintptr) & y.(uintptr)
   532  		}
   533  
   534  	case token.OR:
   535  		switch x.(type) {
   536  		case int:
   537  			return x.(int) | y.(int)
   538  		case int8:
   539  			return x.(int8) | y.(int8)
   540  		case int16:
   541  			return x.(int16) | y.(int16)
   542  		case int32:
   543  			return x.(int32) | y.(int32)
   544  		case int64:
   545  			return x.(int64) | y.(int64)
   546  		case uint:
   547  			return x.(uint) | y.(uint)
   548  		case uint8:
   549  			return x.(uint8) | y.(uint8)
   550  		case uint16:
   551  			return x.(uint16) | y.(uint16)
   552  		case uint32:
   553  			return x.(uint32) | y.(uint32)
   554  		case uint64:
   555  			return x.(uint64) | y.(uint64)
   556  		case uintptr:
   557  			return x.(uintptr) | y.(uintptr)
   558  		}
   559  
   560  	case token.XOR:
   561  		switch x.(type) {
   562  		case int:
   563  			return x.(int) ^ y.(int)
   564  		case int8:
   565  			return x.(int8) ^ y.(int8)
   566  		case int16:
   567  			return x.(int16) ^ y.(int16)
   568  		case int32:
   569  			return x.(int32) ^ y.(int32)
   570  		case int64:
   571  			return x.(int64) ^ y.(int64)
   572  		case uint:
   573  			return x.(uint) ^ y.(uint)
   574  		case uint8:
   575  			return x.(uint8) ^ y.(uint8)
   576  		case uint16:
   577  			return x.(uint16) ^ y.(uint16)
   578  		case uint32:
   579  			return x.(uint32) ^ y.(uint32)
   580  		case uint64:
   581  			return x.(uint64) ^ y.(uint64)
   582  		case uintptr:
   583  			return x.(uintptr) ^ y.(uintptr)
   584  		}
   585  
   586  	case token.AND_NOT:
   587  		switch x.(type) {
   588  		case int:
   589  			return x.(int) &^ y.(int)
   590  		case int8:
   591  			return x.(int8) &^ y.(int8)
   592  		case int16:
   593  			return x.(int16) &^ y.(int16)
   594  		case int32:
   595  			return x.(int32) &^ y.(int32)
   596  		case int64:
   597  			return x.(int64) &^ y.(int64)
   598  		case uint:
   599  			return x.(uint) &^ y.(uint)
   600  		case uint8:
   601  			return x.(uint8) &^ y.(uint8)
   602  		case uint16:
   603  			return x.(uint16) &^ y.(uint16)
   604  		case uint32:
   605  			return x.(uint32) &^ y.(uint32)
   606  		case uint64:
   607  			return x.(uint64) &^ y.(uint64)
   608  		case uintptr:
   609  			return x.(uintptr) &^ y.(uintptr)
   610  		}
   611  
   612  	case token.SHL:
   613  		u, ok := asUnsigned(y)
   614  		if !ok {
   615  			panic("negative shift amount")
   616  		}
   617  		y := asUint64(u)
   618  		switch x.(type) {
   619  		case int:
   620  			return x.(int) << y
   621  		case int8:
   622  			return x.(int8) << y
   623  		case int16:
   624  			return x.(int16) << y
   625  		case int32:
   626  			return x.(int32) << y
   627  		case int64:
   628  			return x.(int64) << y
   629  		case uint:
   630  			return x.(uint) << y
   631  		case uint8:
   632  			return x.(uint8) << y
   633  		case uint16:
   634  			return x.(uint16) << y
   635  		case uint32:
   636  			return x.(uint32) << y
   637  		case uint64:
   638  			return x.(uint64) << y
   639  		case uintptr:
   640  			return x.(uintptr) << y
   641  		}
   642  
   643  	case token.SHR:
   644  		u, ok := asUnsigned(y)
   645  		if !ok {
   646  			panic("negative shift amount")
   647  		}
   648  		y := asUint64(u)
   649  		switch x.(type) {
   650  		case int:
   651  			return x.(int) >> y
   652  		case int8:
   653  			return x.(int8) >> y
   654  		case int16:
   655  			return x.(int16) >> y
   656  		case int32:
   657  			return x.(int32) >> y
   658  		case int64:
   659  			return x.(int64) >> y
   660  		case uint:
   661  			return x.(uint) >> y
   662  		case uint8:
   663  			return x.(uint8) >> y
   664  		case uint16:
   665  			return x.(uint16) >> y
   666  		case uint32:
   667  			return x.(uint32) >> y
   668  		case uint64:
   669  			return x.(uint64) >> y
   670  		case uintptr:
   671  			return x.(uintptr) >> y
   672  		}
   673  
   674  	case token.LSS:
   675  		switch x.(type) {
   676  		case int:
   677  			return x.(int) < y.(int)
   678  		case int8:
   679  			return x.(int8) < y.(int8)
   680  		case int16:
   681  			return x.(int16) < y.(int16)
   682  		case int32:
   683  			return x.(int32) < y.(int32)
   684  		case int64:
   685  			return x.(int64) < y.(int64)
   686  		case uint:
   687  			return x.(uint) < y.(uint)
   688  		case uint8:
   689  			return x.(uint8) < y.(uint8)
   690  		case uint16:
   691  			return x.(uint16) < y.(uint16)
   692  		case uint32:
   693  			return x.(uint32) < y.(uint32)
   694  		case uint64:
   695  			return x.(uint64) < y.(uint64)
   696  		case uintptr:
   697  			return x.(uintptr) < y.(uintptr)
   698  		case float32:
   699  			return x.(float32) < y.(float32)
   700  		case float64:
   701  			return x.(float64) < y.(float64)
   702  		case string:
   703  			return x.(string) < y.(string)
   704  		}
   705  
   706  	case token.LEQ:
   707  		switch x.(type) {
   708  		case int:
   709  			return x.(int) <= y.(int)
   710  		case int8:
   711  			return x.(int8) <= y.(int8)
   712  		case int16:
   713  			return x.(int16) <= y.(int16)
   714  		case int32:
   715  			return x.(int32) <= y.(int32)
   716  		case int64:
   717  			return x.(int64) <= y.(int64)
   718  		case uint:
   719  			return x.(uint) <= y.(uint)
   720  		case uint8:
   721  			return x.(uint8) <= y.(uint8)
   722  		case uint16:
   723  			return x.(uint16) <= y.(uint16)
   724  		case uint32:
   725  			return x.(uint32) <= y.(uint32)
   726  		case uint64:
   727  			return x.(uint64) <= y.(uint64)
   728  		case uintptr:
   729  			return x.(uintptr) <= y.(uintptr)
   730  		case float32:
   731  			return x.(float32) <= y.(float32)
   732  		case float64:
   733  			return x.(float64) <= y.(float64)
   734  		case string:
   735  			return x.(string) <= y.(string)
   736  		}
   737  
   738  	case token.EQL:
   739  		return eqnil(t, x, y)
   740  
   741  	case token.NEQ:
   742  		return !eqnil(t, x, y)
   743  
   744  	case token.GTR:
   745  		switch x.(type) {
   746  		case int:
   747  			return x.(int) > y.(int)
   748  		case int8:
   749  			return x.(int8) > y.(int8)
   750  		case int16:
   751  			return x.(int16) > y.(int16)
   752  		case int32:
   753  			return x.(int32) > y.(int32)
   754  		case int64:
   755  			return x.(int64) > y.(int64)
   756  		case uint:
   757  			return x.(uint) > y.(uint)
   758  		case uint8:
   759  			return x.(uint8) > y.(uint8)
   760  		case uint16:
   761  			return x.(uint16) > y.(uint16)
   762  		case uint32:
   763  			return x.(uint32) > y.(uint32)
   764  		case uint64:
   765  			return x.(uint64) > y.(uint64)
   766  		case uintptr:
   767  			return x.(uintptr) > y.(uintptr)
   768  		case float32:
   769  			return x.(float32) > y.(float32)
   770  		case float64:
   771  			return x.(float64) > y.(float64)
   772  		case string:
   773  			return x.(string) > y.(string)
   774  		}
   775  
   776  	case token.GEQ:
   777  		switch x.(type) {
   778  		case int:
   779  			return x.(int) >= y.(int)
   780  		case int8:
   781  			return x.(int8) >= y.(int8)
   782  		case int16:
   783  			return x.(int16) >= y.(int16)
   784  		case int32:
   785  			return x.(int32) >= y.(int32)
   786  		case int64:
   787  			return x.(int64) >= y.(int64)
   788  		case uint:
   789  			return x.(uint) >= y.(uint)
   790  		case uint8:
   791  			return x.(uint8) >= y.(uint8)
   792  		case uint16:
   793  			return x.(uint16) >= y.(uint16)
   794  		case uint32:
   795  			return x.(uint32) >= y.(uint32)
   796  		case uint64:
   797  			return x.(uint64) >= y.(uint64)
   798  		case uintptr:
   799  			return x.(uintptr) >= y.(uintptr)
   800  		case float32:
   801  			return x.(float32) >= y.(float32)
   802  		case float64:
   803  			return x.(float64) >= y.(float64)
   804  		case string:
   805  			return x.(string) >= y.(string)
   806  		}
   807  	}
   808  	panic(fmt.Sprintf("invalid binary op: %T %s %T", x, op, y))
   809  }
   810  
   811  // eqnil returns the comparison x == y using the equivalence relation
   812  // appropriate for type t.
   813  // If t is a reference type, at most one of x or y may be a nil value
   814  // of that type.
   815  func eqnil(t types.Type, x, y value) bool {
   816  	switch t.Underlying().(type) {
   817  	case *types.Map, *types.Signature, *types.Slice:
   818  		// Since these types don't support comparison,
   819  		// one of the operands must be a literal nil.
   820  		switch x := x.(type) {
   821  		case *hashmap:
   822  			return (x != nil) == (y.(*hashmap) != nil)
   823  		case map[value]value:
   824  			return (x != nil) == (y.(map[value]value) != nil)
   825  		case *ssa.Function:
   826  			switch y := y.(type) {
   827  			case *ssa.Function:
   828  				return (x != nil) == (y != nil)
   829  			case *closure:
   830  				return true
   831  			}
   832  		case *closure:
   833  			return (x != nil) == (y.(*ssa.Function) != nil)
   834  		case []value:
   835  			return (x != nil) == (y.([]value) != nil)
   836  		}
   837  		panic(fmt.Sprintf("eqnil(%s): illegal dynamic type: %T", t, x))
   838  	}
   839  
   840  	return equals(t, x, y)
   841  }
   842  
   843  func unop(instr *ssa.UnOp, x value) value {
   844  	switch instr.Op {
   845  	case token.ARROW: // receive
   846  		v, ok := <-x.(chan value)
   847  		if !ok {
   848  			v = zero(instr.X.Type().Underlying().(*types.Chan).Elem())
   849  		}
   850  		if instr.CommaOk {
   851  			v = tuple{v, ok}
   852  		}
   853  		return v
   854  	case token.SUB:
   855  		switch x := x.(type) {
   856  		case int:
   857  			return -x
   858  		case int8:
   859  			return -x
   860  		case int16:
   861  			return -x
   862  		case int32:
   863  			return -x
   864  		case int64:
   865  			return -x
   866  		case uint:
   867  			return -x
   868  		case uint8:
   869  			return -x
   870  		case uint16:
   871  			return -x
   872  		case uint32:
   873  			return -x
   874  		case uint64:
   875  			return -x
   876  		case uintptr:
   877  			return -x
   878  		case float32:
   879  			return -x
   880  		case float64:
   881  			return -x
   882  		case complex64:
   883  			return -x
   884  		case complex128:
   885  			return -x
   886  		}
   887  	case token.MUL:
   888  		return load(typeparams.MustDeref(instr.X.Type()), x.(*value))
   889  	case token.NOT:
   890  		return !x.(bool)
   891  	case token.XOR:
   892  		switch x := x.(type) {
   893  		case int:
   894  			return ^x
   895  		case int8:
   896  			return ^x
   897  		case int16:
   898  			return ^x
   899  		case int32:
   900  			return ^x
   901  		case int64:
   902  			return ^x
   903  		case uint:
   904  			return ^x
   905  		case uint8:
   906  			return ^x
   907  		case uint16:
   908  			return ^x
   909  		case uint32:
   910  			return ^x
   911  		case uint64:
   912  			return ^x
   913  		case uintptr:
   914  			return ^x
   915  		}
   916  	}
   917  	panic(fmt.Sprintf("invalid unary op %s %T", instr.Op, x))
   918  }
   919  
   920  // typeAssert checks whether dynamic type of itf is instr.AssertedType.
   921  // It returns the extracted value on success, and panics on failure,
   922  // unless instr.CommaOk, in which case it always returns a "value,ok" tuple.
   923  func typeAssert(i *interpreter, instr *ssa.TypeAssert, itf iface) value {
   924  	var v value
   925  	err := ""
   926  	if itf.t == nil {
   927  		err = fmt.Sprintf("interface conversion: interface is nil, not %s", instr.AssertedType)
   928  
   929  	} else if idst, ok := instr.AssertedType.Underlying().(*types.Interface); ok {
   930  		v = itf
   931  		err = checkInterface(i, idst, itf)
   932  
   933  	} else if types.Identical(itf.t, instr.AssertedType) {
   934  		v = itf.v // extract value
   935  
   936  	} else {
   937  		err = fmt.Sprintf("interface conversion: interface is %s, not %s", itf.t, instr.AssertedType)
   938  	}
   939  	// Note: if instr.Underlying==true ever becomes reachable from interp check that
   940  	// types.Identical(itf.t.Underlying(), instr.AssertedType)
   941  
   942  	if err != "" {
   943  		if !instr.CommaOk {
   944  			panic(err)
   945  		}
   946  		return tuple{zero(instr.AssertedType), false}
   947  	}
   948  	if instr.CommaOk {
   949  		return tuple{v, true}
   950  	}
   951  	return v
   952  }
   953  
   954  // If CapturedOutput is non-nil, all writes by the interpreted program
   955  // to file descriptors 1 and 2 will also be written to CapturedOutput.
   956  //
   957  // (The $GOROOT/test system requires that the test be considered a
   958  // failure if "BUG" appears in the combined stdout/stderr output, even
   959  // if it exits zero.  This is a global variable shared by all
   960  // interpreters in the same process.)
   961  var CapturedOutput *bytes.Buffer
   962  var capturedOutputMu sync.Mutex
   963  
   964  // write writes bytes b to the target program's standard output.
   965  // The print/println built-ins and the write() system call funnel
   966  // through here so they can be captured by the test driver.
   967  func print(b []byte) (int, error) {
   968  	if CapturedOutput != nil {
   969  		capturedOutputMu.Lock()
   970  		CapturedOutput.Write(b) // ignore errors
   971  		capturedOutputMu.Unlock()
   972  	}
   973  	return os.Stdout.Write(b)
   974  }
   975  
   976  // callBuiltin interprets a call to builtin fn with arguments args,
   977  // returning its result.
   978  func callBuiltin(caller *frame, callpos token.Pos, fn *ssa.Builtin, args []value) value {
   979  	switch fn.Name() {
   980  	case "append":
   981  		if len(args) == 1 {
   982  			return args[0]
   983  		}
   984  		if s, ok := args[1].(string); ok {
   985  			// append([]byte, ...string) []byte
   986  			arg0 := args[0].([]value)
   987  			for i := 0; i < len(s); i++ {
   988  				arg0 = append(arg0, s[i])
   989  			}
   990  			return arg0
   991  		}
   992  		// append([]T, ...[]T) []T
   993  		return append(args[0].([]value), args[1].([]value)...)
   994  
   995  	case "copy": // copy([]T, []T) int or copy([]byte, string) int
   996  		src := args[1]
   997  		if _, ok := src.(string); ok {
   998  			params := fn.Type().(*types.Signature).Params()
   999  			src = conv(params.At(0).Type(), params.At(1).Type(), src)
  1000  		}
  1001  		return copy(args[0].([]value), src.([]value))
  1002  
  1003  	case "close": // close(chan T)
  1004  		close(args[0].(chan value))
  1005  		return nil
  1006  
  1007  	case "delete": // delete(map[K]value, K)
  1008  		switch m := args[0].(type) {
  1009  		case map[value]value:
  1010  			delete(m, args[1])
  1011  		case *hashmap:
  1012  			m.delete(args[1].(hashable))
  1013  		default:
  1014  			panic(fmt.Sprintf("illegal map type: %T", m))
  1015  		}
  1016  		return nil
  1017  
  1018  	case "print", "println": // print(any, ...)
  1019  		ln := fn.Name() == "println"
  1020  		var buf bytes.Buffer
  1021  		for i, arg := range args {
  1022  			if i > 0 && ln {
  1023  				buf.WriteRune(' ')
  1024  			}
  1025  			buf.WriteString(toString(arg))
  1026  		}
  1027  		if ln {
  1028  			buf.WriteRune('\n')
  1029  		}
  1030  		print(buf.Bytes())
  1031  		return nil
  1032  
  1033  	case "len":
  1034  		switch x := args[0].(type) {
  1035  		case string:
  1036  			return len(x)
  1037  		case array:
  1038  			return len(x)
  1039  		case *value:
  1040  			return len((*x).(array))
  1041  		case []value:
  1042  			return len(x)
  1043  		case map[value]value:
  1044  			return len(x)
  1045  		case *hashmap:
  1046  			return x.len()
  1047  		case chan value:
  1048  			return len(x)
  1049  		default:
  1050  			panic(fmt.Sprintf("len: illegal operand: %T", x))
  1051  		}
  1052  
  1053  	case "cap":
  1054  		switch x := args[0].(type) {
  1055  		case array:
  1056  			return cap(x)
  1057  		case *value:
  1058  			return cap((*x).(array))
  1059  		case []value:
  1060  			return cap(x)
  1061  		case chan value:
  1062  			return cap(x)
  1063  		default:
  1064  			panic(fmt.Sprintf("cap: illegal operand: %T", x))
  1065  		}
  1066  
  1067  	case "min":
  1068  		return foldLeft(min, args)
  1069  	case "max":
  1070  		return foldLeft(max, args)
  1071  
  1072  	case "real":
  1073  		switch c := args[0].(type) {
  1074  		case complex64:
  1075  			return real(c)
  1076  		case complex128:
  1077  			return real(c)
  1078  		default:
  1079  			panic(fmt.Sprintf("real: illegal operand: %T", c))
  1080  		}
  1081  
  1082  	case "imag":
  1083  		switch c := args[0].(type) {
  1084  		case complex64:
  1085  			return imag(c)
  1086  		case complex128:
  1087  			return imag(c)
  1088  		default:
  1089  			panic(fmt.Sprintf("imag: illegal operand: %T", c))
  1090  		}
  1091  
  1092  	case "complex":
  1093  		switch f := args[0].(type) {
  1094  		case float32:
  1095  			return complex(f, args[1].(float32))
  1096  		case float64:
  1097  			return complex(f, args[1].(float64))
  1098  		default:
  1099  			panic(fmt.Sprintf("complex: illegal operand: %T", f))
  1100  		}
  1101  
  1102  	case "panic":
  1103  		// ssa.Panic handles most cases; this is only for "go
  1104  		// panic" or "defer panic".
  1105  		panic(targetPanic{args[0]})
  1106  
  1107  	case "recover":
  1108  		return doRecover(caller)
  1109  
  1110  	case "ssa:wrapnilchk":
  1111  		recv := args[0]
  1112  		if recv.(*value) == nil {
  1113  			recvType := args[1]
  1114  			methodName := args[2]
  1115  			panic(fmt.Sprintf("value method (%s).%s called using nil *%s pointer",
  1116  				recvType, methodName, recvType))
  1117  		}
  1118  		return recv
  1119  	}
  1120  
  1121  	panic("unknown built-in: " + fn.Name())
  1122  }
  1123  
  1124  func rangeIter(x value, t types.Type) iter {
  1125  	switch x := x.(type) {
  1126  	case map[value]value:
  1127  		return &mapIter{iter: reflect.ValueOf(x).MapRange()}
  1128  	case *hashmap:
  1129  		return &hashmapIter{iter: reflect.ValueOf(x.entries()).MapRange()}
  1130  	case string:
  1131  		return &stringIter{Reader: strings.NewReader(x)}
  1132  	}
  1133  	panic(fmt.Sprintf("cannot range over %T", x))
  1134  }
  1135  
  1136  // widen widens a basic typed value x to the widest type of its
  1137  // category, one of:
  1138  //
  1139  //	bool, int64, uint64, float64, complex128, string.
  1140  //
  1141  // This is inefficient but reduces the size of the cross-product of
  1142  // cases we have to consider.
  1143  func widen(x value) value {
  1144  	switch y := x.(type) {
  1145  	case bool, int64, uint64, float64, complex128, string, unsafe.Pointer:
  1146  		return x
  1147  	case int:
  1148  		return int64(y)
  1149  	case int8:
  1150  		return int64(y)
  1151  	case int16:
  1152  		return int64(y)
  1153  	case int32:
  1154  		return int64(y)
  1155  	case uint:
  1156  		return uint64(y)
  1157  	case uint8:
  1158  		return uint64(y)
  1159  	case uint16:
  1160  		return uint64(y)
  1161  	case uint32:
  1162  		return uint64(y)
  1163  	case uintptr:
  1164  		return uint64(y)
  1165  	case float32:
  1166  		return float64(y)
  1167  	case complex64:
  1168  		return complex128(y)
  1169  	}
  1170  	panic(fmt.Sprintf("cannot widen %T", x))
  1171  }
  1172  
  1173  // conv converts the value x of type t_src to type t_dst and returns
  1174  // the result.
  1175  // Possible cases are described with the ssa.Convert operator.
  1176  func conv(t_dst, t_src types.Type, x value) value {
  1177  	ut_src := t_src.Underlying()
  1178  	ut_dst := t_dst.Underlying()
  1179  
  1180  	// Destination type is not an "untyped" type.
  1181  	if b, ok := ut_dst.(*types.Basic); ok && b.Info()&types.IsUntyped != 0 {
  1182  		panic("oops: conversion to 'untyped' type: " + b.String())
  1183  	}
  1184  
  1185  	// Nor is it an interface type.
  1186  	if _, ok := ut_dst.(*types.Interface); ok {
  1187  		if _, ok := ut_src.(*types.Interface); ok {
  1188  			panic("oops: Convert should be ChangeInterface")
  1189  		} else {
  1190  			panic("oops: Convert should be MakeInterface")
  1191  		}
  1192  	}
  1193  
  1194  	// Remaining conversions:
  1195  	//    + untyped string/number/bool constant to a specific
  1196  	//      representation.
  1197  	//    + conversions between non-complex numeric types.
  1198  	//    + conversions between complex numeric types.
  1199  	//    + integer/[]byte/[]rune -> string.
  1200  	//    + string -> []byte/[]rune.
  1201  	//
  1202  	// All are treated the same: first we extract the value to the
  1203  	// widest representation (int64, uint64, float64, complex128,
  1204  	// or string), then we convert it to the desired type.
  1205  
  1206  	switch ut_src := ut_src.(type) {
  1207  	case *types.Pointer:
  1208  		switch ut_dst := ut_dst.(type) {
  1209  		case *types.Basic:
  1210  			// *value to unsafe.Pointer?
  1211  			if ut_dst.Kind() == types.UnsafePointer {
  1212  				return unsafe.Pointer(x.(*value))
  1213  			}
  1214  		}
  1215  
  1216  	case *types.Slice:
  1217  		// []byte or []rune -> string
  1218  		switch ut_src.Elem().Underlying().(*types.Basic).Kind() {
  1219  		case types.Byte:
  1220  			x := x.([]value)
  1221  			b := make([]byte, 0, len(x))
  1222  			for i := range x {
  1223  				b = append(b, x[i].(byte))
  1224  			}
  1225  			return string(b)
  1226  
  1227  		case types.Rune:
  1228  			x := x.([]value)
  1229  			r := make([]rune, 0, len(x))
  1230  			for i := range x {
  1231  				r = append(r, x[i].(rune))
  1232  			}
  1233  			return string(r)
  1234  		}
  1235  
  1236  	case *types.Basic:
  1237  		x = widen(x)
  1238  
  1239  		// integer -> string?
  1240  		if ut_src.Info()&types.IsInteger != 0 {
  1241  			if ut_dst, ok := ut_dst.(*types.Basic); ok && ut_dst.Kind() == types.String {
  1242  				return fmt.Sprintf("%c", x)
  1243  			}
  1244  		}
  1245  
  1246  		// string -> []rune, []byte or string?
  1247  		if s, ok := x.(string); ok {
  1248  			switch ut_dst := ut_dst.(type) {
  1249  			case *types.Slice:
  1250  				var res []value
  1251  				switch ut_dst.Elem().Underlying().(*types.Basic).Kind() {
  1252  				case types.Rune:
  1253  					for _, r := range []rune(s) {
  1254  						res = append(res, r)
  1255  					}
  1256  					return res
  1257  				case types.Byte:
  1258  					for _, b := range []byte(s) {
  1259  						res = append(res, b)
  1260  					}
  1261  					return res
  1262  				}
  1263  			case *types.Basic:
  1264  				if ut_dst.Kind() == types.String {
  1265  					return x.(string)
  1266  				}
  1267  			}
  1268  			break // fail: no other conversions for string
  1269  		}
  1270  
  1271  		// unsafe.Pointer -> *value
  1272  		if ut_src.Kind() == types.UnsafePointer {
  1273  			// TODO(adonovan): this is wrong and cannot
  1274  			// really be fixed with the current design.
  1275  			//
  1276  			// return (*value)(x.(unsafe.Pointer))
  1277  			// creates a new pointer of a different
  1278  			// type but the underlying interface value
  1279  			// knows its "true" type and so cannot be
  1280  			// meaningfully used through the new pointer.
  1281  			//
  1282  			// To make this work, the interpreter needs to
  1283  			// simulate the memory layout of a real
  1284  			// compiled implementation.
  1285  			//
  1286  			// To at least preserve type-safety, we'll
  1287  			// just return the zero value of the
  1288  			// destination type.
  1289  			return zero(t_dst)
  1290  		}
  1291  
  1292  		// Conversions between complex numeric types?
  1293  		if ut_src.Info()&types.IsComplex != 0 {
  1294  			switch ut_dst.(*types.Basic).Kind() {
  1295  			case types.Complex64:
  1296  				return complex64(x.(complex128))
  1297  			case types.Complex128:
  1298  				return x.(complex128)
  1299  			}
  1300  			break // fail: no other conversions for complex
  1301  		}
  1302  
  1303  		// Conversions between non-complex numeric types?
  1304  		if ut_src.Info()&types.IsNumeric != 0 {
  1305  			kind := ut_dst.(*types.Basic).Kind()
  1306  			switch x := x.(type) {
  1307  			case int64: // signed integer -> numeric?
  1308  				switch kind {
  1309  				case types.Int:
  1310  					return int(x)
  1311  				case types.Int8:
  1312  					return int8(x)
  1313  				case types.Int16:
  1314  					return int16(x)
  1315  				case types.Int32:
  1316  					return int32(x)
  1317  				case types.Int64:
  1318  					return int64(x)
  1319  				case types.Uint:
  1320  					return uint(x)
  1321  				case types.Uint8:
  1322  					return uint8(x)
  1323  				case types.Uint16:
  1324  					return uint16(x)
  1325  				case types.Uint32:
  1326  					return uint32(x)
  1327  				case types.Uint64:
  1328  					return uint64(x)
  1329  				case types.Uintptr:
  1330  					return uintptr(x)
  1331  				case types.Float32:
  1332  					return float32(x)
  1333  				case types.Float64:
  1334  					return float64(x)
  1335  				}
  1336  
  1337  			case uint64: // unsigned integer -> numeric?
  1338  				switch kind {
  1339  				case types.Int:
  1340  					return int(x)
  1341  				case types.Int8:
  1342  					return int8(x)
  1343  				case types.Int16:
  1344  					return int16(x)
  1345  				case types.Int32:
  1346  					return int32(x)
  1347  				case types.Int64:
  1348  					return int64(x)
  1349  				case types.Uint:
  1350  					return uint(x)
  1351  				case types.Uint8:
  1352  					return uint8(x)
  1353  				case types.Uint16:
  1354  					return uint16(x)
  1355  				case types.Uint32:
  1356  					return uint32(x)
  1357  				case types.Uint64:
  1358  					return uint64(x)
  1359  				case types.Uintptr:
  1360  					return uintptr(x)
  1361  				case types.Float32:
  1362  					return float32(x)
  1363  				case types.Float64:
  1364  					return float64(x)
  1365  				}
  1366  
  1367  			case float64: // floating point -> numeric?
  1368  				switch kind {
  1369  				case types.Int:
  1370  					return int(x)
  1371  				case types.Int8:
  1372  					return int8(x)
  1373  				case types.Int16:
  1374  					return int16(x)
  1375  				case types.Int32:
  1376  					return int32(x)
  1377  				case types.Int64:
  1378  					return int64(x)
  1379  				case types.Uint:
  1380  					return uint(x)
  1381  				case types.Uint8:
  1382  					return uint8(x)
  1383  				case types.Uint16:
  1384  					return uint16(x)
  1385  				case types.Uint32:
  1386  					return uint32(x)
  1387  				case types.Uint64:
  1388  					return uint64(x)
  1389  				case types.Uintptr:
  1390  					return uintptr(x)
  1391  				case types.Float32:
  1392  					return float32(x)
  1393  				case types.Float64:
  1394  					return float64(x)
  1395  				}
  1396  			}
  1397  		}
  1398  	}
  1399  
  1400  	panic(fmt.Sprintf("unsupported conversion: %s  -> %s, dynamic type %T", t_src, t_dst, x))
  1401  }
  1402  
  1403  // sliceToArrayPointer converts the value x of type slice to type t_dst
  1404  // a pointer to array and returns the result.
  1405  func sliceToArrayPointer(t_dst, t_src types.Type, x value) value {
  1406  	if _, ok := t_src.Underlying().(*types.Slice); ok {
  1407  		if ptr, ok := t_dst.Underlying().(*types.Pointer); ok {
  1408  			if arr, ok := ptr.Elem().Underlying().(*types.Array); ok {
  1409  				x := x.([]value)
  1410  				if arr.Len() > int64(len(x)) {
  1411  					panic("array length is greater than slice length")
  1412  				}
  1413  				if x == nil {
  1414  					return zero(t_dst)
  1415  				}
  1416  				v := value(array(x[:arr.Len()]))
  1417  				return &v
  1418  			}
  1419  		}
  1420  	}
  1421  
  1422  	panic(fmt.Sprintf("unsupported conversion: %s  -> %s, dynamic type %T", t_src, t_dst, x))
  1423  }
  1424  
  1425  // checkInterface checks that the method set of x implements the
  1426  // interface itype.
  1427  // On success it returns "", on failure, an error message.
  1428  func checkInterface(i *interpreter, itype *types.Interface, x iface) string {
  1429  	if meth, _ := types.MissingMethod(x.t, itype, true); meth != nil {
  1430  		return fmt.Sprintf("interface conversion: %v is not %v: missing method %s",
  1431  			x.t, itype, meth.Name())
  1432  	}
  1433  	return "" // ok
  1434  }
  1435  
  1436  func foldLeft(op func(value, value) value, args []value) value {
  1437  	x := args[0]
  1438  	for _, arg := range args[1:] {
  1439  		x = op(x, arg)
  1440  	}
  1441  	return x
  1442  }
  1443  
  1444  func min(x, y value) value {
  1445  	switch x := x.(type) {
  1446  	case float32:
  1447  		return fmin(x, y.(float32))
  1448  	case float64:
  1449  		return fmin(x, y.(float64))
  1450  	}
  1451  
  1452  	// return (y < x) ? y : x
  1453  	if binop(token.LSS, nil, y, x).(bool) {
  1454  		return y
  1455  	}
  1456  	return x
  1457  }
  1458  
  1459  func max(x, y value) value {
  1460  	switch x := x.(type) {
  1461  	case float32:
  1462  		return fmax(x, y.(float32))
  1463  	case float64:
  1464  		return fmax(x, y.(float64))
  1465  	}
  1466  
  1467  	// return (y > x) ? y : x
  1468  	if binop(token.GTR, nil, y, x).(bool) {
  1469  		return y
  1470  	}
  1471  	return x
  1472  }
  1473  
  1474  // copied from $GOROOT/src/runtime/minmax.go
  1475  
  1476  type floaty interface{ ~float32 | ~float64 }
  1477  
  1478  func fmin[F floaty](x, y F) F {
  1479  	if y != y || y < x {
  1480  		return y
  1481  	}
  1482  	if x != x || x < y || x != 0 {
  1483  		return x
  1484  	}
  1485  	// x and y are both ±0
  1486  	// if either is -0, return -0; else return +0
  1487  	return forbits(x, y)
  1488  }
  1489  
  1490  func fmax[F floaty](x, y F) F {
  1491  	if y != y || y > x {
  1492  		return y
  1493  	}
  1494  	if x != x || x > y || x != 0 {
  1495  		return x
  1496  	}
  1497  	// x and y are both ±0
  1498  	// if both are -0, return -0; else return +0
  1499  	return fandbits(x, y)
  1500  }
  1501  
  1502  func forbits[F floaty](x, y F) F {
  1503  	switch unsafe.Sizeof(x) {
  1504  	case 4:
  1505  		*(*uint32)(unsafe.Pointer(&x)) |= *(*uint32)(unsafe.Pointer(&y))
  1506  	case 8:
  1507  		*(*uint64)(unsafe.Pointer(&x)) |= *(*uint64)(unsafe.Pointer(&y))
  1508  	}
  1509  	return x
  1510  }
  1511  
  1512  func fandbits[F floaty](x, y F) F {
  1513  	switch unsafe.Sizeof(x) {
  1514  	case 4:
  1515  		*(*uint32)(unsafe.Pointer(&x)) &= *(*uint32)(unsafe.Pointer(&y))
  1516  	case 8:
  1517  		*(*uint64)(unsafe.Pointer(&x)) &= *(*uint64)(unsafe.Pointer(&y))
  1518  	}
  1519  	return x
  1520  }
  1521  

View as plain text