github.com/jd-ly/tools@v0.5.7/go/ssa/interp/external.go (about)

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