...

Source file src/golang.org/x/tools/go/ssa/interp/external.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  // Emulated functions that we cannot interpret because they are
     8  // external or because they use "unsafe" or "reflect" operations.
     9  
    10  import (
    11  	"bytes"
    12  	"math"
    13  	"os"
    14  	"runtime"
    15  	"sort"
    16  	"strconv"
    17  	"strings"
    18  	"time"
    19  	"unicode/utf8"
    20  )
    21  
    22  type externalFn func(fr *frame, args []value) value
    23  
    24  // TODO(adonovan): fix: reflect.Value abstracts an lvalue or an
    25  // rvalue; Set() causes mutations that can be observed via aliases.
    26  // We have not captured that correctly here.
    27  
    28  // Key strings are from Function.String().
    29  var externals = make(map[string]externalFn)
    30  
    31  func init() {
    32  	// That little dot ۰ is an Arabic zero numeral (U+06F0), categories [Nd].
    33  	for k, v := range map[string]externalFn{
    34  		"(reflect.Value).Bool":            ext۰reflect۰Value۰Bool,
    35  		"(reflect.Value).CanAddr":         ext۰reflect۰Value۰CanAddr,
    36  		"(reflect.Value).CanInterface":    ext۰reflect۰Value۰CanInterface,
    37  		"(reflect.Value).Elem":            ext۰reflect۰Value۰Elem,
    38  		"(reflect.Value).Field":           ext۰reflect۰Value۰Field,
    39  		"(reflect.Value).Float":           ext۰reflect۰Value۰Float,
    40  		"(reflect.Value).Index":           ext۰reflect۰Value۰Index,
    41  		"(reflect.Value).Int":             ext۰reflect۰Value۰Int,
    42  		"(reflect.Value).Interface":       ext۰reflect۰Value۰Interface,
    43  		"(reflect.Value).IsNil":           ext۰reflect۰Value۰IsNil,
    44  		"(reflect.Value).IsValid":         ext۰reflect۰Value۰IsValid,
    45  		"(reflect.Value).Kind":            ext۰reflect۰Value۰Kind,
    46  		"(reflect.Value).Len":             ext۰reflect۰Value۰Len,
    47  		"(reflect.Value).MapIndex":        ext۰reflect۰Value۰MapIndex,
    48  		"(reflect.Value).MapKeys":         ext۰reflect۰Value۰MapKeys,
    49  		"(reflect.Value).NumField":        ext۰reflect۰Value۰NumField,
    50  		"(reflect.Value).NumMethod":       ext۰reflect۰Value۰NumMethod,
    51  		"(reflect.Value).Pointer":         ext۰reflect۰Value۰Pointer,
    52  		"(reflect.Value).Set":             ext۰reflect۰Value۰Set,
    53  		"(reflect.Value).String":          ext۰reflect۰Value۰String,
    54  		"(reflect.Value).Type":            ext۰reflect۰Value۰Type,
    55  		"(reflect.Value).Uint":            ext۰reflect۰Value۰Uint,
    56  		"(reflect.error).Error":           ext۰reflect۰error۰Error,
    57  		"(reflect.rtype).Bits":            ext۰reflect۰rtype۰Bits,
    58  		"(reflect.rtype).Elem":            ext۰reflect۰rtype۰Elem,
    59  		"(reflect.rtype).Field":           ext۰reflect۰rtype۰Field,
    60  		"(reflect.rtype).In":              ext۰reflect۰rtype۰In,
    61  		"(reflect.rtype).Kind":            ext۰reflect۰rtype۰Kind,
    62  		"(reflect.rtype).NumField":        ext۰reflect۰rtype۰NumField,
    63  		"(reflect.rtype).NumIn":           ext۰reflect۰rtype۰NumIn,
    64  		"(reflect.rtype).NumMethod":       ext۰reflect۰rtype۰NumMethod,
    65  		"(reflect.rtype).NumOut":          ext۰reflect۰rtype۰NumOut,
    66  		"(reflect.rtype).Out":             ext۰reflect۰rtype۰Out,
    67  		"(reflect.rtype).Size":            ext۰reflect۰rtype۰Size,
    68  		"(reflect.rtype).String":          ext۰reflect۰rtype۰String,
    69  		"bytes.Equal":                     ext۰bytes۰Equal,
    70  		"bytes.IndexByte":                 ext۰bytes۰IndexByte,
    71  		"fmt.Sprint":                      ext۰fmt۰Sprint,
    72  		"math.Abs":                        ext۰math۰Abs,
    73  		"math.Exp":                        ext۰math۰Exp,
    74  		"math.Float32bits":                ext۰math۰Float32bits,
    75  		"math.Float32frombits":            ext۰math۰Float32frombits,
    76  		"math.Float64bits":                ext۰math۰Float64bits,
    77  		"math.Float64frombits":            ext۰math۰Float64frombits,
    78  		"math.Inf":                        ext۰math۰Inf,
    79  		"math.IsNaN":                      ext۰math۰IsNaN,
    80  		"math.Ldexp":                      ext۰math۰Ldexp,
    81  		"math.Log":                        ext۰math۰Log,
    82  		"math.Min":                        ext۰math۰Min,
    83  		"math.NaN":                        ext۰math۰NaN,
    84  		"math.Sqrt":                       ext۰math۰Sqrt,
    85  		"os.Exit":                         ext۰os۰Exit,
    86  		"os.Getenv":                       ext۰os۰Getenv,
    87  		"reflect.New":                     ext۰reflect۰New,
    88  		"reflect.SliceOf":                 ext۰reflect۰SliceOf,
    89  		"reflect.TypeOf":                  ext۰reflect۰TypeOf,
    90  		"reflect.ValueOf":                 ext۰reflect۰ValueOf,
    91  		"reflect.Zero":                    ext۰reflect۰Zero,
    92  		"runtime.Breakpoint":              ext۰runtime۰Breakpoint,
    93  		"runtime.GC":                      ext۰runtime۰GC,
    94  		"runtime.GOMAXPROCS":              ext۰runtime۰GOMAXPROCS,
    95  		"runtime.GOROOT":                  ext۰runtime۰GOROOT,
    96  		"runtime.Goexit":                  ext۰runtime۰Goexit,
    97  		"runtime.Gosched":                 ext۰runtime۰Gosched,
    98  		"runtime.NumCPU":                  ext۰runtime۰NumCPU,
    99  		"sort.Float64s":                   ext۰sort۰Float64s,
   100  		"sort.Ints":                       ext۰sort۰Ints,
   101  		"sort.Strings":                    ext۰sort۰Strings,
   102  		"strconv.Atoi":                    ext۰strconv۰Atoi,
   103  		"strconv.Itoa":                    ext۰strconv۰Itoa,
   104  		"strconv.FormatFloat":             ext۰strconv۰FormatFloat,
   105  		"strings.Count":                   ext۰strings۰Count,
   106  		"strings.EqualFold":               ext۰strings۰EqualFold,
   107  		"strings.Index":                   ext۰strings۰Index,
   108  		"strings.IndexByte":               ext۰strings۰IndexByte,
   109  		"strings.Replace":                 ext۰strings۰Replace,
   110  		"strings.ToLower":                 ext۰strings۰ToLower,
   111  		"time.Sleep":                      ext۰time۰Sleep,
   112  		"unicode/utf8.DecodeRuneInString": ext۰unicode۰utf8۰DecodeRuneInString,
   113  	} {
   114  		externals[k] = v
   115  	}
   116  }
   117  
   118  func ext۰bytes۰Equal(fr *frame, args []value) value {
   119  	// func Equal(a, b []byte) bool
   120  	a := args[0].([]value)
   121  	b := args[1].([]value)
   122  	if len(a) != len(b) {
   123  		return false
   124  	}
   125  	for i := range a {
   126  		if a[i] != b[i] {
   127  			return false
   128  		}
   129  	}
   130  	return true
   131  }
   132  
   133  func ext۰bytes۰IndexByte(fr *frame, args []value) value {
   134  	// func IndexByte(s []byte, c byte) int
   135  	s := args[0].([]value)
   136  	c := args[1].(byte)
   137  	for i, b := range s {
   138  		if b.(byte) == c {
   139  			return i
   140  		}
   141  	}
   142  	return -1
   143  }
   144  
   145  func ext۰math۰Float64frombits(fr *frame, args []value) value {
   146  	return math.Float64frombits(args[0].(uint64))
   147  }
   148  
   149  func ext۰math۰Float64bits(fr *frame, args []value) value {
   150  	return math.Float64bits(args[0].(float64))
   151  }
   152  
   153  func ext۰math۰Float32frombits(fr *frame, args []value) value {
   154  	return math.Float32frombits(args[0].(uint32))
   155  }
   156  
   157  func ext۰math۰Abs(fr *frame, args []value) value {
   158  	return math.Abs(args[0].(float64))
   159  }
   160  
   161  func ext۰math۰Exp(fr *frame, args []value) value {
   162  	return math.Exp(args[0].(float64))
   163  }
   164  
   165  func ext۰math۰Float32bits(fr *frame, args []value) value {
   166  	return math.Float32bits(args[0].(float32))
   167  }
   168  
   169  func ext۰math۰Min(fr *frame, args []value) value {
   170  	return math.Min(args[0].(float64), args[1].(float64))
   171  }
   172  
   173  func ext۰math۰NaN(fr *frame, args []value) value {
   174  	return math.NaN()
   175  }
   176  
   177  func ext۰math۰IsNaN(fr *frame, args []value) value {
   178  	return math.IsNaN(args[0].(float64))
   179  }
   180  
   181  func ext۰math۰Inf(fr *frame, args []value) value {
   182  	return math.Inf(args[0].(int))
   183  }
   184  
   185  func ext۰math۰Ldexp(fr *frame, args []value) value {
   186  	return math.Ldexp(args[0].(float64), args[1].(int))
   187  }
   188  
   189  func ext۰math۰Log(fr *frame, args []value) value {
   190  	return math.Log(args[0].(float64))
   191  }
   192  
   193  func ext۰math۰Sqrt(fr *frame, args []value) value {
   194  	return math.Sqrt(args[0].(float64))
   195  }
   196  
   197  func ext۰runtime۰Breakpoint(fr *frame, args []value) value {
   198  	runtime.Breakpoint()
   199  	return nil
   200  }
   201  
   202  func ext۰sort۰Ints(fr *frame, args []value) value {
   203  	x := args[0].([]value)
   204  	sort.Slice(x, func(i, j int) bool {
   205  		return x[i].(int) < x[j].(int)
   206  	})
   207  	return nil
   208  }
   209  func ext۰sort۰Strings(fr *frame, args []value) value {
   210  	x := args[0].([]value)
   211  	sort.Slice(x, func(i, j int) bool {
   212  		return x[i].(string) < x[j].(string)
   213  	})
   214  	return nil
   215  }
   216  func ext۰sort۰Float64s(fr *frame, args []value) value {
   217  	x := args[0].([]value)
   218  	sort.Slice(x, func(i, j int) bool {
   219  		return x[i].(float64) < x[j].(float64)
   220  	})
   221  	return nil
   222  }
   223  
   224  func ext۰strconv۰Atoi(fr *frame, args []value) value {
   225  	i, e := strconv.Atoi(args[0].(string))
   226  	if e != nil {
   227  		return tuple{i, iface{fr.i.runtimeErrorString, e.Error()}}
   228  	}
   229  	return tuple{i, iface{}}
   230  }
   231  func ext۰strconv۰Itoa(fr *frame, args []value) value {
   232  	return strconv.Itoa(args[0].(int))
   233  }
   234  func ext۰strconv۰FormatFloat(fr *frame, args []value) value {
   235  	return strconv.FormatFloat(args[0].(float64), args[1].(byte), args[2].(int), args[3].(int))
   236  }
   237  
   238  func ext۰strings۰Count(fr *frame, args []value) value {
   239  	return strings.Count(args[0].(string), args[1].(string))
   240  }
   241  
   242  func ext۰strings۰EqualFold(fr *frame, args []value) value {
   243  	return strings.EqualFold(args[0].(string), args[1].(string))
   244  }
   245  func ext۰strings۰IndexByte(fr *frame, args []value) value {
   246  	return strings.IndexByte(args[0].(string), args[1].(byte))
   247  }
   248  
   249  func ext۰strings۰Index(fr *frame, args []value) value {
   250  	return strings.Index(args[0].(string), args[1].(string))
   251  }
   252  
   253  func ext۰strings۰Replace(fr *frame, args []value) value {
   254  	// func Replace(s, old, new string, n int) string
   255  	s := args[0].(string)
   256  	new := args[1].(string)
   257  	old := args[2].(string)
   258  	n := args[3].(int)
   259  	return strings.Replace(s, old, new, n)
   260  }
   261  
   262  func ext۰strings۰ToLower(fr *frame, args []value) value {
   263  	return strings.ToLower(args[0].(string))
   264  }
   265  
   266  func ext۰runtime۰GOMAXPROCS(fr *frame, args []value) value {
   267  	// Ignore args[0]; don't let the interpreted program
   268  	// set the interpreter's GOMAXPROCS!
   269  	return runtime.GOMAXPROCS(0)
   270  }
   271  
   272  func ext۰runtime۰Goexit(fr *frame, args []value) value {
   273  	// TODO(adonovan): don't kill the interpreter's main goroutine.
   274  	runtime.Goexit()
   275  	return nil
   276  }
   277  
   278  func ext۰runtime۰GOROOT(fr *frame, args []value) value {
   279  	return runtime.GOROOT()
   280  }
   281  
   282  func ext۰runtime۰GC(fr *frame, args []value) value {
   283  	runtime.GC()
   284  	return nil
   285  }
   286  
   287  func ext۰runtime۰Gosched(fr *frame, args []value) value {
   288  	runtime.Gosched()
   289  	return nil
   290  }
   291  
   292  func ext۰runtime۰NumCPU(fr *frame, args []value) value {
   293  	return runtime.NumCPU()
   294  }
   295  
   296  func ext۰time۰Sleep(fr *frame, args []value) value {
   297  	time.Sleep(time.Duration(args[0].(int64)))
   298  	return nil
   299  }
   300  
   301  func valueToBytes(v value) []byte {
   302  	in := v.([]value)
   303  	b := make([]byte, len(in))
   304  	for i := range in {
   305  		b[i] = in[i].(byte)
   306  	}
   307  	return b
   308  }
   309  
   310  func ext۰os۰Getenv(fr *frame, args []value) value {
   311  	name := args[0].(string)
   312  	switch name {
   313  	case "GOSSAINTERP":
   314  		return "1"
   315  	case "GOARCH":
   316  		return "amd64"
   317  	case "GOOS":
   318  		return "linux"
   319  	}
   320  	return os.Getenv(name)
   321  }
   322  
   323  func ext۰os۰Exit(fr *frame, args []value) value {
   324  	panic(exitPanic(args[0].(int)))
   325  }
   326  
   327  func ext۰unicode۰utf8۰DecodeRuneInString(fr *frame, args []value) value {
   328  	r, n := utf8.DecodeRuneInString(args[0].(string))
   329  	return tuple{r, n}
   330  }
   331  
   332  // A fake function for turning an arbitrary value into a string.
   333  // Handles only the cases needed by the tests.
   334  // Uses same logic as 'print' built-in.
   335  func ext۰fmt۰Sprint(fr *frame, args []value) value {
   336  	buf := new(bytes.Buffer)
   337  	wasStr := false
   338  	for i, arg := range args[0].([]value) {
   339  		x := arg.(iface).v
   340  		_, isStr := x.(string)
   341  		if i > 0 && !wasStr && !isStr {
   342  			buf.WriteByte(' ')
   343  		}
   344  		wasStr = isStr
   345  		buf.WriteString(toString(x))
   346  	}
   347  	return buf.String()
   348  }
   349  

View as plain text