golang.org/x/tools@v0.21.1-0.20240520172518-788d39e776b1/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 "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.Copysign": ext۰math۰Copysign, 74 "math.Exp": ext۰math۰Exp, 75 "math.Float32bits": ext۰math۰Float32bits, 76 "math.Float32frombits": ext۰math۰Float32frombits, 77 "math.Float64bits": ext۰math۰Float64bits, 78 "math.Float64frombits": ext۰math۰Float64frombits, 79 "math.Inf": ext۰math۰Inf, 80 "math.IsNaN": ext۰math۰IsNaN, 81 "math.Ldexp": ext۰math۰Ldexp, 82 "math.Log": ext۰math۰Log, 83 "math.Min": ext۰math۰Min, 84 "math.NaN": ext۰math۰NaN, 85 "math.Sqrt": ext۰math۰Sqrt, 86 "os.Exit": ext۰os۰Exit, 87 "os.Getenv": ext۰os۰Getenv, 88 "reflect.New": ext۰reflect۰New, 89 "reflect.SliceOf": ext۰reflect۰SliceOf, 90 "reflect.TypeOf": ext۰reflect۰TypeOf, 91 "reflect.ValueOf": ext۰reflect۰ValueOf, 92 "reflect.Zero": ext۰reflect۰Zero, 93 "runtime.Breakpoint": ext۰runtime۰Breakpoint, 94 "runtime.GC": ext۰runtime۰GC, 95 "runtime.GOMAXPROCS": ext۰runtime۰GOMAXPROCS, 96 "runtime.GOROOT": ext۰runtime۰GOROOT, 97 "runtime.Goexit": ext۰runtime۰Goexit, 98 "runtime.Gosched": ext۰runtime۰Gosched, 99 "runtime.NumCPU": ext۰runtime۰NumCPU, 100 "sort.Float64s": ext۰sort۰Float64s, 101 "sort.Ints": ext۰sort۰Ints, 102 "sort.Strings": ext۰sort۰Strings, 103 "strconv.Atoi": ext۰strconv۰Atoi, 104 "strconv.Itoa": ext۰strconv۰Itoa, 105 "strconv.FormatFloat": ext۰strconv۰FormatFloat, 106 "strings.Count": ext۰strings۰Count, 107 "strings.EqualFold": ext۰strings۰EqualFold, 108 "strings.Index": ext۰strings۰Index, 109 "strings.IndexByte": ext۰strings۰IndexByte, 110 "strings.Replace": ext۰strings۰Replace, 111 "strings.ToLower": ext۰strings۰ToLower, 112 "time.Sleep": ext۰time۰Sleep, 113 "unicode/utf8.DecodeRuneInString": ext۰unicode۰utf8۰DecodeRuneInString, 114 } { 115 externals[k] = v 116 } 117 } 118 119 func ext۰bytes۰Equal(fr *frame, args []value) value { 120 // func Equal(a, b []byte) bool 121 a := args[0].([]value) 122 b := args[1].([]value) 123 if len(a) != len(b) { 124 return false 125 } 126 for i := range a { 127 if a[i] != b[i] { 128 return false 129 } 130 } 131 return true 132 } 133 134 func ext۰bytes۰IndexByte(fr *frame, args []value) value { 135 // func IndexByte(s []byte, c byte) int 136 s := args[0].([]value) 137 c := args[1].(byte) 138 for i, b := range s { 139 if b.(byte) == c { 140 return i 141 } 142 } 143 return -1 144 } 145 146 func ext۰math۰Float64frombits(fr *frame, args []value) value { 147 return math.Float64frombits(args[0].(uint64)) 148 } 149 150 func ext۰math۰Float64bits(fr *frame, args []value) value { 151 return math.Float64bits(args[0].(float64)) 152 } 153 154 func ext۰math۰Float32frombits(fr *frame, args []value) value { 155 return math.Float32frombits(args[0].(uint32)) 156 } 157 158 func ext۰math۰Abs(fr *frame, args []value) value { 159 return math.Abs(args[0].(float64)) 160 } 161 162 func ext۰math۰Copysign(fr *frame, args []value) value { 163 return math.Copysign(args[0].(float64), args[1].(float64)) 164 } 165 166 func ext۰math۰Exp(fr *frame, args []value) value { 167 return math.Exp(args[0].(float64)) 168 } 169 170 func ext۰math۰Float32bits(fr *frame, args []value) value { 171 return math.Float32bits(args[0].(float32)) 172 } 173 174 func ext۰math۰Min(fr *frame, args []value) value { 175 return math.Min(args[0].(float64), args[1].(float64)) 176 } 177 178 func ext۰math۰NaN(fr *frame, args []value) value { 179 return math.NaN() 180 } 181 182 func ext۰math۰IsNaN(fr *frame, args []value) value { 183 return math.IsNaN(args[0].(float64)) 184 } 185 186 func ext۰math۰Inf(fr *frame, args []value) value { 187 return math.Inf(args[0].(int)) 188 } 189 190 func ext۰math۰Ldexp(fr *frame, args []value) value { 191 return math.Ldexp(args[0].(float64), args[1].(int)) 192 } 193 194 func ext۰math۰Log(fr *frame, args []value) value { 195 return math.Log(args[0].(float64)) 196 } 197 198 func ext۰math۰Sqrt(fr *frame, args []value) value { 199 return math.Sqrt(args[0].(float64)) 200 } 201 202 func ext۰runtime۰Breakpoint(fr *frame, args []value) value { 203 runtime.Breakpoint() 204 return nil 205 } 206 207 func ext۰sort۰Ints(fr *frame, args []value) value { 208 x := args[0].([]value) 209 sort.Slice(x, func(i, j int) bool { 210 return x[i].(int) < x[j].(int) 211 }) 212 return nil 213 } 214 func ext۰sort۰Strings(fr *frame, args []value) value { 215 x := args[0].([]value) 216 sort.Slice(x, func(i, j int) bool { 217 return x[i].(string) < x[j].(string) 218 }) 219 return nil 220 } 221 func ext۰sort۰Float64s(fr *frame, args []value) value { 222 x := args[0].([]value) 223 sort.Slice(x, func(i, j int) bool { 224 return x[i].(float64) < x[j].(float64) 225 }) 226 return nil 227 } 228 229 func ext۰strconv۰Atoi(fr *frame, args []value) value { 230 i, e := strconv.Atoi(args[0].(string)) 231 if e != nil { 232 return tuple{i, iface{fr.i.runtimeErrorString, e.Error()}} 233 } 234 return tuple{i, iface{}} 235 } 236 func ext۰strconv۰Itoa(fr *frame, args []value) value { 237 return strconv.Itoa(args[0].(int)) 238 } 239 func ext۰strconv۰FormatFloat(fr *frame, args []value) value { 240 return strconv.FormatFloat(args[0].(float64), args[1].(byte), args[2].(int), args[3].(int)) 241 } 242 243 func ext۰strings۰Count(fr *frame, args []value) value { 244 return strings.Count(args[0].(string), args[1].(string)) 245 } 246 247 func ext۰strings۰EqualFold(fr *frame, args []value) value { 248 return strings.EqualFold(args[0].(string), args[1].(string)) 249 } 250 func ext۰strings۰IndexByte(fr *frame, args []value) value { 251 return strings.IndexByte(args[0].(string), args[1].(byte)) 252 } 253 254 func ext۰strings۰Index(fr *frame, args []value) value { 255 return strings.Index(args[0].(string), args[1].(string)) 256 } 257 258 func ext۰strings۰Replace(fr *frame, args []value) value { 259 // func Replace(s, old, new string, n int) string 260 s := args[0].(string) 261 new := args[1].(string) 262 old := args[2].(string) 263 n := args[3].(int) 264 return strings.Replace(s, old, new, n) 265 } 266 267 func ext۰strings۰ToLower(fr *frame, args []value) value { 268 return strings.ToLower(args[0].(string)) 269 } 270 271 func ext۰runtime۰GOMAXPROCS(fr *frame, args []value) value { 272 // Ignore args[0]; don't let the interpreted program 273 // set the interpreter's GOMAXPROCS! 274 return runtime.GOMAXPROCS(0) 275 } 276 277 func ext۰runtime۰Goexit(fr *frame, args []value) value { 278 // TODO(adonovan): don't kill the interpreter's main goroutine. 279 runtime.Goexit() 280 return nil 281 } 282 283 func ext۰runtime۰GOROOT(fr *frame, args []value) value { 284 return runtime.GOROOT() 285 } 286 287 func ext۰runtime۰GC(fr *frame, args []value) value { 288 runtime.GC() 289 return nil 290 } 291 292 func ext۰runtime۰Gosched(fr *frame, args []value) value { 293 runtime.Gosched() 294 return nil 295 } 296 297 func ext۰runtime۰NumCPU(fr *frame, args []value) value { 298 return runtime.NumCPU() 299 } 300 301 func ext۰time۰Sleep(fr *frame, args []value) value { 302 time.Sleep(time.Duration(args[0].(int64))) 303 return nil 304 } 305 306 func valueToBytes(v value) []byte { 307 in := v.([]value) 308 b := make([]byte, len(in)) 309 for i := range in { 310 b[i] = in[i].(byte) 311 } 312 return b 313 } 314 315 func ext۰os۰Getenv(fr *frame, args []value) value { 316 name := args[0].(string) 317 switch name { 318 case "GOSSAINTERP": 319 return "1" 320 } 321 return os.Getenv(name) 322 } 323 324 func ext۰os۰Exit(fr *frame, args []value) value { 325 panic(exitPanic(args[0].(int))) 326 } 327 328 func ext۰unicode۰utf8۰DecodeRuneInString(fr *frame, args []value) value { 329 r, n := utf8.DecodeRuneInString(args[0].(string)) 330 return tuple{r, n} 331 } 332 333 // A fake function for turning an arbitrary value into a string. 334 // Handles only the cases needed by the tests. 335 // Uses same logic as 'print' built-in. 336 func ext۰fmt۰Sprint(fr *frame, args []value) value { 337 buf := new(bytes.Buffer) 338 wasStr := false 339 for i, arg := range args[0].([]value) { 340 x := arg.(iface).v 341 _, isStr := x.(string) 342 if i > 0 && !wasStr && !isStr { 343 buf.WriteByte(' ') 344 } 345 wasStr = isStr 346 buf.WriteString(toString(x)) 347 } 348 return buf.String() 349 }