github.com/goplus/gox@v1.14.13-0.20240308130321-6ff7f61cfae8/builtin.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 "fmt" 18 "go/ast" 19 "go/constant" 20 "go/token" 21 "go/types" 22 "log" 23 "runtime" 24 "strings" 25 "syscall" 26 27 "golang.org/x/tools/go/types/typeutil" 28 ) 29 30 func newBuiltinDefault(pkg *Package, conf *Config) *types.Package { 31 builtin := types.NewPackage("", "") 32 InitBuiltin(pkg, builtin, conf) 33 return builtin 34 } 35 36 func InitBuiltin(pkg *Package, builtin *types.Package, conf *Config) { 37 initBuiltinOps(builtin, conf) 38 initBuiltinAssignOps(builtin) 39 initBuiltinFuncs(builtin) 40 initBuiltinTIs(pkg) 41 initUnsafeFuncs(pkg) 42 } 43 44 // ---------------------------------------------------------------------------- 45 46 type typeTParam struct { 47 name string 48 contract Contract 49 } 50 51 type typeParam struct { 52 name string 53 tidx int 54 } 55 56 // initBuiltinOps initializes operators of the builtin package. 57 func initBuiltinOps(builtin *types.Package, conf *Config) { 58 ops := [...]struct { 59 name string 60 tparams []typeTParam 61 params []typeParam 62 result int 63 }{ 64 {"Add", []typeTParam{{"T", addable}}, []typeParam{{"a", 0}, {"b", 0}}, 0}, 65 // func Gop_Add[T addable](a, b T) T 66 67 {"Sub", []typeTParam{{"T", number}}, []typeParam{{"a", 0}, {"b", 0}}, 0}, 68 // func Gop_Sub[T number](a, b T) T 69 70 {"Mul", []typeTParam{{"T", number}}, []typeParam{{"a", 0}, {"b", 0}}, 0}, 71 // func Gop_Mul[T number](a, b T) T 72 73 {"Quo", []typeTParam{{"T", number}}, []typeParam{{"a", 0}, {"b", 0}}, 0}, 74 // func Gop_Quo(a, b untyped_bigint) untyped_bigrat 75 // func Gop_Quo[T number](a, b T) T 76 77 {"Rem", []typeTParam{{"T", integer}}, []typeParam{{"a", 0}, {"b", 0}}, 0}, 78 // func Gop_Rem[T integer](a, b T) T 79 80 {"Or", []typeTParam{{"T", integer}}, []typeParam{{"a", 0}, {"b", 0}}, 0}, 81 // func Gop_Or[T integer](a, b T) T 82 83 {"Xor", []typeTParam{{"T", integer}}, []typeParam{{"a", 0}, {"b", 0}}, 0}, 84 // func Gop_Xor[T integer](a, b T) T 85 86 {"And", []typeTParam{{"T", integer}}, []typeParam{{"a", 0}, {"b", 0}}, 0}, 87 // func Gop_And[T integer](a, b T) T 88 89 {"AndNot", []typeTParam{{"T", integer}}, []typeParam{{"a", 0}, {"b", 0}}, 0}, 90 // func Gop_AndNot[T integer](a, b T) T 91 92 {"Lsh", []typeTParam{{"T", integer}, {"N", ninteger}}, []typeParam{{"a", 0}, {"n", 1}}, 0}, 93 // func Gop_Lsh[T integer, N ninteger](a T, n N) T 94 95 {"Rsh", []typeTParam{{"T", integer}, {"N", ninteger}}, []typeParam{{"a", 0}, {"n", 1}}, 0}, 96 // func Gop_Rsh[T integer, N ninteger](a T, n N) T 97 98 {"LT", []typeTParam{{"T", orderable}}, []typeParam{{"a", 0}, {"b", 0}}, -1}, 99 // func Gop_LT[T orderable](a, b T) untyped_bool 100 101 {"LE", []typeTParam{{"T", orderable}}, []typeParam{{"a", 0}, {"b", 0}}, -1}, 102 // func Gop_LE[T orderable](a, b T) untyped_bool 103 104 {"GT", []typeTParam{{"T", orderable}}, []typeParam{{"a", 0}, {"b", 0}}, -1}, 105 // func Gop_GT[T orderable](a, b T) untyped_bool 106 107 {"GE", []typeTParam{{"T", orderable}}, []typeParam{{"a", 0}, {"b", 0}}, -1}, 108 // func Gop_GE[T orderable](a, b T) untyped_bool 109 110 {"EQ", []typeTParam{{"T", comparable}}, []typeParam{{"a", 0}, {"b", 0}}, -1}, 111 // func Gop_EQ[T comparable](a, b T) untyped_bool 112 113 {"NE", []typeTParam{{"T", comparable}}, []typeParam{{"a", 0}, {"b", 0}}, -1}, 114 // func Gop_NE[T comparable](a, b T) untyped_bool 115 116 {"LAnd", []typeTParam{{"T", cbool}}, []typeParam{{"a", 0}, {"b", 0}}, 0}, 117 // func Gop_LAnd[T bool](a, b T) T 118 119 {"LOr", []typeTParam{{"T", cbool}}, []typeParam{{"a", 0}, {"b", 0}}, 0}, 120 // func Gop_LOr[T bool](a, b T) T 121 122 {"Neg", []typeTParam{{"T", number}}, []typeParam{{"a", 0}}, 0}, 123 // func Gop_Neg[T number](a T) T 124 125 {"Dup", []typeTParam{{"T", number}}, []typeParam{{"a", 0}}, 0}, 126 // func Gop_Dup[T number](a T) T 127 128 {"Not", []typeTParam{{"T", integer}}, []typeParam{{"a", 0}}, 0}, 129 // func Gop_Not[T integer](a T) T 130 131 {"LNot", []typeTParam{{"T", cbool}}, []typeParam{{"a", 0}}, 0}, 132 // func Gop_LNot[T bool](a T) T 133 } 134 gbl := builtin.Scope() 135 for _, op := range ops { 136 tparams := newTParams(op.tparams) 137 n := len(op.params) 138 params := make([]*types.Var, n) 139 for i, param := range op.params { 140 params[i] = types.NewParam(token.NoPos, builtin, param.name, tparams[param.tidx]) 141 } 142 var results *types.Tuple 143 if op.result != -2 { 144 var ret types.Type 145 if op.result < 0 { 146 ret = types.Typ[types.UntypedBool] 147 } else { 148 ret = tparams[op.result] 149 } 150 result := types.NewParam(token.NoPos, builtin, "", ret) 151 results = types.NewTuple(result) 152 } 153 tokFlag := nameToOps[op.name].Tok 154 if n == 1 { 155 tokFlag |= tokUnaryFlag 156 } 157 name := goxPrefix + op.name 158 tsig := NewTemplateSignature(tparams, nil, types.NewTuple(params...), results, false, tokFlag) 159 var tfn types.Object = NewTemplateFunc(token.NoPos, builtin, name, tsig) 160 if op.name == "Quo" { // func Gop_Quo(a, b untyped_bigint) untyped_bigrat 161 a := types.NewParam(token.NoPos, builtin, "a", conf.UntypedBigInt) 162 b := types.NewParam(token.NoPos, builtin, "b", conf.UntypedBigInt) 163 ret := types.NewParam(token.NoPos, builtin, "", conf.UntypedBigRat) 164 sig := NewTemplateSignature(nil, nil, types.NewTuple(a, b), types.NewTuple(ret), false, tokFlag) 165 quo := NewTemplateFunc(token.NoPos, builtin, name, sig) 166 tfn = NewOverloadFunc(token.NoPos, builtin, name, tfn, quo) 167 } 168 gbl.Insert(tfn) 169 } 170 171 // Inc++, Dec--, Recv<-, Addr& are special cases 172 gbl.Insert(NewInstruction(token.NoPos, builtin, goxPrefix+"Inc", incInstr{})) 173 gbl.Insert(NewInstruction(token.NoPos, builtin, goxPrefix+"Dec", decInstr{})) 174 gbl.Insert(NewInstruction(token.NoPos, builtin, goxPrefix+"Recv", recvInstr{})) 175 gbl.Insert(NewInstruction(token.NoPos, builtin, goxPrefix+"Addr", addrInstr{})) 176 } 177 178 func newTParams(params []typeTParam) []*TemplateParamType { 179 n := len(params) 180 tparams := make([]*TemplateParamType, n) 181 for i, tparam := range params { 182 tparams[i] = NewTemplateParamType(i, tparam.name, tparam.contract) 183 } 184 return tparams 185 } 186 187 // initBuiltinAssignOps initializes assign operators of the builtin package. 188 func initBuiltinAssignOps(builtin *types.Package) { 189 ops := [...]struct { 190 name string 191 t Contract 192 ninteger bool 193 }{ 194 {"AddAssign", addable, false}, 195 // func Gop_AddAssign[T addable](a *T, b T) 196 197 {"SubAssign", number, false}, 198 // func Gop_SubAssign[T number](a *T, b T) 199 200 {"MulAssign", number, false}, 201 // func Gop_MulAssign[T number](a *T, b T) 202 203 {"QuoAssign", number, false}, 204 // func Gop_QuoAssign[T number](a *T, b T) 205 206 {"RemAssign", integer, false}, 207 // func Gop_RemAssign[T integer](a *T, b T) 208 209 {"OrAssign", integer, false}, 210 // func Gop_OrAssign[T integer](a *T, b T) 211 212 {"XorAssign", integer, false}, 213 // func Gop_XorAssign[T integer](a *T, b T) 214 215 {"AndAssign", integer, false}, 216 // func Gop_Assign[T integer](a *T, b T) 217 218 {"AndNotAssign", integer, false}, 219 // func Gop_AndNotAssign[T integer](a *T, b T) 220 221 {"LshAssign", integer, true}, 222 // func Gop_LshAssign[T integer, N ninteger](a *T, n N) 223 224 {"RshAssign", integer, true}, 225 // func Gop_RshAssign[T integer, N ninteger](a *T, n N) 226 } 227 gbl := builtin.Scope() 228 for _, op := range ops { 229 tparams := newOpTParams(op.t, op.ninteger) 230 params := make([]*types.Var, 2) 231 params[0] = types.NewParam(token.NoPos, builtin, "a", NewPointer(tparams[0])) 232 if op.ninteger { 233 params[1] = types.NewParam(token.NoPos, builtin, "n", tparams[1]) 234 } else { 235 params[1] = types.NewParam(token.NoPos, builtin, "b", tparams[0]) 236 } 237 name := goxPrefix + op.name 238 tsig := NewTemplateSignature(tparams, nil, types.NewTuple(params...), nil, false, 0) 239 tfn := NewTemplateFunc(token.NoPos, builtin, name, tsig) 240 gbl.Insert(tfn) 241 } 242 } 243 244 func newOpTParams(t Contract, utinteger bool) []*TemplateParamType { 245 tparams := make([]*TemplateParamType, 1, 2) 246 tparams[0] = NewTemplateParamType(0, "T", t) 247 if utinteger { 248 tparams = append(tparams, NewTemplateParamType(1, "N", ninteger)) 249 } 250 return tparams 251 } 252 253 // ---------------------------------------------------------------------------- 254 255 type typeBParam struct { 256 name string 257 typ types.BasicKind 258 } 259 260 type typeBFunc struct { 261 params []typeBParam 262 result types.BasicKind 263 } 264 265 type xType = interface{} 266 type typeXParam struct { 267 name string 268 typ xType // tidx | types.Type 269 } 270 271 const ( 272 xtNone = iota << 16 273 xtEllipsis 274 xtSlice 275 xtMap 276 xtChanIn 277 ) 278 279 // initBuiltinFuncs initializes builtin functions of the builtin package. 280 func initBuiltinFuncs(builtin *types.Package) { 281 fns := [...]struct { 282 name string 283 tparams []typeTParam 284 params []typeXParam 285 result xType 286 }{ 287 {"copy", []typeTParam{{"Type", any}}, []typeXParam{{"dst", xtSlice}, {"src", xtSlice}}, types.Typ[types.Int]}, 288 // func [Type any] copy(dst, src []Type) int 289 290 {"close", []typeTParam{{"Type", any}}, []typeXParam{{"c", xtChanIn}}, nil}, 291 // func [Type any] close(c chan<- Type) 292 293 {"append", []typeTParam{{"Type", any}}, []typeXParam{{"slice", xtSlice}, {"elems", xtEllipsis}}, xtSlice}, 294 // func [Type any] append(slice []Type, elems ...Type) []Type 295 296 {"delete", []typeTParam{{"Key", comparable}, {"Elem", any}}, []typeXParam{{"m", xtMap}, {"key", 0}}, nil}, 297 // func [Key comparable, Elem any] delete(m map[Key]Elem, key Key) 298 } 299 gbl := builtin.Scope() 300 for _, fn := range fns { 301 tparams := newTParams(fn.tparams) 302 n := len(fn.params) 303 params := make([]*types.Var, n) 304 for i, param := range fn.params { 305 typ := newXParamType(tparams, param.typ) 306 params[i] = types.NewParam(token.NoPos, builtin, param.name, typ) 307 } 308 var ellipsis bool 309 if tidx, ok := fn.params[n-1].typ.(int); ok && (tidx&xtEllipsis) != 0 { 310 ellipsis = true 311 } 312 var results *types.Tuple 313 if fn.result != nil { 314 typ := newXParamType(tparams, fn.result) 315 results = types.NewTuple(types.NewParam(token.NoPos, builtin, "", typ)) 316 } 317 tsig := NewTemplateSignature(tparams, nil, types.NewTuple(params...), results, ellipsis, tokFlagApproxType) 318 var tfn types.Object = NewTemplateFunc(token.NoPos, builtin, fn.name, tsig) 319 if fn.name == "append" { // append is a special case 320 appendString := NewInstruction(token.NoPos, builtin, "append", appendStringInstr{}) 321 tfn = NewOverloadFunc(token.NoPos, builtin, "append", appendString, tfn) 322 } else if fn.name == "copy" { 323 // func [S string] copy(dst []byte, src S) int 324 tparams := newTParams([]typeTParam{{"S", tstring}}) 325 dst := types.NewParam(token.NoPos, builtin, "dst", types.NewSlice(types.Typ[types.Byte])) 326 src := types.NewParam(token.NoPos, builtin, "src", tparams[0]) 327 ret := types.NewParam(token.NoPos, builtin, "", types.Typ[types.Int]) 328 tsig := NewTemplateSignature(tparams, nil, types.NewTuple(dst, src), types.NewTuple(ret), false) 329 copyString := NewTemplateFunc(token.NoPos, builtin, "copy", tsig) 330 tfn = NewOverloadFunc(token.NoPos, builtin, "copy", copyString, tfn) 331 } 332 gbl.Insert(tfn) 333 } 334 overloads := [...]struct { 335 name string 336 fns [3]typeBFunc 337 }{ 338 {"complex", [...]typeBFunc{ 339 {[]typeBParam{{"r", types.UntypedFloat}, {"i", types.UntypedFloat}}, types.UntypedComplex}, 340 {[]typeBParam{{"r", types.Float32}, {"i", types.Float32}}, types.Complex64}, 341 {[]typeBParam{{"r", types.Float64}, {"i", types.Float64}}, types.Complex128}, 342 }}, 343 // func complex(r, i untyped_float) untyped_complex 344 // func complex(r, i float32) complex64 345 // func complex(r, i float64) complex128 346 347 {"real", [...]typeBFunc{ 348 {[]typeBParam{{"c", types.UntypedComplex}}, types.UntypedFloat}, 349 {[]typeBParam{{"c", types.Complex64}}, types.Float32}, 350 {[]typeBParam{{"c", types.Complex128}}, types.Float64}, 351 }}, 352 // func real(c untyped_complex) untyped_float 353 // func real(c complex64) float32 354 // func real(c complex128) float64 355 356 {"imag", [...]typeBFunc{ 357 {[]typeBParam{{"c", types.UntypedComplex}}, types.UntypedFloat}, 358 {[]typeBParam{{"c", types.Complex64}}, types.Float32}, 359 {[]typeBParam{{"c", types.Complex128}}, types.Float64}, 360 }}, 361 // func imag(c untyped_complex) untyped_float 362 // func imag(c complex64) float32 363 // func imag(c complex128) float64 364 } 365 for _, overload := range overloads { 366 fns := []types.Object{ 367 newBFunc(builtin, overload.name, overload.fns[0]), 368 newBFunc(builtin, overload.name, overload.fns[1]), 369 newBFunc(builtin, overload.name, overload.fns[2]), 370 } 371 gbl.Insert(NewOverloadFunc(token.NoPos, builtin, overload.name, fns...)) 372 } 373 // func panic(v interface{}) 374 // func recover() interface{} 375 // func print(args ...interface{}) 376 // func println(args ...interface{}) 377 emptyIntfVar := types.NewVar(token.NoPos, builtin, "v", TyEmptyInterface) 378 emptyIntfTuple := types.NewTuple(emptyIntfVar) 379 emptyIntfSlice := types.NewSlice(TyEmptyInterface) 380 emptyIntfSliceVar := types.NewVar(token.NoPos, builtin, "args", emptyIntfSlice) 381 emptyIntfSliceTuple := types.NewTuple(emptyIntfSliceVar) 382 gbl.Insert(types.NewFunc(token.NoPos, builtin, "panic", types.NewSignatureType(nil, nil, nil, emptyIntfTuple, nil, false))) 383 gbl.Insert(types.NewFunc(token.NoPos, builtin, "recover", types.NewSignatureType(nil, nil, nil, nil, emptyIntfTuple, false))) 384 gbl.Insert(types.NewFunc(token.NoPos, builtin, "print", types.NewSignatureType(nil, nil, nil, emptyIntfSliceTuple, nil, true))) 385 gbl.Insert(types.NewFunc(token.NoPos, builtin, "println", types.NewSignatureType(nil, nil, nil, emptyIntfSliceTuple, nil, true))) 386 387 // new & make are special cases, they require to pass a type. 388 gbl.Insert(NewInstruction(token.NoPos, builtin, "new", newInstr{})) 389 gbl.Insert(NewInstruction(token.NoPos, builtin, "make", makeInstr{})) 390 391 // len & cap are special cases, because they may return a constant value. 392 gbl.Insert(NewInstruction(token.NoPos, builtin, "len", lenInstr{})) 393 gbl.Insert(NewInstruction(token.NoPos, builtin, "cap", capInstr{})) 394 } 395 396 func initUnsafeFuncs(pkg *Package) { 397 unsafe := types.NewPackage("unsafe", "unsafe") 398 gbl := unsafe.Scope() 399 // unsafe 400 gbl.Insert(NewInstruction(token.NoPos, types.Unsafe, "Sizeof", unsafeSizeofInstr{})) 401 gbl.Insert(NewInstruction(token.NoPos, types.Unsafe, "Alignof", unsafeAlignofInstr{})) 402 gbl.Insert(NewInstruction(token.NoPos, types.Unsafe, "Offsetof", unsafeOffsetofInstr{})) 403 gbl.Insert(NewInstruction(token.NoPos, types.Unsafe, "Add", unsafeAddInstr{})) 404 gbl.Insert(NewInstruction(token.NoPos, types.Unsafe, "Slice", unsafeSliceInstr{})) 405 pkg.unsafe_.Types = unsafe 406 } 407 408 func newBFunc(builtin *types.Package, name string, t typeBFunc) types.Object { 409 n := len(t.params) 410 vars := make([]*types.Var, n) 411 for i, param := range t.params { 412 vars[i] = types.NewParam(token.NoPos, builtin, param.name, types.Typ[param.typ]) 413 } 414 result := types.NewParam(token.NoPos, builtin, "", types.Typ[t.result]) 415 sig := types.NewSignatureType(nil, nil, nil, types.NewTuple(vars...), types.NewTuple(result), false) 416 return types.NewFunc(token.NoPos, builtin, name, sig) 417 } 418 419 func newXParamType(tparams []*TemplateParamType, x xType) types.Type { 420 if tidx, ok := x.(int); ok { 421 idx := tidx & 0xffff 422 switch tidx &^ 0xffff { 423 case xtNone: 424 return tparams[idx] 425 case xtEllipsis, xtSlice: 426 return NewSlice(tparams[idx]) 427 case xtMap: 428 return NewMap(tparams[idx], tparams[idx+1]) 429 case xtChanIn: 430 return NewChan(types.SendOnly, tparams[idx]) 431 default: 432 panic("TODO: newXParamType - unexpected xType") 433 } 434 } 435 return x.(types.Type) 436 } 437 438 // ---------------------------------------------------------------------------- 439 440 type builtinFn struct { 441 fn interface{} 442 narg int 443 } 444 445 var ( 446 builtinFns = map[string]builtinFn{ 447 "complex": {makeComplex, 2}, 448 "real": {constant.Real, 1}, 449 "imag": {constant.Imag, 1}, 450 } 451 ) 452 453 func builtinCall(fn *Element, args []*Element) constant.Value { 454 if fn, ok := fn.Val.(*ast.Ident); ok { 455 if bfn, ok := builtinFns[fn.Name]; ok { 456 a := args[0].CVal 457 switch bfn.narg { 458 case 1: 459 return bfn.fn.(func(a constant.Value) constant.Value)(a) 460 case 2: 461 b := args[1].CVal 462 return bfn.fn.(func(a, b constant.Value) constant.Value)(a, b) 463 } 464 } 465 panic("builtinCall: expect constant") 466 } 467 return nil 468 } 469 470 func makeComplex(re, im constant.Value) constant.Value { 471 return constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) 472 } 473 474 type appendStringInstr struct { 475 } 476 477 // func append(slice []byte, val ..string) []byte 478 func (p appendStringInstr) Call(pkg *Package, args []*Element, flags InstrFlags, src ast.Node) (ret *Element, err error) { 479 if len(args) == 2 && flags != 0 { 480 if t, ok := args[0].Type.(*types.Slice); ok { 481 if elem, ok := t.Elem().(*types.Basic); ok && elem.Kind() == types.Byte { 482 if v, ok := args[1].Type.(*types.Basic); ok { 483 if v.Kind() == types.String || v.Kind() == types.UntypedString { 484 return &Element{ 485 Val: &ast.CallExpr{ 486 Fun: identAppend, 487 Args: []ast.Expr{args[0].Val, args[1].Val}, 488 Ellipsis: 1, 489 }, 490 Type: t, 491 }, nil 492 } 493 } 494 } 495 } 496 } 497 return nil, syscall.EINVAL 498 } 499 500 type lenInstr struct { 501 } 502 503 type capInstr struct { 504 } 505 506 // func [Type lenable] len(v Type) int 507 func (p lenInstr) Call(pkg *Package, args []*Element, flags InstrFlags, src ast.Node) (ret *Element, err error) { 508 if len(args) != 1 { 509 panic("TODO: len() should have one parameter") 510 } 511 var cval constant.Value 512 switch t := args[0].Type.(type) { 513 case *types.Basic: 514 switch t.Kind() { 515 case types.String, types.UntypedString: 516 if v := args[0].CVal; v != nil { 517 n := len(constant.StringVal(v)) 518 cval = constant.MakeInt64(int64(n)) 519 } 520 default: 521 panic("TODO: call len() to a basic type") 522 } 523 case *types.Array: 524 cval = constant.MakeInt64(t.Len()) 525 case *types.Pointer: 526 if tt, ok := t.Elem().(*types.Array); ok { 527 cval = constant.MakeInt64(tt.Len()) 528 } else { 529 panic("TODO: call len() to a pointer") 530 } 531 default: 532 if !lenable.Match(pkg, t) { 533 log.Panicln("TODO: can't call len() to", t) 534 } 535 } 536 ret = &Element{ 537 Val: &ast.CallExpr{Fun: identLen, Args: []ast.Expr{args[0].Val}}, 538 Type: types.Typ[types.Int], 539 CVal: cval, 540 } 541 return 542 } 543 544 // func [Type capable] cap(v Type) int 545 func (p capInstr) Call(pkg *Package, args []*Element, flags InstrFlags, src ast.Node) (ret *Element, err error) { 546 if len(args) != 1 { 547 panic("TODO: cap() should have one parameter") 548 } 549 var cval constant.Value 550 switch t := args[0].Type.(type) { 551 case *types.Array: 552 cval = constant.MakeInt64(t.Len()) 553 case *types.Pointer: 554 if tt, ok := t.Elem().(*types.Array); ok { 555 cval = constant.MakeInt64(tt.Len()) 556 } else { 557 panic("TODO: call cap() to a pointer") 558 } 559 default: 560 if !capable.Match(pkg, t) { 561 log.Panicln("TODO: can't call cap() to", t) 562 } 563 } 564 ret = &Element{ 565 Val: &ast.CallExpr{Fun: identCap, Args: []ast.Expr{args[0].Val}}, 566 Type: types.Typ[types.Int], 567 CVal: cval, 568 } 569 return 570 } 571 572 type incInstr struct { 573 } 574 575 type decInstr struct { 576 } 577 578 // val++ 579 func (p incInstr) Call(pkg *Package, args []*Element, flags InstrFlags, src ast.Node) (ret *Element, err error) { 580 return callIncDec(pkg, args, token.INC) 581 } 582 583 // val-- 584 func (p decInstr) Call(pkg *Package, args []*Element, flags InstrFlags, src ast.Node) (ret *Element, err error) { 585 return callIncDec(pkg, args, token.DEC) 586 } 587 588 func callIncDec(pkg *Package, args []*Element, tok token.Token) (ret *Element, err error) { 589 if len(args) != 1 { 590 panic("TODO: please use val" + tok.String()) 591 } 592 t, ok := args[0].Type.(*refType) 593 if !ok { 594 panic("TODO: not addressable") 595 } 596 cb := &pkg.cb 597 if !isNumeric(cb, t.typ) { 598 text, pos := cb.loadExpr(args[0].Src) 599 cb.panicCodeErrorf(pos, "invalid operation: %s%v (non-numeric type %v)", text, tok, t.typ) 600 } 601 cb.emitStmt(&ast.IncDecStmt{X: args[0].Val, Tok: tok}) 602 return 603 } 604 605 func isNumeric(cb *CodeBuilder, typ types.Type) bool { 606 const ( 607 numericFlags = types.IsInteger | types.IsFloat | types.IsComplex 608 ) 609 if t, ok := typ.(*types.Named); ok { 610 typ = cb.getUnderlying(t) 611 } 612 if t, ok := typ.(*types.Basic); ok { 613 return (t.Info() & numericFlags) != 0 614 } 615 return false 616 } 617 618 type recvInstr struct { 619 } 620 621 // <-ch 622 func (p recvInstr) Call(pkg *Package, args []*Element, flags InstrFlags, src ast.Node) (ret *Element, err error) { 623 if len(args) != 1 { 624 panic("TODO: please use <-ch") 625 } 626 t0 := args[0].Type 627 retry: 628 switch t := t0.(type) { 629 case *types.Chan: 630 if t.Dir() != types.SendOnly { 631 typ := t.Elem() 632 if flags != 0 { // twoValue mode 633 typ = types.NewTuple( 634 pkg.NewParam(token.NoPos, "", typ), 635 pkg.NewParam(token.NoPos, "", types.Typ[types.Bool])) 636 } 637 ret = &Element{Val: &ast.UnaryExpr{Op: token.ARROW, X: args[0].Val}, Type: typ} 638 return 639 } 640 panic("TODO: <-ch is a send only chan") 641 case *types.Named: 642 t0 = pkg.cb.getUnderlying(t) 643 goto retry 644 } 645 panic("TODO: <-ch not a chan type") 646 } 647 648 type addrInstr struct { 649 } 650 651 // &variable 652 func (p addrInstr) Call(pkg *Package, args []*Element, flags InstrFlags, src ast.Node) (ret *Element, err error) { 653 if len(args) != 1 { 654 panic("TODO: please use &variable to get its address") 655 } 656 // TODO: can't take addr(&) to a non-reference type 657 t, _ := DerefType(args[0].Type) 658 ret = &Element{Val: &ast.UnaryExpr{Op: token.AND, X: args[0].Val}, Type: types.NewPointer(t)} 659 return 660 } 661 662 type newInstr struct { 663 } 664 665 // func [] new(T any) *T 666 func (p newInstr) Call(pkg *Package, args []*Element, flags InstrFlags, src ast.Node) (ret *Element, err error) { 667 if len(args) != 1 { 668 panic("TODO: use new(T) please") 669 } 670 ttyp, ok := args[0].Type.(*TypeType) 671 if !ok { 672 panic("TODO: new arg isn't a type") 673 } 674 typ := ttyp.Type() 675 ret = &Element{ 676 Val: &ast.CallExpr{ 677 Fun: identNew, 678 Args: []ast.Expr{args[0].Val}, 679 }, 680 Type: types.NewPointer(typ), 681 } 682 return 683 } 684 685 type makeInstr struct { 686 } 687 688 // func [N ninteger] make(Type makable, size ...N) Type 689 func (p makeInstr) Call(pkg *Package, args []*Element, flags InstrFlags, src ast.Node) (ret *Element, err error) { 690 n := len(args) 691 if n == 0 { 692 panic("TODO: make without args") 693 } else if n > 3 { 694 n, args = 3, args[:3] 695 } 696 ttyp, ok := args[0].Type.(*TypeType) 697 if !ok { 698 panic("TODO: make: first arg isn't a type") 699 } 700 typ := ttyp.Type() 701 if !makable.Match(pkg, typ) { 702 log.Panicln("TODO: can't make this type -", typ) 703 } 704 argsExpr := make([]ast.Expr, n) 705 for i, arg := range args { 706 argsExpr[i] = arg.Val 707 } 708 ret = &Element{ 709 Val: &ast.CallExpr{ 710 Fun: identMake, 711 Args: argsExpr, 712 }, 713 Type: typ, 714 } 715 return 716 } 717 718 func checkArgsCount(pkg *Package, fn string, n int, args int, src ast.Node) { 719 if args == n { 720 return 721 } 722 cb := &pkg.cb 723 text, pos := cb.loadExpr(src) 724 if pos != token.NoPos { 725 pos += token.Pos(len(fn)) 726 } 727 if args < n { 728 cb.panicCodeErrorf(pos, "missing argument to function call: %v", text) 729 } 730 cb.panicCodeErrorf(pos, "too many arguments to function call: %v", text) 731 } 732 733 var ( 734 std types.Sizes 735 ) 736 737 func init() { 738 if runtime.Compiler == "gopherjs" { 739 std = &types.StdSizes{WordSize: 4, MaxAlign: 4} 740 } else { 741 std = types.SizesFor(runtime.Compiler, runtime.GOARCH) 742 } 743 } 744 745 func unsafeRef(name string) Ref { 746 return PkgRef{types.Unsafe}.Ref(name) 747 } 748 749 type unsafeSizeofInstr struct{} 750 751 // func unsafe.Sizeof(x ArbitraryType) uintptr 752 func (p unsafeSizeofInstr) Call(pkg *Package, args []*Element, flags InstrFlags, src ast.Node) (ret *Element, err error) { 753 checkArgsCount(pkg, "unsafe.Sizeof", 1, len(args), src) 754 755 typ := types.Default(realType(args[0].Type)) 756 fn := toObjectExpr(pkg, unsafeRef("Sizeof")) 757 ret = &Element{ 758 Val: &ast.CallExpr{Fun: fn, Args: []ast.Expr{args[0].Val}}, 759 Type: types.Typ[types.Uintptr], 760 CVal: constant.MakeInt64(std.Sizeof(typ)), 761 Src: src, 762 } 763 return 764 } 765 766 type unsafeAlignofInstr struct{} 767 768 // func unsafe.Alignof(x ArbitraryType) uintptr 769 func (p unsafeAlignofInstr) Call(pkg *Package, args []*Element, flags InstrFlags, src ast.Node) (ret *Element, err error) { 770 checkArgsCount(pkg, "unsafe.Alignof", 1, len(args), src) 771 772 typ := types.Default(realType(args[0].Type)) 773 fn := toObjectExpr(pkg, unsafeRef("Alignof")) 774 ret = &Element{ 775 Val: &ast.CallExpr{Fun: fn, Args: []ast.Expr{args[0].Val}}, 776 Type: types.Typ[types.Uintptr], 777 CVal: constant.MakeInt64(std.Alignof(typ)), 778 Src: src, 779 } 780 return 781 } 782 783 type unsafeOffsetofInstr struct{} 784 785 // func unsafe.Offsetof(x ArbitraryType) uintptr 786 func (p unsafeOffsetofInstr) Call(pkg *Package, args []*Element, flags InstrFlags, src ast.Node) (ret *Element, err error) { 787 checkArgsCount(pkg, "unsafe.Offsetof", 1, len(args), src) 788 789 var sel *ast.SelectorExpr 790 var ok bool 791 if sel, ok = args[0].Val.(*ast.SelectorExpr); !ok { 792 s, pos := pkg.cb.loadExpr(src) 793 if pos != token.NoPos { 794 pos += token.Pos(len("unsafe.Offsetof")) 795 } 796 pkg.cb.panicCodeErrorf(pos, "invalid expression %v", s) 797 } 798 if _, ok = args[0].Type.(*types.Signature); ok { 799 s, pos := pkg.cb.loadExpr(src) 800 if pos != token.NoPos { 801 pos += token.Pos(len("unsafe.Offsetof")) 802 } 803 pkg.cb.panicCodeErrorf(pos, "invalid expression %v: argument is a method value", s) 804 } 805 recv := denoteRecv(sel) 806 typ := getStruct(pkg, recv.Type) 807 _, index, _ := types.LookupFieldOrMethod(typ, false, pkg.Types, sel.Sel.Name) 808 offset, err := offsetof(pkg, typ, index, recv.Src, sel.Sel.Name) 809 if err != nil { 810 _, pos := pkg.cb.loadExpr(src) 811 if pos != token.NoPos { 812 pos += token.Pos(len("unsafe.Offsetof")) 813 } 814 pkg.cb.panicCodeErrorf(pos, "%v", err) 815 } 816 //var offset int64 817 fn := toObjectExpr(pkg, unsafeRef("Offsetof")) 818 ret = &Element{ 819 Val: &ast.CallExpr{Fun: fn, Args: []ast.Expr{args[0].Val}}, 820 Type: types.Typ[types.Uintptr], 821 CVal: constant.MakeInt64(offset), 822 Src: src, 823 } 824 return 825 } 826 827 func getStruct(pkg *Package, typ types.Type) *types.Struct { 828 retry: 829 switch t := typ.(type) { 830 case *types.Struct: 831 return t 832 case *types.Pointer: 833 typ = t.Elem() 834 goto retry 835 case *types.Named: 836 typ = pkg.cb.getUnderlying(t) 837 goto retry 838 } 839 return nil 840 } 841 842 func offsetsof(T *types.Struct) []int64 { 843 var fields []*types.Var 844 for i := 0; i < T.NumFields(); i++ { 845 fields = append(fields, T.Field(i)) 846 } 847 return std.Offsetsof(fields) 848 } 849 850 // offsetof returns the offset of the field specified via 851 // the index sequence relative to typ. All embedded fields 852 // must be structs (rather than pointer to structs). 853 func offsetof(pkg *Package, typ types.Type, index []int, recv ast.Node, sel string) (int64, error) { 854 var o int64 855 var typList []string 856 var indirectType int 857 for n, i := range index { 858 if n > 0 { 859 if t, ok := typ.(*types.Pointer); ok { 860 typ = t.Elem() 861 indirectType = n 862 } 863 if t, ok := typ.(*types.Named); ok { 864 typList = append(typList, t.Obj().Name()) 865 typ = t.Underlying() 866 } 867 } 868 s := typ.(*types.Struct) 869 o += offsetsof(s)[i] 870 typ = s.Field(i).Type() 871 } 872 if indirectType > 0 { 873 s, _ := pkg.cb.loadExpr(recv) 874 return -1, fmt.Errorf("invalid expression unsafe.Offsetof(%v.%v.%v): selector implies indirection of embedded %v.%v", 875 s, strings.Join(typList, "."), sel, 876 s, strings.Join(typList[:indirectType], ".")) 877 } 878 return o, nil 879 } 880 881 type unsafeAddInstr struct{} 882 883 // func unsafe.Add(ptr Pointer, len IntegerType) Pointer 884 func (p unsafeAddInstr) Call(pkg *Package, args []*Element, flags InstrFlags, src ast.Node) (ret *Element, err error) { 885 checkArgsCount(pkg, "unsafe.Add", 2, len(args), src) 886 887 if ts := args[0].Type.String(); ts != "unsafe.Pointer" { 888 s, _ := pkg.cb.loadExpr(args[0].Src) 889 pos := getSrcPos(src) 890 if pos != token.NoPos { 891 pos += token.Pos(len("unsafe.Add")) 892 } 893 pkg.cb.panicCodeErrorf(pos, "cannot use %v (type %v) as type unsafe.Pointer in argument to unsafe.Add", s, ts) 894 } 895 if t := args[1].Type; !ninteger.Match(pkg, t) { 896 s, _ := pkg.cb.loadExpr(args[1].Src) 897 pos := getSrcPos(src) 898 if pos != token.NoPos { 899 pos += token.Pos(len("unsafe.Add")) 900 } 901 pkg.cb.panicCodeErrorf(pos, "cannot use %v (type %v) as type int", s, t) 902 } 903 fn := toObjectExpr(pkg, unsafeRef("Sizeof")).(*ast.SelectorExpr) 904 fn.Sel.Name = "Add" // only in go v1.7+ 905 ret = &Element{ 906 Val: &ast.CallExpr{Fun: fn, Args: []ast.Expr{args[0].Val, args[1].Val}}, 907 Type: types.Typ[types.UnsafePointer], 908 } 909 return 910 } 911 912 type unsafeSliceInstr struct{} 913 914 // func unsafe.Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType 915 func (p unsafeSliceInstr) Call(pkg *Package, args []*Element, flags InstrFlags, src ast.Node) (ret *Element, err error) { 916 checkArgsCount(pkg, "unsafe.Slice", 2, len(args), src) 917 918 t0, ok := args[0].Type.(*types.Pointer) 919 if !ok { 920 pos := getSrcPos(src) 921 if pos != token.NoPos { 922 pos += token.Pos(len("unsafe.Slice")) 923 } 924 pkg.cb.panicCodeErrorf(pos, "first argument to unsafe.Slice must be pointer; have %v", args[0].Type) 925 } 926 if t := args[1].Type; !ninteger.Match(pkg, t) { 927 pos := getSrcPos(src) 928 if pos != token.NoPos { 929 pos += token.Pos(len("unsafe.Slice")) 930 } 931 pkg.cb.panicCodeErrorf(pos, "non-integer len argument in unsafe.Slice - %v", t) 932 } 933 fn := toObjectExpr(pkg, unsafeRef("Sizeof")).(*ast.SelectorExpr) 934 fn.Sel.Name = "Slice" // only in go v1.7+ 935 ret = &Element{ 936 Val: &ast.CallExpr{Fun: fn, Args: []ast.Expr{args[0].Val, args[1].Val}}, 937 Type: types.NewSlice(t0.Elem()), 938 } 939 return 940 } 941 942 // ---------------------------------------------------------------------------- 943 944 type basicContract struct { 945 kinds uint64 946 desc string 947 } 948 949 func (p *basicContract) Match(pkg *Package, typ types.Type) bool { 950 retry: 951 switch t := typ.(type) { 952 case *types.Basic: 953 if (uint64(1)<<t.Kind())&p.kinds != 0 { 954 return true 955 } 956 case *types.Named: 957 typ = pkg.cb.getUnderlying(t) 958 goto retry 959 } 960 return false 961 } 962 963 func (p *basicContract) String() string { 964 return p.desc 965 } 966 967 const ( 968 // int, int64, int32, int16, int8, uint, uintptr, uint64, uint32, uint16, uint8 969 kindsInteger = (1 << types.Int) | (1 << types.Int64) | (1 << types.Int32) | (1 << types.Int16) | (1 << types.Int8) | 970 (1 << types.Uint) | (1 << types.Uintptr) | (1 << types.Uint64) | (1 << types.Uint32) | (1 << types.Uint16) | (1 << types.Uint8) | 971 (1 << types.UntypedInt) | (1 << types.UntypedRune) 972 973 // float32, float64 974 kindsFloat = (1 << types.Float32) | (1 << types.Float64) | (1 << types.UntypedFloat) 975 976 // complex64, complex128 977 kindsComplex = (1 << types.Complex64) | (1 << types.Complex128) | (1 << types.UntypedComplex) 978 979 // string 980 kindsString = (1 << types.String) | (1 << types.UntypedString) 981 982 // bool 983 kindsBool = (1 << types.Bool) | (1 << types.UntypedBool) 984 985 // integer, float, complex 986 kindsNumber = kindsInteger | kindsFloat | kindsComplex 987 988 // number, string 989 kindsAddable = kindsNumber | kindsString 990 991 // integer, float, string 992 kindsOrderable = kindsInteger | kindsFloat | kindsString 993 ) 994 995 // ---------------------------------------------------------------------------- 996 997 type comparableT struct { 998 // addable 999 // type bool, interface, pointer, array, chan, struct 1000 // NOTE: slice/map/func is very special, can only be compared to nil 1001 } 1002 1003 func (p comparableT) Match(pkg *Package, typ types.Type) bool { 1004 retry: 1005 switch t := typ.(type) { 1006 case *types.Basic: 1007 return t.Kind() != types.UntypedNil // excluding nil 1008 case *types.Named: 1009 typ = pkg.cb.getUnderlying(t) 1010 goto retry 1011 case *types.Slice: // slice/map/func is very special 1012 return false 1013 case *types.Map: 1014 return false 1015 case *types.Signature: 1016 return false 1017 case *TemplateSignature: 1018 return false 1019 case *TemplateParamType: 1020 panic("TODO: unexpected - compare to template param type?") 1021 case *types.Tuple: 1022 panic("TODO: unexpected - compare to tuple type?") 1023 case *unboundType: 1024 panic("TODO: unexpected - compare to unboundType?") 1025 case *unboundFuncParam: 1026 panic("TODO: unexpected - compare to unboundFuncParam?") 1027 } 1028 return true 1029 } 1030 1031 func (p comparableT) String() string { 1032 return "comparable" 1033 } 1034 1035 // ---------------------------------------------------------------------------- 1036 1037 type anyT struct { 1038 } 1039 1040 func (p anyT) Match(pkg *Package, typ types.Type) bool { 1041 return true 1042 } 1043 1044 func (p anyT) String() string { 1045 return "any" 1046 } 1047 1048 // ---------------------------------------------------------------------------- 1049 1050 type capableT struct { 1051 // type slice, chan, array, array_pointer 1052 } 1053 1054 func (p capableT) Match(pkg *Package, typ types.Type) bool { 1055 retry: 1056 switch t := typ.(type) { 1057 case *types.Slice: 1058 return true 1059 case *types.Chan: 1060 return true 1061 case *types.Array: 1062 return true 1063 case *types.Pointer: 1064 _, ok := t.Elem().(*types.Array) // array_pointer 1065 return ok 1066 case *types.Named: 1067 typ = pkg.cb.getUnderlying(t) 1068 goto retry 1069 } 1070 return false 1071 } 1072 1073 func (p capableT) String() string { 1074 return "capable" 1075 } 1076 1077 // ---------------------------------------------------------------------------- 1078 1079 type lenableT struct { 1080 // capable 1081 // type map, string 1082 } 1083 1084 func (p lenableT) Match(pkg *Package, typ types.Type) bool { 1085 retry: 1086 switch t := typ.(type) { 1087 case *types.Basic: 1088 k := t.Kind() 1089 return k == types.String || k == types.UntypedString 1090 case *types.Map: 1091 return true 1092 case *types.Named: 1093 typ = pkg.cb.getUnderlying(t) 1094 goto retry 1095 } 1096 return capable.Match(pkg, typ) 1097 } 1098 1099 func (p lenableT) String() string { 1100 return "lenable" 1101 } 1102 1103 // ---------------------------------------------------------------------------- 1104 1105 type makableT struct { 1106 // type slice, chan, map 1107 } 1108 1109 func (p makableT) Match(pkg *Package, typ types.Type) bool { 1110 retry: 1111 switch t := typ.(type) { 1112 case *types.Slice: 1113 return true 1114 case *types.Map: 1115 return true 1116 case *types.Chan: 1117 return true 1118 case *types.Named: 1119 typ = pkg.cb.getUnderlying(t) 1120 goto retry 1121 } 1122 return false 1123 } 1124 1125 func (p makableT) String() string { 1126 return "makable" 1127 } 1128 1129 // ---------------------------------------------------------------------------- 1130 1131 type addableT struct { 1132 // type basicContract{kindsAddable}, untyped_bigint, untyped_bigrat, untyped_bigfloat 1133 } 1134 1135 func (p addableT) Match(pkg *Package, typ types.Type) bool { 1136 switch t := typ.(type) { 1137 case *types.Named: 1138 switch t { 1139 case pkg.utBigInt, pkg.utBigRat, pkg.utBigFlt: 1140 return true 1141 default: 1142 // TODO: refactor 1143 cb := pkg.cb 1144 cb.stk.Push(elemNone) 1145 kind := cb.findMember(typ, "Gop_Add", "", MemberFlagVal, &Element{}, nil) 1146 if kind != 0 { 1147 cb.stk.PopN(1) 1148 if kind == MemberMethod { 1149 return true 1150 } 1151 } 1152 } 1153 } 1154 c := &basicContract{kinds: kindsAddable} 1155 return c.Match(pkg, typ) 1156 } 1157 1158 func (p addableT) String() string { 1159 return "addable" 1160 } 1161 1162 // ---------------------------------------------------------------------------- 1163 1164 type numberT struct { 1165 // type basicContract{kindsNumber}, untyped_bigint, untyped_bigrat, untyped_bigfloat 1166 } 1167 1168 func (p numberT) Match(pkg *Package, typ types.Type) bool { 1169 switch t := typ.(type) { 1170 case *types.Named: 1171 switch t { 1172 case pkg.utBigInt, pkg.utBigRat, pkg.utBigFlt: 1173 return true 1174 } 1175 } 1176 c := &basicContract{kinds: kindsNumber} 1177 return c.Match(pkg, typ) 1178 } 1179 1180 func (p numberT) String() string { 1181 return "number" 1182 } 1183 1184 // ---------------------------------------------------------------------------- 1185 1186 type orderableT struct { 1187 // type basicContract{kindsOrderable}, untyped_bigint, untyped_bigrat, untyped_bigfloat 1188 } 1189 1190 func (p orderableT) Match(pkg *Package, typ types.Type) bool { 1191 switch t := typ.(type) { 1192 case *types.Named: 1193 switch t { 1194 case pkg.utBigInt, pkg.utBigRat, pkg.utBigFlt: 1195 return true 1196 } 1197 } 1198 c := &basicContract{kinds: kindsOrderable} 1199 return c.Match(pkg, typ) 1200 } 1201 1202 func (p orderableT) String() string { 1203 return "orderable" 1204 } 1205 1206 // ---------------------------------------------------------------------------- 1207 1208 type integerT struct { 1209 // type basicContract{kindsNumber}, untyped_bigint 1210 } 1211 1212 func (p integerT) Match(pkg *Package, typ types.Type) bool { 1213 c := &basicContract{kinds: kindsNumber} 1214 if c.Match(pkg, typ) { 1215 return true 1216 } 1217 return typ == pkg.utBigInt 1218 } 1219 1220 func (p integerT) String() string { 1221 return "integer" 1222 } 1223 1224 // ---------------------------------------------------------------------------- 1225 1226 var ( 1227 any = anyT{} 1228 capable = capableT{} 1229 lenable = lenableT{} 1230 makable = makableT{} 1231 cbool = &basicContract{kindsBool, "bool"} 1232 ninteger = &basicContract{kindsInteger, "ninteger"} 1233 tstring = &basicContract{kindsString, "tstring"} 1234 orderable = orderableT{} 1235 integer = integerT{} 1236 number = numberT{} 1237 addable = addableT{} 1238 comparable = comparableT{} 1239 ) 1240 1241 // ---------------------------------------------------------------------------- 1242 1243 type bmExargs = []interface{} 1244 1245 type builtinMethod struct { 1246 name string 1247 fn types.Object 1248 eargs bmExargs 1249 } 1250 1251 func (p *builtinMethod) Results() *types.Tuple { 1252 return p.fn.Type().(*types.Signature).Results() 1253 } 1254 1255 func (p *builtinMethod) Params() *types.Tuple { 1256 params := p.fn.Type().(*types.Signature).Params() 1257 n := params.Len() - len(p.eargs) - 1 1258 if n <= 0 { 1259 return nil 1260 } 1261 ret := make([]*types.Var, n) 1262 for i := 0; i < n; i++ { 1263 ret[i] = params.At(i + 1) 1264 } 1265 return types.NewTuple(ret...) 1266 } 1267 1268 type mthdSignature interface { 1269 Results() *types.Tuple 1270 Params() *types.Tuple 1271 } 1272 1273 type builtinTI struct { 1274 typ types.Type 1275 methods []*builtinMethod 1276 } 1277 1278 func (p *builtinTI) NumMethods() int { 1279 return len(p.methods) 1280 } 1281 1282 func (p *builtinTI) Method(i int) *builtinMethod { 1283 return p.methods[i] 1284 } 1285 1286 func (p *builtinTI) lookupByName(name string) mthdSignature { 1287 for i, n := 0, p.NumMethods(); i < n; i++ { 1288 method := p.Method(i) 1289 if method.name == name { 1290 return method 1291 } 1292 } 1293 return nil 1294 } 1295 1296 var ( 1297 tyMap types.Type = types.NewMap(types.Typ[types.Invalid], types.Typ[types.Invalid]) 1298 tyChan types.Type = types.NewChan(0, types.Typ[types.Invalid]) 1299 tySlice types.Type = types.NewSlice(types.Typ[types.Invalid]) 1300 ) 1301 1302 func initBuiltinTIs(pkg *Package) { 1303 var ( 1304 float64TI, intTI, int64TI, uint64TI *builtinTI 1305 ioxTI, stringTI, stringSliceTI *builtinTI 1306 ) 1307 btiMap := new(typeutil.Map) 1308 strconv := pkg.TryImport("strconv") 1309 strings := pkg.TryImport("strings") 1310 btoLen := types.Universe.Lookup("len") 1311 btoCap := types.Universe.Lookup("cap") 1312 { 1313 ioxPkg := pkg.conf.PkgPathIox 1314 if debugImportIox && ioxPkg == "" { 1315 ioxPkg = "github.com/goplus/gox/internal/iox" 1316 } 1317 if ioxPkg != "" { 1318 if os := pkg.TryImport("os"); os.isValid() { 1319 if iox := pkg.TryImport(ioxPkg); iox.isValid() { 1320 ioxTI = &builtinTI{ 1321 typ: os.Ref("File").Type(), 1322 methods: []*builtinMethod{ 1323 {"Gop_Enum", iox.Ref("EnumLines"), nil}, 1324 }, 1325 } 1326 } 1327 } 1328 } 1329 } 1330 if strconv.isValid() { 1331 float64TI = &builtinTI{ 1332 typ: types.Typ[types.Float64], 1333 methods: []*builtinMethod{ 1334 {"String", strconv.Ref("FormatFloat"), bmExargs{'g', -1, 64}}, 1335 }, 1336 } 1337 intTI = &builtinTI{ 1338 typ: types.Typ[types.Int], 1339 methods: []*builtinMethod{ 1340 {"String", strconv.Ref("Itoa"), nil}, 1341 }, 1342 } 1343 int64TI = &builtinTI{ 1344 typ: types.Typ[types.Int64], 1345 methods: []*builtinMethod{ 1346 {"String", strconv.Ref("FormatInt"), bmExargs{10}}, 1347 }, 1348 } 1349 uint64TI = &builtinTI{ 1350 typ: types.Typ[types.Uint64], 1351 methods: []*builtinMethod{ 1352 {"String", strconv.Ref("FormatUint"), bmExargs{10}}, 1353 }, 1354 } 1355 } 1356 if strings.isValid() && strconv.isValid() { 1357 stringTI = &builtinTI{ 1358 typ: types.Typ[types.String], 1359 methods: []*builtinMethod{ 1360 {"Len", btoLen, nil}, 1361 {"Count", strings.Ref("Count"), nil}, 1362 {"Int", strconv.Ref("Atoi"), nil}, 1363 {"Int64", strconv.Ref("ParseInt"), bmExargs{10, 64}}, 1364 {"Uint64", strconv.Ref("ParseUint"), bmExargs{10, 64}}, 1365 {"Float", strconv.Ref("ParseFloat"), bmExargs{64}}, 1366 {"Index", strings.Ref("Index"), nil}, 1367 {"IndexAny", strings.Ref("IndexAny"), nil}, 1368 {"IndexByte", strings.Ref("IndexByte"), nil}, 1369 {"IndexRune", strings.Ref("IndexRune"), nil}, 1370 {"LastIndex", strings.Ref("LastIndex"), nil}, 1371 {"LastIndexAny", strings.Ref("LastIndexAny"), nil}, 1372 {"LastIndexByte", strings.Ref("LastIndexByte"), nil}, 1373 {"Contains", strings.Ref("Contains"), nil}, 1374 {"ContainsAny", strings.Ref("ContainsAny"), nil}, 1375 {"ContainsRune", strings.Ref("ContainsRune"), nil}, 1376 {"Compare", strings.Ref("Compare"), nil}, 1377 {"EqualFold", strings.Ref("EqualFold"), nil}, 1378 {"HasPrefix", strings.Ref("HasPrefix"), nil}, 1379 {"HasSuffix", strings.Ref("HasSuffix"), nil}, 1380 {"Quote", strconv.Ref("Quote"), nil}, 1381 {"Unquote", strconv.Ref("Unquote"), nil}, 1382 {"ToTitle", strings.Ref("ToTitle"), nil}, 1383 {"ToUpper", strings.Ref("ToUpper"), nil}, 1384 {"ToLower", strings.Ref("ToLower"), nil}, 1385 {"Fields", strings.Ref("Fields"), nil}, 1386 {"Repeat", strings.Ref("Repeat"), nil}, 1387 {"Split", strings.Ref("Split"), nil}, 1388 {"SplitAfter", strings.Ref("SplitAfter"), nil}, 1389 {"SplitN", strings.Ref("SplitN"), nil}, 1390 {"SplitAfterN", strings.Ref("SplitAfterN"), nil}, 1391 {"Replace", strings.Ref("Replace"), nil}, 1392 {"ReplaceAll", strings.Ref("ReplaceAll"), nil}, 1393 {"Trim", strings.Ref("Trim"), nil}, 1394 {"TrimSpace", strings.Ref("TrimSpace"), nil}, 1395 {"TrimLeft", strings.Ref("TrimLeft"), nil}, 1396 {"TrimRight", strings.Ref("TrimRight"), nil}, 1397 {"TrimPrefix", strings.Ref("TrimPrefix"), nil}, 1398 {"TrimSuffix", strings.Ref("TrimSuffix"), nil}, 1399 }, 1400 } 1401 } 1402 if strings.isValid() { 1403 stringSliceTI = &builtinTI{ 1404 typ: types.NewSlice(types.Typ[types.String]), 1405 methods: []*builtinMethod{ 1406 {"Len", btoLen, nil}, 1407 {"Cap", btoCap, nil}, 1408 {"Join", strings.Ref("Join"), nil}, 1409 }, 1410 } 1411 } 1412 tis := []*builtinTI{ 1413 ioxTI, 1414 float64TI, 1415 intTI, 1416 int64TI, 1417 uint64TI, 1418 stringTI, 1419 stringSliceTI, 1420 { 1421 typ: tySlice, 1422 methods: []*builtinMethod{ 1423 {"Len", btoLen, nil}, 1424 {"Cap", btoCap, nil}, 1425 }, 1426 }, 1427 { 1428 typ: tyMap, 1429 methods: []*builtinMethod{ 1430 {"Len", btoLen, nil}, 1431 }, 1432 }, 1433 { 1434 typ: tyChan, 1435 methods: []*builtinMethod{ 1436 {"Len", btoLen, nil}, 1437 }, 1438 }, 1439 } 1440 for _, ti := range tis { 1441 if ti != nil { 1442 btiMap.Set(ti.typ, ti) 1443 } 1444 } 1445 pkg.cb.btiMap = btiMap 1446 } 1447 1448 func (p *CodeBuilder) getBuiltinTI(typ types.Type) *builtinTI { 1449 switch t := typ.(type) { 1450 case *types.Basic: 1451 typ = types.Default(typ) 1452 case *types.Slice: 1453 if t.Elem() != types.Typ[types.String] { 1454 typ = tySlice 1455 } 1456 case *types.Map: 1457 typ = tyMap 1458 case *types.Chan: 1459 typ = tyChan 1460 } 1461 if bti := p.btiMap.At(typ); bti != nil { 1462 return bti.(*builtinTI) 1463 } 1464 return nil 1465 } 1466 1467 // ----------------------------------------------------------------------------